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 // POPUP statement definition.
541 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx
542 class PopupItem
: public MenuDefinition
{
546 MenuDefinitionList SubItems
;
548 PopupItem(StringRef Caption
, uint16_t ItemFlags
,
549 MenuDefinitionList
&&SubItemsList
)
550 : Name(Caption
), Flags(ItemFlags
), SubItems(std::move(SubItemsList
)) {}
551 raw_ostream
&log(raw_ostream
&) const override
;
553 // This has an additional (0x10) flag. It doesn't match with documented
554 // 0x01 flag, though.
555 uint16_t getResFlags() const override
{ return Flags
| 0x10; }
556 MenuDefKind
getKind() const override
{ return MkPopup
; }
557 static bool classof(const MenuDefinition
*D
) {
558 return D
->getKind() == MkPopup
;
562 // Menu resource definition.
563 class MenuResource
: public OptStatementsRCResource
{
565 MenuDefinitionList Elements
;
567 MenuResource(OptionalStmtList
&&OptStmts
, MenuDefinitionList
&&Items
,
569 : OptStatementsRCResource(std::move(OptStmts
), Flags
),
570 Elements(std::move(Items
)) {}
571 raw_ostream
&log(raw_ostream
&) const override
;
573 IntOrString
getResourceType() const override
{ return RkMenu
; }
574 Twine
getResourceTypeName() const override
{ return "MENU"; }
575 Error
visit(Visitor
*V
) const override
{ return V
->visitMenuResource(this); }
576 ResourceKind
getKind() const override
{ return RkMenu
; }
577 static bool classof(const RCResource
*Res
) {
578 return Res
->getKind() == RkMenu
;
582 // STRINGTABLE resource. Contains a list of strings, each having its unique ID.
584 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381050(v=vs.85).aspx
585 class StringTableResource
: public OptStatementsRCResource
{
587 std::vector
<std::pair
<uint32_t, std::vector
<StringRef
>>> Table
;
589 StringTableResource(OptionalStmtList
&&List
, uint16_t Flags
)
590 : OptStatementsRCResource(std::move(List
), Flags
) {}
591 void addStrings(uint32_t ID
, std::vector
<StringRef
> &&Strings
) {
592 Table
.emplace_back(ID
, Strings
);
594 raw_ostream
&log(raw_ostream
&) const override
;
595 Twine
getResourceTypeName() const override
{ return "STRINGTABLE"; }
596 Error
visit(Visitor
*V
) const override
{
597 return V
->visitStringTableResource(this);
601 // -- DIALOG(EX) resource and its helper classes --
603 // This resource describes dialog boxes and controls residing inside them.
605 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381003(v=vs.85).aspx
606 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx
608 // Single control definition.
613 uint32_t ID
, X
, Y
, Width
, Height
;
614 Optional
<IntWithNotMask
> Style
;
615 Optional
<uint32_t> ExtStyle
, HelpID
;
618 // Control classes as described in DLGITEMTEMPLATEEX documentation.
620 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms645389.aspx
630 // Simple information about a single control type.
637 Control(StringRef CtlType
, IntOrString CtlTitle
, uint32_t CtlID
,
638 uint32_t PosX
, uint32_t PosY
, uint32_t ItemWidth
, uint32_t ItemHeight
,
639 Optional
<IntWithNotMask
> ItemStyle
, Optional
<uint32_t> ExtItemStyle
,
640 Optional
<uint32_t> CtlHelpID
, IntOrString CtlClass
)
641 : Type(CtlType
), Title(CtlTitle
), ID(CtlID
), X(PosX
), Y(PosY
),
642 Width(ItemWidth
), Height(ItemHeight
), Style(ItemStyle
),
643 ExtStyle(ExtItemStyle
), HelpID(CtlHelpID
), Class(CtlClass
) {}
645 static const StringMap
<CtlInfo
> SupportedCtls
;
647 raw_ostream
&log(raw_ostream
&) const;
650 // Single dialog definition. We don't create distinct classes for DIALOG and
651 // DIALOGEX because of their being too similar to each other. We only have a
652 // flag determining the type of the dialog box.
653 class DialogResource
: public OptStatementsRCResource
{
655 uint32_t X
, Y
, Width
, Height
, HelpID
;
656 std::vector
<Control
> Controls
;
659 DialogResource(uint32_t PosX
, uint32_t PosY
, uint32_t DlgWidth
,
660 uint32_t DlgHeight
, uint32_t DlgHelpID
,
661 OptionalStmtList
&&OptStmts
, bool IsDialogEx
, uint16_t Flags
)
662 : OptStatementsRCResource(std::move(OptStmts
), Flags
), X(PosX
), Y(PosY
),
663 Width(DlgWidth
), Height(DlgHeight
), HelpID(DlgHelpID
),
664 IsExtended(IsDialogEx
) {}
666 void addControl(Control
&&Ctl
) { Controls
.push_back(std::move(Ctl
)); }
668 raw_ostream
&log(raw_ostream
&) const override
;
670 // It was a weird design decision to assign the same resource type number
671 // both for DIALOG and DIALOGEX (and the same structure version number).
672 // It makes it possible for DIALOG to be mistaken for DIALOGEX.
673 IntOrString
getResourceType() const override
{ return RkDialog
; }
674 Twine
getResourceTypeName() const override
{
675 return "DIALOG" + Twine(IsExtended
? "EX" : "");
677 Error
visit(Visitor
*V
) const override
{
678 return V
->visitDialogResource(this);
680 ResourceKind
getKind() const override
{ return RkDialog
; }
681 static bool classof(const RCResource
*Res
) {
682 return Res
->getKind() == RkDialog
;
686 // User-defined resource. It is either:
687 // * a link to the file, e.g. NAME TYPE "filename",
688 // * or contains a list of integers and strings, e.g. NAME TYPE {1, "a", 2}.
689 class UserDefinedResource
: public RCResource
{
693 std::vector
<IntOrString
> Contents
;
696 UserDefinedResource(IntOrString ResourceType
, StringRef FileLocation
,
698 : RCResource(Flags
), Type(ResourceType
), FileLoc(FileLocation
),
699 IsFileResource(true) {}
700 UserDefinedResource(IntOrString ResourceType
, std::vector
<IntOrString
> &&Data
,
702 : RCResource(Flags
), Type(ResourceType
), Contents(std::move(Data
)),
703 IsFileResource(false) {}
705 raw_ostream
&log(raw_ostream
&) const override
;
706 IntOrString
getResourceType() const override
{ return Type
; }
707 Twine
getResourceTypeName() const override
{ return Type
; }
708 static uint16_t getDefaultMemoryFlags() { return MfPure
| MfMoveable
; }
710 Error
visit(Visitor
*V
) const override
{
711 return V
->visitUserDefinedResource(this);
713 ResourceKind
getKind() const override
{ return RkUser
; }
714 static bool classof(const RCResource
*Res
) {
715 return Res
->getKind() == RkUser
;
719 // -- VERSIONINFO resource and its helper classes --
721 // This resource lists the version information on the executable/library.
722 // The declaration consists of the following items:
723 // * A number of fixed optional version statements (e.g. FILEVERSION, FILEOS)
725 // * A number of BLOCK and/or VALUE statements. BLOCK recursively defines
726 // another block of version information, whereas VALUE defines a
727 // key -> value correspondence. There might be more than one value
728 // corresponding to the single key.
731 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381058(v=vs.85).aspx
733 // A single VERSIONINFO statement;
734 class VersionInfoStmt
{
736 enum StmtKind
{ StBase
= 0, StBlock
= 1, StValue
= 2 };
738 virtual raw_ostream
&log(raw_ostream
&OS
) const { return OS
<< "VI stmt\n"; }
739 virtual ~VersionInfoStmt() {}
741 virtual StmtKind
getKind() const { return StBase
; }
742 static bool classof(const VersionInfoStmt
*S
) {
743 return S
->getKind() == StBase
;
747 // BLOCK definition; also the main VERSIONINFO declaration is considered a
748 // BLOCK, although it has no name.
749 // The correct top-level blocks are "VarFileInfo" and "StringFileInfo". We don't
750 // care about them at the parsing phase.
751 class VersionInfoBlock
: public VersionInfoStmt
{
753 std::vector
<std::unique_ptr
<VersionInfoStmt
>> Stmts
;
756 VersionInfoBlock(StringRef BlockName
) : Name(BlockName
) {}
757 void addStmt(std::unique_ptr
<VersionInfoStmt
> Stmt
) {
758 Stmts
.push_back(std::move(Stmt
));
760 raw_ostream
&log(raw_ostream
&) const override
;
762 StmtKind
getKind() const override
{ return StBlock
; }
763 static bool classof(const VersionInfoStmt
*S
) {
764 return S
->getKind() == StBlock
;
768 class VersionInfoValue
: public VersionInfoStmt
{
771 std::vector
<IntOrString
> Values
;
772 BitVector HasPrecedingComma
;
774 VersionInfoValue(StringRef InfoKey
, std::vector
<IntOrString
> &&Vals
,
775 BitVector
&&CommasBeforeVals
)
776 : Key(InfoKey
), Values(std::move(Vals
)),
777 HasPrecedingComma(std::move(CommasBeforeVals
)) {}
778 raw_ostream
&log(raw_ostream
&) const override
;
780 StmtKind
getKind() const override
{ return StValue
; }
781 static bool classof(const VersionInfoStmt
*S
) {
782 return S
->getKind() == StValue
;
786 class VersionInfoResource
: public RCResource
{
788 // A class listing fixed VERSIONINFO statements (occuring before main BEGIN).
789 // If any of these is not specified, it is assumed by the original tool to
791 class VersionInfoFixed
{
793 enum VersionInfoFixedType
{
806 static const StringMap
<VersionInfoFixedType
> FixedFieldsInfoMap
;
807 static const StringRef FixedFieldsNames
[FtNumTypes
];
810 SmallVector
<uint32_t, 4> FixedInfo
[FtNumTypes
];
811 SmallVector
<bool, FtNumTypes
> IsTypePresent
;
813 static VersionInfoFixedType
getFixedType(StringRef Type
);
814 static bool isTypeSupported(VersionInfoFixedType Type
);
815 static bool isVersionType(VersionInfoFixedType Type
);
817 VersionInfoFixed() : IsTypePresent(FtNumTypes
, false) {}
819 void setValue(VersionInfoFixedType Type
, ArrayRef
<uint32_t> Value
) {
820 FixedInfo
[Type
] = SmallVector
<uint32_t, 4>(Value
.begin(), Value
.end());
821 IsTypePresent
[Type
] = true;
824 raw_ostream
&log(raw_ostream
&) const;
827 VersionInfoBlock MainBlock
;
828 VersionInfoFixed FixedData
;
830 VersionInfoResource(VersionInfoBlock
&&TopLevelBlock
,
831 VersionInfoFixed
&&FixedInfo
, uint16_t Flags
)
832 : RCResource(Flags
), MainBlock(std::move(TopLevelBlock
)),
833 FixedData(std::move(FixedInfo
)) {}
835 raw_ostream
&log(raw_ostream
&) const override
;
836 IntOrString
getResourceType() const override
{ return RkVersionInfo
; }
837 static uint16_t getDefaultMemoryFlags() { return MfMoveable
| MfPure
; }
838 Twine
getResourceTypeName() const override
{ return "VERSIONINFO"; }
839 Error
visit(Visitor
*V
) const override
{
840 return V
->visitVersionInfoResource(this);
842 ResourceKind
getKind() const override
{ return RkVersionInfo
; }
843 static bool classof(const RCResource
*Res
) {
844 return Res
->getKind() == RkVersionInfo
;
848 // CHARACTERISTICS optional statement.
850 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380872(v=vs.85).aspx
851 class CharacteristicsStmt
: public OptionalStmt
{
855 CharacteristicsStmt(uint32_t Characteristic
) : Value(Characteristic
) {}
856 raw_ostream
&log(raw_ostream
&) const override
;
858 Twine
getResourceTypeName() const override
{ return "CHARACTERISTICS"; }
859 Error
visit(Visitor
*V
) const override
{
860 return V
->visitCharacteristicsStmt(this);
864 // VERSION optional statement.
866 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381059(v=vs.85).aspx
867 class VersionStmt
: public OptionalStmt
{
871 VersionStmt(uint32_t Version
) : Value(Version
) {}
872 raw_ostream
&log(raw_ostream
&) const override
;
874 Twine
getResourceTypeName() const override
{ return "VERSION"; }
875 Error
visit(Visitor
*V
) const override
{ return V
->visitVersionStmt(this); }
878 // CAPTION optional statement.
880 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx
881 class CaptionStmt
: public OptionalStmt
{
885 CaptionStmt(StringRef Caption
) : Value(Caption
) {}
886 raw_ostream
&log(raw_ostream
&) const override
;
887 Twine
getResourceTypeName() const override
{ return "CAPTION"; }
888 Error
visit(Visitor
*V
) const override
{ return V
->visitCaptionStmt(this); }
891 // FONT optional statement.
892 // Note that the documentation is inaccurate: it expects five arguments to be
893 // given, however the example provides only two. In fact, the original tool
894 // expects two arguments - point size and name of the typeface.
896 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381013(v=vs.85).aspx
897 class FontStmt
: public OptionalStmt
{
899 uint32_t Size
, Weight
, Charset
;
903 FontStmt(uint32_t FontSize
, StringRef FontName
, uint32_t FontWeight
,
904 bool FontItalic
, uint32_t FontCharset
)
905 : Size(FontSize
), Weight(FontWeight
), Charset(FontCharset
),
906 Name(FontName
), Italic(FontItalic
) {}
907 raw_ostream
&log(raw_ostream
&) const override
;
908 Twine
getResourceTypeName() const override
{ return "FONT"; }
909 Error
visit(Visitor
*V
) const override
{ return V
->visitFontStmt(this); }
912 // STYLE optional statement.
914 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx
915 class StyleStmt
: public OptionalStmt
{
919 StyleStmt(uint32_t Style
) : Value(Style
) {}
920 raw_ostream
&log(raw_ostream
&) const override
;
921 Twine
getResourceTypeName() const override
{ return "STYLE"; }
922 Error
visit(Visitor
*V
) const override
{ return V
->visitStyleStmt(this); }
925 // EXSTYLE optional statement.
927 // Ref: docs.microsoft.com/en-us/windows/desktop/menurc/exstyle-statement
928 class ExStyleStmt
: public OptionalStmt
{
932 ExStyleStmt(uint32_t ExStyle
) : Value(ExStyle
) {}
933 raw_ostream
&log(raw_ostream
&) const override
;
934 Twine
getResourceTypeName() const override
{ return "EXSTYLE"; }
935 Error
visit(Visitor
*V
) const override
{ return V
->visitExStyleStmt(this); }
938 // CLASS optional statement.
940 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380883(v=vs.85).aspx
941 class ClassStmt
: public OptionalStmt
{
945 ClassStmt(IntOrString Class
) : Value(Class
) {}
946 raw_ostream
&log(raw_ostream
&) const override
;
947 Twine
getResourceTypeName() const override
{ return "CLASS"; }
948 Error
visit(Visitor
*V
) const override
{ return V
->visitClassStmt(this); }