!LET
[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 <errno.h>
22 #include <limits.h>
23 #include <stdlib.h>
24
25 #include "data/settings.h"
26 #include "language/lexer/segment.h"
27 #include "language/lexer/scan.h"
28 #include "libpspp/assertion.h"
29 #include "libpspp/cast.h"
30 #include "libpspp/i18n.h"
31 #include "libpspp/message.h"
32 #include "libpspp/str.h"
33 #include "libpspp/string-array.h"
34 #include "libpspp/string-map.h"
35
36 #include "gl/c-ctype.h"
37
38 #include "gettext.h"
39 #define _(msgid) gettext (msgid)
40
41 void
42 macro_token_copy (struct macro_token *dst, const struct macro_token *src)
43 {
44   token_copy (&dst->token, &src->token);
45   ss_alloc_substring (&dst->representation, src->representation);
46 }
47
48 void
49 macro_token_uninit (struct macro_token *mt)
50 {
51   token_uninit (&mt->token);
52   ss_dealloc (&mt->representation);
53 }
54
55 void
56 macro_token_to_representation (struct macro_token *mt, struct string *s)
57 {
58   ds_put_substring (s, mt->representation);
59 }
60
61 void
62 macro_tokens_copy (struct macro_tokens *dst, const struct macro_tokens *src)
63 {
64   *dst = (struct macro_tokens) {
65     .mts = xmalloc (src->n * sizeof *dst->mts),
66     .n = src->n,
67     .allocated = src->n,
68   };
69   for (size_t i = 0; i < src->n; i++)
70     macro_token_copy (&dst->mts[i], &src->mts[i]);
71 }
72
73 void
74 macro_tokens_uninit (struct macro_tokens *mts)
75 {
76   for (size_t i = 0; i < mts->n; i++)
77     macro_token_uninit (&mts->mts[i]);
78   free (mts->mts);
79 }
80
81 struct macro_token *
82 macro_tokens_add_uninit (struct macro_tokens *mts)
83 {
84   if (mts->n >= mts->allocated)
85     mts->mts = x2nrealloc (mts->mts, &mts->allocated, sizeof *mts->mts);
86   return &mts->mts[mts->n++];
87 }
88
89 void
90 macro_tokens_add (struct macro_tokens *mts, const struct macro_token *mt)
91 {
92   macro_token_copy (macro_tokens_add_uninit (mts), mt);
93 }
94
95 void
96 macro_tokens_from_string (struct macro_tokens *mts, const struct substring src,
97                           enum segmenter_mode mode)
98 {
99   struct state
100     {
101       struct segmenter segmenter;
102       struct substring body;
103     };
104
105   struct state state = {
106     .segmenter = SEGMENTER_INIT (mode),
107     .body = src,
108   };
109   struct state saved = state;
110
111   while (state.body.length > 0)
112     {
113       struct macro_token mt = {
114         .token = { .type = T_STOP },
115         .representation = { .string = state.body.string },
116       };
117       struct token *token = &mt.token;
118
119       struct scanner scanner;
120       scanner_init (&scanner, token);
121
122       for (;;)
123         {
124           enum segment_type type;
125           int seg_len = segmenter_push (&state.segmenter, state.body.string,
126                                         state.body.length, true, &type);
127           assert (seg_len >= 0);
128
129           struct substring segment = ss_head (state.body, seg_len);
130           ss_advance (&state.body, seg_len);
131
132           enum scan_result result = scanner_push (&scanner, type, segment, token);
133           if (result == SCAN_SAVE)
134             saved = state;
135           else if (result == SCAN_BACK)
136             {
137               state = saved;
138               break;
139             }
140           else if (result == SCAN_DONE)
141             break;
142         }
143
144       /* We have a token in 'token'. */
145       if (is_scan_type (token->type))
146         {
147           if (token->type != SCAN_SKIP)
148             {
149               printf ("error\n");
150               /* XXX report error */
151             }
152         }
153       else
154         {
155           mt.representation.length = state.body.string - mt.representation.string;
156           macro_tokens_add (mts, &mt);
157         }
158       token_uninit (token);
159     }
160 }
161
162 void
163 macro_tokens_print (const struct macro_tokens *mts, FILE *stream)
164 {
165   for (size_t i = 0; i < mts->n; i++)
166     token_print (&mts->mts[i].token, stream);
167 }
168
169 enum token_class
170   {
171     TC_ENDCMD,                  /* No space before or after (new-line after). */
172     TC_BINOP,                   /* Space on both sides. */
173     TC_COMMA,                   /* Space afterward. */
174     TC_ID,                      /* Don't need spaces except sequentially. */
175     TC_PUNCT,                   /* Don't need spaces except sequentially. */
176   };
177
178 static bool
179 needs_space (enum token_class prev, enum token_class next)
180 {
181   /* Don't need a space before or after the end of a command.
182      (A new-line is needed afterward as a special case.) */
183   if (prev == TC_ENDCMD || next == TC_ENDCMD)
184     return false;
185
186   /* Binary operators always have a space on both sides. */
187   if (prev == TC_BINOP || next == TC_BINOP)
188     return true;
189
190   /* A comma always has a space afterward. */
191   if (prev == TC_COMMA)
192     return true;
193
194   /* Otherwise, PREV is TC_ID or TC_PUNCT, which only need a space if there are
195      two or them in a row. */
196   return prev == next;
197 }
198
199 static enum token_class
200 classify_token (enum token_type type)
201 {
202   switch (type)
203     {
204     case T_ID:
205     case T_MACRO_ID:
206     case T_POS_NUM:
207     case T_NEG_NUM:
208     case T_STRING:
209       return TC_ID;
210
211     case T_STOP:
212       return TC_PUNCT;
213
214     case T_ENDCMD:
215       return TC_ENDCMD;
216
217     case T_LPAREN:
218     case T_RPAREN:
219     case T_LBRACK:
220     case T_RBRACK:
221       return TC_PUNCT;
222
223     case T_PLUS:
224     case T_DASH:
225     case T_ASTERISK:
226     case T_SLASH:
227     case T_EQUALS:
228     case T_AND:
229     case T_OR:
230     case T_NOT:
231     case T_EQ:
232     case T_GE:
233     case T_GT:
234     case T_LE:
235     case T_LT:
236     case T_NE:
237     case T_ALL:
238     case T_BY:
239     case T_TO:
240     case T_WITH:
241     case T_EXP:
242     case T_MACRO_PUNCT:
243       return TC_BINOP;
244
245     case T_COMMA:
246       return TC_COMMA;
247     }
248
249   NOT_REACHED ();
250 }
251
252 void
253 macro_tokens_to_representation (struct macro_tokens *mts, struct string *s)
254 {
255   if (!mts->n)
256     return;
257
258   macro_token_to_representation (&mts->mts[0], s);
259   for (size_t i = 1; i < mts->n; i++)
260     {
261       enum token_type prev = mts->mts[i - 1].token.type;
262       enum token_type next = mts->mts[i].token.type;
263
264       if (prev == T_ENDCMD)
265         ds_put_byte (s, '\n');
266       else
267         {
268           enum token_class pc = classify_token (prev);
269           enum token_class nc = classify_token (next);
270           if (needs_space (pc, nc))
271             ds_put_byte (s, ' ');
272         }
273
274       macro_token_to_representation (&mts->mts[i], s);
275     }
276 }
277
278 void
279 macro_destroy (struct macro *m)
280 {
281   if (!m)
282     return;
283
284   free (m->name);
285   for (size_t i = 0; i < m->n_params; i++)
286     {
287       struct macro_param *p = &m->params[i];
288       free (p->name);
289
290       macro_tokens_uninit (&p->def);
291
292       switch (p->arg_type)
293         {
294         case ARG_N_TOKENS:
295           break;
296
297         case ARG_CHAREND:
298           token_uninit (&p->charend);
299           break;
300
301         case ARG_ENCLOSE:
302           token_uninit (&p->enclose[0]);
303           token_uninit (&p->enclose[1]);
304           break;
305
306         case ARG_CMDEND:
307           break;
308         }
309     }
310   free (m->params);
311   macro_tokens_uninit (&m->body);
312   free (m);
313 }
314 \f
315 struct macro_set *
316 macro_set_create (void)
317 {
318   struct macro_set *set = xmalloc (sizeof *set);
319   *set = (struct macro_set) {
320     .macros = HMAP_INITIALIZER (set->macros),
321   };
322   return set;
323 }
324
325 void
326 macro_set_destroy (struct macro_set *set)
327 {
328   if (!set)
329     return;
330
331   struct macro *macro, *next;
332   HMAP_FOR_EACH_SAFE (macro, next, struct macro, hmap_node, &set->macros)
333     {
334       hmap_delete (&set->macros, &macro->hmap_node);
335       macro_destroy (macro);
336     }
337   hmap_destroy (&set->macros);
338   free (set);
339 }
340
341 static unsigned int
342 hash_macro_name (const char *name)
343 {
344   return utf8_hash_case_string (name, 0);
345 }
346
347 static struct macro *
348 macro_set_find__ (struct macro_set *set, const char *name)
349 {
350   struct macro *macro;
351   HMAP_FOR_EACH_WITH_HASH (macro, struct macro, hmap_node,
352                            hash_macro_name (name), &set->macros)
353     if (!utf8_strcasecmp (macro->name, name))
354       return macro;
355
356   return NULL;
357 }
358
359 const struct macro *
360 macro_set_find (const struct macro_set *set, const char *name)
361 {
362   return macro_set_find__ (CONST_CAST (struct macro_set *, set), name);
363 }
364
365 /* Adds M to SET.  M replaces any existing macro with the same name.  Takes
366    ownership of M. */
367 void
368 macro_set_add (struct macro_set *set, struct macro *m)
369 {
370   struct macro *victim = macro_set_find__ (set, m->name);
371   if (victim)
372     {
373       hmap_delete (&set->macros, &victim->hmap_node);
374       macro_destroy (victim);
375     }
376
377   hmap_insert (&set->macros, &m->hmap_node, hash_macro_name (m->name));
378 }
379 \f
380 enum me_state
381   {
382     /* Error state. */
383     ME_ERROR,
384
385     /* Accumulating tokens in me->params toward the end of any type of
386        argument. */
387     ME_ARG,
388
389     /* Expecting the opening delimiter of an ARG_ENCLOSE argument. */
390     ME_ENCLOSE,
391
392     /* Expecting a keyword for a keyword argument. */
393     ME_KEYWORD,
394
395     /* Expecting an equal sign for a keyword argument. */
396     ME_EQUALS,
397   };
398
399
400 struct macro_expander
401   {
402     const struct macro_set *macros;
403
404     enum me_state state;
405     size_t n_tokens;
406
407     const struct macro *macro;
408     struct macro_tokens **args;
409     const struct macro_param *param;
410   };
411
412 static int
413 me_finished (struct macro_expander *me)
414 {
415   for (size_t i = 0; i < me->macro->n_params; i++)
416     if (!me->args[i])
417       {
418         me->args[i] = xmalloc (sizeof *me->args[i]);
419         macro_tokens_copy (me->args[i], &me->macro->params[i].def);
420       }
421   return me->n_tokens;
422 }
423
424 static int
425 me_next_arg (struct macro_expander *me)
426 {
427   if (!me->param)
428     {
429       assert (!me->macro->n_params);
430       return me_finished (me);
431     }
432   else if (me->param->positional)
433     {
434       me->param++;
435       if (me->param >= &me->macro->params[me->macro->n_params])
436         return me_finished (me);
437       else
438         {
439           me->state = (!me->param->positional ? ME_KEYWORD
440                        : me->param->arg_type == ARG_ENCLOSE ? ME_ENCLOSE
441                        : ME_ARG);
442           return 0;
443         }
444     }
445   else
446     {
447       for (size_t i = 0; i < me->macro->n_params; i++)
448         if (!me->args[i])
449           {
450             me->state = ME_KEYWORD;
451             return 0;
452           }
453       return me_finished (me);
454     }
455 }
456
457 static int
458 me_error (struct macro_expander *me)
459 {
460   me->state = ME_ERROR;
461   return -1;
462 }
463
464 static int
465 me_add_arg (struct macro_expander *me, const struct macro_token *mt)
466 {
467   const struct macro_param *p = me->param;
468
469   const struct token *token = &mt->token;
470   if ((token->type == T_ENDCMD || token->type == T_STOP)
471       && p->arg_type != ARG_CMDEND)
472     {
473       msg (SE, _("Unexpected end of command reading argument %s "
474                  "to macro %s."), me->param->name, me->macro->name);
475
476       return me_error (me);
477     }
478
479   me->n_tokens++;
480
481   struct macro_tokens **argp = &me->args[p - me->macro->params];
482   if (!*argp)
483     *argp = xzalloc (sizeof **argp);
484   struct macro_tokens *arg = *argp;
485   if (p->arg_type == ARG_N_TOKENS)
486     {
487       macro_tokens_add (arg, mt);
488       if (arg->n >= p->n_tokens)
489         return me_next_arg (me);
490       return 0;
491     }
492   else if (p->arg_type == ARG_CMDEND)
493     {
494       if (token->type == T_ENDCMD || token->type == T_STOP)
495         return me_next_arg (me);
496       macro_tokens_add (arg, mt);
497       return 0;
498     }
499   else
500     {
501       const struct token *end
502         = p->arg_type == ARG_CHAREND ? &p->charend : &p->enclose[1];
503       if (token_equal (token, end))
504         return me_next_arg (me);
505       macro_tokens_add (arg, mt);
506       return 0;
507     }
508 }
509
510 static int
511 me_expected (struct macro_expander *me, const struct macro_token *actual,
512              const struct token *expected)
513 {
514   const struct substring actual_s
515     = (actual->representation.length ? actual->representation
516        : ss_cstr (_("<end of input>")));
517   char *expected_s = token_to_string (expected);
518   msg (SE, _("Found `%.*s' while expecting `%s' reading argument %s "
519              "to macro %s."),
520        (int) actual_s.length, actual_s.string, expected_s,
521        me->param->name, me->macro->name);
522   free (expected_s);
523
524   return me_error (me);
525 }
526
527 static int
528 me_enclose (struct macro_expander *me, const struct macro_token *mt)
529 {
530   const struct token *token = &mt->token;
531   me->n_tokens++;
532
533   if (token_equal (&me->param->enclose[0], token))
534     {
535       me->state = ME_ARG;
536       return 0;
537     }
538
539   return me_expected (me, mt, &me->param->enclose[0]);
540 }
541
542 static const struct macro_param *
543 macro_find_parameter_by_name (const struct macro *m, struct substring name)
544 {
545   if (ss_first (name) == '!')
546     ss_advance (&name, 1);
547
548   for (size_t i = 0; i < m->n_params; i++)
549     {
550       const struct macro_param *p = &m->params[i];
551       struct substring p_name = ss_cstr (p->name + 1);
552       if (!utf8_strncasecmp (p_name.string, p_name.length,
553                              name.string, name.length))
554         return p;
555     }
556   return NULL;
557 }
558
559 static int
560 me_keyword (struct macro_expander *me, const struct macro_token *mt)
561 {
562   const struct token *token = &mt->token;
563   if (token->type != T_ID)
564     return me_finished (me);
565
566   const struct macro_param *p = macro_find_parameter_by_name (me->macro,
567                                                               token->string);
568   if (p)
569     {
570       size_t arg_index = p - me->macro->params;
571       me->param = p;
572       if (me->args[arg_index])
573         {
574           msg (SE,
575                _("Argument %s multiply specified in call to macro %s."),
576                p->name, me->macro->name);
577           return me_error (me);
578         }
579
580       me->n_tokens++;
581       me->state = ME_EQUALS;
582       return 0;
583     }
584
585   return me_finished (me);
586 }
587
588 static int
589 me_equals (struct macro_expander *me, const struct macro_token *mt)
590 {
591   const struct token *token = &mt->token;
592   me->n_tokens++;
593
594   if (token->type == T_EQUALS)
595     {
596       me->state = ME_ARG;
597       return 0;
598     }
599
600   return me_expected (me, mt, &(struct token) { .type = T_EQUALS });
601 }
602
603 int
604 macro_expander_create (const struct macro_set *macros,
605                        const struct token *token,
606                        struct macro_expander **mep)
607 {
608   *mep = NULL;
609   if (macro_set_is_empty (macros))
610     return -1;
611   if (token->type != T_ID && token->type != T_MACRO_ID)
612     return -1;
613
614   const struct macro *macro = macro_set_find (macros, token->string.string);
615   if (!macro)
616     return -1;
617
618   struct macro_expander *me = xmalloc (sizeof *me);
619   *me = (struct macro_expander) {
620     .macros = macros,
621     .n_tokens = 1,
622     .macro = macro,
623   };
624   *mep = me;
625
626   if (!macro->n_params)
627     return 1;
628   else
629     {
630       me->state = (!macro->params[0].positional ? ME_KEYWORD
631                    : macro->params[0].arg_type == ARG_ENCLOSE ? ME_ENCLOSE
632                    : ME_ARG);
633       me->args = xcalloc (macro->n_params, sizeof *me->args);
634       me->param = macro->params;
635       return 0;
636     }
637 }
638
639 void
640 macro_expander_destroy (struct macro_expander *me)
641 {
642   if (!me)
643     return;
644
645   for (size_t i = 0; i < me->macro->n_params; i++)
646     if (me->args[i])
647       {
648         macro_tokens_uninit (me->args[i]);
649         free (me->args[i]);
650       }
651   free (me->args);
652   free (me);
653 }
654
655 /* Adds TOKEN to the collection of tokens in ME that potentially need to be
656    macro expanded.
657
658    Returns -1 if the tokens added do not actually invoke a macro.  The caller
659    should consume the first token without expanding it.
660
661    Returns 0 if the macro expander needs more tokens, for macro arguments or to
662    decide whether this is actually a macro invocation.  The caller should call
663    macro_expander_add() again with the next token.
664
665    Returns a positive number to indicate that the returned number of tokens
666    invoke a macro.  The number returned might be less than the number of tokens
667    added because it can take a few tokens of lookahead to determine whether the
668    macro invocation is finished.  The caller should call
669    macro_expander_get_expansion() to obtain the expansion. */
670 int
671 macro_expander_add (struct macro_expander *me, const struct macro_token *mt)
672 {
673   switch (me->state)
674     {
675     case ME_ERROR:
676       return -1;
677
678     case ME_ARG:
679       return me_add_arg (me, mt);
680
681     case ME_ENCLOSE:
682       return me_enclose (me, mt);
683
684     case ME_KEYWORD:
685       return me_keyword (me, mt);
686
687     case ME_EQUALS:
688       return me_equals (me, mt);
689
690     default:
691       NOT_REACHED ();
692     }
693 }
694
695 /* Each argument to a macro function is one of:
696
697        - A quoted string or other single literal token.
698
699        - An argument to the macro being expanded, e.g. !1 or a named argument.
700
701        - !*.
702
703        - A function invocation.
704
705    Each function invocation yields a character sequence to be turned into a
706    sequence of tokens.  The case where that character sequence is a single
707    quoted string is an important special case.
708 */
709 struct parse_macro_function_ctx
710   {
711     const struct macro_token *input;
712     size_t n_input;
713     int nesting_countdown;
714     const struct macro_set *macros;
715     const struct macro_expander *me;
716     struct string_map *vars;
717     bool *expand;
718   };
719
720 static void
721 macro_expand (const struct macro_tokens *,
722               int nesting_countdown, const struct macro_set *,
723               const struct macro_expander *, struct string_map *vars,
724               bool *expand, struct macro_tokens *exp);
725
726 static bool
727 expand_macro_function (struct parse_macro_function_ctx *ctx,
728                        struct string *output, size_t *input_consumed);
729
730 /* Returns true if the pair of tokens starting at offset OFS within MTS are !*,
731    false otherwise. */
732 static bool
733 is_bang_star (const struct macro_token *mts, size_t n, size_t ofs)
734 {
735   return (ofs + 1 < n
736           && mts[ofs].token.type == T_MACRO_ID
737           && ss_equals (mts[ofs].token.string, ss_cstr ("!"))
738           && mts[ofs + 1].token.type == T_ASTERISK);
739 }
740
741 static size_t
742 parse_function_arg (struct parse_macro_function_ctx *ctx,
743                     size_t i, struct string *farg)
744 {
745   const struct macro_token *tokens = ctx->input;
746   const struct token *token = &tokens[i].token;
747   if (token->type == T_MACRO_ID)
748     {
749       const struct macro_param *param = macro_find_parameter_by_name (
750         ctx->me->macro, token->string);
751       if (param)
752         {
753           size_t param_idx = param - ctx->me->macro->params;
754           const struct macro_tokens *marg = ctx->me->args[param_idx];
755           for (size_t i = 0; i < marg->n; i++)
756             {
757               if (i)
758                 ds_put_byte (farg, ' ');
759               ds_put_substring (farg, marg->mts[i].representation);
760             }
761           return 1;
762         }
763
764       if (is_bang_star (ctx->input, ctx->n_input, i))
765         {
766           for (size_t i = 0; i < ctx->me->macro->n_params; i++)
767             {
768               if (!ctx->me->macro->params[i].positional)
769                 break;
770
771               const struct macro_tokens *marg = ctx->me->args[i];
772               for (size_t j = 0; j < marg->n; j++)
773                 {
774                   if (i || j)
775                     ds_put_byte (farg, ' ');
776                   ds_put_substring (farg, marg->mts[j].representation);
777                 }
778             }
779           return 2;
780         }
781
782       if (ctx->vars)
783         {
784           const char *value = string_map_find__ (ctx->vars,
785                                                  token->string.string,
786                                                  token->string.length);
787           if (value)
788             {
789               ds_put_cstr (farg, value);
790               return 1;
791             }
792         }
793
794       struct parse_macro_function_ctx subctx = {
795         .input = &ctx->input[i],
796         .n_input = ctx->n_input - i,
797         .nesting_countdown = ctx->nesting_countdown,
798         .macros = ctx->macros,
799         .me = ctx->me,
800         .vars = ctx->vars,
801         .expand = ctx->expand,
802       };
803       size_t subinput_consumed;
804       if (expand_macro_function (&subctx, farg, &subinput_consumed))
805         return subinput_consumed;
806     }
807
808   ds_put_substring (farg, tokens[i].representation);
809   return 1;
810 }
811
812 static bool
813 parse_macro_function (struct parse_macro_function_ctx *ctx,
814                       struct string_array *args,
815                       struct substring function,
816                       int min_args, int max_args,
817                       size_t *input_consumed)
818 {
819   const struct macro_token *tokens = ctx->input;
820   size_t n_tokens = ctx->n_input;
821
822   if (!n_tokens
823       || tokens[0].token.type != T_MACRO_ID
824       || !ss_equals_case (tokens[0].token.string, function))
825     return false;
826
827   if (n_tokens < 2 || tokens[1].token.type != T_LPAREN)
828     {
829       printf ("`(' expected following %s'\n", function.string);
830       return false;
831     }
832
833   string_array_init (args);
834
835   for (size_t i = 2;; )
836     {
837       if (i >= n_tokens)
838         goto unexpected_end;
839       if (tokens[i].token.type == T_RPAREN)
840         {
841           *input_consumed = i + 1;
842           if (args->n < min_args || args->n > max_args)
843             {
844               printf ("Wrong number of arguments to %s.\n", function.string);
845               goto error;
846             }
847           return true;
848         }
849
850       struct string s = DS_EMPTY_INITIALIZER;
851       i += parse_function_arg (ctx, i, &s);
852       if (i >= n_tokens)
853         {
854           ds_destroy (&s);
855           goto unexpected_end;
856         }
857       string_array_append_nocopy (args, ds_steal_cstr (&s));
858
859       if (tokens[i].token.type == T_COMMA)
860         i++;
861       else if (tokens[i].token.type != T_RPAREN)
862         {
863           printf ("Expecting `,' or `)' in %s invocation.", function.string);
864           goto error;
865         }
866     }
867
868 unexpected_end:
869   printf ("Missing closing parenthesis in arguments to %s.\n",
870           function.string);
871   /* Fall through. */
872 error:
873   string_array_destroy (args);
874   return false;
875 }
876
877 static bool
878 unquote_string (const char *s, struct string *content)
879 {
880   struct string_lexer slex;
881   string_lexer_init (&slex, s, strlen (s), SEG_MODE_INTERACTIVE /* XXX */);
882
883   struct token token1;
884   if (!string_lexer_next (&slex, &token1))
885     return false;
886
887   if (token1.type != T_STRING)
888     {
889       token_uninit (&token1);
890       return false;
891     }
892
893   struct token token2;
894   if (string_lexer_next (&slex, &token2))
895     {
896       token_uninit (&token1);
897       token_uninit (&token2);
898       return false;
899     }
900
901   ds_put_substring (content, token1.string);
902   token_uninit (&token1);
903   return true;
904 }
905
906 static const char *
907 unquote_string_in_place (const char *s, struct string *tmp)
908 {
909   ds_init_empty (tmp);
910   return unquote_string (s, tmp) ? ds_cstr (tmp) : s;
911 }
912
913 static bool
914 parse_integer (const char *s, int *np)
915 {
916   errno = 0;
917
918   char *tail;
919   long int n = strtol (s, &tail, 10);
920   *np = n < INT_MIN ? INT_MIN : n > INT_MAX ? INT_MAX : n;
921   tail += strspn (tail, CC_SPACES);
922   return *tail == '\0' && errno != ERANGE && n == *np;
923 }
924
925 static bool
926 expand_macro_function (struct parse_macro_function_ctx *ctx,
927                        struct string *output,
928                        size_t *input_consumed)
929 {
930   struct string_array args;
931
932   if (parse_macro_function (ctx, &args, ss_cstr ("!length"), 1, 1,
933                             input_consumed))
934     ds_put_format (output, "%zu", strlen (args.strings[0]));
935   else if (parse_macro_function (ctx, &args, ss_cstr ("!blanks"), 1, 1,
936                                  input_consumed))
937     {
938       int n;
939       if (!parse_integer (args.strings[0], &n))
940         {
941           printf ("argument to !BLANKS must be non-negative integer (not \"%s\")\n", args.strings[0]);
942           string_array_destroy (&args);
943           return false;
944         }
945
946       ds_put_byte_multiple (output, ' ', n);
947     }
948   else if (parse_macro_function (ctx, &args, ss_cstr ("!concat"), 1, INT_MAX,
949                                  input_consumed))
950     {
951       for (size_t i = 0; i < args.n; i++)
952         if (!unquote_string (args.strings[i], output))
953           ds_put_cstr (output, args.strings[i]);
954     }
955   else if (parse_macro_function (ctx, &args, ss_cstr ("!head"), 1, 1,
956                                  input_consumed))
957     {
958       struct string tmp;
959       const char *s = unquote_string_in_place (args.strings[0], &tmp);
960
961       struct macro_tokens mts = { .n = 0 };
962       macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */);
963       if (mts.n > 0)
964         ds_put_substring (output, mts.mts[0].representation);
965       macro_tokens_uninit (&mts);
966       ds_destroy (&tmp);
967     }
968   else if (parse_macro_function (ctx, &args, ss_cstr ("!index"), 2, 2,
969                                  input_consumed))
970     {
971       const char *haystack = args.strings[0];
972       const char *needle = strstr (haystack, args.strings[1]);
973       ds_put_format (output, "%zu", needle ? needle - haystack + 1 : 0);
974     }
975   else if (parse_macro_function (ctx, &args, ss_cstr ("!quote"), 1, 1,
976                                  input_consumed))
977     {
978       if (unquote_string (args.strings[0], NULL))
979         ds_put_cstr (output, args.strings[0]);
980       else
981         {
982           ds_extend (output, strlen (args.strings[0]) + 2);
983           ds_put_byte (output, '\'');
984           for (const char *p = args.strings[0]; *p; p++)
985             {
986               if (*p == '\'')
987                 ds_put_byte (output, '\'');
988               ds_put_byte (output, *p);
989             }
990           ds_put_byte (output, '\'');
991         }
992     }
993   else if (parse_macro_function (ctx, &args, ss_cstr ("!substr"), 2, 3,
994                                  input_consumed))
995     {
996       int start;
997       if (!parse_integer (args.strings[1], &start) || start < 1)
998         {
999           printf ("second argument to !SUBSTR must be positive integer (not \"%s\")\n", args.strings[1]);
1000           string_array_destroy (&args);
1001           return false;
1002         }
1003
1004       int count = INT_MAX;
1005       if (args.n > 2 && (!parse_integer (args.strings[2], &count) || count < 0))
1006         {
1007           printf ("third argument to !SUBSTR must be non-negative integer (not \"%s\")\n", args.strings[1]);
1008           string_array_destroy (&args);
1009           return false;
1010         }
1011
1012       struct substring s = ss_cstr (args.strings[0]);
1013       ds_put_substring (output, ss_substr (s, start - 1, count));
1014     }
1015   else if (parse_macro_function (ctx, &args, ss_cstr ("!tail"), 1, 1,
1016                                  input_consumed))
1017     {
1018       struct string tmp;
1019       const char *s = unquote_string_in_place (args.strings[0], &tmp);
1020
1021       struct macro_tokens mts = { .n = 0 };
1022       macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */);
1023       if (mts.n > 1)
1024         {
1025           struct macro_tokens tail = { .mts = mts.mts + 1, .n = mts.n - 1 };
1026           macro_tokens_to_representation (&tail, output);
1027         }
1028       macro_tokens_uninit (&mts);
1029       ds_destroy (&tmp);
1030     }
1031   else if (parse_macro_function (ctx, &args, ss_cstr ("!unquote"), 1, 1,
1032                                  input_consumed))
1033     {
1034       if (!unquote_string (args.strings[0], output))
1035         ds_put_cstr (output, args.strings[0]);
1036     }
1037   else if (parse_macro_function (ctx, &args, ss_cstr ("!upcase"), 1, 1,
1038                                  input_consumed))
1039     {
1040       struct string tmp;
1041       const char *s = unquote_string_in_place (args.strings[0], &tmp);
1042       char *upper = utf8_to_upper (s);
1043       ds_put_cstr (output, upper);
1044       free (upper);
1045       ds_destroy (&tmp);
1046     }
1047   else if (parse_macro_function (ctx, &args, ss_cstr ("!eval"), 1, 1,
1048                                  input_consumed))
1049     {
1050       struct macro_tokens mts = { .n = 0 };
1051       macro_tokens_from_string (&mts, ss_cstr (args.strings[0]),
1052                                 SEG_MODE_INTERACTIVE /* XXX */);
1053       struct macro_tokens exp = { .n = 0 };
1054       macro_expand (&mts, ctx->nesting_countdown - 1, ctx->macros, ctx->me,
1055                     ctx->vars, ctx->expand, &exp);
1056       macro_tokens_to_representation (&exp, output);
1057       macro_tokens_uninit (&exp);
1058       macro_tokens_uninit (&mts);
1059     }
1060   else if (ctx->n_input > 0
1061            && ctx->input[0].token.type == T_MACRO_ID
1062            && ss_equals_case (ctx->input[0].token.string, ss_cstr ("!null")))
1063     {
1064       *input_consumed = 1;
1065       return true;
1066     }
1067   else
1068     return false;
1069
1070   string_array_destroy (&args);
1071   return true;
1072 }
1073
1074 struct expr_context
1075   {
1076     int nesting_countdown;
1077     const struct macro_set *macros;
1078     const struct macro_expander *me;
1079     struct string_map *vars;
1080     bool *expand;
1081   };
1082
1083 static char *macro_evaluate_or (const struct expr_context *ctx,
1084                                 const struct macro_token **tokens,
1085                                 const struct macro_token *end);
1086
1087 static char *
1088 macro_evaluate_literal (const struct expr_context *ctx,
1089                         const struct macro_token **tokens,
1090                         const struct macro_token *end)
1091 {
1092   const struct macro_token *p = *tokens;
1093   if (p >= end)
1094     return NULL;
1095   if (p->token.type == T_LPAREN)
1096     {
1097       p++;
1098       char *value = macro_evaluate_or (ctx, &p, end);
1099       if (!value)
1100         return NULL;
1101       if (p >= end || p->token.type != T_RPAREN)
1102         {
1103           free (value);
1104           printf ("expecting ')' in macro expression\n");
1105           return NULL;
1106         }
1107       p++;
1108       *tokens = p;
1109       return value;
1110     }
1111
1112   struct parse_macro_function_ctx fctx = {
1113     .input = p,
1114     .n_input = end - p,
1115     .nesting_countdown = ctx->nesting_countdown,
1116     .macros = ctx->macros,
1117     .me = ctx->me,
1118     .vars = ctx->vars,
1119     .expand = ctx->expand,
1120   };
1121   struct string function_output = DS_EMPTY_INITIALIZER;
1122   size_t function_consumed = parse_function_arg (&fctx, 0, &function_output);
1123   *tokens = p + function_consumed;
1124   return ds_steal_cstr (&function_output);
1125 }
1126
1127 /* Returns true if MT is valid as a macro operator.  Only operators written as
1128    symbols (e.g. <>) are usable in macro expressions, not operator written as
1129    letters (e.g. EQ). */
1130 static bool
1131 is_macro_operator (const struct macro_token *mt)
1132 {
1133   return (mt->representation.length > 0
1134           && !c_isalpha (mt->representation.string[0]));
1135 }
1136
1137 static enum token_type
1138 parse_relational_op (const struct macro_token *mt)
1139 {
1140   switch (mt->token.type)
1141     {
1142     case T_EQUALS:
1143       return T_EQ;
1144
1145     case T_NE:
1146     case T_LT:
1147     case T_GT:
1148     case T_LE:
1149     case T_GE:
1150       return is_macro_operator (mt) ? mt->token.type : T_STOP;
1151
1152     case T_MACRO_ID:
1153       return (ss_equals_case (mt->token.string, ss_cstr ("!EQ")) ? T_EQ
1154               : ss_equals_case (mt->token.string, ss_cstr ("!NE")) ? T_NE
1155               : ss_equals_case (mt->token.string, ss_cstr ("!LT")) ? T_LT
1156               : ss_equals_case (mt->token.string, ss_cstr ("!GT")) ? T_GT
1157               : ss_equals_case (mt->token.string, ss_cstr ("!LE")) ? T_LE
1158               : ss_equals_case (mt->token.string, ss_cstr ("!GE")) ? T_GE
1159               : T_STOP);
1160
1161     default:
1162       return T_STOP;
1163     }
1164 }
1165
1166 static char *
1167 macro_evaluate_relational (const struct expr_context *ctx,
1168                            const struct macro_token **tokens,
1169                            const struct macro_token *end)
1170 {
1171   const struct macro_token *p = *tokens;
1172   char *lhs = macro_evaluate_literal (ctx, &p, end);
1173   if (!lhs)
1174     return NULL;
1175
1176   enum token_type op = p >= end ? T_STOP : parse_relational_op (p);
1177   if (op == T_STOP)
1178     {
1179       *tokens = p;
1180       return lhs;
1181     }
1182   p++;
1183
1184   char *rhs = macro_evaluate_literal (ctx, &p, end);
1185   if (!rhs)
1186     {
1187       free (lhs);
1188       return NULL;
1189     }
1190
1191   struct string lhs_tmp, rhs_tmp;
1192   int cmp = strcmp/*XXX*/ (unquote_string_in_place (lhs, &lhs_tmp),
1193                            unquote_string_in_place (rhs, &rhs_tmp));
1194   ds_destroy (&lhs_tmp);
1195   ds_destroy (&rhs_tmp);
1196
1197   free (lhs);
1198   free (rhs);
1199
1200   bool b = (op == T_EQUALS || op == T_EQ ? !cmp
1201             : op == T_NE ? cmp
1202             : op == T_LT ? cmp < 0
1203             : op == T_GT ? cmp > 0
1204             : op == T_LE ? cmp <= 0
1205             :/*op == T_GE*/cmp >= 0);
1206
1207   *tokens = p;
1208   return xstrdup (b ? "1" : "0");
1209 }
1210
1211 static char *
1212 macro_evaluate_not (const struct expr_context *ctx,
1213                     const struct macro_token **tokens,
1214                     const struct macro_token *end)
1215 {
1216   const struct macro_token *p = *tokens;
1217
1218   unsigned int negations = 0;
1219   while (p < end
1220          && (ss_equals_case (p->representation, ss_cstr ("!NOT"))
1221              || ss_equals (p->representation, ss_cstr ("~"))))
1222     {
1223       p++;
1224       negations++;
1225     }
1226
1227   char *operand = macro_evaluate_relational (ctx, &p, end);
1228   if (!operand || !negations)
1229     {
1230       *tokens = p;
1231       return operand;
1232     }
1233
1234   bool b = strcmp (operand, "0") ^ (negations & 1);
1235   free (operand);
1236   *tokens = p;
1237   return xstrdup (b ? "1" : "0");
1238 }
1239
1240 static char *
1241 macro_evaluate_and (const struct expr_context *ctx,
1242                     const struct macro_token **tokens,
1243                     const struct macro_token *end)
1244 {
1245   const struct macro_token *p = *tokens;
1246   char *lhs = macro_evaluate_not (ctx, &p, end);
1247   if (!lhs)
1248     return NULL;
1249
1250   while (p < end
1251          && (ss_equals_case (p->representation, ss_cstr ("!AND"))
1252              || ss_equals (p->representation, ss_cstr ("&"))))
1253     {
1254       p++;
1255       char *rhs = macro_evaluate_not (ctx, &p, end);
1256       if (!rhs)
1257         {
1258           free (lhs);
1259           return NULL;
1260         }
1261
1262       bool b = strcmp (lhs, "0") && strcmp (rhs, "0");
1263       free (lhs);
1264       free (rhs);
1265       lhs = xstrdup (b ? "1" : "0");
1266     }
1267   *tokens = p;
1268   return lhs;
1269 }
1270
1271 static char *
1272 macro_evaluate_or (const struct expr_context *ctx,
1273                    const struct macro_token **tokens,
1274                    const struct macro_token *end)
1275 {
1276   const struct macro_token *p = *tokens;
1277   char *lhs = macro_evaluate_and (ctx, &p, end);
1278   if (!lhs)
1279     return NULL;
1280
1281   while (p < end
1282          && (ss_equals_case (p->representation, ss_cstr ("!OR"))
1283              || ss_equals (p->representation, ss_cstr ("|"))))
1284     {
1285       p++;
1286       char *rhs = macro_evaluate_and (ctx, &p, end);
1287       if (!rhs)
1288         {
1289           free (lhs);
1290           return NULL;
1291         }
1292
1293       bool b = strcmp (lhs, "0") || strcmp (rhs, "0");
1294       free (lhs);
1295       free (rhs);
1296       lhs = xstrdup (b ? "1" : "0");
1297     }
1298   *tokens = p;
1299   return lhs;
1300 }
1301
1302 static char *
1303 macro_evaluate_expression (const struct macro_token **tokens, size_t n_tokens,
1304                            int nesting_countdown, const struct macro_set *macros,
1305                            const struct macro_expander *me, struct string_map *vars,
1306                            bool *expand)
1307 {
1308   const struct expr_context ctx = {
1309     .nesting_countdown = nesting_countdown,
1310     .macros = macros,
1311     .me = me,
1312     .vars = vars,
1313     .expand = expand,
1314   };
1315   return macro_evaluate_or (&ctx, tokens, *tokens + n_tokens);
1316 }
1317
1318 static const struct macro_token *
1319 find_ifend_clause (const struct macro_token *p, const struct macro_token *end)
1320 {
1321   size_t nesting = 0;
1322   for (; p < end; p++)
1323     {
1324       if (p->token.type != T_MACRO_ID)
1325         continue;
1326
1327       if (ss_equals_case (p->token.string, ss_cstr ("!IF")))
1328         nesting++;
1329       else if (ss_equals_case (p->token.string, ss_cstr ("!IFEND")))
1330         {
1331           if (!nesting)
1332             return p;
1333           nesting--;
1334         }
1335       else if (ss_equals_case (p->token.string, ss_cstr ("!ELSE")) && !nesting)
1336         return p;
1337     }
1338   return NULL;
1339 }
1340
1341 static size_t
1342 macro_expand_if (const struct macro_token *tokens, size_t n_tokens,
1343                  int nesting_countdown, const struct macro_set *macros,
1344                  const struct macro_expander *me, struct string_map *vars,
1345                  bool *expand, struct macro_tokens *exp)
1346 {
1347   const struct macro_token *p = tokens;
1348   const struct macro_token *end = tokens + n_tokens;
1349
1350   if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!IF")))
1351     return 0;
1352
1353   p++;
1354   char *result = macro_evaluate_expression (&p, end - p,
1355                                             nesting_countdown, macros, me, vars,
1356                                             expand);
1357   if (!result)
1358     return 0;
1359   bool b = strcmp (result, "0");
1360   free (result);
1361
1362   if (p >= end
1363       || p->token.type != T_MACRO_ID
1364       || !ss_equals_case (p->token.string, ss_cstr ("!THEN")))
1365     {
1366       printf ("!THEN expected\n");
1367       return 0;
1368     }
1369
1370   const struct macro_token *start_then = p + 1;
1371   const struct macro_token *end_then = find_ifend_clause (start_then, end);
1372   if (!end_then)
1373     {
1374       printf ("!ELSE or !IFEND expected\n");
1375       return 0;
1376     }
1377
1378   const struct macro_token *start_else, *end_if;
1379   if (ss_equals_case (end_then->token.string, ss_cstr ("!ELSE")))
1380     {
1381       start_else = end_then + 1;
1382       end_if = find_ifend_clause (start_else, end);
1383       if (!end_if
1384           || !ss_equals_case (end_if->token.string, ss_cstr ("!IFEND")))
1385         {
1386           printf ("!IFEND expected\n");
1387           return 0;
1388         }
1389     }
1390   else
1391     {
1392       start_else = NULL;
1393       end_if = end_then;
1394     }
1395
1396   const struct macro_token *start;
1397   size_t n;
1398   if (b)
1399     {
1400       start = start_then;
1401       n = end_then - start_then;
1402     }
1403   else if (start_else)
1404     {
1405       start = start_else;
1406       n = end_if - start_else;
1407     }
1408   else
1409     {
1410       start = NULL;
1411       n = 0;
1412     }
1413
1414   if (n)
1415     {
1416       struct macro_tokens mts = {
1417         .mts = CONST_CAST (struct macro_token *, start),
1418         .n = n,
1419       };
1420       macro_expand (&mts, nesting_countdown, macros, me, vars, expand, exp);
1421     }
1422   return (end_if + 1) - tokens;
1423 }
1424
1425 static size_t
1426 macro_parse_let (const struct macro_token *tokens, size_t n_tokens,
1427                  int nesting_countdown, const struct macro_set *macros,
1428                  const struct macro_expander *me, struct string_map *vars,
1429                  bool *expand)
1430 {
1431   const struct macro_token *p = tokens;
1432   const struct macro_token *end = tokens + n_tokens;
1433
1434   if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!LET")))
1435     return 0;
1436   p++;
1437
1438   if (p >= end || p->token.type != T_MACRO_ID)
1439     {
1440       printf ("expected macro variable name following !LET\n");
1441       return 0;
1442     }
1443   const struct substring var_name = p->token.string;
1444   p++;
1445
1446   if (p >= end || p->token.type != T_EQUALS)
1447     {
1448       printf ("expected = following !LET\n");
1449       return 0;
1450     }
1451   p++;
1452
1453   char *value = macro_evaluate_expression (&p, end - p,
1454                                            nesting_countdown, macros, me, vars,
1455                                            expand);
1456   if (!value)
1457     return 0;
1458
1459   string_map_replace_nocopy (vars, ss_xstrdup (var_name), value);
1460   return p - tokens;
1461 }
1462
1463 static void
1464 macro_expand (const struct macro_tokens *mts,
1465               int nesting_countdown, const struct macro_set *macros,
1466               const struct macro_expander *me, struct string_map *vars,
1467               bool *expand, struct macro_tokens *exp)
1468 {
1469   if (nesting_countdown <= 0)
1470     {
1471       printf ("maximum nesting level exceeded\n");
1472       for (size_t i = 0; i < mts->n; i++)
1473         macro_tokens_add (exp, &mts->mts[i]);
1474       return;
1475     }
1476
1477   struct string_map own_vars = STRING_MAP_INITIALIZER (own_vars);
1478   if (!vars)
1479     vars = &own_vars;
1480   for (size_t i = 0; i < mts->n; i++)
1481     {
1482       const struct macro_token *mt = &mts->mts[i];
1483       const struct token *token = &mt->token;
1484       if (token->type == T_MACRO_ID && me)
1485         {
1486           const struct macro_param *param = macro_find_parameter_by_name (
1487             me->macro, token->string);
1488           if (param)
1489             {
1490               const struct macro_tokens *arg = me->args[param - me->macro->params];
1491               //macro_tokens_print (arg, stdout);
1492               if (*expand && param->expand_arg)
1493                 macro_expand (arg, nesting_countdown, macros, NULL, NULL,
1494                               expand, exp);
1495               else
1496                 for (size_t i = 0; i < arg->n; i++)
1497                   macro_tokens_add (exp, &arg->mts[i]);
1498               continue;
1499             }
1500
1501           if (is_bang_star (mts->mts, mts->n, i))
1502             {
1503               for (size_t j = 0; j < me->macro->n_params; j++)
1504                 {
1505                   const struct macro_param *param = &me->macro->params[j];
1506                   if (!param->positional)
1507                     break;
1508
1509                   const struct macro_tokens *arg = me->args[j];
1510                   if (*expand && param->expand_arg)
1511                     macro_expand (arg, nesting_countdown, macros, NULL, NULL,
1512                                   expand, exp);
1513                   else
1514                     for (size_t k = 0; k < arg->n; k++)
1515                       macro_tokens_add (exp, &arg->mts[k]);
1516                 }
1517               i++;
1518               continue;
1519             }
1520
1521           size_t n = macro_expand_if (&mts->mts[i], mts->n - i,
1522                                       nesting_countdown, macros, me, vars,
1523                                       expand, exp);
1524           if (n > 0)
1525             {
1526               i += n - 1;
1527               continue;
1528             }
1529         }
1530
1531       if (token->type == T_MACRO_ID && vars)
1532         {
1533           const char *value = string_map_find__ (vars, token->string.string,
1534                                                  token->string.length);
1535           if (value)
1536             {
1537               macro_tokens_from_string (exp, ss_cstr (value),
1538                                         SEG_MODE_INTERACTIVE /* XXX */);
1539               continue;
1540             }
1541         }
1542
1543       if (*expand)
1544         {
1545           struct macro_expander *subme;
1546           int retval = macro_expander_create (macros, token, &subme);
1547           for (size_t j = 1; !retval; j++)
1548             {
1549               const struct macro_token endcmd = { .token = { .type = T_ENDCMD } };
1550               retval = macro_expander_add (
1551                 subme, i + j < mts->n ? &mts->mts[i + j] : &endcmd);
1552             }
1553           if (retval > 0)
1554             {
1555               i += retval - 1;
1556               macro_expand (&subme->macro->body, nesting_countdown - 1, macros,
1557                             subme, NULL, expand, exp);
1558               macro_expander_destroy (subme);
1559               continue;
1560             }
1561
1562           macro_expander_destroy (subme);
1563         }
1564
1565       if (token->type != T_MACRO_ID)
1566         {
1567           macro_tokens_add (exp, mt);
1568           continue;
1569         }
1570
1571       struct parse_macro_function_ctx ctx = {
1572         .input = &mts->mts[i],
1573         .n_input = mts->n - i,
1574         .nesting_countdown = nesting_countdown,
1575         .macros = macros,
1576         .me = me,
1577         .vars = vars,
1578         .expand = expand,
1579       };
1580       struct string function_output = DS_EMPTY_INITIALIZER;
1581       size_t function_consumed;
1582       if (expand_macro_function (&ctx, &function_output, &function_consumed))
1583         {
1584           i += function_consumed - 1;
1585
1586           macro_tokens_from_string (exp, function_output.ss,
1587                                     SEG_MODE_INTERACTIVE /* XXX */);
1588           ds_destroy (&function_output);
1589
1590           continue;
1591         }
1592
1593       size_t n = macro_parse_let (&mts->mts[i], mts->n - i,
1594                                   nesting_countdown, macros, me, vars,
1595                                   expand);
1596       if (n > 0)
1597         {
1598           i += n - 1;
1599           continue;
1600         }
1601
1602       if (ss_equals_case (token->string, ss_cstr ("!onexpand")))
1603         *expand = true;
1604       else if (ss_equals_case (token->string, ss_cstr ("!offexpand")))
1605         *expand = false;
1606       else
1607         macro_tokens_add (exp, mt);
1608     }
1609   if (vars == &own_vars)
1610     string_map_destroy (&own_vars);
1611 }
1612
1613 void
1614 macro_expander_get_expansion (struct macro_expander *me, struct macro_tokens *exp)
1615 {
1616 #if 0
1617   for (size_t i = 0; i < me->macro->n_params; i++)
1618     {
1619       printf ("%s:\n", me->macro->params[i].name);
1620       macro_tokens_print (me->args[i], stdout);
1621     }
1622 #endif
1623
1624   bool expand = true;
1625   macro_expand (&me->macro->body, settings_get_mnest (),
1626                 me->macros, me, NULL, &expand, exp);
1627
1628 #if 0
1629   printf ("expansion:\n");
1630   macro_tokens_print (exp, stdout);
1631 #endif
1632 }
1633