blob: 3ba1f6619eb8d2a7c0329034bb3b78a5e665d43c [file] [log] [blame]
Marek Sokolowski0b33df92017-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 Sokolowskie37621b2017-09-29 17:14:09 +000018#include "ResourceVisitor.h"
Marek Sokolowski0b33df92017-08-18 18:24:17 +000019
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +000020#include "llvm/ADT/StringSet.h"
21
Marek Sokolowski0b33df92017-08-18 18:24:17 +000022namespace llvm {
23namespace rc {
24
Zachary Turner93bb30d2017-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
Martin Storsjoe96cf5f2018-12-05 13:22:56 +000070class IntWithNotMask {
71private:
72 RCInt Value;
73 int32_t NotMask;
74
75public:
76 IntWithNotMask() : IntWithNotMask(RCInt(0)) {}
77 IntWithNotMask(RCInt Value, int32_t NotMask = 0) : Value(Value), NotMask(NotMask) {}
78
79 RCInt getValue() const {
80 return Value;
81 }
82
83 uint32_t getNotMask() const {
84 return NotMask;
85 }
86
87 IntWithNotMask &operator+=(const IntWithNotMask &Rhs) {
88 Value &= ~Rhs.NotMask;
89 Value += Rhs.Value;
90 NotMask |= Rhs.NotMask;
91 return *this;
92 }
93
94 IntWithNotMask &operator-=(const IntWithNotMask &Rhs) {
95 Value &= ~Rhs.NotMask;
96 Value -= Rhs.Value;
97 NotMask |= Rhs.NotMask;
98 return *this;
99 }
100
101 IntWithNotMask &operator|=(const IntWithNotMask &Rhs) {
102 Value &= ~Rhs.NotMask;
103 Value |= Rhs.Value;
104 NotMask |= Rhs.NotMask;
105 return *this;
106 }
107
108 IntWithNotMask &operator&=(const IntWithNotMask &Rhs) {
109 Value &= ~Rhs.NotMask;
110 Value &= Rhs.Value;
111 NotMask |= Rhs.NotMask;
112 return *this;
113 }
114
115 IntWithNotMask operator-() const { return {-Value, NotMask}; }
116 IntWithNotMask operator~() const { return {~Value, 0}; }
117
118 friend raw_ostream &operator<<(raw_ostream &OS, const IntWithNotMask &Int) {
119 return OS << Int.Value;
120 }
121};
122
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000123// A class holding a name - either an integer or a reference to the string.
124class IntOrString {
125private:
126 union Data {
Zachary Turner93bb30d2017-10-06 21:26:06 +0000127 RCInt Int;
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000128 StringRef String;
Zachary Turner93bb30d2017-10-06 21:26:06 +0000129 Data(RCInt Value) : Int(Value) {}
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000130 Data(const StringRef Value) : String(Value) {}
Marek Sokolowski66c13b12017-08-28 22:58:31 +0000131 Data(const RCToken &Token) {
132 if (Token.kind() == RCToken::Kind::Int)
Zachary Turner93bb30d2017-10-06 21:26:06 +0000133 Int = RCInt(Token);
Marek Sokolowski66c13b12017-08-28 22:58:31 +0000134 else
135 String = Token.value();
136 }
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000137 } Data;
138 bool IsInt;
139
140public:
Zachary Turner93bb30d2017-10-06 21:26:06 +0000141 IntOrString() : IntOrString(RCInt(0)) {}
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000142 IntOrString(uint32_t Value) : Data(Value), IsInt(1) {}
Zachary Turner93bb30d2017-10-06 21:26:06 +0000143 IntOrString(RCInt Value) : Data(Value), IsInt(1) {}
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000144 IntOrString(StringRef Value) : Data(Value), IsInt(0) {}
145 IntOrString(const RCToken &Token)
146 : Data(Token), IsInt(Token.kind() == RCToken::Kind::Int) {}
147
148 bool equalsLower(const char *Str) {
149 return !IsInt && Data.String.equals_lower(Str);
150 }
151
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000152 bool isInt() const { return IsInt; }
153
Zachary Turner93bb30d2017-10-06 21:26:06 +0000154 RCInt getInt() const {
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000155 assert(IsInt);
156 return Data.Int;
157 }
158
159 const StringRef &getString() const {
160 assert(!IsInt);
161 return Data.String;
162 }
163
164 operator Twine() const {
165 return isInt() ? Twine(getInt()) : Twine(getString());
166 }
167
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000168 friend raw_ostream &operator<<(raw_ostream &, const IntOrString &);
169};
170
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000171enum ResourceKind {
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.
175 RkNull = 0,
Zachary Turner4c72b952017-10-06 21:25:44 +0000176 RkSingleCursor = 1,
Martin Storsjo31dc80f2018-05-07 20:27:37 +0000177 RkBitmap = 2,
Zachary Turner4c72b952017-10-06 21:25:44 +0000178 RkSingleIcon = 3,
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000179 RkMenu = 4,
180 RkDialog = 5,
Zachary Turner84ad96b2017-10-06 21:30:55 +0000181 RkStringTableBundle = 6,
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000182 RkAccelerators = 9,
Martin Storsjo0aa38c82018-05-09 18:20:56 +0000183 RkRcData = 10,
Zachary Turner4c72b952017-10-06 21:25:44 +0000184 RkCursorGroup = 12,
185 RkIconGroup = 14,
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000186 RkVersionInfo = 16,
187 RkHTML = 23,
188
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.
193 RkInvalid = 256,
194 RkBase,
195 RkCursor,
196 RkIcon,
Zachary Turner84ad96b2017-10-06 21:30:55 +0000197 RkStringTable,
Zachary Turner4c72b952017-10-06 21:25:44 +0000198 RkUser,
199 RkSingleCursorOrIconRes,
Zachary Turner84ad96b2017-10-06 21:30:55 +0000200 RkCursorOrIconGroupRes,
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000201};
202
203// Non-zero memory flags.
204// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648027(v=vs.85).aspx
205enum MemoryFlags {
206 MfMoveable = 0x10,
207 MfPure = 0x20,
208 MfPreload = 0x40,
209 MfDiscardable = 0x1000
210};
211
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000212// Base resource. All the resources should derive from this base.
213class RCResource {
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000214public:
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000215 IntOrString ResName;
Martin Storsjo370633f2018-05-15 06:35:29 +0000216 uint16_t MemoryFlags = getDefaultMemoryFlags();
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000217 void setName(const IntOrString &Name) { ResName = Name; }
218 virtual raw_ostream &log(raw_ostream &OS) const {
219 return OS << "Base statement\n";
220 };
Martin Storsjo370633f2018-05-15 06:35:29 +0000221 RCResource() {}
222 RCResource(uint16_t Flags) : MemoryFlags(Flags) {}
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000223 virtual ~RCResource() {}
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000224
225 virtual Error visit(Visitor *) const {
226 llvm_unreachable("This is unable to call methods from Visitor base");
227 }
228
Marek Sokolowskib121e772017-09-29 19:07:44 +0000229 // Apply the statements attached to this resource. Generic resources
230 // don't have any.
231 virtual Error applyStmts(Visitor *) const { return Error::success(); }
232
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000233 // By default, memory flags are DISCARDABLE | PURE | MOVEABLE.
Martin Storsjo370633f2018-05-15 06:35:29 +0000234 static uint16_t getDefaultMemoryFlags() {
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000235 return MfDiscardable | MfPure | MfMoveable;
236 }
Martin Storsjo370633f2018-05-15 06:35:29 +0000237
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000238 virtual ResourceKind getKind() const { return RkBase; }
239 static bool classof(const RCResource *Res) { return true; }
240
241 virtual IntOrString getResourceType() const {
242 llvm_unreachable("This cannot be called on objects without types.");
243 }
244 virtual Twine getResourceTypeName() const {
245 llvm_unreachable("This cannot be called on objects without types.");
246 };
247};
248
249// An empty resource. It has no content, type 0, ID 0 and all of its
250// characteristics are equal to 0.
251class NullResource : public RCResource {
252public:
Martin Storsjo370633f2018-05-15 06:35:29 +0000253 NullResource() : RCResource(0) {}
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000254 raw_ostream &log(raw_ostream &OS) const override {
255 return OS << "Null resource\n";
256 }
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)"; }
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000260};
261
262// Optional statement base. All such statements should derive from this base.
263class OptionalStmt : public RCResource {};
264
265class OptionalStmtList : public OptionalStmt {
266 std::vector<std::unique_ptr<OptionalStmt>> Statements;
267
268public:
269 OptionalStmtList() {}
Marek Sokolowskib121e772017-09-29 19:07:44 +0000270 raw_ostream &log(raw_ostream &OS) const override;
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000271
272 void addStmt(std::unique_ptr<OptionalStmt> Stmt) {
273 Statements.push_back(std::move(Stmt));
274 }
Marek Sokolowskib121e772017-09-29 19:07:44 +0000275
276 Error visit(Visitor *V) const override {
277 for (auto &StmtPtr : Statements)
278 if (auto Err = StmtPtr->visit(V))
279 return Err;
280 return Error::success();
281 }
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000282};
283
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000284class OptStatementsRCResource : public RCResource {
285public:
286 std::unique_ptr<OptionalStmtList> OptStatements;
287
Martin Storsjo370633f2018-05-15 06:35:29 +0000288 OptStatementsRCResource(OptionalStmtList &&Stmts,
289 uint16_t Flags = RCResource::getDefaultMemoryFlags())
290 : RCResource(Flags),
291 OptStatements(llvm::make_unique<OptionalStmtList>(std::move(Stmts))) {}
Marek Sokolowskib121e772017-09-29 19:07:44 +0000292
293 virtual Error applyStmts(Visitor *V) const { return OptStatements->visit(V); }
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000294};
295
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000296// LANGUAGE statement. It can occur both as a top-level statement (in such
297// a situation, it changes the default language until the end of the file)
298// and as an optional resource statement (then it changes the language
299// of a single resource).
300//
301// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381019(v=vs.85).aspx
302class LanguageResource : public OptionalStmt {
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000303public:
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000304 uint32_t Lang, SubLang;
305
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000306 LanguageResource(uint32_t LangId, uint32_t SubLangId)
307 : Lang(LangId), SubLang(SubLangId) {}
308 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000309
310 // This is not a regular top-level statement; when it occurs, it just
311 // modifies the language context.
312 Error visit(Visitor *V) const override { return V->visitLanguageStmt(this); }
313 Twine getResourceTypeName() const override { return "LANGUAGE"; }
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000314};
315
Marek Sokolowski66c13b12017-08-28 22:58:31 +0000316// ACCELERATORS resource. Defines a named table of accelerators for the app.
317//
318// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380610(v=vs.85).aspx
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000319class AcceleratorsResource : public OptStatementsRCResource {
Marek Sokolowski66c13b12017-08-28 22:58:31 +0000320public:
321 class Accelerator {
322 public:
323 IntOrString Event;
324 uint32_t Id;
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000325 uint16_t Flags;
Marek Sokolowski66c13b12017-08-28 22:58:31 +0000326
327 enum Options {
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000328 // This is actually 0x0000 (accelerator is assumed to be ASCII if it's
329 // not VIRTKEY). However, rc.exe behavior is different in situations
330 // "only ASCII defined" and "neither ASCII nor VIRTKEY defined".
331 // Therefore, we include ASCII as another flag. This must be zeroed
332 // when serialized.
333 ASCII = 0x8000,
334 VIRTKEY = 0x0001,
335 NOINVERT = 0x0002,
336 ALT = 0x0010,
337 SHIFT = 0x0004,
338 CONTROL = 0x0008
Marek Sokolowski66c13b12017-08-28 22:58:31 +0000339 };
340
341 static constexpr size_t NumFlags = 6;
342 static StringRef OptionsStr[NumFlags];
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000343 static uint32_t OptionsFlags[NumFlags];
Marek Sokolowski66c13b12017-08-28 22:58:31 +0000344 };
345
Martin Storsjo370633f2018-05-15 06:35:29 +0000346 AcceleratorsResource(OptionalStmtList &&List, uint16_t Flags)
347 : OptStatementsRCResource(std::move(List), Flags) {}
348
Marek Sokolowskib121e772017-09-29 19:07:44 +0000349 std::vector<Accelerator> Accelerators;
350
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000351 void addAccelerator(IntOrString Event, uint32_t Id, uint16_t Flags) {
Marek Sokolowski66c13b12017-08-28 22:58:31 +0000352 Accelerators.push_back(Accelerator{Event, Id, Flags});
353 }
354 raw_ostream &log(raw_ostream &) const override;
355
Marek Sokolowskib121e772017-09-29 19:07:44 +0000356 IntOrString getResourceType() const override { return RkAccelerators; }
Martin Storsjo370633f2018-05-15 06:35:29 +0000357 static uint16_t getDefaultMemoryFlags() { return MfPure | MfMoveable; }
Marek Sokolowskib121e772017-09-29 19:07:44 +0000358 Twine getResourceTypeName() const override { return "ACCELERATORS"; }
359
360 Error visit(Visitor *V) const override {
361 return V->visitAcceleratorsResource(this);
362 }
363 ResourceKind getKind() const override { return RkAccelerators; }
364 static bool classof(const RCResource *Res) {
365 return Res->getKind() == RkAccelerators;
366 }
Marek Sokolowski66c13b12017-08-28 22:58:31 +0000367};
368
Martin Storsjo31dc80f2018-05-07 20:27:37 +0000369// BITMAP resource. Represents a bitmap (".bmp") file.
370//
371// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380680(v=vs.85).aspx
372class BitmapResource : public RCResource {
373public:
374 StringRef BitmapLoc;
375
Martin Storsjo370633f2018-05-15 06:35:29 +0000376 BitmapResource(StringRef Location, uint16_t Flags)
377 : RCResource(Flags), BitmapLoc(Location) {}
Martin Storsjo31dc80f2018-05-07 20:27:37 +0000378 raw_ostream &log(raw_ostream &) const override;
379
380 IntOrString getResourceType() const override { return RkBitmap; }
Martin Storsjo370633f2018-05-15 06:35:29 +0000381 static uint16_t getDefaultMemoryFlags() { return MfPure | MfMoveable; }
Martin Storsjo31dc80f2018-05-07 20:27:37 +0000382
383 Twine getResourceTypeName() const override { return "BITMAP"; }
384 Error visit(Visitor *V) const override {
385 return V->visitBitmapResource(this);
386 }
387 ResourceKind getKind() const override { return RkBitmap; }
388 static bool classof(const RCResource *Res) {
389 return Res->getKind() == RkBitmap;
390 }
391};
392
Marek Sokolowskif2e55892017-08-28 21:59:54 +0000393// CURSOR resource. Represents a single cursor (".cur") file.
394//
395// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380920(v=vs.85).aspx
396class CursorResource : public RCResource {
Zachary Turner4c72b952017-10-06 21:25:44 +0000397public:
Marek Sokolowskif2e55892017-08-28 21:59:54 +0000398 StringRef CursorLoc;
399
Martin Storsjo370633f2018-05-15 06:35:29 +0000400 CursorResource(StringRef Location, uint16_t Flags)
401 : RCResource(Flags), CursorLoc(Location) {}
Marek Sokolowskif2e55892017-08-28 21:59:54 +0000402 raw_ostream &log(raw_ostream &) const override;
Zachary Turner4c72b952017-10-06 21:25:44 +0000403
404 Twine getResourceTypeName() const override { return "CURSOR"; }
Martin Storsjo370633f2018-05-15 06:35:29 +0000405 static uint16_t getDefaultMemoryFlags() { return MfDiscardable | MfMoveable; }
Zachary Turner4c72b952017-10-06 21:25:44 +0000406 Error visit(Visitor *V) const override {
407 return V->visitCursorResource(this);
408 }
409 ResourceKind getKind() const override { return RkCursor; }
410 static bool classof(const RCResource *Res) {
411 return Res->getKind() == RkCursor;
412 }
Marek Sokolowskif2e55892017-08-28 21:59:54 +0000413};
414
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000415// ICON resource. Represents a single ".ico" file containing a group of icons.
416//
417// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381018(v=vs.85).aspx
418class IconResource : public RCResource {
Zachary Turner4c72b952017-10-06 21:25:44 +0000419public:
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000420 StringRef IconLoc;
421
Martin Storsjo370633f2018-05-15 06:35:29 +0000422 IconResource(StringRef Location, uint16_t Flags)
423 : RCResource(Flags), IconLoc(Location) {}
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000424 raw_ostream &log(raw_ostream &) const override;
Zachary Turner4c72b952017-10-06 21:25:44 +0000425
426 Twine getResourceTypeName() const override { return "ICON"; }
Martin Storsjo370633f2018-05-15 06:35:29 +0000427 static uint16_t getDefaultMemoryFlags() { return MfDiscardable | MfMoveable; }
Zachary Turner4c72b952017-10-06 21:25:44 +0000428 Error visit(Visitor *V) const override { return V->visitIconResource(this); }
429 ResourceKind getKind() const override { return RkIcon; }
430 static bool classof(const RCResource *Res) {
431 return Res->getKind() == RkIcon;
432 }
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000433};
434
Marek Sokolowskif2e55892017-08-28 21:59:54 +0000435// HTML resource. Represents a local webpage that is to be embedded into the
436// resulting resource file. It embeds a file only - no additional resources
437// (images etc.) are included with this resource.
438//
439// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa966018(v=vs.85).aspx
440class HTMLResource : public RCResource {
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000441public:
Marek Sokolowskif2e55892017-08-28 21:59:54 +0000442 StringRef HTMLLoc;
443
Martin Storsjo370633f2018-05-15 06:35:29 +0000444 HTMLResource(StringRef Location, uint16_t Flags)
445 : RCResource(Flags), HTMLLoc(Location) {}
Marek Sokolowskif2e55892017-08-28 21:59:54 +0000446 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000447
448 Error visit(Visitor *V) const override { return V->visitHTMLResource(this); }
449
450 // Curiously, file resources don't have DISCARDABLE flag set.
Martin Storsjo370633f2018-05-15 06:35:29 +0000451 static uint16_t getDefaultMemoryFlags() { return MfPure | MfMoveable; }
Marek Sokolowskie37621b2017-09-29 17:14:09 +0000452 IntOrString getResourceType() const override { return RkHTML; }
453 Twine getResourceTypeName() const override { return "HTML"; }
454 ResourceKind getKind() const override { return RkHTML; }
455 static bool classof(const RCResource *Res) {
456 return Res->getKind() == RkHTML;
457 }
Marek Sokolowskif2e55892017-08-28 21:59:54 +0000458};
459
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000460// -- MENU resource and its helper classes --
461// This resource describes the contents of an application menu
462// (usually located in the upper part of the dialog.)
463//
464// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381025(v=vs.85).aspx
465
466// Description of a single submenu item.
467class MenuDefinition {
468public:
469 enum Options {
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000470 CHECKED = 0x0008,
471 GRAYED = 0x0001,
472 HELP = 0x4000,
473 INACTIVE = 0x0002,
474 MENUBARBREAK = 0x0020,
475 MENUBREAK = 0x0040
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000476 };
477
Marek Sokolowskiea529932017-09-29 22:25:05 +0000478 enum MenuDefKind { MkBase, MkSeparator, MkMenuItem, MkPopup };
479
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000480 static constexpr size_t NumFlags = 6;
481 static StringRef OptionsStr[NumFlags];
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000482 static uint32_t OptionsFlags[NumFlags];
483 static raw_ostream &logFlags(raw_ostream &, uint16_t Flags);
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000484 virtual raw_ostream &log(raw_ostream &OS) const {
485 return OS << "Base menu definition\n";
486 }
487 virtual ~MenuDefinition() {}
Marek Sokolowskiea529932017-09-29 22:25:05 +0000488
489 virtual uint16_t getResFlags() const { return 0; }
490 virtual MenuDefKind getKind() const { return MkBase; }
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000491};
492
493// Recursive description of a whole submenu.
494class MenuDefinitionList : public MenuDefinition {
Marek Sokolowskiea529932017-09-29 22:25:05 +0000495public:
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000496 std::vector<std::unique_ptr<MenuDefinition>> Definitions;
497
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000498 void addDefinition(std::unique_ptr<MenuDefinition> Def) {
499 Definitions.push_back(std::move(Def));
500 }
501 raw_ostream &log(raw_ostream &) const override;
502};
503
504// Separator in MENU definition (MENUITEM SEPARATOR).
505//
506// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
507class MenuSeparator : public MenuDefinition {
508public:
509 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowskiea529932017-09-29 22:25:05 +0000510
511 MenuDefKind getKind() const override { return MkSeparator; }
512 static bool classof(const MenuDefinition *D) {
513 return D->getKind() == MkSeparator;
514 }
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000515};
516
517// MENUITEM statement definition.
518//
519// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
520class MenuItem : public MenuDefinition {
Marek Sokolowskiea529932017-09-29 22:25:05 +0000521public:
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000522 StringRef Name;
523 uint32_t Id;
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000524 uint16_t Flags;
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000525
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000526 MenuItem(StringRef Caption, uint32_t ItemId, uint16_t ItemFlags)
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000527 : Name(Caption), Id(ItemId), Flags(ItemFlags) {}
528 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowskiea529932017-09-29 22:25:05 +0000529
530 uint16_t getResFlags() const override { return Flags; }
531 MenuDefKind getKind() const override { return MkMenuItem; }
532 static bool classof(const MenuDefinition *D) {
533 return D->getKind() == MkMenuItem;
534 }
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000535};
536
537// POPUP statement definition.
538//
539// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx
540class PopupItem : public MenuDefinition {
Marek Sokolowskiea529932017-09-29 22:25:05 +0000541public:
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000542 StringRef Name;
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000543 uint16_t Flags;
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000544 MenuDefinitionList SubItems;
545
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000546 PopupItem(StringRef Caption, uint16_t ItemFlags,
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000547 MenuDefinitionList &&SubItemsList)
548 : Name(Caption), Flags(ItemFlags), SubItems(std::move(SubItemsList)) {}
549 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowskiea529932017-09-29 22:25:05 +0000550
551 // This has an additional (0x10) flag. It doesn't match with documented
552 // 0x01 flag, though.
553 uint16_t getResFlags() const override { return Flags | 0x10; }
554 MenuDefKind getKind() const override { return MkPopup; }
555 static bool classof(const MenuDefinition *D) {
556 return D->getKind() == MkPopup;
557 }
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000558};
559
560// Menu resource definition.
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000561class MenuResource : public OptStatementsRCResource {
Marek Sokolowskiea529932017-09-29 22:25:05 +0000562public:
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000563 MenuDefinitionList Elements;
564
Martin Storsjo370633f2018-05-15 06:35:29 +0000565 MenuResource(OptionalStmtList &&OptStmts, MenuDefinitionList &&Items,
566 uint16_t Flags)
567 : OptStatementsRCResource(std::move(OptStmts), Flags),
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000568 Elements(std::move(Items)) {}
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000569 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowskiea529932017-09-29 22:25:05 +0000570
571 IntOrString getResourceType() const override { return RkMenu; }
572 Twine getResourceTypeName() const override { return "MENU"; }
573 Error visit(Visitor *V) const override { return V->visitMenuResource(this); }
574 ResourceKind getKind() const override { return RkMenu; }
575 static bool classof(const RCResource *Res) {
576 return Res->getKind() == RkMenu;
577 }
Marek Sokolowski233d2b82017-08-28 23:46:30 +0000578};
579
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000580// STRINGTABLE resource. Contains a list of strings, each having its unique ID.
581//
582// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381050(v=vs.85).aspx
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000583class StringTableResource : public OptStatementsRCResource {
Zachary Turner84ad96b2017-10-06 21:30:55 +0000584public:
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000585 std::vector<std::pair<uint32_t, StringRef>> Table;
586
Martin Storsjo370633f2018-05-15 06:35:29 +0000587 StringTableResource(OptionalStmtList &&List, uint16_t Flags)
588 : OptStatementsRCResource(std::move(List), Flags) {}
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000589 void addString(uint32_t ID, StringRef String) {
590 Table.emplace_back(ID, String);
591 }
592 raw_ostream &log(raw_ostream &) const override;
Zachary Turner84ad96b2017-10-06 21:30:55 +0000593 Twine getResourceTypeName() const override { return "STRINGTABLE"; }
594 Error visit(Visitor *V) const override {
595 return V->visitStringTableResource(this);
596 }
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000597};
598
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000599// -- DIALOG(EX) resource and its helper classes --
600//
601// This resource describes dialog boxes and controls residing inside them.
602//
603// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381003(v=vs.85).aspx
604// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx
605
606// Single control definition.
607class Control {
Marek Sokolowskibbf12f32017-09-30 00:38:52 +0000608public:
609 StringRef Type;
610 IntOrString Title;
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000611 uint32_t ID, X, Y, Width, Height;
Martin Storsjoe96cf5f2018-12-05 13:22:56 +0000612 Optional<IntWithNotMask> Style;
613 Optional<uint32_t> ExtStyle, HelpID;
Martin Storsjo793104b2018-05-08 20:55:58 +0000614 IntOrString Class;
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000615
Marek Sokolowskibbf12f32017-09-30 00:38:52 +0000616 // Control classes as described in DLGITEMTEMPLATEEX documentation.
617 //
618 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms645389.aspx
619 enum CtlClasses {
620 ClsButton = 0x80,
621 ClsEdit = 0x81,
622 ClsStatic = 0x82,
623 ClsListBox = 0x83,
624 ClsScrollBar = 0x84,
625 ClsComboBox = 0x85
626 };
627
628 // Simple information about a single control type.
629 struct CtlInfo {
630 uint32_t Style;
631 uint16_t CtlClass;
632 bool HasTitle;
633 };
634
635 Control(StringRef CtlType, IntOrString CtlTitle, uint32_t CtlID,
636 uint32_t PosX, uint32_t PosY, uint32_t ItemWidth, uint32_t ItemHeight,
Martin Storsjoe96cf5f2018-12-05 13:22:56 +0000637 Optional<IntWithNotMask> ItemStyle, Optional<uint32_t> ExtItemStyle,
Martin Storsjo793104b2018-05-08 20:55:58 +0000638 Optional<uint32_t> CtlHelpID, IntOrString CtlClass)
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000639 : Type(CtlType), Title(CtlTitle), ID(CtlID), X(PosX), Y(PosY),
640 Width(ItemWidth), Height(ItemHeight), Style(ItemStyle),
Martin Storsjo793104b2018-05-08 20:55:58 +0000641 ExtStyle(ExtItemStyle), HelpID(CtlHelpID), Class(CtlClass) {}
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000642
Marek Sokolowskibbf12f32017-09-30 00:38:52 +0000643 static const StringMap<CtlInfo> SupportedCtls;
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000644
645 raw_ostream &log(raw_ostream &) const;
646};
647
648// Single dialog definition. We don't create distinct classes for DIALOG and
649// DIALOGEX because of their being too similar to each other. We only have a
650// flag determining the type of the dialog box.
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000651class DialogResource : public OptStatementsRCResource {
Marek Sokolowskibbf12f32017-09-30 00:38:52 +0000652public:
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000653 uint32_t X, Y, Width, Height, HelpID;
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000654 std::vector<Control> Controls;
655 bool IsExtended;
656
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000657 DialogResource(uint32_t PosX, uint32_t PosY, uint32_t DlgWidth,
658 uint32_t DlgHeight, uint32_t DlgHelpID,
Martin Storsjo370633f2018-05-15 06:35:29 +0000659 OptionalStmtList &&OptStmts, bool IsDialogEx, uint16_t Flags)
660 : OptStatementsRCResource(std::move(OptStmts), Flags), X(PosX), Y(PosY),
Marek Sokolowskiafe86312017-09-29 17:46:32 +0000661 Width(DlgWidth), Height(DlgHeight), HelpID(DlgHelpID),
662 IsExtended(IsDialogEx) {}
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000663
664 void addControl(Control &&Ctl) { Controls.push_back(std::move(Ctl)); }
665
666 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowskibbf12f32017-09-30 00:38:52 +0000667
668 // It was a weird design decision to assign the same resource type number
669 // both for DIALOG and DIALOGEX (and the same structure version number).
670 // It makes it possible for DIALOG to be mistaken for DIALOGEX.
671 IntOrString getResourceType() const override { return RkDialog; }
672 Twine getResourceTypeName() const override {
673 return "DIALOG" + Twine(IsExtended ? "EX" : "");
674 }
675 Error visit(Visitor *V) const override {
676 return V->visitDialogResource(this);
677 }
678 ResourceKind getKind() const override { return RkDialog; }
679 static bool classof(const RCResource *Res) {
680 return Res->getKind() == RkDialog;
681 }
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000682};
683
Marek Sokolowski0bce0412017-09-29 00:14:18 +0000684// User-defined resource. It is either:
685// * a link to the file, e.g. NAME TYPE "filename",
686// * or contains a list of integers and strings, e.g. NAME TYPE {1, "a", 2}.
687class UserDefinedResource : public RCResource {
Zachary Turner080f10e2017-10-06 21:52:15 +0000688public:
Marek Sokolowski0bce0412017-09-29 00:14:18 +0000689 IntOrString Type;
690 StringRef FileLoc;
691 std::vector<IntOrString> Contents;
692 bool IsFileResource;
693
Martin Storsjo370633f2018-05-15 06:35:29 +0000694 UserDefinedResource(IntOrString ResourceType, StringRef FileLocation,
695 uint16_t Flags)
696 : RCResource(Flags), Type(ResourceType), FileLoc(FileLocation),
697 IsFileResource(true) {}
698 UserDefinedResource(IntOrString ResourceType, std::vector<IntOrString> &&Data,
699 uint16_t Flags)
700 : RCResource(Flags), Type(ResourceType), Contents(std::move(Data)),
701 IsFileResource(false) {}
Marek Sokolowski0bce0412017-09-29 00:14:18 +0000702
703 raw_ostream &log(raw_ostream &) const override;
Zachary Turner080f10e2017-10-06 21:52:15 +0000704 IntOrString getResourceType() const override { return Type; }
705 Twine getResourceTypeName() const override { return Type; }
Martin Storsjo370633f2018-05-15 06:35:29 +0000706 static uint16_t getDefaultMemoryFlags() { return MfPure | MfMoveable; }
Zachary Turner080f10e2017-10-06 21:52:15 +0000707
708 Error visit(Visitor *V) const override {
709 return V->visitUserDefinedResource(this);
710 }
711 ResourceKind getKind() const override { return RkUser; }
712 static bool classof(const RCResource *Res) {
713 return Res->getKind() == RkUser;
714 }
Marek Sokolowski0bce0412017-09-29 00:14:18 +0000715};
716
Marek Sokolowski86b61382017-09-28 22:41:38 +0000717// -- VERSIONINFO resource and its helper classes --
718//
719// This resource lists the version information on the executable/library.
720// The declaration consists of the following items:
721// * A number of fixed optional version statements (e.g. FILEVERSION, FILEOS)
722// * BEGIN
723// * A number of BLOCK and/or VALUE statements. BLOCK recursively defines
724// another block of version information, whereas VALUE defines a
725// key -> value correspondence. There might be more than one value
726// corresponding to the single key.
727// * END
728//
729// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381058(v=vs.85).aspx
730
731// A single VERSIONINFO statement;
732class VersionInfoStmt {
733public:
Zachary Turner93bb30d2017-10-06 21:26:06 +0000734 enum StmtKind { StBase = 0, StBlock = 1, StValue = 2 };
735
Marek Sokolowski86b61382017-09-28 22:41:38 +0000736 virtual raw_ostream &log(raw_ostream &OS) const { return OS << "VI stmt\n"; }
737 virtual ~VersionInfoStmt() {}
Zachary Turner93bb30d2017-10-06 21:26:06 +0000738
739 virtual StmtKind getKind() const { return StBase; }
740 static bool classof(const VersionInfoStmt *S) {
741 return S->getKind() == StBase;
742 }
Marek Sokolowski86b61382017-09-28 22:41:38 +0000743};
744
745// BLOCK definition; also the main VERSIONINFO declaration is considered a
746// BLOCK, although it has no name.
747// The correct top-level blocks are "VarFileInfo" and "StringFileInfo". We don't
748// care about them at the parsing phase.
749class VersionInfoBlock : public VersionInfoStmt {
Zachary Turner93bb30d2017-10-06 21:26:06 +0000750public:
Marek Sokolowski86b61382017-09-28 22:41:38 +0000751 std::vector<std::unique_ptr<VersionInfoStmt>> Stmts;
752 StringRef Name;
753
Marek Sokolowski86b61382017-09-28 22:41:38 +0000754 VersionInfoBlock(StringRef BlockName) : Name(BlockName) {}
755 void addStmt(std::unique_ptr<VersionInfoStmt> Stmt) {
756 Stmts.push_back(std::move(Stmt));
757 }
758 raw_ostream &log(raw_ostream &) const override;
Zachary Turner93bb30d2017-10-06 21:26:06 +0000759
760 StmtKind getKind() const override { return StBlock; }
761 static bool classof(const VersionInfoStmt *S) {
762 return S->getKind() == StBlock;
763 }
Marek Sokolowski86b61382017-09-28 22:41:38 +0000764};
765
766class VersionInfoValue : public VersionInfoStmt {
Zachary Turner93bb30d2017-10-06 21:26:06 +0000767public:
Marek Sokolowski86b61382017-09-28 22:41:38 +0000768 StringRef Key;
769 std::vector<IntOrString> Values;
Zachary Turner93bb30d2017-10-06 21:26:06 +0000770 std::vector<bool> HasPrecedingComma;
Marek Sokolowski86b61382017-09-28 22:41:38 +0000771
Zachary Turner93bb30d2017-10-06 21:26:06 +0000772 VersionInfoValue(StringRef InfoKey, std::vector<IntOrString> &&Vals,
773 std::vector<bool> &&CommasBeforeVals)
774 : Key(InfoKey), Values(std::move(Vals)),
775 HasPrecedingComma(std::move(CommasBeforeVals)) {}
Marek Sokolowski86b61382017-09-28 22:41:38 +0000776 raw_ostream &log(raw_ostream &) const override;
Zachary Turner93bb30d2017-10-06 21:26:06 +0000777
778 StmtKind getKind() const override { return StValue; }
779 static bool classof(const VersionInfoStmt *S) {
780 return S->getKind() == StValue;
781 }
Marek Sokolowski86b61382017-09-28 22:41:38 +0000782};
783
784class VersionInfoResource : public RCResource {
785public:
786 // A class listing fixed VERSIONINFO statements (occuring before main BEGIN).
787 // If any of these is not specified, it is assumed by the original tool to
788 // be equal to 0.
789 class VersionInfoFixed {
790 public:
791 enum VersionInfoFixedType {
792 FtUnknown,
793 FtFileVersion,
794 FtProductVersion,
795 FtFileFlagsMask,
796 FtFileFlags,
797 FtFileOS,
798 FtFileType,
799 FtFileSubtype,
800 FtNumTypes
801 };
802
803 private:
804 static const StringMap<VersionInfoFixedType> FixedFieldsInfoMap;
805 static const StringRef FixedFieldsNames[FtNumTypes];
806
807 public:
808 SmallVector<uint32_t, 4> FixedInfo[FtNumTypes];
809 SmallVector<bool, FtNumTypes> IsTypePresent;
810
811 static VersionInfoFixedType getFixedType(StringRef Type);
812 static bool isTypeSupported(VersionInfoFixedType Type);
813 static bool isVersionType(VersionInfoFixedType Type);
814
815 VersionInfoFixed() : IsTypePresent(FtNumTypes, false) {}
816
817 void setValue(VersionInfoFixedType Type, ArrayRef<uint32_t> Value) {
818 FixedInfo[Type] = SmallVector<uint32_t, 4>(Value.begin(), Value.end());
819 IsTypePresent[Type] = true;
820 }
821
822 raw_ostream &log(raw_ostream &) const;
823 };
824
Marek Sokolowski86b61382017-09-28 22:41:38 +0000825 VersionInfoBlock MainBlock;
826 VersionInfoFixed FixedData;
827
Marek Sokolowski86b61382017-09-28 22:41:38 +0000828 VersionInfoResource(VersionInfoBlock &&TopLevelBlock,
Martin Storsjo370633f2018-05-15 06:35:29 +0000829 VersionInfoFixed &&FixedInfo, uint16_t Flags)
830 : RCResource(Flags), MainBlock(std::move(TopLevelBlock)),
831 FixedData(std::move(FixedInfo)) {}
Marek Sokolowski86b61382017-09-28 22:41:38 +0000832
833 raw_ostream &log(raw_ostream &) const override;
Zachary Turner93bb30d2017-10-06 21:26:06 +0000834 IntOrString getResourceType() const override { return RkVersionInfo; }
Martin Storsjo370633f2018-05-15 06:35:29 +0000835 static uint16_t getDefaultMemoryFlags() { return MfMoveable | MfPure; }
Zachary Turner93bb30d2017-10-06 21:26:06 +0000836 Twine getResourceTypeName() const override { return "VERSIONINFO"; }
837 Error visit(Visitor *V) const override {
838 return V->visitVersionInfoResource(this);
839 }
840 ResourceKind getKind() const override { return RkVersionInfo; }
841 static bool classof(const RCResource *Res) {
842 return Res->getKind() == RkVersionInfo;
843 }
Marek Sokolowski86b61382017-09-28 22:41:38 +0000844};
845
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000846// CHARACTERISTICS optional statement.
847//
848// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380872(v=vs.85).aspx
849class CharacteristicsStmt : public OptionalStmt {
Marek Sokolowskib121e772017-09-29 19:07:44 +0000850public:
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000851 uint32_t Value;
852
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000853 CharacteristicsStmt(uint32_t Characteristic) : Value(Characteristic) {}
854 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowskib121e772017-09-29 19:07:44 +0000855
856 Twine getResourceTypeName() const override { return "CHARACTERISTICS"; }
857 Error visit(Visitor *V) const override {
858 return V->visitCharacteristicsStmt(this);
859 }
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000860};
861
862// VERSION optional statement.
863//
864// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381059(v=vs.85).aspx
865class VersionStmt : public OptionalStmt {
Marek Sokolowskib121e772017-09-29 19:07:44 +0000866public:
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000867 uint32_t Value;
868
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000869 VersionStmt(uint32_t Version) : Value(Version) {}
870 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowskib121e772017-09-29 19:07:44 +0000871
872 Twine getResourceTypeName() const override { return "VERSION"; }
873 Error visit(Visitor *V) const override { return V->visitVersionStmt(this); }
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000874};
875
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000876// CAPTION optional statement.
877//
878// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx
879class CaptionStmt : public OptionalStmt {
Zachary Turner44bde8d2017-10-06 20:51:20 +0000880public:
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000881 StringRef Value;
882
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000883 CaptionStmt(StringRef Caption) : Value(Caption) {}
884 raw_ostream &log(raw_ostream &) const override;
Zachary Turner44bde8d2017-10-06 20:51:20 +0000885 Twine getResourceTypeName() const override { return "CAPTION"; }
886 Error visit(Visitor *V) const override { return V->visitCaptionStmt(this); }
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000887};
888
889// FONT optional statement.
890// Note that the documentation is inaccurate: it expects five arguments to be
891// given, however the example provides only two. In fact, the original tool
892// expects two arguments - point size and name of the typeface.
893//
894// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381013(v=vs.85).aspx
895class FontStmt : public OptionalStmt {
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000896public:
Zachary Turner44bde8d2017-10-06 20:51:20 +0000897 uint32_t Size, Weight, Charset;
898 StringRef Name;
899 bool Italic;
900
901 FontStmt(uint32_t FontSize, StringRef FontName, uint32_t FontWeight,
902 bool FontItalic, uint32_t FontCharset)
903 : Size(FontSize), Weight(FontWeight), Charset(FontCharset),
904 Name(FontName), Italic(FontItalic) {}
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000905 raw_ostream &log(raw_ostream &) const override;
Zachary Turner44bde8d2017-10-06 20:51:20 +0000906 Twine getResourceTypeName() const override { return "FONT"; }
907 Error visit(Visitor *V) const override { return V->visitFontStmt(this); }
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000908};
909
910// STYLE optional statement.
911//
912// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx
913class StyleStmt : public OptionalStmt {
Zachary Turner44bde8d2017-10-06 20:51:20 +0000914public:
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000915 uint32_t Value;
916
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000917 StyleStmt(uint32_t Style) : Value(Style) {}
918 raw_ostream &log(raw_ostream &) const override;
Zachary Turner44bde8d2017-10-06 20:51:20 +0000919 Twine getResourceTypeName() const override { return "STYLE"; }
920 Error visit(Visitor *V) const override { return V->visitStyleStmt(this); }
Marek Sokolowski7ca5fcc2017-08-29 16:49:59 +0000921};
922
Martin Storsjocec32ed2018-11-29 12:17:39 +0000923// EXSTYLE optional statement.
924//
925// Ref: docs.microsoft.com/en-us/windows/desktop/menurc/exstyle-statement
926class ExStyleStmt : public OptionalStmt {
927public:
928 uint32_t Value;
929
930 ExStyleStmt(uint32_t ExStyle) : Value(ExStyle) {}
931 raw_ostream &log(raw_ostream &) const override;
932 Twine getResourceTypeName() const override { return "EXSTYLE"; }
933 Error visit(Visitor *V) const override { return V->visitExStyleStmt(this); }
934};
935
Martin Storsjo65de7bd2018-05-15 19:21:28 +0000936// CLASS optional statement.
937//
938// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380883(v=vs.85).aspx
939class ClassStmt : public OptionalStmt {
940public:
941 IntOrString Value;
942
943 ClassStmt(IntOrString Class) : Value(Class) {}
944 raw_ostream &log(raw_ostream &) const override;
945 Twine getResourceTypeName() const override { return "CLASS"; }
946 Error visit(Visitor *V) const override { return V->visitClassStmt(this); }
947};
948
Marek Sokolowski0b33df92017-08-18 18:24:17 +0000949} // namespace rc
950} // namespace llvm
951
952#endif