summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-rc/ResourceScriptParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-rc/ResourceScriptParser.cpp')
-rw-r--r--llvm/tools/llvm-rc/ResourceScriptParser.cpp61
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);
OpenPOWER on IntegriCloud