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