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_lower(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(llvm::make_unique
<OptionalStmtList
>(std::move(Stmts
))) {}
292 virtual Error
applyStmts(Visitor
*V
) const { return OptStatements
->visit(V
); }
295 // LANGUAGE statement. It can occur both as a top-level statement (in such
296 // a situation, it changes the default language until the end of the file)
297 // and as an optional resource statement (then it changes the language
298 // of a single resource).
300 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381019(v=vs.85).aspx
301 class LanguageResource
: public OptionalStmt
{
303 uint32_t Lang
, SubLang
;
305 LanguageResource(uint32_t LangId
, uint32_t SubLangId
)
306 : Lang(LangId
), SubLang(SubLangId
) {}
307 raw_ostream
&log(raw_ostream
&) const override
;
309 // This is not a regular top-level statement; when it occurs, it just
310 // modifies the language context.
311 Error
visit(Visitor
*V
) const override
{ return V
->visitLanguageStmt(this); }
312 Twine
getResourceTypeName() const override
{ return "LANGUAGE"; }
315 // ACCELERATORS resource. Defines a named table of accelerators for the app.
317 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380610(v=vs.85).aspx
318 class AcceleratorsResource
: public OptStatementsRCResource
{
327 // This is actually 0x0000 (accelerator is assumed to be ASCII if it's
328 // not VIRTKEY). However, rc.exe behavior is different in situations
329 // "only ASCII defined" and "neither ASCII nor VIRTKEY defined".
330 // Therefore, we include ASCII as another flag. This must be zeroed
340 static constexpr size_t NumFlags
= 6;
341 static StringRef OptionsStr
[NumFlags
];
342 static uint32_t OptionsFlags
[NumFlags
];
345 AcceleratorsResource(OptionalStmtList
&&List
, uint16_t Flags
)
346 : OptStatementsRCResource(std::move(List
), Flags
) {}
348 std::vector
<Accelerator
> Accelerators
;
350 void addAccelerator(IntOrString Event
, uint32_t Id
, uint16_t Flags
) {
351 Accelerators
.push_back(Accelerator
{Event
, Id
, Flags
});
353 raw_ostream
&log(raw_ostream
&) const override
;
355 IntOrString
getResourceType() const override
{ return RkAccelerators
; }
356 static uint16_t getDefaultMemoryFlags() { return MfPure
| MfMoveable
; }
357 Twine
getResourceTypeName() const override
{ return "ACCELERATORS"; }
359 Error
visit(Visitor
*V
) const override
{
360 return V
->visitAcceleratorsResource(this);
362 ResourceKind
getKind() const override
{ return RkAccelerators
; }
363 static bool classof(const RCResource
*Res
) {
364 return Res
->getKind() == RkAccelerators
;
368 // BITMAP resource. Represents a bitmap (".bmp") file.
370 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380680(v=vs.85).aspx
371 class BitmapResource
: public RCResource
{
375 BitmapResource(StringRef Location
, uint16_t Flags
)
376 : RCResource(Flags
), BitmapLoc(Location
) {}
377 raw_ostream
&log(raw_ostream
&) const override
;
379 IntOrString
getResourceType() const override
{ return RkBitmap
; }
380 static uint16_t getDefaultMemoryFlags() { return MfPure
| MfMoveable
; }
382 Twine
getResourceTypeName() const override
{ return "BITMAP"; }
383 Error
visit(Visitor
*V
) const override
{
384 return V
->visitBitmapResource(this);
386 ResourceKind
getKind() const override
{ return RkBitmap
; }
387 static bool classof(const RCResource
*Res
) {
388 return Res
->getKind() == RkBitmap
;
392 // CURSOR resource. Represents a single cursor (".cur") file.
394 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380920(v=vs.85).aspx
395 class CursorResource
: public RCResource
{
399 CursorResource(StringRef Location
, uint16_t Flags
)
400 : RCResource(Flags
), CursorLoc(Location
) {}
401 raw_ostream
&log(raw_ostream
&) const override
;
403 Twine
getResourceTypeName() const override
{ return "CURSOR"; }
404 static uint16_t getDefaultMemoryFlags() { return MfDiscardable
| MfMoveable
; }
405 Error
visit(Visitor
*V
) const override
{
406 return V
->visitCursorResource(this);
408 ResourceKind
getKind() const override
{ return RkCursor
; }
409 static bool classof(const RCResource
*Res
) {
410 return Res
->getKind() == RkCursor
;
414 // ICON resource. Represents a single ".ico" file containing a group of icons.
416 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381018(v=vs.85).aspx
417 class IconResource
: public RCResource
{
421 IconResource(StringRef Location
, uint16_t Flags
)
422 : RCResource(Flags
), IconLoc(Location
) {}
423 raw_ostream
&log(raw_ostream
&) const override
;
425 Twine
getResourceTypeName() const override
{ return "ICON"; }
426 static uint16_t getDefaultMemoryFlags() { return MfDiscardable
| MfMoveable
; }
427 Error
visit(Visitor
*V
) const override
{ return V
->visitIconResource(this); }
428 ResourceKind
getKind() const override
{ return RkIcon
; }
429 static bool classof(const RCResource
*Res
) {
430 return Res
->getKind() == RkIcon
;
434 // HTML resource. Represents a local webpage that is to be embedded into the
435 // resulting resource file. It embeds a file only - no additional resources
436 // (images etc.) are included with this resource.
438 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa966018(v=vs.85).aspx
439 class HTMLResource
: public RCResource
{
443 HTMLResource(StringRef Location
, uint16_t Flags
)
444 : RCResource(Flags
), HTMLLoc(Location
) {}
445 raw_ostream
&log(raw_ostream
&) const override
;
447 Error
visit(Visitor
*V
) const override
{ return V
->visitHTMLResource(this); }
449 // Curiously, file resources don't have DISCARDABLE flag set.
450 static uint16_t getDefaultMemoryFlags() { return MfPure
| MfMoveable
; }
451 IntOrString
getResourceType() const override
{ return RkHTML
; }
452 Twine
getResourceTypeName() const override
{ return "HTML"; }
453 ResourceKind
getKind() const override
{ return RkHTML
; }
454 static bool classof(const RCResource
*Res
) {
455 return Res
->getKind() == RkHTML
;
459 // -- MENU resource and its helper classes --
460 // This resource describes the contents of an application menu
461 // (usually located in the upper part of the dialog.)
463 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381025(v=vs.85).aspx
465 // Description of a single submenu item.
466 class MenuDefinition
{
473 MENUBARBREAK
= 0x0020,
477 enum MenuDefKind
{ MkBase
, MkSeparator
, MkMenuItem
, MkPopup
};
479 static constexpr size_t NumFlags
= 6;
480 static StringRef OptionsStr
[NumFlags
];
481 static uint32_t OptionsFlags
[NumFlags
];
482 static raw_ostream
&logFlags(raw_ostream
&, uint16_t Flags
);
483 virtual raw_ostream
&log(raw_ostream
&OS
) const {
484 return OS
<< "Base menu definition\n";
486 virtual ~MenuDefinition() {}
488 virtual uint16_t getResFlags() const { return 0; }
489 virtual MenuDefKind
getKind() const { return MkBase
; }
492 // Recursive description of a whole submenu.
493 class MenuDefinitionList
: public MenuDefinition
{
495 std::vector
<std::unique_ptr
<MenuDefinition
>> Definitions
;
497 void addDefinition(std::unique_ptr
<MenuDefinition
> Def
) {
498 Definitions
.push_back(std::move(Def
));
500 raw_ostream
&log(raw_ostream
&) const override
;
503 // Separator in MENU definition (MENUITEM SEPARATOR).
505 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
506 class MenuSeparator
: public MenuDefinition
{
508 raw_ostream
&log(raw_ostream
&) const override
;
510 MenuDefKind
getKind() const override
{ return MkSeparator
; }
511 static bool classof(const MenuDefinition
*D
) {
512 return D
->getKind() == MkSeparator
;
516 // MENUITEM statement definition.
518 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
519 class MenuItem
: public MenuDefinition
{
525 MenuItem(StringRef Caption
, uint32_t ItemId
, uint16_t ItemFlags
)
526 : Name(Caption
), Id(ItemId
), Flags(ItemFlags
) {}
527 raw_ostream
&log(raw_ostream
&) const override
;
529 uint16_t getResFlags() const override
{ return Flags
; }
530 MenuDefKind
getKind() const override
{ return MkMenuItem
; }
531 static bool classof(const MenuDefinition
*D
) {
532 return D
->getKind() == MkMenuItem
;
536 // POPUP statement definition.
538 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx
539 class PopupItem
: public MenuDefinition
{
543 MenuDefinitionList SubItems
;
545 PopupItem(StringRef Caption
, uint16_t ItemFlags
,
546 MenuDefinitionList
&&SubItemsList
)
547 : Name(Caption
), Flags(ItemFlags
), SubItems(std::move(SubItemsList
)) {}
548 raw_ostream
&log(raw_ostream
&) const override
;
550 // This has an additional (0x10) flag. It doesn't match with documented
551 // 0x01 flag, though.
552 uint16_t getResFlags() const override
{ return Flags
| 0x10; }
553 MenuDefKind
getKind() const override
{ return MkPopup
; }
554 static bool classof(const MenuDefinition
*D
) {
555 return D
->getKind() == MkPopup
;
559 // Menu resource definition.
560 class MenuResource
: public OptStatementsRCResource
{
562 MenuDefinitionList Elements
;
564 MenuResource(OptionalStmtList
&&OptStmts
, MenuDefinitionList
&&Items
,
566 : OptStatementsRCResource(std::move(OptStmts
), Flags
),
567 Elements(std::move(Items
)) {}
568 raw_ostream
&log(raw_ostream
&) const override
;
570 IntOrString
getResourceType() const override
{ return RkMenu
; }
571 Twine
getResourceTypeName() const override
{ return "MENU"; }
572 Error
visit(Visitor
*V
) const override
{ return V
->visitMenuResource(this); }
573 ResourceKind
getKind() const override
{ return RkMenu
; }
574 static bool classof(const RCResource
*Res
) {
575 return Res
->getKind() == RkMenu
;
579 // STRINGTABLE resource. Contains a list of strings, each having its unique ID.
581 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381050(v=vs.85).aspx
582 class StringTableResource
: public OptStatementsRCResource
{
584 std::vector
<std::pair
<uint32_t, StringRef
>> Table
;
586 StringTableResource(OptionalStmtList
&&List
, uint16_t Flags
)
587 : OptStatementsRCResource(std::move(List
), Flags
) {}
588 void addString(uint32_t ID
, StringRef String
) {
589 Table
.emplace_back(ID
, String
);
591 raw_ostream
&log(raw_ostream
&) const override
;
592 Twine
getResourceTypeName() const override
{ return "STRINGTABLE"; }
593 Error
visit(Visitor
*V
) const override
{
594 return V
->visitStringTableResource(this);
598 // -- DIALOG(EX) resource and its helper classes --
600 // This resource describes dialog boxes and controls residing inside them.
602 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381003(v=vs.85).aspx
603 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx
605 // Single control definition.
610 uint32_t ID
, X
, Y
, Width
, Height
;
611 Optional
<IntWithNotMask
> Style
;
612 Optional
<uint32_t> ExtStyle
, HelpID
;
615 // Control classes as described in DLGITEMTEMPLATEEX documentation.
617 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms645389.aspx
627 // Simple information about a single control type.
634 Control(StringRef CtlType
, IntOrString CtlTitle
, uint32_t CtlID
,
635 uint32_t PosX
, uint32_t PosY
, uint32_t ItemWidth
, uint32_t ItemHeight
,
636 Optional
<IntWithNotMask
> ItemStyle
, Optional
<uint32_t> ExtItemStyle
,
637 Optional
<uint32_t> CtlHelpID
, IntOrString CtlClass
)
638 : Type(CtlType
), Title(CtlTitle
), ID(CtlID
), X(PosX
), Y(PosY
),
639 Width(ItemWidth
), Height(ItemHeight
), Style(ItemStyle
),
640 ExtStyle(ExtItemStyle
), HelpID(CtlHelpID
), Class(CtlClass
) {}
642 static const StringMap
<CtlInfo
> SupportedCtls
;
644 raw_ostream
&log(raw_ostream
&) const;
647 // Single dialog definition. We don't create distinct classes for DIALOG and
648 // DIALOGEX because of their being too similar to each other. We only have a
649 // flag determining the type of the dialog box.
650 class DialogResource
: public OptStatementsRCResource
{
652 uint32_t X
, Y
, Width
, Height
, HelpID
;
653 std::vector
<Control
> Controls
;
656 DialogResource(uint32_t PosX
, uint32_t PosY
, uint32_t DlgWidth
,
657 uint32_t DlgHeight
, uint32_t DlgHelpID
,
658 OptionalStmtList
&&OptStmts
, bool IsDialogEx
, uint16_t Flags
)
659 : OptStatementsRCResource(std::move(OptStmts
), Flags
), X(PosX
), Y(PosY
),
660 Width(DlgWidth
), Height(DlgHeight
), HelpID(DlgHelpID
),
661 IsExtended(IsDialogEx
) {}
663 void addControl(Control
&&Ctl
) { Controls
.push_back(std::move(Ctl
)); }
665 raw_ostream
&log(raw_ostream
&) const override
;
667 // It was a weird design decision to assign the same resource type number
668 // both for DIALOG and DIALOGEX (and the same structure version number).
669 // It makes it possible for DIALOG to be mistaken for DIALOGEX.
670 IntOrString
getResourceType() const override
{ return RkDialog
; }
671 Twine
getResourceTypeName() const override
{
672 return "DIALOG" + Twine(IsExtended
? "EX" : "");
674 Error
visit(Visitor
*V
) const override
{
675 return V
->visitDialogResource(this);
677 ResourceKind
getKind() const override
{ return RkDialog
; }
678 static bool classof(const RCResource
*Res
) {
679 return Res
->getKind() == RkDialog
;
683 // User-defined resource. It is either:
684 // * a link to the file, e.g. NAME TYPE "filename",
685 // * or contains a list of integers and strings, e.g. NAME TYPE {1, "a", 2}.
686 class UserDefinedResource
: public RCResource
{
690 std::vector
<IntOrString
> Contents
;
693 UserDefinedResource(IntOrString ResourceType
, StringRef FileLocation
,
695 : RCResource(Flags
), Type(ResourceType
), FileLoc(FileLocation
),
696 IsFileResource(true) {}
697 UserDefinedResource(IntOrString ResourceType
, std::vector
<IntOrString
> &&Data
,
699 : RCResource(Flags
), Type(ResourceType
), Contents(std::move(Data
)),
700 IsFileResource(false) {}
702 raw_ostream
&log(raw_ostream
&) const override
;
703 IntOrString
getResourceType() const override
{ return Type
; }
704 Twine
getResourceTypeName() const override
{ return Type
; }
705 static uint16_t getDefaultMemoryFlags() { return MfPure
| MfMoveable
; }
707 Error
visit(Visitor
*V
) const override
{
708 return V
->visitUserDefinedResource(this);
710 ResourceKind
getKind() const override
{ return RkUser
; }
711 static bool classof(const RCResource
*Res
) {
712 return Res
->getKind() == RkUser
;
716 // -- VERSIONINFO resource and its helper classes --
718 // This resource lists the version information on the executable/library.
719 // The declaration consists of the following items:
720 // * A number of fixed optional version statements (e.g. FILEVERSION, FILEOS)
722 // * A number of BLOCK and/or VALUE statements. BLOCK recursively defines
723 // another block of version information, whereas VALUE defines a
724 // key -> value correspondence. There might be more than one value
725 // corresponding to the single key.
728 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381058(v=vs.85).aspx
730 // A single VERSIONINFO statement;
731 class VersionInfoStmt
{
733 enum StmtKind
{ StBase
= 0, StBlock
= 1, StValue
= 2 };
735 virtual raw_ostream
&log(raw_ostream
&OS
) const { return OS
<< "VI stmt\n"; }
736 virtual ~VersionInfoStmt() {}
738 virtual StmtKind
getKind() const { return StBase
; }
739 static bool classof(const VersionInfoStmt
*S
) {
740 return S
->getKind() == StBase
;
744 // BLOCK definition; also the main VERSIONINFO declaration is considered a
745 // BLOCK, although it has no name.
746 // The correct top-level blocks are "VarFileInfo" and "StringFileInfo". We don't
747 // care about them at the parsing phase.
748 class VersionInfoBlock
: public VersionInfoStmt
{
750 std::vector
<std::unique_ptr
<VersionInfoStmt
>> Stmts
;
753 VersionInfoBlock(StringRef BlockName
) : Name(BlockName
) {}
754 void addStmt(std::unique_ptr
<VersionInfoStmt
> Stmt
) {
755 Stmts
.push_back(std::move(Stmt
));
757 raw_ostream
&log(raw_ostream
&) const override
;
759 StmtKind
getKind() const override
{ return StBlock
; }
760 static bool classof(const VersionInfoStmt
*S
) {
761 return S
->getKind() == StBlock
;
765 class VersionInfoValue
: public VersionInfoStmt
{
768 std::vector
<IntOrString
> Values
;
769 std::vector
<bool> HasPrecedingComma
;
771 VersionInfoValue(StringRef InfoKey
, std::vector
<IntOrString
> &&Vals
,
772 std::vector
<bool> &&CommasBeforeVals
)
773 : Key(InfoKey
), Values(std::move(Vals
)),
774 HasPrecedingComma(std::move(CommasBeforeVals
)) {}
775 raw_ostream
&log(raw_ostream
&) const override
;
777 StmtKind
getKind() const override
{ return StValue
; }
778 static bool classof(const VersionInfoStmt
*S
) {
779 return S
->getKind() == StValue
;
783 class VersionInfoResource
: public RCResource
{
785 // A class listing fixed VERSIONINFO statements (occuring before main BEGIN).
786 // If any of these is not specified, it is assumed by the original tool to
788 class VersionInfoFixed
{
790 enum VersionInfoFixedType
{
803 static const StringMap
<VersionInfoFixedType
> FixedFieldsInfoMap
;
804 static const StringRef FixedFieldsNames
[FtNumTypes
];
807 SmallVector
<uint32_t, 4> FixedInfo
[FtNumTypes
];
808 SmallVector
<bool, FtNumTypes
> IsTypePresent
;
810 static VersionInfoFixedType
getFixedType(StringRef Type
);
811 static bool isTypeSupported(VersionInfoFixedType Type
);
812 static bool isVersionType(VersionInfoFixedType Type
);
814 VersionInfoFixed() : IsTypePresent(FtNumTypes
, false) {}
816 void setValue(VersionInfoFixedType Type
, ArrayRef
<uint32_t> Value
) {
817 FixedInfo
[Type
] = SmallVector
<uint32_t, 4>(Value
.begin(), Value
.end());
818 IsTypePresent
[Type
] = true;
821 raw_ostream
&log(raw_ostream
&) const;
824 VersionInfoBlock MainBlock
;
825 VersionInfoFixed FixedData
;
827 VersionInfoResource(VersionInfoBlock
&&TopLevelBlock
,
828 VersionInfoFixed
&&FixedInfo
, uint16_t Flags
)
829 : RCResource(Flags
), MainBlock(std::move(TopLevelBlock
)),
830 FixedData(std::move(FixedInfo
)) {}
832 raw_ostream
&log(raw_ostream
&) const override
;
833 IntOrString
getResourceType() const override
{ return RkVersionInfo
; }
834 static uint16_t getDefaultMemoryFlags() { return MfMoveable
| MfPure
; }
835 Twine
getResourceTypeName() const override
{ return "VERSIONINFO"; }
836 Error
visit(Visitor
*V
) const override
{
837 return V
->visitVersionInfoResource(this);
839 ResourceKind
getKind() const override
{ return RkVersionInfo
; }
840 static bool classof(const RCResource
*Res
) {
841 return Res
->getKind() == RkVersionInfo
;
845 // CHARACTERISTICS optional statement.
847 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380872(v=vs.85).aspx
848 class CharacteristicsStmt
: public OptionalStmt
{
852 CharacteristicsStmt(uint32_t Characteristic
) : Value(Characteristic
) {}
853 raw_ostream
&log(raw_ostream
&) const override
;
855 Twine
getResourceTypeName() const override
{ return "CHARACTERISTICS"; }
856 Error
visit(Visitor
*V
) const override
{
857 return V
->visitCharacteristicsStmt(this);
861 // VERSION optional statement.
863 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381059(v=vs.85).aspx
864 class VersionStmt
: public OptionalStmt
{
868 VersionStmt(uint32_t Version
) : Value(Version
) {}
869 raw_ostream
&log(raw_ostream
&) const override
;
871 Twine
getResourceTypeName() const override
{ return "VERSION"; }
872 Error
visit(Visitor
*V
) const override
{ return V
->visitVersionStmt(this); }
875 // CAPTION optional statement.
877 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx
878 class CaptionStmt
: public OptionalStmt
{
882 CaptionStmt(StringRef Caption
) : Value(Caption
) {}
883 raw_ostream
&log(raw_ostream
&) const override
;
884 Twine
getResourceTypeName() const override
{ return "CAPTION"; }
885 Error
visit(Visitor
*V
) const override
{ return V
->visitCaptionStmt(this); }
888 // FONT optional statement.
889 // Note that the documentation is inaccurate: it expects five arguments to be
890 // given, however the example provides only two. In fact, the original tool
891 // expects two arguments - point size and name of the typeface.
893 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381013(v=vs.85).aspx
894 class FontStmt
: public OptionalStmt
{
896 uint32_t Size
, Weight
, Charset
;
900 FontStmt(uint32_t FontSize
, StringRef FontName
, uint32_t FontWeight
,
901 bool FontItalic
, uint32_t FontCharset
)
902 : Size(FontSize
), Weight(FontWeight
), Charset(FontCharset
),
903 Name(FontName
), Italic(FontItalic
) {}
904 raw_ostream
&log(raw_ostream
&) const override
;
905 Twine
getResourceTypeName() const override
{ return "FONT"; }
906 Error
visit(Visitor
*V
) const override
{ return V
->visitFontStmt(this); }
909 // STYLE optional statement.
911 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx
912 class StyleStmt
: public OptionalStmt
{
916 StyleStmt(uint32_t Style
) : Value(Style
) {}
917 raw_ostream
&log(raw_ostream
&) const override
;
918 Twine
getResourceTypeName() const override
{ return "STYLE"; }
919 Error
visit(Visitor
*V
) const override
{ return V
->visitStyleStmt(this); }
922 // EXSTYLE optional statement.
924 // Ref: docs.microsoft.com/en-us/windows/desktop/menurc/exstyle-statement
925 class ExStyleStmt
: public OptionalStmt
{
929 ExStyleStmt(uint32_t ExStyle
) : Value(ExStyle
) {}
930 raw_ostream
&log(raw_ostream
&) const override
;
931 Twine
getResourceTypeName() const override
{ return "EXSTYLE"; }
932 Error
visit(Visitor
*V
) const override
{ return V
->visitExStyleStmt(this); }
935 // CLASS optional statement.
937 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380883(v=vs.85).aspx
938 class ClassStmt
: public OptionalStmt
{
942 ClassStmt(IntOrString Class
) : Value(Class
) {}
943 raw_ostream
&log(raw_ostream
&) const override
;
944 Twine
getResourceTypeName() const override
{ return "CLASS"; }
945 Error
visit(Visitor
*V
) const override
{ return V
->visitClassStmt(this); }