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/ResourceFileWriter.cpp7
-rw-r--r--llvm/tools/llvm-rc/ResourceScriptParser.cpp41
-rw-r--r--llvm/tools/llvm-rc/ResourceScriptParser.h4
-rw-r--r--llvm/tools/llvm-rc/ResourceScriptStmt.cpp2
-rw-r--r--llvm/tools/llvm-rc/ResourceScriptStmt.h58
5 files changed, 92 insertions, 20 deletions
diff --git a/llvm/tools/llvm-rc/ResourceFileWriter.cpp b/llvm/tools/llvm-rc/ResourceFileWriter.cpp
index e69d4793dd1..7fe95669083 100644
--- a/llvm/tools/llvm-rc/ResourceFileWriter.cpp
+++ b/llvm/tools/llvm-rc/ResourceFileWriter.cpp
@@ -987,7 +987,8 @@ Error ResourceFileWriter::writeSingleDialogControl(const Control &Ctl,
padStream(sizeof(uint32_t));
auto TypeInfo = Control::SupportedCtls.lookup(Ctl.Type);
- uint32_t CtlStyle = TypeInfo.Style | Ctl.Style.getValueOr(0);
+ IntWithNotMask CtlStyle(TypeInfo.Style);
+ CtlStyle |= Ctl.Style.getValueOr(RCInt(0));
uint32_t CtlExtStyle = Ctl.ExtStyle.getValueOr(0);
// DIALOG(EX) item header prefix.
@@ -995,7 +996,7 @@ Error ResourceFileWriter::writeSingleDialogControl(const Control &Ctl,
struct {
ulittle32_t Style;
ulittle32_t ExtStyle;
- } Prefix{ulittle32_t(CtlStyle), ulittle32_t(CtlExtStyle)};
+ } Prefix{ulittle32_t(CtlStyle.getValue()), ulittle32_t(CtlExtStyle)};
writeObject(Prefix);
} else {
struct {
@@ -1003,7 +1004,7 @@ Error ResourceFileWriter::writeSingleDialogControl(const Control &Ctl,
ulittle32_t ExtStyle;
ulittle32_t Style;
} Prefix{ulittle32_t(Ctl.HelpID.getValueOr(0)), ulittle32_t(CtlExtStyle),
- ulittle32_t(CtlStyle)};
+ ulittle32_t(CtlStyle.getValue())};
writeObject(Prefix);
}
diff --git a/llvm/tools/llvm-rc/ResourceScriptParser.cpp b/llvm/tools/llvm-rc/ResourceScriptParser.cpp
index 09c88ff879a..c66fc4fc2e7 100644
--- a/llvm/tools/llvm-rc/ResourceScriptParser.cpp
+++ b/llvm/tools/llvm-rc/ResourceScriptParser.cpp
@@ -114,16 +114,23 @@ void RCParser::consume() {
// An integer description might consist of a single integer or
// an arithmetic expression evaluating to the integer. The expressions
-// can contain the following tokens: <int> ( ) + - | & ~. Their meaning
-// is the same as in C++.
+// can contain the following tokens: <int> ( ) + - | & ~ not. Their meaning
+// is the same as in C++ except for 'not' expression.
// The operators in the original RC implementation have the following
// precedence:
-// 1) Unary operators (- ~),
+// 1) Unary operators (- ~ not),
// 2) Binary operators (+ - & |), with no precedence.
//
+// 'not' expression is mostly useful for style values. It evaluates to 0,
+// but value given to the operator is stored separately from integer value.
+// It's mostly useful for control style expressions and causes bits from
+// default control style to be excluded from generated style. For binary
+// operators the mask from the right operand is applied to the left operand
+// and masks from both operands are combined in operator result.
+//
// The following grammar is used to parse the expressions Exp1:
// Exp1 ::= Exp2 || Exp1 + Exp2 || Exp1 - Exp2 || Exp1 | Exp2 || Exp1 & Exp2
-// Exp2 ::= -Exp2 || ~Exp2 || Int || (Exp1).
+// Exp2 ::= -Exp2 || ~Exp2 || not Expr2 || Int || (Exp1).
// (More conveniently, Exp1 is a non-empty sequence of Exp2 expressions,
// separated by binary operators.)
//
@@ -139,12 +146,15 @@ void RCParser::consume() {
// 1 => 01 00, -1 => ff ff, --1 => 01 00, ---1 => ff ff;
// 1 => 01 00, ~1 => fe ff, ~~1 => 01 00, ~~~1 => fe ff.
-Expected<RCInt> RCParser::readInt() { return parseIntExpr1(); }
+Expected<RCInt> RCParser::readInt() {
+ ASSIGN_OR_RETURN(Value, parseIntExpr1());
+ return (*Value).getValue();
+}
-Expected<RCInt> RCParser::parseIntExpr1() {
+Expected<IntWithNotMask> RCParser::parseIntExpr1() {
// Exp1 ::= Exp2 || Exp1 + Exp2 || Exp1 - Exp2 || Exp1 | Exp2 || Exp1 & Exp2.
ASSIGN_OR_RETURN(FirstResult, parseIntExpr2());
- RCInt Result = *FirstResult;
+ IntWithNotMask Result = *FirstResult;
while (!isEof() && look().isBinaryOp()) {
auto OpToken = read();
@@ -175,8 +185,8 @@ Expected<RCInt> RCParser::parseIntExpr1() {
return Result;
}
-Expected<RCInt> RCParser::parseIntExpr2() {
- // Exp2 ::= -Exp2 || ~Exp2 || Int || (Exp1).
+Expected<IntWithNotMask> RCParser::parseIntExpr2() {
+ // Exp2 ::= -Exp2 || ~Exp2 || not Expr2 || Int || (Exp1).
static const char ErrorMsg[] = "'-', '~', integer or '('";
if (isEof())
@@ -205,6 +215,13 @@ Expected<RCInt> RCParser::parseIntExpr2() {
return *Result;
}
+ case Kind::Identifier: {
+ if (!read().value().equals_lower("not"))
+ return getExpectedError(ErrorMsg, true);
+ ASSIGN_OR_RETURN(Result, parseIntExpr2());
+ return IntWithNotMask(0, (*Result).getValue());
+ }
+
default:
return getExpectedError(ErrorMsg);
}
@@ -539,13 +556,13 @@ Expected<Control> RCParser::parseControl() {
RETURN_IF_ERROR(consumeType(Kind::Comma));
IntOrString Class;
- Optional<uint32_t> Style;
+ Optional<IntWithNotMask> 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());
+ ASSIGN_OR_RETURN(StyleVal, parseIntExpr1());
RETURN_IF_ERROR(consumeType(Kind::Comma));
Style = *StyleVal;
} else {
@@ -557,7 +574,7 @@ Expected<Control> RCParser::parseControl() {
if (ClassUpper != "CONTROL") {
if (consumeOptionalType(Kind::Comma)) {
- ASSIGN_OR_RETURN(Val, readInt());
+ ASSIGN_OR_RETURN(Val, parseIntExpr1());
Style = *Val;
}
}
diff --git a/llvm/tools/llvm-rc/ResourceScriptParser.h b/llvm/tools/llvm-rc/ResourceScriptParser.h
index 4f047f34fc0..20d8ff9624d 100644
--- a/llvm/tools/llvm-rc/ResourceScriptParser.h
+++ b/llvm/tools/llvm-rc/ResourceScriptParser.h
@@ -89,8 +89,8 @@ private:
Expected<IntOrString> readTypeOrName(); // Parse an integer or an identifier.
// Helper integer expression parsing methods.
- Expected<RCInt> parseIntExpr1();
- Expected<RCInt> parseIntExpr2();
+ Expected<IntWithNotMask> parseIntExpr1();
+ Expected<IntWithNotMask> parseIntExpr2();
// Advance the state by one, discarding the current token.
// If the discarded token had an incorrect type, fail.
diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.cpp b/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
index 325707226c4..7b8b0def4c9 100644
--- a/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
+++ b/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
@@ -151,7 +151,7 @@ raw_ostream &Control::log(raw_ostream &OS) const {
<< ", loc: (" << X << ", " << Y << "), size: [" << Width << ", " << Height
<< "]";
if (Style)
- OS << ", style: " << *Style;
+ OS << ", style: " << (*Style).getValue();
if (ExtStyle)
OS << ", ext. style: " << *ExtStyle;
if (HelpID)
diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.h b/llvm/tools/llvm-rc/ResourceScriptStmt.h
index 0051f83fcf2..3ba1f6619eb 100644
--- a/llvm/tools/llvm-rc/ResourceScriptStmt.h
+++ b/llvm/tools/llvm-rc/ResourceScriptStmt.h
@@ -67,6 +67,59 @@ public:
}
};
+class IntWithNotMask {
+private:
+ RCInt Value;
+ int32_t NotMask;
+
+public:
+ IntWithNotMask() : IntWithNotMask(RCInt(0)) {}
+ IntWithNotMask(RCInt Value, int32_t NotMask = 0) : Value(Value), NotMask(NotMask) {}
+
+ RCInt getValue() const {
+ return Value;
+ }
+
+ uint32_t getNotMask() const {
+ return NotMask;
+ }
+
+ IntWithNotMask &operator+=(const IntWithNotMask &Rhs) {
+ Value &= ~Rhs.NotMask;
+ Value += Rhs.Value;
+ NotMask |= Rhs.NotMask;
+ return *this;
+ }
+
+ IntWithNotMask &operator-=(const IntWithNotMask &Rhs) {
+ Value &= ~Rhs.NotMask;
+ Value -= Rhs.Value;
+ NotMask |= Rhs.NotMask;
+ return *this;
+ }
+
+ IntWithNotMask &operator|=(const IntWithNotMask &Rhs) {
+ Value &= ~Rhs.NotMask;
+ Value |= Rhs.Value;
+ NotMask |= Rhs.NotMask;
+ return *this;
+ }
+
+ IntWithNotMask &operator&=(const IntWithNotMask &Rhs) {
+ Value &= ~Rhs.NotMask;
+ Value &= Rhs.Value;
+ NotMask |= Rhs.NotMask;
+ return *this;
+ }
+
+ IntWithNotMask operator-() const { return {-Value, NotMask}; }
+ IntWithNotMask operator~() const { return {~Value, 0}; }
+
+ friend raw_ostream &operator<<(raw_ostream &OS, const IntWithNotMask &Int) {
+ return OS << Int.Value;
+ }
+};
+
// A class holding a name - either an integer or a reference to the string.
class IntOrString {
private:
@@ -556,7 +609,8 @@ public:
StringRef Type;
IntOrString Title;
uint32_t ID, X, Y, Width, Height;
- Optional<uint32_t> Style, ExtStyle, HelpID;
+ Optional<IntWithNotMask> Style;
+ Optional<uint32_t> ExtStyle, HelpID;
IntOrString Class;
// Control classes as described in DLGITEMTEMPLATEEX documentation.
@@ -580,7 +634,7 @@ public:
Control(StringRef CtlType, IntOrString CtlTitle, uint32_t CtlID,
uint32_t PosX, uint32_t PosY, uint32_t ItemWidth, uint32_t ItemHeight,
- Optional<uint32_t> ItemStyle, Optional<uint32_t> ExtItemStyle,
+ Optional<IntWithNotMask> ItemStyle, Optional<uint32_t> ExtItemStyle,
Optional<uint32_t> CtlHelpID, IntOrString CtlClass)
: Type(CtlType), Title(CtlTitle), ID(CtlID), X(PosX), Y(PosY),
Width(ItemWidth), Height(ItemHeight), Style(ItemStyle),
OpenPOWER on IntegriCloud