[llvm] r311956 - [llvm-rc] Add MENU parsing ability (parser, pt 4/8).
Marek Sokolowski via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 28 16:46:31 PDT 2017
Author: mnbvmar
Date: Mon Aug 28 16:46:30 2017
New Revision: 311956
URL: http://llvm.org/viewvc/llvm-project?rev=311956&view=rev
Log:
[llvm-rc] Add MENU parsing ability (parser, pt 4/8).
This extends llvm-rc parsing tool by MENU resource
(msdn.microsoft.com/en-us/library/windows/desktop/aa381025(v=vs.85).aspx).
As for now, MENUEX
(msdn.microsoft.com/en-us/library/windows/desktop/aa381023(v=vs.85).aspx)
seems unnecessary.
Thanks for Nico Weber for his original work in this area.
Differential Revision: https://reviews.llvm.org/D36898
Added:
llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-bad-flag.rc
llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-bad-id.rc
llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-missing-block.rc
llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-misspelled-separator.rc
Modified:
llvm/trunk/test/tools/llvm-rc/Inputs/parser-correct-everything.rc
llvm/trunk/test/tools/llvm-rc/parser.test
llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp
llvm/trunk/tools/llvm-rc/ResourceScriptParser.h
llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp
llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h
Modified: llvm/trunk/test/tools/llvm-rc/Inputs/parser-correct-everything.rc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/Inputs/parser-correct-everything.rc?rev=311956&r1=311955&r2=311956&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/Inputs/parser-correct-everything.rc (original)
+++ llvm/trunk/test/tools/llvm-rc/Inputs/parser-correct-everything.rc Mon Aug 28 16:46:30 2017
@@ -29,3 +29,30 @@ LANGUAGE 0, 2
2, 2, CONTROL, VIRTKEY
3, 3, ALT, CONTROL, SHIFT, NOINVERT, ASCII, VIRTKEY
}
+
+LLVMTest MENU
+LANGUAGE 4, 1
+{
+ POPUP "&OneMenu"
+ {
+ POPUP "Menu&1"
+ {
+ MENUITEM "Item&1", 301, MENUBREAK, CHECKED
+ MENUITEM "Item&2", 302, CHECKED, MENUBARBREAK
+ MENUITEM "Item&3", 303, MENUBREAK, INACTIVE, HELP
+ MENUITEM "Item&4", 304, GRAYED
+ }
+ POPUP "Menu&2"
+ {
+ MENUITEM "&A", 401
+ MENUITEM "&B", 402
+ }
+ }
+ POPUP "&Items"
+ {
+ MENUITEM "&Row", 500
+ MENUITEM "&Column", 501, CHECKED
+ MENUITEM SEPARATOR
+ MENUITEM "&Word", 502
+ }
+}
Added: llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-bad-flag.rc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-bad-flag.rc?rev=311956&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-bad-flag.rc (added)
+++ llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-bad-flag.rc Mon Aug 28 16:46:30 2017
@@ -0,0 +1,3 @@
+1 MENU {
+ MENUITEM "&Item", 500, MENUBREAK, ERRONEOUS, HELP
+}
Added: llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-bad-id.rc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-bad-id.rc?rev=311956&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-bad-id.rc (added)
+++ llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-bad-id.rc Mon Aug 28 16:46:30 2017
@@ -0,0 +1,3 @@
+1 MENU {
+ MENUITEM "Hello", A
+}
Added: llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-missing-block.rc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-missing-block.rc?rev=311956&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-missing-block.rc (added)
+++ llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-missing-block.rc Mon Aug 28 16:46:30 2017
@@ -0,0 +1,4 @@
+1 MENU {
+ POPUP "1"
+ POPUP "2" {}
+}
Added: llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-misspelled-separator.rc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-misspelled-separator.rc?rev=311956&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-misspelled-separator.rc (added)
+++ llvm/trunk/test/tools/llvm-rc/Inputs/parser-menu-misspelled-separator.rc Mon Aug 28 16:46:30 2017
@@ -0,0 +1,3 @@
+1 MENU {
+ MENUITEM NOTSEPARATOR
+}
Modified: llvm/trunk/test/tools/llvm-rc/parser.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/parser.test?rev=311956&r1=311955&r2=311956&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/parser.test (original)
+++ llvm/trunk/test/tools/llvm-rc/parser.test Mon Aug 28 16:46:30 2017
@@ -23,6 +23,32 @@
; PGOOD-NEXT: Accelerator: 1 1 VIRTKEY CONTROL
; PGOOD-NEXT: Accelerator: 2 2 VIRTKEY CONTROL
; PGOOD-NEXT: Accelerator: 3 3 ASCII VIRTKEY NOINVERT ALT SHIFT CONTROL
+; PGOOD-NEXT: Menu (LLVMTest):
+; PGOOD-NEXT: Option: Language: 4, Sublanguage: 1
+; PGOOD-NEXT: Menu list starts
+; PGOOD-NEXT: Popup ("&OneMenu"):
+; PGOOD-NEXT: Menu list starts
+; PGOOD-NEXT: Popup ("Menu&1"):
+; PGOOD-NEXT: Menu list starts
+; PGOOD-NEXT: MenuItem ("Item&1"), ID = 301 CHECKED MENUBREAK
+; PGOOD-NEXT: MenuItem ("Item&2"), ID = 302 CHECKED MENUBARBREAK
+; PGOOD-NEXT: MenuItem ("Item&3"), ID = 303 HELP INACTIVE MENUBREAK
+; PGOOD-NEXT: MenuItem ("Item&4"), ID = 304 GRAYED
+; PGOOD-NEXT: Menu list ends
+; PGOOD-NEXT: Popup ("Menu&2"):
+; PGOOD-NEXT: Menu list starts
+; PGOOD-NEXT: MenuItem ("&A"), ID = 401
+; PGOOD-NEXT: MenuItem ("&B"), ID = 402
+; PGOOD-NEXT: Menu list ends
+; PGOOD-NEXT: Menu list ends
+; PGOOD-NEXT: Popup ("&Items"):
+; PGOOD-NEXT: Menu list starts
+; PGOOD-NEXT: MenuItem ("&Row"), ID = 500
+; PGOOD-NEXT: MenuItem ("&Column"), ID = 501 CHECKED
+; PGOOD-NEXT: Menu separator
+; PGOOD-NEXT: MenuItem ("&Word"), ID = 502
+; PGOOD-NEXT: Menu list ends
+; PGOOD-NEXT: Menu list ends
; RUN: not llvm-rc /V %p/Inputs/parser-stringtable-no-string.rc 2>&1 | FileCheck %s --check-prefix PSTRINGTABLE1
@@ -98,3 +124,23 @@
; RUN: not llvm-rc /V %p/Inputs/parser-accelerators-no-comma-2.rc 2>&1 | FileCheck %s --check-prefix PACCELERATORS4
; PACCELERATORS4: llvm-rc: Error parsing file: expected ',', got 10
+
+
+; RUN: not llvm-rc /V %p/Inputs/parser-menu-bad-id.rc 2>&1 | FileCheck %s --check-prefix PMENU1
+
+; PMENU1: llvm-rc: Error parsing file: expected integer, got A
+
+
+; RUN: not llvm-rc /V %p/Inputs/parser-menu-bad-flag.rc 2>&1 | FileCheck %s --check-prefix PMENU2
+
+; PMENU2: llvm-rc: Error parsing file: expected CHECKED/GRAYED/HELP/INACTIVE/MENUBARBREAK/MENUBREAK, got ERRONEOUS
+
+
+; RUN: not llvm-rc /V %p/Inputs/parser-menu-missing-block.rc 2>&1 | FileCheck %s --check-prefix PMENU3
+
+; PMENU3: llvm-rc: Error parsing file: expected '{', got POPUP
+
+
+; RUN: not llvm-rc /V %p/Inputs/parser-menu-misspelled-separator.rc 2>&1 | FileCheck %s --check-prefix PMENU4
+
+; PMENU4: llvm-rc: Error parsing file: expected SEPARATOR or string, got NOTSEPARATOR
Modified: llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp?rev=311956&r1=311955&r2=311956&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp (original)
+++ llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp Mon Aug 28 16:46:30 2017
@@ -71,6 +71,8 @@ RCParser::ParseType RCParser::parseSingl
Result = parseIconResource();
else if (TypeToken->equalsLower("HTML"))
Result = parseHTMLResource();
+ else if (TypeToken->equalsLower("MENU"))
+ Result = parseMenuResource();
else
return getExpectedError("resource type", /* IsAlreadyRead = */ true);
@@ -285,6 +287,71 @@ RCParser::ParseType RCParser::parseHTMLR
return make_unique<HTMLResource>(*Arg);
}
+RCParser::ParseType RCParser::parseMenuResource() {
+ ASSIGN_OR_RETURN(OptStatements, parseOptionalStatements());
+ ASSIGN_OR_RETURN(Items, parseMenuItemsList());
+ return make_unique<MenuResource>(std::move(*OptStatements),
+ std::move(*Items));
+}
+
+Expected<MenuDefinitionList> RCParser::parseMenuItemsList() {
+ RETURN_IF_ERROR(consumeType(Kind::BlockBegin));
+
+ MenuDefinitionList List;
+
+ // Read a set of items. Each item is of one of three kinds:
+ // MENUITEM SEPARATOR
+ // MENUITEM caption:String, result:Int [, menu flags]...
+ // POPUP caption:String [, menu flags]... { items... }
+ while (!consumeOptionalType(Kind::BlockEnd)) {
+ ASSIGN_OR_RETURN(ItemTypeResult, readIdentifier());
+
+ bool IsMenuItem = ItemTypeResult->equals_lower("MENUITEM");
+ bool IsPopup = ItemTypeResult->equals_lower("POPUP");
+ if (!IsMenuItem && !IsPopup)
+ return getExpectedError("MENUITEM, POPUP, END or '}'", true);
+
+ if (IsMenuItem && isNextTokenKind(Kind::Identifier)) {
+ // Now, expecting SEPARATOR.
+ ASSIGN_OR_RETURN(SeparatorResult, readIdentifier());
+ if (SeparatorResult->equals_lower("SEPARATOR")) {
+ List.addDefinition(make_unique<MenuSeparator>());
+ continue;
+ }
+
+ return getExpectedError("SEPARATOR or string", true);
+ }
+
+ // Not a separator. Read the caption.
+ ASSIGN_OR_RETURN(CaptionResult, readString());
+
+ // If MENUITEM, expect also a comma and an integer.
+ uint32_t MenuResult = -1;
+
+ if (IsMenuItem) {
+ RETURN_IF_ERROR(consumeType(Kind::Comma));
+ ASSIGN_OR_RETURN(IntResult, readInt());
+ MenuResult = *IntResult;
+ }
+
+ ASSIGN_OR_RETURN(FlagsResult, parseFlags(MenuDefinition::OptionsStr));
+
+ if (IsPopup) {
+ // If POPUP, read submenu items recursively.
+ ASSIGN_OR_RETURN(SubMenuResult, parseMenuItemsList());
+ List.addDefinition(make_unique<PopupItem>(*CaptionResult, *FlagsResult,
+ std::move(*SubMenuResult)));
+ continue;
+ }
+
+ assert(IsMenuItem);
+ List.addDefinition(
+ make_unique<MenuItem>(*CaptionResult, MenuResult, *FlagsResult));
+ }
+
+ return std::move(List);
+}
+
RCParser::ParseType RCParser::parseStringTableResource() {
ASSIGN_OR_RETURN(OptStatements, parseOptionalStatements());
RETURN_IF_ERROR(consumeType(Kind::BlockBegin));
Modified: llvm/trunk/tools/llvm-rc/ResourceScriptParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rc/ResourceScriptParser.h?rev=311956&r1=311955&r2=311956&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rc/ResourceScriptParser.h (original)
+++ llvm/trunk/tools/llvm-rc/ResourceScriptParser.h Mon Aug 28 16:46:30 2017
@@ -130,8 +130,12 @@ private:
ParseType parseCursorResource();
ParseType parseIconResource();
ParseType parseHTMLResource();
+ ParseType parseMenuResource();
ParseType parseStringTableResource();
+ // Helper MENU parser.
+ Expected<MenuDefinitionList> parseMenuItemsList();
+
// Optional statement parsers.
ParseOptionType parseLanguageStmt();
ParseOptionType parseCharacteristicsStmt();
Modified: llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp?rev=311956&r1=311955&r2=311956&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp (original)
+++ llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp Mon Aug 28 16:46:30 2017
@@ -65,6 +65,46 @@ raw_ostream &HTMLResource::log(raw_ostre
return OS << "HTML (" << ResName << "): " << HTMLLoc << "\n";
}
+StringRef MenuDefinition::OptionsStr[MenuDefinition::NumFlags] = {
+ "CHECKED", "GRAYED", "HELP", "INACTIVE", "MENUBARBREAK", "MENUBREAK"};
+
+raw_ostream &MenuDefinition::logFlags(raw_ostream &OS, uint8_t Flags) {
+ for (size_t i = 0; i < NumFlags; ++i)
+ if (Flags & (1U << i))
+ OS << " " << OptionsStr[i];
+ return OS;
+}
+
+raw_ostream &MenuDefinitionList::log(raw_ostream &OS) const {
+ OS << " Menu list starts\n";
+ for (auto &Item : Definitions)
+ Item->log(OS);
+ return OS << " Menu list ends\n";
+}
+
+raw_ostream &MenuItem::log(raw_ostream &OS) const {
+ OS << " MenuItem (" << Name << "), ID = " << Id;
+ logFlags(OS, Flags);
+ return OS << "\n";
+}
+
+raw_ostream &MenuSeparator::log(raw_ostream &OS) const {
+ return OS << " Menu separator\n";
+}
+
+raw_ostream &PopupItem::log(raw_ostream &OS) const {
+ OS << " Popup (" << Name << ")";
+ logFlags(OS, Flags);
+ OS << ":\n";
+ return SubItems.log(OS);
+}
+
+raw_ostream &MenuResource::log(raw_ostream &OS) const {
+ OS << "Menu (" << ResName << "):\n";
+ OptStatements.log(OS);
+ return Elements.log(OS);
+}
+
raw_ostream &StringTableResource::log(raw_ostream &OS) const {
OS << "StringTable:\n";
OptStatements.log(OS);
Modified: llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h?rev=311956&r1=311955&r2=311956&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h (original)
+++ llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h Mon Aug 28 16:46:30 2017
@@ -166,6 +166,92 @@ public:
raw_ostream &log(raw_ostream &) const override;
};
+// -- MENU resource and its helper classes --
+// This resource describes the contents of an application menu
+// (usually located in the upper part of the dialog.)
+//
+// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381025(v=vs.85).aspx
+
+// Description of a single submenu item.
+class MenuDefinition {
+public:
+ enum Options {
+ CHECKED = (1 << 0),
+ GRAYED = (1 << 1),
+ HELP = (1 << 2),
+ INACTIVE = (1 << 3),
+ MENUBARBREAK = (1 << 4),
+ MENUBREAK = (1 << 5)
+ };
+
+ static constexpr size_t NumFlags = 6;
+ static StringRef OptionsStr[NumFlags];
+ static raw_ostream &logFlags(raw_ostream &, uint8_t Flags);
+ virtual raw_ostream &log(raw_ostream &OS) const {
+ return OS << "Base menu definition\n";
+ }
+ virtual ~MenuDefinition() {}
+};
+
+// Recursive description of a whole submenu.
+class MenuDefinitionList : public MenuDefinition {
+ std::vector<std::unique_ptr<MenuDefinition>> Definitions;
+
+public:
+ void addDefinition(std::unique_ptr<MenuDefinition> Def) {
+ Definitions.push_back(std::move(Def));
+ }
+ raw_ostream &log(raw_ostream &) const override;
+};
+
+// Separator in MENU definition (MENUITEM SEPARATOR).
+//
+// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
+class MenuSeparator : public MenuDefinition {
+public:
+ raw_ostream &log(raw_ostream &) const override;
+};
+
+// MENUITEM statement definition.
+//
+// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
+class MenuItem : public MenuDefinition {
+ StringRef Name;
+ uint32_t Id;
+ uint8_t Flags;
+
+public:
+ MenuItem(StringRef Caption, uint32_t ItemId, uint8_t ItemFlags)
+ : Name(Caption), Id(ItemId), Flags(ItemFlags) {}
+ raw_ostream &log(raw_ostream &) const override;
+};
+
+// POPUP statement definition.
+//
+// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx
+class PopupItem : public MenuDefinition {
+ StringRef Name;
+ uint8_t Flags;
+ MenuDefinitionList SubItems;
+
+public:
+ PopupItem(StringRef Caption, uint8_t ItemFlags,
+ MenuDefinitionList &&SubItemsList)
+ : Name(Caption), Flags(ItemFlags), SubItems(std::move(SubItemsList)) {}
+ raw_ostream &log(raw_ostream &) const override;
+};
+
+// Menu resource definition.
+class MenuResource : public RCResource {
+ OptionalStmtList OptStatements;
+ MenuDefinitionList Elements;
+
+public:
+ MenuResource(OptionalStmtList &&OptStmts, MenuDefinitionList &&Items)
+ : OptStatements(std::move(OptStmts)), Elements(std::move(Items)) {}
+ raw_ostream &log(raw_ostream &) const override;
+};
+
// STRINGTABLE resource. Contains a list of strings, each having its unique ID.
//
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381050(v=vs.85).aspx
More information about the llvm-commits
mailing list