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/StringSet.h"
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
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
);
46 RCInt
&operator-=(const RCInt
&Rhs
) {
47 std::tie(Val
, Long
) = std::make_pair(Val
- Rhs
.Val
, Long
| Rhs
.Long
);
51 RCInt
&operator|=(const RCInt
&Rhs
) {
52 std::tie(Val
, Long
) = std::make_pair(Val
| Rhs
.Val
, Long
| Rhs
.Long
);
56 RCInt
&operator&=(const RCInt
&Rhs
) {
57 std::tie(Val
, Long
) = std::make_pair(Val
& Rhs
.Val
, Long
| Rhs
.Long
);
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
{
75 IntWithNotMask() : IntWithNotMask(RCInt(0)) {}
76 IntWithNotMask(RCInt Value
, int32_t NotMask
= 0) : Value(Value
), NotMask(NotMask
) {}
78 RCInt
getValue() const {
82 uint32_t getNotMask() const {
86 IntWithNotMask
&operator+=(const IntWithNotMask
&Rhs
) {
87 Value
&= ~Rhs
.NotMask
;
89 NotMask
|= Rhs
.NotMask
;
93 IntWithNotMask
&operator-=(const IntWithNotMask
&Rhs
) {
94 Value
&= ~Rhs
.NotMask
;
96 NotMask
|= Rhs
.NotMask
;
100 IntWithNotMask
&operator|=(const IntWithNotMask
&Rhs
) {
101 Value
&= ~Rhs
.NotMask
;
103 NotMask
|= Rhs
.NotMask
;
107 IntWithNotMask
&operator&=(const IntWithNotMask
&Rhs
) {
108 Value
&= ~Rhs
.NotMask
;
110 NotMask
|= Rhs
.NotMask
;
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.
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
)
134 String
= Token
.value();
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 {
158 const StringRef
&getString() const {
163 operator Twine() const {
164 return isInt() ? Twine(getInt()) : Twine(getString());
167 friend raw_ostream
&operator<<(raw_ostream
&, const IntOrString
&);
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.
180 RkStringTableBundle
= 6,
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.
198 RkSingleCursorOrIconRes
,
199 RkCursorOrIconGroupRes
,
202 // Non-zero memory flags.
203 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648027(v=vs.85).aspx
208 MfDiscardable
= 0x1000
211 // Base resource. All the resources should derive from this base.
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";
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
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
{
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
;
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
))
279 return Error::success();
283 class OptStatementsRCResource
: public RCResource
{
285 std::unique_ptr
<OptionalStmtList
> OptStatements
;
287 OptStatementsRCResource(OptionalStmtList
&&Stmts
,
288 uint16_t Flags
= RCResource::getDefaultMemoryFlags())
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
{
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
{
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
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
{
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
{
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
{
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
{
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
{
475 MENUBARBREAK
= 0x0020,
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
{
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
{
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
{
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
{
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
{
564 MenuDefinitionList Elements
;
566 MenuResource(OptionalStmtList
&&OptStmts
, MenuDefinitionList
&&Items
,
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
{
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.
612 uint32_t ID
, X
, Y
, Width
, Height
;
613 Optional
<IntWithNotMask
> Style
;
614 Optional
<uint32_t> ExtStyle
, HelpID
;
617 // Control classes as described in DLGITEMTEMPLATEEX documentation.
619 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms645389.aspx
629 // Simple information about a single control type.
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
{
654 uint32_t X
, Y
, Width
, Height
, HelpID
;
655 std::vector
<Control
> Controls
;
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
{
692 std::vector
<IntOrString
> Contents
;
695 UserDefinedResource(IntOrString ResourceType
, StringRef FileLocation
,
697 : RCResource(Flags
), Type(ResourceType
), FileLoc(FileLocation
),
698 IsFileResource(true) {}
699 UserDefinedResource(IntOrString ResourceType
, std::vector
<IntOrString
> &&Data
,
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)
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.
730 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381058(v=vs.85).aspx
732 // A single VERSIONINFO statement;
733 class VersionInfoStmt
{
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
{
752 std::vector
<std::unique_ptr
<VersionInfoStmt
>> Stmts
;
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
{
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
{
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
790 class VersionInfoFixed
{
792 enum VersionInfoFixedType
{
805 static const StringMap
<VersionInfoFixedType
> FixedFieldsInfoMap
;
806 static const StringRef FixedFieldsNames
[FtNumTypes
];
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
{
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
{
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
{
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
{
898 uint32_t Size
, Weight
, Charset
;
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
{
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
{
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
{
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); }