diff options
author | Marek Sokolowski <mnbvmar@gmail.com> | 2017-09-28 22:41:38 +0000 |
---|---|---|
committer | Marek Sokolowski <mnbvmar@gmail.com> | 2017-09-28 22:41:38 +0000 |
commit | fb74cb1edfa64424fb5204d10a16892f972435ed (patch) | |
tree | 7d957908f643f7220954015652c2509e3a963683 /llvm/tools/llvm-rc/ResourceScriptParser.cpp | |
parent | 3b87336a0c4e7974c007d489926e5e1bcf722a75 (diff) | |
download | bcm5719-llvm-fb74cb1edfa64424fb5204d10a16892f972435ed.tar.gz bcm5719-llvm-fb74cb1edfa64424fb5204d10a16892f972435ed.zip |
[llvm-rc] Add VERSIONINFO parsing ability. [6/8]
This extends the set of llvm-rc parser's available resources by
another one, VERSIONINFO.
Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381058.aspx
Thanks to Nico Weber for his original work in this area.
Differential Revision: https://reviews.llvm.org/D37021
llvm-svn: 314468
Diffstat (limited to 'llvm/tools/llvm-rc/ResourceScriptParser.cpp')
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptParser.cpp | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/llvm/tools/llvm-rc/ResourceScriptParser.cpp b/llvm/tools/llvm-rc/ResourceScriptParser.cpp index 41b11911b06..57a30d14371 100644 --- a/llvm/tools/llvm-rc/ResourceScriptParser.cpp +++ b/llvm/tools/llvm-rc/ResourceScriptParser.cpp @@ -77,6 +77,8 @@ RCParser::ParseType RCParser::parseSingleResource() { Result = parseHTMLResource(); else if (TypeToken->equalsLower("MENU")) Result = parseMenuResource(); + else if (TypeToken->equalsLower("VERSIONINFO")) + Result = parseVersionInfoResource(); else return getExpectedError("resource type", /* IsAlreadyRead = */ true); @@ -322,6 +324,13 @@ RCParser::ParseType RCParser::parseDialogResource(bool IsExtended) { return std::move(Dialog); } +RCParser::ParseType RCParser::parseVersionInfoResource() { + ASSIGN_OR_RETURN(FixedResult, parseVersionInfoFixed()); + ASSIGN_OR_RETURN(BlockResult, parseVersionInfoBlockContents(StringRef())); + return make_unique<VersionInfoResource>(std::move(**BlockResult), + std::move(*FixedResult)); +} + Expected<Control> RCParser::parseControl() { // Each control definition (except CONTROL) follows one of the schemes below // depending on the control class: @@ -446,6 +455,72 @@ RCParser::ParseType RCParser::parseStringTableResource() { return std::move(Table); } +Expected<std::unique_ptr<VersionInfoBlock>> +RCParser::parseVersionInfoBlockContents(StringRef BlockName) { + RETURN_IF_ERROR(consumeType(Kind::BlockBegin)); + + auto Contents = make_unique<VersionInfoBlock>(BlockName); + + while (!isNextTokenKind(Kind::BlockEnd)) { + ASSIGN_OR_RETURN(Stmt, parseVersionInfoStmt()); + Contents->addStmt(std::move(*Stmt)); + } + + consume(); // Consume BlockEnd. + + return std::move(Contents); +} + +Expected<std::unique_ptr<VersionInfoStmt>> RCParser::parseVersionInfoStmt() { + // Expect either BLOCK or VALUE, then a name or a key (a string). + ASSIGN_OR_RETURN(TypeResult, readIdentifier()); + + if (TypeResult->equals_lower("BLOCK")) { + ASSIGN_OR_RETURN(NameResult, readString()); + return parseVersionInfoBlockContents(*NameResult); + } + + if (TypeResult->equals_lower("VALUE")) { + ASSIGN_OR_RETURN(KeyResult, readString()); + // Read a (possibly empty) list of strings and/or ints, each preceded by + // a comma. + std::vector<IntOrString> Values; + + while (consumeOptionalType(Kind::Comma)) { + ASSIGN_OR_RETURN(ValueResult, readIntOrString()); + Values.push_back(*ValueResult); + } + return make_unique<VersionInfoValue>(*KeyResult, std::move(Values)); + } + + return getExpectedError("BLOCK or VALUE", true); +} + +Expected<VersionInfoResource::VersionInfoFixed> +RCParser::parseVersionInfoFixed() { + using RetType = VersionInfoResource::VersionInfoFixed; + RetType Result; + + // Read until the beginning of the block. + while (!isNextTokenKind(Kind::BlockBegin)) { + ASSIGN_OR_RETURN(TypeResult, readIdentifier()); + auto FixedType = RetType::getFixedType(*TypeResult); + + if (!RetType::isTypeSupported(FixedType)) + return getExpectedError("fixed VERSIONINFO statement type", true); + if (Result.IsTypePresent[FixedType]) + return getExpectedError("yet unread fixed VERSIONINFO statement type", + true); + + // VERSION variations take multiple integers. + size_t NumInts = RetType::isVersionType(FixedType) ? 4 : 1; + ASSIGN_OR_RETURN(ArgsResult, readIntsWithCommas(NumInts, NumInts)); + Result.setValue(FixedType, *ArgsResult); + } + + return Result; +} + RCParser::ParseOptionType RCParser::parseLanguageStmt() { ASSIGN_OR_RETURN(Args, readIntsWithCommas(/* min = */ 2, /* max = */ 2)); return make_unique<LanguageResource>((*Args)[0], (*Args)[1]); |