From 97bbe4d0d87c81ed1b205feb294d60ab57438bc5 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 4 Jul 2021 15:56:34 -0700 Subject: [PATCH 1/1] Move stack into macro_expander. --- src/language/lexer/macro.c | 232 +++++++++++++++---------------- tests/language/control/define.at | 24 ++-- 2 files changed, 127 insertions(+), 129 deletions(-) diff --git a/src/language/lexer/macro.c b/src/language/lexer/macro.c index 3b17d90f38..c35144dc3a 100644 --- a/src/language/lexer/macro.c +++ b/src/language/lexer/macro.c @@ -874,6 +874,7 @@ struct macro_expander bool *expand; bool *break_; int nesting_countdown; + const struct macro_expansion_stack *stack; }; /* Each argument to a macro function is one of: @@ -895,12 +896,10 @@ struct parse_macro_function_ctx const struct macro_token *input; size_t n_input; const struct macro_expander *me; - const struct macro_expansion_stack *stack; }; static void macro_expand (const struct macro_tokens *, const struct macro_expander *, - const struct macro_expansion_stack *, struct macro_tokens *); static bool @@ -972,7 +971,6 @@ parse_function_arg (struct parse_macro_function_ctx *ctx, .input = &ctx->input[i], .n_input = ctx->n_input - i, .me = ctx->me, - .stack = ctx->stack, }; size_t subinput_consumed; if (expand_macro_function (&subctx, farg, &subinput_consumed)) @@ -1000,7 +998,7 @@ parse_macro_function (struct parse_macro_function_ctx *ctx, if (n_tokens < 2 || tokens[1].token.type != T_LPAREN) { - macro_error (ctx->stack, n_tokens > 1 ? &tokens[1] : NULL, + macro_error (ctx->me->stack, n_tokens > 1 ? &tokens[1] : NULL, _("`(' expected following %s."), function.string); return false; } @@ -1016,7 +1014,7 @@ parse_macro_function (struct parse_macro_function_ctx *ctx, *input_consumed = i + 1; if (args->n < min_args || args->n > max_args) { - macro_error (ctx->stack, &tokens[i], + macro_error (ctx->me->stack, &tokens[i], _("Wrong number of arguments to macro function %s."), function.string); goto error; @@ -1037,7 +1035,7 @@ parse_macro_function (struct parse_macro_function_ctx *ctx, i++; else if (tokens[i].token.type != T_RPAREN) { - macro_error (ctx->stack, &tokens[i], + macro_error (ctx->me->stack, &tokens[i], _("`,' or `)' expected in call to macro function %s."), function.string); goto error; @@ -1045,7 +1043,7 @@ parse_macro_function (struct parse_macro_function_ctx *ctx, } unexpected_end: - macro_error (ctx->stack, NULL, _("Missing `)' in call to macro function %s."), + macro_error (ctx->me->stack, NULL, _("Missing `)' in call to macro function %s."), function.string); /* Fall through. */ error: @@ -1119,7 +1117,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, int n; if (!parse_integer (args.strings[0], &n)) { - macro_error (ctx->stack, NULL, + macro_error (ctx->me->stack, NULL, _("Argument to !BLANKS must be non-negative integer " "(not \"%s\")."), args.strings[0]); string_array_destroy (&args); @@ -1144,7 +1142,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, struct macro_tokens mts = { .n = 0 }; macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->me->segmenter_mode, - ctx->stack); + ctx->me->stack); if (mts.n > 0) ds_put_substring (output, mts.mts[0].representation); macro_tokens_uninit (&mts); @@ -1181,7 +1179,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, int start; if (!parse_integer (args.strings[1], &start) || start < 1) { - macro_error (ctx->stack, NULL, + macro_error (ctx->me->stack, NULL, _("Second argument of !SUBSTR must be " "positive integer (not \"%s\")."), args.strings[1]); @@ -1192,7 +1190,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, int count = INT_MAX; if (args.n > 2 && (!parse_integer (args.strings[2], &count) || count < 0)) { - macro_error (ctx->stack, NULL, + macro_error (ctx->me->stack, NULL, _("Third argument of !SUBSTR must be " "non-negative integer (not \"%s\")."), args.strings[2]); @@ -1212,7 +1210,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, struct macro_tokens mts = { .n = 0 }; macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->me->segmenter_mode, - ctx->stack); + ctx->me->stack); if (mts.n > 1) { struct macro_tokens tail = { .mts = mts.mts + 1, .n = mts.n - 1 }; @@ -1243,15 +1241,17 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, { struct macro_tokens mts = { .n = 0 }; macro_tokens_from_string__ (&mts, ss_cstr (args.strings[0]), - ctx->me->segmenter_mode, ctx->stack); + ctx->me->segmenter_mode, ctx->me->stack); struct macro_tokens exp = { .n = 0 }; + struct macro_expansion_stack stack = { + .name = "!EVAL", + .next = ctx->me->stack + }; struct macro_expander subme = *ctx->me; subme.break_ = NULL; - macro_expand (&mts, &subme, - &(struct macro_expansion_stack) { - .name = "!EVAL", - .next = ctx->stack, - }, &exp); + subme.stack = &stack; + + macro_expand (&mts, &subme, &exp); macro_tokens_to_representation (&exp, output, NULL, NULL); macro_tokens_uninit (&exp); macro_tokens_uninit (&mts); @@ -1271,13 +1271,11 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, } static char *macro_evaluate_or (const struct macro_expander *me, - const struct macro_expansion_stack *stack, const struct macro_token **tokens, const struct macro_token *end); static char * macro_evaluate_literal (const struct macro_expander *me, - const struct macro_expansion_stack *stack, const struct macro_token **tokens, const struct macro_token *end) { @@ -1287,13 +1285,13 @@ macro_evaluate_literal (const struct macro_expander *me, if (p->token.type == T_LPAREN) { p++; - char *value = macro_evaluate_or (me, stack, &p, end); + char *value = macro_evaluate_or (me, &p, end); if (!value) return NULL; if (p >= end || p->token.type != T_RPAREN) { free (value); - macro_error (stack, p < end ? p : NULL, + macro_error (me->stack, p < end ? p : NULL, _("Expecting ')' in macro expression.")); return NULL; } @@ -1303,8 +1301,8 @@ macro_evaluate_literal (const struct macro_expander *me, } else if (p->token.type == T_RPAREN) { - macro_error (stack, p, _("Expecting literal or function invocation " - "in macro expression.")); + macro_error (me->stack, p, _("Expecting literal or function invocation " + "in macro expression.")); return NULL; } @@ -1312,7 +1310,6 @@ macro_evaluate_literal (const struct macro_expander *me, .input = p, .n_input = end - p, .me = me, - .stack = stack, }; struct string function_output = DS_EMPTY_INITIALIZER; size_t function_consumed = parse_function_arg (&fctx, 0, &function_output); @@ -1368,12 +1365,11 @@ parse_relational_op (const struct macro_token *mt) static char * macro_evaluate_relational (const struct macro_expander *me, - const struct macro_expansion_stack *stack, const struct macro_token **tokens, const struct macro_token *end) { const struct macro_token *p = *tokens; - char *lhs = macro_evaluate_literal (me, stack, &p, end); + char *lhs = macro_evaluate_literal (me, &p, end); if (!lhs) return NULL; @@ -1385,7 +1381,7 @@ macro_evaluate_relational (const struct macro_expander *me, } p++; - char *rhs = macro_evaluate_literal (me, stack, &p, end); + char *rhs = macro_evaluate_literal (me, &p, end); if (!rhs) { free (lhs); @@ -1416,7 +1412,6 @@ macro_evaluate_relational (const struct macro_expander *me, static char * macro_evaluate_not (const struct macro_expander *me, - const struct macro_expansion_stack *stack, const struct macro_token **tokens, const struct macro_token *end) { @@ -1431,7 +1426,7 @@ macro_evaluate_not (const struct macro_expander *me, negations++; } - char *operand = macro_evaluate_relational (me, stack, &p, end); + char *operand = macro_evaluate_relational (me, &p, end); if (!operand || !negations) { *tokens = p; @@ -1446,12 +1441,11 @@ macro_evaluate_not (const struct macro_expander *me, static char * macro_evaluate_and (const struct macro_expander *me, - const struct macro_expansion_stack *stack, const struct macro_token **tokens, const struct macro_token *end) { const struct macro_token *p = *tokens; - char *lhs = macro_evaluate_not (me, stack, &p, end); + char *lhs = macro_evaluate_not (me, &p, end); if (!lhs) return NULL; @@ -1460,7 +1454,7 @@ macro_evaluate_and (const struct macro_expander *me, || ss_equals (p->representation, ss_cstr ("&")))) { p++; - char *rhs = macro_evaluate_not (me, stack, &p, end); + char *rhs = macro_evaluate_not (me, &p, end); if (!rhs) { free (lhs); @@ -1478,12 +1472,11 @@ macro_evaluate_and (const struct macro_expander *me, static char * macro_evaluate_or (const struct macro_expander *me, - const struct macro_expansion_stack *stack, const struct macro_token **tokens, const struct macro_token *end) { const struct macro_token *p = *tokens; - char *lhs = macro_evaluate_and (me, stack, &p, end); + char *lhs = macro_evaluate_and (me, &p, end); if (!lhs) return NULL; @@ -1492,7 +1485,7 @@ macro_evaluate_or (const struct macro_expander *me, || ss_equals (p->representation, ss_cstr ("|")))) { p++; - char *rhs = macro_evaluate_and (me, stack, &p, end); + char *rhs = macro_evaluate_and (me, &p, end); if (!rhs) { free (lhs); @@ -1510,27 +1503,25 @@ macro_evaluate_or (const struct macro_expander *me, static char * macro_evaluate_expression (const struct macro_token **tokens, size_t n_tokens, - const struct macro_expander *me, - const struct macro_expansion_stack *stack) + const struct macro_expander *me) { - return macro_evaluate_or (me, stack, tokens, *tokens + n_tokens); + return macro_evaluate_or (me, tokens, *tokens + n_tokens); } static bool macro_evaluate_number (const struct macro_token **tokens, size_t n_tokens, const struct macro_expander *me, - const struct macro_expansion_stack *stack, double *number) { - char *s = macro_evaluate_expression (tokens, n_tokens, me, stack); + char *s = macro_evaluate_expression (tokens, n_tokens, me); if (!s) return false; struct macro_tokens mts = { .n = 0 }; - macro_tokens_from_string__ (&mts, ss_cstr (s), me->segmenter_mode, stack); + macro_tokens_from_string__ (&mts, ss_cstr (s), me->segmenter_mode, me->stack); if (mts.n != 1 || !token_is_number (&mts.mts[0].token)) { - macro_error (stack, mts.n > 0 ? &mts.mts[0] : NULL, + macro_error (me->stack, mts.n > 0 ? &mts.mts[0] : NULL, _("Macro expression must evaluate to " "a number (not \"%s\")."), s); free (s); @@ -1570,7 +1561,6 @@ find_ifend_clause (const struct macro_token *p, const struct macro_token *end) static size_t macro_expand_if (const struct macro_token *tokens, size_t n_tokens, const struct macro_expander *me, - const struct macro_expansion_stack *stack, struct macro_tokens *exp) { const struct macro_token *p = tokens; @@ -1580,7 +1570,7 @@ macro_expand_if (const struct macro_token *tokens, size_t n_tokens, return 0; p++; - char *result = macro_evaluate_expression (&p, end - p, me, stack); + char *result = macro_evaluate_expression (&p, end - p, me); if (!result) return 0; bool b = strcmp (result, "0"); @@ -1590,7 +1580,7 @@ macro_expand_if (const struct macro_token *tokens, size_t n_tokens, || p->token.type != T_MACRO_ID || !ss_equals_case (p->token.string, ss_cstr ("!THEN"))) { - macro_error (stack, p < end ? p : NULL, + macro_error (me->stack, p < end ? p : NULL, _("!THEN expected in macro !IF construct.")); return 0; } @@ -1599,7 +1589,7 @@ macro_expand_if (const struct macro_token *tokens, size_t n_tokens, const struct macro_token *end_then = find_ifend_clause (start_then, end); if (!end_then) { - macro_error (stack, NULL, + macro_error (me->stack, NULL, _("!ELSE or !IFEND expected in macro !IF construct.")); return 0; } @@ -1612,7 +1602,7 @@ macro_expand_if (const struct macro_token *tokens, size_t n_tokens, if (!end_if || !ss_equals_case (end_if->token.string, ss_cstr ("!IFEND"))) { - macro_error (stack, end_if ? end_if : NULL, + macro_error (me->stack, end_if ? end_if : NULL, _("!IFEND expected in macro !IF construct.")); return 0; } @@ -1647,19 +1637,20 @@ macro_expand_if (const struct macro_token *tokens, size_t n_tokens, .mts = CONST_CAST (struct macro_token *, start), .n = n, }; - macro_expand (&mts, me, &(struct macro_expansion_stack) { - .name = "!IF", - .next = stack, - }, - exp); + struct macro_expansion_stack stack = { + .name = "!IF", + .next = me->stack, + }; + struct macro_expander subme = *me; + subme.stack = &stack; + macro_expand (&mts, &subme, exp); } return (end_if + 1) - tokens; } static size_t macro_parse_let (const struct macro_token *tokens, size_t n_tokens, - const struct macro_expander *me, - const struct macro_expansion_stack *stack) + const struct macro_expander *me) { const struct macro_token *p = tokens; const struct macro_token *end = tokens + n_tokens; @@ -1670,7 +1661,7 @@ macro_parse_let (const struct macro_token *tokens, size_t n_tokens, if (p >= end || p->token.type != T_MACRO_ID) { - macro_error (stack, p < end ? p : NULL, + macro_error (me->stack, p < end ? p : NULL, _("Expected macro variable name following !LET.")); return 0; } @@ -1678,7 +1669,7 @@ macro_parse_let (const struct macro_token *tokens, size_t n_tokens, if (is_macro_keyword (var_name) || (me->macro && macro_find_parameter_by_name (me->macro, var_name))) { - macro_error (stack, p < end ? p : NULL, + macro_error (me->stack, p < end ? p : NULL, _("Cannot use argument name or macro keyword " "\"%.*s\" as !LET variable."), (int) var_name.length, var_name.string); @@ -1688,13 +1679,13 @@ macro_parse_let (const struct macro_token *tokens, size_t n_tokens, if (p >= end || p->token.type != T_EQUALS) { - macro_error (stack, p < end ? p : NULL, + macro_error (me->stack, p < end ? p : NULL, _("Expected `=' following !LET.")); return 0; } p++; - char *value = macro_evaluate_expression (&p, end - p, me, stack); + char *value = macro_evaluate_expression (&p, end - p, me); if (!value) return 0; @@ -1728,7 +1719,6 @@ find_doend (const struct macro_expansion_stack *stack, static size_t macro_expand_do (const struct macro_token *tokens, size_t n_tokens, const struct macro_expander *me, - const struct macro_expansion_stack *stack, struct macro_tokens *exp) { const struct macro_token *p = tokens; @@ -1740,7 +1730,7 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, if (p >= end || p->token.type != T_MACRO_ID) { - macro_error (stack, p < end ? p : NULL, + macro_error (me->stack, p < end ? p : NULL, _("Expected macro variable name following !DO.")); return 0; } @@ -1748,30 +1738,36 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, if (is_macro_keyword (var_name) || (me->macro && macro_find_parameter_by_name (me->macro, var_name))) { - macro_error (stack, p, _("Cannot use argument name or macro " + macro_error (me->stack, p, _("Cannot use argument name or macro " "keyword as !DO variable.")); return 0; } p++; - struct macro_expansion_stack next_stack = { - .name = "!DO", .next = stack, + struct macro_expansion_stack substack = { + .name = "!DO", + .next = me->stack, }; + bool break_ = false; + struct macro_expander subme = *me; + subme.break_ = &break_; + subme.stack = &substack; + int miterate = settings_get_miterate (); if (p < end && p->token.type == T_MACRO_ID && ss_equals_case (p->token.string, ss_cstr ("!IN"))) { p++; - char *list = macro_evaluate_expression (&p, end - p, me, &next_stack); + char *list = macro_evaluate_expression (&p, end - p, &subme); if (!list) return 0; struct macro_tokens items = { .n = 0 }; macro_tokens_from_string__ (&items, ss_cstr (list), me->segmenter_mode, - stack); + me->stack); free (list); - const struct macro_token *do_end = find_doend (stack, p, end); + const struct macro_token *do_end = find_doend (subme.stack, p, end); if (!do_end) { macro_tokens_uninit (&items); @@ -1783,15 +1779,11 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, .n = do_end - p }; - bool break_ = false; - struct macro_expander subme = *me; - subme.break_ = &break_; - for (size_t i = 0; i < items.n && !break_; i++) { if (i >= miterate) { - macro_error (stack, NULL, + macro_error (&substack, NULL, _("!DO loop over list exceeded " "maximum number of iterations %d. " "(Use SET MITERATE to change the limit.)"), @@ -1801,7 +1793,7 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, stringi_map_replace_nocopy (me->vars, ss_xstrdup (var_name), ss_xstrdup (items.mts[i].representation)); - macro_expand (&inner, &subme, &next_stack, exp); + macro_expand (&inner, &subme, exp); } return do_end - tokens + 1; } @@ -1809,20 +1801,20 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, { p++; double first; - if (!macro_evaluate_number (&p, end - p, me, &next_stack, &first)) + if (!macro_evaluate_number (&p, end - p, &subme, &first)) return 0; if (p >= end || p->token.type != T_MACRO_ID || !ss_equals_case (p->token.string, ss_cstr ("!TO"))) { - macro_error (stack, p < end ? p : NULL, + macro_error (subme.stack, p < end ? p : NULL, _("Expected !TO in numerical !DO loop.")); return 0; } p++; double last; - if (!macro_evaluate_number (&p, end - p, me, &next_stack, &last)) + if (!macro_evaluate_number (&p, end - p, &subme, &last)) return 0; double by = 1.0; @@ -1830,17 +1822,17 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, && ss_equals_case (p->token.string, ss_cstr ("!BY"))) { p++; - if (!macro_evaluate_number (&p, end - p, me, &next_stack, &by)) + if (!macro_evaluate_number (&p, end - p, &subme, &by)) return 0; if (by == 0.0) { - macro_error (stack, NULL, _("!BY value cannot be zero.")); + macro_error (subme.stack, NULL, _("!BY value cannot be zero.")); return 0; } } - const struct macro_token *do_end = find_doend (stack, p, end); + const struct macro_token *do_end = find_doend (subme.stack, p, end); if (!do_end) return 0; const struct macro_tokens inner = { @@ -1848,10 +1840,6 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, .n = do_end - p }; - bool break_ = false; - struct macro_expander subme = *me; - subme.break_ = &break_; - if ((by > 0 && first <= last) || (by < 0 && first >= last)) { int i = 0; @@ -1861,7 +1849,7 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, { if (i++ > miterate) { - macro_error (stack, NULL, + macro_error (subme.stack, NULL, _("Numerical !DO loop exceeded " "maximum number of iterations %d. " "(Use SET MITERATE to change the limit.)"), @@ -1874,7 +1862,7 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, stringi_map_replace_nocopy (me->vars, ss_xstrdup (var_name), xstrdup (index_s)); - macro_expand (&inner, &subme, &next_stack, exp); + macro_expand (&inner, &subme, exp); } } @@ -1882,7 +1870,7 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, } else { - macro_error (stack, p < end ? p : NULL, + macro_error (me->stack, p < end ? p : NULL, _("Expected `=' or !IN in !DO loop.")); return 0; } @@ -1891,13 +1879,12 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, static void macro_expand (const struct macro_tokens *mts, const struct macro_expander *me, - const struct macro_expansion_stack *stack, struct macro_tokens *exp) { if (me->nesting_countdown <= 0) { - macro_error (stack, NULL, _("Maximum nesting level %d exceeded. " - "(Use SET MNEST to change the limit.)"), + macro_error (me->stack, NULL, _("Maximum nesting level %d exceeded. " + "(Use SET MNEST to change the limit.)"), settings_get_mnest ()); for (size_t i = 0; i < mts->n; i++) macro_tokens_add (exp, &mts->mts[i]); @@ -1919,6 +1906,10 @@ macro_expand (const struct macro_tokens *mts, if (*me->expand && param->expand_arg) { struct stringi_map vars = STRINGI_MAP_INITIALIZER (vars); + struct macro_expansion_stack stack = { + .name = param->name, + .next = me->stack, + }; struct macro_expander subme = { .macros = me->macros, .macro = NULL, @@ -1928,11 +1919,9 @@ macro_expand (const struct macro_tokens *mts, .break_ = NULL, .vars = &vars, .nesting_countdown = me->nesting_countdown, + .stack = &stack, }; - macro_expand (arg, &subme, &(struct macro_expansion_stack) { - .name = param->name, - .next = stack, - }, exp); + macro_expand (arg, &subme, exp); stringi_map_destroy (&vars); } else @@ -1953,6 +1942,10 @@ macro_expand (const struct macro_tokens *mts, if (*me->expand && param->expand_arg) { struct stringi_map vars = STRINGI_MAP_INITIALIZER (vars); + struct macro_expansion_stack stack = { + .name = "!*", + .next = me->stack, + }; struct macro_expander subme = { .macros = me->macros, .macro = NULL, @@ -1962,12 +1955,9 @@ macro_expand (const struct macro_tokens *mts, .break_ = NULL, .vars = &vars, .nesting_countdown = me->nesting_countdown, + .stack = &stack, }; - macro_expand (arg, &subme, - &(struct macro_expansion_stack) { - .name = "!*", - .next = stack, - }, exp); + macro_expand (arg, &subme, exp); stringi_map_destroy (&vars); } else @@ -1978,8 +1968,7 @@ macro_expand (const struct macro_tokens *mts, continue; } - size_t n = macro_expand_if (&mts->mts[i], mts->n - i, me, stack, - exp); + size_t n = macro_expand_if (&mts->mts[i], mts->n - i, me, exp); if (n > 0) { i += n - 1; @@ -1995,7 +1984,7 @@ macro_expand (const struct macro_tokens *mts, if (value) { macro_tokens_from_string__ (exp, ss_cstr (value), - me->segmenter_mode, stack); + me->segmenter_mode, me->stack); continue; } } @@ -2015,6 +2004,13 @@ macro_expand (const struct macro_tokens *mts, { i += retval - 1; struct stringi_map vars = STRINGI_MAP_INITIALIZER (vars); + struct macro_expansion_stack stack = { + .name = submc->macro->name, + .file_name = submc->macro->file_name, + .first_line = submc->macro->first_line, + .last_line = submc->macro->last_line, + .next = me->stack, + }; struct macro_expander subme = { .macros = submc->macros, .macro = submc->macro, @@ -2024,15 +2020,9 @@ macro_expand (const struct macro_tokens *mts, .break_ = NULL, .vars = &vars, .nesting_countdown = me->nesting_countdown - 1, + .stack = &stack, }; - macro_expand (&submc->macro->body, &subme, - &(struct macro_expansion_stack) { - .name = submc->macro->name, - .file_name = submc->macro->file_name, - .first_line = submc->macro->first_line, - .last_line = submc->macro->last_line, - .next = stack, - }, exp); + macro_expand (&submc->macro->body, &subme, exp); macro_call_destroy (submc); stringi_map_destroy (&vars); continue; @@ -2050,7 +2040,7 @@ macro_expand (const struct macro_tokens *mts, if (ss_equals_case (token->string, ss_cstr ("!break"))) { if (!me->break_) - macro_error (stack, mt, _("!BREAK outside !DO.")); + macro_error (me->stack, mt, _("!BREAK outside !DO.")); else { *me->break_ = true; @@ -2062,7 +2052,6 @@ macro_expand (const struct macro_tokens *mts, .input = &mts->mts[i], .n_input = mts->n - i, .me = me, - .stack = stack, }; struct string function_output = DS_EMPTY_INITIALIZER; size_t function_consumed; @@ -2071,20 +2060,20 @@ macro_expand (const struct macro_tokens *mts, i += function_consumed - 1; macro_tokens_from_string__ (exp, function_output.ss, - me->segmenter_mode, stack); + me->segmenter_mode, me->stack); ds_destroy (&function_output); continue; } - size_t n = macro_parse_let (&mts->mts[i], mts->n - i, me, stack); + size_t n = macro_parse_let (&mts->mts[i], mts->n - i, me); if (n > 0) { i += n - 1; continue; } - n = macro_expand_do (&mts->mts[i], mts->n - i, me, stack, exp); + n = macro_expand_do (&mts->mts[i], mts->n - i, me, exp); if (n > 0) { i += n - 1; @@ -2108,6 +2097,12 @@ macro_call_expand (struct macro_call *mc, enum segmenter_mode segmenter_mode, bool expand = true; struct stringi_map vars = STRINGI_MAP_INITIALIZER (vars); + struct macro_expansion_stack stack = { + .name = mc->macro->name, + .file_name = mc->macro->file_name, + .first_line = mc->macro->first_line, + .last_line = mc->macro->last_line, + }; struct macro_expander me = { .macros = mc->macros, .macro = mc->macro, @@ -2117,15 +2112,10 @@ macro_call_expand (struct macro_call *mc, enum segmenter_mode segmenter_mode, .break_ = NULL, .vars = &vars, .nesting_countdown = settings_get_mnest (), + .stack = &stack, }; - struct macro_expansion_stack stack = { - .name = mc->macro->name, - .file_name = mc->macro->file_name, - .first_line = mc->macro->first_line, - .last_line = mc->macro->last_line, - }; - macro_expand (&mc->macro->body, &me, &stack, exp); + macro_expand (&mc->macro->body, &me, exp); stringi_map_destroy (&vars); } diff --git a/tests/language/control/define.at b/tests/language/control/define.at index 44061836d3..1e18b81bd7 100644 --- a/tests/language/control/define.at +++ b/tests/language/control/define.at @@ -956,13 +956,15 @@ DEBUG EXPAND. AT_CHECK([pspp --testing-mode define.sps], [1], [dnl "increasing". -define.sps:3-5: In the expansion of `!for', +In the expansion of `!DO', +define.sps:3-5: inside the expansion of `!for', define.sps:14: error: DEBUG EXPAND: Numerical !DO loop exceeded maximum number of iterations 3. (Use SET MITERATE to change the limit.) 1 2 3 4. -define.sps:7-9: In the expansion of `!forby', +In the expansion of `!DO', +define.sps:7-9: inside the expansion of `!forby', define.sps:15: error: DEBUG EXPAND: Numerical !DO loop exceeded maximum number of iterations 3. (Use SET MITERATE to change the limit.) @@ -980,7 +982,8 @@ of iterations 3. (Use SET MITERATE to change the limit.) . -define.sps:7-9: In the expansion of `!forby', +In the expansion of `!DO', +define.sps:7-9: inside the expansion of `!forby', define.sps:23: error: DEBUG EXPAND: Numerical !DO loop exceeded maximum number of iterations 3. (Use SET MITERATE to change the limit.) @@ -1058,13 +1061,15 @@ DEBUG EXPAND. !for. ]) AT_CHECK([pspp --testing-mode define.sps], [1], [dnl -define.sps:1-3: In the expansion of `!for', +In the expansion of `!DO', +define.sps:1-3: inside the expansion of `!for', define.sps:7: error: DEBUG EXPAND: !DO loop over list exceeded maximum number of iterations 2. (Use SET MITERATE to change the limit.) ( (a) (b) ). -define.sps:1-3: In the expansion of `!for', +In the expansion of `!DO', +define.sps:1-3: inside the expansion of `!for', define.sps:8: error: DEBUG EXPAND: !DO loop over list exceeded maximum number of iterations 2. (Use SET MITERATE to change the limit.) @@ -1461,7 +1466,8 @@ define.sps:14: error: DEBUG EXPAND: Expected `=' or !IN in !DO loop. !DO !x -define.sps:4: In the expansion of `!d', +In the expansion of `!DO', +define.sps:4: inside the expansion of `!d', define.sps:15: error: DEBUG EXPAND: Missing !DOEND. !DO !x !in(x) @@ -1473,12 +1479,14 @@ define.sps:16: error: DEBUG EXPAND: Macro expression must evaluate to a number !DO !x = x. -define.sps:6: At `x' in the expansion of `!f', +At `x' in the expansion of `!DO', +define.sps:6: inside the expansion of `!f', define.sps:17: error: DEBUG EXPAND: Expected !TO in numerical !DO loop. !DO !x = 5 x -define.sps:7: In the expansion of `!g', +In the expansion of `!DO', +define.sps:7: inside the expansion of `!g', define.sps:18: error: DEBUG EXPAND: !BY value cannot be zero. !DO !x = 5 !TO 6 !BY 0 -- 2.30.2