X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Flexer%2Fmacro.c;fp=src%2Flanguage%2Flexer%2Fmacro.c;h=718f268e658505dd3c74f7e76cbafd3c28ad011e;hb=97650194a14bde3c89cf3164497d93a58110c23f;hp=fdf76bacea12b2a07d5d3e6ead9811e7cdb84922;hpb=25e92a9025f146d5880059f7e863d9c7944fafe6;p=pspp diff --git a/src/language/lexer/macro.c b/src/language/lexer/macro.c index fdf76bacea..718f268e65 100644 --- a/src/language/lexer/macro.c +++ b/src/language/lexer/macro.c @@ -32,6 +32,8 @@ #include "libpspp/str.h" #include "libpspp/string-array.h" +#include "gl/c-ctype.h" + #include "gettext.h" #define _(msgid) gettext (msgid) @@ -1099,19 +1101,52 @@ macro_evaluate_literal (const struct expr_context *ctx, .expand = ctx->expand, }; struct string function_output = DS_EMPTY_INITIALIZER; - size_t function_consumed; - if (expand_macro_function (&fctx, &function_output, &function_consumed)) + size_t function_consumed = parse_function_arg (&fctx, 0, &function_output); + *tokens = p + function_consumed; + return ds_steal_cstr (&function_output); +} + +/* Returns true if MT is valid as a macro operator. Only operators written as + symbols (e.g. <>) are usable in macro expressions, not operator written as + letters (e.g. EQ). */ +static bool +is_macro_operator (const struct macro_token *mt) +{ + return (mt->representation.length > 0 + && !c_isalpha (mt->representation.string[0])); +} + +static enum token_type +parse_relational_op (const struct macro_token *mt) +{ + switch (mt->token.type) { - *tokens = p + function_consumed; - return ds_steal_cstr (&function_output); - } + case T_EQUALS: + return T_EQ; - *tokens = p + 1; - return ss_xstrdup (p->representation); + case T_NE: + case T_LT: + case T_GT: + case T_LE: + case T_GE: + return is_macro_operator (mt) ? mt->token.type : T_STOP; + + case T_MACRO_ID: + return (ss_equals_case (mt->token.string, ss_cstr ("!EQ")) ? T_EQ + : ss_equals_case (mt->token.string, ss_cstr ("!NE")) ? T_NE + : ss_equals_case (mt->token.string, ss_cstr ("!LT")) ? T_LT + : ss_equals_case (mt->token.string, ss_cstr ("!GT")) ? T_GT + : ss_equals_case (mt->token.string, ss_cstr ("!LE")) ? T_LE + : ss_equals_case (mt->token.string, ss_cstr ("!GE")) ? T_GE + : T_STOP); + + default: + return T_STOP; + } } static char * -macro_evaluate_logical (const struct expr_context *ctx, +macro_evaluate_relational (const struct expr_context *ctx, const struct macro_token **tokens, const struct macro_token *end) { @@ -1120,9 +1155,8 @@ macro_evaluate_logical (const struct expr_context *ctx, if (!lhs) return NULL; - enum token_type op = p < end ? p->token.type : T_STOP; - if (op != T_EQUALS && op != T_EQ && op != T_NE && op != T_LT - && op != T_GT && op != T_LE && op != T_GE) + enum token_type op = p >= end ? T_STOP : parse_relational_op (p); + if (op == T_STOP) { *tokens = p; return lhs; @@ -1144,7 +1178,7 @@ macro_evaluate_logical (const struct expr_context *ctx, free (lhs); free (rhs); - + bool b = (op == T_EQUALS || op == T_EQ ? !cmp : op == T_NE ? cmp : op == T_LT ? cmp < 0 @@ -1164,13 +1198,15 @@ macro_evaluate_not (const struct expr_context *ctx, const struct macro_token *p = *tokens; unsigned int negations = 0; - while (p < end && p->token.type == T_NOT) + while (p < end + && (ss_equals_case (p->representation, ss_cstr ("!NOT")) + || ss_equals (p->representation, ss_cstr ("~")))) { p++; negations++; } - char *operand = macro_evaluate_logical (ctx, &p, end); + char *operand = macro_evaluate_relational (ctx, &p, end); if (!operand || !negations) { *tokens = p; @@ -1193,7 +1229,9 @@ macro_evaluate_and (const struct expr_context *ctx, if (!lhs) return NULL; - while (p < end && p->token.type == T_AND) + while (p < end + && (ss_equals_case (p->representation, ss_cstr ("!AND")) + || ss_equals (p->representation, ss_cstr ("&")))) { p++; char *rhs = macro_evaluate_not (ctx, &p, end); @@ -1222,7 +1260,9 @@ macro_evaluate_or (const struct expr_context *ctx, if (!lhs) return NULL; - while (p < end && p->token.type == T_OR) + while (p < end + && (ss_equals_case (p->representation, ss_cstr ("!OR")) + || ss_equals (p->representation, ss_cstr ("|")))) { p++; char *rhs = macro_evaluate_and (ctx, &p, end);