summaryrefslogtreecommitdiff
path: root/tools/llvm-rc
diff options
context:
space:
mode:
authorMarek Sokolowski <mnbvmar@gmail.com>2017-09-29 22:25:05 +0000
committerMarek Sokolowski <mnbvmar@gmail.com>2017-09-29 22:25:05 +0000
commitea529937cede4029b2145fdccd82f22dd3b0c24a (patch)
tree4977a27ac655efd0cfcc68cc55839b5454fa93cf /tools/llvm-rc
parent9e5998cdf769181e4977d0a8e9e535c55ca1de7c (diff)
[llvm-rc] Serialize MENU resources to .res files (serialization, pt 3).
This allows MENU resources to be serialized. MENU resource statement doc: msdn.microsoft.com/en-us/library/windows/desktop/aa381025.aspx POPUP sub-statement doc: msdn.microsoft.com/en-us/library/windows/desktop/aa381030.aspx MENUITEM sub-statement doc: msdn.microsoft.com/en-us/library/windows/desktop/aa381024.aspx MENUHEADER structure: msdn.microsoft.com/en-us/library/windows/desktop/ms648018.aspx (and NORMALMENUITEM, POPUPMENUITEM structs). Thanks for Nico Weber for his original work in this area. Differential Revision: https://reviews.llvm.org/D37828 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@314562 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-rc')
-rw-r--r--tools/llvm-rc/ResourceFileWriter.cpp54
-rw-r--r--tools/llvm-rc/ResourceFileWriter.h7
-rw-r--r--tools/llvm-rc/ResourceScriptStmt.h40
-rw-r--r--tools/llvm-rc/ResourceVisitor.h1
4 files changed, 98 insertions, 4 deletions
diff --git a/tools/llvm-rc/ResourceFileWriter.cpp b/tools/llvm-rc/ResourceFileWriter.cpp
index f8ba2a7694a..af002e347be 100644
--- a/tools/llvm-rc/ResourceFileWriter.cpp
+++ b/tools/llvm-rc/ResourceFileWriter.cpp
@@ -205,6 +205,10 @@ Error ResourceFileWriter::visitHTMLResource(const RCResource *Res) {
return writeResource(Res, &ResourceFileWriter::writeHTMLBody);
}
+Error ResourceFileWriter::visitMenuResource(const RCResource *Res) {
+ return writeResource(Res, &ResourceFileWriter::writeMenuBody);
+}
+
Error ResourceFileWriter::visitCharacteristicsStmt(
const CharacteristicsStmt *Stmt) {
ObjectData.Characteristics = Stmt->Value;
@@ -382,5 +386,55 @@ Error ResourceFileWriter::writeHTMLBody(const RCResource *Base) {
return appendFile(cast<HTMLResource>(Base)->HTMLLoc);
}
+// --- MenuResource helpers. --- //
+
+Error ResourceFileWriter::writeMenuDefinition(
+ const std::unique_ptr<MenuDefinition> &Def, uint16_t Flags) {
+ assert(Def);
+ const MenuDefinition *DefPtr = Def.get();
+
+ if (auto *MenuItemPtr = dyn_cast<MenuItem>(DefPtr)) {
+ writeInt<uint16_t>(Flags);
+ RETURN_IF_ERROR(
+ checkNumberFits<uint16_t>(MenuItemPtr->Id, "MENUITEM action ID"));
+ writeInt<uint16_t>(MenuItemPtr->Id);
+ RETURN_IF_ERROR(writeCString(MenuItemPtr->Name));
+ return Error::success();
+ }
+
+ if (isa<MenuSeparator>(DefPtr)) {
+ writeInt<uint16_t>(Flags);
+ writeInt<uint32_t>(0);
+ return Error::success();
+ }
+
+ auto *PopupPtr = cast<PopupItem>(DefPtr);
+ writeInt<uint16_t>(Flags);
+ RETURN_IF_ERROR(writeCString(PopupPtr->Name));
+ return writeMenuDefinitionList(PopupPtr->SubItems);
+}
+
+Error ResourceFileWriter::writeMenuDefinitionList(
+ const MenuDefinitionList &List) {
+ for (auto &Def : List.Definitions) {
+ uint16_t Flags = Def->getResFlags();
+ // Last element receives an additional 0x80 flag.
+ const uint16_t LastElementFlag = 0x0080;
+ if (&Def == &List.Definitions.back())
+ Flags |= LastElementFlag;
+
+ RETURN_IF_ERROR(writeMenuDefinition(Def, Flags));
+ }
+ return Error::success();
+}
+
+Error ResourceFileWriter::writeMenuBody(const RCResource *Base) {
+ // At first, MENUHEADER structure. In fact, these are two WORDs equal to 0.
+ // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648018.aspx
+ writeObject<uint32_t>(0);
+
+ return writeMenuDefinitionList(cast<MenuResource>(Base)->Elements);
+}
+
} // namespace rc
} // namespace llvm
diff --git a/tools/llvm-rc/ResourceFileWriter.h b/tools/llvm-rc/ResourceFileWriter.h
index ce730d20eed..ef736baa169 100644
--- a/tools/llvm-rc/ResourceFileWriter.h
+++ b/tools/llvm-rc/ResourceFileWriter.h
@@ -32,6 +32,7 @@ public:
Error visitNullResource(const RCResource *) override;
Error visitAcceleratorsResource(const RCResource *) override;
Error visitHTMLResource(const RCResource *) override;
+ Error visitMenuResource(const RCResource *) override;
Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;
Error visitLanguageStmt(const LanguageResource *) override;
@@ -63,6 +64,12 @@ private:
// HTMLResource
Error writeHTMLBody(const RCResource *);
+ // MenuResource
+ Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &,
+ uint16_t Flags);
+ Error writeMenuDefinitionList(const MenuDefinitionList &List);
+ Error writeMenuBody(const RCResource *);
+
// Output stream handling.
std::unique_ptr<raw_fd_ostream> FS;
diff --git a/tools/llvm-rc/ResourceScriptStmt.h b/tools/llvm-rc/ResourceScriptStmt.h
index 6f83d722d24..d00e178426d 100644
--- a/tools/llvm-rc/ResourceScriptStmt.h
+++ b/tools/llvm-rc/ResourceScriptStmt.h
@@ -315,6 +315,8 @@ public:
MENUBREAK = 0x0040
};
+ enum MenuDefKind { MkBase, MkSeparator, MkMenuItem, MkPopup };
+
static constexpr size_t NumFlags = 6;
static StringRef OptionsStr[NumFlags];
static uint32_t OptionsFlags[NumFlags];
@@ -323,13 +325,16 @@ public:
return OS << "Base menu definition\n";
}
virtual ~MenuDefinition() {}
+
+ virtual uint16_t getResFlags() const { return 0; }
+ virtual MenuDefKind getKind() const { return MkBase; }
};
// Recursive description of a whole submenu.
class MenuDefinitionList : public MenuDefinition {
+public:
std::vector<std::unique_ptr<MenuDefinition>> Definitions;
-public:
void addDefinition(std::unique_ptr<MenuDefinition> Def) {
Definitions.push_back(std::move(Def));
}
@@ -342,46 +347,73 @@ public:
class MenuSeparator : public MenuDefinition {
public:
raw_ostream &log(raw_ostream &) const override;
+
+ MenuDefKind getKind() const override { return MkSeparator; }
+ static bool classof(const MenuDefinition *D) {
+ return D->getKind() == MkSeparator;
+ }
};
// MENUITEM statement definition.
//
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
class MenuItem : public MenuDefinition {
+public:
StringRef Name;
uint32_t Id;
uint16_t Flags;
-public:
MenuItem(StringRef Caption, uint32_t ItemId, uint16_t ItemFlags)
: Name(Caption), Id(ItemId), Flags(ItemFlags) {}
raw_ostream &log(raw_ostream &) const override;
+
+ uint16_t getResFlags() const override { return Flags; }
+ MenuDefKind getKind() const override { return MkMenuItem; }
+ static bool classof(const MenuDefinition *D) {
+ return D->getKind() == MkMenuItem;
+ }
};
// POPUP statement definition.
//
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx
class PopupItem : public MenuDefinition {
+public:
StringRef Name;
uint16_t Flags;
MenuDefinitionList SubItems;
-public:
PopupItem(StringRef Caption, uint16_t ItemFlags,
MenuDefinitionList &&SubItemsList)
: Name(Caption), Flags(ItemFlags), SubItems(std::move(SubItemsList)) {}
raw_ostream &log(raw_ostream &) const override;
+
+ // This has an additional (0x10) flag. It doesn't match with documented
+ // 0x01 flag, though.
+ uint16_t getResFlags() const override { return Flags | 0x10; }
+ MenuDefKind getKind() const override { return MkPopup; }
+ static bool classof(const MenuDefinition *D) {
+ return D->getKind() == MkPopup;
+ }
};
// Menu resource definition.
class MenuResource : public OptStatementsRCResource {
+public:
MenuDefinitionList Elements;
-public:
MenuResource(OptionalStmtList &&OptStmts, MenuDefinitionList &&Items)
: OptStatementsRCResource(std::move(OptStmts)),
Elements(std::move(Items)) {}
raw_ostream &log(raw_ostream &) const override;
+
+ IntOrString getResourceType() const override { return RkMenu; }
+ Twine getResourceTypeName() const override { return "MENU"; }
+ Error visit(Visitor *V) const override { return V->visitMenuResource(this); }
+ ResourceKind getKind() const override { return RkMenu; }
+ static bool classof(const RCResource *Res) {
+ return Res->getKind() == RkMenu;
+ }
};
// STRINGTABLE resource. Contains a list of strings, each having its unique ID.
diff --git a/tools/llvm-rc/ResourceVisitor.h b/tools/llvm-rc/ResourceVisitor.h
index 358a31c875c..14992dac5af 100644
--- a/tools/llvm-rc/ResourceVisitor.h
+++ b/tools/llvm-rc/ResourceVisitor.h
@@ -30,6 +30,7 @@ public:
virtual Error visitNullResource(const RCResource *) = 0;
virtual Error visitAcceleratorsResource(const RCResource *) = 0;
virtual Error visitHTMLResource(const RCResource *) = 0;
+ virtual Error visitMenuResource(const RCResource *) = 0;
virtual Error visitCharacteristicsStmt(const CharacteristicsStmt *) = 0;
virtual Error visitLanguageStmt(const LanguageResource *) = 0;