Work on DEFINE command.
[pspp] / src / language / lexer / macro.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2021 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>. */
16
17 #include <config.h>
18
19 #include "language/lexer/macro.h"
20
21 #include <limits.h>
22 #include <stdlib.h>
23
24 #include "data/settings.h"
25 #include "language/lexer/segment.h"
26 #include "language/lexer/scan.h"
27 #include "libpspp/assertion.h"
28 #include "libpspp/i18n.h"
29 #include "libpspp/message.h"
30 #include "libpspp/str.h"
31
32 #include "gettext.h"
33 #define _(msgid) gettext (msgid)
34
35 void
36 macro_token_copy (struct macro_token *dst, const struct macro_token *src)
37 {
38   token_copy (&dst->token, &src->token);
39   ss_alloc_substring (&dst->representation, src->representation);
40 }
41
42 void
43 macro_token_uninit (struct macro_token *mt)
44 {
45   token_uninit (&mt->token);
46   ss_dealloc (&mt->representation);
47 }
48
49 void
50 macro_tokens_copy (struct macro_tokens *dst, const struct macro_tokens *src)
51 {
52   *dst = (struct macro_tokens) {
53     .mts = xmalloc (src->n * sizeof *dst->mts),
54     .n = src->n,
55     .allocated = src->n,
56   };
57   for (size_t i = 0; i < src->n; i++)
58     macro_token_copy (&dst->mts[i], &src->mts[i]);
59 }
60
61 void
62 macro_tokens_uninit (struct macro_tokens *mts)
63 {
64   for (size_t i = 0; i < mts->n; i++)
65     macro_token_uninit (&mts->mts[i]);
66   free (mts->mts);
67 }
68
69 struct macro_token *
70 macro_tokens_add_uninit (struct macro_tokens *mts)
71 {
72   if (mts->n >= mts->allocated)
73     mts->mts = x2nrealloc (mts->mts, &mts->allocated, sizeof *mts->mts);
74   return &mts->mts[mts->n++];
75 }
76
77 void
78 macro_tokens_add (struct macro_tokens *mts, const struct macro_token *mt)
79 {
80   macro_token_copy (macro_tokens_add_uninit (mts), mt);
81 }
82
83 void
84 macro_tokens_from_string (struct macro_tokens *mts, const struct substring src,
85                           enum segmenter_mode mode)
86 {
87   struct state
88     {
89       struct segmenter segmenter;
90       struct substring body;
91     };
92
93   struct state state = {
94     .segmenter = SEGMENTER_INIT (mode),
95     .body = src,
96   };
97   struct state saved = state;
98
99   while (state.body.length > 0)
100     {
101       struct macro_token mt = {
102         .token = { .type = T_STOP },
103         .representation = { .string = state.body.string },
104       };
105       struct token *token = &mt.token;
106
107       struct scanner scanner;
108       scanner_init (&scanner, token);
109
110       for (;;)
111         {
112           enum segment_type type;
113           int seg_len = segmenter_push (&state.segmenter, state.body.string,
114                                         state.body.length, true, &type);
115           assert (seg_len >= 0);
116
117           struct substring segment = ss_head (state.body, seg_len);
118           ss_advance (&state.body, seg_len);
119
120           enum scan_result result = scanner_push (&scanner, type, segment, token);
121           if (result == SCAN_SAVE)
122             saved = state;
123           else if (result == SCAN_BACK)
124             {
125               state = saved;
126               break;
127             }
128           else if (result == SCAN_DONE)
129             break;
130         }
131
132       /* We have a token in 'token'. */
133       if (is_scan_type (token->type))
134         {
135           if (token->type != SCAN_SKIP)
136             {
137               /* XXX report error */
138             }
139         }
140       else
141         {
142           mt.representation.length = state.body.string - mt.representation.string;
143           macro_tokens_add (mts, &mt);
144         }
145       token_uninit (token);
146     }
147 }
148
149 void
150 macro_tokens_print (const struct macro_tokens *mts, FILE *stream)
151 {
152   for (size_t i = 0; i < mts->n; i++)
153     token_print (&mts->mts[i].token, stream);
154 }
155
156 void
157 macro_destroy (struct macro *m)
158 {
159   if (!m)
160     return;
161
162   free (m->name);
163   for (size_t i = 0; i < m->n_params; i++)
164     {
165       struct macro_param *p = &m->params[i];
166       free (p->name);
167
168       macro_tokens_uninit (&p->def);
169
170       switch (p->arg_type)
171         {
172         case ARG_N_TOKENS:
173           break;
174
175         case ARG_CHAREND:
176           token_uninit (&p->charend);
177           break;
178
179         case ARG_ENCLOSE:
180           token_uninit (&p->enclose[0]);
181           token_uninit (&p->enclose[1]);
182           break;
183
184         case ARG_CMDEND:
185           break;
186         }
187     }
188   free (m->params);
189   macro_tokens_uninit (&m->body);
190   free (m);
191 }
192 \f
193 struct macro_set *
194 macro_set_create (void)
195 {
196   struct macro_set *set = xmalloc (sizeof *set);
197   *set = (struct macro_set) {
198     .macros = HMAP_INITIALIZER (set->macros),
199   };
200   return set;
201 }
202
203 void
204 macro_set_destroy (struct macro_set *set)
205 {
206   if (!set)
207     return;
208
209   struct macro *macro, *next;
210   HMAP_FOR_EACH_SAFE (macro, next, struct macro, hmap_node, &set->macros)
211     {
212       hmap_delete (&set->macros, &macro->hmap_node);
213       macro_destroy (macro);
214     }
215   hmap_destroy (&set->macros);
216   free (set);
217 }
218
219 static unsigned int
220 hash_macro_name (const char *name)
221 {
222   return utf8_hash_case_string (name, 0);
223 }
224
225 static struct macro *
226 macro_set_find__ (struct macro_set *set, const char *name)
227 {
228   struct macro *macro;
229   HMAP_FOR_EACH_WITH_HASH (macro, struct macro, hmap_node,
230                            hash_macro_name (name), &set->macros)
231     if (!utf8_strcasecmp (macro->name, name))
232       return macro;
233
234   return NULL;
235 }
236
237 const struct macro *
238 macro_set_find (const struct macro_set *set, const char *name)
239 {
240   return macro_set_find__ (CONST_CAST (struct macro_set *, set), name);
241 }
242
243 /* Adds M to SET.  M replaces any existing macro with the same name.  Takes
244    ownership of M. */
245 void
246 macro_set_add (struct macro_set *set, struct macro *m)
247 {
248   struct macro *victim = macro_set_find__ (set, m->name);
249   if (victim)
250     {
251       hmap_delete (&set->macros, &victim->hmap_node);
252       macro_destroy (victim);
253     }
254
255   hmap_insert (&set->macros, &m->hmap_node, hash_macro_name (m->name));
256 }
257 \f
258 enum me_state
259   {
260     /* Error state. */
261     ME_ERROR,
262
263     /* Accumulating tokens in me->params toward the end of any type of
264        argument. */
265     ME_ARG,
266
267     /* Expecting the opening delimiter of an ARG_ENCLOSE argument. */
268     ME_ENCLOSE,
269
270     /* Expecting a keyword for a keyword argument. */
271     ME_KEYWORD,
272
273     /* Expecting an equal sign for a keyword argument. */
274     ME_EQUALS,
275   };
276
277
278 struct macro_expander
279   {
280     const struct macro_set *macros;
281
282     enum me_state state;
283     size_t n_tokens;
284
285     const struct macro *macro;
286     struct macro_tokens **args;
287     const struct macro_param *param;
288   };
289
290 static int
291 me_finished (struct macro_expander *me)
292 {
293   for (size_t i = 0; i < me->macro->n_params; i++)
294     if (!me->args[i])
295       {
296         me->args[i] = xmalloc (sizeof *me->args[i]);
297         macro_tokens_copy (me->args[i], &me->macro->params[i].def);
298       }
299   return me->n_tokens;
300 }
301
302 static int
303 me_next_arg (struct macro_expander *me)
304 {
305   if (!me->param)
306     {
307       assert (!me->macro->n_params);
308       return me_finished (me);
309     }
310   else if (me->param->positional)
311     {
312       me->param++;
313       if (me->param >= &me->macro->params[me->macro->n_params])
314         return me_finished (me);
315       else
316         {
317           me->state = me->param->positional ? ME_ARG : ME_KEYWORD;
318           return 0;
319         }
320     }
321   else
322     {
323       for (size_t i = 0; i < me->macro->n_params; i++)
324         if (!me->args[i])
325           {
326             me->state = ME_KEYWORD;
327             return 0;
328           }
329       return me_finished (me);
330     }
331 }
332
333 static int
334 me_error (struct macro_expander *me)
335 {
336   me->state = ME_ERROR;
337   return -1;
338 }
339
340 static int
341 me_add_arg (struct macro_expander *me, const struct macro_token *mt)
342 {
343   const struct token *token = &mt->token;
344   if (token->type == T_STOP)
345     {
346       msg (SE, _("Unexpected end of file reading argument %s "
347                  "to macro %s."), me->param->name, me->macro->name);
348
349       return me_error (me);
350     }
351
352   me->n_tokens++;
353
354   const struct macro_param *p = me->param;
355   struct macro_tokens **argp = &me->args[p - me->macro->params];
356   if (!*argp)
357     *argp = xzalloc (sizeof **argp);
358   struct macro_tokens *arg = *argp;
359   if (p->arg_type == ARG_N_TOKENS)
360     {
361       macro_tokens_add (arg, mt);
362       if (arg->n >= p->n_tokens)
363         return me_next_arg (me);
364       return 0;
365     }
366   else if (p->arg_type == ARG_CMDEND)
367     {
368       if (token->type == T_ENDCMD || token->type == T_STOP)
369         return me_next_arg (me);
370       macro_tokens_add (arg, mt);
371       return 0;
372     }
373   else
374     {
375       const struct token *end
376         = p->arg_type == ARG_CMDEND ? &p->charend : &p->enclose[1];
377       if (token_equal (token, end))
378         return me_next_arg (me);
379       macro_tokens_add (arg, mt);
380       return 0;
381     }
382 }
383
384 static int
385 me_expected (struct macro_expander *me, const struct macro_token *actual,
386              const struct token *expected)
387 {
388   const struct substring actual_s
389     = (actual->representation.length ? actual->representation
390        : ss_cstr (_("<end of input>")));
391   char *expected_s = token_to_string (expected);
392   msg (SE, _("Found `%.*s' while expecting `%s' reading argument %s "
393              "to macro %s."),
394        (int) actual_s.length, actual_s.string, expected_s,
395        me->param->name, me->macro->name);
396   free (expected_s);
397
398   return me_error (me);
399 }
400
401 static int
402 me_enclose (struct macro_expander *me, const struct macro_token *mt)
403 {
404   const struct token *token = &mt->token;
405   me->n_tokens++;
406
407   if (token_equal (&me->param->enclose[0], token))
408     {
409       me->state = ME_ARG;
410       return 0;
411     }
412
413   return me_expected (me, mt, &me->param->enclose[0]);
414 }
415
416 static const struct macro_param *
417 macro_find_parameter_by_name (const struct macro *m, struct substring name)
418 {
419   for (size_t i = 0; i < m->n_params; i++)
420     {
421       const struct macro_param *p = &m->params[i];
422       struct substring p_name = ss_cstr (p->name);
423       if (!utf8_strncasecmp (p_name.string, p_name.length,
424                              name.string, name.length))
425         return p;
426     }
427   return NULL;
428 }
429
430 static int
431 me_keyword (struct macro_expander *me, const struct macro_token *mt)
432 {
433   const struct token *token = &mt->token;
434   if (token->type != T_ID)
435     return me_finished (me);
436
437   const struct macro_param *p = macro_find_parameter_by_name (me->macro,
438                                                               token->string);
439   if (p)
440     {
441       size_t arg_index = p - me->macro->params;
442       me->param = p;
443       if (me->args[arg_index])
444         {
445           msg (SE,
446                _("Argument %s multiply specified in call to macro %s."),
447                p->name, me->macro->name);
448           return me_error (me);
449         }
450
451       me->n_tokens++;
452       me->state = ME_EQUALS;
453       return 0;
454     }
455
456   return me_finished (me);
457 }
458
459 static int
460 me_equals (struct macro_expander *me, const struct macro_token *mt)
461 {
462   const struct token *token = &mt->token;
463   me->n_tokens++;
464
465   if (token->type == T_EQUALS)
466     {
467       me->state = ME_ARG;
468       return 0;
469     }
470
471   return me_expected (me, mt, &(struct token) { .type = T_EQUALS });
472 }
473
474 int
475 macro_expander_create (const struct macro_set *macros,
476                        const struct token *token,
477                        struct macro_expander **mep)
478 {
479   *mep = NULL;
480   if (macro_set_is_empty (macros))
481     return -1;
482   if (token->type != T_ID && token->type != T_MACRO_ID)
483     return -1;
484
485   const struct macro *macro = macro_set_find (macros, token->string.string);
486   if (!macro)
487     return -1;
488
489   struct macro_expander *me = xmalloc (sizeof *me);
490   *me = (struct macro_expander) {
491     .macros = macros,
492     .n_tokens = 1,
493     .macro = macro,
494   };
495   *mep = me;
496
497   if (!macro->n_params)
498     return 1;
499   else
500     {
501       me->state = macro->params[0].positional ? ME_ARG : ME_KEYWORD;
502       me->args = xcalloc (macro->n_params, sizeof *me->args);
503       me->param = macro->params;
504       return 0;
505     }
506 }
507
508 void
509 macro_expander_destroy (struct macro_expander *me)
510 {
511   if (!me)
512     return;
513
514   for (size_t i = 0; i < me->macro->n_params; i++)
515     if (me->args[i])
516       {
517         macro_tokens_uninit (me->args[i]);
518         free (me->args[i]);
519       }
520   free (me->args);
521   free (me);
522 }
523
524 /* Adds TOKEN to the collection of tokens in ME that potentially need to be
525    macro expanded.
526
527    Returns -1 if the tokens added do not actually invoke a macro.  The caller
528    should consume the first token without expanding it.
529
530    Returns 0 if the macro expander needs more tokens, for macro arguments or to
531    decide whether this is actually a macro invocation.  The caller should call
532    macro_expander_add() again with the next token.
533
534    Returns a positive number to indicate that the returned number of tokens
535    invoke a macro.  The number returned might be less than the number of tokens
536    added because it can take a few tokens of lookahead to determine whether the
537    macro invocation is finished.  The caller should call
538    macro_expander_get_expansion() to obtain the expansion. */
539 int
540 macro_expander_add (struct macro_expander *me, const struct macro_token *mt)
541 {
542   switch (me->state)
543     {
544     case ME_ERROR:
545       return -1;
546
547     case ME_ARG:
548       return me_add_arg (me, mt);
549
550     case ME_ENCLOSE:
551       return me_enclose (me, mt);
552
553     case ME_KEYWORD:
554       return me_keyword (me, mt);
555
556     case ME_EQUALS:
557       return me_equals (me, mt);
558
559     default:
560       NOT_REACHED ();
561     }
562 }
563
564 /* Each argument to a macro function is one of:
565
566        - A quoted string or other single literal token.
567
568        - An argument to the macro being expanded, e.g. !1 or a named argument.
569
570        - !*.
571
572        - A function invocation.
573
574    Each function invocation yields a character sequence to be turned into a
575    sequence of tokens.  The case where that character sequence is a single
576    quoted string is an important special case.
577 */
578 struct parse_macro_function_ctx
579   {
580     struct macro_token *input;
581     size_t n_input;
582     int nesting_countdown;
583     const struct macro_set *macros;
584     const struct macro_expander *me;
585     bool *expand;
586   };
587
588 static void
589 macro_expand (const struct macro_tokens *,
590               int nesting_countdown, const struct macro_set *,
591               const struct macro_expander *, bool *expand, struct macro_tokens *exp);
592
593 static bool
594 expand_macro_function (struct parse_macro_function_ctx *ctx,
595                        struct macro_token *output,
596                        size_t *input_consumed);
597
598 static size_t
599 parse_function_arg (struct parse_macro_function_ctx *ctx,
600                     size_t i, struct macro_token *farg)
601 {
602   struct macro_token *tokens = ctx->input;
603   const struct token *token = &tokens[i].token;
604   if (token->type == T_MACRO_ID)
605     {
606       const struct macro_param *param = macro_find_parameter_by_name (
607         ctx->me->macro, token->string);
608       if (param)
609         {
610           size_t param_idx = param - ctx->me->macro->params;
611           const struct macro_tokens *marg = ctx->me->args[param_idx];
612           if (marg->n == 1)
613             macro_token_copy (farg, &marg->mts[0]);
614           else
615             {
616               struct string s = DS_EMPTY_INITIALIZER;
617               for (size_t i = 0; i < marg->n; i++)
618                 {
619                   if (i)
620                     ds_put_byte (&s, ' ');
621                   ds_put_substring (&s, marg->mts[i].representation);
622                 }
623
624               struct substring s_copy;
625               ss_alloc_substring (&s_copy, s.ss);
626
627               *farg = (struct macro_token) {
628                 .token = { .type = T_MACRO_ID, .string = s.ss },
629                 .representation = s_copy,
630               };
631             }
632           return 1;
633         }
634
635       struct parse_macro_function_ctx subctx = {
636         .input = &ctx->input[i],
637         .n_input = ctx->n_input - i,
638         .nesting_countdown = ctx->nesting_countdown,
639         .macros = ctx->macros,
640         .me = ctx->me,
641         .expand = ctx->expand,
642       };
643       size_t subinput_consumed;
644       if (expand_macro_function (&subctx, farg, &subinput_consumed))
645         return subinput_consumed;
646     }
647
648   macro_token_copy (farg, &tokens[i]);
649   return 1;
650 }
651
652 static bool
653 parse_macro_function (struct parse_macro_function_ctx *ctx,
654                       struct macro_tokens *args,
655                       struct substring function,
656                       int min_args, int max_args,
657                       size_t *input_consumed)
658 {
659   struct macro_token *tokens = ctx->input;
660   size_t n_tokens = ctx->n_input;
661
662   if (!n_tokens
663       || tokens[0].token.type != T_MACRO_ID
664       || !ss_equals_case (tokens[0].token.string, function))
665     return false;
666
667   if (n_tokens < 2 || tokens[1].token.type != T_LPAREN)
668     {
669       printf ("`(' expected following %s'\n", function.string);
670       return false;
671     }
672
673   *args = (struct macro_tokens) { .n = 0 };
674
675   for (size_t i = 2;; )
676     {
677       if (i >= n_tokens)
678         goto unexpected_end;
679       if (tokens[i].token.type == T_RPAREN)
680         {
681           *input_consumed = i + 1;
682           if (args->n < min_args || args->n > max_args)
683             {
684               printf ("Wrong number of arguments to %s.\n", function.string);
685               goto error;
686             }
687           return true;
688         }
689
690       i += parse_function_arg (ctx, i, macro_tokens_add_uninit (args));
691       if (i >= n_tokens)
692         goto unexpected_end;
693
694       if (tokens[i].token.type == T_COMMA)
695         i++;
696       else if (tokens[i].token.type != T_RPAREN)
697         {
698           printf ("Expecting `,' or `)' in %s invocation.", function.string);
699           goto error;
700         }
701     }
702
703 unexpected_end:
704   printf ("Missing closing parenthesis in arguments to %s.\n",
705           function.string);
706   /* Fall through. */
707 error:
708   macro_tokens_uninit (args);
709   return false;
710 }
711
712 static bool
713 expand_macro_function (struct parse_macro_function_ctx *ctx,
714                        struct macro_token *output,
715                        size_t *input_consumed)
716 {
717   struct macro_tokens args;
718
719   if (parse_macro_function (ctx, &args, ss_cstr ("!length"), 1, 1,
720                             input_consumed))
721     {
722       size_t length = args.mts[0].representation.length;
723       *output = (struct macro_token) {
724         .token = { .type = T_POS_NUM, .number = length },
725         .representation = ss_cstr (xasprintf ("%zu", length)),
726       };
727     }
728   else if (parse_macro_function (ctx, &args, ss_cstr ("!blanks"), 1, 1,
729                                  input_consumed))
730     {
731       /* XXX this isn't right, it might be a character string containing a
732          positive integer, e.g. via !CONCAT. */
733       if (args.mts[0].token.type != T_POS_NUM)
734         {
735           printf ("argument to !BLANKS must be positive integer\n");
736           macro_tokens_uninit (&args);
737           return false;
738         }
739
740       struct string s = DS_EMPTY_INITIALIZER;
741       ds_put_byte_multiple (&s, ' ', args.mts[0].token.number);
742
743       struct substring s_copy;
744       ss_alloc_substring (&s_copy, s.ss);
745
746       *output = (struct macro_token) {
747         .token = { .type = T_ID, .string = s.ss },
748         .representation = s_copy,
749       };
750     }
751   else if (parse_macro_function (ctx, &args, ss_cstr ("!concat"), 1, INT_MAX,
752                                  input_consumed))
753     {
754       struct string s;
755       bool all_strings = true;
756       for (size_t i = 0; i < args.n; i++)
757         {
758           if (args.mts[i].token.type == T_STRING)
759             ds_put_substring (&s, args.mts[i].token.string);
760           else
761             {
762               all_strings = false;
763               ds_put_substring (&s, args.mts[i].representation);
764             }
765         }
766
767       if (all_strings)
768         {
769           *output = (struct macro_token) {
770             .token = { .type = T_STRING, .string = s.ss },
771           };
772           output->representation = ss_cstr (token_to_string (&output->token));
773         }
774       else
775         {
776           *output = (struct macro_token) {
777             .token = { .type = T_MACRO_ID /*XXX*/, .string = s.ss },
778           };
779           ss_alloc_substring (&output->representation, s.ss);
780         }
781     }
782   else if (parse_macro_function (ctx, &args, ss_cstr ("!quote"), 1, 1,
783                                  input_consumed))
784     {
785       if (args.mts[0].token.type == T_STRING)
786         macro_token_copy (output, &args.mts[0]);
787       else
788         {
789           *output = (struct macro_token) { .token = { .type = T_STRING } };
790           ss_alloc_substring (&output->token.string, args.mts[0].representation);
791           output->representation = ss_cstr (token_to_string (&output->token));
792         }
793     }
794   else if (parse_macro_function (ctx, &args, ss_cstr ("!unquote"), 1, 1,
795                                  input_consumed))
796     {
797       if (args.mts[0].token.type == T_STRING)
798         {
799           *output = (struct macro_token) { .token = { .type = T_MACRO_ID } };
800           ss_alloc_substring (&output->token.string, args.mts[0].token.string);
801           output->representation = ss_cstr (token_to_string (&output->token));
802         }
803       else
804         macro_token_copy (output, &args.mts[0]);
805     }
806   else
807     return false;
808
809   macro_tokens_uninit (&args);
810   return true;
811 }
812
813 static void
814 macro_expand (const struct macro_tokens *mts,
815               int nesting_countdown, const struct macro_set *macros,
816               const struct macro_expander *me, bool *expand,
817               struct macro_tokens *exp)
818 {
819   if (nesting_countdown <= 0)
820     {
821       printf ("maximum nesting level exceeded\n");
822       for (size_t i = 0; i < mts->n; i++)
823         macro_tokens_add (exp, &mts->mts[i]);
824       return;
825     }
826
827   for (size_t i = 0; i < mts->n; i++)
828     {
829       const struct macro_token *mt = &mts->mts[i];
830       const struct token *token = &mt->token;
831       if (token->type == T_MACRO_ID && me)
832         {
833           const struct macro_param *param = macro_find_parameter_by_name (
834             me->macro, token->string);
835           if (param)
836             {
837               const struct macro_tokens *arg = me->args[param - me->macro->params];
838               //macro_tokens_print (arg, stdout);
839               if (*expand && param->expand_arg)
840                 macro_expand (arg, nesting_countdown, macros, NULL, expand, exp);
841               else
842                 for (size_t i = 0; i < arg->n; i++)
843                   macro_tokens_add (exp, &arg->mts[i]);
844               continue;
845             }
846         }
847
848       if (*expand)
849         {
850           struct macro_expander *subme;
851           int retval = macro_expander_create (macros, token, &subme);
852           for (size_t j = 1; !retval; j++)
853             {
854               const struct macro_token stop = { .token = { .type = T_STOP } };
855               retval = macro_expander_add (
856                 subme, i + j < mts->n ? &mts->mts[i + j] : &stop);
857             }
858           if (retval > 0)
859             {
860               i += retval - 1;
861               macro_expand (&subme->macro->body, nesting_countdown - 1, macros,
862                             subme, expand, exp);
863               macro_expander_destroy (subme);
864               continue;
865             }
866
867           macro_expander_destroy (subme);
868         }
869
870       if (token->type != T_MACRO_ID)
871         {
872           macro_tokens_add (exp, mt);
873           continue;
874         }
875
876       /* Maybe each arg should just be a string, either a quoted string or a
877          non-quoted string containing tokens. */
878       struct parse_macro_function_ctx ctx = {
879         .input = &mts->mts[i],
880         .n_input = mts->n - i,
881         .nesting_countdown = nesting_countdown,
882         .macros = macros,
883         .me = me,
884         .expand = expand,
885       };
886       struct macro_token function_output;
887       size_t function_consumed;
888       if (expand_macro_function (&ctx, &function_output, &function_consumed))
889         {
890           i += function_consumed - 1;
891
892           if (function_output.token.type == T_MACRO_ID)
893             macro_tokens_from_string (exp, function_output.token.string,
894                                       SEG_MODE_INTERACTIVE /* XXX */);
895           else
896             macro_tokens_add (exp, &function_output);
897           macro_token_uninit (&function_output);
898
899           continue;
900         }
901
902       if (ss_equals_case (token->string, ss_cstr ("!onexpand")))
903         *expand = true;
904       else if (ss_equals_case (token->string, ss_cstr ("!offexpand")))
905         *expand = false;
906       else
907         macro_tokens_add (exp, mt);
908     }
909 }
910
911 void
912 macro_expander_get_expansion (struct macro_expander *me, struct macro_tokens *exp)
913 {
914 #if 0
915   for (size_t i = 0; i < me->macro->n_params; i++)
916     {
917       printf ("%s:\n", me->macro->params[i].name);
918       macro_tokens_print (me->args[i], stdout);
919     }
920 #endif
921
922   bool expand = true;
923   macro_expand (&me->macro->body, settings_get_mnest (),
924                 me->macros, me, &expand, exp);
925
926 #if 0
927   printf ("expansion:\n");
928   macro_tokens_print (exp, stdout);
929 #endif
930 }
931