blob: 908232940a5d364dbd978348300927ba25cbcb56 [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
25// A class holding a name - either an integer or a reference to the string.
26class IntOrString {
27private:
28 union Data {
29 uint32_t Int;
30 StringRef String;
31 Data(uint32_t Value) : Int(Value) {}
32 Data(const StringRef Value) : String(Value) {}
Marek Sokolowski7f110522017-08-28 22:58:31 +000033 Data(const RCToken &Token) {
34 if (Token.kind() == RCToken::Kind::Int)
35 Int = Token.intValue();
36 else
37 String = Token.value();
38 }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +000039 } Data;
40 bool IsInt;
41
42public:
43 IntOrString() : IntOrString(0) {}
44 IntOrString(uint32_t Value) : Data(Value), IsInt(1) {}
45 IntOrString(StringRef Value) : Data(Value), IsInt(0) {}
46 IntOrString(const RCToken &Token)
47 : Data(Token), IsInt(Token.kind() == RCToken::Kind::Int) {}
48
49 bool equalsLower(const char *Str) {
50 return !IsInt && Data.String.equals_lower(Str);
51 }
52
Marek Sokolowski8f193432017-09-29 17:14:09 +000053 bool isInt() const { return IsInt; }
54
55 uint32_t getInt() const {
56 assert(IsInt);
57 return Data.Int;
58 }
59
60 const StringRef &getString() const {
61 assert(!IsInt);
62 return Data.String;
63 }
64
65 operator Twine() const {
66 return isInt() ? Twine(getInt()) : Twine(getString());
67 }
68
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +000069 friend raw_ostream &operator<<(raw_ostream &, const IntOrString &);
70};
71
Marek Sokolowski8f193432017-09-29 17:14:09 +000072enum ResourceKind {
73 // These resource kinds have corresponding .res resource type IDs
74 // (TYPE in RESOURCEHEADER structure). The numeric value assigned to each
75 // kind is equal to this type ID.
76 RkNull = 0,
77 RkMenu = 4,
78 RkDialog = 5,
79 RkAccelerators = 9,
80 RkVersionInfo = 16,
81 RkHTML = 23,
82
83 // These kinds don't have assigned type IDs (they might be the resources
84 // of invalid kind, expand to many resource structures in .res files,
85 // or have variable type ID). In order to avoid ID clashes with IDs above,
86 // we assign the kinds the values 256 and larger.
87 RkInvalid = 256,
88 RkBase,
89 RkCursor,
90 RkIcon,
91 RkUser
92};
93
94// Non-zero memory flags.
95// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648027(v=vs.85).aspx
96enum MemoryFlags {
97 MfMoveable = 0x10,
98 MfPure = 0x20,
99 MfPreload = 0x40,
100 MfDiscardable = 0x1000
101};
102
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000103// Base resource. All the resources should derive from this base.
104class RCResource {
Marek Sokolowski8f193432017-09-29 17:14:09 +0000105public:
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000106 IntOrString ResName;
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000107 void setName(const IntOrString &Name) { ResName = Name; }
108 virtual raw_ostream &log(raw_ostream &OS) const {
109 return OS << "Base statement\n";
110 };
111 virtual ~RCResource() {}
Marek Sokolowski8f193432017-09-29 17:14:09 +0000112
113 virtual Error visit(Visitor *) const {
114 llvm_unreachable("This is unable to call methods from Visitor base");
115 }
116
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000117 // Apply the statements attached to this resource. Generic resources
118 // don't have any.
119 virtual Error applyStmts(Visitor *) const { return Error::success(); }
120
Marek Sokolowski8f193432017-09-29 17:14:09 +0000121 // By default, memory flags are DISCARDABLE | PURE | MOVEABLE.
122 virtual uint16_t getMemoryFlags() const {
123 return MfDiscardable | MfPure | MfMoveable;
124 }
125 virtual ResourceKind getKind() const { return RkBase; }
126 static bool classof(const RCResource *Res) { return true; }
127
128 virtual IntOrString getResourceType() const {
129 llvm_unreachable("This cannot be called on objects without types.");
130 }
131 virtual Twine getResourceTypeName() const {
132 llvm_unreachable("This cannot be called on objects without types.");
133 };
134};
135
136// An empty resource. It has no content, type 0, ID 0 and all of its
137// characteristics are equal to 0.
138class NullResource : public RCResource {
139public:
140 raw_ostream &log(raw_ostream &OS) const override {
141 return OS << "Null resource\n";
142 }
143 Error visit(Visitor *V) const override { return V->visitNullResource(this); }
144 IntOrString getResourceType() const override { return 0; }
145 Twine getResourceTypeName() const override { return "(NULL)"; }
146 uint16_t getMemoryFlags() const override { return 0; }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000147};
148
149// Optional statement base. All such statements should derive from this base.
150class OptionalStmt : public RCResource {};
151
152class OptionalStmtList : public OptionalStmt {
153 std::vector<std::unique_ptr<OptionalStmt>> Statements;
154
155public:
156 OptionalStmtList() {}
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000157 raw_ostream &log(raw_ostream &OS) const override;
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000158
159 void addStmt(std::unique_ptr<OptionalStmt> Stmt) {
160 Statements.push_back(std::move(Stmt));
161 }
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000162
163 Error visit(Visitor *V) const override {
164 for (auto &StmtPtr : Statements)
165 if (auto Err = StmtPtr->visit(V))
166 return Err;
167 return Error::success();
168 }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000169};
170
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000171class OptStatementsRCResource : public RCResource {
172public:
173 std::unique_ptr<OptionalStmtList> OptStatements;
174
175 OptStatementsRCResource(OptionalStmtList &&Stmts)
176 : OptStatements(llvm::make_unique<OptionalStmtList>(std::move(Stmts))) {}
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000177
178 virtual Error applyStmts(Visitor *V) const { return OptStatements->visit(V); }
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000179};
180
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000181// LANGUAGE statement. It can occur both as a top-level statement (in such
182// a situation, it changes the default language until the end of the file)
183// and as an optional resource statement (then it changes the language
184// of a single resource).
185//
186// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381019(v=vs.85).aspx
187class LanguageResource : public OptionalStmt {
Marek Sokolowski8f193432017-09-29 17:14:09 +0000188public:
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000189 uint32_t Lang, SubLang;
190
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000191 LanguageResource(uint32_t LangId, uint32_t SubLangId)
192 : Lang(LangId), SubLang(SubLangId) {}
193 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski8f193432017-09-29 17:14:09 +0000194
195 // This is not a regular top-level statement; when it occurs, it just
196 // modifies the language context.
197 Error visit(Visitor *V) const override { return V->visitLanguageStmt(this); }
198 Twine getResourceTypeName() const override { return "LANGUAGE"; }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000199};
200
Marek Sokolowski7f110522017-08-28 22:58:31 +0000201// ACCELERATORS resource. Defines a named table of accelerators for the app.
202//
203// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380610(v=vs.85).aspx
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000204class AcceleratorsResource : public OptStatementsRCResource {
Marek Sokolowski7f110522017-08-28 22:58:31 +0000205public:
206 class Accelerator {
207 public:
208 IntOrString Event;
209 uint32_t Id;
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000210 uint16_t Flags;
Marek Sokolowski7f110522017-08-28 22:58:31 +0000211
212 enum Options {
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000213 // This is actually 0x0000 (accelerator is assumed to be ASCII if it's
214 // not VIRTKEY). However, rc.exe behavior is different in situations
215 // "only ASCII defined" and "neither ASCII nor VIRTKEY defined".
216 // Therefore, we include ASCII as another flag. This must be zeroed
217 // when serialized.
218 ASCII = 0x8000,
219 VIRTKEY = 0x0001,
220 NOINVERT = 0x0002,
221 ALT = 0x0010,
222 SHIFT = 0x0004,
223 CONTROL = 0x0008
Marek Sokolowski7f110522017-08-28 22:58:31 +0000224 };
225
226 static constexpr size_t NumFlags = 6;
227 static StringRef OptionsStr[NumFlags];
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000228 static uint32_t OptionsFlags[NumFlags];
Marek Sokolowski7f110522017-08-28 22:58:31 +0000229 };
230
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000231 std::vector<Accelerator> Accelerators;
232
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000233 using OptStatementsRCResource::OptStatementsRCResource;
234 void addAccelerator(IntOrString Event, uint32_t Id, uint16_t Flags) {
Marek Sokolowski7f110522017-08-28 22:58:31 +0000235 Accelerators.push_back(Accelerator{Event, Id, Flags});
236 }
237 raw_ostream &log(raw_ostream &) const override;
238
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000239 IntOrString getResourceType() const override { return RkAccelerators; }
240 uint16_t getMemoryFlags() const override {
241 return MfPure | MfMoveable;
242 }
243 Twine getResourceTypeName() const override { return "ACCELERATORS"; }
244
245 Error visit(Visitor *V) const override {
246 return V->visitAcceleratorsResource(this);
247 }
248 ResourceKind getKind() const override { return RkAccelerators; }
249 static bool classof(const RCResource *Res) {
250 return Res->getKind() == RkAccelerators;
251 }
Marek Sokolowski7f110522017-08-28 22:58:31 +0000252};
253
Marek Sokolowski72aa9372017-08-28 21:59:54 +0000254// CURSOR resource. Represents a single cursor (".cur") file.
255//
256// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380920(v=vs.85).aspx
257class CursorResource : public RCResource {
258 StringRef CursorLoc;
259
260public:
261 CursorResource(StringRef Location) : CursorLoc(Location) {}
262 raw_ostream &log(raw_ostream &) const override;
263};
264
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000265// ICON resource. Represents a single ".ico" file containing a group of icons.
266//
267// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381018(v=vs.85).aspx
268class IconResource : public RCResource {
269 StringRef IconLoc;
270
271public:
272 IconResource(StringRef Location) : IconLoc(Location) {}
273 raw_ostream &log(raw_ostream &) const override;
274};
275
Marek Sokolowski72aa9372017-08-28 21:59:54 +0000276// HTML resource. Represents a local webpage that is to be embedded into the
277// resulting resource file. It embeds a file only - no additional resources
278// (images etc.) are included with this resource.
279//
280// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa966018(v=vs.85).aspx
281class HTMLResource : public RCResource {
Marek Sokolowski8f193432017-09-29 17:14:09 +0000282public:
Marek Sokolowski72aa9372017-08-28 21:59:54 +0000283 StringRef HTMLLoc;
284
Marek Sokolowski72aa9372017-08-28 21:59:54 +0000285 HTMLResource(StringRef Location) : HTMLLoc(Location) {}
286 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski8f193432017-09-29 17:14:09 +0000287
288 Error visit(Visitor *V) const override { return V->visitHTMLResource(this); }
289
290 // Curiously, file resources don't have DISCARDABLE flag set.
291 uint16_t getMemoryFlags() const override { return MfPure | MfMoveable; }
292 IntOrString getResourceType() const override { return RkHTML; }
293 Twine getResourceTypeName() const override { return "HTML"; }
294 ResourceKind getKind() const override { return RkHTML; }
295 static bool classof(const RCResource *Res) {
296 return Res->getKind() == RkHTML;
297 }
Marek Sokolowski72aa9372017-08-28 21:59:54 +0000298};
299
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000300// -- MENU resource and its helper classes --
301// This resource describes the contents of an application menu
302// (usually located in the upper part of the dialog.)
303//
304// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381025(v=vs.85).aspx
305
306// Description of a single submenu item.
307class MenuDefinition {
308public:
309 enum Options {
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000310 CHECKED = 0x0008,
311 GRAYED = 0x0001,
312 HELP = 0x4000,
313 INACTIVE = 0x0002,
314 MENUBARBREAK = 0x0020,
315 MENUBREAK = 0x0040
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000316 };
317
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000318 enum MenuDefKind { MkBase, MkSeparator, MkMenuItem, MkPopup };
319
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000320 static constexpr size_t NumFlags = 6;
321 static StringRef OptionsStr[NumFlags];
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000322 static uint32_t OptionsFlags[NumFlags];
323 static raw_ostream &logFlags(raw_ostream &, uint16_t Flags);
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000324 virtual raw_ostream &log(raw_ostream &OS) const {
325 return OS << "Base menu definition\n";
326 }
327 virtual ~MenuDefinition() {}
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000328
329 virtual uint16_t getResFlags() const { return 0; }
330 virtual MenuDefKind getKind() const { return MkBase; }
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000331};
332
333// Recursive description of a whole submenu.
334class MenuDefinitionList : public MenuDefinition {
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000335public:
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000336 std::vector<std::unique_ptr<MenuDefinition>> Definitions;
337
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000338 void addDefinition(std::unique_ptr<MenuDefinition> Def) {
339 Definitions.push_back(std::move(Def));
340 }
341 raw_ostream &log(raw_ostream &) const override;
342};
343
344// Separator in MENU definition (MENUITEM SEPARATOR).
345//
346// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
347class MenuSeparator : public MenuDefinition {
348public:
349 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000350
351 MenuDefKind getKind() const override { return MkSeparator; }
352 static bool classof(const MenuDefinition *D) {
353 return D->getKind() == MkSeparator;
354 }
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000355};
356
357// MENUITEM statement definition.
358//
359// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
360class MenuItem : public MenuDefinition {
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000361public:
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000362 StringRef Name;
363 uint32_t Id;
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000364 uint16_t Flags;
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000365
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000366 MenuItem(StringRef Caption, uint32_t ItemId, uint16_t ItemFlags)
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000367 : Name(Caption), Id(ItemId), Flags(ItemFlags) {}
368 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000369
370 uint16_t getResFlags() const override { return Flags; }
371 MenuDefKind getKind() const override { return MkMenuItem; }
372 static bool classof(const MenuDefinition *D) {
373 return D->getKind() == MkMenuItem;
374 }
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000375};
376
377// POPUP statement definition.
378//
379// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx
380class PopupItem : public MenuDefinition {
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000381public:
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000382 StringRef Name;
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000383 uint16_t Flags;
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000384 MenuDefinitionList SubItems;
385
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000386 PopupItem(StringRef Caption, uint16_t ItemFlags,
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000387 MenuDefinitionList &&SubItemsList)
388 : Name(Caption), Flags(ItemFlags), SubItems(std::move(SubItemsList)) {}
389 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000390
391 // This has an additional (0x10) flag. It doesn't match with documented
392 // 0x01 flag, though.
393 uint16_t getResFlags() const override { return Flags | 0x10; }
394 MenuDefKind getKind() const override { return MkPopup; }
395 static bool classof(const MenuDefinition *D) {
396 return D->getKind() == MkPopup;
397 }
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000398};
399
400// Menu resource definition.
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000401class MenuResource : public OptStatementsRCResource {
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000402public:
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000403 MenuDefinitionList Elements;
404
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000405 MenuResource(OptionalStmtList &&OptStmts, MenuDefinitionList &&Items)
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000406 : OptStatementsRCResource(std::move(OptStmts)),
407 Elements(std::move(Items)) {}
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000408 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000409
410 IntOrString getResourceType() const override { return RkMenu; }
411 Twine getResourceTypeName() const override { return "MENU"; }
412 Error visit(Visitor *V) const override { return V->visitMenuResource(this); }
413 ResourceKind getKind() const override { return RkMenu; }
414 static bool classof(const RCResource *Res) {
415 return Res->getKind() == RkMenu;
416 }
Marek Sokolowski99ecb0e2017-08-28 23:46:30 +0000417};
418
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000419// STRINGTABLE resource. Contains a list of strings, each having its unique ID.
420//
421// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381050(v=vs.85).aspx
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000422class StringTableResource : public OptStatementsRCResource {
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000423 std::vector<std::pair<uint32_t, StringRef>> Table;
424
425public:
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000426 using OptStatementsRCResource::OptStatementsRCResource;
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000427 void addString(uint32_t ID, StringRef String) {
428 Table.emplace_back(ID, String);
429 }
430 raw_ostream &log(raw_ostream &) const override;
431};
432
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000433// -- DIALOG(EX) resource and its helper classes --
434//
435// This resource describes dialog boxes and controls residing inside them.
436//
437// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381003(v=vs.85).aspx
438// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx
439
440// Single control definition.
441class Control {
Marek Sokolowski7f7745c2017-09-30 00:38:52 +0000442public:
443 StringRef Type;
444 IntOrString Title;
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000445 uint32_t ID, X, Y, Width, Height;
446 Optional<uint32_t> Style, ExtStyle, HelpID;
447
Marek Sokolowski7f7745c2017-09-30 00:38:52 +0000448 // Control classes as described in DLGITEMTEMPLATEEX documentation.
449 //
450 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms645389.aspx
451 enum CtlClasses {
452 ClsButton = 0x80,
453 ClsEdit = 0x81,
454 ClsStatic = 0x82,
455 ClsListBox = 0x83,
456 ClsScrollBar = 0x84,
457 ClsComboBox = 0x85
458 };
459
460 // Simple information about a single control type.
461 struct CtlInfo {
462 uint32_t Style;
463 uint16_t CtlClass;
464 bool HasTitle;
465 };
466
467 Control(StringRef CtlType, IntOrString CtlTitle, uint32_t CtlID,
468 uint32_t PosX, uint32_t PosY, uint32_t ItemWidth, uint32_t ItemHeight,
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000469 Optional<uint32_t> ItemStyle, Optional<uint32_t> ExtItemStyle,
470 Optional<uint32_t> CtlHelpID)
471 : Type(CtlType), Title(CtlTitle), ID(CtlID), X(PosX), Y(PosY),
472 Width(ItemWidth), Height(ItemHeight), Style(ItemStyle),
473 ExtStyle(ExtItemStyle), HelpID(CtlHelpID) {}
474
Marek Sokolowski7f7745c2017-09-30 00:38:52 +0000475 static const StringMap<CtlInfo> SupportedCtls;
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000476
477 raw_ostream &log(raw_ostream &) const;
478};
479
480// Single dialog definition. We don't create distinct classes for DIALOG and
481// DIALOGEX because of their being too similar to each other. We only have a
482// flag determining the type of the dialog box.
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000483class DialogResource : public OptStatementsRCResource {
Marek Sokolowski7f7745c2017-09-30 00:38:52 +0000484public:
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000485 uint32_t X, Y, Width, Height, HelpID;
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000486 std::vector<Control> Controls;
487 bool IsExtended;
488
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000489 DialogResource(uint32_t PosX, uint32_t PosY, uint32_t DlgWidth,
490 uint32_t DlgHeight, uint32_t DlgHelpID,
491 OptionalStmtList &&OptStmts, bool IsDialogEx)
Marek Sokolowskic75a0872017-09-29 17:46:32 +0000492 : OptStatementsRCResource(std::move(OptStmts)), X(PosX), Y(PosY),
493 Width(DlgWidth), Height(DlgHeight), HelpID(DlgHelpID),
494 IsExtended(IsDialogEx) {}
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000495
496 void addControl(Control &&Ctl) { Controls.push_back(std::move(Ctl)); }
497
498 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski7f7745c2017-09-30 00:38:52 +0000499
500 // It was a weird design decision to assign the same resource type number
501 // both for DIALOG and DIALOGEX (and the same structure version number).
502 // It makes it possible for DIALOG to be mistaken for DIALOGEX.
503 IntOrString getResourceType() const override { return RkDialog; }
504 Twine getResourceTypeName() const override {
505 return "DIALOG" + Twine(IsExtended ? "EX" : "");
506 }
507 Error visit(Visitor *V) const override {
508 return V->visitDialogResource(this);
509 }
510 ResourceKind getKind() const override { return RkDialog; }
511 static bool classof(const RCResource *Res) {
512 return Res->getKind() == RkDialog;
513 }
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000514};
515
Marek Sokolowskib5f39a02017-09-29 00:14:18 +0000516// User-defined resource. It is either:
517// * a link to the file, e.g. NAME TYPE "filename",
518// * or contains a list of integers and strings, e.g. NAME TYPE {1, "a", 2}.
519class UserDefinedResource : public RCResource {
520 IntOrString Type;
521 StringRef FileLoc;
522 std::vector<IntOrString> Contents;
523 bool IsFileResource;
524
525public:
526 UserDefinedResource(IntOrString ResourceType, StringRef FileLocation)
527 : Type(ResourceType), FileLoc(FileLocation), IsFileResource(true) {}
528 UserDefinedResource(IntOrString ResourceType, std::vector<IntOrString> &&Data)
529 : Type(ResourceType), Contents(std::move(Data)), IsFileResource(false) {}
530
531 raw_ostream &log(raw_ostream &) const override;
532};
533
Marek Sokolowskifb74cb12017-09-28 22:41:38 +0000534// -- VERSIONINFO resource and its helper classes --
535//
536// This resource lists the version information on the executable/library.
537// The declaration consists of the following items:
538// * A number of fixed optional version statements (e.g. FILEVERSION, FILEOS)
539// * BEGIN
540// * A number of BLOCK and/or VALUE statements. BLOCK recursively defines
541// another block of version information, whereas VALUE defines a
542// key -> value correspondence. There might be more than one value
543// corresponding to the single key.
544// * END
545//
546// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381058(v=vs.85).aspx
547
548// A single VERSIONINFO statement;
549class VersionInfoStmt {
550public:
551 virtual raw_ostream &log(raw_ostream &OS) const { return OS << "VI stmt\n"; }
552 virtual ~VersionInfoStmt() {}
553};
554
555// BLOCK definition; also the main VERSIONINFO declaration is considered a
556// BLOCK, although it has no name.
557// The correct top-level blocks are "VarFileInfo" and "StringFileInfo". We don't
558// care about them at the parsing phase.
559class VersionInfoBlock : public VersionInfoStmt {
560 std::vector<std::unique_ptr<VersionInfoStmt>> Stmts;
561 StringRef Name;
562
563public:
564 VersionInfoBlock(StringRef BlockName) : Name(BlockName) {}
565 void addStmt(std::unique_ptr<VersionInfoStmt> Stmt) {
566 Stmts.push_back(std::move(Stmt));
567 }
568 raw_ostream &log(raw_ostream &) const override;
569};
570
571class VersionInfoValue : public VersionInfoStmt {
572 StringRef Key;
573 std::vector<IntOrString> Values;
574
575public:
576 VersionInfoValue(StringRef InfoKey, std::vector<IntOrString> &&Vals)
577 : Key(InfoKey), Values(std::move(Vals)) {}
578 raw_ostream &log(raw_ostream &) const override;
579};
580
581class VersionInfoResource : public RCResource {
582public:
583 // A class listing fixed VERSIONINFO statements (occuring before main BEGIN).
584 // If any of these is not specified, it is assumed by the original tool to
585 // be equal to 0.
586 class VersionInfoFixed {
587 public:
588 enum VersionInfoFixedType {
589 FtUnknown,
590 FtFileVersion,
591 FtProductVersion,
592 FtFileFlagsMask,
593 FtFileFlags,
594 FtFileOS,
595 FtFileType,
596 FtFileSubtype,
597 FtNumTypes
598 };
599
600 private:
601 static const StringMap<VersionInfoFixedType> FixedFieldsInfoMap;
602 static const StringRef FixedFieldsNames[FtNumTypes];
603
604 public:
605 SmallVector<uint32_t, 4> FixedInfo[FtNumTypes];
606 SmallVector<bool, FtNumTypes> IsTypePresent;
607
608 static VersionInfoFixedType getFixedType(StringRef Type);
609 static bool isTypeSupported(VersionInfoFixedType Type);
610 static bool isVersionType(VersionInfoFixedType Type);
611
612 VersionInfoFixed() : IsTypePresent(FtNumTypes, false) {}
613
614 void setValue(VersionInfoFixedType Type, ArrayRef<uint32_t> Value) {
615 FixedInfo[Type] = SmallVector<uint32_t, 4>(Value.begin(), Value.end());
616 IsTypePresent[Type] = true;
617 }
618
619 raw_ostream &log(raw_ostream &) const;
620 };
621
622private:
623 VersionInfoBlock MainBlock;
624 VersionInfoFixed FixedData;
625
626public:
627 VersionInfoResource(VersionInfoBlock &&TopLevelBlock,
628 VersionInfoFixed &&FixedInfo)
629 : MainBlock(std::move(TopLevelBlock)), FixedData(std::move(FixedInfo)) {}
630
631 raw_ostream &log(raw_ostream &) const override;
632};
633
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000634// CHARACTERISTICS optional statement.
635//
636// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380872(v=vs.85).aspx
637class CharacteristicsStmt : public OptionalStmt {
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000638public:
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000639 uint32_t Value;
640
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000641 CharacteristicsStmt(uint32_t Characteristic) : Value(Characteristic) {}
642 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000643
644 Twine getResourceTypeName() const override { return "CHARACTERISTICS"; }
645 Error visit(Visitor *V) const override {
646 return V->visitCharacteristicsStmt(this);
647 }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000648};
649
650// VERSION optional statement.
651//
652// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381059(v=vs.85).aspx
653class VersionStmt : public OptionalStmt {
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000654public:
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000655 uint32_t Value;
656
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000657 VersionStmt(uint32_t Version) : Value(Version) {}
658 raw_ostream &log(raw_ostream &) const override;
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000659
660 Twine getResourceTypeName() const override { return "VERSION"; }
661 Error visit(Visitor *V) const override { return V->visitVersionStmt(this); }
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000662};
663
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000664// CAPTION optional statement.
665//
666// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx
667class CaptionStmt : public OptionalStmt {
Zachary Turner420090a2017-10-06 20:51:20 +0000668public:
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000669 StringRef Value;
670
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000671 CaptionStmt(StringRef Caption) : Value(Caption) {}
672 raw_ostream &log(raw_ostream &) const override;
Zachary Turner420090a2017-10-06 20:51:20 +0000673 Twine getResourceTypeName() const override { return "CAPTION"; }
674 Error visit(Visitor *V) const override { return V->visitCaptionStmt(this); }
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000675};
676
677// FONT optional statement.
678// Note that the documentation is inaccurate: it expects five arguments to be
679// given, however the example provides only two. In fact, the original tool
680// expects two arguments - point size and name of the typeface.
681//
682// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381013(v=vs.85).aspx
683class FontStmt : public OptionalStmt {
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000684public:
Zachary Turner420090a2017-10-06 20:51:20 +0000685 uint32_t Size, Weight, Charset;
686 StringRef Name;
687 bool Italic;
688
689 FontStmt(uint32_t FontSize, StringRef FontName, uint32_t FontWeight,
690 bool FontItalic, uint32_t FontCharset)
691 : Size(FontSize), Weight(FontWeight), Charset(FontCharset),
692 Name(FontName), Italic(FontItalic) {}
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000693 raw_ostream &log(raw_ostream &) const override;
Zachary Turner420090a2017-10-06 20:51:20 +0000694 Twine getResourceTypeName() const override { return "FONT"; }
695 Error visit(Visitor *V) const override { return V->visitFontStmt(this); }
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000696};
697
698// STYLE optional statement.
699//
700// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx
701class StyleStmt : public OptionalStmt {
Zachary Turner420090a2017-10-06 20:51:20 +0000702public:
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000703 uint32_t Value;
704
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000705 StyleStmt(uint32_t Style) : Value(Style) {}
706 raw_ostream &log(raw_ostream &) const override;
Zachary Turner420090a2017-10-06 20:51:20 +0000707 Twine getResourceTypeName() const override { return "STYLE"; }
708 Error visit(Visitor *V) const override { return V->visitStyleStmt(this); }
Marek Sokolowski4ac54d92017-08-29 16:49:59 +0000709};
710
Marek Sokolowski5cd3d5c2017-08-18 18:24:17 +0000711} // namespace rc
712} // namespace llvm
713
714#endif