1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2021 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "language/lexer/macro.h"
25 #include "data/settings.h"
26 #include "language/lexer/lexer.h"
27 #include "language/lexer/segment.h"
28 #include "language/lexer/scan.h"
29 #include "libpspp/assertion.h"
30 #include "libpspp/cast.h"
31 #include "libpspp/i18n.h"
32 #include "libpspp/message.h"
33 #include "libpspp/str.h"
34 #include "libpspp/string-array.h"
35 #include "libpspp/stringi-map.h"
36 #include "libpspp/stringi-set.h"
38 #include "gl/c-ctype.h"
39 #include "gl/ftoastr.h"
42 #define _(msgid) gettext (msgid)
44 /* An entry in the stack of macros and macro directives being expanded. The
45 stack is maintained as a linked list. Entries are not dynamically allocated
46 but on the program stack.
48 The outermost entry, where 'next' is NULL, represents the source location of
49 the call to the macro. */
50 struct macro_expansion_stack
52 const struct macro_expansion_stack *next; /* Next outer stack entry. */
53 const char *name; /* A macro name or !IF, !DO, etc. */
54 const struct msg_location *location; /* Source location if available. */
57 /* Reports an error during macro expansion. STACK is the stack for reporting
58 the location of the error, MT is the optional token at which the error was
59 detected, and FORMAT along with the varargs is the message to report. */
60 static void PRINTF_FORMAT (3, 0)
61 macro_error_valist (const struct macro_expansion_stack *stack,
62 const struct macro_token *mt, const char *format,
65 struct msg_stack **ms = NULL;
66 size_t allocated_ms = 0;
69 const struct macro_expansion_stack *p;
70 for (p = stack; p && p->next; p = p->next)
72 if (n_ms >= allocated_ms)
73 ms = x2nrealloc (ms, &allocated_ms, sizeof *ms);
75 /* TRANSLATORS: These strings are used for explaining the context of an
76 error. The "While expanding" message appears first, followed by zero
77 or more of the "inside expansion" messages. `innermost',
78 `next_inner`, etc., are names of macros, and `foobar' is a piece of
81 foo.sps:12: At `foobar' in the expansion of 'innermost',
82 foo.sps:23: inside the expansion of 'next_inner',
83 foo.sps:34: inside the expansion of 'next_inner2',
84 foo.sps:45: inside the expansion of 'outermost',
85 foo.sps:76: This is the actual error message. */
89 if (mt && mt->syntax.length)
92 str_ellipsize (mt->syntax, syntax, sizeof syntax);
93 description = xasprintf (_("At `%s' in the expansion of `%s',"),
97 description = xasprintf (_("In the expansion of `%s',"), p->name);
100 description = xasprintf (_("inside the expansion of `%s',"), p->name);
102 ms[n_ms] = xmalloc (sizeof *ms[n_ms]);
103 *ms[n_ms] = (struct msg_stack) {
104 .location = msg_location_dup (p->location),
105 .description = description,
110 struct msg *m = xmalloc (sizeof *m);
112 .category = MSG_C_SYNTAX,
113 .severity = MSG_S_ERROR,
116 .location = msg_location_dup (p ? p->location : NULL),
117 .text = xvasprintf (format, args),
122 /* Reports an error during macro expansion. STACK is the stack for reporting
123 the location of the error, MT is the optional token at which the error was
124 detected, and FORMAT along with the varargs is the message to report. */
125 static void PRINTF_FORMAT (3, 4)
126 macro_error (const struct macro_expansion_stack *stack,
127 const struct macro_token *mt, const char *format, ...)
130 va_start (args, format);
131 macro_error_valist (stack, mt, format, args);
136 macro_token_copy (struct macro_token *dst, const struct macro_token *src)
138 token_copy (&dst->token, &src->token);
139 ss_alloc_substring (&dst->syntax, src->syntax);
143 macro_token_uninit (struct macro_token *mt)
145 token_uninit (&mt->token);
146 ss_dealloc (&mt->syntax);
150 macro_token_to_syntax (struct macro_token *mt, struct string *s)
152 ds_put_substring (s, mt->syntax);
155 is_macro_keyword (struct substring s)
157 static struct stringi_set keywords = STRINGI_SET_INITIALIZER (keywords);
158 if (stringi_set_is_empty (&keywords))
160 static const char *kws[] = {
181 for (size_t i = 0; i < sizeof kws / sizeof *kws; i++)
182 stringi_set_insert (&keywords, kws[i]);
185 ss_ltrim (&s, ss_cstr ("!"));
186 return stringi_set_contains_len (&keywords, s.string, s.length);
190 macro_tokens_copy (struct macro_tokens *dst, const struct macro_tokens *src)
192 *dst = (struct macro_tokens) {
193 .mts = xmalloc (src->n * sizeof *dst->mts),
197 for (size_t i = 0; i < src->n; i++)
198 macro_token_copy (&dst->mts[i], &src->mts[i]);
202 macro_tokens_uninit (struct macro_tokens *mts)
204 for (size_t i = 0; i < mts->n; i++)
205 macro_token_uninit (&mts->mts[i]);
210 macro_tokens_add_uninit (struct macro_tokens *mts)
212 if (mts->n >= mts->allocated)
213 mts->mts = x2nrealloc (mts->mts, &mts->allocated, sizeof *mts->mts);
214 return &mts->mts[mts->n++];
218 macro_tokens_add (struct macro_tokens *mts, const struct macro_token *mt)
220 macro_token_copy (macro_tokens_add_uninit (mts), mt);
223 /* Tokenizes SRC according to MODE and appends the tokens to MTS. Uses STACK,
224 if nonull, for error reporting. */
226 macro_tokens_from_string__ (struct macro_tokens *mts, const struct substring src,
227 enum segmenter_mode mode,
228 const struct macro_expansion_stack *stack)
230 struct segmenter segmenter = segmenter_init (mode, true);
231 struct substring body = src;
233 while (body.length > 0)
235 struct macro_token mt = {
236 .token = { .type = T_STOP },
237 .syntax = { .string = body.string },
239 struct token *token = &mt.token;
241 enum segment_type type;
242 int seg_len = segmenter_push (&segmenter, body.string,
243 body.length, true, &type);
244 assert (seg_len >= 0);
246 struct substring segment = ss_head (body, seg_len);
247 enum tokenize_result result = token_from_segment (type, segment, token);
248 ss_advance (&body, seg_len);
256 mt.syntax.length = body.string - mt.syntax.string;
257 macro_tokens_add (mts, &mt);
261 mt.syntax.length = body.string - mt.syntax.string;
262 macro_error (stack, &mt, "%s", token->string.string);
266 token_uninit (token);
270 /* Tokenizes SRC according to MODE and appends the tokens to MTS. */
272 macro_tokens_from_string (struct macro_tokens *mts, const struct substring src,
273 enum segmenter_mode mode)
275 macro_tokens_from_string__ (mts, src, mode, NULL);
279 macro_tokens_print (const struct macro_tokens *mts, FILE *stream)
281 for (size_t i = 0; i < mts->n; i++)
282 token_print (&mts->mts[i].token, stream);
287 TC_ENDCMD, /* No space before or after (new-line after). */
288 TC_BINOP, /* Space on both sides. */
289 TC_COMMA, /* Space afterward. */
290 TC_ID, /* Don't need spaces except sequentially. */
291 TC_PUNCT, /* Don't need spaces except sequentially. */
295 needs_space (enum token_class prev, enum token_class next)
297 /* Don't need a space before or after the end of a command.
298 (A new-line is needed afterward as a special case.) */
299 if (prev == TC_ENDCMD || next == TC_ENDCMD)
302 /* Binary operators always have a space on both sides. */
303 if (prev == TC_BINOP || next == TC_BINOP)
306 /* A comma always has a space afterward. */
307 if (prev == TC_COMMA)
310 /* Otherwise, PREV is TC_ID or TC_PUNCT, which only need a space if there are
311 two or them in a row. */
315 static enum token_class
316 classify_token (enum token_type type)
368 /* Appends syntax for the tokens in MTS to S. If OFS and LEN are nonnull, sets
369 OFS[i] to the offset within S of the start of token 'i' in MTS and LEN[i] to
370 its length. OFS[i] + LEN[i] is not necessarily OFS[i + 1] because some
371 tokens are separated by white space. */
373 macro_tokens_to_syntax (struct macro_tokens *mts, struct string *s,
374 size_t *ofs, size_t *len)
376 assert ((ofs != NULL) == (len != NULL));
381 for (size_t i = 0; i < mts->n; i++)
385 enum token_type prev = mts->mts[i - 1].token.type;
386 enum token_type next = mts->mts[i].token.type;
388 if (prev == T_ENDCMD)
389 ds_put_byte (s, '\n');
392 enum token_class pc = classify_token (prev);
393 enum token_class nc = classify_token (next);
394 if (needs_space (pc, nc))
395 ds_put_byte (s, ' ');
400 ofs[i] = s->ss.length;
401 macro_token_to_syntax (&mts->mts[i], s);
403 len[i] = s->ss.length - ofs[i];
408 macro_destroy (struct macro *m)
414 msg_location_destroy (m->location);
415 for (size_t i = 0; i < m->n_params; i++)
417 struct macro_param *p = &m->params[i];
420 macro_tokens_uninit (&p->def);
421 token_uninit (&p->start);
422 token_uninit (&p->end);
425 macro_tokens_uninit (&m->body);
430 macro_set_create (void)
432 struct macro_set *set = xmalloc (sizeof *set);
433 *set = (struct macro_set) {
434 .macros = HMAP_INITIALIZER (set->macros),
440 macro_set_destroy (struct macro_set *set)
445 struct macro *macro, *next;
446 HMAP_FOR_EACH_SAFE (macro, next, struct macro, hmap_node, &set->macros)
448 hmap_delete (&set->macros, ¯o->hmap_node);
449 macro_destroy (macro);
451 hmap_destroy (&set->macros);
456 hash_macro_name (const char *name)
458 return utf8_hash_case_string (name, 0);
461 static struct macro *
462 macro_set_find__ (struct macro_set *set, const char *name)
464 if (macro_set_is_empty (set))
468 HMAP_FOR_EACH_WITH_HASH (macro, struct macro, hmap_node,
469 hash_macro_name (name), &set->macros)
470 if (!utf8_strcasecmp (macro->name, name))
477 macro_set_find (const struct macro_set *set, const char *name)
479 return macro_set_find__ (CONST_CAST (struct macro_set *, set), name);
482 /* Adds M to SET. M replaces any existing macro with the same name. Takes
485 macro_set_add (struct macro_set *set, struct macro *m)
487 struct macro *victim = macro_set_find__ (set, m->name);
490 hmap_delete (&set->macros, &victim->hmap_node);
491 macro_destroy (victim);
494 hmap_insert (&set->macros, &m->hmap_node, hash_macro_name (m->name));
497 /* Macro call parsing. */
501 /* Accumulating tokens in mc->params toward the end of any type of
505 /* Expecting the opening delimiter of an ARG_ENCLOSE argument. */
508 /* Expecting a keyword for a keyword argument. */
511 /* Expecting an equal sign for a keyword argument. */
514 /* Macro fully parsed and ready for expansion. */
518 /* Parsing macro calls. This is a FSM driven by macro_call_create() and
519 macro_call_add() to identify the macro being called and obtain its
520 arguments. 'state' identifies the FSM state. */
523 const struct macro_set *macros;
524 const struct macro *macro;
525 struct macro_tokens **args;
526 const struct macro_expansion_stack *stack;
527 const struct macro_expander *me;
531 const struct macro_param *param; /* Parameter currently being parsed. */
534 static bool macro_expand_arg (const struct token *,
535 const struct macro_expander *,
536 struct macro_tokens *exp);
538 /* Completes macro expansion by initializing arguments that weren't supplied to
541 mc_finished (struct macro_call *mc)
543 mc->state = MC_FINISHED;
544 for (size_t i = 0; i < mc->macro->n_params; i++)
546 mc->args[i] = &mc->macro->params[i].def;
551 mc_next_arg (struct macro_call *mc)
555 assert (!mc->macro->n_params);
556 return mc_finished (mc);
558 else if (mc->param->positional)
561 if (mc->param >= &mc->macro->params[mc->macro->n_params])
562 return mc_finished (mc);
565 mc->state = (!mc->param->positional ? MC_KEYWORD
566 : mc->param->arg_type == ARG_ENCLOSE ? MC_ENCLOSE
573 for (size_t i = 0; i < mc->macro->n_params; i++)
576 mc->state = MC_KEYWORD;
579 return mc_finished (mc);
583 static void PRINTF_FORMAT (3, 4)
584 mc_error (const struct macro_call *mc, const struct msg_location *loc,
585 const char *format, ...)
588 va_start (args, format);
591 const struct macro_expansion_stack stack = { .location = loc };
592 macro_error_valist (&stack, NULL, format, args);
595 macro_error_valist (mc->stack, NULL, format, args);
600 mc_add_arg (struct macro_call *mc, const struct macro_token *mt,
601 const struct msg_location *loc)
603 const struct macro_param *p = mc->param;
604 struct macro_tokens **argp = &mc->args[p - mc->macro->params];
606 const struct token *token = &mt->token;
607 if (token->type == T_ENDCMD || token->type == T_STOP)
614 /* This is OK, it's the expected way to end the argument. */
619 ngettext (_("Reached end of command expecting %zu "
620 "more token in argument %s to macro %s."),
621 _("Reached end of command expecting %zu "
622 "more tokens in argument %s to macro %s."),
623 p->n_tokens - (*argp)->n),
624 p->n_tokens - (*argp)->n, p->name, mc->macro->name);
630 char *end = token_to_string (&p->end);
631 mc_error (mc, loc, _("Reached end of command expecting \"%s\" "
632 "in argument %s to macro %s."),
633 end, p->name, mc->macro->name);
640 /* The end of a command ends the current argument, precludes any further
641 arguments, and is not itself part of the argument. */
642 return mc_finished (mc);
648 *argp = xzalloc (sizeof **argp);
650 bool add_token; /* Should we add 'mt' to the current arg? */
651 bool next_arg; /* Should we advance to the next arg? */
655 next_arg = (*argp)->n + 1 >= p->n_tokens;
661 next_arg = token_equal (token, &p->end);
662 add_token = !next_arg;
676 if (!macro_expand_arg (&mt->token, mc->me, *argp))
677 macro_tokens_add (*argp, mt);
679 return next_arg ? mc_next_arg (mc) : 0;
683 mc_expected (struct macro_call *mc, const struct macro_token *actual,
684 const struct msg_location *loc, const struct token *expected)
686 const struct substring actual_s = (actual->syntax.length ? actual->syntax
687 : ss_cstr (_("<end of input>")));
688 char *expected_s = token_to_string (expected);
690 _("Found `%.*s' while expecting `%s' reading argument %s "
692 (int) actual_s.length, actual_s.string, expected_s,
693 mc->param->name, mc->macro->name);
696 return mc_finished (mc);
700 mc_enclose (struct macro_call *mc, const struct macro_token *mt,
701 const struct msg_location *loc)
703 const struct token *token = &mt->token;
704 const struct macro_param *p = mc->param;
705 if (token_equal (&p->start, token))
709 struct macro_tokens **argp = &mc->args[p - mc->macro->params];
711 *argp = xzalloc (sizeof **argp);
715 else if (p->positional && (token->type == T_ENDCMD || token->type == T_STOP))
716 return mc_finished (mc);
718 return mc_expected (mc, mt, loc, &p->start);
721 static const struct macro_param *
722 macro_find_parameter_by_name (const struct macro *m, struct substring name)
727 ss_ltrim (&name, ss_cstr ("!"));
729 for (size_t i = 0; i < m->n_params; i++)
731 const struct macro_param *p = &m->params[i];
732 struct substring p_name = ss_cstr (p->name + 1);
733 if (!utf8_strncasecmp (p_name.string, p_name.length,
734 name.string, name.length))
741 mc_keyword (struct macro_call *mc, const struct macro_token *mt,
742 const struct msg_location *loc)
744 const struct token *token = &mt->token;
745 if (token->type != T_ID)
746 return mc_finished (mc);
748 const struct macro_param *p = macro_find_parameter_by_name (mc->macro,
752 struct macro_tokens **argp = &mc->args[p - mc->macro->params];
755 _("Argument %s multiply specified in call to macro %s."),
756 p->name, mc->macro->name);
758 *argp = xzalloc (sizeof **argp);
761 mc->state = MC_EQUALS;
765 return mc_finished (mc);
769 mc_equals (struct macro_call *mc, const struct macro_token *mt,
770 const struct msg_location *loc)
772 if (mt->token.type == T_EQUALS)
775 mc->state = mc->param->arg_type == ARG_ENCLOSE ? MC_ENCLOSE : MC_ARG;
779 return mc_expected (mc, mt, loc, &(struct token) { .type = T_EQUALS });
783 macro_call_create__ (const struct macro_set *macros,
784 const struct macro_expansion_stack *stack,
785 const struct macro_expander *me,
786 const struct token *token,
787 struct macro_call **mcp)
789 const struct macro *macro = (token->type == T_ID || token->type == T_MACRO_ID
790 ? macro_set_find (macros, token->string.string)
798 struct macro_call *mc = xmalloc (sizeof *mc);
799 *mc = (struct macro_call) {
803 .state = (!macro->n_params ? MC_FINISHED
804 : !macro->params[0].positional ? MC_KEYWORD
805 : macro->params[0].arg_type == ARG_ENCLOSE ? MC_ENCLOSE
807 .args = macro->n_params ? xcalloc (macro->n_params, sizeof *mc->args) : NULL,
808 .param = macro->params,
814 return mc->state == MC_FINISHED ? 1 : 0;
817 /* If TOKEN is the first token of a call to a macro in MACROS, create a new
818 macro expander, initializes *MCP to it. Returns 0 if more tokens are needed
819 and should be added via macro_call_add() or 1 if the caller should next call
820 macro_call_get_expansion().
822 If TOKEN is not the first token of a macro call, returns -1 and sets *MCP to
825 macro_call_create (const struct macro_set *macros,
826 const struct token *token,
827 struct macro_call **mcp)
829 return macro_call_create__ (macros, NULL, NULL, token, mcp);
833 macro_call_destroy (struct macro_call *mc)
838 for (size_t i = 0; i < mc->macro->n_params; i++)
840 struct macro_tokens *a = mc->args[i];
841 if (a && a != &mc->macro->params[i].def)
843 macro_tokens_uninit (a);
851 /* Adds TOKEN to the collection of tokens in MC that potentially need to be
854 Returns -1 if the tokens added do not actually invoke a macro. The caller
855 should consume the first token without expanding it. (Later tokens might
856 invoke a macro so it's best to feed the second token into a new expander.)
858 Returns 0 if the macro expander needs more tokens, for macro arguments or to
859 decide whether this is actually a macro invocation. The caller should call
860 macro_call_add() again with the next token.
862 Returns a positive number to indicate that the returned number of tokens
863 invoke a macro. The number returned might be less than the number of tokens
864 added because it can take a few tokens of lookahead to determine whether the
865 macro invocation is finished. The caller should call
866 macro_call_get_expansion() to obtain the expansion. */
868 macro_call_add (struct macro_call *mc, const struct macro_token *mt,
869 const struct msg_location *loc)
874 return mc_add_arg (mc, mt, loc);
877 return mc_enclose (mc, mt, loc);
880 return mc_keyword (mc, mt, loc);
883 return mc_equals (mc, mt, loc);
890 /* Macro expansion. */
892 struct macro_expander
894 /* Always available. */
895 const struct macro_set *macros; /* Macros to expand recursively. */
896 enum segmenter_mode segmenter_mode; /* Mode for tokenization. */
897 int nesting_countdown; /* Remaining nesting levels. */
898 const struct macro_expansion_stack *stack; /* Stack for error reporting. */
899 bool *expand; /* May macro calls be expanded? */
900 struct stringi_map *vars; /* Variables from !do and !let. */
902 /* Only nonnull if inside a !DO loop. */
903 bool *break_; /* Set to true to break out of loop. */
905 /* Only nonnull if expanding a macro (and not, say, a macro argument). */
906 const struct macro *macro;
907 struct macro_tokens **args;
911 macro_expand (const struct macro_token *mts, size_t n_mts,
912 const struct macro_expander *, struct macro_tokens *);
915 expand_macro_function (const struct macro_expander *me,
916 const struct macro_token *input, size_t n_input,
917 struct string *output);
919 /* Parses one function argument from the N_INPUT tokens in INPUT
920 Each argument to a macro function is one of:
922 - A quoted string or other single literal token.
924 - An argument to the macro being expanded, e.g. !1 or a named argument.
928 - A function invocation.
930 Each function invocation yields a character sequence to be turned into a
931 sequence of tokens. The case where that character sequence is a single
932 quoted string is an important special case.
935 parse_function_arg (const struct macro_expander *me,
936 const struct macro_token *input, size_t n_input,
939 assert (n_input > 0);
941 const struct token *token = &input[0].token;
942 if (token->type == T_MACRO_ID && me->macro)
944 const struct macro_param *param = macro_find_parameter_by_name (
945 me->macro, token->string);
948 size_t param_idx = param - me->macro->params;
949 macro_tokens_to_syntax (me->args[param_idx], farg, NULL, NULL);
953 if (ss_equals (token->string, ss_cstr ("!*")))
955 for (size_t i = 0; i < me->macro->n_params; i++)
957 if (!me->macro->params[i].positional)
960 ds_put_byte (farg, ' ');
961 macro_tokens_to_syntax (me->args[i], farg, NULL, NULL);
966 const char *var = stringi_map_find__ (me->vars,
967 token->string.string,
968 token->string.length);
971 ds_put_cstr (farg, var);
975 size_t n_function = expand_macro_function (me, input, n_input, farg);
980 ds_put_substring (farg, input[0].syntax);
985 parse_function_args (const struct macro_expander *me,
986 const struct macro_token *mts, size_t n,
987 const char *function,
988 struct string_array *args)
990 assert (n >= 2 && mts[1].token.type == T_LPAREN);
992 for (size_t i = 2; i < n; )
994 if (mts[i].token.type == T_RPAREN)
997 struct string s = DS_EMPTY_INITIALIZER;
998 i += parse_function_arg (me, mts + i, n - i, &s);
999 string_array_append_nocopy (args, ds_steal_cstr (&s));
1003 else if (mts[i].token.type == T_COMMA)
1005 else if (mts[i].token.type != T_RPAREN)
1007 macro_error (me->stack, &mts[i],
1008 _("`,' or `)' expected in call to macro function %s."),
1014 macro_error (me->stack, NULL, _("Missing `)' in call to macro function %s."),
1020 unquote_string (const char *s, enum segmenter_mode segmenter_mode,
1021 struct string *content)
1023 struct string_lexer slex;
1024 string_lexer_init (&slex, s, strlen (s), segmenter_mode, true);
1026 struct token token1;
1027 if (string_lexer_next (&slex, &token1) != SLR_TOKEN
1028 || token1.type != T_STRING)
1030 token_uninit (&token1);
1034 struct token token2;
1035 if (string_lexer_next (&slex, &token2) != SLR_END)
1037 token_uninit (&token1);
1038 token_uninit (&token2);
1043 ds_put_substring (content, token1.string);
1044 token_uninit (&token1);
1049 unquote_string_in_place (const char *s, enum segmenter_mode segmenter_mode,
1052 ds_init_empty (tmp);
1053 return unquote_string (s, segmenter_mode, tmp) ? ds_cstr (tmp) : s;
1057 parse_integer (const char *s, int *np)
1062 long int n = strtol (s, &tail, 10);
1063 *np = n < INT_MIN ? INT_MIN : n > INT_MAX ? INT_MAX : n;
1064 tail += strspn (tail, CC_SPACES);
1065 return *tail == '\0' && errno != ERANGE && n == *np;
1069 expand_macro_function (const struct macro_expander *me,
1070 const struct macro_token *input, size_t n_input,
1071 struct string *output)
1073 if (!n_input || input[0].token.type != T_MACRO_ID)
1076 struct macro_function
1082 enum macro_function_id
1096 static const struct macro_function mfs[] = {
1097 [MF_BLANKS] = { "!BLANKS", 1, 1 },
1098 [MF_CONCAT] = { "!CONCAT", 1, INT_MAX },
1099 [MF_EVAL] = { "!EVAL", 1, 1 },
1100 [MF_HEAD] = { "!HEAD", 1, 1 },
1101 [MF_INDEX] = { "!INDEX", 2, 2 },
1102 [MF_LENGTH] = { "!LENGTH", 1, 1 },
1103 [MF_QUOTE] = { "!QUOTE", 1, 1 },
1104 [MF_SUBSTR] = { "!SUBSTR", 2, 3 },
1105 [MF_TAIL] = { "!TAIL", 1, 1 },
1106 [MF_UNQUOTE] = { "!UNQUOTE", 1, 1 },
1107 [MF_UPCASE] = { "!UPCASE", 1, 1 },
1110 if (lex_id_match_n (ss_cstr ("!NULL"), input[0].token.string, 4))
1113 if (n_input < 2 || input[1].token.type != T_LPAREN)
1115 /* Only consider macro functions when the name is followed by '('. */
1119 /* Is this a macro function name? */
1120 const struct macro_function *mf;
1121 for (mf = mfs; ; mf++)
1123 if (mf >= mfs + sizeof mfs / sizeof *mfs)
1125 /* Not a macro function. */
1129 if (lex_id_match_n (ss_cstr (mf->name), input[0].token.string, 4))
1133 enum macro_function_id id = mf - mfs;
1135 struct string_array args = STRING_ARRAY_INITIALIZER;
1136 size_t n_consumed = parse_function_args (me, input, n_input, mf->name, &args);
1139 string_array_destroy (&args);
1143 if (args.n < mf->min_args || args.n > mf->max_args)
1145 if (mf->min_args == 1 && mf->max_args == 1)
1146 macro_error (me->stack, NULL,
1147 _("Macro function %s takes one argument (not %zu)."),
1149 else if (mf->min_args == 2 && mf->max_args == 2)
1150 macro_error (me->stack, NULL,
1151 _("Macro function %s takes two arguments (not %zu)."),
1153 else if (mf->min_args == 2 && mf->max_args == 3)
1154 macro_error (me->stack, NULL,
1155 _("Macro function %s takes two or three arguments "
1158 else if (mf->min_args == 1 && mf->max_args == INT_MAX)
1159 macro_error (me->stack, NULL,
1160 _("Macro function %s needs at least one argument."),
1164 string_array_destroy (&args);
1171 ds_put_format (output, "%zu", strlen (args.strings[0]));
1177 if (!parse_integer (args.strings[0], &n))
1179 macro_error (me->stack, NULL,
1180 _("Argument to !BLANKS must be non-negative integer "
1181 "(not \"%s\")."), args.strings[0]);
1182 string_array_destroy (&args);
1186 ds_put_byte_multiple (output, ' ', n);
1191 for (size_t i = 0; i < args.n; i++)
1192 if (!unquote_string (args.strings[i], me->segmenter_mode, output))
1193 ds_put_cstr (output, args.strings[i]);
1199 const char *s = unquote_string_in_place (args.strings[0],
1200 me->segmenter_mode, &tmp);
1202 struct macro_tokens mts = { .n = 0 };
1203 macro_tokens_from_string__ (&mts, ss_cstr (s), me->segmenter_mode,
1206 ds_put_substring (output, mts.mts[0].syntax);
1207 macro_tokens_uninit (&mts);
1214 const char *haystack = args.strings[0];
1215 const char *needle = strstr (haystack, args.strings[1]);
1216 ds_put_format (output, "%zu", needle ? needle - haystack + 1 : 0);
1221 if (unquote_string (args.strings[0], me->segmenter_mode, NULL))
1222 ds_put_cstr (output, args.strings[0]);
1225 ds_extend (output, strlen (args.strings[0]) + 2);
1226 ds_put_byte (output, '\'');
1227 for (const char *p = args.strings[0]; *p; p++)
1230 ds_put_byte (output, '\'');
1231 ds_put_byte (output, *p);
1233 ds_put_byte (output, '\'');
1240 if (!parse_integer (args.strings[1], &start) || start < 1)
1242 macro_error (me->stack, NULL,
1243 _("Second argument of !SUBSTR must be "
1244 "positive integer (not \"%s\")."),
1246 string_array_destroy (&args);
1250 int count = INT_MAX;
1251 if (args.n > 2 && (!parse_integer (args.strings[2], &count) || count < 0))
1253 macro_error (me->stack, NULL,
1254 _("Third argument of !SUBSTR must be "
1255 "non-negative integer (not \"%s\")."),
1257 string_array_destroy (&args);
1261 struct substring s = ss_cstr (args.strings[0]);
1262 ds_put_substring (output, ss_substr (s, start - 1, count));
1269 const char *s = unquote_string_in_place (args.strings[0],
1270 me->segmenter_mode, &tmp);
1272 struct macro_tokens mts = { .n = 0 };
1273 macro_tokens_from_string__ (&mts, ss_cstr (s), me->segmenter_mode,
1277 struct macro_tokens tail = { .mts = mts.mts + 1, .n = mts.n - 1 };
1278 macro_tokens_to_syntax (&tail, output, NULL, NULL);
1280 macro_tokens_uninit (&mts);
1286 if (!unquote_string (args.strings[0], me->segmenter_mode, output))
1287 ds_put_cstr (output, args.strings[0]);
1293 const char *s = unquote_string_in_place (args.strings[0],
1294 me->segmenter_mode, &tmp);
1295 char *upper = utf8_to_upper (s);
1296 ds_put_cstr (output, upper);
1304 struct macro_tokens mts = { .n = 0 };
1305 macro_tokens_from_string__ (&mts, ss_cstr (args.strings[0]),
1306 me->segmenter_mode, me->stack);
1307 struct macro_tokens exp = { .n = 0 };
1308 struct macro_expansion_stack stack = {
1312 struct macro_expander subme = *me;
1313 subme.break_ = NULL;
1314 subme.stack = &stack;
1316 macro_expand (mts.mts, mts.n, &subme, &exp);
1317 macro_tokens_to_syntax (&exp, output, NULL, NULL);
1318 macro_tokens_uninit (&exp);
1319 macro_tokens_uninit (&mts);
1327 string_array_destroy (&args);
1331 static char *macro_evaluate_or (const struct macro_expander *me,
1332 const struct macro_token **tokens,
1333 const struct macro_token *end);
1336 macro_evaluate_literal (const struct macro_expander *me,
1337 const struct macro_token **tokens,
1338 const struct macro_token *end)
1340 const struct macro_token *p = *tokens;
1343 if (p->token.type == T_LPAREN)
1346 char *value = macro_evaluate_or (me, &p, end);
1349 if (p >= end || p->token.type != T_RPAREN)
1352 macro_error (me->stack, p < end ? p : NULL,
1353 _("Expecting ')' in macro expression."));
1360 else if (p->token.type == T_RPAREN)
1362 macro_error (me->stack, p, _("Expecting literal or function invocation "
1363 "in macro expression."));
1367 struct string function_output = DS_EMPTY_INITIALIZER;
1368 size_t function_consumed = parse_function_arg (me, p, end - p,
1370 struct string unquoted = DS_EMPTY_INITIALIZER;
1371 if (unquote_string (ds_cstr (&function_output), me->segmenter_mode,
1374 ds_swap (&function_output, &unquoted);
1375 ds_destroy (&unquoted);
1377 *tokens = p + function_consumed;
1378 return ds_steal_cstr (&function_output);
1381 /* Returns true if MT is valid as a macro operator. Only operators written as
1382 symbols (e.g. <>) are usable in macro expressions, not operator written as
1383 letters (e.g. EQ). */
1385 is_macro_operator (const struct macro_token *mt)
1387 return mt->syntax.length > 0 && !c_isalpha (mt->syntax.string[0]);
1390 static enum token_type
1391 parse_relational_op (const struct macro_token *mt)
1393 switch (mt->token.type)
1403 return is_macro_operator (mt) ? mt->token.type : T_STOP;
1406 return (ss_equals_case (mt->token.string, ss_cstr ("!EQ")) ? T_EQ
1407 : ss_equals_case (mt->token.string, ss_cstr ("!NE")) ? T_NE
1408 : ss_equals_case (mt->token.string, ss_cstr ("!LT")) ? T_LT
1409 : ss_equals_case (mt->token.string, ss_cstr ("!GT")) ? T_GT
1410 : ss_equals_case (mt->token.string, ss_cstr ("!LE")) ? T_LE
1411 : ss_equals_case (mt->token.string, ss_cstr ("!GE")) ? T_GE
1420 macro_evaluate_relational (const struct macro_expander *me,
1421 const struct macro_token **tokens,
1422 const struct macro_token *end)
1424 const struct macro_token *p = *tokens;
1425 char *lhs = macro_evaluate_literal (me, &p, end);
1429 enum token_type op = p >= end ? T_STOP : parse_relational_op (p);
1437 char *rhs = macro_evaluate_literal (me, &p, end);
1444 struct string lhs_tmp, rhs_tmp;
1445 int cmp = strcmp (unquote_string_in_place (lhs, me->segmenter_mode,
1447 unquote_string_in_place (rhs, me->segmenter_mode,
1449 ds_destroy (&lhs_tmp);
1450 ds_destroy (&rhs_tmp);
1455 bool b = (op == T_EQUALS || op == T_EQ ? !cmp
1457 : op == T_LT ? cmp < 0
1458 : op == T_GT ? cmp > 0
1459 : op == T_LE ? cmp <= 0
1460 : /* T_GE */ cmp >= 0);
1463 return xstrdup (b ? "1" : "0");
1467 macro_evaluate_not (const struct macro_expander *me,
1468 const struct macro_token **tokens,
1469 const struct macro_token *end)
1471 const struct macro_token *p = *tokens;
1473 unsigned int negations = 0;
1475 && (ss_equals_case (p->syntax, ss_cstr ("!NOT"))
1476 || ss_equals (p->syntax, ss_cstr ("~"))))
1482 char *operand = macro_evaluate_relational (me, &p, end);
1483 if (!operand || !negations)
1489 bool b = strcmp (operand, "0") ^ (negations & 1);
1492 return xstrdup (b ? "1" : "0");
1496 macro_evaluate_and (const struct macro_expander *me,
1497 const struct macro_token **tokens,
1498 const struct macro_token *end)
1500 const struct macro_token *p = *tokens;
1501 char *lhs = macro_evaluate_not (me, &p, end);
1506 && (ss_equals_case (p->syntax, ss_cstr ("!AND"))
1507 || ss_equals (p->syntax, ss_cstr ("&"))))
1510 char *rhs = macro_evaluate_not (me, &p, end);
1517 bool b = strcmp (lhs, "0") && strcmp (rhs, "0");
1520 lhs = xstrdup (b ? "1" : "0");
1527 macro_evaluate_or (const struct macro_expander *me,
1528 const struct macro_token **tokens,
1529 const struct macro_token *end)
1531 const struct macro_token *p = *tokens;
1532 char *lhs = macro_evaluate_and (me, &p, end);
1537 && (ss_equals_case (p->syntax, ss_cstr ("!OR"))
1538 || ss_equals (p->syntax, ss_cstr ("|"))))
1541 char *rhs = macro_evaluate_and (me, &p, end);
1548 bool b = strcmp (lhs, "0") || strcmp (rhs, "0");
1551 lhs = xstrdup (b ? "1" : "0");
1558 macro_evaluate_expression (const struct macro_token **tokens, size_t n_tokens,
1559 const struct macro_expander *me)
1561 return macro_evaluate_or (me, tokens, *tokens + n_tokens);
1565 macro_evaluate_number (const struct macro_token **tokens, size_t n_tokens,
1566 const struct macro_expander *me,
1569 char *s = macro_evaluate_expression (tokens, n_tokens, me);
1573 struct macro_tokens mts = { .n = 0 };
1574 macro_tokens_from_string__ (&mts, ss_cstr (s), me->segmenter_mode, me->stack);
1575 if (mts.n != 1 || !token_is_number (&mts.mts[0].token))
1577 macro_error (me->stack, mts.n > 0 ? &mts.mts[0] : NULL,
1578 _("Macro expression must evaluate to "
1579 "a number (not \"%s\")."), s);
1581 macro_tokens_uninit (&mts);
1585 *number = token_number (&mts.mts[0].token);
1587 macro_tokens_uninit (&mts);
1591 static const struct macro_token *
1592 find_ifend_clause (const struct macro_token *p, const struct macro_token *end)
1595 for (; p < end; p++)
1597 if (p->token.type != T_MACRO_ID)
1600 if (ss_equals_case (p->token.string, ss_cstr ("!IF")))
1602 else if (lex_id_match_n (p->token.string, ss_cstr ("!IFEND"), 4))
1608 else if (lex_id_match_n (p->token.string, ss_cstr ("!ELSE"), 4)
1616 macro_expand_if (const struct macro_token *tokens, size_t n_tokens,
1617 const struct macro_expander *me,
1618 struct macro_tokens *exp)
1620 const struct macro_token *p = tokens;
1621 const struct macro_token *end = tokens + n_tokens;
1623 if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!IF")))
1627 char *result = macro_evaluate_expression (&p, end - p, me);
1630 bool b = strcmp (result, "0");
1634 || p->token.type != T_MACRO_ID
1635 || !lex_id_match_n (p->token.string, ss_cstr ("!THEN"), 4))
1637 macro_error (me->stack, p < end ? p : NULL,
1638 _("!THEN expected in macro !IF construct."));
1642 const struct macro_token *start_then = p + 1;
1643 const struct macro_token *end_then = find_ifend_clause (start_then, end);
1646 macro_error (me->stack, NULL,
1647 _("!ELSE or !IFEND expected in macro !IF construct."));
1651 const struct macro_token *start_else, *end_if;
1652 if (lex_id_match_n (end_then->token.string, ss_cstr ("!ELSE"), 4))
1654 start_else = end_then + 1;
1655 end_if = find_ifend_clause (start_else, end);
1657 || !lex_id_match_n (end_if->token.string, ss_cstr ("!IFEND"), 4))
1659 macro_error (me->stack, end_if ? end_if : NULL,
1660 _("!IFEND expected in macro !IF construct."));
1670 const struct macro_token *start;
1675 n = end_then - start_then;
1677 else if (start_else)
1680 n = end_if - start_else;
1690 struct macro_expansion_stack stack = {
1694 struct macro_expander subme = *me;
1695 subme.stack = &stack;
1696 macro_expand (start, n, &subme, exp);
1698 return (end_if + 1) - tokens;
1702 macro_parse_let (const struct macro_token *tokens, size_t n_tokens,
1703 const struct macro_expander *me)
1705 const struct macro_token *p = tokens;
1706 const struct macro_token *end = tokens + n_tokens;
1708 if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!LET")))
1712 if (p >= end || p->token.type != T_MACRO_ID)
1714 macro_error (me->stack, p < end ? p : NULL,
1715 _("Expected macro variable name following !LET."));
1718 const struct substring var_name = p->token.string;
1719 if (is_macro_keyword (var_name)
1720 || macro_find_parameter_by_name (me->macro, var_name))
1722 macro_error (me->stack, p < end ? p : NULL,
1723 _("Cannot use argument name or macro keyword "
1724 "\"%.*s\" as !LET variable."),
1725 (int) var_name.length, var_name.string);
1730 if (p >= end || p->token.type != T_EQUALS)
1732 macro_error (me->stack, p < end ? p : NULL,
1733 _("Expected `=' following !LET."));
1738 char *value = macro_evaluate_expression (&p, end - p, me);
1742 stringi_map_replace_nocopy (me->vars, ss_xstrdup (var_name), value);
1746 static const struct macro_token *
1747 find_doend (const struct macro_expansion_stack *stack,
1748 const struct macro_token *p, const struct macro_token *end)
1751 for (; p < end; p++)
1753 if (p->token.type != T_MACRO_ID)
1756 if (ss_equals_case (p->token.string, ss_cstr ("!DO")))
1758 else if (lex_id_match_n (p->token.string, ss_cstr ("!DOEND"), 4))
1765 macro_error (stack, NULL, _("Missing !DOEND."));
1770 macro_expand_do (const struct macro_token *tokens, size_t n_tokens,
1771 const struct macro_expander *me,
1772 struct macro_tokens *exp)
1774 const struct macro_token *p = tokens;
1775 const struct macro_token *end = tokens + n_tokens;
1777 if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!DO")))
1781 if (p >= end || p->token.type != T_MACRO_ID)
1783 macro_error (me->stack, p < end ? p : NULL,
1784 _("Expected macro variable name following !DO."));
1787 const struct substring var_name = p->token.string;
1788 if (is_macro_keyword (var_name)
1789 || macro_find_parameter_by_name (me->macro, var_name))
1791 macro_error (me->stack, p, _("Cannot use argument name or macro "
1792 "keyword as !DO variable."));
1797 struct macro_expansion_stack substack = {
1801 bool break_ = false;
1802 struct macro_expander subme = *me;
1803 subme.break_ = &break_;
1804 subme.stack = &substack;
1806 int miterate = settings_get_miterate ();
1807 if (p < end && p->token.type == T_MACRO_ID
1808 && ss_equals_case (p->token.string, ss_cstr ("!IN")))
1811 char *list = macro_evaluate_expression (&p, end - p, &subme);
1815 struct macro_tokens items = { .n = 0 };
1816 macro_tokens_from_string__ (&items, ss_cstr (list), me->segmenter_mode,
1820 const struct macro_token *do_end = find_doend (subme.stack, p, end);
1823 macro_tokens_uninit (&items);
1827 for (size_t i = 0; i < items.n && !break_; i++)
1831 macro_error (&substack, NULL,
1832 _("!DO loop over list exceeded "
1833 "maximum number of iterations %d. "
1834 "(Use SET MITERATE to change the limit.)"),
1838 stringi_map_replace_nocopy (me->vars, ss_xstrdup (var_name),
1839 ss_xstrdup (items.mts[i].syntax));
1841 macro_expand (p, do_end - p, &subme, exp);
1843 macro_tokens_uninit (&items);
1844 return do_end - tokens + 1;
1846 else if (p < end && p->token.type == T_EQUALS)
1850 if (!macro_evaluate_number (&p, end - p, &subme, &first))
1853 if (p >= end || p->token.type != T_MACRO_ID
1854 || !ss_equals_case (p->token.string, ss_cstr ("!TO")))
1856 macro_error (subme.stack, p < end ? p : NULL,
1857 _("Expected !TO in numerical !DO loop."));
1863 if (!macro_evaluate_number (&p, end - p, &subme, &last))
1867 if (p < end && p->token.type == T_MACRO_ID
1868 && ss_equals_case (p->token.string, ss_cstr ("!BY")))
1871 if (!macro_evaluate_number (&p, end - p, &subme, &by))
1876 macro_error (subme.stack, NULL, _("!BY value cannot be zero."));
1881 const struct macro_token *do_end = find_doend (subme.stack, p, end);
1884 if ((by > 0 && first <= last) || (by < 0 && first >= last))
1887 for (double index = first;
1888 by > 0 ? (index <= last) : (index >= last) && !break_;
1893 macro_error (subme.stack, NULL,
1894 _("Numerical !DO loop exceeded "
1895 "maximum number of iterations %d. "
1896 "(Use SET MITERATE to change the limit.)"),
1901 char index_s[DBL_BUFSIZE_BOUND];
1902 c_dtoastr (index_s, sizeof index_s, 0, 0, index);
1903 stringi_map_replace_nocopy (me->vars, ss_xstrdup (var_name),
1906 macro_expand (p, do_end - p, &subme, exp);
1910 return do_end - tokens + 1;
1914 macro_error (me->stack, p < end ? p : NULL,
1915 _("Expected `=' or !IN in !DO loop."));
1921 macro_expand_arg__ (const struct macro_expander *me, size_t idx,
1922 struct macro_tokens *exp)
1924 const struct macro_param *param = &me->macro->params[idx];
1925 const struct macro_tokens *arg = me->args[idx];
1927 if (*me->expand && param->expand_arg)
1929 struct stringi_map vars = STRINGI_MAP_INITIALIZER (vars);
1930 struct macro_expansion_stack stack = {
1931 .name = param->name,
1934 struct macro_expander subme = {
1935 .macros = me->macros,
1938 .segmenter_mode = me->segmenter_mode,
1939 .expand = me->expand,
1942 .nesting_countdown = me->nesting_countdown,
1945 macro_expand (arg->mts, arg->n, &subme, exp);
1946 stringi_map_destroy (&vars);
1949 for (size_t i = 0; i < arg->n; i++)
1950 macro_tokens_add (exp, &arg->mts[i]);
1954 macro_expand_arg (const struct token *token, const struct macro_expander *me,
1955 struct macro_tokens *exp)
1957 if (!me || token->type != T_MACRO_ID)
1960 /* Macro arguments. */
1963 const struct macro_param *param = macro_find_parameter_by_name (
1964 me->macro, token->string);
1967 macro_expand_arg__ (me, param - me->macro->params, exp);
1970 else if (ss_equals (token->string, ss_cstr ("!*")))
1972 for (size_t j = 0; j < me->macro->n_params; j++)
1973 macro_expand_arg__ (me, j, exp);
1978 /* Variables set by !DO or !LET. */
1979 const char *var = stringi_map_find__ (me->vars, token->string.string,
1980 token->string.length);
1983 macro_tokens_from_string__ (exp, ss_cstr (var),
1984 me->segmenter_mode, me->stack);
1992 macro_expand__ (const struct macro_token *mts, size_t n,
1993 const struct macro_expander *me,
1994 struct macro_tokens *exp)
1996 const struct token *token = &mts[0].token;
1998 /* Recursive macro calls. */
2001 struct macro_call *submc;
2002 int n_call = macro_call_create__ (me->macros, me->stack, me,
2004 for (size_t j = 1; !n_call; j++)
2006 const struct macro_token endcmd
2007 = { .token = { .type = T_ENDCMD } };
2008 n_call = macro_call_add (submc, j < n ? &mts[j] : &endcmd, NULL);
2012 struct stringi_map vars = STRINGI_MAP_INITIALIZER (vars);
2013 struct macro_expansion_stack stack = {
2014 .name = submc->macro->name,
2015 .location = submc->macro->location,
2018 struct macro_expander subme = {
2019 .macros = submc->macros,
2020 .macro = submc->macro,
2021 .args = submc->args,
2022 .segmenter_mode = me->segmenter_mode,
2023 .expand = me->expand,
2026 .nesting_countdown = me->nesting_countdown - 1,
2029 const struct macro_tokens *body = &submc->macro->body;
2030 macro_expand (body->mts, body->n, &subme, exp);
2031 macro_call_destroy (submc);
2032 stringi_map_destroy (&vars);
2036 macro_call_destroy (submc);
2039 if (token->type != T_MACRO_ID)
2041 macro_tokens_add (exp, &mts[0]);
2045 /* Parameters and macro variables. */
2046 if (macro_expand_arg (token, me, exp))
2049 /* Macro functions. */
2050 struct string function_output = DS_EMPTY_INITIALIZER;
2051 size_t n_function = expand_macro_function (me, mts, n, &function_output);
2054 macro_tokens_from_string__ (exp, function_output.ss,
2055 me->segmenter_mode, me->stack);
2056 ds_destroy (&function_output);
2061 size_t n_if = macro_expand_if (mts, n, me, exp);
2065 size_t n_let = macro_parse_let (mts, n, me);
2069 size_t n_do = macro_expand_do (mts, n, me, exp);
2073 if (lex_id_match_n (token->string, ss_cstr ("!break"), 4))
2078 macro_error (me->stack, &mts[0], _("!BREAK outside !DO."));
2080 else if (lex_id_match_n (token->string, ss_cstr ("!onexpand"), 4))
2082 else if (lex_id_match_n (token->string, ss_cstr ("!offexpand"), 4))
2083 *me->expand = false;
2085 macro_tokens_add (exp, &mts[0]);
2090 macro_expand (const struct macro_token *mts, size_t n,
2091 const struct macro_expander *me,
2092 struct macro_tokens *exp)
2094 if (me->nesting_countdown <= 0)
2096 macro_error (me->stack, NULL, _("Maximum nesting level %d exceeded. "
2097 "(Use SET MNEST to change the limit.)"),
2098 settings_get_mnest ());
2099 for (size_t i = 0; i < n; i++)
2100 macro_tokens_add (exp, &mts[i]);
2104 for (size_t i = 0; i < n; )
2106 if (me->break_ && *me->break_)
2109 size_t consumed = macro_expand__ (&mts[i], n - i, me, exp);
2110 assert (consumed > 0 && i + consumed <= n);
2116 macro_call_expand (struct macro_call *mc, enum segmenter_mode segmenter_mode,
2117 const struct msg_location *call_loc,
2118 struct macro_tokens *exp)
2120 assert (mc->state == MC_FINISHED);
2123 struct stringi_map vars = STRINGI_MAP_INITIALIZER (vars);
2124 struct macro_expansion_stack stack0 = {
2125 .location = call_loc,
2127 struct macro_expansion_stack stack1 = {
2129 .name = mc->macro->name,
2130 .location = mc->macro->location,
2132 struct macro_expander me = {
2133 .macros = mc->macros,
2136 .segmenter_mode = segmenter_mode,
2140 .nesting_countdown = settings_get_mnest (),
2144 const struct macro_tokens *body = &mc->macro->body;
2145 macro_expand (body->mts, body->n, &me, exp);
2147 stringi_map_destroy (&vars);