diff options
author | Marek Sokolowski <mnbvmar@gmail.com> | 2017-08-28 23:46:30 +0000 |
---|---|---|
committer | Marek Sokolowski <mnbvmar@gmail.com> | 2017-08-28 23:46:30 +0000 |
commit | 99ecb0ebcaa4b953fcc5e9fbf49b233ef1b9b294 (patch) | |
tree | d9bb28e179e99e08584bd940da9d4b21cf16f707 /llvm/tools/llvm-rc/ResourceScriptParser.cpp | |
parent | 873a0746f124c47413407a7f767c906db17828db (diff) | |
download | bcm5719-llvm-99ecb0ebcaa4b953fcc5e9fbf49b233ef1b9b294.tar.gz bcm5719-llvm-99ecb0ebcaa4b953fcc5e9fbf49b233ef1b9b294.zip |
[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
llvm-svn: 311956
Diffstat (limited to 'llvm/tools/llvm-rc/ResourceScriptParser.cpp')
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptParser.cpp | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/llvm/tools/llvm-rc/ResourceScriptParser.cpp b/llvm/tools/llvm-rc/ResourceScriptParser.cpp index 8d08396e615..5cc171c49af 100644 --- a/llvm/tools/llvm-rc/ResourceScriptParser.cpp +++ b/llvm/tools/llvm-rc/ResourceScriptParser.cpp @@ -71,6 +71,8 @@ RCParser::ParseType RCParser::parseSingleResource() { 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::parseHTMLResource() { 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)); |