//===-- ResourceScriptStmt.h ------------------------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// // // This lists all the resource and statement types occurring in RC scripts. // //===---------------------------------------------------------------------===// #ifndef LLVM_TOOLS_LLVMRC_RESOURCESCRIPTSTMT_H #define LLVM_TOOLS_LLVMRC_RESOURCESCRIPTSTMT_H #include "ResourceScriptToken.h" #include "llvm/ADT/StringSet.h" namespace llvm { namespace rc { // A class holding a name - either an integer or a reference to the string. class IntOrString { private: union Data { uint32_t Int; StringRef String; Data(uint32_t Value) : Int(Value) {} Data(const StringRef Value) : String(Value) {} Data(const RCToken &Token) { if (Token.kind() == RCToken::Kind::Int) Int = Token.intValue(); else String = Token.value(); } } Data; bool IsInt; public: IntOrString() : IntOrString(0) {} IntOrString(uint32_t Value) : Data(Value), IsInt(1) {} IntOrString(StringRef Value) : Data(Value), IsInt(0) {} IntOrString(const RCToken &Token) : Data(Token), IsInt(Token.kind() == RCToken::Kind::Int) {} bool equalsLower(const char *Str) { return !IsInt && Data.String.equals_lower(Str); } friend raw_ostream &operator<<(raw_ostream &, const IntOrString &); }; // Base resource. All the resources should derive from this base. class RCResource { protected: IntOrString ResName; public: RCResource() = default; RCResource(RCResource &&) = default; void setName(const IntOrString &Name) { ResName = Name; } virtual raw_ostream &log(raw_ostream &OS) const { return OS << "Base statement\n"; }; virtual ~RCResource() {} }; // Optional statement base. All such statements should derive from this base. class OptionalStmt : public RCResource {}; class OptionalStmtList : public OptionalStmt { std::vector> Statements; public: OptionalStmtList() {} virtual raw_ostream &log(raw_ostream &OS) const; void addStmt(std::unique_ptr Stmt) { Statements.push_back(std::move(Stmt)); } }; // LANGUAGE statement. It can occur both as a top-level statement (in such // a situation, it changes the default language until the end of the file) // and as an optional resource statement (then it changes the language // of a single resource). // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381019(v=vs.85).aspx class LanguageResource : public OptionalStmt { uint32_t Lang, SubLang; public: LanguageResource(uint32_t LangId, uint32_t SubLangId) : Lang(LangId), SubLang(SubLangId) {} raw_ostream &log(raw_ostream &) const override; }; // ACCELERATORS resource. Defines a named table of accelerators for the app. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380610(v=vs.85).aspx class AcceleratorsResource : public RCResource { public: class Accelerator { public: IntOrString Event; uint32_t Id; uint8_t Flags; enum Options { ASCII = (1 << 0), VIRTKEY = (1 << 1), NOINVERT = (1 << 2), ALT = (1 << 3), SHIFT = (1 << 4), CONTROL = (1 << 5) }; static constexpr size_t NumFlags = 6; static StringRef OptionsStr[NumFlags]; }; AcceleratorsResource(OptionalStmtList &&OptStmts) : OptStatements(std::move(OptStmts)) {} void addAccelerator(IntOrString Event, uint32_t Id, uint8_t Flags) { Accelerators.push_back(Accelerator{Event, Id, Flags}); } raw_ostream &log(raw_ostream &) const override; private: std::vector Accelerators; OptionalStmtList OptStatements; }; // CURSOR resource. Represents a single cursor (".cur") file. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380920(v=vs.85).aspx class CursorResource : public RCResource { StringRef CursorLoc; public: CursorResource(StringRef Location) : CursorLoc(Location) {} raw_ostream &log(raw_ostream &) const override; }; // ICON resource. Represents a single ".ico" file containing a group of icons. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381018(v=vs.85).aspx class IconResource : public RCResource { StringRef IconLoc; public: IconResource(StringRef Location) : IconLoc(Location) {} raw_ostream &log(raw_ostream &) const override; }; // HTML resource. Represents a local webpage that is to be embedded into the // resulting resource file. It embeds a file only - no additional resources // (images etc.) are included with this resource. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa966018(v=vs.85).aspx class HTMLResource : public RCResource { StringRef HTMLLoc; public: HTMLResource(StringRef Location) : HTMLLoc(Location) {} raw_ostream &log(raw_ostream &) const override; }; // -- MENU resource and its helper classes -- // This resource describes the contents of an application menu // (usually located in the upper part of the dialog.) // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381025(v=vs.85).aspx // Description of a single submenu item. class MenuDefinition { public: enum Options { CHECKED = (1 << 0), GRAYED = (1 << 1), HELP = (1 << 2), INACTIVE = (1 << 3), MENUBARBREAK = (1 << 4), MENUBREAK = (1 << 5) }; static constexpr size_t NumFlags = 6; static StringRef OptionsStr[NumFlags]; static raw_ostream &logFlags(raw_ostream &, uint8_t Flags); virtual raw_ostream &log(raw_ostream &OS) const { return OS << "Base menu definition\n"; } virtual ~MenuDefinition() {} }; // Recursive description of a whole submenu. class MenuDefinitionList : public MenuDefinition { std::vector> Definitions; public: void addDefinition(std::unique_ptr Def) { Definitions.push_back(std::move(Def)); } raw_ostream &log(raw_ostream &) const override; }; // Separator in MENU definition (MENUITEM SEPARATOR). // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx class MenuSeparator : public MenuDefinition { public: raw_ostream &log(raw_ostream &) const override; }; // MENUITEM statement definition. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx class MenuItem : public MenuDefinition { StringRef Name; uint32_t Id; uint8_t Flags; public: MenuItem(StringRef Caption, uint32_t ItemId, uint8_t ItemFlags) : Name(Caption), Id(ItemId), Flags(ItemFlags) {} raw_ostream &log(raw_ostream &) const override; }; // POPUP statement definition. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx class PopupItem : public MenuDefinition { StringRef Name; uint8_t Flags; MenuDefinitionList SubItems; public: PopupItem(StringRef Caption, uint8_t ItemFlags, MenuDefinitionList &&SubItemsList) : Name(Caption), Flags(ItemFlags), SubItems(std::move(SubItemsList)) {} raw_ostream &log(raw_ostream &) const override; }; // Menu resource definition. class MenuResource : public RCResource { OptionalStmtList OptStatements; MenuDefinitionList Elements; public: MenuResource(OptionalStmtList &&OptStmts, MenuDefinitionList &&Items) : OptStatements(std::move(OptStmts)), Elements(std::move(Items)) {} raw_ostream &log(raw_ostream &) const override; }; // STRINGTABLE resource. Contains a list of strings, each having its unique ID. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381050(v=vs.85).aspx class StringTableResource : public RCResource { OptionalStmtList OptStatements; std::vector> Table; public: StringTableResource(OptionalStmtList &&OptStmts) : OptStatements(std::move(OptStmts)) {} void addString(uint32_t ID, StringRef String) { Table.emplace_back(ID, String); } raw_ostream &log(raw_ostream &) const override; }; // -- DIALOG(EX) resource and its helper classes -- // // This resource describes dialog boxes and controls residing inside them. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381003(v=vs.85).aspx // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx // Single control definition. class Control { StringRef Type, Title; uint32_t ID, X, Y, Width, Height; Optional Style, ExtStyle, HelpID; public: Control(StringRef CtlType, StringRef CtlTitle, uint32_t CtlID, uint32_t PosX, uint32_t PosY, uint32_t ItemWidth, uint32_t ItemHeight, Optional ItemStyle, Optional ExtItemStyle, Optional CtlHelpID) : Type(CtlType), Title(CtlTitle), ID(CtlID), X(PosX), Y(PosY), Width(ItemWidth), Height(ItemHeight), Style(ItemStyle), ExtStyle(ExtItemStyle), HelpID(CtlHelpID) {} static const StringSet<> SupportedCtls; static const StringSet<> CtlsWithTitle; raw_ostream &log(raw_ostream &) const; }; // Single dialog definition. We don't create distinct classes for DIALOG and // DIALOGEX because of their being too similar to each other. We only have a // flag determining the type of the dialog box. class DialogResource : public RCResource { uint32_t X, Y, Width, Height, HelpID; OptionalStmtList OptStatements; std::vector Controls; bool IsExtended; public: DialogResource(uint32_t PosX, uint32_t PosY, uint32_t DlgWidth, uint32_t DlgHeight, uint32_t DlgHelpID, OptionalStmtList &&OptStmts, bool IsDialogEx) : X(PosX), Y(PosY), Width(DlgWidth), Height(DlgHeight), HelpID(DlgHelpID), OptStatements(std::move(OptStmts)), IsExtended(IsDialogEx) {} void addControl(Control &&Ctl) { Controls.push_back(std::move(Ctl)); } raw_ostream &log(raw_ostream &) const override; }; // User-defined resource. It is either: // * a link to the file, e.g. NAME TYPE "filename", // * or contains a list of integers and strings, e.g. NAME TYPE {1, "a", 2}. class UserDefinedResource : public RCResource { IntOrString Type; StringRef FileLoc; std::vector Contents; bool IsFileResource; public: UserDefinedResource(IntOrString ResourceType, StringRef FileLocation) : Type(ResourceType), FileLoc(FileLocation), IsFileResource(true) {} UserDefinedResource(IntOrString ResourceType, std::vector &&Data) : Type(ResourceType), Contents(std::move(Data)), IsFileResource(false) {} raw_ostream &log(raw_ostream &) const override; }; // -- VERSIONINFO resource and its helper classes -- // // This resource lists the version information on the executable/library. // The declaration consists of the following items: // * A number of fixed optional version statements (e.g. FILEVERSION, FILEOS) // * BEGIN // * A number of BLOCK and/or VALUE statements. BLOCK recursively defines // another block of version information, whereas VALUE defines a // key -> value correspondence. There might be more than one value // corresponding to the single key. // * END // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381058(v=vs.85).aspx // A single VERSIONINFO statement; class VersionInfoStmt { public: virtual raw_ostream &log(raw_ostream &OS) const { return OS << "VI stmt\n"; } virtual ~VersionInfoStmt() {} }; // BLOCK definition; also the main VERSIONINFO declaration is considered a // BLOCK, although it has no name. // The correct top-level blocks are "VarFileInfo" and "StringFileInfo". We don't // care about them at the parsing phase. class VersionInfoBlock : public VersionInfoStmt { std::vector> Stmts; StringRef Name; public: VersionInfoBlock(StringRef BlockName) : Name(BlockName) {} void addStmt(std::unique_ptr Stmt) { Stmts.push_back(std::move(Stmt)); } raw_ostream &log(raw_ostream &) const override; }; class VersionInfoValue : public VersionInfoStmt { StringRef Key; std::vector Values; public: VersionInfoValue(StringRef InfoKey, std::vector &&Vals) : Key(InfoKey), Values(std::move(Vals)) {} raw_ostream &log(raw_ostream &) const override; }; class VersionInfoResource : public RCResource { public: // A class listing fixed VERSIONINFO statements (occuring before main BEGIN). // If any of these is not specified, it is assumed by the original tool to // be equal to 0. class VersionInfoFixed { public: enum VersionInfoFixedType { FtUnknown, FtFileVersion, FtProductVersion, FtFileFlagsMask, FtFileFlags, FtFileOS, FtFileType, FtFileSubtype, FtNumTypes }; private: static const StringMap FixedFieldsInfoMap; static const StringRef FixedFieldsNames[FtNumTypes]; public: SmallVector FixedInfo[FtNumTypes]; SmallVector IsTypePresent; static VersionInfoFixedType getFixedType(StringRef Type); static bool isTypeSupported(VersionInfoFixedType Type); static bool isVersionType(VersionInfoFixedType Type); VersionInfoFixed() : IsTypePresent(FtNumTypes, false) {} void setValue(VersionInfoFixedType Type, ArrayRef Value) { FixedInfo[Type] = SmallVector(Value.begin(), Value.end()); IsTypePresent[Type] = true; } raw_ostream &log(raw_ostream &) const; }; private: VersionInfoBlock MainBlock; VersionInfoFixed FixedData; public: VersionInfoResource(VersionInfoBlock &&TopLevelBlock, VersionInfoFixed &&FixedInfo) : MainBlock(std::move(TopLevelBlock)), FixedData(std::move(FixedInfo)) {} raw_ostream &log(raw_ostream &) const override; }; // CHARACTERISTICS optional statement. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380872(v=vs.85).aspx class CharacteristicsStmt : public OptionalStmt { uint32_t Value; public: CharacteristicsStmt(uint32_t Characteristic) : Value(Characteristic) {} raw_ostream &log(raw_ostream &) const override; }; // VERSION optional statement. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381059(v=vs.85).aspx class VersionStmt : public OptionalStmt { uint32_t Value; public: VersionStmt(uint32_t Version) : Value(Version) {} raw_ostream &log(raw_ostream &) const override; }; // CAPTION optional statement. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx class CaptionStmt : public OptionalStmt { StringRef Value; public: CaptionStmt(StringRef Caption) : Value(Caption) {} raw_ostream &log(raw_ostream &) const override; }; // FONT optional statement. // Note that the documentation is inaccurate: it expects five arguments to be // given, however the example provides only two. In fact, the original tool // expects two arguments - point size and name of the typeface. // // 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) {} raw_ostream &log(raw_ostream &) const override; }; // STYLE optional statement. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx class StyleStmt : public OptionalStmt { uint32_t Value; public: StyleStmt(uint32_t Style) : Value(Style) {} raw_ostream &log(raw_ostream &) const override; }; } // namespace rc } // namespace llvm #endif