summaryrefslogtreecommitdiffstats
path: root/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/llvm-rc/ResourceFileWriter.cpp67
-rw-r--r--llvm/tools/llvm-rc/ResourceFileWriter.h14
-rw-r--r--llvm/tools/llvm-rc/ResourceScriptParser.cpp40
-rw-r--r--llvm/tools/llvm-rc/ResourceScriptParser.h8
-rw-r--r--llvm/tools/llvm-rc/ResourceScriptStmt.cpp6
-rw-r--r--llvm/tools/llvm-rc/ResourceScriptStmt.h23
-rw-r--r--llvm/tools/llvm-rc/ResourceVisitor.h6
7 files changed, 138 insertions, 26 deletions
diff --git a/llvm/tools/llvm-rc/ResourceFileWriter.cpp b/llvm/tools/llvm-rc/ResourceFileWriter.cpp
index 701c4449ffa..243b3da404b 100644
--- a/llvm/tools/llvm-rc/ResourceFileWriter.cpp
+++ b/llvm/tools/llvm-rc/ResourceFileWriter.cpp
@@ -224,6 +224,11 @@ Error ResourceFileWriter::visitDialogResource(const RCResource *Res) {
return writeResource(Res, &ResourceFileWriter::writeDialogBody);
}
+Error ResourceFileWriter::visitCaptionStmt(const CaptionStmt *Stmt) {
+ ObjectData.Caption = Stmt->Value;
+ return Error::success();
+}
+
Error ResourceFileWriter::visitHTMLResource(const RCResource *Res) {
return writeResource(Res, &ResourceFileWriter::writeHTMLBody);
}
@@ -238,6 +243,16 @@ Error ResourceFileWriter::visitCharacteristicsStmt(
return Error::success();
}
+Error ResourceFileWriter::visitFontStmt(const FontStmt *Stmt) {
+ RETURN_IF_ERROR(checkNumberFits<uint16_t>(Stmt->Size, "Font size"));
+ RETURN_IF_ERROR(checkNumberFits<uint16_t>(Stmt->Weight, "Font weight"));
+ RETURN_IF_ERROR(checkNumberFits<uint8_t>(Stmt->Charset, "Font charset"));
+ ObjectInfo::FontInfo Font{Stmt->Size, Stmt->Name, Stmt->Weight, Stmt->Italic,
+ Stmt->Charset};
+ ObjectData.Font.emplace(Font);
+ return Error::success();
+}
+
Error ResourceFileWriter::visitLanguageStmt(const LanguageResource *Stmt) {
RETURN_IF_ERROR(checkNumberFits(Stmt->Lang, 10, "Primary language ID"));
RETURN_IF_ERROR(checkNumberFits(Stmt->SubLang, 6, "Sublanguage ID"));
@@ -245,6 +260,11 @@ Error ResourceFileWriter::visitLanguageStmt(const LanguageResource *Stmt) {
return Error::success();
}
+Error ResourceFileWriter::visitStyleStmt(const StyleStmt *Stmt) {
+ ObjectData.Style = Stmt->Value;
+ return Error::success();
+}
+
Error ResourceFileWriter::visitVersionStmt(const VersionStmt *Stmt) {
ObjectData.VersionInfo = Stmt->Value;
return Error::success();
@@ -474,10 +494,36 @@ Error ResourceFileWriter::writeDialogBody(const RCResource *Base) {
auto *Res = cast<DialogResource>(Base);
// Default style: WS_POPUP | WS_BORDER | WS_SYSMENU.
- const uint32_t UsedStyle = 0x80880000;
+ const uint32_t DefaultStyle = 0x80880000;
+ const uint32_t StyleFontFlag = 0x40;
+ const uint32_t StyleCaptionFlag = 0x00C00000;
+
+ uint32_t UsedStyle = ObjectData.Style.getValueOr(DefaultStyle);
+ if (ObjectData.Font)
+ UsedStyle |= StyleFontFlag;
+ else
+ UsedStyle &= ~StyleFontFlag;
+
+ // Actually, in case of empty (but existent) caption, the examined field
+ // is equal to "\"\"". That's why empty captions are still noticed.
+ if (ObjectData.Caption != "")
+ UsedStyle |= StyleCaptionFlag;
+
+ const uint16_t DialogExMagic = 0xFFFF;
// Write DIALOG(EX) header prefix. These are pretty different.
if (!Res->IsExtended) {
+ // We cannot let the higher word of DefaultStyle be equal to 0xFFFF.
+ // In such a case, whole object (in .res file) is equivalent to a
+ // DIALOGEX. It might lead to access violation/segmentation fault in
+ // resource readers. For example,
+ // 1 DIALOG 0, 0, 0, 65432
+ // STYLE 0xFFFF0001 {}
+ // would be compiled to a DIALOGEX with 65432 controls.
+ if ((UsedStyle >> 16) == DialogExMagic)
+ return createError("16 higher bits of DIALOG resource style cannot be"
+ " equal to 0xFFFF");
+
struct {
ulittle32_t Style;
ulittle32_t ExtStyle;
@@ -486,8 +532,6 @@ Error ResourceFileWriter::writeDialogBody(const RCResource *Base) {
writeObject(Prefix);
} else {
- const uint16_t DialogExMagic = 0xFFFF;
-
struct {
ulittle16_t Version;
ulittle16_t Magic;
@@ -529,8 +573,21 @@ Error ResourceFileWriter::writeDialogBody(const RCResource *Base) {
// Window CLASS field. Not kept here.
writeInt<uint16_t>(0);
- // Window title. There is no title for now, so all we output is '\0'.
- writeInt<uint16_t>(0);
+ // Window title or a single word equal to 0.
+ RETURN_IF_ERROR(writeCString(ObjectData.Caption));
+
+ // If there *is* a window font declared, output its data.
+ auto &Font = ObjectData.Font;
+ if (Font) {
+ writeInt<uint16_t>(Font->Size);
+ // Additional description occurs only in DIALOGEX.
+ if (Res->IsExtended) {
+ writeInt<uint16_t>(Font->Weight);
+ writeInt<uint8_t>(Font->IsItalic);
+ writeInt<uint8_t>(Font->Charset);
+ }
+ RETURN_IF_ERROR(writeCString(Font->Typeface));
+ }
auto handleCtlError = [&](Error &&Err, const Control &Ctl) -> Error {
if (!Err)
diff --git a/llvm/tools/llvm-rc/ResourceFileWriter.h b/llvm/tools/llvm-rc/ResourceFileWriter.h
index e9f9695cca6..1370c6168d2 100644
--- a/llvm/tools/llvm-rc/ResourceFileWriter.h
+++ b/llvm/tools/llvm-rc/ResourceFileWriter.h
@@ -35,8 +35,11 @@ public:
Error visitHTMLResource(const RCResource *) override;
Error visitMenuResource(const RCResource *) override;
+ Error visitCaptionStmt(const CaptionStmt *) override;
Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;
+ Error visitFontStmt(const FontStmt *) override;
Error visitLanguageStmt(const LanguageResource *) override;
+ Error visitStyleStmt(const StyleStmt *) override;
Error visitVersionStmt(const VersionStmt *) override;
struct ObjectInfo {
@@ -44,6 +47,17 @@ public:
uint32_t Characteristics;
uint32_t VersionInfo;
+ Optional<uint32_t> Style;
+ StringRef Caption;
+ struct FontInfo {
+ uint32_t Size;
+ StringRef Typeface;
+ uint32_t Weight;
+ bool IsItalic;
+ uint32_t Charset;
+ };
+ Optional<FontInfo> Font;
+
ObjectInfo() : LanguageInfo(0), Characteristics(0), VersionInfo(0) {}
} ObjectData;
diff --git a/llvm/tools/llvm-rc/ResourceScriptParser.cpp b/llvm/tools/llvm-rc/ResourceScriptParser.cpp
index 1e32d4d1a9d..d8c081771cb 100644
--- a/llvm/tools/llvm-rc/ResourceScriptParser.cpp
+++ b/llvm/tools/llvm-rc/ResourceScriptParser.cpp
@@ -320,13 +320,13 @@ Expected<uint32_t> RCParser::parseFlags(ArrayRef<StringRef> FlagDesc,
return Result;
}
-// As for now, we ignore the extended set of statements.
-Expected<OptionalStmtList> RCParser::parseOptionalStatements(bool IsExtended) {
+Expected<OptionalStmtList>
+RCParser::parseOptionalStatements(OptStmtType StmtsType) {
OptionalStmtList Result;
// The last statement is always followed by the start of the block.
while (!isNextTokenKind(Kind::BlockBegin)) {
- ASSIGN_OR_RETURN(SingleParse, parseSingleOptionalStatement(IsExtended));
+ ASSIGN_OR_RETURN(SingleParse, parseSingleOptionalStatement(StmtsType));
Result.addStmt(std::move(*SingleParse));
}
@@ -334,7 +334,7 @@ Expected<OptionalStmtList> RCParser::parseOptionalStatements(bool IsExtended) {
}
Expected<std::unique_ptr<OptionalStmt>>
-RCParser::parseSingleOptionalStatement(bool IsExtended) {
+RCParser::parseSingleOptionalStatement(OptStmtType StmtsType) {
ASSIGN_OR_RETURN(TypeToken, readIdentifier());
if (TypeToken->equals_lower("CHARACTERISTICS"))
return parseCharacteristicsStmt();
@@ -343,11 +343,11 @@ RCParser::parseSingleOptionalStatement(bool IsExtended) {
if (TypeToken->equals_lower("VERSION"))
return parseVersionStmt();
- if (IsExtended) {
+ if (StmtsType != OptStmtType::BasicStmt) {
if (TypeToken->equals_lower("CAPTION"))
return parseCaptionStmt();
if (TypeToken->equals_lower("FONT"))
- return parseFontStmt();
+ return parseFontStmt(StmtsType);
if (TypeToken->equals_lower("STYLE"))
return parseStyleStmt();
}
@@ -401,8 +401,9 @@ RCParser::ParseType RCParser::parseDialogResource(bool IsExtended) {
HelpID = *HelpIDResult;
}
- ASSIGN_OR_RETURN(OptStatements,
- parseOptionalStatements(/*UseExtendedStmts = */ true));
+ ASSIGN_OR_RETURN(OptStatements, parseOptionalStatements(
+ IsExtended ? OptStmtType::DialogExStmt
+ : OptStmtType::DialogStmt));
assert(isNextTokenKind(Kind::BlockBegin) &&
"parseOptionalStatements, when successful, halts on BlockBegin.");
@@ -666,11 +667,30 @@ RCParser::ParseOptionType RCParser::parseCaptionStmt() {
return llvm::make_unique<CaptionStmt>(*Arg);
}
-RCParser::ParseOptionType RCParser::parseFontStmt() {
+RCParser::ParseOptionType RCParser::parseFontStmt(OptStmtType DialogType) {
+ assert(DialogType != OptStmtType::BasicStmt);
+
ASSIGN_OR_RETURN(SizeResult, readInt());
RETURN_IF_ERROR(consumeType(Kind::Comma));
ASSIGN_OR_RETURN(NameResult, readString());
- return llvm::make_unique<FontStmt>(*SizeResult, *NameResult);
+
+ // Default values for the optional arguments.
+ uint32_t FontWeight = 0;
+ bool FontItalic = false;
+ uint32_t FontCharset = 1;
+ if (DialogType == OptStmtType::DialogExStmt) {
+ if (consumeOptionalType(Kind::Comma)) {
+ ASSIGN_OR_RETURN(Args, readIntsWithCommas(/* min = */ 0, /* max = */ 3));
+ if (Args->size() >= 1)
+ FontWeight = (*Args)[0];
+ if (Args->size() >= 2)
+ FontItalic = (*Args)[1] != 0;
+ if (Args->size() >= 3)
+ FontCharset = (*Args)[2];
+ }
+ }
+ return llvm::make_unique<FontStmt>(*SizeResult, *NameResult, FontWeight,
+ FontItalic, FontCharset);
}
RCParser::ParseOptionType RCParser::parseStyleStmt() {
diff --git a/llvm/tools/llvm-rc/ResourceScriptParser.h b/llvm/tools/llvm-rc/ResourceScriptParser.h
index b393bbcdd41..85d103dfe03 100644
--- a/llvm/tools/llvm-rc/ResourceScriptParser.h
+++ b/llvm/tools/llvm-rc/ResourceScriptParser.h
@@ -124,12 +124,14 @@ private:
//
// Ref (to the list of all optional statements):
// msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx
+ enum class OptStmtType { BasicStmt, DialogStmt, DialogExStmt };
+
Expected<OptionalStmtList>
- parseOptionalStatements(bool UseExtendedStatements = false);
+ parseOptionalStatements(OptStmtType StmtsType = OptStmtType::BasicStmt);
// Read a single optional statement.
Expected<std::unique_ptr<OptionalStmt>>
- parseSingleOptionalStatement(bool UseExtendedStatements = false);
+ parseSingleOptionalStatement(OptStmtType StmtsType = OptStmtType::BasicStmt);
// Top-level resource parsers.
ParseType parseLanguageResource();
@@ -163,7 +165,7 @@ private:
ParseOptionType parseCharacteristicsStmt();
ParseOptionType parseVersionStmt();
ParseOptionType parseCaptionStmt();
- ParseOptionType parseFontStmt();
+ ParseOptionType parseFontStmt(OptStmtType DialogType);
ParseOptionType parseStyleStmt();
// Raises an error. If IsAlreadyRead = false (default), this complains about
diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.cpp b/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
index 3897ca3a512..dbfed4c55a1 100644
--- a/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
+++ b/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
@@ -247,7 +247,11 @@ raw_ostream &CaptionStmt::log(raw_ostream &OS) const {
}
raw_ostream &FontStmt::log(raw_ostream &OS) const {
- return OS << "Font: size = " << Size << ", face = " << Typeface << "\n";
+ OS << "Font: size = " << Size << ", face = " << Name
+ << ", weight = " << Weight;
+ if (Italic)
+ OS << ", italic";
+ return OS << ", charset = " << Charset << "\n";
}
raw_ostream &StyleStmt::log(raw_ostream &OS) const {
diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.h b/llvm/tools/llvm-rc/ResourceScriptStmt.h
index 692d2aec5e7..908232940a5 100644
--- a/llvm/tools/llvm-rc/ResourceScriptStmt.h
+++ b/llvm/tools/llvm-rc/ResourceScriptStmt.h
@@ -665,11 +665,13 @@ public:
//
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx
class CaptionStmt : public OptionalStmt {
+public:
StringRef Value;
-public:
CaptionStmt(StringRef Caption) : Value(Caption) {}
raw_ostream &log(raw_ostream &) const override;
+ Twine getResourceTypeName() const override { return "CAPTION"; }
+ Error visit(Visitor *V) const override { return V->visitCaptionStmt(this); }
};
// FONT optional statement.
@@ -679,24 +681,31 @@ public:
//
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381013(v=vs.85).aspx
class FontStmt : public OptionalStmt {
- uint32_t Size;
- StringRef Typeface;
-
public:
- FontStmt(uint32_t FontSize, StringRef FontName)
- : Size(FontSize), Typeface(FontName) {}
+ uint32_t Size, Weight, Charset;
+ StringRef Name;
+ bool Italic;
+
+ FontStmt(uint32_t FontSize, StringRef FontName, uint32_t FontWeight,
+ bool FontItalic, uint32_t FontCharset)
+ : Size(FontSize), Weight(FontWeight), Charset(FontCharset),
+ Name(FontName), Italic(FontItalic) {}
raw_ostream &log(raw_ostream &) const override;
+ Twine getResourceTypeName() const override { return "FONT"; }
+ Error visit(Visitor *V) const override { return V->visitFontStmt(this); }
};
// STYLE optional statement.
//
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx
class StyleStmt : public OptionalStmt {
+public:
uint32_t Value;
-public:
StyleStmt(uint32_t Style) : Value(Style) {}
raw_ostream &log(raw_ostream &) const override;
+ Twine getResourceTypeName() const override { return "STYLE"; }
+ Error visit(Visitor *V) const override { return V->visitStyleStmt(this); }
};
} // namespace rc
diff --git a/llvm/tools/llvm-rc/ResourceVisitor.h b/llvm/tools/llvm-rc/ResourceVisitor.h
index 5655a53333a..376a20b336d 100644
--- a/llvm/tools/llvm-rc/ResourceVisitor.h
+++ b/llvm/tools/llvm-rc/ResourceVisitor.h
@@ -21,8 +21,11 @@ namespace rc {
class RCResource;
+class CaptionStmt;
class CharacteristicsStmt;
+class FontStmt;
class LanguageResource;
+class StyleStmt;
class VersionStmt;
class Visitor {
@@ -33,8 +36,11 @@ public:
virtual Error visitHTMLResource(const RCResource *) = 0;
virtual Error visitMenuResource(const RCResource *) = 0;
+ virtual Error visitCaptionStmt(const CaptionStmt *) = 0;
virtual Error visitCharacteristicsStmt(const CharacteristicsStmt *) = 0;
+ virtual Error visitFontStmt(const FontStmt *) = 0;
virtual Error visitLanguageStmt(const LanguageResource *) = 0;
+ virtual Error visitStyleStmt(const StyleStmt *) = 0;
virtual Error visitVersionStmt(const VersionStmt *) = 0;
virtual ~Visitor() {}
OpenPOWER on IntegriCloud