summaryrefslogtreecommitdiff
path: root/tools/llvm-rc/ResourceScriptParser.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
commiteb11fae6d08f479c0799db45860a98af528fa6e7 (patch)
tree44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /tools/llvm-rc/ResourceScriptParser.cpp
parentb8a2042aa938069e862750553db0e4d82d25822c (diff)
Notes
Diffstat (limited to 'tools/llvm-rc/ResourceScriptParser.cpp')
-rw-r--r--tools/llvm-rc/ResourceScriptParser.cpp164
1 files changed, 138 insertions, 26 deletions
diff --git a/tools/llvm-rc/ResourceScriptParser.cpp b/tools/llvm-rc/ResourceScriptParser.cpp
index cf1579ee2a11..8cc0b50933c2 100644
--- a/tools/llvm-rc/ResourceScriptParser.cpp
+++ b/tools/llvm-rc/ResourceScriptParser.cpp
@@ -66,18 +66,22 @@ RCParser::ParseType RCParser::parseSingleResource() {
if (TypeToken->equalsLower("ACCELERATORS"))
Result = parseAcceleratorsResource();
+ else if (TypeToken->equalsLower("BITMAP"))
+ Result = parseBitmapResource();
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"))
Result = parseHTMLResource();
+ else if (TypeToken->equalsLower("ICON"))
+ Result = parseIconResource();
else if (TypeToken->equalsLower("MENU"))
Result = parseMenuResource();
+ else if (TypeToken->equalsLower("RCDATA"))
+ Result = parseUserDefinedResource(RkRcData);
else if (TypeToken->equalsLower("VERSIONINFO"))
Result = parseVersionInfoResource();
else
@@ -212,6 +216,12 @@ Expected<StringRef> RCParser::readString() {
return read().value();
}
+Expected<StringRef> RCParser::readFilename() {
+ if (!isNextTokenKind(Kind::String) && !isNextTokenKind(Kind::Identifier))
+ return getExpectedError("string");
+ return read().value();
+}
+
Expected<StringRef> RCParser::readIdentifier() {
if (!isNextTokenKind(Kind::Identifier))
return getExpectedError("identifier");
@@ -319,6 +329,37 @@ Expected<uint32_t> RCParser::parseFlags(ArrayRef<StringRef> FlagDesc,
return Result;
}
+uint16_t RCParser::parseMemoryFlags(uint16_t Flags) {
+ while (!isEof()) {
+ const RCToken &Token = look();
+ if (Token.kind() != Kind::Identifier)
+ return Flags;
+ const StringRef Ident = Token.value();
+ if (Ident.equals_lower("PRELOAD"))
+ Flags |= MfPreload;
+ else if (Ident.equals_lower("LOADONCALL"))
+ Flags &= ~MfPreload;
+ else if (Ident.equals_lower("FIXED"))
+ Flags &= ~(MfMoveable | MfDiscardable);
+ else if (Ident.equals_lower("MOVEABLE"))
+ Flags |= MfMoveable;
+ else if (Ident.equals_lower("DISCARDABLE"))
+ Flags |= MfDiscardable | MfMoveable | MfPure;
+ else if (Ident.equals_lower("PURE"))
+ Flags |= MfPure;
+ else if (Ident.equals_lower("IMPURE"))
+ Flags &= ~(MfPure | MfDiscardable);
+ else if (Ident.equals_lower("SHARED"))
+ Flags |= MfPure;
+ else if (Ident.equals_lower("NONSHARED"))
+ Flags &= ~(MfPure | MfDiscardable);
+ else
+ return Flags;
+ consume();
+ }
+ return Flags;
+}
+
Expected<OptionalStmtList>
RCParser::parseOptionalStatements(OptStmtType StmtsType) {
OptionalStmtList Result;
@@ -345,6 +386,8 @@ RCParser::parseSingleOptionalStatement(OptStmtType StmtsType) {
if (StmtsType != OptStmtType::BasicStmt) {
if (TypeToken->equals_lower("CAPTION"))
return parseCaptionStmt();
+ if (TypeToken->equals_lower("CLASS"))
+ return parseClassStmt();
if (TypeToken->equals_lower("FONT"))
return parseFontStmt(StmtsType);
if (TypeToken->equals_lower("STYLE"))
@@ -362,11 +405,13 @@ RCParser::ParseType RCParser::parseLanguageResource() {
}
RCParser::ParseType RCParser::parseAcceleratorsResource() {
+ uint16_t MemoryFlags =
+ parseMemoryFlags(AcceleratorsResource::getDefaultMemoryFlags());
ASSIGN_OR_RETURN(OptStatements, parseOptionalStatements());
RETURN_IF_ERROR(consumeType(Kind::BlockBegin));
- auto Accels =
- llvm::make_unique<AcceleratorsResource>(std::move(*OptStatements));
+ auto Accels = llvm::make_unique<AcceleratorsResource>(
+ std::move(*OptStatements), MemoryFlags);
while (!consumeOptionalType(Kind::BlockEnd)) {
ASSIGN_OR_RETURN(EventResult, readIntOrString());
@@ -383,11 +428,15 @@ RCParser::ParseType RCParser::parseAcceleratorsResource() {
}
RCParser::ParseType RCParser::parseCursorResource() {
- ASSIGN_OR_RETURN(Arg, readString());
- return llvm::make_unique<CursorResource>(*Arg);
+ uint16_t MemoryFlags =
+ parseMemoryFlags(CursorResource::getDefaultMemoryFlags());
+ ASSIGN_OR_RETURN(Arg, readFilename());
+ return llvm::make_unique<CursorResource>(*Arg, MemoryFlags);
}
RCParser::ParseType RCParser::parseDialogResource(bool IsExtended) {
+ uint16_t MemoryFlags =
+ parseMemoryFlags(DialogResource::getDefaultMemoryFlags());
// 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...}
@@ -410,7 +459,7 @@ RCParser::ParseType RCParser::parseDialogResource(bool IsExtended) {
auto Dialog = llvm::make_unique<DialogResource>(
(*LocResult)[0], (*LocResult)[1], (*LocResult)[2], (*LocResult)[3],
- HelpID, std::move(*OptStatements), IsExtended);
+ HelpID, std::move(*OptStatements), IsExtended, MemoryFlags);
while (!consumeOptionalType(Kind::BlockEnd)) {
ASSIGN_OR_RETURN(ControlDefResult, parseControl());
@@ -421,12 +470,20 @@ RCParser::ParseType RCParser::parseDialogResource(bool IsExtended) {
}
RCParser::ParseType RCParser::parseUserDefinedResource(IntOrString Type) {
+ uint16_t MemoryFlags =
+ parseMemoryFlags(UserDefinedResource::getDefaultMemoryFlags());
if (isEof())
return getExpectedError("filename, '{' or BEGIN");
// Check if this is a file resource.
- if (look().kind() == Kind::String)
- return llvm::make_unique<UserDefinedResource>(Type, read().value());
+ switch (look().kind()) {
+ case Kind::String:
+ case Kind::Identifier:
+ return llvm::make_unique<UserDefinedResource>(Type, read().value(),
+ MemoryFlags);
+ default:
+ break;
+ }
RETURN_IF_ERROR(consumeType(Kind::BlockBegin));
std::vector<IntOrString> Data;
@@ -442,14 +499,17 @@ RCParser::ParseType RCParser::parseUserDefinedResource(IntOrString Type) {
Data.push_back(*Item);
}
- return llvm::make_unique<UserDefinedResource>(Type, std::move(Data));
+ return llvm::make_unique<UserDefinedResource>(Type, std::move(Data),
+ MemoryFlags);
}
RCParser::ParseType RCParser::parseVersionInfoResource() {
+ uint16_t MemoryFlags =
+ parseMemoryFlags(VersionInfoResource::getDefaultMemoryFlags());
ASSIGN_OR_RETURN(FixedResult, parseVersionInfoFixed());
ASSIGN_OR_RETURN(BlockResult, parseVersionInfoBlockContents(StringRef()));
- return llvm::make_unique<VersionInfoResource>(std::move(**BlockResult),
- std::move(*FixedResult));
+ return llvm::make_unique<VersionInfoResource>(
+ std::move(**BlockResult), std::move(*FixedResult), MemoryFlags);
}
Expected<Control> RCParser::parseControl() {
@@ -473,32 +533,76 @@ Expected<Control> RCParser::parseControl() {
Caption = *CaptionResult;
}
- ASSIGN_OR_RETURN(Args, readIntsWithCommas(5, 8));
+ ASSIGN_OR_RETURN(ID, readInt());
+ RETURN_IF_ERROR(consumeType(Kind::Comma));
+
+ IntOrString Class;
+ Optional<uint32_t> Style;
+ if (ClassUpper == "CONTROL") {
+ // CONTROL text, id, class, style, x, y, width, height [, exstyle] [, helpID]
+ ASSIGN_OR_RETURN(ClassStr, readString());
+ RETURN_IF_ERROR(consumeType(Kind::Comma));
+ Class = *ClassStr;
+ ASSIGN_OR_RETURN(StyleVal, readInt());
+ RETURN_IF_ERROR(consumeType(Kind::Comma));
+ Style = *StyleVal;
+ } else {
+ Class = CtlInfo->getValue().CtlClass;
+ }
+
+ // x, y, width, height
+ ASSIGN_OR_RETURN(Args, readIntsWithCommas(4, 4));
- auto TakeOptArg = [&Args](size_t Id) -> Optional<uint32_t> {
- return Args->size() > Id ? (uint32_t)(*Args)[Id] : Optional<uint32_t>();
- };
+ if (ClassUpper != "CONTROL") {
+ if (consumeOptionalType(Kind::Comma)) {
+ ASSIGN_OR_RETURN(Val, readInt());
+ Style = *Val;
+ }
+ }
- return Control(*ClassResult, Caption, (*Args)[0], (*Args)[1], (*Args)[2],
- (*Args)[3], (*Args)[4], TakeOptArg(5), TakeOptArg(6),
- TakeOptArg(7));
+ Optional<uint32_t> ExStyle;
+ if (consumeOptionalType(Kind::Comma)) {
+ ASSIGN_OR_RETURN(Val, readInt());
+ ExStyle = *Val;
+ }
+ Optional<uint32_t> HelpID;
+ if (consumeOptionalType(Kind::Comma)) {
+ ASSIGN_OR_RETURN(Val, readInt());
+ HelpID = *Val;
+ }
+
+ return Control(*ClassResult, Caption, *ID, (*Args)[0], (*Args)[1],
+ (*Args)[2], (*Args)[3], Style, ExStyle, HelpID, Class);
+}
+
+RCParser::ParseType RCParser::parseBitmapResource() {
+ uint16_t MemoryFlags =
+ parseMemoryFlags(BitmapResource::getDefaultMemoryFlags());
+ ASSIGN_OR_RETURN(Arg, readFilename());
+ return llvm::make_unique<BitmapResource>(*Arg, MemoryFlags);
}
RCParser::ParseType RCParser::parseIconResource() {
- ASSIGN_OR_RETURN(Arg, readString());
- return llvm::make_unique<IconResource>(*Arg);
+ uint16_t MemoryFlags =
+ parseMemoryFlags(IconResource::getDefaultMemoryFlags());
+ ASSIGN_OR_RETURN(Arg, readFilename());
+ return llvm::make_unique<IconResource>(*Arg, MemoryFlags);
}
RCParser::ParseType RCParser::parseHTMLResource() {
- ASSIGN_OR_RETURN(Arg, readString());
- return llvm::make_unique<HTMLResource>(*Arg);
+ uint16_t MemoryFlags =
+ parseMemoryFlags(HTMLResource::getDefaultMemoryFlags());
+ ASSIGN_OR_RETURN(Arg, readFilename());
+ return llvm::make_unique<HTMLResource>(*Arg, MemoryFlags);
}
RCParser::ParseType RCParser::parseMenuResource() {
+ uint16_t MemoryFlags =
+ parseMemoryFlags(MenuResource::getDefaultMemoryFlags());
ASSIGN_OR_RETURN(OptStatements, parseOptionalStatements());
ASSIGN_OR_RETURN(Items, parseMenuItemsList());
return llvm::make_unique<MenuResource>(std::move(*OptStatements),
- std::move(*Items));
+ std::move(*Items), MemoryFlags);
}
Expected<MenuDefinitionList> RCParser::parseMenuItemsList() {
@@ -561,11 +665,13 @@ Expected<MenuDefinitionList> RCParser::parseMenuItemsList() {
}
RCParser::ParseType RCParser::parseStringTableResource() {
+ uint16_t MemoryFlags =
+ parseMemoryFlags(StringTableResource::getDefaultMemoryFlags());
ASSIGN_OR_RETURN(OptStatements, parseOptionalStatements());
RETURN_IF_ERROR(consumeType(Kind::BlockBegin));
- auto Table =
- llvm::make_unique<StringTableResource>(std::move(*OptStatements));
+ auto Table = llvm::make_unique<StringTableResource>(std::move(*OptStatements),
+ MemoryFlags);
// Read strings until we reach the end of the block.
while (!consumeOptionalType(Kind::BlockEnd)) {
@@ -573,6 +679,7 @@ RCParser::ParseType RCParser::parseStringTableResource() {
// Some examples in documentation suggest that there might be a comma in
// between, however we strictly adhere to the single statement definition.
ASSIGN_OR_RETURN(IDResult, readInt());
+ consumeOptionalType(Kind::Comma);
ASSIGN_OR_RETURN(StrResult, readString());
Table->addString(*IDResult, *StrResult);
}
@@ -674,6 +781,11 @@ RCParser::ParseOptionType RCParser::parseCaptionStmt() {
return llvm::make_unique<CaptionStmt>(*Arg);
}
+RCParser::ParseOptionType RCParser::parseClassStmt() {
+ ASSIGN_OR_RETURN(Arg, readIntOrString());
+ return llvm::make_unique<ClassStmt>(*Arg);
+}
+
RCParser::ParseOptionType RCParser::parseFontStmt(OptStmtType DialogType) {
assert(DialogType != OptStmtType::BasicStmt);