diff options
Diffstat (limited to 'llvm/tools')
-rw-r--r-- | llvm/tools/llvm-rc/ResourceFileWriter.cpp | 67 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceFileWriter.h | 14 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptParser.cpp | 40 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptParser.h | 8 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptStmt.cpp | 6 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptStmt.h | 23 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceVisitor.h | 6 |
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() {} |