[JITLink] Add support of R_X86_64_32S relocation
[llvm-project.git] / llvm / tools / llvm-rc / ResourceScriptStmt.h
blob9f77d361a5f02900b4144a01d53d915097e351ff
1 //===-- ResourceScriptStmt.h ------------------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===---------------------------------------------------------------------===//
8 //
9 // This lists all the resource and statement types occurring in RC scripts.
11 //===---------------------------------------------------------------------===//
13 #ifndef LLVM_TOOLS_LLVMRC_RESOURCESCRIPTSTMT_H
14 #define LLVM_TOOLS_LLVMRC_RESOURCESCRIPTSTMT_H
16 #include "ResourceScriptToken.h"
17 #include "ResourceVisitor.h"
19 #include "llvm/ADT/StringSet.h"
21 namespace llvm {
22 namespace rc {
24 // Integer wrapper that also holds information whether the user declared
25 // the integer to be long (by appending L to the end of the integer) or not.
26 // It allows to be implicitly cast from and to uint32_t in order
27 // to be compatible with the parts of code that don't care about the integers
28 // being marked long.
29 class RCInt {
30 uint32_t Val;
31 bool Long;
33 public:
34 RCInt(const RCToken &Token)
35 : Val(Token.intValue()), Long(Token.isLongInt()) {}
36 RCInt(uint32_t Value) : Val(Value), Long(false) {}
37 RCInt(uint32_t Value, bool IsLong) : Val(Value), Long(IsLong) {}
38 operator uint32_t() const { return Val; }
39 bool isLong() const { return Long; }
41 RCInt &operator+=(const RCInt &Rhs) {
42 std::tie(Val, Long) = std::make_pair(Val + Rhs.Val, Long | Rhs.Long);
43 return *this;
46 RCInt &operator-=(const RCInt &Rhs) {
47 std::tie(Val, Long) = std::make_pair(Val - Rhs.Val, Long | Rhs.Long);
48 return *this;
51 RCInt &operator|=(const RCInt &Rhs) {
52 std::tie(Val, Long) = std::make_pair(Val | Rhs.Val, Long | Rhs.Long);
53 return *this;
56 RCInt &operator&=(const RCInt &Rhs) {
57 std::tie(Val, Long) = std::make_pair(Val & Rhs.Val, Long | Rhs.Long);
58 return *this;
61 RCInt operator-() const { return {-Val, Long}; }
62 RCInt operator~() const { return {~Val, Long}; }
64 friend raw_ostream &operator<<(raw_ostream &OS, const RCInt &Int) {
65 return OS << Int.Val << (Int.Long ? "L" : "");
69 class IntWithNotMask {
70 private:
71 RCInt Value;
72 int32_t NotMask;
74 public:
75 IntWithNotMask() : IntWithNotMask(RCInt(0)) {}
76 IntWithNotMask(RCInt Value, int32_t NotMask = 0) : Value(Value), NotMask(NotMask) {}
78 RCInt getValue() const {
79 return Value;
82 uint32_t getNotMask() const {
83 return NotMask;
86 IntWithNotMask &operator+=(const IntWithNotMask &Rhs) {
87 Value &= ~Rhs.NotMask;
88 Value += Rhs.Value;
89 NotMask |= Rhs.NotMask;
90 return *this;
93 IntWithNotMask &operator-=(const IntWithNotMask &Rhs) {
94 Value &= ~Rhs.NotMask;
95 Value -= Rhs.Value;
96 NotMask |= Rhs.NotMask;
97 return *this;
100 IntWithNotMask &operator|=(const IntWithNotMask &Rhs) {
101 Value &= ~Rhs.NotMask;
102 Value |= Rhs.Value;
103 NotMask |= Rhs.NotMask;
104 return *this;
107 IntWithNotMask &operator&=(const IntWithNotMask &Rhs) {
108 Value &= ~Rhs.NotMask;
109 Value &= Rhs.Value;
110 NotMask |= Rhs.NotMask;
111 return *this;
114 IntWithNotMask operator-() const { return {-Value, NotMask}; }
115 IntWithNotMask operator~() const { return {~Value, 0}; }
117 friend raw_ostream &operator<<(raw_ostream &OS, const IntWithNotMask &Int) {
118 return OS << Int.Value;
122 // A class holding a name - either an integer or a reference to the string.
123 class IntOrString {
124 private:
125 union Data {
126 RCInt Int;
127 StringRef String;
128 Data(RCInt Value) : Int(Value) {}
129 Data(const StringRef Value) : String(Value) {}
130 Data(const RCToken &Token) {
131 if (Token.kind() == RCToken::Kind::Int)
132 Int = RCInt(Token);
133 else
134 String = Token.value();
136 } Data;
137 bool IsInt;
139 public:
140 IntOrString() : IntOrString(RCInt(0)) {}
141 IntOrString(uint32_t Value) : Data(Value), IsInt(1) {}
142 IntOrString(RCInt Value) : Data(Value), IsInt(1) {}
143 IntOrString(StringRef Value) : Data(Value), IsInt(0) {}
144 IntOrString(const RCToken &Token)
145 : Data(Token), IsInt(Token.kind() == RCToken::Kind::Int) {}
147 bool equalsLower(const char *Str) {
148 return !IsInt && Data.String.equals_insensitive(Str);
151 bool isInt() const { return IsInt; }
153 RCInt getInt() const {
154 assert(IsInt);
155 return Data.Int;
158 const StringRef &getString() const {
159 assert(!IsInt);
160 return Data.String;
163 operator Twine() const {
164 return isInt() ? Twine(getInt()) : Twine(getString());
167 friend raw_ostream &operator<<(raw_ostream &, const IntOrString &);
170 enum ResourceKind {
171 // These resource kinds have corresponding .res resource type IDs
172 // (TYPE in RESOURCEHEADER structure). The numeric value assigned to each
173 // kind is equal to this type ID.
174 RkNull = 0,
175 RkSingleCursor = 1,
176 RkBitmap = 2,
177 RkSingleIcon = 3,
178 RkMenu = 4,
179 RkDialog = 5,
180 RkStringTableBundle = 6,
181 RkAccelerators = 9,
182 RkRcData = 10,
183 RkCursorGroup = 12,
184 RkIconGroup = 14,
185 RkVersionInfo = 16,
186 RkHTML = 23,
188 // These kinds don't have assigned type IDs (they might be the resources
189 // of invalid kind, expand to many resource structures in .res files,
190 // or have variable type ID). In order to avoid ID clashes with IDs above,
191 // we assign the kinds the values 256 and larger.
192 RkInvalid = 256,
193 RkBase,
194 RkCursor,
195 RkIcon,
196 RkStringTable,
197 RkUser,
198 RkSingleCursorOrIconRes,
199 RkCursorOrIconGroupRes,
202 // Non-zero memory flags.
203 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648027(v=vs.85).aspx
204 enum MemoryFlags {
205 MfMoveable = 0x10,
206 MfPure = 0x20,
207 MfPreload = 0x40,
208 MfDiscardable = 0x1000
211 // Base resource. All the resources should derive from this base.
212 class RCResource {
213 public:
214 IntOrString ResName;
215 uint16_t MemoryFlags = getDefaultMemoryFlags();
216 void setName(const IntOrString &Name) { ResName = Name; }
217 virtual raw_ostream &log(raw_ostream &OS) const {
218 return OS << "Base statement\n";
220 RCResource() {}
221 RCResource(uint16_t Flags) : MemoryFlags(Flags) {}
222 virtual ~RCResource() {}
224 virtual Error visit(Visitor *) const {
225 llvm_unreachable("This is unable to call methods from Visitor base");
228 // Apply the statements attached to this resource. Generic resources
229 // don't have any.
230 virtual Error applyStmts(Visitor *) const { return Error::success(); }
232 // By default, memory flags are DISCARDABLE | PURE | MOVEABLE.
233 static uint16_t getDefaultMemoryFlags() {
234 return MfDiscardable | MfPure | MfMoveable;
237 virtual ResourceKind getKind() const { return RkBase; }
238 static bool classof(const RCResource *Res) { return true; }
240 virtual IntOrString getResourceType() const {
241 llvm_unreachable("This cannot be called on objects without types.");
243 virtual Twine getResourceTypeName() const {
244 llvm_unreachable("This cannot be called on objects without types.");
248 // An empty resource. It has no content, type 0, ID 0 and all of its
249 // characteristics are equal to 0.
250 class NullResource : public RCResource {
251 public:
252 NullResource() : RCResource(0) {}
253 raw_ostream &log(raw_ostream &OS) const override {
254 return OS << "Null resource\n";
256 Error visit(Visitor *V) const override { return V->visitNullResource(this); }
257 IntOrString getResourceType() const override { return 0; }
258 Twine getResourceTypeName() const override { return "(NULL)"; }
261 // Optional statement base. All such statements should derive from this base.
262 class OptionalStmt : public RCResource {};
264 class OptionalStmtList : public OptionalStmt {
265 std::vector<std::unique_ptr<OptionalStmt>> Statements;
267 public:
268 OptionalStmtList() {}
269 raw_ostream &log(raw_ostream &OS) const override;
271 void addStmt(std::unique_ptr<OptionalStmt> Stmt) {
272 Statements.push_back(std::move(Stmt));
275 Error visit(Visitor *V) const override {
276 for (auto &StmtPtr : Statements)
277 if (auto Err = StmtPtr->visit(V))
278 return Err;
279 return Error::success();
283 class OptStatementsRCResource : public RCResource {
284 public:
285 std::unique_ptr<OptionalStmtList> OptStatements;
287 OptStatementsRCResource(OptionalStmtList &&Stmts,
288 uint16_t Flags = RCResource::getDefaultMemoryFlags())
289 : RCResource(Flags),
290 OptStatements(std::make_unique<OptionalStmtList>(std::move(Stmts))) {}
292 Error applyStmts(Visitor *V) const override {
293 return OptStatements->visit(V);
297 // LANGUAGE statement. It can occur both as a top-level statement (in such
298 // a situation, it changes the default language until the end of the file)
299 // and as an optional resource statement (then it changes the language
300 // of a single resource).
302 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381019(v=vs.85).aspx
303 class LanguageResource : public OptionalStmt {
304 public:
305 uint32_t Lang, SubLang;
307 LanguageResource(uint32_t LangId, uint32_t SubLangId)
308 : Lang(LangId), SubLang(SubLangId) {}
309 raw_ostream &log(raw_ostream &) const override;
311 // This is not a regular top-level statement; when it occurs, it just
312 // modifies the language context.
313 Error visit(Visitor *V) const override { return V->visitLanguageStmt(this); }
314 Twine getResourceTypeName() const override { return "LANGUAGE"; }
317 // ACCELERATORS resource. Defines a named table of accelerators for the app.
319 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380610(v=vs.85).aspx
320 class AcceleratorsResource : public OptStatementsRCResource {
321 public:
322 class Accelerator {
323 public:
324 IntOrString Event;
325 uint32_t Id;
326 uint16_t Flags;
328 enum Options {
329 // This is actually 0x0000 (accelerator is assumed to be ASCII if it's
330 // not VIRTKEY). However, rc.exe behavior is different in situations
331 // "only ASCII defined" and "neither ASCII nor VIRTKEY defined".
332 // Therefore, we include ASCII as another flag. This must be zeroed
333 // when serialized.
334 ASCII = 0x8000,
335 VIRTKEY = 0x0001,
336 NOINVERT = 0x0002,
337 ALT = 0x0010,
338 SHIFT = 0x0004,
339 CONTROL = 0x0008
342 static constexpr size_t NumFlags = 6;
343 static StringRef OptionsStr[NumFlags];
344 static uint32_t OptionsFlags[NumFlags];
347 AcceleratorsResource(OptionalStmtList &&List, uint16_t Flags)
348 : OptStatementsRCResource(std::move(List), Flags) {}
350 std::vector<Accelerator> Accelerators;
352 void addAccelerator(IntOrString Event, uint32_t Id, uint16_t Flags) {
353 Accelerators.push_back(Accelerator{Event, Id, Flags});
355 raw_ostream &log(raw_ostream &) const override;
357 IntOrString getResourceType() const override { return RkAccelerators; }
358 static uint16_t getDefaultMemoryFlags() { return MfPure | MfMoveable; }
359 Twine getResourceTypeName() const override { return "ACCELERATORS"; }
361 Error visit(Visitor *V) const override {
362 return V->visitAcceleratorsResource(this);
364 ResourceKind getKind() const override { return RkAccelerators; }
365 static bool classof(const RCResource *Res) {
366 return Res->getKind() == RkAccelerators;
370 // BITMAP resource. Represents a bitmap (".bmp") file.
372 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380680(v=vs.85).aspx
373 class BitmapResource : public RCResource {
374 public:
375 StringRef BitmapLoc;
377 BitmapResource(StringRef Location, uint16_t Flags)
378 : RCResource(Flags), BitmapLoc(Location) {}
379 raw_ostream &log(raw_ostream &) const override;
381 IntOrString getResourceType() const override { return RkBitmap; }
382 static uint16_t getDefaultMemoryFlags() { return MfPure | MfMoveable; }
384 Twine getResourceTypeName() const override { return "BITMAP"; }
385 Error visit(Visitor *V) const override {
386 return V->visitBitmapResource(this);
388 ResourceKind getKind() const override { return RkBitmap; }
389 static bool classof(const RCResource *Res) {
390 return Res->getKind() == RkBitmap;
394 // CURSOR resource. Represents a single cursor (".cur") file.
396 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380920(v=vs.85).aspx
397 class CursorResource : public RCResource {
398 public:
399 StringRef CursorLoc;
401 CursorResource(StringRef Location, uint16_t Flags)
402 : RCResource(Flags), CursorLoc(Location) {}
403 raw_ostream &log(raw_ostream &) const override;
405 Twine getResourceTypeName() const override { return "CURSOR"; }
406 static uint16_t getDefaultMemoryFlags() { return MfDiscardable | MfMoveable; }
407 Error visit(Visitor *V) const override {
408 return V->visitCursorResource(this);
410 ResourceKind getKind() const override { return RkCursor; }
411 static bool classof(const RCResource *Res) {
412 return Res->getKind() == RkCursor;
416 // ICON resource. Represents a single ".ico" file containing a group of icons.
418 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381018(v=vs.85).aspx
419 class IconResource : public RCResource {
420 public:
421 StringRef IconLoc;
423 IconResource(StringRef Location, uint16_t Flags)
424 : RCResource(Flags), IconLoc(Location) {}
425 raw_ostream &log(raw_ostream &) const override;
427 Twine getResourceTypeName() const override { return "ICON"; }
428 static uint16_t getDefaultMemoryFlags() { return MfDiscardable | MfMoveable; }
429 Error visit(Visitor *V) const override { return V->visitIconResource(this); }
430 ResourceKind getKind() const override { return RkIcon; }
431 static bool classof(const RCResource *Res) {
432 return Res->getKind() == RkIcon;
436 // HTML resource. Represents a local webpage that is to be embedded into the
437 // resulting resource file. It embeds a file only - no additional resources
438 // (images etc.) are included with this resource.
440 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa966018(v=vs.85).aspx
441 class HTMLResource : public RCResource {
442 public:
443 StringRef HTMLLoc;
445 HTMLResource(StringRef Location, uint16_t Flags)
446 : RCResource(Flags), HTMLLoc(Location) {}
447 raw_ostream &log(raw_ostream &) const override;
449 Error visit(Visitor *V) const override { return V->visitHTMLResource(this); }
451 // Curiously, file resources don't have DISCARDABLE flag set.
452 static uint16_t getDefaultMemoryFlags() { return MfPure | MfMoveable; }
453 IntOrString getResourceType() const override { return RkHTML; }
454 Twine getResourceTypeName() const override { return "HTML"; }
455 ResourceKind getKind() const override { return RkHTML; }
456 static bool classof(const RCResource *Res) {
457 return Res->getKind() == RkHTML;
461 // -- MENU resource and its helper classes --
462 // This resource describes the contents of an application menu
463 // (usually located in the upper part of the dialog.)
465 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381025(v=vs.85).aspx
467 // Description of a single submenu item.
468 class MenuDefinition {
469 public:
470 enum Options {
471 CHECKED = 0x0008,
472 GRAYED = 0x0001,
473 HELP = 0x4000,
474 INACTIVE = 0x0002,
475 MENUBARBREAK = 0x0020,
476 MENUBREAK = 0x0040
479 enum MenuDefKind { MkBase, MkSeparator, MkMenuItem, MkPopup };
481 static constexpr size_t NumFlags = 6;
482 static StringRef OptionsStr[NumFlags];
483 static uint32_t OptionsFlags[NumFlags];
484 static raw_ostream &logFlags(raw_ostream &, uint16_t Flags);
485 virtual raw_ostream &log(raw_ostream &OS) const {
486 return OS << "Base menu definition\n";
488 virtual ~MenuDefinition() {}
490 virtual uint16_t getResFlags() const { return 0; }
491 virtual MenuDefKind getKind() const { return MkBase; }
494 // Recursive description of a whole submenu.
495 class MenuDefinitionList : public MenuDefinition {
496 public:
497 std::vector<std::unique_ptr<MenuDefinition>> Definitions;
499 void addDefinition(std::unique_ptr<MenuDefinition> Def) {
500 Definitions.push_back(std::move(Def));
502 raw_ostream &log(raw_ostream &) const override;
505 // Separator in MENU definition (MENUITEM SEPARATOR).
507 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
508 class MenuSeparator : public MenuDefinition {
509 public:
510 raw_ostream &log(raw_ostream &) const override;
512 MenuDefKind getKind() const override { return MkSeparator; }
513 static bool classof(const MenuDefinition *D) {
514 return D->getKind() == MkSeparator;
518 // MENUITEM statement definition.
520 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
521 class MenuItem : public MenuDefinition {
522 public:
523 StringRef Name;
524 uint32_t Id;
525 uint16_t Flags;
527 MenuItem(StringRef Caption, uint32_t ItemId, uint16_t ItemFlags)
528 : Name(Caption), Id(ItemId), Flags(ItemFlags) {}
529 raw_ostream &log(raw_ostream &) const override;
531 uint16_t getResFlags() const override { return Flags; }
532 MenuDefKind getKind() const override { return MkMenuItem; }
533 static bool classof(const MenuDefinition *D) {
534 return D->getKind() == MkMenuItem;
538 // POPUP statement definition.
540 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx
541 class PopupItem : public MenuDefinition {
542 public:
543 StringRef Name;
544 uint16_t Flags;
545 MenuDefinitionList SubItems;
547 PopupItem(StringRef Caption, uint16_t ItemFlags,
548 MenuDefinitionList &&SubItemsList)
549 : Name(Caption), Flags(ItemFlags), SubItems(std::move(SubItemsList)) {}
550 raw_ostream &log(raw_ostream &) const override;
552 // This has an additional (0x10) flag. It doesn't match with documented
553 // 0x01 flag, though.
554 uint16_t getResFlags() const override { return Flags | 0x10; }
555 MenuDefKind getKind() const override { return MkPopup; }
556 static bool classof(const MenuDefinition *D) {
557 return D->getKind() == MkPopup;
561 // Menu resource definition.
562 class MenuResource : public OptStatementsRCResource {
563 public:
564 MenuDefinitionList Elements;
566 MenuResource(OptionalStmtList &&OptStmts, MenuDefinitionList &&Items,
567 uint16_t Flags)
568 : OptStatementsRCResource(std::move(OptStmts), Flags),
569 Elements(std::move(Items)) {}
570 raw_ostream &log(raw_ostream &) const override;
572 IntOrString getResourceType() const override { return RkMenu; }
573 Twine getResourceTypeName() const override { return "MENU"; }
574 Error visit(Visitor *V) const override { return V->visitMenuResource(this); }
575 ResourceKind getKind() const override { return RkMenu; }
576 static bool classof(const RCResource *Res) {
577 return Res->getKind() == RkMenu;
581 // STRINGTABLE resource. Contains a list of strings, each having its unique ID.
583 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381050(v=vs.85).aspx
584 class StringTableResource : public OptStatementsRCResource {
585 public:
586 std::vector<std::pair<uint32_t, std::vector<StringRef>>> Table;
588 StringTableResource(OptionalStmtList &&List, uint16_t Flags)
589 : OptStatementsRCResource(std::move(List), Flags) {}
590 void addStrings(uint32_t ID, std::vector<StringRef> &&Strings) {
591 Table.emplace_back(ID, Strings);
593 raw_ostream &log(raw_ostream &) const override;
594 Twine getResourceTypeName() const override { return "STRINGTABLE"; }
595 Error visit(Visitor *V) const override {
596 return V->visitStringTableResource(this);
600 // -- DIALOG(EX) resource and its helper classes --
602 // This resource describes dialog boxes and controls residing inside them.
604 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381003(v=vs.85).aspx
605 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx
607 // Single control definition.
608 class Control {
609 public:
610 StringRef Type;
611 IntOrString Title;
612 uint32_t ID, X, Y, Width, Height;
613 Optional<IntWithNotMask> Style;
614 Optional<uint32_t> ExtStyle, HelpID;
615 IntOrString Class;
617 // Control classes as described in DLGITEMTEMPLATEEX documentation.
619 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms645389.aspx
620 enum CtlClasses {
621 ClsButton = 0x80,
622 ClsEdit = 0x81,
623 ClsStatic = 0x82,
624 ClsListBox = 0x83,
625 ClsScrollBar = 0x84,
626 ClsComboBox = 0x85
629 // Simple information about a single control type.
630 struct CtlInfo {
631 uint32_t Style;
632 uint16_t CtlClass;
633 bool HasTitle;
636 Control(StringRef CtlType, IntOrString CtlTitle, uint32_t CtlID,
637 uint32_t PosX, uint32_t PosY, uint32_t ItemWidth, uint32_t ItemHeight,
638 Optional<IntWithNotMask> ItemStyle, Optional<uint32_t> ExtItemStyle,
639 Optional<uint32_t> CtlHelpID, IntOrString CtlClass)
640 : Type(CtlType), Title(CtlTitle), ID(CtlID), X(PosX), Y(PosY),
641 Width(ItemWidth), Height(ItemHeight), Style(ItemStyle),
642 ExtStyle(ExtItemStyle), HelpID(CtlHelpID), Class(CtlClass) {}
644 static const StringMap<CtlInfo> SupportedCtls;
646 raw_ostream &log(raw_ostream &) const;
649 // Single dialog definition. We don't create distinct classes for DIALOG and
650 // DIALOGEX because of their being too similar to each other. We only have a
651 // flag determining the type of the dialog box.
652 class DialogResource : public OptStatementsRCResource {
653 public:
654 uint32_t X, Y, Width, Height, HelpID;
655 std::vector<Control> Controls;
656 bool IsExtended;
658 DialogResource(uint32_t PosX, uint32_t PosY, uint32_t DlgWidth,
659 uint32_t DlgHeight, uint32_t DlgHelpID,
660 OptionalStmtList &&OptStmts, bool IsDialogEx, uint16_t Flags)
661 : OptStatementsRCResource(std::move(OptStmts), Flags), X(PosX), Y(PosY),
662 Width(DlgWidth), Height(DlgHeight), HelpID(DlgHelpID),
663 IsExtended(IsDialogEx) {}
665 void addControl(Control &&Ctl) { Controls.push_back(std::move(Ctl)); }
667 raw_ostream &log(raw_ostream &) const override;
669 // It was a weird design decision to assign the same resource type number
670 // both for DIALOG and DIALOGEX (and the same structure version number).
671 // It makes it possible for DIALOG to be mistaken for DIALOGEX.
672 IntOrString getResourceType() const override { return RkDialog; }
673 Twine getResourceTypeName() const override {
674 return "DIALOG" + Twine(IsExtended ? "EX" : "");
676 Error visit(Visitor *V) const override {
677 return V->visitDialogResource(this);
679 ResourceKind getKind() const override { return RkDialog; }
680 static bool classof(const RCResource *Res) {
681 return Res->getKind() == RkDialog;
685 // User-defined resource. It is either:
686 // * a link to the file, e.g. NAME TYPE "filename",
687 // * or contains a list of integers and strings, e.g. NAME TYPE {1, "a", 2}.
688 class UserDefinedResource : public RCResource {
689 public:
690 IntOrString Type;
691 StringRef FileLoc;
692 std::vector<IntOrString> Contents;
693 bool IsFileResource;
695 UserDefinedResource(IntOrString ResourceType, StringRef FileLocation,
696 uint16_t Flags)
697 : RCResource(Flags), Type(ResourceType), FileLoc(FileLocation),
698 IsFileResource(true) {}
699 UserDefinedResource(IntOrString ResourceType, std::vector<IntOrString> &&Data,
700 uint16_t Flags)
701 : RCResource(Flags), Type(ResourceType), Contents(std::move(Data)),
702 IsFileResource(false) {}
704 raw_ostream &log(raw_ostream &) const override;
705 IntOrString getResourceType() const override { return Type; }
706 Twine getResourceTypeName() const override { return Type; }
707 static uint16_t getDefaultMemoryFlags() { return MfPure | MfMoveable; }
709 Error visit(Visitor *V) const override {
710 return V->visitUserDefinedResource(this);
712 ResourceKind getKind() const override { return RkUser; }
713 static bool classof(const RCResource *Res) {
714 return Res->getKind() == RkUser;
718 // -- VERSIONINFO resource and its helper classes --
720 // This resource lists the version information on the executable/library.
721 // The declaration consists of the following items:
722 // * A number of fixed optional version statements (e.g. FILEVERSION, FILEOS)
723 // * BEGIN
724 // * A number of BLOCK and/or VALUE statements. BLOCK recursively defines
725 // another block of version information, whereas VALUE defines a
726 // key -> value correspondence. There might be more than one value
727 // corresponding to the single key.
728 // * END
730 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381058(v=vs.85).aspx
732 // A single VERSIONINFO statement;
733 class VersionInfoStmt {
734 public:
735 enum StmtKind { StBase = 0, StBlock = 1, StValue = 2 };
737 virtual raw_ostream &log(raw_ostream &OS) const { return OS << "VI stmt\n"; }
738 virtual ~VersionInfoStmt() {}
740 virtual StmtKind getKind() const { return StBase; }
741 static bool classof(const VersionInfoStmt *S) {
742 return S->getKind() == StBase;
746 // BLOCK definition; also the main VERSIONINFO declaration is considered a
747 // BLOCK, although it has no name.
748 // The correct top-level blocks are "VarFileInfo" and "StringFileInfo". We don't
749 // care about them at the parsing phase.
750 class VersionInfoBlock : public VersionInfoStmt {
751 public:
752 std::vector<std::unique_ptr<VersionInfoStmt>> Stmts;
753 StringRef Name;
755 VersionInfoBlock(StringRef BlockName) : Name(BlockName) {}
756 void addStmt(std::unique_ptr<VersionInfoStmt> Stmt) {
757 Stmts.push_back(std::move(Stmt));
759 raw_ostream &log(raw_ostream &) const override;
761 StmtKind getKind() const override { return StBlock; }
762 static bool classof(const VersionInfoStmt *S) {
763 return S->getKind() == StBlock;
767 class VersionInfoValue : public VersionInfoStmt {
768 public:
769 StringRef Key;
770 std::vector<IntOrString> Values;
771 std::vector<bool> HasPrecedingComma;
773 VersionInfoValue(StringRef InfoKey, std::vector<IntOrString> &&Vals,
774 std::vector<bool> &&CommasBeforeVals)
775 : Key(InfoKey), Values(std::move(Vals)),
776 HasPrecedingComma(std::move(CommasBeforeVals)) {}
777 raw_ostream &log(raw_ostream &) const override;
779 StmtKind getKind() const override { return StValue; }
780 static bool classof(const VersionInfoStmt *S) {
781 return S->getKind() == StValue;
785 class VersionInfoResource : public RCResource {
786 public:
787 // A class listing fixed VERSIONINFO statements (occuring before main BEGIN).
788 // If any of these is not specified, it is assumed by the original tool to
789 // be equal to 0.
790 class VersionInfoFixed {
791 public:
792 enum VersionInfoFixedType {
793 FtUnknown,
794 FtFileVersion,
795 FtProductVersion,
796 FtFileFlagsMask,
797 FtFileFlags,
798 FtFileOS,
799 FtFileType,
800 FtFileSubtype,
801 FtNumTypes
804 private:
805 static const StringMap<VersionInfoFixedType> FixedFieldsInfoMap;
806 static const StringRef FixedFieldsNames[FtNumTypes];
808 public:
809 SmallVector<uint32_t, 4> FixedInfo[FtNumTypes];
810 SmallVector<bool, FtNumTypes> IsTypePresent;
812 static VersionInfoFixedType getFixedType(StringRef Type);
813 static bool isTypeSupported(VersionInfoFixedType Type);
814 static bool isVersionType(VersionInfoFixedType Type);
816 VersionInfoFixed() : IsTypePresent(FtNumTypes, false) {}
818 void setValue(VersionInfoFixedType Type, ArrayRef<uint32_t> Value) {
819 FixedInfo[Type] = SmallVector<uint32_t, 4>(Value.begin(), Value.end());
820 IsTypePresent[Type] = true;
823 raw_ostream &log(raw_ostream &) const;
826 VersionInfoBlock MainBlock;
827 VersionInfoFixed FixedData;
829 VersionInfoResource(VersionInfoBlock &&TopLevelBlock,
830 VersionInfoFixed &&FixedInfo, uint16_t Flags)
831 : RCResource(Flags), MainBlock(std::move(TopLevelBlock)),
832 FixedData(std::move(FixedInfo)) {}
834 raw_ostream &log(raw_ostream &) const override;
835 IntOrString getResourceType() const override { return RkVersionInfo; }
836 static uint16_t getDefaultMemoryFlags() { return MfMoveable | MfPure; }
837 Twine getResourceTypeName() const override { return "VERSIONINFO"; }
838 Error visit(Visitor *V) const override {
839 return V->visitVersionInfoResource(this);
841 ResourceKind getKind() const override { return RkVersionInfo; }
842 static bool classof(const RCResource *Res) {
843 return Res->getKind() == RkVersionInfo;
847 // CHARACTERISTICS optional statement.
849 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380872(v=vs.85).aspx
850 class CharacteristicsStmt : public OptionalStmt {
851 public:
852 uint32_t Value;
854 CharacteristicsStmt(uint32_t Characteristic) : Value(Characteristic) {}
855 raw_ostream &log(raw_ostream &) const override;
857 Twine getResourceTypeName() const override { return "CHARACTERISTICS"; }
858 Error visit(Visitor *V) const override {
859 return V->visitCharacteristicsStmt(this);
863 // VERSION optional statement.
865 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381059(v=vs.85).aspx
866 class VersionStmt : public OptionalStmt {
867 public:
868 uint32_t Value;
870 VersionStmt(uint32_t Version) : Value(Version) {}
871 raw_ostream &log(raw_ostream &) const override;
873 Twine getResourceTypeName() const override { return "VERSION"; }
874 Error visit(Visitor *V) const override { return V->visitVersionStmt(this); }
877 // CAPTION optional statement.
879 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx
880 class CaptionStmt : public OptionalStmt {
881 public:
882 StringRef Value;
884 CaptionStmt(StringRef Caption) : Value(Caption) {}
885 raw_ostream &log(raw_ostream &) const override;
886 Twine getResourceTypeName() const override { return "CAPTION"; }
887 Error visit(Visitor *V) const override { return V->visitCaptionStmt(this); }
890 // FONT optional statement.
891 // Note that the documentation is inaccurate: it expects five arguments to be
892 // given, however the example provides only two. In fact, the original tool
893 // expects two arguments - point size and name of the typeface.
895 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381013(v=vs.85).aspx
896 class FontStmt : public OptionalStmt {
897 public:
898 uint32_t Size, Weight, Charset;
899 StringRef Name;
900 bool Italic;
902 FontStmt(uint32_t FontSize, StringRef FontName, uint32_t FontWeight,
903 bool FontItalic, uint32_t FontCharset)
904 : Size(FontSize), Weight(FontWeight), Charset(FontCharset),
905 Name(FontName), Italic(FontItalic) {}
906 raw_ostream &log(raw_ostream &) const override;
907 Twine getResourceTypeName() const override { return "FONT"; }
908 Error visit(Visitor *V) const override { return V->visitFontStmt(this); }
911 // STYLE optional statement.
913 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx
914 class StyleStmt : public OptionalStmt {
915 public:
916 uint32_t Value;
918 StyleStmt(uint32_t Style) : Value(Style) {}
919 raw_ostream &log(raw_ostream &) const override;
920 Twine getResourceTypeName() const override { return "STYLE"; }
921 Error visit(Visitor *V) const override { return V->visitStyleStmt(this); }
924 // EXSTYLE optional statement.
926 // Ref: docs.microsoft.com/en-us/windows/desktop/menurc/exstyle-statement
927 class ExStyleStmt : public OptionalStmt {
928 public:
929 uint32_t Value;
931 ExStyleStmt(uint32_t ExStyle) : Value(ExStyle) {}
932 raw_ostream &log(raw_ostream &) const override;
933 Twine getResourceTypeName() const override { return "EXSTYLE"; }
934 Error visit(Visitor *V) const override { return V->visitExStyleStmt(this); }
937 // CLASS optional statement.
939 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380883(v=vs.85).aspx
940 class ClassStmt : public OptionalStmt {
941 public:
942 IntOrString Value;
944 ClassStmt(IntOrString Class) : Value(Class) {}
945 raw_ostream &log(raw_ostream &) const override;
946 Twine getResourceTypeName() const override { return "CLASS"; }
947 Error visit(Visitor *V) const override { return V->visitClassStmt(this); }
950 } // namespace rc
951 } // namespace llvm
953 #endif