diff options
Diffstat (limited to 'llvm/tools/llvm-rc/ResourceScriptParser.cpp')
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptParser.cpp | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/llvm/tools/llvm-rc/ResourceScriptParser.cpp b/llvm/tools/llvm-rc/ResourceScriptParser.cpp index e4c0f2a7f7c..8d08396e615 100644 --- a/llvm/tools/llvm-rc/ResourceScriptParser.cpp +++ b/llvm/tools/llvm-rc/ResourceScriptParser.cpp @@ -63,7 +63,9 @@ RCParser::ParseType RCParser::parseSingleResource() { ParseType Result = std::unique_ptr<RCResource>(); (void)!Result; - if (TypeToken->equalsLower("CURSOR")) + if (TypeToken->equalsLower("ACCELERATORS")) + Result = parseAcceleratorsResource(); + else if (TypeToken->equalsLower("CURSOR")) Result = parseCursorResource(); else if (TypeToken->equalsLower("ICON")) Result = parseIconResource(); @@ -115,17 +117,18 @@ Expected<StringRef> RCParser::readIdentifier() { return read().value(); } +Expected<IntOrString> RCParser::readIntOrString() { + if (!isNextTokenKind(Kind::Int) && !isNextTokenKind(Kind::String)) + return getExpectedError("int or string"); + return IntOrString(read()); +} + Expected<IntOrString> RCParser::readTypeOrName() { // We suggest that the correct resource name or type should be either an // identifier or an integer. The original RC tool is much more liberal. if (!isNextTokenKind(Kind::Identifier) && !isNextTokenKind(Kind::Int)) return getExpectedError("int or identifier"); - - const RCToken &Tok = read(); - if (Tok.kind() == Kind::Int) - return IntOrString(Tok.intValue()); - else - return IntOrString(Tok.value()); + return IntOrString(read()); } Error RCParser::consumeType(Kind TokenKind) { @@ -190,6 +193,32 @@ RCParser::readIntsWithCommas(size_t MinCount, size_t MaxCount) { return std::move(Result); } +Expected<uint32_t> RCParser::parseFlags(ArrayRef<StringRef> FlagDesc) { + assert(FlagDesc.size() <= 32 && "More than 32 flags won't fit in result."); + assert(!FlagDesc.empty()); + + uint32_t Result = 0; + while (isNextTokenKind(Kind::Comma)) { + consume(); + ASSIGN_OR_RETURN(FlagResult, readIdentifier()); + bool FoundFlag = false; + + for (size_t FlagId = 0; FlagId < FlagDesc.size(); ++FlagId) { + if (!FlagResult->equals_lower(FlagDesc[FlagId])) + continue; + + Result |= (1U << FlagId); + FoundFlag = true; + break; + } + + if (!FoundFlag) + return getExpectedError(join(FlagDesc, "/"), true); + } + + return Result; +} + // As for now, we ignore the extended set of statements. Expected<OptionalStmtList> RCParser::parseOptionalStatements(bool IsExtended) { OptionalStmtList Result; @@ -223,6 +252,24 @@ RCParser::ParseType RCParser::parseLanguageResource() { return parseLanguageStmt(); } +RCParser::ParseType RCParser::parseAcceleratorsResource() { + ASSIGN_OR_RETURN(OptStatements, parseOptionalStatements()); + RETURN_IF_ERROR(consumeType(Kind::BlockBegin)); + + auto Accels = make_unique<AcceleratorsResource>(std::move(*OptStatements)); + + while (!consumeOptionalType(Kind::BlockEnd)) { + ASSIGN_OR_RETURN(EventResult, readIntOrString()); + RETURN_IF_ERROR(consumeType(Kind::Comma)); + ASSIGN_OR_RETURN(IDResult, readInt()); + ASSIGN_OR_RETURN(FlagsResult, + parseFlags(AcceleratorsResource::Accelerator::OptionsStr)); + Accels->addAccelerator(*EventResult, *IDResult, *FlagsResult); + } + + return std::move(Accels); +} + RCParser::ParseType RCParser::parseCursorResource() { ASSIGN_OR_RETURN(Arg, readString()); return make_unique<CursorResource>(*Arg); |