diff options
Diffstat (limited to 'llvm/tools/llvm-rc')
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptParser.cpp | 61 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptParser.h | 17 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptStmt.cpp | 17 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptStmt.h | 43 |
4 files changed, 126 insertions, 12 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); diff --git a/llvm/tools/llvm-rc/ResourceScriptParser.h b/llvm/tools/llvm-rc/ResourceScriptParser.h index b217a73ae76..e286f83160c 100644 --- a/llvm/tools/llvm-rc/ResourceScriptParser.h +++ b/llvm/tools/llvm-rc/ResourceScriptParser.h @@ -77,10 +77,11 @@ private: // The following methods try to read a single token, check if it has the // correct type and then parse it. - Expected<uint32_t> readInt(); // Parse an integer. - Expected<StringRef> readString(); // Parse a string. - Expected<StringRef> readIdentifier(); // Parse an identifier. - Expected<IntOrString> readTypeOrName(); // Parse an integer or an identifier. + Expected<uint32_t> readInt(); // Parse an integer. + Expected<StringRef> readString(); // Parse a string. + Expected<StringRef> readIdentifier(); // Parse an identifier. + Expected<IntOrString> readIntOrString(); // Parse an integer or a string. + Expected<IntOrString> readTypeOrName(); // Parse an integer or an identifier. // Advance the state by one, discarding the current token. // If the discarded token had an incorrect type, fail. @@ -97,6 +98,13 @@ private: Expected<SmallVector<uint32_t, 8>> readIntsWithCommas(size_t MinCount, size_t MaxCount); + // Read an unknown number of flags preceded by commas. Each correct flag + // has an entry in FlagDesc array of length NumFlags. In case i-th + // flag (0-based) has been read, the i-th bit of the result is set. + // As long as parser has a comma to read, it expects to be fed with + // a correct flag afterwards. + Expected<uint32_t> parseFlags(ArrayRef<StringRef> FlagDesc); + // Reads a set of optional statements. These can change the behavior of // a number of resource types (e.g. STRINGTABLE, MENU or DIALOG) if provided // before the main block with the contents of the resource. @@ -118,6 +126,7 @@ private: // Top-level resource parsers. ParseType parseLanguageResource(); + ParseType parseAcceleratorsResource(); ParseType parseCursorResource(); ParseType parseIconResource(); ParseType parseHTMLResource(); diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.cpp b/llvm/tools/llvm-rc/ResourceScriptStmt.cpp index f008641ff76..150b668bd91 100644 --- a/llvm/tools/llvm-rc/ResourceScriptStmt.cpp +++ b/llvm/tools/llvm-rc/ResourceScriptStmt.cpp @@ -36,6 +36,23 @@ raw_ostream &LanguageResource::log(raw_ostream &OS) const { return OS << "Language: " << Lang << ", Sublanguage: " << SubLang << "\n"; } +StringRef AcceleratorsResource::Accelerator::OptionsStr + [AcceleratorsResource::Accelerator::NumFlags] = { + "ASCII", "VIRTKEY", "NOINVERT", "ALT", "SHIFT", "CONTROL"}; + +raw_ostream &AcceleratorsResource::log(raw_ostream &OS) const { + OS << "Accelerators (" << ResName << "): \n"; + OptStatements.log(OS); + for (const auto &Acc : Accelerators) { + OS << " Accelerator: " << Acc.Event << " " << Acc.Id; + for (size_t i = 0; i < Accelerator::NumFlags; ++i) + if (Acc.Flags & (1U << i)) + OS << " " << Accelerator::OptionsStr[i]; + OS << "\n"; + } + return OS; +} + raw_ostream &CursorResource::log(raw_ostream &OS) const { return OS << "Cursor (" << ResName << "): " << CursorLoc << "\n"; } diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.h b/llvm/tools/llvm-rc/ResourceScriptStmt.h index 8ff0e5bb19c..cf1406e043f 100644 --- a/llvm/tools/llvm-rc/ResourceScriptStmt.h +++ b/llvm/tools/llvm-rc/ResourceScriptStmt.h @@ -27,7 +27,12 @@ private: StringRef String; Data(uint32_t Value) : Int(Value) {} Data(const StringRef Value) : String(Value) {} - Data(const RCToken &Token); + Data(const RCToken &Token) { + if (Token.kind() == RCToken::Kind::Int) + Int = Token.intValue(); + else + String = Token.value(); + } } Data; bool IsInt; @@ -90,6 +95,42 @@ public: raw_ostream &log(raw_ostream &) const override; }; +// ACCELERATORS resource. Defines a named table of accelerators for the app. +// +// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380610(v=vs.85).aspx +class AcceleratorsResource : public RCResource { +public: + class Accelerator { + public: + IntOrString Event; + uint32_t Id; + uint8_t Flags; + + enum Options { + ASCII = (1 << 0), + VIRTKEY = (1 << 1), + NOINVERT = (1 << 2), + ALT = (1 << 3), + SHIFT = (1 << 4), + CONTROL = (1 << 5) + }; + + static constexpr size_t NumFlags = 6; + static StringRef OptionsStr[NumFlags]; + }; + + AcceleratorsResource(OptionalStmtList &&OptStmts) + : OptStatements(std::move(OptStmts)) {} + void addAccelerator(IntOrString Event, uint32_t Id, uint8_t Flags) { + Accelerators.push_back(Accelerator{Event, Id, Flags}); + } + raw_ostream &log(raw_ostream &) const override; + +private: + std::vector<Accelerator> Accelerators; + OptionalStmtList OptStatements; +}; + // CURSOR resource. Represents a single cursor (".cur") file. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380920(v=vs.85).aspx |