Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 3 commits
  • 12 files changed
  • 0 commit comments
  • 3 contributors
Commits on Apr 03, 2012
noid Adding support for the {%if_dir } structure in preprocessor expression 842f269
Commits on Apr 06, 2012
@hyqneuron hyqneuron Adding support for ?!:, the ternary conditional operator. Works like ?:
but !? is chosen instead of ? so as not to confuse nasm(? is recognised
as a proper part of an nasm identifier). Also added the %definex
directive, the content following which is fully expanded using
expand_smacro, so that concatenation of PP variables to produce new
variable names will be easier.
E.g.
%define p1 aaa
%define p2 bbb
%define p3 ccc
%definex p1 %+ p2 %+ p3 value; defines aaabbbccc to value
143f9b9
@cbergstrom cbergstrom Merge pull request #4 from houyunqing/master
Added features
6ba25af
View
1  include/yasmx/Op.h
@@ -70,6 +70,7 @@ namespace Op
GE, ///< Greater than or equal to comparison.
NE, ///< Not equal comparison.
NONNUM, ///< Start of non-numeric operations (not an op).
+ COND, ///< Ternary condition ?:
SEG, ///< SEG operator (gets segment portion of address).
/// WRT operator (gets offset of address relative to some other
/// segment).
View
38 lib/yasmx/Expr.cpp
@@ -663,6 +663,41 @@ Expr::LevelOp(Diagnostic& diags, bool simplify_reg_mul, int pos)
root.Clear();
return; // End immediately since we cleared root.
}
+ if(op == Op::COND)
+ {
+ //a !? b : c
+ if(!intchild)
+ {
+ //processing c
+ intchild = & child;
+ continue;
+ }
+ else if(!fltchild)
+ {
+ //processing b
+ fltchild = & child;
+ continue;
+ }
+ else
+ {
+ bool pickb=true;
+ //processing a
+ if(IntNum* intn = child.getIntNum())
+ pickb = !intn->isZero();
+ else if(llvm::APFloat* fltn = child.getFloat())
+ pickb = fltn->isNonZero();
+ else
+ {
+ //error. For now can only process int or float
+ }
+ child.Clear();
+ if(pickb)
+ intchild->Clear();
+ else
+ fltchild->Clear();
+ root.AddNumChild(-2);
+ }
+ }
again:
if (IntNum* intn = child.getIntNum())
@@ -717,8 +752,9 @@ Expr::LevelOp(Diagnostic& diags, bool simplify_reg_mul, int pos)
}
else if (llvm::APFloat* fltn = child.getFloat())
{
+ //FIXME: Should the LNOT operator work with float?
// currently can only handle 5 basic ops: +, -, *, /, %
- if (op >= Op::NEG)
+ if (op >= Op::NEG )
continue;
// if there's an integer child, upconvert it
View
1  lib/yasmx/Op.cpp
@@ -86,6 +86,7 @@ yasm::isAssociative(Op::Op op)
case Op::LAND:
case Op::LXOR:
case Op::LXNOR:
+ case Op::COND:
return true;
default:
return false;
View
8 modules/parsers/nasm/NasmLexer.cpp
@@ -411,11 +411,17 @@ NasmLexer::LexTokenInternal(Token* result)
kind = NasmToken::tilde;
break;
case '!':
- if (getCharAndSize(cur_ptr, &size_tmp) == '=')
+ ch = getCharAndSize(cur_ptr, &size_tmp);
+ if (ch == '=')
{
cur_ptr = ConsumeChar(cur_ptr, size_tmp, result);
kind = NasmToken::exclaimequal;
}
+ else if (ch == '?')
+ {
+ cur_ptr = ConsumeChar(cur_ptr, size_tmp, result);
+ kind = NasmToken::tern;
+ }
else
kind = NasmToken::exclaim;
break;
View
1  modules/parsers/nasm/NasmLexer.h
@@ -55,6 +55,7 @@ class NasmToken : public Token
slashslash, // //
percentpercent, // %%
caretcaret, // ^^
+ tern, // !?
// keywords
kw_abs,
kw_byte,
View
8 modules/parsers/nasm/NasmParser.cpp
@@ -222,7 +222,13 @@ NasmParser::Parse(Object& object, Directives& dirs, Diagnostic& diags)
return;
}
- //fputs(result.c_str(), stdout); // for debugging
+#if 0
+ fputs("=================\n", stdout);
+ fputs("=================\n", stdout);
+ fputs(result.c_str(), stdout); // for debugging
+ fputs("=================\n", stdout);
+ fputs("=================\n", stdout);
+#endif
// override main file with preprocessed source
const char* filename =
View
1  modules/parsers/nasm/NasmParser.h
@@ -116,6 +116,7 @@ class YASM_STD_EXPORT NasmParser : public ParserImpl
bool ParseSegOffExpr(Expr& e, const ParseExprTerm* parse_term = 0);
bool ParseExpr(Expr& e, const ParseExprTerm* parse_term = 0);
+ bool ParseExprc(Expr& e, const ParseExprTerm* parse_term);
bool ParseExpr0(Expr& e, const ParseExprTerm* parse_term);
bool ParseExpr1(Expr& e, const ParseExprTerm* parse_term);
bool ParseExpr2(Expr& e, const ParseExprTerm* parse_term);
View
39 modules/parsers/nasm/NasmParser_parse.cpp
@@ -1244,6 +1244,7 @@ NasmParser::ParseMemoryAddress()
//
// expr : bexpr [ : bexpr ]
// bexpr : expr0 [ WRT expr6 ]
+// exprc : expr0 [ !? expr0 : expr0...]
// expr0 : expr1 [ {|} expr1...]
// expr1 : expr2 [ {^} expr2...]
// expr2 : expr3 [ {&} expr3...]
@@ -1281,7 +1282,7 @@ NasmParser::ParseSegOffExpr(Expr& e, const ParseExprTerm* parse_term)
bool
NasmParser::ParseExpr(Expr& e, const ParseExprTerm* parse_term)
{
- if (!ParseExpr0(e, parse_term))
+ if (!ParseExprc(e, parse_term))
return false;
for (;;)
@@ -1304,6 +1305,32 @@ NasmParser::ParseExpr(Expr& e, const ParseExprTerm* parse_term)
}
bool
+NasmParser::ParseExprc(Expr& e, const ParseExprTerm* parse_term)
+{
+ if (!ParseExpr0(e, parse_term))
+ return false;
+ while (m_token.getKind()==NasmToken::tern)
+ {
+ SourceLocation op_source = ConsumeToken();
+ Expr f, f2;
+ if (!ParseExpr0(f, parse_term))
+ return false;
+ if (m_token.getKind() != NasmToken::colon) {
+ // FIXME: when user attempts to use floating point
+ // And error message?
+ return false;
+ }
+ ConsumeToken();
+ if (!ParseExpr0(f2, parse_term))
+ return false;
+ e.Append(f);
+ e.Append(f2);
+ e.AppendOp(Op::COND, 3, op_source);
+ }
+ return true;
+}
+
+bool
NasmParser::ParseExpr0(Expr& e, const ParseExprTerm* parse_term)
{
ParseExprCommon(ParseExpr1, NasmToken::pipe, ParseExpr1, Op::OR);
@@ -1543,6 +1570,16 @@ NasmParser::ParseExpr6(Expr& e, const ParseExprTerm* parse_term)
e.Calc(Op::NEG, op_source);
return true;
}
+ //the NasmToken::exclain thing isn't a proper part
+ //of NASM's syntax
+ case NasmToken::exclaim:
+ {
+ SourceLocation op_source = ConsumeToken();
+ if (!ParseExpr6(e, parse_term))
+ return false;
+ e.Calc(Op::LNOT, op_source);
+ return true;
+ }
case NasmToken::tilde:
{
SourceLocation op_source = ConsumeToken();
View
77 modules/parsers/nasm/nasm-eval.cpp
@@ -29,6 +29,7 @@ yasm::Object *yasm_object;
static scanner scan; /* Address of scanner routine */
static efunc error; /* Address of error reporting routine */
+static curl_eval curly_evaluator; /*curly structure processor func*/
static struct tokenval *tokval; /* The current token */
static int i; /* The t_type of tokval */
@@ -50,7 +51,8 @@ static void *scpriv;
* Grammar parsed is:
*
* expr : bexpr [ WRT expr6 ]
- * bexpr : rexp0 or expr0 depending on relative-mode setting
+ * bexpr : rexpc or expr0 depending on relative-mode setting
+ * rexpc : rexp0 [ ? rexp0 : rexp0...]
* rexp0 : rexp1 [ {||} rexp1...]
* rexp1 : rexp2 [ {^^} rexp2...]
* rexp2 : rexp3 [ {&&} rexp3...]
@@ -68,6 +70,7 @@ static void *scpriv;
* | number
*/
+static bool rexpc(Expr*);
static bool rexp0(Expr*), rexp1(Expr*), rexp2(Expr*), rexp3(Expr*);
static bool expr0(Expr*), expr1(Expr*), expr2(Expr*), expr3(Expr*);
@@ -75,6 +78,50 @@ static bool expr4(Expr*), expr5(Expr*), expr6(Expr*);
static bool (*bexpr)(Expr*);
+
+/*
+ * Added to process the !?: operand.
+ * !? is chosen instead of ? because ? can be recognised as a part or
+ * the beginning of an identifier in the nasm language.
+ */
+static bool rexpc(Expr* e)
+{
+ if (!rexp0(e))
+ return false;
+ while (i == TOKEN_TERN)
+ {
+ i = scan(scpriv, tokval);
+ Expr f, f2;
+ if (!rexp1(&f))
+ return false;
+ if (i != ':') {
+ /*
+ * FIXME: when user attempts to use floating point
+ * numbers, the dot will be an unrecognised token. If the
+ * float comes before :, then the following error line
+ * will be reported, which seems inappropriate.
+ */
+ error(ERR_FATAL, "expecting `:'");
+ return false;
+ }
+ i = scan(scpriv, tokval);
+ if (!rexp1(&f2))
+ return false;
+ /*
+ * yasm-nextgen currently has no handler for ternary operators
+ * so the e->Calc approach cannot be used here and the stuffs
+ * inside e->Calc is directly done here. Might not worth
+ * fixing anyway since the ?: is probably the only ternary
+ * operator that will be supported by yasm-nextgen
+ */
+ e->Append(f);
+ e->Append(f2);
+ e->AppendOp(yasm::Op::COND, 3);
+
+ }
+ return true;
+}
+
static bool rexp0(Expr* e)
{
if (!rexp1(e))
@@ -311,6 +358,17 @@ static bool expr6(Expr* e)
return false;
e->Calc(yasm::Op::NOT);
return true;
+ } else if (i == '!') {
+ /*
+ * This LNOT operator isn't a standard part of NASM's
+ * preprocessor expression syntax. Added here to get the work
+ * done.
+ */
+ i = scan(scpriv, tokval);
+ if (!expr6(e))
+ return false;
+ e->Calc(yasm::Op::LNOT);
+ return true;
} else if (i == TOKEN_SEG) {
i = scan(scpriv, tokval);
if (!expr6(e))
@@ -327,6 +385,17 @@ static bool expr6(Expr* e)
}
i = scan(scpriv, tokval);
return true;
+ } else if (i == '{' ) {
+ void* saved_priv = scpriv;
+ tokenval *saved_tok = tokval;
+ int j = curly_evaluator(scpriv);
+ scpriv = saved_priv;
+ tokval = saved_tok;
+ if( j == -1)
+ return false;
+ *e = Expr(IntNum(j));
+ i = scan(scpriv, tokval);
+ return true;
}
else if (i == TOKEN_NUM || i == TOKEN_ID ||
i == TOKEN_HERE || i == TOKEN_BASE)
@@ -368,14 +437,16 @@ static bool expr6(Expr* e)
}
Expr *nasm_evaluate (scanner sc, void *scprivate, struct tokenval *tv,
- int critical, efunc report_error)
+ int critical, efunc report_error,
+ curl_eval _curly_evaluator)
{
if (critical & CRITICAL) {
critical &= ~CRITICAL;
- bexpr = rexp0;
+ bexpr = rexpc;
} else
bexpr = expr0;
+ curly_evaluator = _curly_evaluator;
scan = sc;
scpriv = scprivate;
tokval = tv;
View
4 modules/parsers/nasm/nasm-eval.h
@@ -21,7 +21,9 @@ extern yasm::Object* yasm_object;
* The evaluator itself.
*/
yasm::Expr *nasm_evaluate (scanner sc, void *scprivate, struct tokenval *tv,
- int critical, efunc report_error);
+ int critical, efunc report_error,
+ curl_eval _curly_evaluator);
+
} // namespace nasm
View
304 modules/parsers/nasm/nasm-pp.cpp
@@ -56,6 +56,7 @@ using yasm::FileID;
using yasm::IntNum;
using yasm::SourceLocation;
+
namespace nasm {
int tasm_compatible_mode = 0;
@@ -357,7 +358,7 @@ static int inverse_ccs[] = {
*/
static const char *directives[] = {
"%arg",
- "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
+ "%assign", "%clear", "%define", "%definex", "%elif", "%elifctx", "%elifdef",
"%elifid", "%elifidn", "%elifidni", "%elifmacro", "%elifnctx", "%elifndef",
"%elifnid", "%elifnidn", "%elifnidni", "%elifnmacro", "%elifnnum", "%elifnstr",
"%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
@@ -374,7 +375,7 @@ static const char *directives[] = {
enum
{
PP_ARG,
- PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
+ PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_DEFINEX, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFMACRO, PP_ELIFNCTX, PP_ELIFNDEF,
PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNMACRO, PP_ELIFNNUM, PP_ELIFNSTR,
PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO,
@@ -440,6 +441,7 @@ static Line *builtindef = NULL;
static Line *stddef = NULL;
static Line *predef = NULL;
static int first_line = 1;
+static int curly_opened = 0;
/*
* The number of hash values we use for the macro lookup tables.
@@ -556,6 +558,7 @@ static Token *new_Token(Token * next, int type, const char *text,
size_t txtlen);
static Token *delete_Token(Token * t);
static Token *tokenise(char *line);
+static int evaluate_curly_brackets(void *private_data);
/*
* Macros for safe checking of token pointers, avoid *(NULL)
@@ -1486,7 +1489,8 @@ tokenise(char *line)
(p[0] == '<' && p[1] == '>') ||
(p[0] == '&' && p[1] == '&') ||
(p[0] == '|' && p[1] == '|') ||
- (p[0] == '^' && p[1] == '^'))
+ (p[0] == '^' && p[1] == '^') ||
+ (p[0] == '!' && p[1] == '?')) //ternary operator
{
p++;
}
@@ -1769,6 +1773,8 @@ ppscan(void *private_data, struct tokenval *tokval)
return tokval->t_type = TOKEN_NE;
if (!strcmp(tline->text, "!="))
return tokval->t_type = TOKEN_NE;
+ if (!strcmp(tline->text, "!?"))
+ return tokval->t_type = TOKEN_TERN;
if (!strcmp(tline->text, "<="))
return tokval->t_type = TOKEN_LE;
if (!strcmp(tline->text, ">="))
@@ -2081,6 +2087,7 @@ if_condition(Token * tline, int i)
switch (i)
{
+ //affected by {} structure
case PP_IFCTX:
case PP_ELIFCTX:
case PP_IFNCTX:
@@ -2103,9 +2110,11 @@ if_condition(Token * tline, int i)
}
if (i == PP_IFNCTX || i == PP_ELIFNCTX)
j = !j;
- free_tlist(origline);
+ if(curly_opened == 0)
+ free_tlist(origline);
return j;
+ //affected by {} structure
case PP_IFDEF:
case PP_ELIFDEF:
case PP_IFNDEF:
@@ -2121,7 +2130,8 @@ if_condition(Token * tline, int i)
error(ERR_NONFATAL,
"`%s' expects macro identifiers",
directives[i]);
- free_tlist(origline);
+ if(curly_opened == 0)
+ free_tlist(origline);
return -1;
}
if (smacro_defined(NULL, tline->text, 0, NULL, 1))
@@ -2130,9 +2140,11 @@ if_condition(Token * tline, int i)
}
if (i == PP_IFNDEF || i == PP_ELIFNDEF)
j = !j;
- free_tlist(origline);
+ if(curly_opened == 0)
+ free_tlist(origline);
return j;
+ //affected by {} structure
case PP_IFIDN:
case PP_ELIFIDN:
case PP_IFNIDN:
@@ -2150,7 +2162,8 @@ if_condition(Token * tline, int i)
error(ERR_NONFATAL,
"`%s' expects two comma-separated arguments",
directives[i]);
- free_tlist(tline);
+ if(curly_opened == 0)
+ free_tlist(tline);
return -1;
}
tt = tt->next;
@@ -2163,7 +2176,8 @@ if_condition(Token * tline, int i)
{
error(ERR_NONFATAL, "`%s': more than one comma on line",
directives[i]);
- free_tlist(tline);
+ if(curly_opened == 0)
+ free_tlist(tline);
return -1;
}
if (t->type == TOK_WHITESPACE)
@@ -2201,9 +2215,11 @@ if_condition(Token * tline, int i)
if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
i == PP_IFNIDNI || i == PP_ELIFNIDNI)
j = !j;
- free_tlist(tline);
+ if(curly_opened == 0)
+ free_tlist(tline);
return j;
+ //affected by {} structure
case PP_IFMACRO:
case PP_ELIFMACRO:
case PP_IFNMACRO:
@@ -2291,12 +2307,14 @@ if_condition(Token * tline, int i)
mmac = mmac->next;
}
nasm_free(searching.name);
- free_tlist(origline);
+ if(curly_opened == 0)
+ free_tlist(origline);
if (i == PP_IFNMACRO || i == PP_ELIFNMACRO)
found = !found;
return found;
}
+ //affected by {} structure
case PP_IFID:
case PP_ELIFID:
case PP_IFNID:
@@ -2340,7 +2358,8 @@ if_condition(Token * tline, int i)
i == PP_IFNNUM || i == PP_ELIFNNUM ||
i == PP_IFNSTR || i == PP_ELIFNSTR)
j = !j;
- free_tlist(tline);
+ if(curly_opened == 0)
+ free_tlist(tline);
return j;
case PP_IF:
@@ -2350,8 +2369,13 @@ if_condition(Token * tline, int i)
tptr = &t;
tokval.t_type = TOKEN_INVALID;
evalresult = evaluate(ppscan, tptr, &tokval, pass | CRITICAL,
- error);
- free_tlist(tline);
+ error, evaluate_curly_brackets);
+ /*
+ * Do not free if this function is invoked when processing
+ * a {%pp_id} structure, which is part of %if*** line
+ */
+ if(curly_opened == 0)
+ free_tlist(tline);
if (!evalresult)
return -1;
if (tokval.t_type)
@@ -2373,6 +2397,10 @@ if_condition(Token * tline, int i)
error(ERR_FATAL,
"preprocessor directive `%s' not yet implemented",
directives[i]);
+ /* this one doesn't need check curly_opened because it is
+ * not affected at all by the {} structure. If a directive
+ * is not recognised, it won't go through to this place
+ */
free_tlist(origline);
return -1; /* yeah, right */
}
@@ -2391,6 +2419,36 @@ expand_macros_in_string(char **p)
*p = detoken(line, FALSE);
}
+/*
+ * This function uses a binary search to find out what directive tline
+ * is. It is called by do_directive() and evaluate_curly_brackets()
+ */
+static void locate_directive(int &i, int &j, int&k, Token *tline)
+{
+ int m;
+ i = -1;
+ j = elements(directives);
+ while (j - i > 1)
+ {
+ k = (j + i) / 2;
+ m = nasm_stricmp(tline->text, directives[k]);
+ if (m == 0) {
+ if (tasm_compatible_mode) {
+ i = k;
+ j = -2;
+ } else if (k != PP_ARG && k != PP_LOCAL && k != PP_STACKSIZE) {
+ i = k;
+ j = -2;
+ }
+ break;
+ }
+ else if (m < 0) {
+ j = k;
+ }
+ else
+ i = k;
+ }
+}
/**
* find and process preprocessor directive in passed line
* Find out if a line contains a preprocessor directive, and deal
@@ -2427,29 +2485,7 @@ do_directive(Token * tline)
(tline->text[1] == '%' || tline->text[1] == '$'
|| tline->text[1] == '!'))
return NO_DIRECTIVE_FOUND;
-
- i = -1;
- j = elements(directives);
- while (j - i > 1)
- {
- k = (j + i) / 2;
- m = nasm_stricmp(tline->text, directives[k]);
- if (m == 0) {
- if (tasm_compatible_mode) {
- i = k;
- j = -2;
- } else if (k != PP_ARG && k != PP_LOCAL && k != PP_STACKSIZE) {
- i = k;
- j = -2;
- }
- break;
- }
- else if (m < 0) {
- j = k;
- }
- else
- i = k;
- }
+ locate_directive(i,j,k, tline);
/*
* If we're in a non-emitting branch of a condition construct,
@@ -3197,8 +3233,10 @@ do_directive(Token * tline)
tline = t;
tptr = &t;
tokval.t_type = TOKEN_INVALID;
- evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
- free_tlist(tline);
+ evalresult = evaluate(ppscan, tptr, &tokval, pass, error,
+ evaluate_curly_brackets);
+ if(curly_opened == 0)
+ free_tlist(tline);
if (!evalresult)
return DIRECTIVE_FOUND;
if (tokval.t_type)
@@ -3256,10 +3294,12 @@ do_directive(Token * tline)
t = expand_smacro(tline);
tptr = &t;
tokval.t_type = TOKEN_INVALID;
- evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
+ evalresult = evaluate(ppscan, tptr, &tokval, pass, error,
+ evaluate_curly_brackets);
if (!evalresult)
{
- free_tlist(origline);
+ if(curly_opened == 0)
+ free_tlist(origline);
return DIRECTIVE_FOUND;
}
if (tokval.t_type)
@@ -3350,9 +3390,13 @@ do_directive(Token * tline)
case PP_IXDEFINE:
case PP_DEFINE:
case PP_IDEFINE:
+ case PP_DEFINEX:
tline = tline->next;
skip_white_(tline);
- tline = expand_id(tline);
+ if(i!=PP_DEFINEX)
+ tline = expand_id(tline);
+ else
+ tline = expand_smacro(tline);
if (!tline || (tline->type != TOK_ID &&
(tline->type != TOK_PREPROC_ID ||
tline->text[1] != '$')))
@@ -3659,7 +3703,8 @@ do_directive(Token * tline)
tt = t->next;
tptr = &tt;
tokval.t_type = TOKEN_INVALID;
- evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
+ evalresult = evaluate(ppscan, tptr, &tokval, pass, error,
+ evaluate_curly_brackets);
if (!evalresult)
{
free_tlist(tline);
@@ -3759,8 +3804,10 @@ do_directive(Token * tline)
t = tline;
tptr = &t;
tokval.t_type = TOKEN_INVALID;
- evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
- free_tlist(tline);
+ evalresult = evaluate(ppscan, tptr, &tokval, pass, error,
+ evaluate_curly_brackets);
+ if(curly_opened == 0)
+ free_tlist(tline);
if (!evalresult)
{
free_tlist(origline);
@@ -4191,8 +4238,72 @@ expand_smacro(Token * tline)
tail = &thead;
thead = NULL;
+ /*
+ * curl_valid represents if we're inside a valid {%pp_dir}
+ * structure. curl_valid_opened is the number of nested {}s
+ * currently encountered
+ */
+ bool curl_valid = false;
+ int curl_valid_opened = 0;
while (tline)
{ /* main token loop */
+ /* if we encounter {%if*** }, the part inside the {} won't get
+ * expanded. They are left as-is for the corresponding
+ * directive handlers to process.
+ *
+ * { needs processing both when we're in a valid {%pp_dir}
+ * section and when we are not, as we need to keep track of
+ * the curl_valid_opened when it's valid, and inspect and mark
+ * it as valid when it's not.
+ */
+ if(tok_is_(tline, "{") )
+ {
+ if(curl_valid)
+ {
+ ++curl_valid_opened;
+ goto smacro_skip;
+ }
+
+ /*
+ * now check for %%pp_dir to decide if it should be marked
+ * as valid
+ */
+ Token *curlstart = tline;
+ tline = tline->next;
+ skip_white_(tline);
+ if(tok_type_(tline, TOK_PREPROC_ID))
+ {
+ int i,j,k;
+ locate_directive(i, j, k, tline);
+ if(j == -2 && i >= PP_IF && i <= PP_IFSTR)
+ {
+ curl_valid = true;
+ curl_valid_opened = 0;
+ }
+ }
+ //put the "{ %pp_dir" into the expanded line
+ t = *tail = curlstart;
+ while(t != tline)
+ {
+ tail = &t->next;
+ t->mac = NULL;
+ t = t->next;
+ }
+ if(!tline)break;
+ goto smacro_skip;
+ }
+ else if(curl_valid)
+ {
+ if(tok_is_(tline, "}" ))
+ {
+ --curl_valid_opened;
+ if(curl_valid_opened == -1)
+ curl_valid = false;
+ }
+ goto smacro_skip;
+ }
+
+ //start of expansion
if ((mname = tline->text))
{
/* if this token is a local macro, look in local context */
@@ -4457,6 +4568,7 @@ expand_smacro(Token * tline)
}
else
{
+ smacro_skip:
t = *tail = tline;
tline = tline->next;
t->mac = NULL;
@@ -5393,4 +5505,108 @@ Preproc nasmpp = {
pp_cleanup
};
+/*
+ * This function processes the {%pp_dir} structure inside a
+ * preprocessor expression. It is called by nasm-eval.cpp::expr6()
+ * A %pp_dir is a preprocessor directive that starts with %if,
+ * including %if itself.
+ *
+ * This function cuts out the part enclosed by {}, and sends this
+ * partial line to be evaluated using if_condition() and returns the
+ * result of the evaluation. if_condition() has been modified so that
+ * it frees the partial line sent to it only when it is not evaluating
+ * something inside the {%pp_dir} structure.
+ */
+static int evaluate_curly_brackets(void *private_data)
+{
+ //t1 is a Token** that points to the first token after '{'
+ Token **t1 = (Token**)private_data;
+ //First we'll find the corresponding '}' to cut off
+ Token *t_head = *t1;
+ Token *t_end = t_head;//t_end shall be the token for '}'
+ Token *t_last = NULL; //the token before end.
+ int num_open=0, num_close = 0; //number of { and } encountered
+ int i,j;
+
+ ++curly_opened; /* informs if_condition() we're processing a
+ {%pp_dir} so that it will not free the line sent to it */
+
+ while(t_end)
+ {
+ if(tok_is_(t_end, "}"))
+ {
+ ++num_close;
+ if( num_close > num_open )
+ break;
+ }
+ else if(tok_is_(t_end, "{"))
+ ++num_open;
+ t_last= t_end;
+ t_end = t_end->next;
+ }
+ if( num_close <= num_open)
+ {
+ error(ERR_FATAL, "{ and } must appear in pairs");
+ return -1;
+ }
+ //till this point, t_end = }, t_last is the ending token in the {}
+ if(t_head == t_end)
+ {
+ error(ERR_FATAL, "{} must contain a conditional directive");
+ return -1;
+ }
+ t_last->next = NULL; //cut it off for processing. Recover later
+ skip_white_(t_head); // enough? multiple ws?
+ if(!tok_type_(t_head, TOK_PREPROC_ID))
+ {
+ error(ERR_FATAL, "the content inside {} must start with a conditional preprocessor directive");
+ return -1;
+ }
+
+ //Start binary search
+ int k;
+ locate_directive(i,j,k, t_head);
+ if (j != -2)
+ {
+ error(ERR_FATAL, "inside {}, unknown preprocessor directive `%s'", t_head->text);
+ return -1;
+ }
+ if( i < PP_IF || i > PP_IFSTR)
+ {
+ error(ERR_FATAL, "inside {}, only conditional preprocessor directives may be used (those that start with 'if')");
+ return -1;
+ }
+ //Only %if to %ifstr will go through to this if_condition
+ j = if_condition(t_head->next, i);
+ //stick back the part that we cut off
+ t_last->next = t_end;
+ //point private data to the unprocessed token
+ //(used in nasm-eval.cpp)
+ *t1 = t_end->next;
+ --curly_opened;
+ return j;
+}
+/* Note:
+ * 1. Maybe the {} structure shouldn't appear in just any preprocessor
+ * expression. Maybe something should be set in 'critical' to help
+ * expr6 identify whether this structure should be recognised
+ * 2. the function above needs to verify if the curly brackets contain
+ * anything at all. It should be able to find '%' followed by an
+ * acceptable PP directive:
+ * if, ifctx, ifdef, ifid, ifidn, ifidni, ifmacro, ifnctx,
+ * ifndef, ifnid, ifnidn, ifnidni, ifnmacro, ifnnum,
+ * ifnstr, ifnum, ifstr
+ * If no %directive is found, it should report an error
+ * 3. The structure %{pp_id} will not interrupt this {%pp_dir}
+ * structure as %{pp_id} is expanded before processed. However, in
+ * case expansion fails... nasm doesn't do this properly.
+ */
+
+/* evaluate_curly_brackets structure:
+ * 1. Find the right }
+ * 2. Binary search, find the index for the contained directive
+ * 3. Call if_condition to process the identified section
+ * 4. Return result
+ */
+
} // namespace nasm
View
11 modules/parsers/nasm/nasm.h
@@ -163,6 +163,12 @@ struct tokenval {
};
typedef int (*scanner) (void *private_data, struct tokenval *tv);
+
+/*
+ * Processing function of {%pp_dir} structure
+ */
+typedef int (*curl_eval) (void *private_data);
+
/*
* Token types returned by the scanner, in addition to ordinary
* ASCII character values, and zero for end-of-string.
@@ -180,6 +186,7 @@ enum { /* token types, other than chars */
TOKEN_SDIV, TOKEN_SMOD, /* // and %% */
TOKEN_GE, TOKEN_LE, TOKEN_NE, /* >=, <= and <> (!= is same as <>) */
TOKEN_DBL_AND, TOKEN_DBL_OR, TOKEN_DBL_XOR, /* &&, || and ^^ */
+ TOKEN_TERN, /* !? ternary condition operator*/
TOKEN_SEG, TOKEN_WRT, /* SEG and WRT */
TOKEN_FLOAT /* floating-point constant */
};
@@ -204,7 +211,9 @@ enum { /* token types, other than chars */
*/
#define CRITICAL 0x100
typedef yasm::Expr *(*evalfunc) (scanner sc, void *scprivate, struct tokenval *tv,
- int critical, efunc error);
+ int critical, efunc error,
+ curl_eval curly_evaluator);
+
/*
* Preprocessors ought to look like this:

No commit comments for this range

Something went wrong with that request. Please try again.