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