From 0e3b4b187c70b0674e53d467f28c5354f7f12fac Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 4 Jul 2021 13:20:14 -0700 Subject: [PATCH] macro: Separate macro_expander from macro_call. --- src/language/lexer/macro.c | 211 ++++++++++++++++++++++--------------- 1 file changed, 124 insertions(+), 87 deletions(-) diff --git a/src/language/lexer/macro.c b/src/language/lexer/macro.c index 3346692e10..ce6ee62046 100644 --- a/src/language/lexer/macro.c +++ b/src/language/lexer/macro.c @@ -536,7 +536,7 @@ macro_set_add (struct macro_set *set, struct macro *m) hmap_insert (&set->macros, &m->hmap_node, hash_macro_name (m->name)); } -/* Macro expander. */ +/* Macro call parsing.. */ enum mc_state { @@ -572,8 +572,6 @@ struct macro_call enum mc_state state; size_t n_tokens; const struct macro_param *param; /* Parameter currently being parsed. */ - - enum segmenter_mode segmenter_mode; }; /* Completes macro expansion by initializing arguments that weren't supplied to @@ -863,6 +861,16 @@ macro_call_add (struct macro_call *mc, const struct macro_token *mt) NOT_REACHED (); } } + +/* Macro expansion. */ + +struct macro_expander + { + const struct macro_set *macros; + const struct macro *macro; + struct macro_tokens **args; + enum segmenter_mode segmenter_mode; + }; /* Each argument to a macro function is one of: @@ -884,7 +892,7 @@ struct parse_macro_function_ctx size_t n_input; int nesting_countdown; const struct macro_set *macros; - const struct macro_call *mc; + const struct macro_expander *me; const struct macro_expansion_stack *stack; struct string_map *vars; bool *expand; @@ -893,7 +901,7 @@ struct parse_macro_function_ctx static void macro_expand (const struct macro_tokens *, int nesting_countdown, const struct macro_set *, - const struct macro_call *, struct string_map *vars, + const struct macro_expander *, struct string_map *vars, const struct macro_expansion_stack *stack, bool *expand, bool *break_, struct macro_tokens *exp); @@ -919,14 +927,14 @@ parse_function_arg (struct parse_macro_function_ctx *ctx, { const struct macro_token *tokens = ctx->input; const struct token *token = &tokens[i].token; - if (token->type == T_MACRO_ID) + if (token->type == T_MACRO_ID && ctx->me->macro) { const struct macro_param *param = macro_find_parameter_by_name ( - ctx->mc->macro, token->string); + ctx->me->macro, token->string); if (param) { - size_t param_idx = param - ctx->mc->macro->params; - const struct macro_tokens *marg = ctx->mc->args[param_idx]; + size_t param_idx = param - ctx->me->macro->params; + const struct macro_tokens *marg = ctx->me->args[param_idx]; for (size_t i = 0; i < marg->n; i++) { if (i) @@ -938,12 +946,12 @@ parse_function_arg (struct parse_macro_function_ctx *ctx, if (is_bang_star (ctx->input, ctx->n_input, i)) { - for (size_t i = 0; i < ctx->mc->macro->n_params; i++) + for (size_t i = 0; i < ctx->me->macro->n_params; i++) { - if (!ctx->mc->macro->params[i].positional) + if (!ctx->me->macro->params[i].positional) break; - const struct macro_tokens *marg = ctx->mc->args[i]; + const struct macro_tokens *marg = ctx->me->args[i]; for (size_t j = 0; j < marg->n; j++) { if (i || j) @@ -971,7 +979,7 @@ parse_function_arg (struct parse_macro_function_ctx *ctx, .n_input = ctx->n_input - i, .nesting_countdown = ctx->nesting_countdown, .macros = ctx->macros, - .mc = ctx->mc, + .me = ctx->me, .stack = ctx->stack, .vars = ctx->vars, .expand = ctx->expand, @@ -1134,7 +1142,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, input_consumed)) { for (size_t i = 0; i < args.n; i++) - if (!unquote_string (args.strings[i], ctx->mc->segmenter_mode, output)) + if (!unquote_string (args.strings[i], ctx->me->segmenter_mode, output)) ds_put_cstr (output, args.strings[i]); } else if (parse_macro_function (ctx, &args, ss_cstr ("!HEAD"), 1, 1, @@ -1142,10 +1150,10 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, { struct string tmp; const char *s = unquote_string_in_place (args.strings[0], - ctx->mc->segmenter_mode, &tmp); + ctx->me->segmenter_mode, &tmp); struct macro_tokens mts = { .n = 0 }; - macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->mc->segmenter_mode, + macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->me->segmenter_mode, ctx->stack); if (mts.n > 0) ds_put_substring (output, mts.mts[0].representation); @@ -1162,7 +1170,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, else if (parse_macro_function (ctx, &args, ss_cstr ("!QUOTE"), 1, 1, input_consumed)) { - if (unquote_string (args.strings[0], ctx->mc->segmenter_mode, NULL)) + if (unquote_string (args.strings[0], ctx->me->segmenter_mode, NULL)) ds_put_cstr (output, args.strings[0]); else { @@ -1210,10 +1218,10 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, { struct string tmp; const char *s = unquote_string_in_place (args.strings[0], - ctx->mc->segmenter_mode, &tmp); + ctx->me->segmenter_mode, &tmp); struct macro_tokens mts = { .n = 0 }; - macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->mc->segmenter_mode, + macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->me->segmenter_mode, ctx->stack); if (mts.n > 1) { @@ -1226,7 +1234,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, else if (parse_macro_function (ctx, &args, ss_cstr ("!UNQUOTE"), 1, 1, input_consumed)) { - if (!unquote_string (args.strings[0], ctx->mc->segmenter_mode, output)) + if (!unquote_string (args.strings[0], ctx->me->segmenter_mode, output)) ds_put_cstr (output, args.strings[0]); } else if (parse_macro_function (ctx, &args, ss_cstr ("!UPCASE"), 1, 1, @@ -1234,7 +1242,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, { struct string tmp; const char *s = unquote_string_in_place (args.strings[0], - ctx->mc->segmenter_mode, &tmp); + ctx->me->segmenter_mode, &tmp); char *upper = utf8_to_upper (s); ds_put_cstr (output, upper); free (upper); @@ -1245,10 +1253,10 @@ 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->mc->segmenter_mode, ctx->stack); + ctx->me->segmenter_mode, ctx->stack); struct macro_tokens exp = { .n = 0 }; macro_expand (&mts, ctx->nesting_countdown - 1, - ctx->macros, ctx->mc, ctx->vars, + ctx->macros, ctx->me, ctx->vars, &(struct macro_expansion_stack) { .name = "!EVAL", .next = ctx->stack, @@ -1275,7 +1283,7 @@ struct expr_context { int nesting_countdown; const struct macro_set *macros; - const struct macro_call *mc; + const struct macro_expander *me; const struct macro_expansion_stack *stack; struct string_map *vars; bool *expand; @@ -1322,7 +1330,7 @@ macro_evaluate_literal (const struct expr_context *ctx, .n_input = end - p, .nesting_countdown = ctx->nesting_countdown, .macros = ctx->macros, - .mc = ctx->mc, + .me = ctx->me, .stack = ctx->stack, .vars = ctx->vars, .expand = ctx->expand, @@ -1330,7 +1338,7 @@ macro_evaluate_literal (const struct expr_context *ctx, struct string function_output = DS_EMPTY_INITIALIZER; size_t function_consumed = parse_function_arg (&fctx, 0, &function_output); struct string unquoted = DS_EMPTY_INITIALIZER; - if (unquote_string (ds_cstr (&function_output), ctx->mc->segmenter_mode, + if (unquote_string (ds_cstr (&function_output), ctx->me->segmenter_mode, &unquoted)) { ds_swap (&function_output, &unquoted); @@ -1405,9 +1413,9 @@ macro_evaluate_relational (const struct expr_context *ctx, } struct string lhs_tmp, rhs_tmp; - int cmp = strcmp (unquote_string_in_place (lhs, ctx->mc->segmenter_mode, + int cmp = strcmp (unquote_string_in_place (lhs, ctx->me->segmenter_mode, &lhs_tmp), - unquote_string_in_place (rhs, ctx->mc->segmenter_mode, + unquote_string_in_place (rhs, ctx->me->segmenter_mode, &rhs_tmp)); ds_destroy (&lhs_tmp); ds_destroy (&rhs_tmp); @@ -1521,14 +1529,14 @@ static char * macro_evaluate_expression (const struct macro_token **tokens, size_t n_tokens, int nesting_countdown, const struct macro_set *macros, - const struct macro_call *mc, + const struct macro_expander *me, const struct macro_expansion_stack *stack, struct string_map *vars, bool *expand) { const struct expr_context ctx = { .nesting_countdown = nesting_countdown, .macros = macros, - .mc = mc, + .me = me, .stack = stack, .vars = vars, .expand = expand, @@ -1540,18 +1548,18 @@ static bool macro_evaluate_number (const struct macro_token **tokens, size_t n_tokens, int nesting_countdown, const struct macro_set *macros, - const struct macro_call *mc, + const struct macro_expander *me, const struct macro_expansion_stack *stack, struct string_map *vars, bool *expand, double *number) { char *s = macro_evaluate_expression (tokens, n_tokens, nesting_countdown, - macros, mc, stack, vars, expand); + macros, me, stack, vars, expand); if (!s) return false; struct macro_tokens mts = { .n = 0 }; - macro_tokens_from_string__ (&mts, ss_cstr (s), mc->segmenter_mode, stack); + macro_tokens_from_string__ (&mts, ss_cstr (s), me->segmenter_mode, stack); if (mts.n != 1 || !token_is_number (&mts.mts[0].token)) { macro_error (stack, mts.n > 0 ? &mts.mts[0] : NULL, @@ -1594,7 +1602,7 @@ 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, int nesting_countdown, const struct macro_set *macros, - const struct macro_call *mc, + const struct macro_expander *me, const struct macro_expansion_stack *stack, struct string_map *vars, bool *expand, bool *break_, struct macro_tokens *exp) @@ -1608,7 +1616,7 @@ macro_expand_if (const struct macro_token *tokens, size_t n_tokens, p++; char *result = macro_evaluate_expression (&p, end - p, nesting_countdown, - macros, mc, + macros, me, stack, vars, expand); if (!result) return 0; @@ -1676,7 +1684,7 @@ macro_expand_if (const struct macro_token *tokens, size_t n_tokens, .mts = CONST_CAST (struct macro_token *, start), .n = n, }; - macro_expand (&mts, nesting_countdown, macros, mc, vars, + macro_expand (&mts, nesting_countdown, macros, me, vars, &(struct macro_expansion_stack) { .name = "!IF", .next = stack, @@ -1689,7 +1697,7 @@ macro_expand_if (const struct macro_token *tokens, size_t n_tokens, static size_t macro_parse_let (const struct macro_token *tokens, size_t n_tokens, int nesting_countdown, const struct macro_set *macros, - const struct macro_call *mc, + const struct macro_expander *me, const struct macro_expansion_stack *stack, struct string_map *vars, bool *expand) { @@ -1708,7 +1716,7 @@ macro_parse_let (const struct macro_token *tokens, size_t n_tokens, } const struct substring var_name = p->token.string; if (is_macro_keyword (var_name) - || macro_find_parameter_by_name (mc->macro, var_name)) + || (me->macro && macro_find_parameter_by_name (me->macro, var_name))) { macro_error (stack, p < end ? p : NULL, _("Cannot use argument name or macro keyword " @@ -1727,7 +1735,7 @@ macro_parse_let (const struct macro_token *tokens, size_t n_tokens, p++; char *value = macro_evaluate_expression (&p, end - p, nesting_countdown, - macros, mc, stack, vars, expand); + macros, me, stack, vars, expand); if (!value) return 0; @@ -1761,7 +1769,7 @@ find_doend (const struct macro_expansion_stack *stack, static size_t macro_expand_do (const struct macro_token *tokens, size_t n_tokens, int nesting_countdown, const struct macro_set *macros, - const struct macro_call *mc, + const struct macro_expander *me, const struct macro_expansion_stack *stack, struct string_map *vars, bool *expand, struct macro_tokens *exp) @@ -1781,7 +1789,7 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, } const struct substring var_name = p->token.string; if (is_macro_keyword (var_name) - || macro_find_parameter_by_name (mc->macro, var_name)) + || (me->macro && macro_find_parameter_by_name (me->macro, var_name))) { macro_error (stack, p, _("Cannot use argument name or macro " "keyword as !DO variable.")); @@ -1798,13 +1806,13 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, { p++; char *list = macro_evaluate_expression (&p, end - p, nesting_countdown, - macros, mc, &next_stack, vars, + macros, me, &next_stack, vars, expand); if (!list) return 0; struct macro_tokens items = { .n = 0 }; - macro_tokens_from_string__ (&items, ss_cstr (list), mc->segmenter_mode, + macro_tokens_from_string__ (&items, ss_cstr (list), me->segmenter_mode, stack); free (list); @@ -1835,7 +1843,7 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, bool break_ = false; macro_expand (&inner, nesting_countdown, macros, - mc, vars, &next_stack, expand, &break_, exp); + me, vars, &next_stack, expand, &break_, exp); if (break_) break; } @@ -1846,7 +1854,7 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, p++; double first; if (!macro_evaluate_number (&p, end - p, nesting_countdown, - macros, mc, &next_stack, + macros, me, &next_stack, vars, expand, &first)) return 0; @@ -1861,7 +1869,7 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, double last; if (!macro_evaluate_number (&p, end - p, nesting_countdown, - macros, mc, &next_stack, + macros, me, &next_stack, vars, expand, &last)) return 0; @@ -1871,7 +1879,7 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, { p++; if (!macro_evaluate_number (&p, end - p, nesting_countdown, - macros, mc, &next_stack, + macros, me, &next_stack, vars, expand, &by)) return 0; @@ -1914,7 +1922,7 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, bool break_ = false; macro_expand (&inner, nesting_countdown, - macros, mc, vars, &next_stack, expand, &break_, + macros, me, vars, &next_stack, expand, &break_, exp); if (break_) break; @@ -1934,7 +1942,7 @@ macro_expand_do (const struct macro_token *tokens, size_t n_tokens, static void macro_expand (const struct macro_tokens *mts, int nesting_countdown, const struct macro_set *macros, - const struct macro_call *mc, struct string_map *vars, + const struct macro_expander *me, struct string_map *vars, const struct macro_expansion_stack *stack, bool *expand, bool *break_, struct macro_tokens *exp) { @@ -1956,20 +1964,28 @@ macro_expand (const struct macro_tokens *mts, int nesting_countdown, { const struct macro_token *mt = &mts->mts[i]; const struct token *token = &mt->token; - if (token->type == T_MACRO_ID && mc) + if (token->type == T_MACRO_ID && me->macro) { const struct macro_param *param = macro_find_parameter_by_name ( - mc->macro, token->string); + me->macro, token->string); if (param) { - const struct macro_tokens *arg = mc->args[param - mc->macro->params]; + const struct macro_tokens *arg = me->args[param - me->macro->params]; if (*expand && param->expand_arg) - macro_expand (arg, nesting_countdown, - macros, NULL, NULL, - &(struct macro_expansion_stack) { - .name = param->name, - .next = stack, - }, expand, break_, exp); + { + struct macro_expander subme = { + .macros = me->macros, + .macro = NULL, + .args = NULL, + .segmenter_mode = me->segmenter_mode, + }; + macro_expand (arg, nesting_countdown, + macros, &subme, NULL, + &(struct macro_expansion_stack) { + .name = param->name, + .next = stack, + }, expand, break_, exp); + } else for (size_t i = 0; i < arg->n; i++) macro_tokens_add (exp, &arg->mts[i]); @@ -1978,20 +1994,28 @@ macro_expand (const struct macro_tokens *mts, int nesting_countdown, if (is_bang_star (mts->mts, mts->n, i)) { - for (size_t j = 0; j < mc->macro->n_params; j++) + for (size_t j = 0; j < me->macro->n_params; j++) { - const struct macro_param *param = &mc->macro->params[j]; + const struct macro_param *param = &me->macro->params[j]; if (!param->positional) break; - const struct macro_tokens *arg = mc->args[j]; + const struct macro_tokens *arg = me->args[j]; if (*expand && param->expand_arg) - macro_expand (arg, nesting_countdown, - macros, NULL, NULL, - &(struct macro_expansion_stack) { - .name = "!*", - .next = stack, - }, expand, break_, exp); + { + struct macro_expander subme = { + .macros = me->macros, + .macro = NULL, + .args = NULL, + .segmenter_mode = me->segmenter_mode, + }; + macro_expand (arg, nesting_countdown, + macros, &subme, NULL, + &(struct macro_expansion_stack) { + .name = "!*", + .next = stack, + }, expand, break_, exp); + } else for (size_t k = 0; k < arg->n; k++) macro_tokens_add (exp, &arg->mts[k]); @@ -2002,7 +2026,7 @@ macro_expand (const struct macro_tokens *mts, int nesting_countdown, size_t n = macro_expand_if (&mts->mts[i], mts->n - i, nesting_countdown, - macros, mc, stack, + macros, me, stack, vars, expand, break_, exp); if (n > 0) { @@ -2018,38 +2042,45 @@ macro_expand (const struct macro_tokens *mts, int nesting_countdown, if (value) { macro_tokens_from_string__ (exp, ss_cstr (value), - mc->segmenter_mode, stack); + me->segmenter_mode, stack); continue; } } if (*expand) { - struct macro_call *subme; - int retval = macro_call_create (macros, token, &subme); + struct macro_call *submc; + int retval = macro_call_create (macros, token, &submc); for (size_t j = 1; !retval; j++) { - const struct macro_token endcmd = { .token = { .type = T_ENDCMD } }; + const struct macro_token endcmd + = { .token = { .type = T_ENDCMD } }; retval = macro_call_add ( - subme, i + j < mts->n ? &mts->mts[i + j] : &endcmd); + submc, i + j < mts->n ? &mts->mts[i + j] : &endcmd); } if (retval > 0) { i += retval - 1; - macro_expand (&subme->macro->body, nesting_countdown - 1, - macros, subme, NULL, + struct macro_expander subme = { + .macros = submc->macros, + .macro = submc->macro, + .args = submc->args, + .segmenter_mode = me->segmenter_mode, + }; + macro_expand (&submc->macro->body, nesting_countdown - 1, + macros, &subme, NULL, &(struct macro_expansion_stack) { - .name = subme->macro->name, - .file_name = subme->macro->file_name, - .first_line = subme->macro->first_line, - .last_line = subme->macro->last_line, + .name = submc->macro->name, + .file_name = submc->macro->file_name, + .first_line = submc->macro->first_line, + .last_line = submc->macro->last_line, .next = stack, }, expand, break_, exp); - macro_call_destroy (subme); + macro_call_destroy (submc); continue; } - macro_call_destroy (subme); + macro_call_destroy (submc); } if (token->type != T_MACRO_ID) @@ -2074,7 +2105,7 @@ macro_expand (const struct macro_tokens *mts, int nesting_countdown, .n_input = mts->n - i, .nesting_countdown = nesting_countdown, .macros = macros, - .mc = mc, + .me = me, .stack = stack, .vars = vars, .expand = expand, @@ -2086,7 +2117,7 @@ macro_expand (const struct macro_tokens *mts, int nesting_countdown, i += function_consumed - 1; macro_tokens_from_string__ (exp, function_output.ss, - mc->segmenter_mode, stack); + me->segmenter_mode, stack); ds_destroy (&function_output); continue; @@ -2094,7 +2125,7 @@ macro_expand (const struct macro_tokens *mts, int nesting_countdown, size_t n = macro_parse_let (&mts->mts[i], mts->n - i, nesting_countdown, - macros, mc, stack, vars, expand); + macros, me, stack, vars, expand); if (n > 0) { i += n - 1; @@ -2102,7 +2133,7 @@ macro_expand (const struct macro_tokens *mts, int nesting_countdown, } n = macro_expand_do (&mts->mts[i], mts->n - i, - nesting_countdown, macros, mc, stack, + nesting_countdown, macros, me, stack, vars, expand, exp); if (n > 0) { @@ -2126,7 +2157,13 @@ macro_call_expand (struct macro_call *mc, enum segmenter_mode segmenter_mode, struct macro_tokens *exp) { assert (mc->state == MC_FINISHED); - mc->segmenter_mode = segmenter_mode; + + struct macro_expander me = { + .macros = mc->macros, + .macro = mc->macro, + .args = mc->args, + .segmenter_mode = segmenter_mode, + }; bool expand = true; struct macro_expansion_stack stack = { @@ -2136,6 +2173,6 @@ macro_call_expand (struct macro_call *mc, enum segmenter_mode segmenter_mode, .last_line = mc->macro->last_line, }; macro_expand (&mc->macro->body, settings_get_mnest (), - mc->macros, mc, NULL, &stack, &expand, NULL, exp); + mc->macros, &me, NULL, &stack, &expand, NULL, exp); } -- 2.30.2