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, using STACK
224 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 enum segment_type type;
236 int seg_len = segmenter_push (&segmenter, body.string,
237 body.length, true, &type);
238 assert (seg_len >= 0);
240 struct macro_token mt = {
241 .token = { .type = T_STOP },
242 .syntax = ss_head (body, seg_len),
244 enum tokenize_result result
245 = token_from_segment (type, mt.syntax, &mt.token);
246 ss_advance (&body, seg_len);
254 macro_tokens_add (mts, &mt);
258 macro_error (stack, &mt, "%s", mt.token.string.string);
262 token_uninit (&mt.token);
267 macro_tokens_print (const struct macro_tokens *mts, FILE *stream)
269 for (size_t i = 0; i < mts->n; i++)
270 token_print (&mts->mts[i].token, stream);
275 TC_ENDCMD, /* No space before or after (new-line after). */
276 TC_BINOP, /* Space on both sides. */
277 TC_COMMA, /* Space afterward. */
278 TC_ID, /* Don't need spaces except sequentially. */
279 TC_PUNCT, /* Don't need spaces except sequentially. */
283 needs_space (enum token_class prev, enum token_class next)
285 /* Don't need a space before or after the end of a command.
286 (A new-line is needed afterward as a special case.) */
287 if (prev == TC_ENDCMD || next == TC_ENDCMD)
290 /* Binary operators always have a space on both sides. */
291 if (prev == TC_BINOP || next == TC_BINOP)
294 /* A comma always has a space afterward. */
295 if (prev == TC_COMMA)
298 /* Otherwise, PREV is TC_ID or TC_PUNCT, which only need a space if there are
299 two or them in a row. */
303 static enum token_class
304 classify_token (enum token_type type)
360 /* Appends syntax for the tokens in MTS to S. If OFS and LEN are nonnull, sets
361 OFS[i] to the offset within S of the start of token 'i' in MTS and LEN[i] to
362 its length. OFS[i] + LEN[i] is not necessarily OFS[i + 1] because some
363 tokens are separated by white space. */
365 macro_tokens_to_syntax (struct macro_tokens *mts, struct string *s,
366 size_t *ofs, size_t *len)
368 assert ((ofs != NULL) == (len != NULL));
373 for (size_t i = 0; i < mts->n; i++)
377 enum token_type prev = mts->mts[i - 1].token.type;
378 enum token_type next = mts->mts[i].token.type;
380 if (prev == T_ENDCMD)
381 ds_put_byte (s, '\n');
384 enum token_class pc = classify_token (prev);
385 enum token_class nc = classify_token (next);
386 if (needs_space (pc, nc))
387 ds_put_byte (s, ' ');
392 ofs[i] = s->ss.length;
393 macro_token_to_syntax (&mts->mts[i], s);
395 len[i] = s->ss.length - ofs[i];
400 macro_destroy (struct macro *m)
406 msg_location_destroy (m->location);
407 for (size_t i = 0; i < m->n_params; i++)
409 struct macro_param *p = &m->params[i];
412 macro_tokens_uninit (&p->def);
413 token_uninit (&p->start);
414 token_uninit (&p->end);
417 macro_tokens_uninit (&m->body);
422 macro_set_create (void)
424 struct macro_set *set = xmalloc (sizeof *set);
425 *set = (struct macro_set) {
426 .macros = HMAP_INITIALIZER (set->macros),
432 macro_set_destroy (struct macro_set *set)
437 struct macro *macro, *next;
438 HMAP_FOR_EACH_SAFE (macro, next, struct macro, hmap_node, &set->macros)
440 hmap_delete (&set->macros, ¯o->hmap_node);
441 macro_destroy (macro);
443 hmap_destroy (&set->macros);
448 hash_macro_name (const char *name)
450 return utf8_hash_case_string (name, 0);
453 static struct macro *
454 macro_set_find__ (struct macro_set *set, const char *name)
456 if (macro_set_is_empty (set))
460 HMAP_FOR_EACH_WITH_HASH (macro, struct macro, hmap_node,
461 hash_macro_name (name), &set->macros)
462 if (!utf8_strcasecmp (macro->name, name))
469 macro_set_find (const struct macro_set *set, const char *name)
471 return macro_set_find__ (CONST_CAST (struct macro_set *, set), name);
474 /* Adds M to SET. M replaces any existing macro with the same name. Takes
477 macro_set_add (struct macro_set *set, struct macro *m)
479 struct macro *victim = macro_set_find__ (set, m->name);
482 hmap_delete (&set->macros, &victim->hmap_node);
483 macro_destroy (victim);
486 hmap_insert (&set->macros, &m->hmap_node, hash_macro_name (m->name));
489 /* Macro call parsing. */
493 /* Accumulating tokens in mc->params toward the end of any type of
497 /* Expecting the opening delimiter of an ARG_ENCLOSE argument. */
500 /* Expecting a keyword for a keyword argument. */
503 /* Expecting an equal sign for a keyword argument. */
506 /* Macro fully parsed and ready for expansion. */
510 /* Parsing macro calls. This is a FSM driven by macro_call_create() and
511 macro_call_add() to identify the macro being called and obtain its
512 arguments. 'state' identifies the FSM state. */
515 const struct macro_set *macros;
516 const struct macro *macro;
517 struct macro_tokens **args;
518 const struct macro_expansion_stack *stack;
519 const struct macro_expander *me;
523 const struct macro_param *param; /* Parameter currently being parsed. */
526 static bool macro_expand_arg (const struct token *,
527 const struct macro_expander *,
528 struct macro_tokens *exp);
530 /* Completes macro expansion by initializing arguments that weren't supplied to
533 mc_finished (struct macro_call *mc)
535 mc->state = MC_FINISHED;
536 for (size_t i = 0; i < mc->macro->n_params; i++)
538 mc->args[i] = &mc->macro->params[i].def;
543 mc_next_arg (struct macro_call *mc)
547 assert (!mc->macro->n_params);
548 return mc_finished (mc);
550 else if (mc->param->positional)
553 if (mc->param >= &mc->macro->params[mc->macro->n_params])
554 return mc_finished (mc);
557 mc->state = (!mc->param->positional ? MC_KEYWORD
558 : mc->param->arg_type == ARG_ENCLOSE ? MC_ENCLOSE
565 for (size_t i = 0; i < mc->macro->n_params; i++)
568 mc->state = MC_KEYWORD;
571 return mc_finished (mc);
575 static void PRINTF_FORMAT (3, 4)
576 mc_error (const struct macro_call *mc, const struct msg_location *loc,
577 const char *format, ...)
580 va_start (args, format);
583 const struct macro_expansion_stack stack = { .location = loc };
584 macro_error_valist (&stack, NULL, format, args);
587 macro_error_valist (mc->stack, NULL, format, args);
592 mc_add_arg (struct macro_call *mc, const struct macro_token *mt,
593 const struct msg_location *loc)
595 const struct macro_param *p = mc->param;
596 struct macro_tokens **argp = &mc->args[p - mc->macro->params];
598 const struct token *token = &mt->token;
599 if (token->type == T_ENDCMD || token->type == T_STOP)
606 /* This is OK, it's the expected way to end the argument. */
611 ngettext (_("Reached end of command expecting %zu "
612 "more token in argument %s to macro %s."),
613 _("Reached end of command expecting %zu "
614 "more tokens in argument %s to macro %s."),
615 p->n_tokens - (*argp)->n),
616 p->n_tokens - (*argp)->n, p->name, mc->macro->name);
622 char *end = token_to_string (&p->end);
623 mc_error (mc, loc, _("Reached end of command expecting \"%s\" "
624 "in argument %s to macro %s."),
625 end, p->name, mc->macro->name);
632 /* The end of a command ends the current argument, precludes any further
633 arguments, and is not itself part of the argument. */
634 return mc_finished (mc);
640 *argp = xzalloc (sizeof **argp);
642 bool add_token; /* Should we add 'mt' to the current arg? */
643 bool next_arg; /* Should we advance to the next arg? */
647 next_arg = (*argp)->n + 1 >= p->n_tokens;
653 next_arg = token_equal (token, &p->end);
654 add_token = !next_arg;
668 if (!macro_expand_arg (&mt->token, mc->me, *argp))
669 macro_tokens_add (*argp, mt);
671 return next_arg ? mc_next_arg (mc) : 0;
675 mc_expected (struct macro_call *mc, const struct macro_token *actual,
676 const struct msg_location *loc, const struct token *expected)
678 const struct substring actual_s = (actual->syntax.length ? actual->syntax
679 : ss_cstr (_("<end of input>")));
680 char *expected_s = token_to_string (expected);
682 _("Found `%.*s' while expecting `%s' reading argument %s "
684 (int) actual_s.length, actual_s.string, expected_s,
685 mc->param->name, mc->macro->name);
688 return mc_finished (mc);
692 mc_enclose (struct macro_call *mc, const struct macro_token *mt,
693 const struct msg_location *loc)
695 const struct token *token = &mt->token;
696 const struct macro_param *p = mc->param;
697 if (token_equal (&p->start, token))
701 struct macro_tokens **argp = &mc->args[p - mc->macro->params];
703 *argp = xzalloc (sizeof **argp);
707 else if (p->positional && (token->type == T_ENDCMD || token->type == T_STOP))
708 return mc_finished (mc);
710 return mc_expected (mc, mt, loc, &p->start);
713 static const struct macro_param *
714 macro_find_parameter_by_name (const struct macro *m, struct substring name)
719 ss_ltrim (&name, ss_cstr ("!"));
721 for (size_t i = 0; i < m->n_params; i++)
723 const struct macro_param *p = &m->params[i];
724 struct substring p_name = ss_cstr (p->name + 1);
725 if (!utf8_strncasecmp (p_name.string, p_name.length,
726 name.string, name.length))
733 mc_keyword (struct macro_call *mc, const struct macro_token *mt,
734 const struct msg_location *loc)
736 const struct token *token = &mt->token;
737 if (token->type != T_ID)
738 return mc_finished (mc);
740 const struct macro_param *p = macro_find_parameter_by_name (mc->macro,
744 struct macro_tokens **argp = &mc->args[p - mc->macro->params];
747 _("Argument %s multiply specified in call to macro %s."),
748 p->name, mc->macro->name);
750 *argp = xzalloc (sizeof **argp);
753 mc->state = MC_EQUALS;
757 return mc_finished (mc);
761 mc_equals (struct macro_call *mc, const struct macro_token *mt,
762 const struct msg_location *loc)
764 if (mt->token.type == T_EQUALS)
767 mc->state = mc->param->arg_type == ARG_ENCLOSE ? MC_ENCLOSE : MC_ARG;
771 return mc_expected (mc, mt, loc, &(struct token) { .type = T_EQUALS });
775 macro_call_create__ (const struct macro_set *macros,
776 const struct macro_expansion_stack *stack,
777 const struct macro_expander *me,
778 const struct token *token,
779 struct macro_call **mcp)
781 const struct macro *macro = (token->type == T_ID || token->type == T_MACRO_ID
782 ? macro_set_find (macros, token->string.string)
790 struct macro_call *mc = xmalloc (sizeof *mc);
791 *mc = (struct macro_call) {
795 .state = (!macro->n_params ? MC_FINISHED
796 : !macro->params[0].positional ? MC_KEYWORD
797 : macro->params[0].arg_type == ARG_ENCLOSE ? MC_ENCLOSE
799 .args = macro->n_params ? xcalloc (macro->n_params, sizeof *mc->args) : NULL,
800 .param = macro->params,
806 return mc->state == MC_FINISHED ? 1 : 0;
809 /* If TOKEN is the first token of a call to a macro in MACROS, create a new
810 macro expander, initializes *MCP to it. Returns 0 if more tokens are needed
811 and should be added via macro_call_add() or 1 if the caller should next call
814 If TOKEN is not the first token of a macro call, returns -1 and sets *MCP to
817 macro_call_create (const struct macro_set *macros,
818 const struct token *token,
819 struct macro_call **mcp)
821 return macro_call_create__ (macros, NULL, NULL, token, mcp);
825 macro_call_destroy (struct macro_call *mc)
830 for (size_t i = 0; i < mc->macro->n_params; i++)
832 struct macro_tokens *a = mc->args[i];
833 if (a && a != &mc->macro->params[i].def)
835 macro_tokens_uninit (a);
843 /* Adds TOKEN to the collection of tokens in MC that potentially need to be
846 Returns -1 if the tokens added do not actually invoke a macro. The caller
847 should consume the first token without expanding it. (Later tokens might
848 invoke a macro so it's best to feed the second token into a new expander.)
850 Returns 0 if the macro expander needs more tokens, for macro arguments or to
851 decide whether this is actually a macro invocation. The caller should call
852 macro_call_add() again with the next token.
854 Returns a positive number to indicate that the returned number of tokens
855 invoke a macro. The number returned might be less than the number of tokens
856 added because it can take a few tokens of lookahead to determine whether the
857 macro invocation is finished. The caller should call macro_call_expand() to
858 obtain the expansion. */
860 macro_call_add (struct macro_call *mc, const struct macro_token *mt,
861 const struct msg_location *loc)
866 return mc_add_arg (mc, mt, loc);
869 return mc_enclose (mc, mt, loc);
872 return mc_keyword (mc, mt, loc);
875 return mc_equals (mc, mt, loc);
882 /* Macro expansion. */
884 struct macro_expander
886 /* Always available. */
887 const struct macro_set *macros; /* Macros to expand recursively. */
888 enum segmenter_mode segmenter_mode; /* Mode for tokenization. */
889 int nesting_countdown; /* Remaining nesting levels. */
890 const struct macro_expansion_stack *stack; /* Stack for error reporting. */
891 bool *expand; /* May macro calls be expanded? */
892 struct stringi_map *vars; /* Variables from !do and !let. */
894 /* Only nonnull if inside a !DO loop. */
895 bool *break_; /* Set to true to break out of loop. */
897 /* Only nonnull if expanding a macro (and not, say, a macro argument). */
898 const struct macro *macro;
899 struct macro_tokens **args;
903 macro_expand (const struct macro_token *mts, size_t n_mts,
904 const struct macro_expander *, struct macro_tokens *);
907 expand_macro_function (const struct macro_expander *me,
908 const struct macro_token *input, size_t n_input,
909 struct string *output);
911 /* Parses one function argument from the N_INPUT tokens in INPUT
912 Each argument to a macro function is one of:
914 - A quoted string or other single literal token.
916 - An argument to the macro being expanded, e.g. !1 or a named argument.
920 - A function invocation.
922 Each function invocation yields a character sequence to be turned into a
923 sequence of tokens. The case where that character sequence is a single
924 quoted string is an important special case.
927 parse_function_arg (const struct macro_expander *me,
928 const struct macro_token *input, size_t n_input,
931 assert (n_input > 0);
933 const struct token *token = &input[0].token;
934 if (token->type == T_MACRO_ID && me->macro)
936 const struct macro_param *param = macro_find_parameter_by_name (
937 me->macro, token->string);
940 size_t param_idx = param - me->macro->params;
941 macro_tokens_to_syntax (me->args[param_idx], farg, NULL, NULL);
945 if (ss_equals (token->string, ss_cstr ("!*")))
947 for (size_t i = 0; i < me->macro->n_params; i++)
949 if (!me->macro->params[i].positional)
952 ds_put_byte (farg, ' ');
953 macro_tokens_to_syntax (me->args[i], farg, NULL, NULL);
958 const char *var = stringi_map_find__ (me->vars,
959 token->string.string,
960 token->string.length);
963 ds_put_cstr (farg, var);
967 size_t n_function = expand_macro_function (me, input, n_input, farg);
972 ds_put_substring (farg, input[0].syntax);
977 parse_function_args (const struct macro_expander *me,
978 const struct macro_token *mts, size_t n,
979 const char *function,
980 struct string_array *args)
982 assert (n >= 2 && mts[1].token.type == T_LPAREN);
984 for (size_t i = 2; i < n; )
986 if (mts[i].token.type == T_RPAREN)
989 struct string s = DS_EMPTY_INITIALIZER;
990 i += parse_function_arg (me, mts + i, n - i, &s);
991 string_array_append_nocopy (args, ds_steal_cstr (&s));
995 else if (mts[i].token.type == T_COMMA)
997 else if (mts[i].token.type != T_RPAREN)
999 macro_error (me->stack, &mts[i],
1000 _("`,' or `)' expected in call to macro function %s."),
1006 macro_error (me->stack, NULL, _("Missing `)' in call to macro function %s."),
1012 unquote_string (const char *s, enum segmenter_mode segmenter_mode,
1013 struct string *content)
1015 struct string_lexer slex;
1016 string_lexer_init (&slex, s, strlen (s), segmenter_mode, true);
1018 struct token token1;
1019 if (string_lexer_next (&slex, &token1) != SLR_TOKEN
1020 || token1.type != T_STRING)
1022 token_uninit (&token1);
1026 struct token token2;
1027 if (string_lexer_next (&slex, &token2) != SLR_END)
1029 token_uninit (&token1);
1030 token_uninit (&token2);
1035 ds_put_substring (content, token1.string);
1036 token_uninit (&token1);
1041 unquote_string_in_place (const char *s, enum segmenter_mode segmenter_mode,
1044 ds_init_empty (tmp);
1045 return unquote_string (s, segmenter_mode, tmp) ? ds_cstr (tmp) : s;
1049 parse_integer (const char *s, int *np)
1054 long int n = strtol (s, &tail, 10);
1055 *np = n < INT_MIN ? INT_MIN : n > INT_MAX ? INT_MAX : n;
1056 tail += strspn (tail, CC_SPACES);
1057 return *tail == '\0' && errno != ERANGE && n == *np;
1061 expand_macro_function (const struct macro_expander *me,
1062 const struct macro_token *input, size_t n_input,
1063 struct string *output)
1065 if (!n_input || input[0].token.type != T_MACRO_ID)
1068 struct macro_function
1074 enum macro_function_id
1088 static const struct macro_function mfs[] = {
1089 [MF_BLANKS] = { "!BLANKS", 1, 1 },
1090 [MF_CONCAT] = { "!CONCAT", 1, INT_MAX },
1091 [MF_EVAL] = { "!EVAL", 1, 1 },
1092 [MF_HEAD] = { "!HEAD", 1, 1 },
1093 [MF_INDEX] = { "!INDEX", 2, 2 },
1094 [MF_LENGTH] = { "!LENGTH", 1, 1 },
1095 [MF_QUOTE] = { "!QUOTE", 1, 1 },
1096 [MF_SUBSTR] = { "!SUBSTR", 2, 3 },
1097 [MF_TAIL] = { "!TAIL", 1, 1 },
1098 [MF_UNQUOTE] = { "!UNQUOTE", 1, 1 },
1099 [MF_UPCASE] = { "!UPCASE", 1, 1 },
1102 if (lex_id_match_n (ss_cstr ("!NULL"), input[0].token.string, 4))
1105 if (n_input < 2 || input[1].token.type != T_LPAREN)
1107 /* Only consider macro functions when the name is followed by '('. */
1111 /* Is this a macro function name? */
1112 const struct macro_function *mf;
1113 for (mf = mfs; ; mf++)
1115 if (mf >= mfs + sizeof mfs / sizeof *mfs)
1117 /* Not a macro function. */
1121 if (lex_id_match_n (ss_cstr (mf->name), input[0].token.string, 4))
1125 enum macro_function_id id = mf - mfs;
1127 struct string_array args = STRING_ARRAY_INITIALIZER;
1128 size_t n_consumed = parse_function_args (me, input, n_input, mf->name, &args);
1131 string_array_destroy (&args);
1135 if (args.n < mf->min_args || args.n > mf->max_args)
1137 if (mf->min_args == 1 && mf->max_args == 1)
1138 macro_error (me->stack, NULL,
1139 _("Macro function %s takes one argument (not %zu)."),
1141 else if (mf->min_args == 2 && mf->max_args == 2)
1142 macro_error (me->stack, NULL,
1143 _("Macro function %s takes two arguments (not %zu)."),
1145 else if (mf->min_args == 2 && mf->max_args == 3)
1146 macro_error (me->stack, NULL,
1147 _("Macro function %s takes two or three arguments "
1150 else if (mf->min_args == 1 && mf->max_args == INT_MAX)
1151 macro_error (me->stack, NULL,
1152 _("Macro function %s needs at least one argument."),
1156 string_array_destroy (&args);
1163 ds_put_format (output, "%zu", strlen (args.strings[0]));
1169 if (!parse_integer (args.strings[0], &n))
1171 macro_error (me->stack, NULL,
1172 _("Argument to !BLANKS must be non-negative integer "
1173 "(not \"%s\")."), args.strings[0]);
1174 string_array_destroy (&args);
1178 ds_put_byte_multiple (output, ' ', n);
1183 for (size_t i = 0; i < args.n; i++)
1184 if (!unquote_string (args.strings[i], me->segmenter_mode, output))
1185 ds_put_cstr (output, args.strings[i]);
1191 const char *s = unquote_string_in_place (args.strings[0],
1192 me->segmenter_mode, &tmp);
1194 struct macro_tokens mts = { .n = 0 };
1195 macro_tokens_from_string (&mts, ss_cstr (s), me->segmenter_mode,
1198 ds_put_substring (output, mts.mts[0].syntax);
1199 macro_tokens_uninit (&mts);
1206 const char *haystack = args.strings[0];
1207 const char *needle = strstr (haystack, args.strings[1]);
1208 ds_put_format (output, "%zu", needle ? needle - haystack + 1 : 0);
1213 if (unquote_string (args.strings[0], me->segmenter_mode, NULL))
1214 ds_put_cstr (output, args.strings[0]);
1217 ds_extend (output, strlen (args.strings[0]) + 2);
1218 ds_put_byte (output, '\'');
1219 for (const char *p = args.strings[0]; *p; p++)
1222 ds_put_byte (output, '\'');
1223 ds_put_byte (output, *p);
1225 ds_put_byte (output, '\'');
1232 if (!parse_integer (args.strings[1], &start) || start < 1)
1234 macro_error (me->stack, NULL,
1235 _("Second argument of !SUBSTR must be "
1236 "positive integer (not \"%s\")."),
1238 string_array_destroy (&args);
1242 int count = INT_MAX;
1243 if (args.n > 2 && (!parse_integer (args.strings[2], &count) || count < 0))
1245 macro_error (me->stack, NULL,
1246 _("Third argument of !SUBSTR must be "
1247 "non-negative integer (not \"%s\")."),
1249 string_array_destroy (&args);
1253 struct substring s = ss_cstr (args.strings[0]);
1254 ds_put_substring (output, ss_substr (s, start - 1, count));
1261 const char *s = unquote_string_in_place (args.strings[0],
1262 me->segmenter_mode, &tmp);
1264 struct macro_tokens mts = { .n = 0 };
1265 macro_tokens_from_string (&mts, ss_cstr (s), me->segmenter_mode,
1269 struct macro_tokens tail = { .mts = mts.mts + 1, .n = mts.n - 1 };
1270 macro_tokens_to_syntax (&tail, output, NULL, NULL);
1272 macro_tokens_uninit (&mts);
1278 if (!unquote_string (args.strings[0], me->segmenter_mode, output))
1279 ds_put_cstr (output, args.strings[0]);
1285 const char *s = unquote_string_in_place (args.strings[0],
1286 me->segmenter_mode, &tmp);
1287 char *upper = utf8_to_upper (s);
1288 ds_put_cstr (output, upper);
1296 struct macro_tokens mts = { .n = 0 };
1297 macro_tokens_from_string (&mts, ss_cstr (args.strings[0]),
1298 me->segmenter_mode, me->stack);
1299 struct macro_tokens exp = { .n = 0 };
1300 struct macro_expansion_stack stack = {
1304 struct macro_expander subme = *me;
1305 subme.break_ = NULL;
1306 subme.stack = &stack;
1308 macro_expand (mts.mts, mts.n, &subme, &exp);
1309 macro_tokens_to_syntax (&exp, output, NULL, NULL);
1310 macro_tokens_uninit (&exp);
1311 macro_tokens_uninit (&mts);
1319 string_array_destroy (&args);
1323 static char *macro_evaluate_or (const struct macro_expander *me,
1324 const struct macro_token **tokens,
1325 const struct macro_token *end);
1328 macro_evaluate_literal (const struct macro_expander *me,
1329 const struct macro_token **tokens,
1330 const struct macro_token *end)
1332 const struct macro_token *p = *tokens;
1335 if (p->token.type == T_LPAREN)
1338 char *value = macro_evaluate_or (me, &p, end);
1341 if (p >= end || p->token.type != T_RPAREN)
1344 macro_error (me->stack, p < end ? p : NULL,
1345 _("Expecting ')' in macro expression."));
1352 else if (p->token.type == T_RPAREN)
1354 macro_error (me->stack, p, _("Expecting literal or function invocation "
1355 "in macro expression."));
1359 struct string function_output = DS_EMPTY_INITIALIZER;
1360 size_t function_consumed = parse_function_arg (me, p, end - p,
1362 struct string unquoted = DS_EMPTY_INITIALIZER;
1363 if (unquote_string (ds_cstr (&function_output), me->segmenter_mode,
1366 ds_swap (&function_output, &unquoted);
1367 ds_destroy (&unquoted);
1369 *tokens = p + function_consumed;
1370 return ds_steal_cstr (&function_output);
1373 /* Returns true if MT is valid as a macro operator. Only operators written as
1374 symbols (e.g. <>) are usable in macro expressions, not operator written as
1375 letters (e.g. EQ). */
1377 is_macro_operator (const struct macro_token *mt)
1379 return mt->syntax.length > 0 && !c_isalpha (mt->syntax.string[0]);
1382 static enum token_type
1383 parse_relational_op (const struct macro_token *mt)
1385 switch (mt->token.type)
1395 return is_macro_operator (mt) ? mt->token.type : T_STOP;
1398 return (ss_equals_case (mt->token.string, ss_cstr ("!EQ")) ? T_EQ
1399 : ss_equals_case (mt->token.string, ss_cstr ("!NE")) ? T_NE
1400 : ss_equals_case (mt->token.string, ss_cstr ("!LT")) ? T_LT
1401 : ss_equals_case (mt->token.string, ss_cstr ("!GT")) ? T_GT
1402 : ss_equals_case (mt->token.string, ss_cstr ("!LE")) ? T_LE
1403 : ss_equals_case (mt->token.string, ss_cstr ("!GE")) ? T_GE
1412 macro_evaluate_relational (const struct macro_expander *me,
1413 const struct macro_token **tokens,
1414 const struct macro_token *end)
1416 const struct macro_token *p = *tokens;
1417 char *lhs = macro_evaluate_literal (me, &p, end);
1421 enum token_type op = p >= end ? T_STOP : parse_relational_op (p);
1429 char *rhs = macro_evaluate_literal (me, &p, end);
1436 struct string lhs_tmp, rhs_tmp;
1437 int cmp = strcmp (unquote_string_in_place (lhs, me->segmenter_mode,
1439 unquote_string_in_place (rhs, me->segmenter_mode,
1441 ds_destroy (&lhs_tmp);
1442 ds_destroy (&rhs_tmp);
1447 bool b = (op == T_EQUALS || op == T_EQ ? !cmp
1449 : op == T_LT ? cmp < 0
1450 : op == T_GT ? cmp > 0
1451 : op == T_LE ? cmp <= 0
1452 : /* T_GE */ cmp >= 0);
1455 return xstrdup (b ? "1" : "0");
1459 macro_evaluate_not (const struct macro_expander *me,
1460 const struct macro_token **tokens,
1461 const struct macro_token *end)
1463 const struct macro_token *p = *tokens;
1465 unsigned int negations = 0;
1467 && (ss_equals_case (p->syntax, ss_cstr ("!NOT"))
1468 || ss_equals (p->syntax, ss_cstr ("~"))))
1474 char *operand = macro_evaluate_relational (me, &p, end);
1475 if (!operand || !negations)
1481 bool b = strcmp (operand, "0") ^ (negations & 1);
1484 return xstrdup (b ? "1" : "0");
1488 macro_evaluate_and (const struct macro_expander *me,
1489 const struct macro_token **tokens,
1490 const struct macro_token *end)
1492 const struct macro_token *p = *tokens;
1493 char *lhs = macro_evaluate_not (me, &p, end);
1498 && (ss_equals_case (p->syntax, ss_cstr ("!AND"))
1499 || ss_equals (p->syntax, ss_cstr ("&"))))
1502 char *rhs = macro_evaluate_not (me, &p, end);
1509 bool b = strcmp (lhs, "0") && strcmp (rhs, "0");
1512 lhs = xstrdup (b ? "1" : "0");
1519 macro_evaluate_or (const struct macro_expander *me,
1520 const struct macro_token **tokens,
1521 const struct macro_token *end)
1523 const struct macro_token *p = *tokens;
1524 char *lhs = macro_evaluate_and (me, &p, end);
1529 && (ss_equals_case (p->syntax, ss_cstr ("!OR"))
1530 || ss_equals (p->syntax, ss_cstr ("|"))))
1533 char *rhs = macro_evaluate_and (me, &p, end);
1540 bool b = strcmp (lhs, "0") || strcmp (rhs, "0");
1543 lhs = xstrdup (b ? "1" : "0");
1550 macro_evaluate_expression (const struct macro_token **tokens, size_t n_tokens,
1551 const struct macro_expander *me)
1553 return macro_evaluate_or (me, tokens, *tokens + n_tokens);
1557 macro_evaluate_number (const struct macro_token **tokens, size_t n_tokens,
1558 const struct macro_expander *me,
1561 char *s = macro_evaluate_expression (tokens, n_tokens, me);
1565 struct macro_tokens mts = { .n = 0 };
1566 macro_tokens_from_string (&mts, ss_cstr (s), me->segmenter_mode, me->stack);
1567 if (mts.n != 1 || !token_is_number (&mts.mts[0].token))
1569 macro_error (me->stack, mts.n > 0 ? &mts.mts[0] : NULL,
1570 _("Macro expression must evaluate to "
1571 "a number (not \"%s\")."), s);
1573 macro_tokens_uninit (&mts);
1577 *number = token_number (&mts.mts[0].token);
1579 macro_tokens_uninit (&mts);
1583 static const struct macro_token *
1584 find_ifend_clause (const struct macro_token *p, const struct macro_token *end)
1587 for (; p < end; p++)
1589 if (p->token.type != T_MACRO_ID)
1592 if (ss_equals_case (p->token.string, ss_cstr ("!IF")))
1594 else if (lex_id_match_n (p->token.string, ss_cstr ("!IFEND"), 4))
1600 else if (lex_id_match_n (p->token.string, ss_cstr ("!ELSE"), 4)
1608 macro_expand_if (const struct macro_token *tokens, size_t n_tokens,
1609 const struct macro_expander *me,
1610 struct macro_tokens *exp)
1612 const struct macro_token *p = tokens;
1613 const struct macro_token *end = tokens + n_tokens;
1615 if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!IF")))
1619 char *result = macro_evaluate_expression (&p, end - p, me);
1622 bool b = strcmp (result, "0");
1626 || p->token.type != T_MACRO_ID
1627 || !lex_id_match_n (p->token.string, ss_cstr ("!THEN"), 4))
1629 macro_error (me->stack, p < end ? p : NULL,
1630 _("!THEN expected in macro !IF construct."));
1634 const struct macro_token *start_then = p + 1;
1635 const struct macro_token *end_then = find_ifend_clause (start_then, end);
1638 macro_error (me->stack, NULL,
1639 _("!ELSE or !IFEND expected in macro !IF construct."));
1643 const struct macro_token *start_else, *end_if;
1644 if (lex_id_match_n (end_then->token.string, ss_cstr ("!ELSE"), 4))
1646 start_else = end_then + 1;
1647 end_if = find_ifend_clause (start_else, end);
1649 || !lex_id_match_n (end_if->token.string, ss_cstr ("!IFEND"), 4))
1651 macro_error (me->stack, end_if ? end_if : NULL,
1652 _("!IFEND expected in macro !IF construct."));
1662 const struct macro_token *start;
1667 n = end_then - start_then;
1669 else if (start_else)
1672 n = end_if - start_else;
1682 struct macro_expansion_stack stack = {
1686 struct macro_expander subme = *me;
1687 subme.stack = &stack;
1688 macro_expand (start, n, &subme, exp);
1690 return (end_if + 1) - tokens;
1694 macro_parse_let (const struct macro_token *tokens, size_t n_tokens,
1695 const struct macro_expander *me)
1697 const struct macro_token *p = tokens;
1698 const struct macro_token *end = tokens + n_tokens;
1700 if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!LET")))
1704 if (p >= end || p->token.type != T_MACRO_ID)
1706 macro_error (me->stack, p < end ? p : NULL,
1707 _("Expected macro variable name following !LET."));
1710 const struct substring var_name = p->token.string;
1711 if (is_macro_keyword (var_name)
1712 || macro_find_parameter_by_name (me->macro, var_name))
1714 macro_error (me->stack, p < end ? p : NULL,
1715 _("Cannot use argument name or macro keyword "
1716 "\"%.*s\" as !LET variable."),
1717 (int) var_name.length, var_name.string);
1722 if (p >= end || p->token.type != T_EQUALS)
1724 macro_error (me->stack, p < end ? p : NULL,
1725 _("Expected `=' following !LET."));
1730 char *value = macro_evaluate_expression (&p, end - p, me);
1734 stringi_map_replace_nocopy (me->vars, ss_xstrdup (var_name), value);
1738 static const struct macro_token *
1739 find_doend (const struct macro_expansion_stack *stack,
1740 const struct macro_token *p, const struct macro_token *end)
1743 for (; p < end; p++)
1745 if (p->token.type != T_MACRO_ID)
1748 if (ss_equals_case (p->token.string, ss_cstr ("!DO")))
1750 else if (lex_id_match_n (p->token.string, ss_cstr ("!DOEND"), 4))
1757 macro_error (stack, NULL, _("Missing !DOEND."));
1762 macro_expand_do (const struct macro_token *tokens, size_t n_tokens,
1763 const struct macro_expander *me,
1764 struct macro_tokens *exp)
1766 const struct macro_token *p = tokens;
1767 const struct macro_token *end = tokens + n_tokens;
1769 if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!DO")))
1773 if (p >= end || p->token.type != T_MACRO_ID)
1775 macro_error (me->stack, p < end ? p : NULL,
1776 _("Expected macro variable name following !DO."));
1779 const struct substring var_name = p->token.string;
1780 if (is_macro_keyword (var_name)
1781 || macro_find_parameter_by_name (me->macro, var_name))
1783 macro_error (me->stack, p, _("Cannot use argument name or macro "
1784 "keyword as !DO variable."));
1789 struct macro_expansion_stack substack = {
1793 bool break_ = false;
1794 struct macro_expander subme = *me;
1795 subme.break_ = &break_;
1796 subme.stack = &substack;
1798 int miterate = settings_get_miterate ();
1799 if (p < end && p->token.type == T_MACRO_ID
1800 && ss_equals_case (p->token.string, ss_cstr ("!IN")))
1803 char *list = macro_evaluate_expression (&p, end - p, &subme);
1807 struct macro_tokens items = { .n = 0 };
1808 macro_tokens_from_string (&items, ss_cstr (list), me->segmenter_mode,
1812 const struct macro_token *do_end = find_doend (subme.stack, p, end);
1815 macro_tokens_uninit (&items);
1819 for (size_t i = 0; i < items.n && !break_; i++)
1823 macro_error (&substack, NULL,
1824 _("!DO loop over list exceeded "
1825 "maximum number of iterations %d. "
1826 "(Use SET MITERATE to change the limit.)"),
1830 stringi_map_replace_nocopy (me->vars, ss_xstrdup (var_name),
1831 ss_xstrdup (items.mts[i].syntax));
1833 macro_expand (p, do_end - p, &subme, exp);
1835 macro_tokens_uninit (&items);
1836 return do_end - tokens + 1;
1838 else if (p < end && p->token.type == T_EQUALS)
1842 if (!macro_evaluate_number (&p, end - p, &subme, &first))
1845 if (p >= end || p->token.type != T_MACRO_ID
1846 || !ss_equals_case (p->token.string, ss_cstr ("!TO")))
1848 macro_error (subme.stack, p < end ? p : NULL,
1849 _("Expected !TO in numerical !DO loop."));
1855 if (!macro_evaluate_number (&p, end - p, &subme, &last))
1859 if (p < end && p->token.type == T_MACRO_ID
1860 && ss_equals_case (p->token.string, ss_cstr ("!BY")))
1863 if (!macro_evaluate_number (&p, end - p, &subme, &by))
1868 macro_error (subme.stack, NULL, _("!BY value cannot be zero."));
1873 const struct macro_token *do_end = find_doend (subme.stack, p, end);
1876 if ((by > 0 && first <= last) || (by < 0 && first >= last))
1879 for (double index = first;
1880 by > 0 ? (index <= last) : (index >= last) && !break_;
1885 macro_error (subme.stack, NULL,
1886 _("Numerical !DO loop exceeded "
1887 "maximum number of iterations %d. "
1888 "(Use SET MITERATE to change the limit.)"),
1893 char index_s[DBL_BUFSIZE_BOUND];
1894 c_dtoastr (index_s, sizeof index_s, 0, 0, index);
1895 stringi_map_replace_nocopy (me->vars, ss_xstrdup (var_name),
1898 macro_expand (p, do_end - p, &subme, exp);
1902 return do_end - tokens + 1;
1906 macro_error (me->stack, p < end ? p : NULL,
1907 _("Expected `=' or !IN in !DO loop."));
1913 macro_expand_arg__ (const struct macro_expander *me, size_t idx,
1914 struct macro_tokens *exp)
1916 const struct macro_param *param = &me->macro->params[idx];
1917 const struct macro_tokens *arg = me->args[idx];
1919 if (*me->expand && param->expand_arg)
1921 struct stringi_map vars = STRINGI_MAP_INITIALIZER (vars);
1922 struct macro_expansion_stack stack = {
1923 .name = param->name,
1926 struct macro_expander subme = {
1927 .macros = me->macros,
1930 .segmenter_mode = me->segmenter_mode,
1931 .expand = me->expand,
1934 .nesting_countdown = me->nesting_countdown,
1937 macro_expand (arg->mts, arg->n, &subme, exp);
1938 stringi_map_destroy (&vars);
1941 for (size_t i = 0; i < arg->n; i++)
1942 macro_tokens_add (exp, &arg->mts[i]);
1946 macro_expand_arg (const struct token *token, const struct macro_expander *me,
1947 struct macro_tokens *exp)
1949 if (!me || token->type != T_MACRO_ID)
1952 /* Macro arguments. */
1955 const struct macro_param *param = macro_find_parameter_by_name (
1956 me->macro, token->string);
1959 macro_expand_arg__ (me, param - me->macro->params, exp);
1962 else if (ss_equals (token->string, ss_cstr ("!*")))
1964 for (size_t j = 0; j < me->macro->n_params; j++)
1965 macro_expand_arg__ (me, j, exp);
1970 /* Variables set by !DO or !LET. */
1971 const char *var = stringi_map_find__ (me->vars, token->string.string,
1972 token->string.length);
1975 macro_tokens_from_string (exp, ss_cstr (var),
1976 me->segmenter_mode, me->stack);
1984 macro_expand__ (const struct macro_token *mts, size_t n,
1985 const struct macro_expander *me,
1986 struct macro_tokens *exp)
1988 const struct token *token = &mts[0].token;
1990 /* Recursive macro calls. */
1993 struct macro_call *submc;
1994 int n_call = macro_call_create__ (me->macros, me->stack, me,
1996 for (size_t j = 1; !n_call; j++)
1998 const struct macro_token endcmd
1999 = { .token = { .type = T_ENDCMD } };
2000 n_call = macro_call_add (submc, j < n ? &mts[j] : &endcmd, NULL);
2004 struct stringi_map vars = STRINGI_MAP_INITIALIZER (vars);
2005 struct macro_expansion_stack stack = {
2006 .name = submc->macro->name,
2007 .location = submc->macro->location,
2010 struct macro_expander subme = {
2011 .macros = submc->macros,
2012 .macro = submc->macro,
2013 .args = submc->args,
2014 .segmenter_mode = me->segmenter_mode,
2015 .expand = me->expand,
2018 .nesting_countdown = me->nesting_countdown - 1,
2021 const struct macro_tokens *body = &submc->macro->body;
2022 macro_expand (body->mts, body->n, &subme, exp);
2023 macro_call_destroy (submc);
2024 stringi_map_destroy (&vars);
2028 macro_call_destroy (submc);
2031 if (token->type != T_MACRO_ID)
2033 macro_tokens_add (exp, &mts[0]);
2037 /* Parameters and macro variables. */
2038 if (macro_expand_arg (token, me, exp))
2041 /* Macro functions. */
2042 struct string function_output = DS_EMPTY_INITIALIZER;
2043 size_t n_function = expand_macro_function (me, mts, n, &function_output);
2046 macro_tokens_from_string (exp, function_output.ss,
2047 me->segmenter_mode, me->stack);
2048 ds_destroy (&function_output);
2053 size_t n_if = macro_expand_if (mts, n, me, exp);
2057 size_t n_let = macro_parse_let (mts, n, me);
2061 size_t n_do = macro_expand_do (mts, n, me, exp);
2065 if (lex_id_match_n (token->string, ss_cstr ("!break"), 4))
2070 macro_error (me->stack, &mts[0], _("!BREAK outside !DO."));
2072 else if (lex_id_match_n (token->string, ss_cstr ("!onexpand"), 4))
2074 else if (lex_id_match_n (token->string, ss_cstr ("!offexpand"), 4))
2075 *me->expand = false;
2077 macro_tokens_add (exp, &mts[0]);
2082 macro_expand (const struct macro_token *mts, size_t n,
2083 const struct macro_expander *me,
2084 struct macro_tokens *exp)
2086 if (me->nesting_countdown <= 0)
2088 macro_error (me->stack, NULL, _("Maximum nesting level %d exceeded. "
2089 "(Use SET MNEST to change the limit.)"),
2090 settings_get_mnest ());
2091 for (size_t i = 0; i < n; i++)
2092 macro_tokens_add (exp, &mts[i]);
2096 for (size_t i = 0; i < n; )
2098 if (me->break_ && *me->break_)
2101 size_t consumed = macro_expand__ (&mts[i], n - i, me, exp);
2102 assert (consumed > 0 && i + consumed <= n);
2108 macro_call_expand (struct macro_call *mc, enum segmenter_mode segmenter_mode,
2109 const struct msg_location *call_loc,
2110 struct macro_tokens *exp)
2112 assert (mc->state == MC_FINISHED);
2115 struct stringi_map vars = STRINGI_MAP_INITIALIZER (vars);
2116 struct macro_expansion_stack stack0 = {
2117 .location = call_loc,
2119 struct macro_expansion_stack stack1 = {
2121 .name = mc->macro->name,
2122 .location = mc->macro->location,
2124 struct macro_expander me = {
2125 .macros = mc->macros,
2128 .segmenter_mode = segmenter_mode,
2132 .nesting_countdown = settings_get_mnest (),
2136 const struct macro_tokens *body = &mc->macro->body;
2137 macro_expand (body->mts, body->n, &me, exp);
2139 stringi_map_destroy (&vars);