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/string-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. */
47 struct macro_expansion_stack
49 /* Points to an outer stack entry, or NULL if this is the outermost. */
50 const struct macro_expansion_stack *next;
52 /* A macro name or !IF, !DO, etc. */
55 /* Location of the macro definition, if available. */
56 const char *file_name;
61 /* Reports an error during macro expansion. STACK is the stack for reporting
62 the location of the error, MT is the optional token at which the error was
63 detected, and FORMAT along with the varargs is the message to report. */
64 static void PRINTF_FORMAT (3, 4)
65 macro_error (const struct macro_expansion_stack *stack,
66 const struct macro_token *mt,
67 const char *format, ...)
69 struct msg_stack **ms = NULL;
70 size_t allocated_ms = 0;
73 for (const struct macro_expansion_stack *p = stack; p; p = p->next)
75 if (n_ms >= allocated_ms)
76 ms = x2nrealloc (ms, &allocated_ms, sizeof *ms);
78 /* TRANSLATORS: These strings are used for explaining the context of an
79 error. The "While expanding" message appears first, followed by zero
80 or more of the "inside expansion" messages. `innermost',
81 `next_inner`, etc., are names of macros, and `foobar' is a piece of
84 foo.sps:12: At `foobar' in the expansion of 'innermost',
85 foo.sps:23: inside the expansion of 'next_inner',
86 foo.sps:34: inside the expansion of 'next_inner2',
87 foo.sps:45: inside the expansion of 'outermost',
88 foo.sps:76: This is the actual error message. */
92 if (mt && mt->representation.length)
95 str_ellipsize (mt->representation, syntax, sizeof syntax);
96 description = xasprintf (_("At `%s' in the expansion of `%s',"),
100 description = xasprintf (_("In the expansion of `%s',"), p->name);
103 description = xasprintf (_("inside the expansion of `%s',"), p->name);
105 ms[n_ms] = xmalloc (sizeof *ms[n_ms]);
106 *ms[n_ms] = (struct msg_stack) {
108 .file_name = xstrdup_if_nonnull (p->file_name),
109 .first_line = p->first_line,
110 .last_line = p->last_line,
112 .description = description,
118 va_start (args, format);
119 char *s = xvasprintf (format, args);
122 struct msg *m = xmalloc (sizeof *m);
124 .category = MSG_C_SYNTAX,
125 .severity = MSG_S_ERROR,
134 macro_token_copy (struct macro_token *dst, const struct macro_token *src)
136 token_copy (&dst->token, &src->token);
137 ss_alloc_substring (&dst->representation, src->representation);
141 macro_token_uninit (struct macro_token *mt)
143 token_uninit (&mt->token);
144 ss_dealloc (&mt->representation);
148 macro_token_to_representation (struct macro_token *mt, struct string *s)
150 ds_put_substring (s, mt->representation);
153 is_macro_keyword (struct substring s)
155 static struct stringi_set keywords = STRINGI_SET_INITIALIZER (keywords);
156 if (stringi_set_is_empty (&keywords))
158 static const char *kws[] = {
179 for (size_t i = 0; i < sizeof kws / sizeof *kws; i++)
180 stringi_set_insert (&keywords, kws[i]);
183 ss_ltrim (&s, ss_cstr ("!"));
184 return stringi_set_contains_len (&keywords, s.string, s.length);
188 macro_tokens_copy (struct macro_tokens *dst, const struct macro_tokens *src)
190 *dst = (struct macro_tokens) {
191 .mts = xmalloc (src->n * sizeof *dst->mts),
195 for (size_t i = 0; i < src->n; i++)
196 macro_token_copy (&dst->mts[i], &src->mts[i]);
200 macro_tokens_uninit (struct macro_tokens *mts)
202 for (size_t i = 0; i < mts->n; i++)
203 macro_token_uninit (&mts->mts[i]);
208 macro_tokens_add_uninit (struct macro_tokens *mts)
210 if (mts->n >= mts->allocated)
211 mts->mts = x2nrealloc (mts->mts, &mts->allocated, sizeof *mts->mts);
212 return &mts->mts[mts->n++];
216 macro_tokens_add (struct macro_tokens *mts, const struct macro_token *mt)
218 macro_token_copy (macro_tokens_add_uninit (mts), mt);
221 /* Tokenizes SRC according to MODE and appends the tokens to MTS. Uses STACK,
222 if nonull, for error reporting. */
224 macro_tokens_from_string__ (struct macro_tokens *mts, const struct substring src,
225 enum segmenter_mode mode,
226 const struct macro_expansion_stack *stack)
230 struct segmenter segmenter;
231 struct substring body;
234 struct state state = {
235 .segmenter = segmenter_init (mode, true),
238 struct state saved = state;
240 while (state.body.length > 0)
242 struct macro_token mt = {
243 .token = { .type = T_STOP },
244 .representation = { .string = state.body.string },
246 struct token *token = &mt.token;
248 struct scanner scanner;
249 scanner_init (&scanner, token);
253 enum segment_type type;
254 int seg_len = segmenter_push (&state.segmenter, state.body.string,
255 state.body.length, true, &type);
256 assert (seg_len >= 0);
258 struct substring segment = ss_head (state.body, seg_len);
259 ss_advance (&state.body, seg_len);
261 enum scan_result result = scanner_push (&scanner, type, segment, token);
262 if (result == SCAN_SAVE)
264 else if (result == SCAN_BACK)
269 else if (result == SCAN_DONE)
273 /* We have a token in 'token'. */
274 mt.representation.length = state.body.string - mt.representation.string;
275 if (is_scan_type (token->type))
277 if (token->type != SCAN_SKIP)
279 char *s = scan_token_to_error (token);
282 mt.token.type = T_STRING;
283 macro_error (stack, &mt, "%s", s);
291 macro_tokens_add (mts, &mt);
292 token_uninit (token);
296 /* Tokenizes SRC according to MODE and appends the tokens to MTS. */
298 macro_tokens_from_string (struct macro_tokens *mts, const struct substring src,
299 enum segmenter_mode mode)
301 macro_tokens_from_string__ (mts, src, mode, NULL);
305 macro_tokens_print (const struct macro_tokens *mts, FILE *stream)
307 for (size_t i = 0; i < mts->n; i++)
308 token_print (&mts->mts[i].token, stream);
313 TC_ENDCMD, /* No space before or after (new-line after). */
314 TC_BINOP, /* Space on both sides. */
315 TC_COMMA, /* Space afterward. */
316 TC_ID, /* Don't need spaces except sequentially. */
317 TC_PUNCT, /* Don't need spaces except sequentially. */
321 needs_space (enum token_class prev, enum token_class next)
323 /* Don't need a space before or after the end of a command.
324 (A new-line is needed afterward as a special case.) */
325 if (prev == TC_ENDCMD || next == TC_ENDCMD)
328 /* Binary operators always have a space on both sides. */
329 if (prev == TC_BINOP || next == TC_BINOP)
332 /* A comma always has a space afterward. */
333 if (prev == TC_COMMA)
336 /* Otherwise, PREV is TC_ID or TC_PUNCT, which only need a space if there are
337 two or them in a row. */
341 static enum token_class
342 classify_token (enum token_type type)
394 /* Appends a syntax representation of the tokens in MTS to S. If OFS and LEN
395 are nonnull, sets OFS[i] to the offset within S of the start of token 'i' in
396 MTS and LEN[i] to its length. OFS[i] + LEN[i] is not necessarily OFS[i + 1]
397 because some tokens are separated by white space. */
399 macro_tokens_to_representation (struct macro_tokens *mts, struct string *s,
400 size_t *ofs, size_t *len)
402 assert ((ofs != NULL) == (len != NULL));
407 for (size_t i = 0; i < mts->n; i++)
411 enum token_type prev = mts->mts[i - 1].token.type;
412 enum token_type next = mts->mts[i].token.type;
414 if (prev == T_ENDCMD)
415 ds_put_byte (s, '\n');
418 enum token_class pc = classify_token (prev);
419 enum token_class nc = classify_token (next);
420 if (needs_space (pc, nc))
421 ds_put_byte (s, ' ');
426 ofs[i] = s->ss.length;
427 macro_token_to_representation (&mts->mts[i], s);
429 len[i] = s->ss.length - ofs[i];
434 macro_destroy (struct macro *m)
441 for (size_t i = 0; i < m->n_params; i++)
443 struct macro_param *p = &m->params[i];
446 macro_tokens_uninit (&p->def);
454 token_uninit (&p->charend);
458 token_uninit (&p->enclose[0]);
459 token_uninit (&p->enclose[1]);
467 macro_tokens_uninit (&m->body);
472 macro_set_create (void)
474 struct macro_set *set = xmalloc (sizeof *set);
475 *set = (struct macro_set) {
476 .macros = HMAP_INITIALIZER (set->macros),
482 macro_set_destroy (struct macro_set *set)
487 struct macro *macro, *next;
488 HMAP_FOR_EACH_SAFE (macro, next, struct macro, hmap_node, &set->macros)
490 hmap_delete (&set->macros, ¯o->hmap_node);
491 macro_destroy (macro);
493 hmap_destroy (&set->macros);
498 hash_macro_name (const char *name)
500 return utf8_hash_case_string (name, 0);
503 static struct macro *
504 macro_set_find__ (struct macro_set *set, const char *name)
506 if (macro_set_is_empty (set))
510 HMAP_FOR_EACH_WITH_HASH (macro, struct macro, hmap_node,
511 hash_macro_name (name), &set->macros)
512 if (!utf8_strcasecmp (macro->name, name))
519 macro_set_find (const struct macro_set *set, const char *name)
521 return macro_set_find__ (CONST_CAST (struct macro_set *, set), name);
524 /* Adds M to SET. M replaces any existing macro with the same name. Takes
527 macro_set_add (struct macro_set *set, struct macro *m)
529 struct macro *victim = macro_set_find__ (set, m->name);
532 hmap_delete (&set->macros, &victim->hmap_node);
533 macro_destroy (victim);
536 hmap_insert (&set->macros, &m->hmap_node, hash_macro_name (m->name));
539 /* Macro expander. */
546 /* Accumulating tokens in me->params toward the end of any type of
550 /* Expecting the opening delimiter of an ARG_ENCLOSE argument. */
553 /* Expecting a keyword for a keyword argument. */
556 /* Expecting an equal sign for a keyword argument. */
559 /* Macro fully parsed and ready for expansion. */
565 Macro expansion has two phases. The first phase uses an FSM driven by
566 macro_expander_create() and macro_expander_add() to identify the macro being
567 called and obtain its arguments. 'state' identifies the FSM state.
569 The second phase is macro expansion via macro_expander_get_expansion(). */
570 struct macro_expander
572 const struct macro_set *macros;
573 const struct macro *macro;
578 struct macro_tokens **args;
579 const struct macro_param *param; /* Parameter currently being parsed. */
582 /* Completes macro expansion by initializing arguments that weren't supplied to
585 me_finished (struct macro_expander *me)
587 me->state = ME_FINISHED;
588 for (size_t i = 0; i < me->macro->n_params; i++)
590 me->args[i] = &me->macro->params[i].def;
595 me_next_arg (struct macro_expander *me)
599 assert (!me->macro->n_params);
600 return me_finished (me);
602 else if (me->param->positional)
605 if (me->param >= &me->macro->params[me->macro->n_params])
606 return me_finished (me);
609 me->state = (!me->param->positional ? ME_KEYWORD
610 : me->param->arg_type == ARG_ENCLOSE ? ME_ENCLOSE
617 for (size_t i = 0; i < me->macro->n_params; i++)
620 me->state = ME_KEYWORD;
623 return me_finished (me);
628 me_error (struct macro_expander *me)
630 me->state = ME_ERROR;
635 me_add_arg (struct macro_expander *me, const struct macro_token *mt)
637 const struct macro_param *p = me->param;
639 const struct token *token = &mt->token;
640 if ((token->type == T_ENDCMD || token->type == T_STOP)
641 && p->arg_type != ARG_CMDEND)
643 msg (SE, _("Unexpected end of command reading argument %s "
644 "to macro %s."), me->param->name, me->macro->name);
646 return me_error (me);
651 struct macro_tokens **argp = &me->args[p - me->macro->params];
653 *argp = xzalloc (sizeof **argp);
654 struct macro_tokens *arg = *argp;
655 if (p->arg_type == ARG_N_TOKENS)
657 macro_tokens_add (arg, mt);
658 if (arg->n >= p->n_tokens)
659 return me_next_arg (me);
662 else if (p->arg_type == ARG_CMDEND)
664 if (token->type == T_ENDCMD || token->type == T_STOP)
665 return me_next_arg (me);
666 macro_tokens_add (arg, mt);
671 const struct token *end
672 = p->arg_type == ARG_CHAREND ? &p->charend : &p->enclose[1];
673 if (token_equal (token, end))
674 return me_next_arg (me);
675 macro_tokens_add (arg, mt);
681 me_expected (struct macro_expander *me, const struct macro_token *actual,
682 const struct token *expected)
684 const struct substring actual_s
685 = (actual->representation.length ? actual->representation
686 : ss_cstr (_("<end of input>")));
687 char *expected_s = token_to_string (expected);
688 msg (SE, _("Found `%.*s' while expecting `%s' reading argument %s "
690 (int) actual_s.length, actual_s.string, expected_s,
691 me->param->name, me->macro->name);
694 return me_error (me);
698 me_enclose (struct macro_expander *me, const struct macro_token *mt)
700 const struct token *token = &mt->token;
703 if (token_equal (&me->param->enclose[0], token))
709 return me_expected (me, mt, &me->param->enclose[0]);
712 static const struct macro_param *
713 macro_find_parameter_by_name (const struct macro *m, struct substring name)
715 ss_ltrim (&name, ss_cstr ("!"));
717 for (size_t i = 0; i < m->n_params; i++)
719 const struct macro_param *p = &m->params[i];
720 struct substring p_name = ss_cstr (p->name + 1);
721 if (!utf8_strncasecmp (p_name.string, p_name.length,
722 name.string, name.length))
729 me_keyword (struct macro_expander *me, const struct macro_token *mt)
731 const struct token *token = &mt->token;
732 if (token->type != T_ID)
733 return me_finished (me);
735 const struct macro_param *p = macro_find_parameter_by_name (me->macro,
739 size_t arg_index = p - me->macro->params;
741 if (me->args[arg_index])
744 _("Argument %s multiply specified in call to macro %s."),
745 p->name, me->macro->name);
746 return me_error (me);
750 me->state = ME_EQUALS;
754 return me_finished (me);
758 me_equals (struct macro_expander *me, const struct macro_token *mt)
760 const struct token *token = &mt->token;
763 if (token->type == T_EQUALS)
769 return me_expected (me, mt, &(struct token) { .type = T_EQUALS });
772 /* If TOKEN is the first token of a call to a macro in MACROS, create a new
773 macro expander, initializes *MEP to it. Returns 0 if more tokens are needed
774 and should be added via macro_expander_add() or 1 if the caller should next
775 call macro_expander_get_expansion().
777 If TOKEN is not the first token of a macro call, returns -1 and sets *MEP to
780 macro_expander_create (const struct macro_set *macros,
781 const struct token *token,
782 struct macro_expander **mep)
784 const struct macro *macro = (token->type == T_ID || token->type == T_MACRO_ID
785 ? macro_set_find (macros, token->string.string)
793 struct macro_expander *me = xmalloc (sizeof *me);
794 *me = (struct macro_expander) {
798 .state = (!macro->n_params ? ME_FINISHED
799 : !macro->params[0].positional ? ME_KEYWORD
800 : macro->params[0].arg_type == ARG_ENCLOSE ? ME_ENCLOSE
802 .args = macro->n_params ? xcalloc (macro->n_params, sizeof *me->args) : NULL,
803 .param = macro->params,
807 return me->state == ME_FINISHED ? 1 : 0;
811 macro_expander_destroy (struct macro_expander *me)
816 for (size_t i = 0; i < me->macro->n_params; i++)
818 struct macro_tokens *a = me->args[i];
819 if (a && a != &me->macro->params[i].def)
821 macro_tokens_uninit (a);
829 /* Adds TOKEN to the collection of tokens in ME that potentially need to be
832 Returns -1 if the tokens added do not actually invoke a macro. The caller
833 should consume the first token without expanding it. (Later tokens might
834 invoke a macro so it's best to feed the second token into a new expander.)
836 Returns 0 if the macro expander needs more tokens, for macro arguments or to
837 decide whether this is actually a macro invocation. The caller should call
838 macro_expander_add() again with the next token.
840 Returns a positive number to indicate that the returned number of tokens
841 invoke a macro. The number returned might be less than the number of tokens
842 added because it can take a few tokens of lookahead to determine whether the
843 macro invocation is finished. The caller should call
844 macro_expander_get_expansion() to obtain the expansion. */
846 macro_expander_add (struct macro_expander *me, const struct macro_token *mt)
854 return me_add_arg (me, mt);
857 return me_enclose (me, mt);
860 return me_keyword (me, mt);
863 return me_equals (me, mt);
870 /* Each argument to a macro function is one of:
872 - A quoted string or other single literal token.
874 - An argument to the macro being expanded, e.g. !1 or a named argument.
878 - A function invocation.
880 Each function invocation yields a character sequence to be turned into a
881 sequence of tokens. The case where that character sequence is a single
882 quoted string is an important special case.
884 struct parse_macro_function_ctx
886 const struct macro_token *input;
888 int nesting_countdown;
889 enum segmenter_mode segmenter_mode;
890 const struct macro_set *macros;
891 const struct macro_expander *me;
892 const struct macro_expansion_stack *stack;
893 struct string_map *vars;
898 macro_expand (const struct macro_tokens *, int nesting_countdown,
899 enum segmenter_mode segmenter_mode, const struct macro_set *,
900 const struct macro_expander *, struct string_map *vars,
901 const struct macro_expansion_stack *stack,
902 bool *expand, bool *break_,
903 struct macro_tokens *exp);
906 expand_macro_function (struct parse_macro_function_ctx *ctx,
907 struct string *output, size_t *input_consumed);
909 /* Returns true if the pair of tokens starting at offset OFS within MTS are !*,
912 is_bang_star (const struct macro_token *mts, size_t n, size_t ofs)
915 && mts[ofs].token.type == T_MACRO_ID
916 && ss_equals (mts[ofs].token.string, ss_cstr ("!"))
917 && mts[ofs + 1].token.type == T_ASTERISK);
921 parse_function_arg (struct parse_macro_function_ctx *ctx,
922 size_t i, struct string *farg)
924 const struct macro_token *tokens = ctx->input;
925 const struct token *token = &tokens[i].token;
926 if (token->type == T_MACRO_ID)
928 const struct macro_param *param = macro_find_parameter_by_name (
929 ctx->me->macro, token->string);
932 size_t param_idx = param - ctx->me->macro->params;
933 const struct macro_tokens *marg = ctx->me->args[param_idx];
934 for (size_t i = 0; i < marg->n; i++)
937 ds_put_byte (farg, ' ');
938 ds_put_substring (farg, marg->mts[i].representation);
943 if (is_bang_star (ctx->input, ctx->n_input, i))
945 for (size_t i = 0; i < ctx->me->macro->n_params; i++)
947 if (!ctx->me->macro->params[i].positional)
950 const struct macro_tokens *marg = ctx->me->args[i];
951 for (size_t j = 0; j < marg->n; j++)
954 ds_put_byte (farg, ' ');
955 ds_put_substring (farg, marg->mts[j].representation);
963 const char *value = string_map_find__ (ctx->vars,
964 token->string.string,
965 token->string.length);
968 ds_put_cstr (farg, value);
973 struct parse_macro_function_ctx subctx = {
974 .input = &ctx->input[i],
975 .n_input = ctx->n_input - i,
976 .nesting_countdown = ctx->nesting_countdown,
977 .segmenter_mode = ctx->segmenter_mode,
978 .macros = ctx->macros,
982 .expand = ctx->expand,
984 size_t subinput_consumed;
985 if (expand_macro_function (&subctx, farg, &subinput_consumed))
986 return subinput_consumed;
989 ds_put_substring (farg, tokens[i].representation);
994 parse_macro_function (struct parse_macro_function_ctx *ctx,
995 struct string_array *args,
996 struct substring function,
997 int min_args, int max_args,
998 size_t *input_consumed)
1000 const struct macro_token *tokens = ctx->input;
1001 size_t n_tokens = ctx->n_input;
1004 || tokens[0].token.type != T_MACRO_ID
1005 || !ss_equals_case (tokens[0].token.string, function)) /* XXX abbrevs allowed */
1008 if (n_tokens < 2 || tokens[1].token.type != T_LPAREN)
1010 macro_error (ctx->stack, n_tokens > 1 ? &tokens[1] : NULL,
1011 _("`(' expected following %s."), function.string);
1015 string_array_init (args);
1017 for (size_t i = 2;; )
1020 goto unexpected_end;
1021 if (tokens[i].token.type == T_RPAREN)
1023 *input_consumed = i + 1;
1024 if (args->n < min_args || args->n > max_args)
1026 macro_error (ctx->stack, &tokens[i],
1027 _("Wrong number of arguments to macro function %s."),
1034 struct string s = DS_EMPTY_INITIALIZER;
1035 i += parse_function_arg (ctx, i, &s);
1039 goto unexpected_end;
1041 string_array_append_nocopy (args, ds_steal_cstr (&s));
1043 if (tokens[i].token.type == T_COMMA)
1045 else if (tokens[i].token.type != T_RPAREN)
1047 macro_error (ctx->stack, &tokens[i],
1048 _("`,' or `)' expected in call to macro function %s."),
1055 macro_error (ctx->stack, NULL, _("Missing `)' in call to macro function %s."),
1059 string_array_destroy (args);
1064 unquote_string (const char *s, enum segmenter_mode segmenter_mode,
1065 struct string *content)
1067 struct string_lexer slex;
1068 string_lexer_init (&slex, s, strlen (s), segmenter_mode, true);
1070 struct token token1;
1071 if (!string_lexer_next (&slex, &token1))
1074 if (token1.type != T_STRING)
1076 token_uninit (&token1);
1080 struct token token2;
1081 if (string_lexer_next (&slex, &token2))
1083 token_uninit (&token1);
1084 token_uninit (&token2);
1088 ds_put_substring (content, token1.string);
1089 token_uninit (&token1);
1094 unquote_string_in_place (const char *s, enum segmenter_mode segmenter_mode,
1097 ds_init_empty (tmp);
1098 return unquote_string (s, segmenter_mode, tmp) ? ds_cstr (tmp) : s;
1102 parse_integer (const char *s, int *np)
1107 long int n = strtol (s, &tail, 10);
1108 *np = n < INT_MIN ? INT_MIN : n > INT_MAX ? INT_MAX : n;
1109 tail += strspn (tail, CC_SPACES);
1110 return *tail == '\0' && errno != ERANGE && n == *np;
1114 expand_macro_function (struct parse_macro_function_ctx *ctx,
1115 struct string *output,
1116 size_t *input_consumed)
1118 struct string_array args;
1120 if (parse_macro_function (ctx, &args, ss_cstr ("!LENGTH"), 1, 1,
1122 ds_put_format (output, "%zu", strlen (args.strings[0]));
1123 else if (parse_macro_function (ctx, &args, ss_cstr ("!BLANKS"), 1, 1,
1127 if (!parse_integer (args.strings[0], &n))
1129 macro_error (ctx->stack, NULL,
1130 _("Argument to !BLANKS must be non-negative integer "
1131 "(not \"%s\")."), args.strings[0]);
1132 string_array_destroy (&args);
1136 ds_put_byte_multiple (output, ' ', n);
1138 else if (parse_macro_function (ctx, &args, ss_cstr ("!CONCAT"), 1, INT_MAX,
1141 for (size_t i = 0; i < args.n; i++)
1142 if (!unquote_string (args.strings[i], ctx->segmenter_mode, output))
1143 ds_put_cstr (output, args.strings[i]);
1145 else if (parse_macro_function (ctx, &args, ss_cstr ("!HEAD"), 1, 1,
1149 const char *s = unquote_string_in_place (args.strings[0],
1150 ctx->segmenter_mode, &tmp);
1152 struct macro_tokens mts = { .n = 0 };
1153 macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->segmenter_mode,
1156 ds_put_substring (output, mts.mts[0].representation);
1157 macro_tokens_uninit (&mts);
1160 else if (parse_macro_function (ctx, &args, ss_cstr ("!INDEX"), 2, 2,
1163 const char *haystack = args.strings[0];
1164 const char *needle = strstr (haystack, args.strings[1]);
1165 ds_put_format (output, "%zu", needle ? needle - haystack + 1 : 0);
1167 else if (parse_macro_function (ctx, &args, ss_cstr ("!QUOTE"), 1, 1,
1170 if (unquote_string (args.strings[0], ctx->segmenter_mode, NULL))
1171 ds_put_cstr (output, args.strings[0]);
1174 ds_extend (output, strlen (args.strings[0]) + 2);
1175 ds_put_byte (output, '\'');
1176 for (const char *p = args.strings[0]; *p; p++)
1179 ds_put_byte (output, '\'');
1180 ds_put_byte (output, *p);
1182 ds_put_byte (output, '\'');
1185 else if (parse_macro_function (ctx, &args, ss_cstr ("!SUBSTR"), 2, 3,
1189 if (!parse_integer (args.strings[1], &start) || start < 1)
1191 macro_error (ctx->stack, NULL,
1192 _("Second argument of !SUBSTR must be "
1193 "positive integer (not \"%s\")."),
1195 string_array_destroy (&args);
1199 int count = INT_MAX;
1200 if (args.n > 2 && (!parse_integer (args.strings[2], &count) || count < 0))
1202 macro_error (ctx->stack, NULL,
1203 _("Third argument of !SUBSTR must be "
1204 "non-negative integer (not \"%s\")."),
1206 string_array_destroy (&args);
1210 struct substring s = ss_cstr (args.strings[0]);
1211 ds_put_substring (output, ss_substr (s, start - 1, count));
1213 else if (parse_macro_function (ctx, &args, ss_cstr ("!TAIL"), 1, 1,
1217 const char *s = unquote_string_in_place (args.strings[0],
1218 ctx->segmenter_mode, &tmp);
1220 struct macro_tokens mts = { .n = 0 };
1221 macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->segmenter_mode,
1225 struct macro_tokens tail = { .mts = mts.mts + 1, .n = mts.n - 1 };
1226 macro_tokens_to_representation (&tail, output, NULL, NULL);
1228 macro_tokens_uninit (&mts);
1231 else if (parse_macro_function (ctx, &args, ss_cstr ("!UNQUOTE"), 1, 1,
1234 if (!unquote_string (args.strings[0], ctx->segmenter_mode, output))
1235 ds_put_cstr (output, args.strings[0]);
1237 else if (parse_macro_function (ctx, &args, ss_cstr ("!UPCASE"), 1, 1,
1241 const char *s = unquote_string_in_place (args.strings[0],
1242 ctx->segmenter_mode, &tmp);
1243 char *upper = utf8_to_upper (s);
1244 ds_put_cstr (output, upper);
1248 else if (parse_macro_function (ctx, &args, ss_cstr ("!EVAL"), 1, 1,
1251 struct macro_tokens mts = { .n = 0 };
1252 macro_tokens_from_string__ (&mts, ss_cstr (args.strings[0]),
1253 ctx->segmenter_mode, ctx->stack);
1254 struct macro_tokens exp = { .n = 0 };
1255 macro_expand (&mts, ctx->nesting_countdown - 1, ctx->segmenter_mode,
1256 ctx->macros, ctx->me, ctx->vars,
1257 &(struct macro_expansion_stack) {
1260 }, ctx->expand, NULL, &exp);
1261 macro_tokens_to_representation (&exp, output, NULL, NULL);
1262 macro_tokens_uninit (&exp);
1263 macro_tokens_uninit (&mts);
1265 else if (ctx->n_input > 0
1266 && ctx->input[0].token.type == T_MACRO_ID
1267 && ss_equals_case (ctx->input[0].token.string, ss_cstr ("!NULL")))
1269 *input_consumed = 1;
1275 string_array_destroy (&args);
1281 int nesting_countdown;
1282 enum segmenter_mode segmenter_mode;
1283 const struct macro_set *macros;
1284 const struct macro_expander *me;
1285 const struct macro_expansion_stack *stack;
1286 struct string_map *vars;
1290 static char *macro_evaluate_or (const struct expr_context *ctx,
1291 const struct macro_token **tokens,
1292 const struct macro_token *end);
1295 macro_evaluate_literal (const struct expr_context *ctx,
1296 const struct macro_token **tokens,
1297 const struct macro_token *end)
1299 const struct macro_token *p = *tokens;
1302 if (p->token.type == T_LPAREN)
1305 char *value = macro_evaluate_or (ctx, &p, end);
1308 if (p >= end || p->token.type != T_RPAREN)
1311 macro_error (ctx->stack, p < end ? p : NULL,
1312 _("Expecting ')' in macro expression."));
1319 else if (p->token.type == T_RPAREN)
1321 macro_error (ctx->stack, p, _("Expecting literal or function invocation "
1322 "in macro expression."));
1326 struct parse_macro_function_ctx fctx = {
1329 .nesting_countdown = ctx->nesting_countdown,
1330 .segmenter_mode = ctx->segmenter_mode,
1331 .macros = ctx->macros,
1333 .stack = ctx->stack,
1335 .expand = ctx->expand,
1337 struct string function_output = DS_EMPTY_INITIALIZER;
1338 size_t function_consumed = parse_function_arg (&fctx, 0, &function_output);
1339 struct string unquoted = DS_EMPTY_INITIALIZER;
1340 if (unquote_string (ds_cstr (&function_output), ctx->segmenter_mode,
1343 ds_swap (&function_output, &unquoted);
1344 ds_destroy (&unquoted);
1346 *tokens = p + function_consumed;
1347 return ds_steal_cstr (&function_output);
1350 /* Returns true if MT is valid as a macro operator. Only operators written as
1351 symbols (e.g. <>) are usable in macro expressions, not operator written as
1352 letters (e.g. EQ). */
1354 is_macro_operator (const struct macro_token *mt)
1356 return (mt->representation.length > 0
1357 && !c_isalpha (mt->representation.string[0]));
1360 static enum token_type
1361 parse_relational_op (const struct macro_token *mt)
1363 switch (mt->token.type)
1373 return is_macro_operator (mt) ? mt->token.type : T_STOP;
1376 return (ss_equals_case (mt->token.string, ss_cstr ("!EQ")) ? T_EQ
1377 : ss_equals_case (mt->token.string, ss_cstr ("!NE")) ? T_NE
1378 : ss_equals_case (mt->token.string, ss_cstr ("!LT")) ? T_LT
1379 : ss_equals_case (mt->token.string, ss_cstr ("!GT")) ? T_GT
1380 : ss_equals_case (mt->token.string, ss_cstr ("!LE")) ? T_LE
1381 : ss_equals_case (mt->token.string, ss_cstr ("!GE")) ? T_GE
1390 macro_evaluate_relational (const struct expr_context *ctx,
1391 const struct macro_token **tokens,
1392 const struct macro_token *end)
1394 const struct macro_token *p = *tokens;
1395 char *lhs = macro_evaluate_literal (ctx, &p, end);
1399 enum token_type op = p >= end ? T_STOP : parse_relational_op (p);
1407 char *rhs = macro_evaluate_literal (ctx, &p, end);
1414 struct string lhs_tmp, rhs_tmp;
1415 int cmp = strcmp (unquote_string_in_place (lhs, ctx->segmenter_mode,
1417 unquote_string_in_place (rhs, ctx->segmenter_mode,
1419 ds_destroy (&lhs_tmp);
1420 ds_destroy (&rhs_tmp);
1425 bool b = (op == T_EQUALS || op == T_EQ ? !cmp
1427 : op == T_LT ? cmp < 0
1428 : op == T_GT ? cmp > 0
1429 : op == T_LE ? cmp <= 0
1430 : /* T_GE */ cmp >= 0);
1433 return xstrdup (b ? "1" : "0");
1437 macro_evaluate_not (const struct expr_context *ctx,
1438 const struct macro_token **tokens,
1439 const struct macro_token *end)
1441 const struct macro_token *p = *tokens;
1443 unsigned int negations = 0;
1445 && (ss_equals_case (p->representation, ss_cstr ("!NOT"))
1446 || ss_equals (p->representation, ss_cstr ("~"))))
1452 char *operand = macro_evaluate_relational (ctx, &p, end);
1453 if (!operand || !negations)
1459 bool b = strcmp (operand, "0") ^ (negations & 1);
1462 return xstrdup (b ? "1" : "0");
1466 macro_evaluate_and (const struct expr_context *ctx,
1467 const struct macro_token **tokens,
1468 const struct macro_token *end)
1470 const struct macro_token *p = *tokens;
1471 char *lhs = macro_evaluate_not (ctx, &p, end);
1476 && (ss_equals_case (p->representation, ss_cstr ("!AND"))
1477 || ss_equals (p->representation, ss_cstr ("&"))))
1480 char *rhs = macro_evaluate_not (ctx, &p, end);
1487 bool b = strcmp (lhs, "0") && strcmp (rhs, "0");
1490 lhs = xstrdup (b ? "1" : "0");
1497 macro_evaluate_or (const struct expr_context *ctx,
1498 const struct macro_token **tokens,
1499 const struct macro_token *end)
1501 const struct macro_token *p = *tokens;
1502 char *lhs = macro_evaluate_and (ctx, &p, end);
1507 && (ss_equals_case (p->representation, ss_cstr ("!OR"))
1508 || ss_equals (p->representation, ss_cstr ("|"))))
1511 char *rhs = macro_evaluate_and (ctx, &p, end);
1518 bool b = strcmp (lhs, "0") || strcmp (rhs, "0");
1521 lhs = xstrdup (b ? "1" : "0");
1528 macro_evaluate_expression (const struct macro_token **tokens, size_t n_tokens,
1529 int nesting_countdown,
1530 enum segmenter_mode segmenter_mode,
1531 const struct macro_set *macros,
1532 const struct macro_expander *me,
1533 const struct macro_expansion_stack *stack,
1534 struct string_map *vars, bool *expand)
1536 const struct expr_context ctx = {
1537 .nesting_countdown = nesting_countdown,
1538 .segmenter_mode = segmenter_mode,
1545 return macro_evaluate_or (&ctx, tokens, *tokens + n_tokens);
1549 macro_evaluate_number (const struct macro_token **tokens, size_t n_tokens,
1550 int nesting_countdown,
1551 enum segmenter_mode segmenter_mode,
1552 const struct macro_set *macros,
1553 const struct macro_expander *me,
1554 const struct macro_expansion_stack *stack,
1555 struct string_map *vars,
1556 bool *expand, double *number)
1558 char *s = macro_evaluate_expression (tokens, n_tokens, nesting_countdown,
1559 segmenter_mode, macros, me, stack, vars,
1564 struct macro_tokens mts = { .n = 0 };
1565 macro_tokens_from_string__ (&mts, ss_cstr (s), segmenter_mode, stack);
1566 if (mts.n != 1 || !token_is_number (&mts.mts[0].token))
1568 macro_error (stack, mts.n > 0 ? &mts.mts[0] : NULL,
1569 _("Macro expression must evaluate to "
1570 "a number (not \"%s\")."), s);
1572 macro_tokens_uninit (&mts);
1576 *number = token_number (&mts.mts[0].token);
1578 macro_tokens_uninit (&mts);
1582 static const struct macro_token *
1583 find_ifend_clause (const struct macro_token *p, const struct macro_token *end)
1586 for (; p < end; p++)
1588 if (p->token.type != T_MACRO_ID)
1591 if (ss_equals_case (p->token.string, ss_cstr ("!IF")))
1593 else if (ss_equals_case (p->token.string, ss_cstr ("!IFEND")))
1599 else if (ss_equals_case (p->token.string, ss_cstr ("!ELSE")) && !nesting)
1606 macro_expand_if (const struct macro_token *tokens, size_t n_tokens,
1607 int nesting_countdown, enum segmenter_mode segmenter_mode,
1608 const struct macro_set *macros,
1609 const struct macro_expander *me,
1610 const struct macro_expansion_stack *stack,
1611 struct string_map *vars,
1612 bool *expand, bool *break_, struct macro_tokens *exp)
1614 const struct macro_token *p = tokens;
1615 const struct macro_token *end = tokens + n_tokens;
1617 if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!IF")))
1621 char *result = macro_evaluate_expression (&p, end - p,
1622 nesting_countdown, segmenter_mode,
1624 stack, vars, expand);
1627 bool b = strcmp (result, "0");
1631 || p->token.type != T_MACRO_ID
1632 || !ss_equals_case (p->token.string, ss_cstr ("!THEN")))
1634 macro_error (stack, p < end ? p : NULL,
1635 _("!THEN expected in macro !IF construct."));
1639 const struct macro_token *start_then = p + 1;
1640 const struct macro_token *end_then = find_ifend_clause (start_then, end);
1643 macro_error (stack, NULL,
1644 _("!ELSE or !IFEND expected in macro !IF construct."));
1648 const struct macro_token *start_else, *end_if;
1649 if (ss_equals_case (end_then->token.string, ss_cstr ("!ELSE")))
1651 start_else = end_then + 1;
1652 end_if = find_ifend_clause (start_else, end);
1654 || !ss_equals_case (end_if->token.string, ss_cstr ("!IFEND")))
1656 macro_error (stack, end_if ? end_if : NULL,
1657 _("!IFEND expected in macro !IF construct."));
1667 const struct macro_token *start;
1672 n = end_then - start_then;
1674 else if (start_else)
1677 n = end_if - start_else;
1687 struct macro_tokens mts = {
1688 .mts = CONST_CAST (struct macro_token *, start),
1691 macro_expand (&mts, nesting_countdown, segmenter_mode, macros, me, vars,
1692 &(struct macro_expansion_stack) {
1696 expand, break_, exp);
1698 return (end_if + 1) - tokens;
1702 macro_parse_let (const struct macro_token *tokens, size_t n_tokens,
1703 int nesting_countdown, enum segmenter_mode segmenter_mode,
1704 const struct macro_set *macros,
1705 const struct macro_expander *me,
1706 const struct macro_expansion_stack *stack,
1707 struct string_map *vars, bool *expand)
1709 const struct macro_token *p = tokens;
1710 const struct macro_token *end = tokens + n_tokens;
1712 if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!LET")))
1716 if (p >= end || p->token.type != T_MACRO_ID)
1718 macro_error (stack, p < end ? p : NULL,
1719 _("Expected macro variable name following !LET."));
1722 const struct substring var_name = p->token.string;
1723 if (is_macro_keyword (var_name)
1724 || macro_find_parameter_by_name (me->macro, var_name))
1726 macro_error (stack, p < end ? p : NULL,
1727 _("Cannot use argument name or macro keyword "
1728 "\"%.*s\" as !LET variable."),
1729 (int) var_name.length, var_name.string);
1734 if (p >= end || p->token.type != T_EQUALS)
1736 macro_error (stack, p < end ? p : NULL,
1737 _("Expected `=' following !LET."));
1742 char *value = macro_evaluate_expression (&p, end - p, nesting_countdown,
1743 segmenter_mode, macros, me, stack,
1748 string_map_replace_nocopy (vars, ss_xstrdup (var_name), value);
1752 static const struct macro_token *
1753 find_doend (const struct macro_expansion_stack *stack,
1754 const struct macro_token *p, const struct macro_token *end)
1757 for (; p < end; p++)
1759 if (p->token.type != T_MACRO_ID)
1762 if (ss_equals_case (p->token.string, ss_cstr ("!DO")))
1764 else if (ss_equals_case (p->token.string, ss_cstr ("!DOEND")))
1771 macro_error (stack, NULL, _("Missing !DOEND."));
1776 macro_expand_do (const struct macro_token *tokens, size_t n_tokens,
1777 int nesting_countdown, enum segmenter_mode segmenter_mode,
1778 const struct macro_set *macros,
1779 const struct macro_expander *me,
1780 const struct macro_expansion_stack *stack,
1781 struct string_map *vars,
1782 bool *expand, struct macro_tokens *exp)
1784 const struct macro_token *p = tokens;
1785 const struct macro_token *end = tokens + n_tokens;
1787 if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!DO")))
1791 if (p >= end || p->token.type != T_MACRO_ID)
1793 macro_error (stack, p < end ? p : NULL,
1794 _("Expected macro variable name following !DO."));
1797 const struct substring var_name = p->token.string;
1798 if (is_macro_keyword (var_name)
1799 || macro_find_parameter_by_name (me->macro, var_name))
1801 macro_error (stack, p, _("Cannot use argument name or macro "
1802 "keyword as !DO variable."));
1807 struct macro_expansion_stack next_stack = {
1808 .name = "!DO", .next = stack,
1810 int miterate = settings_get_miterate ();
1811 if (p < end && p->token.type == T_MACRO_ID
1812 && ss_equals_case (p->token.string, ss_cstr ("!IN")))
1815 char *list = macro_evaluate_expression (&p, end - p, nesting_countdown,
1816 segmenter_mode, macros, me,
1817 &next_stack, vars, expand);
1821 struct macro_tokens items = { .n = 0 };
1822 macro_tokens_from_string__ (&items, ss_cstr (list), segmenter_mode,
1826 const struct macro_token *do_end = find_doend (stack, p, end);
1829 macro_tokens_uninit (&items);
1833 const struct macro_tokens inner = {
1834 .mts = CONST_CAST (struct macro_token *, p),
1837 for (size_t i = 0; i < items.n; i++)
1841 macro_error (stack, NULL,
1842 _("!DO loop over list exceeded "
1843 "maximum number of iterations %d. "
1844 "(Use SET MITERATE to change the limit.)"),
1848 string_map_replace_nocopy (vars, ss_xstrdup (var_name),
1849 ss_xstrdup (items.mts[i].representation));
1851 bool break_ = false;
1852 macro_expand (&inner, nesting_countdown, segmenter_mode, macros,
1853 me, vars, &next_stack, expand, &break_, exp);
1857 return do_end - tokens + 1;
1859 else if (p < end && p->token.type == T_EQUALS)
1863 if (!macro_evaluate_number (&p, end - p, nesting_countdown,
1864 segmenter_mode, macros, me, &next_stack,
1865 vars, expand, &first))
1868 if (p >= end || p->token.type != T_MACRO_ID
1869 || !ss_equals_case (p->token.string, ss_cstr ("!TO")))
1871 macro_error (stack, p < end ? p : NULL,
1872 _("Expected !TO in numerical !DO loop."));
1878 if (!macro_evaluate_number (&p, end - p, nesting_countdown,
1879 segmenter_mode, macros, me, &next_stack,
1880 vars, expand, &last))
1884 if (p < end && p->token.type == T_MACRO_ID
1885 && ss_equals_case (p->token.string, ss_cstr ("!BY")))
1888 if (!macro_evaluate_number (&p, end - p, nesting_countdown,
1889 segmenter_mode, macros, me, &next_stack,
1895 macro_error (stack, NULL, _("!BY value cannot be zero."));
1900 const struct macro_token *do_end = find_doend (stack, p, end);
1903 const struct macro_tokens inner = {
1904 .mts = CONST_CAST (struct macro_token *, p),
1908 if ((by > 0 && first <= last) || (by < 0 && first >= last))
1911 for (double index = first;
1912 by > 0 ? (index <= last) : (index >= last);
1917 macro_error (stack, NULL,
1918 _("Numerical !DO loop exceeded "
1919 "maximum number of iterations %d. "
1920 "(Use SET MITERATE to change the limit.)"),
1925 char index_s[DBL_BUFSIZE_BOUND];
1926 c_dtoastr (index_s, sizeof index_s, 0, 0, index);
1927 string_map_replace_nocopy (vars, ss_xstrdup (var_name),
1930 bool break_ = false;
1931 macro_expand (&inner, nesting_countdown, segmenter_mode, macros,
1932 me, vars, &next_stack, expand, &break_, exp);
1938 return do_end - tokens + 1;
1942 macro_error (stack, p < end ? p : NULL,
1943 _("Expected `=' or !IN in !DO loop."));
1949 macro_expand (const struct macro_tokens *mts, int nesting_countdown,
1950 enum segmenter_mode segmenter_mode,
1951 const struct macro_set *macros,
1952 const struct macro_expander *me, struct string_map *vars,
1953 const struct macro_expansion_stack *stack,
1954 bool *expand, bool *break_, struct macro_tokens *exp)
1956 if (nesting_countdown <= 0)
1958 macro_error (stack, NULL, _("Maximum nesting level %d exceeded. "
1959 "(Use SET MNEST to change the limit.)"),
1960 settings_get_mnest ());
1961 for (size_t i = 0; i < mts->n; i++)
1962 macro_tokens_add (exp, &mts->mts[i]);
1966 struct string_map own_vars = STRING_MAP_INITIALIZER (own_vars);
1970 for (size_t i = 0; i < mts->n && (!break_ || !*break_); i++)
1972 const struct macro_token *mt = &mts->mts[i];
1973 const struct token *token = &mt->token;
1974 if (token->type == T_MACRO_ID && me)
1976 const struct macro_param *param = macro_find_parameter_by_name (
1977 me->macro, token->string);
1980 const struct macro_tokens *arg = me->args[param - me->macro->params];
1981 if (*expand && param->expand_arg)
1982 macro_expand (arg, nesting_countdown, segmenter_mode,
1984 &(struct macro_expansion_stack) {
1985 .name = param->name,
1987 }, expand, break_, exp);
1989 for (size_t i = 0; i < arg->n; i++)
1990 macro_tokens_add (exp, &arg->mts[i]);
1994 if (is_bang_star (mts->mts, mts->n, i))
1996 for (size_t j = 0; j < me->macro->n_params; j++)
1998 const struct macro_param *param = &me->macro->params[j];
1999 if (!param->positional)
2002 const struct macro_tokens *arg = me->args[j];
2003 if (*expand && param->expand_arg)
2004 macro_expand (arg, nesting_countdown, segmenter_mode,
2006 &(struct macro_expansion_stack) {
2009 }, expand, break_, exp);
2011 for (size_t k = 0; k < arg->n; k++)
2012 macro_tokens_add (exp, &arg->mts[k]);
2018 size_t n = macro_expand_if (&mts->mts[i], mts->n - i,
2019 nesting_countdown, segmenter_mode,
2021 vars, expand, break_, exp);
2029 if (token->type == T_MACRO_ID && vars)
2031 const char *value = string_map_find__ (vars, token->string.string,
2032 token->string.length);
2035 macro_tokens_from_string__ (exp, ss_cstr (value), segmenter_mode,
2043 struct macro_expander *subme;
2044 int retval = macro_expander_create (macros, token, &subme);
2045 for (size_t j = 1; !retval; j++)
2047 const struct macro_token endcmd = { .token = { .type = T_ENDCMD } };
2048 retval = macro_expander_add (
2049 subme, i + j < mts->n ? &mts->mts[i + j] : &endcmd);
2054 macro_expand (&subme->macro->body, nesting_countdown - 1,
2055 segmenter_mode, macros, subme, NULL,
2056 &(struct macro_expansion_stack) {
2057 .name = subme->macro->name,
2058 .file_name = subme->macro->file_name,
2059 .first_line = subme->macro->first_line,
2060 .last_line = subme->macro->last_line,
2062 }, expand, break_, exp);
2063 macro_expander_destroy (subme);
2067 macro_expander_destroy (subme);
2070 if (token->type != T_MACRO_ID)
2072 macro_tokens_add (exp, mt);
2076 if (ss_equals_case (token->string, ss_cstr ("!break")))
2079 macro_error (stack, mt, _("!BREAK outside !DO."));
2087 struct parse_macro_function_ctx ctx = {
2088 .input = &mts->mts[i],
2089 .n_input = mts->n - i,
2090 .nesting_countdown = nesting_countdown,
2091 .segmenter_mode = segmenter_mode,
2098 struct string function_output = DS_EMPTY_INITIALIZER;
2099 size_t function_consumed;
2100 if (expand_macro_function (&ctx, &function_output, &function_consumed))
2102 i += function_consumed - 1;
2104 macro_tokens_from_string__ (exp, function_output.ss, segmenter_mode,
2106 ds_destroy (&function_output);
2111 size_t n = macro_parse_let (&mts->mts[i], mts->n - i,
2112 nesting_countdown, segmenter_mode,
2113 macros, me, stack, vars, expand);
2120 n = macro_expand_do (&mts->mts[i], mts->n - i,
2121 nesting_countdown, segmenter_mode,
2122 macros, me, stack, vars, expand, exp);
2129 if (ss_equals_case (token->string, ss_cstr ("!onexpand")))
2131 else if (ss_equals_case (token->string, ss_cstr ("!offexpand")))
2134 macro_tokens_add (exp, mt);
2136 if (vars == &own_vars)
2137 string_map_destroy (&own_vars);
2141 macro_expander_get_expansion (struct macro_expander *me,
2142 enum segmenter_mode segmenter_mode,
2143 struct macro_tokens *exp)
2145 assert (me->state == ME_FINISHED);
2147 struct macro_expansion_stack stack = {
2148 .name = me->macro->name,
2149 .file_name = me->macro->file_name,
2150 .first_line = me->macro->first_line,
2151 .last_line = me->macro->last_line,
2153 macro_expand (&me->macro->body, settings_get_mnest (), segmenter_mode,
2154 me->macros, me, NULL, &stack, &expand, NULL, exp);