blob: 2071ac6a9a3ad75c84e393108d00aa85de41cb29 [file] [log] [blame]
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +00001//===-- ResourceScriptStmt.h ------------------------------------*- C++-*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===---------------------------------------------------------------------===//
9//
10// This lists all the resource and statement types occurring in RC scripts.
11//
12//===---------------------------------------------------------------------===//
13
14#ifndef LLVM_TOOLS_LLVMRC_RESOURCESCRIPTSTMT_H
15#define LLVM_TOOLS_LLVMRC_RESOURCESCRIPTSTMT_H
16
17#include "ResourceScriptToken.h"
Marek Sokolowski8f193432017-09-29 17:14:09 +000018#include "ResourceVisitor.h"
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +000019
Marek Sokolowski4ac54d92017-08-29 16:49:59 +000020#include "llvm/ADT/StringSet.h"
21
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +000022namespace llvm {
23namespace rc {
24
Zachary Turner07bc04f2017-10-06 21:26:06 +000025// 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
29// being marked long.
30class RCInt {
31 uint32_t Val;
32 bool Long;
33
34public:
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; }
41
42 RCInt &operator+=(const RCInt &Rhs) {
43 std::tie(Val, Long) = std::make_pair(Val + Rhs.Val, Long | Rhs.Long);
44 return *this;
45 }
46
47 RCInt &operator-=(const RCInt &Rhs) {
48 std::tie(Val, Long) = std::make_pair(Val - Rhs.Val, Long | Rhs.Long);
49 return *this;
50 }
51
52 RCInt &operator|=(const RCInt &Rhs) {
53 std::tie(Val, Long) = std::make_pair(Val | Rhs.Val, Long | Rhs.Long);
54 return *this;
55 }
56
57 RCInt &operator&=(const RCInt &Rhs) {
58 std::tie(Val, Long) = std::make_pair(Val & Rhs.Val, Long | Rhs.Long);
59 return *this;
60 }
61
62 RCInt operator-() const { return {-Val, Long}; }
63 RCInt operator~() const { return {~Val, Long}; }
64
65 friend raw_ostream &operator<<(raw_ostream &OS, const RCInt &Int) {
66 return OS << Int.Val << (Int.Long ? "L" : "");
67 }
68};
69
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +000070// A class holding a name - either an integer or a reference to the string.
71class IntOrString {
72private:
73 union Data {
Zachary Turner07bc04f2017-10-06 21:26:06 +000074 RCInt Int;
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +000075 StringRef String;
Zachary Turner07bc04f2017-10-06 21:26:06 +000076 Data(RCInt Value) : Int(Value) {}
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +000077 Data(const StringRef Value) : String(Value) {}
Marek Sokolowski7f110522017-08-28 22:58:31 +000078 Data(const RCToken &Token) {
79 if (Token.kind() == RCToken::Kind::Int)
Zachary Turner07bc04f2017-10-06 21:26:06 +000080 Int = RCInt(Token);
Marek Sokolowski7f110522017-08-28 22:58:31 +000081 else
82 String = Token.value();
83 }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +000084 } Data;
85 bool IsInt;
86
87public:
Zachary Turner07bc04f2017-10-06 21:26:06 +000088 IntOrString() : IntOrString(RCInt(0)) {}
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +000089 IntOrString(uint32_t Value) : Data(Value), IsInt(1) {}
Zachary Turner07bc04f2017-10-06 21:26:06 +000090 IntOrString(RCInt Value) : Data(Value), IsInt(1) {}
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +000091 IntOrString(StringRef Value) : Data(Value), IsInt(0) {}
92 IntOrString(const RCToken &Token)
93 : Data(Token), IsInt(Token.kind() == RCToken::Kind::Int) {}
94
95 bool equalsLower(const char *Str) {
96 return !IsInt && Data.String.equals_lower(Str);
97 }
98
Marek Sokolowski8f193432017-09-29 17:14:09 +000099 bool isInt() const { return IsInt; }
100
Zachary Turner07bc04f2017-10-06 21:26:06 +0000101 RCInt getInt() const {
Marek Sokolowski8f193432017-09-29 17:14:09 +0000102 assert(IsInt);
103 return Data.Int;
104 }
105
106 const StringRef &getString() const {
107 assert(!IsInt);
108 return Data.String;
109 }
110
111 operator Twine() const {
112 return isInt() ? Twine(getInt()) : Twine(getString());
113 }
114
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000115 friend raw_ostream &operator<<(raw_ostream &, const IntOrString &);
116};
117
Marek Sokolowski8f193432017-09-29 17:14:09 +0000118enum ResourceKind {
119 // These resource kinds have corresponding .res resource type IDs
120 // (TYPE in RESOURCEHEADER structure). The numeric value assigned to each
121 // kind is equal to this type ID.
122 RkNull = 0,
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000123 RkSingleCursor = 1,
Martin Storsjo577b9812018-05-07 20:27:37 +0000124 RkBitmap = 2,
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000125 RkSingleIcon = 3,
Marek Sokolowski8f193432017-09-29 17:14:09 +0000126 RkMenu = 4,
127 RkDialog = 5,
Zachary Turnerda366692017-10-06 21:30:55 +0000128 RkStringTableBundle = 6,
Marek Sokolowski8f193432017-09-29 17:14:09 +0000129 RkAccelerators = 9,
Martin Storsjo7bc3c582018-05-09 18:20:56 +0000130 RkRcData = 10,
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000131 RkCursorGroup = 12,
132 RkIconGroup = 14,
Marek Sokolowski8f193432017-09-29 17:14:09 +0000133 RkVersionInfo = 16,
134 RkHTML = 23,
135
136 // These kinds don't have assigned type IDs (they might be the resources
137 // of invalid kind, expand to many resource structures in .res files,
138 // or have variable type ID). In order to avoid ID clashes with IDs above,
139 // we assign the kinds the values 256 and larger.
140 RkInvalid = 256,
141 RkBase,
142 RkCursor,
143 RkIcon,
Zachary Turnerda366692017-10-06 21:30:55 +0000144 RkStringTable,
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000145 RkUser,
146 RkSingleCursorOrIconRes,
Zachary Turnerda366692017-10-06 21:30:55 +0000147 RkCursorOrIconGroupRes,
Marek Sokolowski8f193432017-09-29 17:14:09 +0000148};
149
150// Non-zero memory flags.
151// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648027(v=vs.85).aspx
152enum MemoryFlags {
153 MfMoveable = 0x10,
154 MfPure = 0x20,
155 MfPreload = 0x40,
156 MfDiscardable = 0x1000
157};
158
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000159// Base resource. All the resources should derive from this base.
160class RCResource {
Marek Sokolowski8f193432017-09-29 17:14:09 +0000161public:
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000162 IntOrString ResName;
Martin Storsjo11adbac2018-05-15 06:35:29 +0000163 uint16_t MemoryFlags = getDefaultMemoryFlags();
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000164 void setName(const IntOrString &Name) { ResName = Name; }
165 virtual raw_ostream &log(raw_ostream &OS) const {
166 return OS << "Base statement\n";
167 };
Martin Storsjo11adbac2018-05-15 06:35:29 +0000168 RCResource() {}
169 RCResource(uint16_t Flags) : MemoryFlags(Flags) {}
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000170 virtual ~RCResource() {}
Marek Sokolowski8f193432017-09-29 17:14:09 +0000171
172 virtual Error visit(Visitor *) const {
173 llvm_unreachable("This is unable to call methods from Visitor base");
174 }
175
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000176 // Apply the statements attached to this resource. Generic resources
177 // don't have any.
178 virtual Error applyStmts(Visitor *) const { return Error::success(); }
179
Marek Sokolowski8f193432017-09-29 17:14:09 +0000180 // By default, memory flags are DISCARDABLE | PURE | MOVEABLE.
Martin Storsjo11adbac2018-05-15 06:35:29 +0000181 static uint16_t getDefaultMemoryFlags() {
Marek Sokolowski8f193432017-09-29 17:14:09 +0000182 return MfDiscardable | MfPure | MfMoveable;
183 }
Martin Storsjo11adbac2018-05-15 06:35:29 +0000184
Marek Sokolowski8f193432017-09-29 17:14:09 +0000185 virtual ResourceKind getKind() const { return RkBase; }
186 static bool classof(const RCResource *Res) { return true; }
187
188 virtual IntOrString getResourceType() const {
189 llvm_unreachable("This cannot be called on objects without types.");
190 }
191 virtual Twine getResourceTypeName() const {
192 llvm_unreachable("This cannot be called on objects without types.");
193 };
194};
195
196// An empty resource. It has no content, type 0, ID 0 and all of its
197// characteristics are equal to 0.
198class NullResource : public RCResource {
199public:
Martin Storsjo11adbac2018-05-15 06:35:29 +0000200 NullResource() : RCResource(0) {}
Marek Sokolowski8f193432017-09-29 17:14:09 +0000201 raw_ostream &log(raw_ostream &OS) const override {
202 return OS << "Null resource\n";
203 }
204 Error visit(Visitor *V) const override { return V->visitNullResource(this); }
205 IntOrString getResourceType() const override { return 0; }
206 Twine getResourceTypeName() const override { return "(NULL)"; }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000207};
208
209// Optional statement base. All such statements should derive from this base.
210class OptionalStmt : public RCResource {};
211
212class OptionalStmtList : public OptionalStmt {
213 std::vector<std::unique_ptr<OptionalStmt>> Statements;
214
215public:
216 OptionalStmtList() {}
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000217 raw_ostream &log(raw_ostream &OS) const override;
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000218
219 void addStmt(std::unique_ptr<OptionalStmt> Stmt) {
220 Statements.push_back(std::move(Stmt));
221 }
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000222
223 Error visit(Visitor *V) const override {
224 for (auto &StmtPtr : Statements)
225 if (auto Err = StmtPtr->visit(V))
226 return Err;
227 return Error::success();
228 }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000229};
230
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000231class OptStatementsRCResource : public RCResource {
232public:
233 std::unique_ptr<OptionalStmtList> OptStatements;
234
Martin Storsjo11adbac2018-05-15 06:35:29 +0000235 OptStatementsRCResource(OptionalStmtList &&Stmts,
236 uint16_t Flags = RCResource::getDefaultMemoryFlags())
237 : RCResource(Flags),
238 OptStatements(llvm::make_unique<OptionalStmtList>(std::move(Stmts))) {}
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000239
240 virtual Error applyStmts(Visitor *V) const { return OptStatements->visit(V); }
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000241};
242
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000243// LANGUAGE statement. It can occur both as a top-level statement (in such
244// a situation, it changes the default language until the end of the file)
245// and as an optional resource statement (then it changes the language
246// of a single resource).
247//
248// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381019(v=vs.85).aspx
249class LanguageResource : public OptionalStmt {
Marek Sokolowski8f193432017-09-29 17:14:09 +0000250public:
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000251 uint32_t Lang, SubLang;
252
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000253 LanguageResource(uint32_t LangId, uint32_t SubLangId)
254 : Lang(LangId), SubLang(SubLangId) {}
255 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski8f193432017-09-29 17:14:09 +0000256
257 // This is not a regular top-level statement; when it occurs, it just
258 // modifies the language context.
259 Error visit(Visitor *V) const override { return V->visitLanguageStmt(this); }
260 Twine getResourceTypeName() const override { return "LANGUAGE"; }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000261};
262
Marek Sokolowski7f110522017-08-28 22:58:31 +0000263// ACCELERATORS resource. Defines a named table of accelerators for the app.
264//
265// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380610(v=vs.85).aspx
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000266class AcceleratorsResource : public OptStatementsRCResource {
Marek Sokolowski7f110522017-08-28 22:58:31 +0000267public:
268 class Accelerator {
269 public:
270 IntOrString Event;
271 uint32_t Id;
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000272 uint16_t Flags;
Marek Sokolowski7f110522017-08-28 22:58:31 +0000273
274 enum Options {
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000275 // This is actually 0x0000 (accelerator is assumed to be ASCII if it's
276 // not VIRTKEY). However, rc.exe behavior is different in situations
277 // "only ASCII defined" and "neither ASCII nor VIRTKEY defined".
278 // Therefore, we include ASCII as another flag. This must be zeroed
279 // when serialized.
280 ASCII = 0x8000,
281 VIRTKEY = 0x0001,
282 NOINVERT = 0x0002,
283 ALT = 0x0010,
284 SHIFT = 0x0004,
285 CONTROL = 0x0008
Marek Sokolowski7f110522017-08-28 22:58:31 +0000286 };
287
288 static constexpr size_t NumFlags = 6;
289 static StringRef OptionsStr[NumFlags];
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000290 static uint32_t OptionsFlags[NumFlags];
Marek Sokolowski7f110522017-08-28 22:58:31 +0000291 };
292
Martin Storsjo11adbac2018-05-15 06:35:29 +0000293 AcceleratorsResource(OptionalStmtList &&List, uint16_t Flags)
294 : OptStatementsRCResource(std::move(List), Flags) {}
295
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000296 std::vector<Accelerator> Accelerators;
297
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000298 void addAccelerator(IntOrString Event, uint32_t Id, uint16_t Flags) {
Marek Sokolowski7f110522017-08-28 22:58:31 +0000299 Accelerators.push_back(Accelerator{Event, Id, Flags});
300 }
301 raw_ostream &log(raw_ostream &) const override;
302
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000303 IntOrString getResourceType() const override { return RkAccelerators; }
Martin Storsjo11adbac2018-05-15 06:35:29 +0000304 static uint16_t getDefaultMemoryFlags() { return MfPure | MfMoveable; }
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000305 Twine getResourceTypeName() const override { return "ACCELERATORS"; }
306
307 Error visit(Visitor *V) const override {
308 return V->visitAcceleratorsResource(this);
309 }
310 ResourceKind getKind() const override { return RkAccelerators; }
311 static bool classof(const RCResource *Res) {
312 return Res->getKind() == RkAccelerators;
313 }
Marek Sokolowski7f110522017-08-28 22:58:31 +0000314};
315
Martin Storsjo577b9812018-05-07 20:27:37 +0000316// BITMAP resource. Represents a bitmap (".bmp") file.
317//
318// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380680(v=vs.85).aspx
319class BitmapResource : public RCResource {
320public:
321 StringRef BitmapLoc;
322
Martin Storsjo11adbac2018-05-15 06:35:29 +0000323 BitmapResource(StringRef Location, uint16_t Flags)
324 : RCResource(Flags), BitmapLoc(Location) {}
Martin Storsjo577b9812018-05-07 20:27:37 +0000325 raw_ostream &log(raw_ostream &) const override;
326
327 IntOrString getResourceType() const override { return RkBitmap; }
Martin Storsjo11adbac2018-05-15 06:35:29 +0000328 static uint16_t getDefaultMemoryFlags() { return MfPure | MfMoveable; }
Martin Storsjo577b9812018-05-07 20:27:37 +0000329
330 Twine getResourceTypeName() const override { return "BITMAP"; }
331 Error visit(Visitor *V) const override {
332 return V->visitBitmapResource(this);
333 }
334 ResourceKind getKind() const override { return RkBitmap; }
335 static bool classof(const RCResource *Res) {
336 return Res->getKind() == RkBitmap;
337 }
338};
339
Marek Sokolowski72aa9372017-08-28 21:59:54 +0000340// CURSOR resource. Represents a single cursor (".cur") file.
341//
342// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380920(v=vs.85).aspx
343class CursorResource : public RCResource {
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000344public:
Marek Sokolowski72aa9372017-08-28 21:59:54 +0000345 StringRef CursorLoc;
346
Martin Storsjo11adbac2018-05-15 06:35:29 +0000347 CursorResource(StringRef Location, uint16_t Flags)
348 : RCResource(Flags), CursorLoc(Location) {}
Marek Sokolowski72aa9372017-08-28 21:59:54 +0000349 raw_ostream &log(raw_ostream &) const override;
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000350
351 Twine getResourceTypeName() const override { return "CURSOR"; }
Martin Storsjo11adbac2018-05-15 06:35:29 +0000352 static uint16_t getDefaultMemoryFlags() { return MfDiscardable | MfMoveable; }
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000353 Error visit(Visitor *V) const override {
354 return V->visitCursorResource(this);
355 }
356 ResourceKind getKind() const override { return RkCursor; }
357 static bool classof(const RCResource *Res) {
358 return Res->getKind() == RkCursor;
359 }
Marek Sokolowski72aa9372017-08-28 21:59:54 +0000360};
361
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000362// ICON resource. Represents a single ".ico" file containing a group of icons.
363//
364// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381018(v=vs.85).aspx
365class IconResource : public RCResource {
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000366public:
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000367 StringRef IconLoc;
368
Martin Storsjo11adbac2018-05-15 06:35:29 +0000369 IconResource(StringRef Location, uint16_t Flags)
370 : RCResource(Flags), IconLoc(Location) {}
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000371 raw_ostream &log(raw_ostream &) const override;
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000372
373 Twine getResourceTypeName() const override { return "ICON"; }
Martin Storsjo11adbac2018-05-15 06:35:29 +0000374 static uint16_t getDefaultMemoryFlags() { return MfDiscardable | MfMoveable; }
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000375 Error visit(Visitor *V) const override { return V->visitIconResource(this); }
376 ResourceKind getKind() const override { return RkIcon; }
377 static bool classof(const RCResource *Res) {
378 return Res->getKind() == RkIcon;
379 }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000380};
381
Marek Sokolowski72aa9372017-08-28 21:59:54 +0000382// HTML resource. Represents a local webpage that is to be embedded into the
383// resulting resource file. It embeds a file only - no additional resources
384// (images etc.) are included with this resource.
385//
386// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa966018(v=vs.85).aspx
387class HTMLResource : public RCResource {
Marek Sokolowski8f193432017-09-29 17:14:09 +0000388public:
Marek Sokolowski72aa9372017-08-28 21:59:54 +0000389 StringRef HTMLLoc;
390
Martin Storsjo11adbac2018-05-15 06:35:29 +0000391 HTMLResource(StringRef Location, uint16_t Flags)
392 : RCResource(Flags), HTMLLoc(Location) {}
Marek Sokolowski72aa9372017-08-28 21:59:54 +0000393 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski8f193432017-09-29 17:14:09 +0000394
395 Error visit(Visitor *V) const override { return V->visitHTMLResource(this); }
396
397 // Curiously, file resources don't have DISCARDABLE flag set.
Martin Storsjo11adbac2018-05-15 06:35:29 +0000398 static uint16_t getDefaultMemoryFlags() { return MfPure | MfMoveable; }
Marek Sokolowski8f193432017-09-29 17:14:09 +0000399 IntOrString getResourceType() const override { return RkHTML; }
400 Twine getResourceTypeName() const override { return "HTML"; }
401 ResourceKind getKind() const override { return RkHTML; }
402 static bool classof(const RCResource *Res) {
403 return Res->getKind() == RkHTML;
404 }
Marek Sokolowski72aa9372017-08-28 21:59:54 +0000405};
406
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000407// -- MENU resource and its helper classes --
408// This resource describes the contents of an application menu
409// (usually located in the upper part of the dialog.)
410//
411// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381025(v=vs.85).aspx
412
413// Description of a single submenu item.
414class MenuDefinition {
415public:
416 enum Options {
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000417 CHECKED = 0x0008,
418 GRAYED = 0x0001,
419 HELP = 0x4000,
420 INACTIVE = 0x0002,
421 MENUBARBREAK = 0x0020,
422 MENUBREAK = 0x0040
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000423 };
424
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000425 enum MenuDefKind { MkBase, MkSeparator, MkMenuItem, MkPopup };
426
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000427 static constexpr size_t NumFlags = 6;
428 static StringRef OptionsStr[NumFlags];
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000429 static uint32_t OptionsFlags[NumFlags];
430 static raw_ostream &logFlags(raw_ostream &, uint16_t Flags);
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000431 virtual raw_ostream &log(raw_ostream &OS) const {
432 return OS << "Base menu definition\n";
433 }
434 virtual ~MenuDefinition() {}
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000435
436 virtual uint16_t getResFlags() const { return 0; }
437 virtual MenuDefKind getKind() const { return MkBase; }
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000438};
439
440// Recursive description of a whole submenu.
441class MenuDefinitionList : public MenuDefinition {
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000442public:
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000443 std::vector<std::unique_ptr<MenuDefinition>> Definitions;
444
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000445 void addDefinition(std::unique_ptr<MenuDefinition> Def) {
446 Definitions.push_back(std::move(Def));
447 }
448 raw_ostream &log(raw_ostream &) const override;
449};
450
451// Separator in MENU definition (MENUITEM SEPARATOR).
452//
453// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
454class MenuSeparator : public MenuDefinition {
455public:
456 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000457
458 MenuDefKind getKind() const override { return MkSeparator; }
459 static bool classof(const MenuDefinition *D) {
460 return D->getKind() == MkSeparator;
461 }
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000462};
463
464// MENUITEM statement definition.
465//
466// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
467class MenuItem : public MenuDefinition {
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000468public:
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000469 StringRef Name;
470 uint32_t Id;
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000471 uint16_t Flags;
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000472
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000473 MenuItem(StringRef Caption, uint32_t ItemId, uint16_t ItemFlags)
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000474 : Name(Caption), Id(ItemId), Flags(ItemFlags) {}
475 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000476
477 uint16_t getResFlags() const override { return Flags; }
478 MenuDefKind getKind() const override { return MkMenuItem; }
479 static bool classof(const MenuDefinition *D) {
480 return D->getKind() == MkMenuItem;
481 }
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000482};
483
484// POPUP statement definition.
485//
486// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx
487class PopupItem : public MenuDefinition {
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000488public:
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000489 StringRef Name;
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000490 uint16_t Flags;
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000491 MenuDefinitionList SubItems;
492
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000493 PopupItem(StringRef Caption, uint16_t ItemFlags,
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000494 MenuDefinitionList &&SubItemsList)
495 : Name(Caption), Flags(ItemFlags), SubItems(std::move(SubItemsList)) {}
496 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000497
498 // This has an additional (0x10) flag. It doesn't match with documented
499 // 0x01 flag, though.
500 uint16_t getResFlags() const override { return Flags | 0x10; }
501 MenuDefKind getKind() const override { return MkPopup; }
502 static bool classof(const MenuDefinition *D) {
503 return D->getKind() == MkPopup;
504 }
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000505};
506
507// Menu resource definition.
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000508class MenuResource : public OptStatementsRCResource {
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000509public:
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000510 MenuDefinitionList Elements;
511
Martin Storsjo11adbac2018-05-15 06:35:29 +0000512 MenuResource(OptionalStmtList &&OptStmts, MenuDefinitionList &&Items,
513 uint16_t Flags)
514 : OptStatementsRCResource(std::move(OptStmts), Flags),
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000515 Elements(std::move(Items)) {}
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000516 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000517
518 IntOrString getResourceType() const override { return RkMenu; }
519 Twine getResourceTypeName() const override { return "MENU"; }
520 Error visit(Visitor *V) const override { return V->visitMenuResource(this); }
521 ResourceKind getKind() const override { return RkMenu; }
522 static bool classof(const RCResource *Res) {
523 return Res->getKind() == RkMenu;
524 }
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000525};
526
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000527// STRINGTABLE resource. Contains a list of strings, each having its unique ID.
528//
529// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381050(v=vs.85).aspx
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000530class StringTableResource : public OptStatementsRCResource {
Zachary Turnerda366692017-10-06 21:30:55 +0000531public:
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000532 std::vector<std::pair<uint32_t, StringRef>> Table;
533
Martin Storsjo11adbac2018-05-15 06:35:29 +0000534 StringTableResource(OptionalStmtList &&List, uint16_t Flags)
535 : OptStatementsRCResource(std::move(List), Flags) {}
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000536 void addString(uint32_t ID, StringRef String) {
537 Table.emplace_back(ID, String);
538 }
539 raw_ostream &log(raw_ostream &) const override;
Zachary Turnerda366692017-10-06 21:30:55 +0000540 Twine getResourceTypeName() const override { return "STRINGTABLE"; }
541 Error visit(Visitor *V) const override {
542 return V->visitStringTableResource(this);
543 }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000544};
545
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000546// -- DIALOG(EX) resource and its helper classes --
547//
548// This resource describes dialog boxes and controls residing inside them.
549//
550// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381003(v=vs.85).aspx
551// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx
552
553// Single control definition.
554class Control {
Marek Sokolowski7f7745c2017-09-30 00:38:52 +0000555public:
556 StringRef Type;
557 IntOrString Title;
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000558 uint32_t ID, X, Y, Width, Height;
559 Optional<uint32_t> Style, ExtStyle, HelpID;
Martin Storsjo818bd562018-05-08 20:55:58 +0000560 IntOrString Class;
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000561
Marek Sokolowski7f7745c2017-09-30 00:38:52 +0000562 // Control classes as described in DLGITEMTEMPLATEEX documentation.
563 //
564 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms645389.aspx
565 enum CtlClasses {
566 ClsButton = 0x80,
567 ClsEdit = 0x81,
568 ClsStatic = 0x82,
569 ClsListBox = 0x83,
570 ClsScrollBar = 0x84,
571 ClsComboBox = 0x85
572 };
573
574 // Simple information about a single control type.
575 struct CtlInfo {
576 uint32_t Style;
577 uint16_t CtlClass;
578 bool HasTitle;
579 };
580
581 Control(StringRef CtlType, IntOrString CtlTitle, uint32_t CtlID,
582 uint32_t PosX, uint32_t PosY, uint32_t ItemWidth, uint32_t ItemHeight,
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000583 Optional<uint32_t> ItemStyle, Optional<uint32_t> ExtItemStyle,
Martin Storsjo818bd562018-05-08 20:55:58 +0000584 Optional<uint32_t> CtlHelpID, IntOrString CtlClass)
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000585 : Type(CtlType), Title(CtlTitle), ID(CtlID), X(PosX), Y(PosY),
586 Width(ItemWidth), Height(ItemHeight), Style(ItemStyle),
Martin Storsjo818bd562018-05-08 20:55:58 +0000587 ExtStyle(ExtItemStyle), HelpID(CtlHelpID), Class(CtlClass) {}
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000588
Marek Sokolowski7f7745c2017-09-30 00:38:52 +0000589 static const StringMap<CtlInfo> SupportedCtls;
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000590
591 raw_ostream &log(raw_ostream &) const;
592};
593
594// Single dialog definition. We don't create distinct classes for DIALOG and
595// DIALOGEX because of their being too similar to each other. We only have a
596// flag determining the type of the dialog box.
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000597class DialogResource : public OptStatementsRCResource {
Marek Sokolowski7f7745c2017-09-30 00:38:52 +0000598public:
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000599 uint32_t X, Y, Width, Height, HelpID;
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000600 std::vector<Control> Controls;
601 bool IsExtended;
602
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000603 DialogResource(uint32_t PosX, uint32_t PosY, uint32_t DlgWidth,
604 uint32_t DlgHeight, uint32_t DlgHelpID,
Martin Storsjo11adbac2018-05-15 06:35:29 +0000605 OptionalStmtList &&OptStmts, bool IsDialogEx, uint16_t Flags)
606 : OptStatementsRCResource(std::move(OptStmts), Flags), X(PosX), Y(PosY),
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000607 Width(DlgWidth), Height(DlgHeight), HelpID(DlgHelpID),
608 IsExtended(IsDialogEx) {}
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000609
610 void addControl(Control &&Ctl) { Controls.push_back(std::move(Ctl)); }
611
612 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski7f7745c2017-09-30 00:38:52 +0000613
614 // It was a weird design decision to assign the same resource type number
615 // both for DIALOG and DIALOGEX (and the same structure version number).
616 // It makes it possible for DIALOG to be mistaken for DIALOGEX.
617 IntOrString getResourceType() const override { return RkDialog; }
618 Twine getResourceTypeName() const override {
619 return "DIALOG" + Twine(IsExtended ? "EX" : "");
620 }
621 Error visit(Visitor *V) const override {
622 return V->visitDialogResource(this);
623 }
624 ResourceKind getKind() const override { return RkDialog; }
625 static bool classof(const RCResource *Res) {
626 return Res->getKind() == RkDialog;
627 }
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000628};
629
Marek Sokolowskib5f39a02017-09-29 00:14:18 +0000630// User-defined resource. It is either:
631// * a link to the file, e.g. NAME TYPE "filename",
632// * or contains a list of integers and strings, e.g. NAME TYPE {1, "a", 2}.
633class UserDefinedResource : public RCResource {
Zachary Turner9d8b3582017-10-06 21:52:15 +0000634public:
Marek Sokolowskib5f39a02017-09-29 00:14:18 +0000635 IntOrString Type;
636 StringRef FileLoc;
637 std::vector<IntOrString> Contents;
638 bool IsFileResource;
639
Martin Storsjo11adbac2018-05-15 06:35:29 +0000640 UserDefinedResource(IntOrString ResourceType, StringRef FileLocation,
641 uint16_t Flags)
642 : RCResource(Flags), Type(ResourceType), FileLoc(FileLocation),
643 IsFileResource(true) {}
644 UserDefinedResource(IntOrString ResourceType, std::vector<IntOrString> &&Data,
645 uint16_t Flags)
646 : RCResource(Flags), Type(ResourceType), Contents(std::move(Data)),
647 IsFileResource(false) {}
Marek Sokolowskib5f39a02017-09-29 00:14:18 +0000648
649 raw_ostream &log(raw_ostream &) const override;
Zachary Turner9d8b3582017-10-06 21:52:15 +0000650 IntOrString getResourceType() const override { return Type; }
651 Twine getResourceTypeName() const override { return Type; }
Martin Storsjo11adbac2018-05-15 06:35:29 +0000652 static uint16_t getDefaultMemoryFlags() { return MfPure | MfMoveable; }
Zachary Turner9d8b3582017-10-06 21:52:15 +0000653
654 Error visit(Visitor *V) const override {
655 return V->visitUserDefinedResource(this);
656 }
657 ResourceKind getKind() const override { return RkUser; }
658 static bool classof(const RCResource *Res) {
659 return Res->getKind() == RkUser;
660 }
Marek Sokolowskib5f39a02017-09-29 00:14:18 +0000661};
662
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000663// -- VERSIONINFO resource and its helper classes --
664//
665// This resource lists the version information on the executable/library.
666// The declaration consists of the following items:
667// * A number of fixed optional version statements (e.g. FILEVERSION, FILEOS)
668// * BEGIN
669// * A number of BLOCK and/or VALUE statements. BLOCK recursively defines
670// another block of version information, whereas VALUE defines a
671// key -> value correspondence. There might be more than one value
672// corresponding to the single key.
673// * END
674//
675// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381058(v=vs.85).aspx
676
677// A single VERSIONINFO statement;
678class VersionInfoStmt {
679public:
Zachary Turner07bc04f2017-10-06 21:26:06 +0000680 enum StmtKind { StBase = 0, StBlock = 1, StValue = 2 };
681
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000682 virtual raw_ostream &log(raw_ostream &OS) const { return OS << "VI stmt\n"; }
683 virtual ~VersionInfoStmt() {}
Zachary Turner07bc04f2017-10-06 21:26:06 +0000684
685 virtual StmtKind getKind() const { return StBase; }
686 static bool classof(const VersionInfoStmt *S) {
687 return S->getKind() == StBase;
688 }
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000689};
690
691// BLOCK definition; also the main VERSIONINFO declaration is considered a
692// BLOCK, although it has no name.
693// The correct top-level blocks are "VarFileInfo" and "StringFileInfo". We don't
694// care about them at the parsing phase.
695class VersionInfoBlock : public VersionInfoStmt {
Zachary Turner07bc04f2017-10-06 21:26:06 +0000696public:
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000697 std::vector<std::unique_ptr<VersionInfoStmt>> Stmts;
698 StringRef Name;
699
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000700 VersionInfoBlock(StringRef BlockName) : Name(BlockName) {}
701 void addStmt(std::unique_ptr<VersionInfoStmt> Stmt) {
702 Stmts.push_back(std::move(Stmt));
703 }
704 raw_ostream &log(raw_ostream &) const override;
Zachary Turner07bc04f2017-10-06 21:26:06 +0000705
706 StmtKind getKind() const override { return StBlock; }
707 static bool classof(const VersionInfoStmt *S) {
708 return S->getKind() == StBlock;
709 }
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000710};
711
712class VersionInfoValue : public VersionInfoStmt {
Zachary Turner07bc04f2017-10-06 21:26:06 +0000713public:
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000714 StringRef Key;
715 std::vector<IntOrString> Values;
Zachary Turner07bc04f2017-10-06 21:26:06 +0000716 std::vector<bool> HasPrecedingComma;
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000717
Zachary Turner07bc04f2017-10-06 21:26:06 +0000718 VersionInfoValue(StringRef InfoKey, std::vector<IntOrString> &&Vals,
719 std::vector<bool> &&CommasBeforeVals)
720 : Key(InfoKey), Values(std::move(Vals)),
721 HasPrecedingComma(std::move(CommasBeforeVals)) {}
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000722 raw_ostream &log(raw_ostream &) const override;
Zachary Turner07bc04f2017-10-06 21:26:06 +0000723
724 StmtKind getKind() const override { return StValue; }
725 static bool classof(const VersionInfoStmt *S) {
726 return S->getKind() == StValue;
727 }
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000728};
729
730class VersionInfoResource : public RCResource {
731public:
732 // A class listing fixed VERSIONINFO statements (occuring before main BEGIN).
733 // If any of these is not specified, it is assumed by the original tool to
734 // be equal to 0.
735 class VersionInfoFixed {
736 public:
737 enum VersionInfoFixedType {
738 FtUnknown,
739 FtFileVersion,
740 FtProductVersion,
741 FtFileFlagsMask,
742 FtFileFlags,
743 FtFileOS,
744 FtFileType,
745 FtFileSubtype,
746 FtNumTypes
747 };
748
749 private:
750 static const StringMap<VersionInfoFixedType> FixedFieldsInfoMap;
751 static const StringRef FixedFieldsNames[FtNumTypes];
752
753 public:
754 SmallVector<uint32_t, 4> FixedInfo[FtNumTypes];
755 SmallVector<bool, FtNumTypes> IsTypePresent;
756
757 static VersionInfoFixedType getFixedType(StringRef Type);
758 static bool isTypeSupported(VersionInfoFixedType Type);
759 static bool isVersionType(VersionInfoFixedType Type);
760
761 VersionInfoFixed() : IsTypePresent(FtNumTypes, false) {}
762
763 void setValue(VersionInfoFixedType Type, ArrayRef<uint32_t> Value) {
764 FixedInfo[Type] = SmallVector<uint32_t, 4>(Value.begin(), Value.end());
765 IsTypePresent[Type] = true;
766 }
767
768 raw_ostream &log(raw_ostream &) const;
769 };
770
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000771 VersionInfoBlock MainBlock;
772 VersionInfoFixed FixedData;
773
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000774 VersionInfoResource(VersionInfoBlock &&TopLevelBlock,
Martin Storsjo11adbac2018-05-15 06:35:29 +0000775 VersionInfoFixed &&FixedInfo, uint16_t Flags)
776 : RCResource(Flags), MainBlock(std::move(TopLevelBlock)),
777 FixedData(std::move(FixedInfo)) {}
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000778
779 raw_ostream &log(raw_ostream &) const override;
Zachary Turner07bc04f2017-10-06 21:26:06 +0000780 IntOrString getResourceType() const override { return RkVersionInfo; }
Martin Storsjo11adbac2018-05-15 06:35:29 +0000781 static uint16_t getDefaultMemoryFlags() { return MfMoveable | MfPure; }
Zachary Turner07bc04f2017-10-06 21:26:06 +0000782 Twine getResourceTypeName() const override { return "VERSIONINFO"; }
783 Error visit(Visitor *V) const override {
784 return V->visitVersionInfoResource(this);
785 }
786 ResourceKind getKind() const override { return RkVersionInfo; }
787 static bool classof(const RCResource *Res) {
788 return Res->getKind() == RkVersionInfo;
789 }
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000790};
791
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000792// CHARACTERISTICS optional statement.
793//
794// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380872(v=vs.85).aspx
795class CharacteristicsStmt : public OptionalStmt {
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000796public:
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000797 uint32_t Value;
798
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000799 CharacteristicsStmt(uint32_t Characteristic) : Value(Characteristic) {}
800 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000801
802 Twine getResourceTypeName() const override { return "CHARACTERISTICS"; }
803 Error visit(Visitor *V) const override {
804 return V->visitCharacteristicsStmt(this);
805 }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000806};
807
808// VERSION optional statement.
809//
810// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381059(v=vs.85).aspx
811class VersionStmt : public OptionalStmt {
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000812public:
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000813 uint32_t Value;
814
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000815 VersionStmt(uint32_t Version) : Value(Version) {}
816 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000817
818 Twine getResourceTypeName() const override { return "VERSION"; }
819 Error visit(Visitor *V) const override { return V->visitVersionStmt(this); }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000820};
821
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000822// CAPTION optional statement.
823//
824// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx
825class CaptionStmt : public OptionalStmt {
Zachary Turner420090a2017-10-06 20:51:20 +0000826public:
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000827 StringRef Value;
828
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000829 CaptionStmt(StringRef Caption) : Value(Caption) {}
830 raw_ostream &log(raw_ostream &) const override;
Zachary Turner420090a2017-10-06 20:51:20 +0000831 Twine getResourceTypeName() const override { return "CAPTION"; }
832 Error visit(Visitor *V) const override { return V->visitCaptionStmt(this); }
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000833};
834
835// FONT optional statement.
836// Note that the documentation is inaccurate: it expects five arguments to be
837// given, however the example provides only two. In fact, the original tool
838// expects two arguments - point size and name of the typeface.
839//
840// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381013(v=vs.85).aspx
841class FontStmt : public OptionalStmt {
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000842public:
Zachary Turner420090a2017-10-06 20:51:20 +0000843 uint32_t Size, Weight, Charset;
844 StringRef Name;
845 bool Italic;
846
847 FontStmt(uint32_t FontSize, StringRef FontName, uint32_t FontWeight,
848 bool FontItalic, uint32_t FontCharset)
849 : Size(FontSize), Weight(FontWeight), Charset(FontCharset),
850 Name(FontName), Italic(FontItalic) {}
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000851 raw_ostream &log(raw_ostream &) const override;
Zachary Turner420090a2017-10-06 20:51:20 +0000852 Twine getResourceTypeName() const override { return "FONT"; }
853 Error visit(Visitor *V) const override { return V->visitFontStmt(this); }
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000854};
855
856// STYLE optional statement.
857//
858// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx
859class StyleStmt : public OptionalStmt {
Zachary Turner420090a2017-10-06 20:51:20 +0000860public:
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000861 uint32_t Value;
862
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000863 StyleStmt(uint32_t Style) : Value(Style) {}
864 raw_ostream &log(raw_ostream &) const override;
Zachary Turner420090a2017-10-06 20:51:20 +0000865 Twine getResourceTypeName() const override { return "STYLE"; }
866 Error visit(Visitor *V) const override { return V->visitStyleStmt(this); }
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000867};
868
Martin Storsjoe241ce62018-05-15 19:21:28 +0000869// CLASS optional statement.
870//
871// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380883(v=vs.85).aspx
872class ClassStmt : public OptionalStmt {
873public:
874 IntOrString Value;
875
876 ClassStmt(IntOrString Class) : Value(Class) {}
877 raw_ostream &log(raw_ostream &) const override;
878 Twine getResourceTypeName() const override { return "CLASS"; }
879 Error visit(Visitor *V) const override { return V->visitClassStmt(this); }
880};
881
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000882} // namespace rc
883} // namespace llvm
884
885#endif