1 //===-- ResourceScriptStmt.h ------------------------------------*- C++-*-===//
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
7 //===---------------------------------------------------------------------===//
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/BitVector.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 class IntWithNotMask
{
76 IntWithNotMask() : IntWithNotMask(RCInt(0)) {}
77 IntWithNotMask(RCInt Value
, int32_t NotMask
= 0) : Value(Value
), NotMask(NotMask
) {}
79 RCInt
getValue() const {
83 uint32_t getNotMask() const {
87 IntWithNotMask
&operator+=(const IntWithNotMask
&Rhs
) {
88 Value
&= ~Rhs
.NotMask
;
90 NotMask
|= Rhs
.NotMask
;
94 IntWithNotMask
&operator-=(const IntWithNotMask
&Rhs
) {
95 Value
&= ~Rhs
.NotMask
;
97 NotMask
|= Rhs
.NotMask
;
101 IntWithNotMask
&operator|=(const IntWithNotMask
&Rhs
) {
102 Value
&= ~Rhs
.NotMask
;
104 NotMask
|= Rhs
.NotMask
;
108 IntWithNotMask
&operator&=(const IntWithNotMask
&Rhs
) {
109 Value
&= ~Rhs
.NotMask
;
111 NotMask
|= Rhs
.NotMask
;
115 IntWithNotMask
operator-() const { return {-Value
, NotMask
}; }
116 IntWithNotMask
operator~() const { return {~Value
, 0}; }
118 friend raw_ostream
&operator<<(raw_ostream
&OS
, const IntWithNotMask
&Int
) {
119 return OS
<< Int
.Value
;
123 // A class holding a name - either an integer or a reference to the string.
129 Data(RCInt Value
) : Int(Value
) {}
130 Data(const StringRef Value
) : String(Value
) {}
131 Data(const RCToken
&Token
) {
132 if (Token
.kind() == RCToken::Kind::Int
)
135 String
= Token
.value();
141 IntOrString() : IntOrString(RCInt(0)) {}
142 IntOrString(uint32_t Value
) : Data(Value
), IsInt(true) {}
143 IntOrString(RCInt Value
) : Data(Value
), IsInt(true) {}
144 IntOrString(StringRef Value
) : Data(Value
), IsInt(false) {}
145 IntOrString(const RCToken
&Token
)
146 : Data(Token
), IsInt(Token
.kind() == RCToken::Kind::Int
) {}
148 bool equalsLower(const char *Str
) {
149 return !IsInt
&& Data
.String
.equals_insensitive(Str
);
152 bool isInt() const { return IsInt
; }
154 RCInt
getInt() const {
159 const StringRef
&getString() const {
164 operator Twine() const {
165 return isInt() ? Twine(getInt()) : Twine(getString());
168 friend raw_ostream
&operator<<(raw_ostream
&, const IntOrString
&);
172 // These resource kinds have corresponding .res resource type IDs
173 // (TYPE in RESOURCEHEADER structure). The numeric value assigned to each
174 // kind is equal to this type ID.
181 RkStringTableBundle
= 6,
189 // These kinds don't have assigned type IDs (they might be the resources
190 // of invalid kind, expand to many resource structures in .res files,
191 // or have variable type ID). In order to avoid ID clashes with IDs above,
192 // we assign the kinds the values 256 and larger.
199 RkSingleCursorOrIconRes
,
200 RkCursorOrIconGroupRes
,
203 // Non-zero memory flags.
204 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648027(v=vs.85).aspx
209 MfDiscardable
= 0x1000
212 // Base resource. All the resources should derive from this base.
216 uint16_t MemoryFlags
= getDefaultMemoryFlags();
217 void setName(const IntOrString
&Name
) { ResName
= Name
; }
218 virtual raw_ostream
&log(raw_ostream
&OS
) const {
219 return OS
<< "Base statement\n";
222 RCResource(uint16_t Flags
) : MemoryFlags(Flags
) {}
223 virtual ~RCResource() {}
225 virtual Error
visit(Visitor
*) const {
226 llvm_unreachable("This is unable to call methods from Visitor base");
229 // Apply the statements attached to this resource. Generic resources
231 virtual Error
applyStmts(Visitor
*) const { return Error::success(); }
233 // By default, memory flags are DISCARDABLE | PURE | MOVEABLE.
234 static uint16_t getDefaultMemoryFlags() {
235 return MfDiscardable
| MfPure
| MfMoveable
;
238 virtual ResourceKind
getKind() const { return RkBase
; }
239 static bool classof(const RCResource
*Res
) { return true; }
241 virtual IntOrString
getResourceType() const {
242 llvm_unreachable("This cannot be called on objects without types.");
244 virtual Twine
getResourceTypeName() const {
245 llvm_unreachable("This cannot be called on objects without types.");
249 // An empty resource. It has no content, type 0, ID 0 and all of its
250 // characteristics are equal to 0.
251 class NullResource
: public RCResource
{
253 NullResource() : RCResource(0) {}
254 raw_ostream
&log(raw_ostream
&OS
) const override
{
255 return OS
<< "Null resource\n";
257 Error
visit(Visitor
*V
) const override
{ return V
->visitNullResource(this); }
258 IntOrString
getResourceType() const override
{ return 0; }
259 Twine
getResourceTypeName() const override
{ return "(NULL)"; }
262 // Optional statement base. All such statements should derive from this base.
263 class OptionalStmt
: public RCResource
{};
265 class OptionalStmtList
: public OptionalStmt
{
266 std::vector
<std::unique_ptr
<OptionalStmt
>> Statements
;
269 OptionalStmtList() {}
270 raw_ostream
&log(raw_ostream
&OS
) const override
;
272 void addStmt(std::unique_ptr
<OptionalStmt
> Stmt
) {
273 Statements
.push_back(std::move(Stmt
));
276 Error
visit(Visitor
*V
) const override
{
277 for (auto &StmtPtr
: Statements
)
278 if (auto Err
= StmtPtr
->visit(V
))
280 return Error::success();
284 class OptStatementsRCResource
: public RCResource
{
286 std::unique_ptr
<OptionalStmtList
> OptStatements
;
288 OptStatementsRCResource(OptionalStmtList
&&Stmts
,
289 uint16_t Flags
= RCResource::getDefaultMemoryFlags())
291 OptStatements(std::make_unique
<OptionalStmtList
>(std::move(Stmts
))) {}
293 Error
applyStmts(Visitor
*V
) const override
{
294 return OptStatements
->visit(V
);
298 // LANGUAGE statement. It can occur both as a top-level statement (in such
299 // a situation, it changes the default language until the end of the file)
300 // and as an optional resource statement (then it changes the language
301 // of a single resource).
303 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381019(v=vs.85).aspx
304 class LanguageResource
: public OptionalStmt
{
306 uint32_t Lang
, SubLang
;
308 LanguageResource(uint32_t LangId
, uint32_t SubLangId
)
309 : Lang(LangId
), SubLang(SubLangId
) {}
310 raw_ostream
&log(raw_ostream
&) const override
;
312 // This is not a regular top-level statement; when it occurs, it just
313 // modifies the language context.
314 Error
visit(Visitor
*V
) const override
{ return V
->visitLanguageStmt(this); }
315 Twine
getResourceTypeName() const override
{ return "LANGUAGE"; }
318 // ACCELERATORS resource. Defines a named table of accelerators for the app.
320 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380610(v=vs.85).aspx
321 class AcceleratorsResource
: public OptStatementsRCResource
{
330 // This is actually 0x0000 (accelerator is assumed to be ASCII if it's
331 // not VIRTKEY). However, rc.exe behavior is different in situations
332 // "only ASCII defined" and "neither ASCII nor VIRTKEY defined".
333 // Therefore, we include ASCII as another flag. This must be zeroed
343 static constexpr size_t NumFlags
= 6;
344 static StringRef OptionsStr
[NumFlags
];
345 static uint32_t OptionsFlags
[NumFlags
];
348 AcceleratorsResource(OptionalStmtList
&&List
, uint16_t Flags
)
349 : OptStatementsRCResource(std::move(List
), Flags
) {}
351 std::vector
<Accelerator
> Accelerators
;
353 void addAccelerator(IntOrString Event
, uint32_t Id
, uint16_t Flags
) {
354 Accelerators
.push_back(Accelerator
{Event
, Id
, Flags
});
356 raw_ostream
&log(raw_ostream
&) const override
;
358 IntOrString
getResourceType() const override
{ return RkAccelerators
; }
359 static uint16_t getDefaultMemoryFlags() { return MfPure
| MfMoveable
; }
360 Twine
getResourceTypeName() const override
{ return "ACCELERATORS"; }
362 Error
visit(Visitor
*V
) const override
{
363 return V
->visitAcceleratorsResource(this);
365 ResourceKind
getKind() const override
{ return RkAccelerators
; }
366 static bool classof(const RCResource
*Res
) {
367 return Res
->getKind() == RkAccelerators
;
371 // BITMAP resource. Represents a bitmap (".bmp") file.
373 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380680(v=vs.85).aspx
374 class BitmapResource
: public RCResource
{
378 BitmapResource(StringRef Location
, uint16_t Flags
)
379 : RCResource(Flags
), BitmapLoc(Location
) {}
380 raw_ostream
&log(raw_ostream
&) const override
;
382 IntOrString
getResourceType() const override
{ return RkBitmap
; }
383 static uint16_t getDefaultMemoryFlags() { return MfPure
| MfMoveable
; }
385 Twine
getResourceTypeName() const override
{ return "BITMAP"; }
386 Error
visit(Visitor
*V
) const override
{
387 return V
->visitBitmapResource(this);
389 ResourceKind
getKind() const override
{ return RkBitmap
; }
390 static bool classof(const RCResource
*Res
) {
391 return Res
->getKind() == RkBitmap
;
395 // CURSOR resource. Represents a single cursor (".cur") file.
397 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380920(v=vs.85).aspx
398 class CursorResource
: public RCResource
{
402 CursorResource(StringRef Location
, uint16_t Flags
)
403 : RCResource(Flags
), CursorLoc(Location
) {}
404 raw_ostream
&log(raw_ostream
&) const override
;
406 Twine
getResourceTypeName() const override
{ return "CURSOR"; }
407 static uint16_t getDefaultMemoryFlags() { return MfDiscardable
| MfMoveable
; }
408 Error
visit(Visitor
*V
) const override
{
409 return V
->visitCursorResource(this);
411 ResourceKind
getKind() const override
{ return RkCursor
; }
412 static bool classof(const RCResource
*Res
) {
413 return Res
->getKind() == RkCursor
;
417 // ICON resource. Represents a single ".ico" file containing a group of icons.
419 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381018(v=vs.85).aspx
420 class IconResource
: public RCResource
{
424 IconResource(StringRef Location
, uint16_t Flags
)
425 : RCResource(Flags
), IconLoc(Location
) {}
426 raw_ostream
&log(raw_ostream
&) const override
;
428 Twine
getResourceTypeName() const override
{ return "ICON"; }
429 static uint16_t getDefaultMemoryFlags() { return MfDiscardable
| MfMoveable
; }
430 Error
visit(Visitor
*V
) const override
{ return V
->visitIconResource(this); }
431 ResourceKind
getKind() const override
{ return RkIcon
; }
432 static bool classof(const RCResource
*Res
) {
433 return Res
->getKind() == RkIcon
;
437 // HTML resource. Represents a local webpage that is to be embedded into the
438 // resulting resource file. It embeds a file only - no additional resources
439 // (images etc.) are included with this resource.
441 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa966018(v=vs.85).aspx
442 class HTMLResource
: public RCResource
{
446 HTMLResource(StringRef Location
, uint16_t Flags
)
447 : RCResource(Flags
), HTMLLoc(Location
) {}
448 raw_ostream
&log(raw_ostream
&) const override
;
450 Error
visit(Visitor
*V
) const override
{ return V
->visitHTMLResource(this); }
452 // Curiously, file resources don't have DISCARDABLE flag set.
453 static uint16_t getDefaultMemoryFlags() { return MfPure
| MfMoveable
; }
454 IntOrString
getResourceType() const override
{ return RkHTML
; }
455 Twine
getResourceTypeName() const override
{ return "HTML"; }
456 ResourceKind
getKind() const override
{ return RkHTML
; }
457 static bool classof(const RCResource
*Res
) {
458 return Res
->getKind() == RkHTML
;
462 // -- MENU resource and its helper classes --
463 // This resource describes the contents of an application menu
464 // (usually located in the upper part of the dialog.)
466 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381025(v=vs.85).aspx
468 // Description of a single submenu item.
469 class MenuDefinition
{
476 MENUBARBREAK
= 0x0020,
480 enum MenuDefKind
{ MkBase
, MkSeparator
, MkMenuItem
, MkPopup
};
482 static constexpr size_t NumFlags
= 6;
483 static StringRef OptionsStr
[NumFlags
];
484 static uint32_t OptionsFlags
[NumFlags
];
485 static raw_ostream
&logFlags(raw_ostream
&, uint16_t Flags
);
486 virtual raw_ostream
&log(raw_ostream
&OS
) const {
487 return OS
<< "Base menu definition\n";
489 virtual ~MenuDefinition() {}
491 virtual uint16_t getResFlags() const { return 0; }
492 virtual MenuDefKind
getKind() const { return MkBase
; }
495 // Recursive description of a whole submenu.
496 class MenuDefinitionList
: public MenuDefinition
{
498 std::vector
<std::unique_ptr
<MenuDefinition
>> Definitions
;
500 void addDefinition(std::unique_ptr
<MenuDefinition
> Def
) {
501 Definitions
.push_back(std::move(Def
));
503 raw_ostream
&log(raw_ostream
&) const override
;
506 // Separator in MENU definition (MENUITEM SEPARATOR).
508 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
509 class MenuSeparator
: public MenuDefinition
{
511 raw_ostream
&log(raw_ostream
&) const override
;
513 MenuDefKind
getKind() const override
{ return MkSeparator
; }
514 static bool classof(const MenuDefinition
*D
) {
515 return D
->getKind() == MkSeparator
;
519 // MENUITEM statement definition.
521 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
522 class MenuItem
: public MenuDefinition
{
528 MenuItem(StringRef Caption
, uint32_t ItemId
, uint16_t ItemFlags
)
529 : Name(Caption
), Id(ItemId
), Flags(ItemFlags
) {}
530 raw_ostream
&log(raw_ostream
&) const override
;
532 uint16_t getResFlags() const override
{ return Flags
; }
533 MenuDefKind
getKind() const override
{ return MkMenuItem
; }
534 static bool classof(const MenuDefinition
*D
) {
535 return D
->getKind() == MkMenuItem
;
539 class MenuExItem
: public MenuDefinition
{
546 MenuExItem(StringRef Caption
, uint32_t ItemId
, uint32_t Type
, uint32_t State
)
547 : Name(Caption
), Id(ItemId
), Type(Type
), State(State
) {}
548 raw_ostream
&log(raw_ostream
&) const override
;
550 MenuDefKind
getKind() const override
{ return MkMenuItem
; }
551 static bool classof(const MenuDefinition
*D
) {
552 return D
->getKind() == MkMenuItem
;
556 // POPUP statement definition.
558 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx
559 class PopupItem
: public MenuDefinition
{
563 MenuDefinitionList SubItems
;
565 PopupItem(StringRef Caption
, uint16_t ItemFlags
,
566 MenuDefinitionList
&&SubItemsList
)
567 : Name(Caption
), Flags(ItemFlags
), SubItems(std::move(SubItemsList
)) {}
568 raw_ostream
&log(raw_ostream
&) const override
;
570 // This has an additional MF_POPUP (0x10) flag.
571 uint16_t getResFlags() const override
{ return Flags
| 0x10; }
572 MenuDefKind
getKind() const override
{ return MkPopup
; }
573 static bool classof(const MenuDefinition
*D
) {
574 return D
->getKind() == MkPopup
;
578 class PopupExItem
: public MenuDefinition
{
585 MenuDefinitionList SubItems
;
587 PopupExItem(StringRef Caption
, uint32_t Id
, uint32_t Type
, uint32_t State
,
588 uint32_t HelpId
, MenuDefinitionList
&&SubItemsList
)
589 : Name(Caption
), Id(Id
), Type(Type
), State(State
), HelpId(HelpId
),
590 SubItems(std::move(SubItemsList
)) {}
591 raw_ostream
&log(raw_ostream
&) const override
;
593 uint16_t getResFlags() const override
{ return 0x01; }
594 MenuDefKind
getKind() const override
{ return MkPopup
; }
595 static bool classof(const MenuDefinition
*D
) {
596 return D
->getKind() == MkPopup
;
600 // Menu resource definition.
601 class MenuResource
: public OptStatementsRCResource
{
603 MenuDefinitionList Elements
;
605 MenuResource(OptionalStmtList
&&OptStmts
, MenuDefinitionList
&&Items
,
607 : OptStatementsRCResource(std::move(OptStmts
), Flags
),
608 Elements(std::move(Items
)) {}
609 raw_ostream
&log(raw_ostream
&) const override
;
611 IntOrString
getResourceType() const override
{ return RkMenu
; }
612 Twine
getResourceTypeName() const override
{ return "MENU"; }
613 Error
visit(Visitor
*V
) const override
{ return V
->visitMenuResource(this); }
614 ResourceKind
getKind() const override
{ return RkMenu
; }
615 static bool classof(const RCResource
*Res
) {
616 return Res
->getKind() == RkMenu
;
620 class MenuExResource
: public OptStatementsRCResource
{
622 MenuDefinitionList Elements
;
624 MenuExResource(MenuDefinitionList
&&Items
, uint16_t Flags
)
625 : OptStatementsRCResource({}, Flags
), Elements(std::move(Items
)) {}
626 raw_ostream
&log(raw_ostream
&) const override
;
628 IntOrString
getResourceType() const override
{ return RkMenu
; }
629 Twine
getResourceTypeName() const override
{ return "MENUEX"; }
630 Error
visit(Visitor
*V
) const override
{
631 return V
->visitMenuExResource(this);
633 ResourceKind
getKind() const override
{ return RkMenu
; }
634 static bool classof(const RCResource
*Res
) {
635 return Res
->getKind() == RkMenu
;
639 // STRINGTABLE resource. Contains a list of strings, each having its unique ID.
641 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381050(v=vs.85).aspx
642 class StringTableResource
: public OptStatementsRCResource
{
644 std::vector
<std::pair
<uint32_t, std::vector
<StringRef
>>> Table
;
646 StringTableResource(OptionalStmtList
&&List
, uint16_t Flags
)
647 : OptStatementsRCResource(std::move(List
), Flags
) {}
648 void addStrings(uint32_t ID
, std::vector
<StringRef
> &&Strings
) {
649 Table
.emplace_back(ID
, Strings
);
651 raw_ostream
&log(raw_ostream
&) const override
;
652 Twine
getResourceTypeName() const override
{ return "STRINGTABLE"; }
653 Error
visit(Visitor
*V
) const override
{
654 return V
->visitStringTableResource(this);
658 // -- DIALOG(EX) resource and its helper classes --
660 // This resource describes dialog boxes and controls residing inside them.
662 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381003(v=vs.85).aspx
663 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx
665 // Single control definition.
670 uint32_t ID
, X
, Y
, Width
, Height
;
671 std::optional
<IntWithNotMask
> Style
;
672 std::optional
<uint32_t> ExtStyle
, HelpID
;
675 // Control classes as described in DLGITEMTEMPLATEEX documentation.
677 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms645389.aspx
687 // Simple information about a single control type.
694 Control(StringRef CtlType
, IntOrString CtlTitle
, uint32_t CtlID
,
695 uint32_t PosX
, uint32_t PosY
, uint32_t ItemWidth
, uint32_t ItemHeight
,
696 std::optional
<IntWithNotMask
> ItemStyle
,
697 std::optional
<uint32_t> ExtItemStyle
,
698 std::optional
<uint32_t> CtlHelpID
, IntOrString CtlClass
)
699 : Type(CtlType
), Title(CtlTitle
), ID(CtlID
), X(PosX
), Y(PosY
),
700 Width(ItemWidth
), Height(ItemHeight
), Style(ItemStyle
),
701 ExtStyle(ExtItemStyle
), HelpID(CtlHelpID
), Class(CtlClass
) {}
703 static const StringMap
<CtlInfo
> SupportedCtls
;
705 raw_ostream
&log(raw_ostream
&) const;
708 // Single dialog definition. We don't create distinct classes for DIALOG and
709 // DIALOGEX because of their being too similar to each other. We only have a
710 // flag determining the type of the dialog box.
711 class DialogResource
: public OptStatementsRCResource
{
713 uint32_t X
, Y
, Width
, Height
, HelpID
;
714 std::vector
<Control
> Controls
;
717 DialogResource(uint32_t PosX
, uint32_t PosY
, uint32_t DlgWidth
,
718 uint32_t DlgHeight
, uint32_t DlgHelpID
,
719 OptionalStmtList
&&OptStmts
, bool IsDialogEx
, uint16_t Flags
)
720 : OptStatementsRCResource(std::move(OptStmts
), Flags
), X(PosX
), Y(PosY
),
721 Width(DlgWidth
), Height(DlgHeight
), HelpID(DlgHelpID
),
722 IsExtended(IsDialogEx
) {}
724 void addControl(Control
&&Ctl
) { Controls
.push_back(std::move(Ctl
)); }
726 raw_ostream
&log(raw_ostream
&) const override
;
728 // It was a weird design decision to assign the same resource type number
729 // both for DIALOG and DIALOGEX (and the same structure version number).
730 // It makes it possible for DIALOG to be mistaken for DIALOGEX.
731 IntOrString
getResourceType() const override
{ return RkDialog
; }
732 Twine
getResourceTypeName() const override
{
733 return "DIALOG" + Twine(IsExtended
? "EX" : "");
735 Error
visit(Visitor
*V
) const override
{
736 return V
->visitDialogResource(this);
738 ResourceKind
getKind() const override
{ return RkDialog
; }
739 static bool classof(const RCResource
*Res
) {
740 return Res
->getKind() == RkDialog
;
744 // User-defined resource. It is either:
745 // * a link to the file, e.g. NAME TYPE "filename",
746 // * or contains a list of integers and strings, e.g. NAME TYPE {1, "a", 2}.
747 class UserDefinedResource
: public RCResource
{
751 std::vector
<IntOrString
> Contents
;
754 UserDefinedResource(IntOrString ResourceType
, StringRef FileLocation
,
756 : RCResource(Flags
), Type(ResourceType
), FileLoc(FileLocation
),
757 IsFileResource(true) {}
758 UserDefinedResource(IntOrString ResourceType
, std::vector
<IntOrString
> &&Data
,
760 : RCResource(Flags
), Type(ResourceType
), Contents(std::move(Data
)),
761 IsFileResource(false) {}
763 raw_ostream
&log(raw_ostream
&) const override
;
764 IntOrString
getResourceType() const override
{ return Type
; }
765 Twine
getResourceTypeName() const override
{ return Type
; }
766 static uint16_t getDefaultMemoryFlags() { return MfPure
| MfMoveable
; }
768 Error
visit(Visitor
*V
) const override
{
769 return V
->visitUserDefinedResource(this);
771 ResourceKind
getKind() const override
{ return RkUser
; }
772 static bool classof(const RCResource
*Res
) {
773 return Res
->getKind() == RkUser
;
777 // -- VERSIONINFO resource and its helper classes --
779 // This resource lists the version information on the executable/library.
780 // The declaration consists of the following items:
781 // * A number of fixed optional version statements (e.g. FILEVERSION, FILEOS)
783 // * A number of BLOCK and/or VALUE statements. BLOCK recursively defines
784 // another block of version information, whereas VALUE defines a
785 // key -> value correspondence. There might be more than one value
786 // corresponding to the single key.
789 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381058(v=vs.85).aspx
791 // A single VERSIONINFO statement;
792 class VersionInfoStmt
{
794 enum StmtKind
{ StBase
= 0, StBlock
= 1, StValue
= 2 };
796 virtual raw_ostream
&log(raw_ostream
&OS
) const { return OS
<< "VI stmt\n"; }
797 virtual ~VersionInfoStmt() {}
799 virtual StmtKind
getKind() const { return StBase
; }
800 static bool classof(const VersionInfoStmt
*S
) {
801 return S
->getKind() == StBase
;
805 // BLOCK definition; also the main VERSIONINFO declaration is considered a
806 // BLOCK, although it has no name.
807 // The correct top-level blocks are "VarFileInfo" and "StringFileInfo". We don't
808 // care about them at the parsing phase.
809 class VersionInfoBlock
: public VersionInfoStmt
{
811 std::vector
<std::unique_ptr
<VersionInfoStmt
>> Stmts
;
814 VersionInfoBlock(StringRef BlockName
) : Name(BlockName
) {}
815 void addStmt(std::unique_ptr
<VersionInfoStmt
> Stmt
) {
816 Stmts
.push_back(std::move(Stmt
));
818 raw_ostream
&log(raw_ostream
&) const override
;
820 StmtKind
getKind() const override
{ return StBlock
; }
821 static bool classof(const VersionInfoStmt
*S
) {
822 return S
->getKind() == StBlock
;
826 class VersionInfoValue
: public VersionInfoStmt
{
829 std::vector
<IntOrString
> Values
;
830 BitVector HasPrecedingComma
;
832 VersionInfoValue(StringRef InfoKey
, std::vector
<IntOrString
> &&Vals
,
833 BitVector
&&CommasBeforeVals
)
834 : Key(InfoKey
), Values(std::move(Vals
)),
835 HasPrecedingComma(std::move(CommasBeforeVals
)) {}
836 raw_ostream
&log(raw_ostream
&) const override
;
838 StmtKind
getKind() const override
{ return StValue
; }
839 static bool classof(const VersionInfoStmt
*S
) {
840 return S
->getKind() == StValue
;
844 class VersionInfoResource
: public RCResource
{
846 // A class listing fixed VERSIONINFO statements (occuring before main BEGIN).
847 // If any of these is not specified, it is assumed by the original tool to
849 class VersionInfoFixed
{
851 enum VersionInfoFixedType
{
864 static const StringMap
<VersionInfoFixedType
> FixedFieldsInfoMap
;
865 static const StringRef FixedFieldsNames
[FtNumTypes
];
868 SmallVector
<uint32_t, 4> FixedInfo
[FtNumTypes
];
869 SmallVector
<bool, FtNumTypes
> IsTypePresent
;
871 static VersionInfoFixedType
getFixedType(StringRef Type
);
872 static bool isTypeSupported(VersionInfoFixedType Type
);
873 static bool isVersionType(VersionInfoFixedType Type
);
875 VersionInfoFixed() : IsTypePresent(FtNumTypes
, false) {}
877 void setValue(VersionInfoFixedType Type
, ArrayRef
<uint32_t> Value
) {
878 FixedInfo
[Type
] = SmallVector
<uint32_t, 4>(Value
.begin(), Value
.end());
879 IsTypePresent
[Type
] = true;
882 raw_ostream
&log(raw_ostream
&) const;
885 VersionInfoBlock MainBlock
;
886 VersionInfoFixed FixedData
;
888 VersionInfoResource(VersionInfoBlock
&&TopLevelBlock
,
889 VersionInfoFixed
&&FixedInfo
, uint16_t Flags
)
890 : RCResource(Flags
), MainBlock(std::move(TopLevelBlock
)),
891 FixedData(std::move(FixedInfo
)) {}
893 raw_ostream
&log(raw_ostream
&) const override
;
894 IntOrString
getResourceType() const override
{ return RkVersionInfo
; }
895 static uint16_t getDefaultMemoryFlags() { return MfMoveable
| MfPure
; }
896 Twine
getResourceTypeName() const override
{ return "VERSIONINFO"; }
897 Error
visit(Visitor
*V
) const override
{
898 return V
->visitVersionInfoResource(this);
900 ResourceKind
getKind() const override
{ return RkVersionInfo
; }
901 static bool classof(const RCResource
*Res
) {
902 return Res
->getKind() == RkVersionInfo
;
906 // CHARACTERISTICS optional statement.
908 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380872(v=vs.85).aspx
909 class CharacteristicsStmt
: public OptionalStmt
{
913 CharacteristicsStmt(uint32_t Characteristic
) : Value(Characteristic
) {}
914 raw_ostream
&log(raw_ostream
&) const override
;
916 Twine
getResourceTypeName() const override
{ return "CHARACTERISTICS"; }
917 Error
visit(Visitor
*V
) const override
{
918 return V
->visitCharacteristicsStmt(this);
922 // VERSION optional statement.
924 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381059(v=vs.85).aspx
925 class VersionStmt
: public OptionalStmt
{
929 VersionStmt(uint32_t Version
) : Value(Version
) {}
930 raw_ostream
&log(raw_ostream
&) const override
;
932 Twine
getResourceTypeName() const override
{ return "VERSION"; }
933 Error
visit(Visitor
*V
) const override
{ return V
->visitVersionStmt(this); }
936 // CAPTION optional statement.
938 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx
939 class CaptionStmt
: public OptionalStmt
{
943 CaptionStmt(StringRef Caption
) : Value(Caption
) {}
944 raw_ostream
&log(raw_ostream
&) const override
;
945 Twine
getResourceTypeName() const override
{ return "CAPTION"; }
946 Error
visit(Visitor
*V
) const override
{ return V
->visitCaptionStmt(this); }
949 // FONT optional statement.
950 // Note that the documentation is inaccurate: it expects five arguments to be
951 // given, however the example provides only two. In fact, the original tool
952 // expects two arguments - point size and name of the typeface.
954 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381013(v=vs.85).aspx
955 class FontStmt
: public OptionalStmt
{
957 uint32_t Size
, Weight
, Charset
;
961 FontStmt(uint32_t FontSize
, StringRef FontName
, uint32_t FontWeight
,
962 bool FontItalic
, uint32_t FontCharset
)
963 : Size(FontSize
), Weight(FontWeight
), Charset(FontCharset
),
964 Name(FontName
), Italic(FontItalic
) {}
965 raw_ostream
&log(raw_ostream
&) const override
;
966 Twine
getResourceTypeName() const override
{ return "FONT"; }
967 Error
visit(Visitor
*V
) const override
{ return V
->visitFontStmt(this); }
970 // STYLE optional statement.
972 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx
973 class StyleStmt
: public OptionalStmt
{
977 StyleStmt(uint32_t Style
) : Value(Style
) {}
978 raw_ostream
&log(raw_ostream
&) const override
;
979 Twine
getResourceTypeName() const override
{ return "STYLE"; }
980 Error
visit(Visitor
*V
) const override
{ return V
->visitStyleStmt(this); }
983 // EXSTYLE optional statement.
985 // Ref: docs.microsoft.com/en-us/windows/desktop/menurc/exstyle-statement
986 class ExStyleStmt
: public OptionalStmt
{
990 ExStyleStmt(uint32_t ExStyle
) : Value(ExStyle
) {}
991 raw_ostream
&log(raw_ostream
&) const override
;
992 Twine
getResourceTypeName() const override
{ return "EXSTYLE"; }
993 Error
visit(Visitor
*V
) const override
{ return V
->visitExStyleStmt(this); }
996 // CLASS optional statement.
998 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380883(v=vs.85).aspx
999 class ClassStmt
: public OptionalStmt
{
1003 ClassStmt(IntOrString Class
) : Value(Class
) {}
1004 raw_ostream
&log(raw_ostream
&) const override
;
1005 Twine
getResourceTypeName() const override
{ return "CLASS"; }
1006 Error
visit(Visitor
*V
) const override
{ return V
->visitClassStmt(this); }