mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
[llvm-rc] Support not expressions.
Patch by Jacek Caban! Differential Revision: https://reviews.llvm.org/D55242 llvm-svn: 348363
This commit is contained in:
parent
820f0e4723
commit
b5caa2c2e4
BIN
test/tools/llvm-rc/Inputs/not-expr.rc
Normal file
BIN
test/tools/llvm-rc/Inputs/not-expr.rc
Normal file
Binary file not shown.
20
test/tools/llvm-rc/not-expr.test
Normal file
20
test/tools/llvm-rc/not-expr.test
Normal file
@ -0,0 +1,20 @@
|
||||
; RUN: llvm-rc /FO %t %p/Inputs/not-expr.rc
|
||||
; RUN: llvm-readobj %t | FileCheck %s --check-prefix=NOTEXPR
|
||||
|
||||
; NOTEXPR: Resource type (int): 5
|
||||
; NOTEXPR-NEXT: Resource name (string): NOT
|
||||
; NOTEXPR-NEXT: Data version: 0
|
||||
; NOTEXPR-NEXT: Memory flags: 0x1030
|
||||
; NOTEXPR-NEXT: Language ID: 1033
|
||||
; NOTEXPR-NEXT: Version (major): 0
|
||||
; NOTEXPR-NEXT: Version (minor): 0
|
||||
; NOTEXPR-NEXT: Characteristics: 0
|
||||
; NOTEXPR-NEXT: Data size: 96
|
||||
; NOTEXPR-NEXT: Data: (
|
||||
; NOTEXPR-NEXT: 0000: 0100FFFF 04000000 F7FFFFFF 03FF00FF |................|
|
||||
; NOTEXPR-NEXT: 0010: 02000000 02003C00 03000000 00000000 |......<.........|
|
||||
; NOTEXPR-NEXT: 0020: 00000000 00000000 22000050 00000A00 |........"..P....|
|
||||
; NOTEXPR-NEXT: 0030: 00000000 00000000 FFFF8000 00000000 |................|
|
||||
; NOTEXPR-NEXT: 0040: 00000000 00000000 01000050 00000000 |...........P....|
|
||||
; NOTEXPR-NEXT: 0050: 00000000 01000000 FFFF8000 00000000 |................|
|
||||
; NOTEXPR-NEXT: )
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user