1 //===-- ResourceScriptStmt.h ------------------------------------*- C++-*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===---------------------------------------------------------------------===//
10 // This lists all the resource and statement types occurring in RC scripts.
12 //===---------------------------------------------------------------------===//
14 #ifndef LLVM_TOOLS_LLVMRC_RESOURCESCRIPTSTMT_H
15 #define LLVM_TOOLS_LLVMRC_RESOURCESCRIPTSTMT_H
17 #include "ResourceScriptToken.h"
18 #include "ResourceVisitor.h"
20 #include "llvm/ADT/StringSet.h"
25 // Integer wrapper that also holds information whether the user declared
26 // the integer to be long (by appending L to the end of the integer) or not.
27 // It allows to be implicitly cast from and to uint32_t in order
28 // to be compatible with the parts of code that don't care about the integers
35 RCInt(const RCToken &Token)
36 : Val(Token.intValue()), Long(Token.isLongInt()) {}
37 RCInt(uint32_t Value) : Val(Value), Long(false) {}
38 RCInt(uint32_t Value, bool IsLong) : Val(Value), Long(IsLong) {}
39 operator uint32_t() const { return Val; }
40 bool isLong() const { return Long; }
42 RCInt &operator+=(const RCInt &Rhs) {
43 std::tie(Val, Long) = std::make_pair(Val + Rhs.Val, Long | Rhs.Long);
47 RCInt &operator-=(const RCInt &Rhs) {
48 std::tie(Val, Long) = std::make_pair(Val - Rhs.Val, Long | Rhs.Long);
52 RCInt &operator|=(const RCInt &Rhs) {
53 std::tie(Val, Long) = std::make_pair(Val | Rhs.Val, Long | Rhs.Long);
57 RCInt &operator&=(const RCInt &Rhs) {
58 std::tie(Val, Long) = std::make_pair(Val & Rhs.Val, Long | Rhs.Long);
62 RCInt operator-() const { return {-Val, Long}; }
63 RCInt operator~() const { return {~Val, Long}; }
65 friend raw_ostream &operator<<(raw_ostream &OS, const RCInt &Int) {
66 return OS << Int.Val << (Int.Long ? "L" : "");
70 // A class holding a name - either an integer or a reference to the string.
76 Data(RCInt Value) : Int(Value) {}
77 Data(const StringRef Value) : String(Value) {}
78 Data(const RCToken &Token) {
79 if (Token.kind() == RCToken::Kind::Int)
82 String = Token.value();
88 IntOrString() : IntOrString(RCInt(0)) {}
89 IntOrString(uint32_t Value) : Data(Value), IsInt(1) {}
90 IntOrString(RCInt Value) : Data(Value), IsInt(1) {}
91 IntOrString(StringRef Value) : Data(Value), IsInt(0) {}
92 IntOrString(const RCToken &Token)
93 : Data(Token), IsInt(Token.kind() == RCToken::Kind::Int) {}
95 bool equalsLower(const char *Str) {
96 return !IsInt && Data.String.equals_lower(Str);
99 bool isInt() const { return IsInt; }
101 RCInt getInt() const {
106 const StringRef &getString() const {
111 operator Twine() const {
112 return isInt() ? Twine(getInt()) : Twine(getString());
115 friend raw_ostream &operator<<(raw_ostream &, const IntOrString &);
119 // These resource kinds have corresponding .res resource type IDs
120 // (TYPE in RESOURCEHEADER structure). The numeric value assigned to each
121 // kind is equal to this type ID.
128 RkStringTableBundle = 6,
135 // These kinds don't have assigned type IDs (they might be the resources
136 // of invalid kind, expand to many resource structures in .res files,
137 // or have variable type ID). In order to avoid ID clashes with IDs above,
138 // we assign the kinds the values 256 and larger.
145 RkSingleCursorOrIconRes,
146 RkCursorOrIconGroupRes,
149 // Non-zero memory flags.
150 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648027(v=vs.85).aspx
155 MfDiscardable = 0x1000
158 // Base resource. All the resources should derive from this base.
162 void setName(const IntOrString &Name) { ResName = Name; }
163 virtual raw_ostream &log(raw_ostream &OS) const {
164 return OS << "Base statement\n";
166 virtual ~RCResource() {}
168 virtual Error visit(Visitor *) const {
169 llvm_unreachable("This is unable to call methods from Visitor base");
172 // Apply the statements attached to this resource. Generic resources
174 virtual Error applyStmts(Visitor *) const { return Error::success(); }
176 // By default, memory flags are DISCARDABLE | PURE | MOVEABLE.
177 virtual uint16_t getMemoryFlags() const {
178 return MfDiscardable | MfPure | MfMoveable;
180 virtual ResourceKind getKind() const { return RkBase; }
181 static bool classof(const RCResource *Res) { return true; }
183 virtual IntOrString getResourceType() const {
184 llvm_unreachable("This cannot be called on objects without types.");
186 virtual Twine getResourceTypeName() const {
187 llvm_unreachable("This cannot be called on objects without types.");
191 // An empty resource. It has no content, type 0, ID 0 and all of its
192 // characteristics are equal to 0.
193 class NullResource : public RCResource {
195 raw_ostream &log(raw_ostream &OS) const override {
196 return OS << "Null resource\n";
198 Error visit(Visitor *V) const override { return V->visitNullResource(this); }
199 IntOrString getResourceType() const override { return 0; }
200 Twine getResourceTypeName() const override { return "(NULL)"; }
201 uint16_t getMemoryFlags() const override { return 0; }
204 // Optional statement base. All such statements should derive from this base.
205 class OptionalStmt : public RCResource {};
207 class OptionalStmtList : public OptionalStmt {
208 std::vector<std::unique_ptr<OptionalStmt>> Statements;
211 OptionalStmtList() {}
212 raw_ostream &log(raw_ostream &OS) const override;
214 void addStmt(std::unique_ptr<OptionalStmt> Stmt) {
215 Statements.push_back(std::move(Stmt));
218 Error visit(Visitor *V) const override {
219 for (auto &StmtPtr : Statements)
220 if (auto Err = StmtPtr->visit(V))
222 return Error::success();
226 class OptStatementsRCResource : public RCResource {
228 std::unique_ptr<OptionalStmtList> OptStatements;
230 OptStatementsRCResource(OptionalStmtList &&Stmts)
231 : OptStatements(llvm::make_unique<OptionalStmtList>(std::move(Stmts))) {}
233 virtual Error applyStmts(Visitor *V) const { return OptStatements->visit(V); }
236 // LANGUAGE statement. It can occur both as a top-level statement (in such
237 // a situation, it changes the default language until the end of the file)
238 // and as an optional resource statement (then it changes the language
239 // of a single resource).
241 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381019(v=vs.85).aspx
242 class LanguageResource : public OptionalStmt {
244 uint32_t Lang, SubLang;
246 LanguageResource(uint32_t LangId, uint32_t SubLangId)
247 : Lang(LangId), SubLang(SubLangId) {}
248 raw_ostream &log(raw_ostream &) const override;
250 // This is not a regular top-level statement; when it occurs, it just
251 // modifies the language context.
252 Error visit(Visitor *V) const override { return V->visitLanguageStmt(this); }
253 Twine getResourceTypeName() const override { return "LANGUAGE"; }
256 // ACCELERATORS resource. Defines a named table of accelerators for the app.
258 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380610(v=vs.85).aspx
259 class AcceleratorsResource : public OptStatementsRCResource {
268 // This is actually 0x0000 (accelerator is assumed to be ASCII if it's
269 // not VIRTKEY). However, rc.exe behavior is different in situations
270 // "only ASCII defined" and "neither ASCII nor VIRTKEY defined".
271 // Therefore, we include ASCII as another flag. This must be zeroed
281 static constexpr size_t NumFlags = 6;
282 static StringRef OptionsStr[NumFlags];
283 static uint32_t OptionsFlags[NumFlags];
286 std::vector<Accelerator> Accelerators;
288 using OptStatementsRCResource::OptStatementsRCResource;
289 void addAccelerator(IntOrString Event, uint32_t Id, uint16_t Flags) {
290 Accelerators.push_back(Accelerator{Event, Id, Flags});
292 raw_ostream &log(raw_ostream &) const override;
294 IntOrString getResourceType() const override { return RkAccelerators; }
295 uint16_t getMemoryFlags() const override {
296 return MfPure | MfMoveable;
298 Twine getResourceTypeName() const override { return "ACCELERATORS"; }
300 Error visit(Visitor *V) const override {
301 return V->visitAcceleratorsResource(this);
303 ResourceKind getKind() const override { return RkAccelerators; }
304 static bool classof(const RCResource *Res) {
305 return Res->getKind() == RkAccelerators;
309 // BITMAP resource. Represents a bitmap (".bmp") file.
311 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380680(v=vs.85).aspx
312 class BitmapResource : public RCResource {
316 BitmapResource(StringRef Location) : BitmapLoc(Location) {}
317 raw_ostream &log(raw_ostream &) const override;
319 IntOrString getResourceType() const override { return RkBitmap; }
320 uint16_t getMemoryFlags() const override { return MfPure | MfMoveable; }
322 Twine getResourceTypeName() const override { return "BITMAP"; }
323 Error visit(Visitor *V) const override {
324 return V->visitBitmapResource(this);
326 ResourceKind getKind() const override { return RkBitmap; }
327 static bool classof(const RCResource *Res) {
328 return Res->getKind() == RkBitmap;
332 // CURSOR resource. Represents a single cursor (".cur") file.
334 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380920(v=vs.85).aspx
335 class CursorResource : public RCResource {
339 CursorResource(StringRef Location) : CursorLoc(Location) {}
340 raw_ostream &log(raw_ostream &) const override;
342 Twine getResourceTypeName() const override { return "CURSOR"; }
343 Error visit(Visitor *V) const override {
344 return V->visitCursorResource(this);
346 ResourceKind getKind() const override { return RkCursor; }
347 static bool classof(const RCResource *Res) {
348 return Res->getKind() == RkCursor;
352 // ICON resource. Represents a single ".ico" file containing a group of icons.
354 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381018(v=vs.85).aspx
355 class IconResource : public RCResource {
359 IconResource(StringRef Location) : IconLoc(Location) {}
360 raw_ostream &log(raw_ostream &) const override;
362 Twine getResourceTypeName() const override { return "ICON"; }
363 Error visit(Visitor *V) const override { return V->visitIconResource(this); }
364 ResourceKind getKind() const override { return RkIcon; }
365 static bool classof(const RCResource *Res) {
366 return Res->getKind() == RkIcon;
370 // HTML resource. Represents a local webpage that is to be embedded into the
371 // resulting resource file. It embeds a file only - no additional resources
372 // (images etc.) are included with this resource.
374 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa966018(v=vs.85).aspx
375 class HTMLResource : public RCResource {
379 HTMLResource(StringRef Location) : HTMLLoc(Location) {}
380 raw_ostream &log(raw_ostream &) const override;
382 Error visit(Visitor *V) const override { return V->visitHTMLResource(this); }
384 // Curiously, file resources don't have DISCARDABLE flag set.
385 uint16_t getMemoryFlags() const override { return MfPure | MfMoveable; }
386 IntOrString getResourceType() const override { return RkHTML; }
387 Twine getResourceTypeName() const override { return "HTML"; }
388 ResourceKind getKind() const override { return RkHTML; }
389 static bool classof(const RCResource *Res) {
390 return Res->getKind() == RkHTML;
394 // -- MENU resource and its helper classes --
395 // This resource describes the contents of an application menu
396 // (usually located in the upper part of the dialog.)
398 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381025(v=vs.85).aspx
400 // Description of a single submenu item.
401 class MenuDefinition {
408 MENUBARBREAK = 0x0020,
412 enum MenuDefKind { MkBase, MkSeparator, MkMenuItem, MkPopup };
414 static constexpr size_t NumFlags = 6;
415 static StringRef OptionsStr[NumFlags];
416 static uint32_t OptionsFlags[NumFlags];
417 static raw_ostream &logFlags(raw_ostream &, uint16_t Flags);
418 virtual raw_ostream &log(raw_ostream &OS) const {
419 return OS << "Base menu definition\n";
421 virtual ~MenuDefinition() {}
423 virtual uint16_t getResFlags() const { return 0; }
424 virtual MenuDefKind getKind() const { return MkBase; }
427 // Recursive description of a whole submenu.
428 class MenuDefinitionList : public MenuDefinition {
430 std::vector<std::unique_ptr<MenuDefinition>> Definitions;
432 void addDefinition(std::unique_ptr<MenuDefinition> Def) {
433 Definitions.push_back(std::move(Def));
435 raw_ostream &log(raw_ostream &) const override;
438 // Separator in MENU definition (MENUITEM SEPARATOR).
440 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
441 class MenuSeparator : public MenuDefinition {
443 raw_ostream &log(raw_ostream &) const override;
445 MenuDefKind getKind() const override { return MkSeparator; }
446 static bool classof(const MenuDefinition *D) {
447 return D->getKind() == MkSeparator;
451 // MENUITEM statement definition.
453 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
454 class MenuItem : public MenuDefinition {
460 MenuItem(StringRef Caption, uint32_t ItemId, uint16_t ItemFlags)
461 : Name(Caption), Id(ItemId), Flags(ItemFlags) {}
462 raw_ostream &log(raw_ostream &) const override;
464 uint16_t getResFlags() const override { return Flags; }
465 MenuDefKind getKind() const override { return MkMenuItem; }
466 static bool classof(const MenuDefinition *D) {
467 return D->getKind() == MkMenuItem;
471 // POPUP statement definition.
473 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx
474 class PopupItem : public MenuDefinition {
478 MenuDefinitionList SubItems;
480 PopupItem(StringRef Caption, uint16_t ItemFlags,
481 MenuDefinitionList &&SubItemsList)
482 : Name(Caption), Flags(ItemFlags), SubItems(std::move(SubItemsList)) {}
483 raw_ostream &log(raw_ostream &) const override;
485 // This has an additional (0x10) flag. It doesn't match with documented
486 // 0x01 flag, though.
487 uint16_t getResFlags() const override { return Flags | 0x10; }
488 MenuDefKind getKind() const override { return MkPopup; }
489 static bool classof(const MenuDefinition *D) {
490 return D->getKind() == MkPopup;
494 // Menu resource definition.
495 class MenuResource : public OptStatementsRCResource {
497 MenuDefinitionList Elements;
499 MenuResource(OptionalStmtList &&OptStmts, MenuDefinitionList &&Items)
500 : OptStatementsRCResource(std::move(OptStmts)),
501 Elements(std::move(Items)) {}
502 raw_ostream &log(raw_ostream &) const override;
504 IntOrString getResourceType() const override { return RkMenu; }
505 Twine getResourceTypeName() const override { return "MENU"; }
506 Error visit(Visitor *V) const override { return V->visitMenuResource(this); }
507 ResourceKind getKind() const override { return RkMenu; }
508 static bool classof(const RCResource *Res) {
509 return Res->getKind() == RkMenu;
513 // STRINGTABLE resource. Contains a list of strings, each having its unique ID.
515 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381050(v=vs.85).aspx
516 class StringTableResource : public OptStatementsRCResource {
518 std::vector<std::pair<uint32_t, StringRef>> Table;
520 using OptStatementsRCResource::OptStatementsRCResource;
521 void addString(uint32_t ID, StringRef String) {
522 Table.emplace_back(ID, String);
524 raw_ostream &log(raw_ostream &) const override;
525 Twine getResourceTypeName() const override { return "STRINGTABLE"; }
526 Error visit(Visitor *V) const override {
527 return V->visitStringTableResource(this);
531 // -- DIALOG(EX) resource and its helper classes --
533 // This resource describes dialog boxes and controls residing inside them.
535 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381003(v=vs.85).aspx
536 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx
538 // Single control definition.
543 uint32_t ID, X, Y, Width, Height;
544 Optional<uint32_t> Style, ExtStyle, HelpID;
547 // Control classes as described in DLGITEMTEMPLATEEX documentation.
549 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms645389.aspx
559 // Simple information about a single control type.
566 Control(StringRef CtlType, IntOrString CtlTitle, uint32_t CtlID,
567 uint32_t PosX, uint32_t PosY, uint32_t ItemWidth, uint32_t ItemHeight,
568 Optional<uint32_t> ItemStyle, Optional<uint32_t> ExtItemStyle,
569 Optional<uint32_t> CtlHelpID, IntOrString CtlClass)
570 : Type(CtlType), Title(CtlTitle), ID(CtlID), X(PosX), Y(PosY),
571 Width(ItemWidth), Height(ItemHeight), Style(ItemStyle),
572 ExtStyle(ExtItemStyle), HelpID(CtlHelpID), Class(CtlClass) {}
574 static const StringMap<CtlInfo> SupportedCtls;
576 raw_ostream &log(raw_ostream &) const;
579 // Single dialog definition. We don't create distinct classes for DIALOG and
580 // DIALOGEX because of their being too similar to each other. We only have a
581 // flag determining the type of the dialog box.
582 class DialogResource : public OptStatementsRCResource {
584 uint32_t X, Y, Width, Height, HelpID;
585 std::vector<Control> Controls;
588 DialogResource(uint32_t PosX, uint32_t PosY, uint32_t DlgWidth,
589 uint32_t DlgHeight, uint32_t DlgHelpID,
590 OptionalStmtList &&OptStmts, bool IsDialogEx)
591 : OptStatementsRCResource(std::move(OptStmts)), X(PosX), Y(PosY),
592 Width(DlgWidth), Height(DlgHeight), HelpID(DlgHelpID),
593 IsExtended(IsDialogEx) {}
595 void addControl(Control &&Ctl) { Controls.push_back(std::move(Ctl)); }
597 raw_ostream &log(raw_ostream &) const override;
599 // It was a weird design decision to assign the same resource type number
600 // both for DIALOG and DIALOGEX (and the same structure version number).
601 // It makes it possible for DIALOG to be mistaken for DIALOGEX.
602 IntOrString getResourceType() const override { return RkDialog; }
603 Twine getResourceTypeName() const override {
604 return "DIALOG" + Twine(IsExtended ? "EX" : "");
606 Error visit(Visitor *V) const override {
607 return V->visitDialogResource(this);
609 ResourceKind getKind() const override { return RkDialog; }
610 static bool classof(const RCResource *Res) {
611 return Res->getKind() == RkDialog;
615 // User-defined resource. It is either:
616 // * a link to the file, e.g. NAME TYPE "filename",
617 // * or contains a list of integers and strings, e.g. NAME TYPE {1, "a", 2}.
618 class UserDefinedResource : public RCResource {
622 std::vector<IntOrString> Contents;
625 UserDefinedResource(IntOrString ResourceType, StringRef FileLocation)
626 : Type(ResourceType), FileLoc(FileLocation), IsFileResource(true) {}
627 UserDefinedResource(IntOrString ResourceType, std::vector<IntOrString> &&Data)
628 : Type(ResourceType), Contents(std::move(Data)), IsFileResource(false) {}
630 raw_ostream &log(raw_ostream &) const override;
631 IntOrString getResourceType() const override { return Type; }
632 Twine getResourceTypeName() const override { return Type; }
633 uint16_t getMemoryFlags() const override { return MfPure | MfMoveable; }
635 Error visit(Visitor *V) const override {
636 return V->visitUserDefinedResource(this);
638 ResourceKind getKind() const override { return RkUser; }
639 static bool classof(const RCResource *Res) {
640 return Res->getKind() == RkUser;
644 // -- VERSIONINFO resource and its helper classes --
646 // This resource lists the version information on the executable/library.
647 // The declaration consists of the following items:
648 // * A number of fixed optional version statements (e.g. FILEVERSION, FILEOS)
650 // * A number of BLOCK and/or VALUE statements. BLOCK recursively defines
651 // another block of version information, whereas VALUE defines a
652 // key -> value correspondence. There might be more than one value
653 // corresponding to the single key.
656 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381058(v=vs.85).aspx
658 // A single VERSIONINFO statement;
659 class VersionInfoStmt {
661 enum StmtKind { StBase = 0, StBlock = 1, StValue = 2 };
663 virtual raw_ostream &log(raw_ostream &OS) const { return OS << "VI stmt\n"; }
664 virtual ~VersionInfoStmt() {}
666 virtual StmtKind getKind() const { return StBase; }
667 static bool classof(const VersionInfoStmt *S) {
668 return S->getKind() == StBase;
672 // BLOCK definition; also the main VERSIONINFO declaration is considered a
673 // BLOCK, although it has no name.
674 // The correct top-level blocks are "VarFileInfo" and "StringFileInfo". We don't
675 // care about them at the parsing phase.
676 class VersionInfoBlock : public VersionInfoStmt {
678 std::vector<std::unique_ptr<VersionInfoStmt>> Stmts;
681 VersionInfoBlock(StringRef BlockName) : Name(BlockName) {}
682 void addStmt(std::unique_ptr<VersionInfoStmt> Stmt) {
683 Stmts.push_back(std::move(Stmt));
685 raw_ostream &log(raw_ostream &) const override;
687 StmtKind getKind() const override { return StBlock; }
688 static bool classof(const VersionInfoStmt *S) {
689 return S->getKind() == StBlock;
693 class VersionInfoValue : public VersionInfoStmt {
696 std::vector<IntOrString> Values;
697 std::vector<bool> HasPrecedingComma;
699 VersionInfoValue(StringRef InfoKey, std::vector<IntOrString> &&Vals,
700 std::vector<bool> &&CommasBeforeVals)
701 : Key(InfoKey), Values(std::move(Vals)),
702 HasPrecedingComma(std::move(CommasBeforeVals)) {}
703 raw_ostream &log(raw_ostream &) const override;
705 StmtKind getKind() const override { return StValue; }
706 static bool classof(const VersionInfoStmt *S) {
707 return S->getKind() == StValue;
711 class VersionInfoResource : public RCResource {
713 // A class listing fixed VERSIONINFO statements (occuring before main BEGIN).
714 // If any of these is not specified, it is assumed by the original tool to
716 class VersionInfoFixed {
718 enum VersionInfoFixedType {
731 static const StringMap<VersionInfoFixedType> FixedFieldsInfoMap;
732 static const StringRef FixedFieldsNames[FtNumTypes];
735 SmallVector<uint32_t, 4> FixedInfo[FtNumTypes];
736 SmallVector<bool, FtNumTypes> IsTypePresent;
738 static VersionInfoFixedType getFixedType(StringRef Type);
739 static bool isTypeSupported(VersionInfoFixedType Type);
740 static bool isVersionType(VersionInfoFixedType Type);
742 VersionInfoFixed() : IsTypePresent(FtNumTypes, false) {}
744 void setValue(VersionInfoFixedType Type, ArrayRef<uint32_t> Value) {
745 FixedInfo[Type] = SmallVector<uint32_t, 4>(Value.begin(), Value.end());
746 IsTypePresent[Type] = true;
749 raw_ostream &log(raw_ostream &) const;
752 VersionInfoBlock MainBlock;
753 VersionInfoFixed FixedData;
755 VersionInfoResource(VersionInfoBlock &&TopLevelBlock,
756 VersionInfoFixed &&FixedInfo)
757 : MainBlock(std::move(TopLevelBlock)), FixedData(std::move(FixedInfo)) {}
759 raw_ostream &log(raw_ostream &) const override;
760 IntOrString getResourceType() const override { return RkVersionInfo; }
761 uint16_t getMemoryFlags() const override { return MfMoveable | MfPure; }
762 Twine getResourceTypeName() const override { return "VERSIONINFO"; }
763 Error visit(Visitor *V) const override {
764 return V->visitVersionInfoResource(this);
766 ResourceKind getKind() const override { return RkVersionInfo; }
767 static bool classof(const RCResource *Res) {
768 return Res->getKind() == RkVersionInfo;
772 // CHARACTERISTICS optional statement.
774 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380872(v=vs.85).aspx
775 class CharacteristicsStmt : public OptionalStmt {
779 CharacteristicsStmt(uint32_t Characteristic) : Value(Characteristic) {}
780 raw_ostream &log(raw_ostream &) const override;
782 Twine getResourceTypeName() const override { return "CHARACTERISTICS"; }
783 Error visit(Visitor *V) const override {
784 return V->visitCharacteristicsStmt(this);
788 // VERSION optional statement.
790 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381059(v=vs.85).aspx
791 class VersionStmt : public OptionalStmt {
795 VersionStmt(uint32_t Version) : Value(Version) {}
796 raw_ostream &log(raw_ostream &) const override;
798 Twine getResourceTypeName() const override { return "VERSION"; }
799 Error visit(Visitor *V) const override { return V->visitVersionStmt(this); }
802 // CAPTION optional statement.
804 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx
805 class CaptionStmt : public OptionalStmt {
809 CaptionStmt(StringRef Caption) : Value(Caption) {}
810 raw_ostream &log(raw_ostream &) const override;
811 Twine getResourceTypeName() const override { return "CAPTION"; }
812 Error visit(Visitor *V) const override { return V->visitCaptionStmt(this); }
815 // FONT optional statement.
816 // Note that the documentation is inaccurate: it expects five arguments to be
817 // given, however the example provides only two. In fact, the original tool
818 // expects two arguments - point size and name of the typeface.
820 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381013(v=vs.85).aspx
821 class FontStmt : public OptionalStmt {
823 uint32_t Size, Weight, Charset;
827 FontStmt(uint32_t FontSize, StringRef FontName, uint32_t FontWeight,
828 bool FontItalic, uint32_t FontCharset)
829 : Size(FontSize), Weight(FontWeight), Charset(FontCharset),
830 Name(FontName), Italic(FontItalic) {}
831 raw_ostream &log(raw_ostream &) const override;
832 Twine getResourceTypeName() const override { return "FONT"; }
833 Error visit(Visitor *V) const override { return V->visitFontStmt(this); }
836 // STYLE optional statement.
838 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx
839 class StyleStmt : public OptionalStmt {
843 StyleStmt(uint32_t Style) : Value(Style) {}
844 raw_ostream &log(raw_ostream &) const override;
845 Twine getResourceTypeName() const override { return "STYLE"; }
846 Error visit(Visitor *V) const override { return V->visitStyleStmt(this); }