summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-rc/ResourceScriptParser.cpp
diff options
context:
space:
mode:
authorMarek Sokolowski <mnbvmar@gmail.com>2017-08-29 16:49:59 +0000
committerMarek Sokolowski <mnbvmar@gmail.com>2017-08-29 16:49:59 +0000
commit4ac54d930280b0d4c774ea51fb52beb81af78190 (patch)
tree59ff2e11b8c6a7e4a9d6539c2494624c11d8cab7 /llvm/tools/llvm-rc/ResourceScriptParser.cpp
parentc6f6aa441b1fb0ed47b3275cd02e158a61e252ac (diff)
downloadbcm5719-llvm-4ac54d930280b0d4c774ea51fb52beb81af78190.tar.gz
bcm5719-llvm-4ac54d930280b0d4c774ea51fb52beb81af78190.zip
[llvm-rc] Add DIALOG(EX) parsing ability (parser, pt 5/8).
This extends the set of resources parsed by llvm-rc by DIALOG and DIALOGEX. Additionally, three optional resource statements specific to these two resources are added: CAPTION, FONT, and STYLE. Thanks for Nico Weber for his original work in this area. Differential Revision: https://reviews.llvm.org/D36905 llvm-svn: 312009
Diffstat (limited to 'llvm/tools/llvm-rc/ResourceScriptParser.cpp')
-rw-r--r--llvm/tools/llvm-rc/ResourceScriptParser.cpp104
1 files changed, 98 insertions, 6 deletions
diff --git a/llvm/tools/llvm-rc/ResourceScriptParser.cpp b/llvm/tools/llvm-rc/ResourceScriptParser.cpp
index 5cc171c49af..499d0af83ad 100644
--- a/llvm/tools/llvm-rc/ResourceScriptParser.cpp
+++ b/llvm/tools/llvm-rc/ResourceScriptParser.cpp
@@ -67,6 +67,10 @@ RCParser::ParseType RCParser::parseSingleResource() {
Result = parseAcceleratorsResource();
else if (TypeToken->equalsLower("CURSOR"))
Result = parseCursorResource();
+ else if (TypeToken->equalsLower("DIALOG"))
+ Result = parseDialogResource(false);
+ else if (TypeToken->equalsLower("DIALOGEX"))
+ Result = parseDialogResource(true);
else if (TypeToken->equalsLower("ICON"))
Result = parseIconResource();
else if (TypeToken->equalsLower("HTML"))
@@ -235,17 +239,26 @@ Expected<OptionalStmtList> RCParser::parseOptionalStatements(bool IsExtended) {
}
Expected<std::unique_ptr<OptionalStmt>>
-RCParser::parseSingleOptionalStatement(bool) {
+RCParser::parseSingleOptionalStatement(bool IsExtended) {
ASSIGN_OR_RETURN(TypeToken, readIdentifier());
if (TypeToken->equals_lower("CHARACTERISTICS"))
return parseCharacteristicsStmt();
- else if (TypeToken->equals_lower("LANGUAGE"))
+ if (TypeToken->equals_lower("LANGUAGE"))
return parseLanguageStmt();
- else if (TypeToken->equals_lower("VERSION"))
+ if (TypeToken->equals_lower("VERSION"))
return parseVersionStmt();
- else
- return getExpectedError("optional statement type, BEGIN or '{'",
- /* IsAlreadyRead = */ true);
+
+ if (IsExtended) {
+ if (TypeToken->equals_lower("CAPTION"))
+ return parseCaptionStmt();
+ if (TypeToken->equals_lower("FONT"))
+ return parseFontStmt();
+ if (TypeToken->equals_lower("STYLE"))
+ return parseStyleStmt();
+ }
+
+ return getExpectedError("optional statement type, BEGIN or '{'",
+ /* IsAlreadyRead = */ true);
}
RCParser::ParseType RCParser::parseLanguageResource() {
@@ -277,6 +290,68 @@ RCParser::ParseType RCParser::parseCursorResource() {
return make_unique<CursorResource>(*Arg);
}
+RCParser::ParseType RCParser::parseDialogResource(bool IsExtended) {
+ // Dialog resources have the following format of the arguments:
+ // DIALOG: x, y, width, height [opt stmts...] {controls...}
+ // DIALOGEX: x, y, width, height [, helpID] [opt stmts...] {controls...}
+ // These are very similar, so we parse them together.
+ ASSIGN_OR_RETURN(LocResult, readIntsWithCommas(4, 4));
+
+ uint32_t HelpID = 0; // When HelpID is unset, it's assumed to be 0.
+ if (IsExtended && consumeOptionalType(Kind::Comma)) {
+ ASSIGN_OR_RETURN(HelpIDResult, readInt());
+ HelpID = *HelpIDResult;
+ }
+
+ ASSIGN_OR_RETURN(OptStatements,
+ parseOptionalStatements(/*UseExtendedStmts = */ true));
+
+ assert(isNextTokenKind(Kind::BlockBegin) &&
+ "parseOptionalStatements, when successful, halts on BlockBegin.");
+ consume();
+
+ auto Dialog = make_unique<DialogResource>(
+ (*LocResult)[0], (*LocResult)[1], (*LocResult)[2], (*LocResult)[3],
+ HelpID, std::move(*OptStatements), IsExtended);
+
+ while (!consumeOptionalType(Kind::BlockEnd)) {
+ ASSIGN_OR_RETURN(ControlDefResult, parseControl());
+ Dialog->addControl(std::move(*ControlDefResult));
+ }
+
+ return std::move(Dialog);
+}
+
+Expected<Control> RCParser::parseControl() {
+ // Each control definition (except CONTROL) follows one of the schemes below
+ // depending on the control class:
+ // [class] text, id, x, y, width, height [, style] [, exstyle] [, helpID]
+ // [class] id, x, y, width, height [, style] [, exstyle] [, helpID]
+ // Note that control ids must be integers.
+ ASSIGN_OR_RETURN(ClassResult, readIdentifier());
+ StringRef ClassUpper = ClassResult->upper();
+ if (Control::SupportedCtls.find(ClassUpper) == Control::SupportedCtls.end())
+ return getExpectedError("control type, END or '}'", true);
+
+ // Read caption if necessary.
+ StringRef Caption;
+ if (Control::CtlsWithTitle.find(ClassUpper) != Control::CtlsWithTitle.end()) {
+ ASSIGN_OR_RETURN(CaptionResult, readString());
+ RETURN_IF_ERROR(consumeType(Kind::Comma));
+ Caption = *CaptionResult;
+ }
+
+ ASSIGN_OR_RETURN(Args, readIntsWithCommas(5, 8));
+
+ auto TakeOptArg = [&Args](size_t Id) -> Optional<uint32_t> {
+ return Args->size() > Id ? (*Args)[Id] : Optional<uint32_t>();
+ };
+
+ return Control(*ClassResult, Caption, (*Args)[0], (*Args)[1], (*Args)[2],
+ (*Args)[3], (*Args)[4], TakeOptArg(5), TakeOptArg(6),
+ TakeOptArg(7));
+}
+
RCParser::ParseType RCParser::parseIconResource() {
ASSIGN_OR_RETURN(Arg, readString());
return make_unique<IconResource>(*Arg);
@@ -386,6 +461,23 @@ RCParser::ParseOptionType RCParser::parseVersionStmt() {
return make_unique<VersionStmt>(*Arg);
}
+RCParser::ParseOptionType RCParser::parseCaptionStmt() {
+ ASSIGN_OR_RETURN(Arg, readString());
+ return make_unique<CaptionStmt>(*Arg);
+}
+
+RCParser::ParseOptionType RCParser::parseFontStmt() {
+ ASSIGN_OR_RETURN(SizeResult, readInt());
+ RETURN_IF_ERROR(consumeType(Kind::Comma));
+ ASSIGN_OR_RETURN(NameResult, readString());
+ return make_unique<FontStmt>(*SizeResult, *NameResult);
+}
+
+RCParser::ParseOptionType RCParser::parseStyleStmt() {
+ ASSIGN_OR_RETURN(Arg, readInt());
+ return make_unique<StyleStmt>(*Arg);
+}
+
Error RCParser::getExpectedError(const Twine Message, bool IsAlreadyRead) {
return make_error<ParserError>(
Message, IsAlreadyRead ? std::prev(CurLoc) : CurLoc, End);
OpenPOWER on IntegriCloud