improve macro error messages
[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   for (size_t i = 0; i < m->n_params; i++)
332     {
333       struct macro_param *p = &m->params[i];
334       free (p->name);
335
336       macro_tokens_uninit (&p->def);
337
338       switch (p->arg_type)
339         {
340         case ARG_N_TOKENS:
341           break;
342
343         case ARG_CHAREND:
344           token_uninit (&p->charend);
345           break;
346
347         case ARG_ENCLOSE:
348           token_uninit (&p->enclose[0]);
349           token_uninit (&p->enclose[1]);
350           break;
351
352         case ARG_CMDEND:
353           break;
354         }
355     }
356   free (m->params);
357   macro_tokens_uninit (&m->body);
358   free (m);
359 }
360 \f
361 struct macro_set *
362 macro_set_create (void)
363 {
364   struct macro_set *set = xmalloc (sizeof *set);
365   *set = (struct macro_set) {
366     .macros = HMAP_INITIALIZER (set->macros),
367   };
368   return set;
369 }
370
371 void
372 macro_set_destroy (struct macro_set *set)
373 {
374   if (!set)
375     return;
376
377   struct macro *macro, *next;
378   HMAP_FOR_EACH_SAFE (macro, next, struct macro, hmap_node, &set->macros)
379     {
380       hmap_delete (&set->macros, &macro->hmap_node);
381       macro_destroy (macro);
382     }
383   hmap_destroy (&set->macros);
384   free (set);
385 }
386
387 static unsigned int
388 hash_macro_name (const char *name)
389 {
390   return utf8_hash_case_string (name, 0);
391 }
392
393 static struct macro *
394 macro_set_find__ (struct macro_set *set, const char *name)
395 {
396   struct macro *macro;
397   HMAP_FOR_EACH_WITH_HASH (macro, struct macro, hmap_node,
398                            hash_macro_name (name), &set->macros)
399     if (!utf8_strcasecmp (macro->name, name))
400       return macro;
401
402   return NULL;
403 }
404
405 const struct macro *
406 macro_set_find (const struct macro_set *set, const char *name)
407 {
408   return macro_set_find__ (CONST_CAST (struct macro_set *, set), name);
409 }
410
411 /* Adds M to SET.  M replaces any existing macro with the same name.  Takes
412    ownership of M. */
413 void
414 macro_set_add (struct macro_set *set, struct macro *m)
415 {
416   struct macro *victim = macro_set_find__ (set, m->name);
417   if (victim)
418     {
419       hmap_delete (&set->macros, &victim->hmap_node);
420       macro_destroy (victim);
421     }
422
423   hmap_insert (&set->macros, &m->hmap_node, hash_macro_name (m->name));
424 }
425 \f
426 enum me_state
427   {
428     /* Error state. */
429     ME_ERROR,
430
431     /* Accumulating tokens in me->params toward the end of any type of
432        argument. */
433     ME_ARG,
434
435     /* Expecting the opening delimiter of an ARG_ENCLOSE argument. */
436     ME_ENCLOSE,
437
438     /* Expecting a keyword for a keyword argument. */
439     ME_KEYWORD,
440
441     /* Expecting an equal sign for a keyword argument. */
442     ME_EQUALS,
443   };
444
445
446 struct macro_expander
447   {
448     const struct macro_set *macros;
449
450     enum me_state state;
451     size_t n_tokens;
452
453     const struct macro *macro;
454     struct macro_tokens **args;
455     const struct macro_param *param;
456   };
457
458 static int
459 me_finished (struct macro_expander *me)
460 {
461   for (size_t i = 0; i < me->macro->n_params; i++)
462     if (!me->args[i])
463       {
464         me->args[i] = xmalloc (sizeof *me->args[i]);
465         macro_tokens_copy (me->args[i], &me->macro->params[i].def);
466       }
467   return me->n_tokens;
468 }
469
470 static int
471 me_next_arg (struct macro_expander *me)
472 {
473   if (!me->param)
474     {
475       assert (!me->macro->n_params);
476       return me_finished (me);
477     }
478   else if (me->param->positional)
479     {
480       me->param++;
481       if (me->param >= &me->macro->params[me->macro->n_params])
482         return me_finished (me);
483       else
484         {
485           me->state = (!me->param->positional ? ME_KEYWORD
486                        : me->param->arg_type == ARG_ENCLOSE ? ME_ENCLOSE
487                        : ME_ARG);
488           return 0;
489         }
490     }
491   else
492     {
493       for (size_t i = 0; i < me->macro->n_params; i++)
494         if (!me->args[i])
495           {
496             me->state = ME_KEYWORD;
497             return 0;
498           }
499       return me_finished (me);
500     }
501 }
502
503 static int
504 me_error (struct macro_expander *me)
505 {
506   me->state = ME_ERROR;
507   return -1;
508 }
509
510 static int
511 me_add_arg (struct macro_expander *me, const struct macro_token *mt)
512 {
513   const struct macro_param *p = me->param;
514
515   const struct token *token = &mt->token;
516   if ((token->type == T_ENDCMD || token->type == T_STOP)
517       && p->arg_type != ARG_CMDEND)
518     {
519       msg (SE, _("Unexpected end of command reading argument %s "
520                  "to macro %s."), me->param->name, me->macro->name);
521
522       return me_error (me);
523     }
524
525   me->n_tokens++;
526
527   struct macro_tokens **argp = &me->args[p - me->macro->params];
528   if (!*argp)
529     *argp = xzalloc (sizeof **argp);
530   struct macro_tokens *arg = *argp;
531   if (p->arg_type == ARG_N_TOKENS)
532     {
533       macro_tokens_add (arg, mt);
534       if (arg->n >= p->n_tokens)
535         return me_next_arg (me);
536       return 0;
537     }
538   else if (p->arg_type == ARG_CMDEND)
539     {
540       if (token->type == T_ENDCMD || token->type == T_STOP)
541         return me_next_arg (me);
542       macro_tokens_add (arg, mt);
543       return 0;
544     }
545   else
546     {
547       const struct token *end
548         = p->arg_type == ARG_CHAREND ? &p->charend : &p->enclose[1];
549       if (token_equal (token, end))
550         return me_next_arg (me);
551       macro_tokens_add (arg, mt);
552       return 0;
553     }
554 }
555
556 static int
557 me_expected (struct macro_expander *me, const struct macro_token *actual,
558              const struct token *expected)
559 {
560   const struct substring actual_s
561     = (actual->representation.length ? actual->representation
562        : ss_cstr (_("<end of input>")));
563   char *expected_s = token_to_string (expected);
564   msg (SE, _("Found `%.*s' while expecting `%s' reading argument %s "
565              "to macro %s."),
566        (int) actual_s.length, actual_s.string, expected_s,
567        me->param->name, me->macro->name);
568   free (expected_s);
569
570   return me_error (me);
571 }
572
573 static int
574 me_enclose (struct macro_expander *me, const struct macro_token *mt)
575 {
576   const struct token *token = &mt->token;
577   me->n_tokens++;
578
579   if (token_equal (&me->param->enclose[0], token))
580     {
581       me->state = ME_ARG;
582       return 0;
583     }
584
585   return me_expected (me, mt, &me->param->enclose[0]);
586 }
587
588 static const struct macro_param *
589 macro_find_parameter_by_name (const struct macro *m, struct substring name)
590 {
591   ss_ltrim (&name, ss_cstr ("!"));
592
593   for (size_t i = 0; i < m->n_params; i++)
594     {
595       const struct macro_param *p = &m->params[i];
596       struct substring p_name = ss_cstr (p->name + 1);
597       if (!utf8_strncasecmp (p_name.string, p_name.length,
598                              name.string, name.length))
599         return p;
600     }
601   return NULL;
602 }
603
604 static int
605 me_keyword (struct macro_expander *me, const struct macro_token *mt)
606 {
607   const struct token *token = &mt->token;
608   if (token->type != T_ID)
609     return me_finished (me);
610
611   const struct macro_param *p = macro_find_parameter_by_name (me->macro,
612                                                               token->string);
613   if (p)
614     {
615       size_t arg_index = p - me->macro->params;
616       me->param = p;
617       if (me->args[arg_index])
618         {
619           msg (SE,
620                _("Argument %s multiply specified in call to macro %s."),
621                p->name, me->macro->name);
622           return me_error (me);
623         }
624
625       me->n_tokens++;
626       me->state = ME_EQUALS;
627       return 0;
628     }
629
630   return me_finished (me);
631 }
632
633 static int
634 me_equals (struct macro_expander *me, const struct macro_token *mt)
635 {
636   const struct token *token = &mt->token;
637   me->n_tokens++;
638
639   if (token->type == T_EQUALS)
640     {
641       me->state = ME_ARG;
642       return 0;
643     }
644
645   return me_expected (me, mt, &(struct token) { .type = T_EQUALS });
646 }
647
648 int
649 macro_expander_create (const struct macro_set *macros,
650                        const struct token *token,
651                        struct macro_expander **mep)
652 {
653   *mep = NULL;
654   if (macro_set_is_empty (macros))
655     return -1;
656   if (token->type != T_ID && token->type != T_MACRO_ID)
657     return -1;
658
659   const struct macro *macro = macro_set_find (macros, token->string.string);
660   if (!macro)
661     return -1;
662
663   struct macro_expander *me = xmalloc (sizeof *me);
664   *me = (struct macro_expander) {
665     .macros = macros,
666     .n_tokens = 1,
667     .macro = macro,
668   };
669   *mep = me;
670
671   if (!macro->n_params)
672     return 1;
673   else
674     {
675       me->state = (!macro->params[0].positional ? ME_KEYWORD
676                    : macro->params[0].arg_type == ARG_ENCLOSE ? ME_ENCLOSE
677                    : ME_ARG);
678       me->args = xcalloc (macro->n_params, sizeof *me->args);
679       me->param = macro->params;
680       return 0;
681     }
682 }
683
684 void
685 macro_expander_destroy (struct macro_expander *me)
686 {
687   if (!me)
688     return;
689
690   for (size_t i = 0; i < me->macro->n_params; i++)
691     if (me->args[i])
692       {
693         macro_tokens_uninit (me->args[i]);
694         free (me->args[i]);
695       }
696   free (me->args);
697   free (me);
698 }
699
700 /* Adds TOKEN to the collection of tokens in ME that potentially need to be
701    macro expanded.
702
703    Returns -1 if the tokens added do not actually invoke a macro.  The caller
704    should consume the first token without expanding it.
705
706    Returns 0 if the macro expander needs more tokens, for macro arguments or to
707    decide whether this is actually a macro invocation.  The caller should call
708    macro_expander_add() again with the next token.
709
710    Returns a positive number to indicate that the returned number of tokens
711    invoke a macro.  The number returned might be less than the number of tokens
712    added because it can take a few tokens of lookahead to determine whether the
713    macro invocation is finished.  The caller should call
714    macro_expander_get_expansion() to obtain the expansion. */
715 int
716 macro_expander_add (struct macro_expander *me, const struct macro_token *mt)
717 {
718   switch (me->state)
719     {
720     case ME_ERROR:
721       return -1;
722
723     case ME_ARG:
724       return me_add_arg (me, mt);
725
726     case ME_ENCLOSE:
727       return me_enclose (me, mt);
728
729     case ME_KEYWORD:
730       return me_keyword (me, mt);
731
732     case ME_EQUALS:
733       return me_equals (me, mt);
734
735     default:
736       NOT_REACHED ();
737     }
738 }
739
740 /* Each argument to a macro function is one of:
741
742        - A quoted string or other single literal token.
743
744        - An argument to the macro being expanded, e.g. !1 or a named argument.
745
746        - !*.
747
748        - A function invocation.
749
750    Each function invocation yields a character sequence to be turned into a
751    sequence of tokens.  The case where that character sequence is a single
752    quoted string is an important special case.
753 */
754 struct parse_macro_function_ctx
755   {
756     const struct macro_token *input;
757     size_t n_input;
758     int nesting_countdown;
759     const struct macro_set *macros;
760     const struct macro_expander *me;
761     struct string_map *vars;
762     bool *expand;
763   };
764
765 static void
766 macro_expand (const struct macro_tokens *,
767               int nesting_countdown, const struct macro_set *,
768               const struct macro_expander *, struct string_map *vars,
769               bool *expand, bool *break_, struct macro_tokens *exp);
770
771 static bool
772 expand_macro_function (struct parse_macro_function_ctx *ctx,
773                        struct string *output, size_t *input_consumed);
774
775 /* Returns true if the pair of tokens starting at offset OFS within MTS are !*,
776    false otherwise. */
777 static bool
778 is_bang_star (const struct macro_token *mts, size_t n, size_t ofs)
779 {
780   return (ofs + 1 < n
781           && mts[ofs].token.type == T_MACRO_ID
782           && ss_equals (mts[ofs].token.string, ss_cstr ("!"))
783           && mts[ofs + 1].token.type == T_ASTERISK);
784 }
785
786 static size_t
787 parse_function_arg (struct parse_macro_function_ctx *ctx,
788                     size_t i, struct string *farg)
789 {
790   const struct macro_token *tokens = ctx->input;
791   const struct token *token = &tokens[i].token;
792   if (token->type == T_MACRO_ID)
793     {
794       const struct macro_param *param = macro_find_parameter_by_name (
795         ctx->me->macro, token->string);
796       if (param)
797         {
798           size_t param_idx = param - ctx->me->macro->params;
799           const struct macro_tokens *marg = ctx->me->args[param_idx];
800           for (size_t i = 0; i < marg->n; i++)
801             {
802               if (i)
803                 ds_put_byte (farg, ' ');
804               ds_put_substring (farg, marg->mts[i].representation);
805             }
806           return 1;
807         }
808
809       if (is_bang_star (ctx->input, ctx->n_input, i))
810         {
811           for (size_t i = 0; i < ctx->me->macro->n_params; i++)
812             {
813               if (!ctx->me->macro->params[i].positional)
814                 break;
815
816               const struct macro_tokens *marg = ctx->me->args[i];
817               for (size_t j = 0; j < marg->n; j++)
818                 {
819                   if (i || j)
820                     ds_put_byte (farg, ' ');
821                   ds_put_substring (farg, marg->mts[j].representation);
822                 }
823             }
824           return 2;
825         }
826
827       if (ctx->vars)
828         {
829           const char *value = string_map_find__ (ctx->vars,
830                                                  token->string.string,
831                                                  token->string.length);
832           if (value)
833             {
834               ds_put_cstr (farg, value);
835               return 1;
836             }
837         }
838
839       struct parse_macro_function_ctx subctx = {
840         .input = &ctx->input[i],
841         .n_input = ctx->n_input - i,
842         .nesting_countdown = ctx->nesting_countdown,
843         .macros = ctx->macros,
844         .me = ctx->me,
845         .vars = ctx->vars,
846         .expand = ctx->expand,
847       };
848       size_t subinput_consumed;
849       if (expand_macro_function (&subctx, farg, &subinput_consumed))
850         return subinput_consumed;
851     }
852
853   ds_put_substring (farg, tokens[i].representation);
854   return 1;
855 }
856
857 static bool
858 parse_macro_function (struct parse_macro_function_ctx *ctx,
859                       struct string_array *args,
860                       struct substring function,
861                       int min_args, int max_args,
862                       size_t *input_consumed)
863 {
864   const struct macro_token *tokens = ctx->input;
865   size_t n_tokens = ctx->n_input;
866
867   if (!n_tokens
868       || tokens[0].token.type != T_MACRO_ID
869       || !ss_equals_case (tokens[0].token.string, function)) /* XXX abbrevs allowed */
870     return false;
871
872   if (n_tokens < 2 || tokens[1].token.type != T_LPAREN)
873     {
874       printf ("`(' expected following %s'\n", function.string);
875       return false;
876     }
877
878   string_array_init (args);
879
880   for (size_t i = 2;; )
881     {
882       if (i >= n_tokens)
883         goto unexpected_end;
884       if (tokens[i].token.type == T_RPAREN)
885         {
886           *input_consumed = i + 1;
887           if (args->n < min_args || args->n > max_args)
888             {
889               printf ("Wrong number of arguments to %s.\n", function.string);
890               goto error;
891             }
892           return true;
893         }
894
895       struct string s = DS_EMPTY_INITIALIZER;
896       i += parse_function_arg (ctx, i, &s);
897       if (i >= n_tokens)
898         {
899           ds_destroy (&s);
900           goto unexpected_end;
901         }
902       string_array_append_nocopy (args, ds_steal_cstr (&s));
903
904       if (tokens[i].token.type == T_COMMA)
905         i++;
906       else if (tokens[i].token.type != T_RPAREN)
907         {
908           printf ("Expecting `,' or `)' in %s invocation.", function.string);
909           goto error;
910         }
911     }
912
913 unexpected_end:
914   printf ("Missing closing parenthesis in arguments to %s.\n",
915           function.string);
916   /* Fall through. */
917 error:
918   string_array_destroy (args);
919   return false;
920 }
921
922 static bool
923 unquote_string (const char *s, struct string *content)
924 {
925   struct string_lexer slex;
926   string_lexer_init (&slex, s, strlen (s), SEG_MODE_INTERACTIVE /* XXX */,
927                      true);
928
929   struct token token1;
930   if (!string_lexer_next (&slex, &token1))
931     return false;
932
933   if (token1.type != T_STRING)
934     {
935       token_uninit (&token1);
936       return false;
937     }
938
939   struct token token2;
940   if (string_lexer_next (&slex, &token2))
941     {
942       token_uninit (&token1);
943       token_uninit (&token2);
944       return false;
945     }
946
947   ds_put_substring (content, token1.string);
948   token_uninit (&token1);
949   return true;
950 }
951
952 static const char *
953 unquote_string_in_place (const char *s, struct string *tmp)
954 {
955   ds_init_empty (tmp);
956   return unquote_string (s, tmp) ? ds_cstr (tmp) : s;
957 }
958
959 static bool
960 parse_integer (const char *s, int *np)
961 {
962   errno = 0;
963
964   char *tail;
965   long int n = strtol (s, &tail, 10);
966   *np = n < INT_MIN ? INT_MIN : n > INT_MAX ? INT_MAX : n;
967   tail += strspn (tail, CC_SPACES);
968   return *tail == '\0' && errno != ERANGE && n == *np;
969 }
970
971 static bool
972 expand_macro_function (struct parse_macro_function_ctx *ctx,
973                        struct string *output,
974                        size_t *input_consumed)
975 {
976   struct string_array args;
977
978   if (parse_macro_function (ctx, &args, ss_cstr ("!length"), 1, 1,
979                             input_consumed))
980     ds_put_format (output, "%zu", strlen (args.strings[0]));
981   else if (parse_macro_function (ctx, &args, ss_cstr ("!blanks"), 1, 1,
982                                  input_consumed))
983     {
984       int n;
985       if (!parse_integer (args.strings[0], &n))
986         {
987           printf ("argument to !BLANKS must be non-negative integer (not \"%s\")\n", args.strings[0]);
988           string_array_destroy (&args);
989           return false;
990         }
991
992       ds_put_byte_multiple (output, ' ', n);
993     }
994   else if (parse_macro_function (ctx, &args, ss_cstr ("!concat"), 1, INT_MAX,
995                                  input_consumed))
996     {
997       for (size_t i = 0; i < args.n; i++)
998         if (!unquote_string (args.strings[i], output))
999           ds_put_cstr (output, args.strings[i]);
1000     }
1001   else if (parse_macro_function (ctx, &args, ss_cstr ("!head"), 1, 1,
1002                                  input_consumed))
1003     {
1004       struct string tmp;
1005       const char *s = unquote_string_in_place (args.strings[0], &tmp);
1006
1007       struct macro_tokens mts = { .n = 0 };
1008       macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */);
1009       if (mts.n > 0)
1010         ds_put_substring (output, mts.mts[0].representation);
1011       macro_tokens_uninit (&mts);
1012       ds_destroy (&tmp);
1013     }
1014   else if (parse_macro_function (ctx, &args, ss_cstr ("!index"), 2, 2,
1015                                  input_consumed))
1016     {
1017       const char *haystack = args.strings[0];
1018       const char *needle = strstr (haystack, args.strings[1]);
1019       ds_put_format (output, "%zu", needle ? needle - haystack + 1 : 0);
1020     }
1021   else if (parse_macro_function (ctx, &args, ss_cstr ("!quote"), 1, 1,
1022                                  input_consumed))
1023     {
1024       if (unquote_string (args.strings[0], NULL))
1025         ds_put_cstr (output, args.strings[0]);
1026       else
1027         {
1028           ds_extend (output, strlen (args.strings[0]) + 2);
1029           ds_put_byte (output, '\'');
1030           for (const char *p = args.strings[0]; *p; p++)
1031             {
1032               if (*p == '\'')
1033                 ds_put_byte (output, '\'');
1034               ds_put_byte (output, *p);
1035             }
1036           ds_put_byte (output, '\'');
1037         }
1038     }
1039   else if (parse_macro_function (ctx, &args, ss_cstr ("!substr"), 2, 3,
1040                                  input_consumed))
1041     {
1042       int start;
1043       if (!parse_integer (args.strings[1], &start) || start < 1)
1044         {
1045           printf ("second argument to !SUBSTR must be positive integer (not \"%s\")\n", args.strings[1]);
1046           string_array_destroy (&args);
1047           return false;
1048         }
1049
1050       int count = INT_MAX;
1051       if (args.n > 2 && (!parse_integer (args.strings[2], &count) || count < 0))
1052         {
1053           printf ("third argument to !SUBSTR must be non-negative integer (not \"%s\")\n", args.strings[1]);
1054           string_array_destroy (&args);
1055           return false;
1056         }
1057
1058       struct substring s = ss_cstr (args.strings[0]);
1059       ds_put_substring (output, ss_substr (s, start - 1, count));
1060     }
1061   else if (parse_macro_function (ctx, &args, ss_cstr ("!tail"), 1, 1,
1062                                  input_consumed))
1063     {
1064       struct string tmp;
1065       const char *s = unquote_string_in_place (args.strings[0], &tmp);
1066
1067       struct macro_tokens mts = { .n = 0 };
1068       macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */);
1069       if (mts.n > 1)
1070         {
1071           struct macro_tokens tail = { .mts = mts.mts + 1, .n = mts.n - 1 };
1072           macro_tokens_to_representation (&tail, output, NULL, NULL);
1073         }
1074       macro_tokens_uninit (&mts);
1075       ds_destroy (&tmp);
1076     }
1077   else if (parse_macro_function (ctx, &args, ss_cstr ("!unquote"), 1, 1,
1078                                  input_consumed))
1079     {
1080       if (!unquote_string (args.strings[0], output))
1081         ds_put_cstr (output, args.strings[0]);
1082     }
1083   else if (parse_macro_function (ctx, &args, ss_cstr ("!upcase"), 1, 1,
1084                                  input_consumed))
1085     {
1086       struct string tmp;
1087       const char *s = unquote_string_in_place (args.strings[0], &tmp);
1088       char *upper = utf8_to_upper (s);
1089       ds_put_cstr (output, upper);
1090       free (upper);
1091       ds_destroy (&tmp);
1092     }
1093   else if (parse_macro_function (ctx, &args, ss_cstr ("!eval"), 1, 1,
1094                                  input_consumed))
1095     {
1096       struct macro_tokens mts = { .n = 0 };
1097       macro_tokens_from_string (&mts, ss_cstr (args.strings[0]),
1098                                 SEG_MODE_INTERACTIVE /* XXX */);
1099       struct macro_tokens exp = { .n = 0 };
1100       macro_expand (&mts, ctx->nesting_countdown - 1, ctx->macros, ctx->me,
1101                     ctx->vars, ctx->expand, NULL, &exp);
1102       macro_tokens_to_representation (&exp, output, NULL, NULL);
1103       macro_tokens_uninit (&exp);
1104       macro_tokens_uninit (&mts);
1105     }
1106   else if (ctx->n_input > 0
1107            && ctx->input[0].token.type == T_MACRO_ID
1108            && ss_equals_case (ctx->input[0].token.string, ss_cstr ("!null")))
1109     {
1110       *input_consumed = 1;
1111       return true;
1112     }
1113   else
1114     return false;
1115
1116   string_array_destroy (&args);
1117   return true;
1118 }
1119
1120 struct expr_context
1121   {
1122     int nesting_countdown;
1123     const struct macro_set *macros;
1124     const struct macro_expander *me;
1125     struct string_map *vars;
1126     bool *expand;
1127   };
1128
1129 static char *macro_evaluate_or (const struct expr_context *ctx,
1130                                 const struct macro_token **tokens,
1131                                 const struct macro_token *end);
1132
1133 static char *
1134 macro_evaluate_literal (const struct expr_context *ctx,
1135                         const struct macro_token **tokens,
1136                         const struct macro_token *end)
1137 {
1138   const struct macro_token *p = *tokens;
1139   if (p >= end)
1140     return NULL;
1141   if (p->token.type == T_LPAREN)
1142     {
1143       p++;
1144       char *value = macro_evaluate_or (ctx, &p, end);
1145       if (!value)
1146         return NULL;
1147       if (p >= end || p->token.type != T_RPAREN)
1148         {
1149           free (value);
1150           printf ("expecting ')' in macro expression\n");
1151           return NULL;
1152         }
1153       p++;
1154       *tokens = p;
1155       return value;
1156     }
1157
1158   struct parse_macro_function_ctx fctx = {
1159     .input = p,
1160     .n_input = end - p,
1161     .nesting_countdown = ctx->nesting_countdown,
1162     .macros = ctx->macros,
1163     .me = ctx->me,
1164     .vars = ctx->vars,
1165     .expand = ctx->expand,
1166   };
1167   struct string function_output = DS_EMPTY_INITIALIZER;
1168   size_t function_consumed = parse_function_arg (&fctx, 0, &function_output);
1169   struct string unquoted = DS_EMPTY_INITIALIZER;
1170   if (unquote_string (ds_cstr (&function_output), &unquoted))
1171     {
1172       ds_swap (&function_output, &unquoted);
1173       ds_destroy (&unquoted);
1174     }
1175   *tokens = p + function_consumed;
1176   return ds_steal_cstr (&function_output);
1177 }
1178
1179 /* Returns true if MT is valid as a macro operator.  Only operators written as
1180    symbols (e.g. <>) are usable in macro expressions, not operator written as
1181    letters (e.g. EQ). */
1182 static bool
1183 is_macro_operator (const struct macro_token *mt)
1184 {
1185   return (mt->representation.length > 0
1186           && !c_isalpha (mt->representation.string[0]));
1187 }
1188
1189 static enum token_type
1190 parse_relational_op (const struct macro_token *mt)
1191 {
1192   switch (mt->token.type)
1193     {
1194     case T_EQUALS:
1195       return T_EQ;
1196
1197     case T_NE:
1198     case T_LT:
1199     case T_GT:
1200     case T_LE:
1201     case T_GE:
1202       return is_macro_operator (mt) ? mt->token.type : T_STOP;
1203
1204     case T_MACRO_ID:
1205       return (ss_equals_case (mt->token.string, ss_cstr ("!EQ")) ? T_EQ
1206               : ss_equals_case (mt->token.string, ss_cstr ("!NE")) ? T_NE
1207               : ss_equals_case (mt->token.string, ss_cstr ("!LT")) ? T_LT
1208               : ss_equals_case (mt->token.string, ss_cstr ("!GT")) ? T_GT
1209               : ss_equals_case (mt->token.string, ss_cstr ("!LE")) ? T_LE
1210               : ss_equals_case (mt->token.string, ss_cstr ("!GE")) ? T_GE
1211               : T_STOP);
1212
1213     default:
1214       return T_STOP;
1215     }
1216 }
1217
1218 static char *
1219 macro_evaluate_relational (const struct expr_context *ctx,
1220                            const struct macro_token **tokens,
1221                            const struct macro_token *end)
1222 {
1223   const struct macro_token *p = *tokens;
1224   char *lhs = macro_evaluate_literal (ctx, &p, end);
1225   if (!lhs)
1226     return NULL;
1227
1228   enum token_type op = p >= end ? T_STOP : parse_relational_op (p);
1229   if (op == T_STOP)
1230     {
1231       *tokens = p;
1232       return lhs;
1233     }
1234   p++;
1235
1236   char *rhs = macro_evaluate_literal (ctx, &p, end);
1237   if (!rhs)
1238     {
1239       free (lhs);
1240       return NULL;
1241     }
1242
1243   struct string lhs_tmp, rhs_tmp;
1244   int cmp = strcmp/*XXX*/ (unquote_string_in_place (lhs, &lhs_tmp),
1245                            unquote_string_in_place (rhs, &rhs_tmp));
1246   ds_destroy (&lhs_tmp);
1247   ds_destroy (&rhs_tmp);
1248
1249   free (lhs);
1250   free (rhs);
1251
1252   bool b = (op == T_EQUALS || op == T_EQ ? !cmp
1253             : op == T_NE ? cmp
1254             : op == T_LT ? cmp < 0
1255             : op == T_GT ? cmp > 0
1256             : op == T_LE ? cmp <= 0
1257             :/*op == T_GE*/cmp >= 0);
1258
1259   *tokens = p;
1260   return xstrdup (b ? "1" : "0");
1261 }
1262
1263 static char *
1264 macro_evaluate_not (const struct expr_context *ctx,
1265                     const struct macro_token **tokens,
1266                     const struct macro_token *end)
1267 {
1268   const struct macro_token *p = *tokens;
1269
1270   unsigned int negations = 0;
1271   while (p < end
1272          && (ss_equals_case (p->representation, ss_cstr ("!NOT"))
1273              || ss_equals (p->representation, ss_cstr ("~"))))
1274     {
1275       p++;
1276       negations++;
1277     }
1278
1279   char *operand = macro_evaluate_relational (ctx, &p, end);
1280   if (!operand || !negations)
1281     {
1282       *tokens = p;
1283       return operand;
1284     }
1285
1286   bool b = strcmp (operand, "0") ^ (negations & 1);
1287   free (operand);
1288   *tokens = p;
1289   return xstrdup (b ? "1" : "0");
1290 }
1291
1292 static char *
1293 macro_evaluate_and (const struct expr_context *ctx,
1294                     const struct macro_token **tokens,
1295                     const struct macro_token *end)
1296 {
1297   const struct macro_token *p = *tokens;
1298   char *lhs = macro_evaluate_not (ctx, &p, end);
1299   if (!lhs)
1300     return NULL;
1301
1302   while (p < end
1303          && (ss_equals_case (p->representation, ss_cstr ("!AND"))
1304              || ss_equals (p->representation, ss_cstr ("&"))))
1305     {
1306       p++;
1307       char *rhs = macro_evaluate_not (ctx, &p, end);
1308       if (!rhs)
1309         {
1310           free (lhs);
1311           return NULL;
1312         }
1313
1314       bool b = strcmp (lhs, "0") && strcmp (rhs, "0");
1315       free (lhs);
1316       free (rhs);
1317       lhs = xstrdup (b ? "1" : "0");
1318     }
1319   *tokens = p;
1320   return lhs;
1321 }
1322
1323 static char *
1324 macro_evaluate_or (const struct expr_context *ctx,
1325                    const struct macro_token **tokens,
1326                    const struct macro_token *end)
1327 {
1328   const struct macro_token *p = *tokens;
1329   char *lhs = macro_evaluate_and (ctx, &p, end);
1330   if (!lhs)
1331     return NULL;
1332
1333   while (p < end
1334          && (ss_equals_case (p->representation, ss_cstr ("!OR"))
1335              || ss_equals (p->representation, ss_cstr ("|"))))
1336     {
1337       p++;
1338       char *rhs = macro_evaluate_and (ctx, &p, end);
1339       if (!rhs)
1340         {
1341           free (lhs);
1342           return NULL;
1343         }
1344
1345       bool b = strcmp (lhs, "0") || strcmp (rhs, "0");
1346       free (lhs);
1347       free (rhs);
1348       lhs = xstrdup (b ? "1" : "0");
1349     }
1350   *tokens = p;
1351   return lhs;
1352 }
1353
1354 static char *
1355 macro_evaluate_expression (const struct macro_token **tokens, size_t n_tokens,
1356                            int nesting_countdown, const struct macro_set *macros,
1357                            const struct macro_expander *me, struct string_map *vars,
1358                            bool *expand)
1359 {
1360   const struct expr_context ctx = {
1361     .nesting_countdown = nesting_countdown,
1362     .macros = macros,
1363     .me = me,
1364     .vars = vars,
1365     .expand = expand,
1366   };
1367   return macro_evaluate_or (&ctx, tokens, *tokens + n_tokens);
1368 }
1369
1370 static bool
1371 macro_evaluate_number (const struct macro_token **tokens, size_t n_tokens,
1372                        int nesting_countdown, const struct macro_set *macros,
1373                        const struct macro_expander *me, struct string_map *vars,
1374                        bool *expand, double *number)
1375 {
1376   char *s = macro_evaluate_expression (tokens, n_tokens, nesting_countdown,
1377                                        macros, me, vars, expand);
1378   if (!s)
1379     return false;
1380
1381   struct macro_tokens mts = { .n = 0 };
1382   macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */);
1383   if (mts.n != 1 || !token_is_number (&mts.mts[0].token))
1384     {
1385       macro_tokens_print (&mts, stdout);
1386       printf ("expression must evaluate to a number (not %s)\n", s);
1387       free (s);
1388       macro_tokens_uninit (&mts);
1389       return false;
1390     }
1391
1392   *number = token_number (&mts.mts[0].token);
1393   free (s);
1394   macro_tokens_uninit (&mts);
1395   return true;
1396 }
1397
1398 static const struct macro_token *
1399 find_ifend_clause (const struct macro_token *p, const struct macro_token *end)
1400 {
1401   size_t nesting = 0;
1402   for (; p < end; p++)
1403     {
1404       if (p->token.type != T_MACRO_ID)
1405         continue;
1406
1407       if (ss_equals_case (p->token.string, ss_cstr ("!IF")))
1408         nesting++;
1409       else if (ss_equals_case (p->token.string, ss_cstr ("!IFEND")))
1410         {
1411           if (!nesting)
1412             return p;
1413           nesting--;
1414         }
1415       else if (ss_equals_case (p->token.string, ss_cstr ("!ELSE")) && !nesting)
1416         return p;
1417     }
1418   return NULL;
1419 }
1420
1421 static size_t
1422 macro_expand_if (const struct macro_token *tokens, size_t n_tokens,
1423                  int nesting_countdown, const struct macro_set *macros,
1424                  const struct macro_expander *me, struct string_map *vars,
1425                  bool *expand, bool *break_, struct macro_tokens *exp)
1426 {
1427   const struct macro_token *p = tokens;
1428   const struct macro_token *end = tokens + n_tokens;
1429
1430   if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!IF")))
1431     return 0;
1432
1433   p++;
1434   char *result = macro_evaluate_expression (&p, end - p,
1435                                             nesting_countdown, macros, me, vars,
1436                                             expand);
1437   if (!result)
1438     return 0;
1439   bool b = strcmp (result, "0");
1440   free (result);
1441
1442   if (p >= end
1443       || p->token.type != T_MACRO_ID
1444       || !ss_equals_case (p->token.string, ss_cstr ("!THEN")))
1445     {
1446       printf ("!THEN expected\n");
1447       return 0;
1448     }
1449
1450   const struct macro_token *start_then = p + 1;
1451   const struct macro_token *end_then = find_ifend_clause (start_then, end);
1452   if (!end_then)
1453     {
1454       printf ("!ELSE or !IFEND expected\n");
1455       return 0;
1456     }
1457
1458   const struct macro_token *start_else, *end_if;
1459   if (ss_equals_case (end_then->token.string, ss_cstr ("!ELSE")))
1460     {
1461       start_else = end_then + 1;
1462       end_if = find_ifend_clause (start_else, end);
1463       if (!end_if
1464           || !ss_equals_case (end_if->token.string, ss_cstr ("!IFEND")))
1465         {
1466           printf ("!IFEND expected\n");
1467           return 0;
1468         }
1469     }
1470   else
1471     {
1472       start_else = NULL;
1473       end_if = end_then;
1474     }
1475
1476   const struct macro_token *start;
1477   size_t n;
1478   if (b)
1479     {
1480       start = start_then;
1481       n = end_then - start_then;
1482     }
1483   else if (start_else)
1484     {
1485       start = start_else;
1486       n = end_if - start_else;
1487     }
1488   else
1489     {
1490       start = NULL;
1491       n = 0;
1492     }
1493
1494   if (n)
1495     {
1496       struct macro_tokens mts = {
1497         .mts = CONST_CAST (struct macro_token *, start),
1498         .n = n,
1499       };
1500       macro_expand (&mts, nesting_countdown, macros, me, vars, expand,
1501                     break_, exp);
1502     }
1503   return (end_if + 1) - tokens;
1504 }
1505
1506 static size_t
1507 macro_parse_let (const struct macro_token *tokens, size_t n_tokens,
1508                  int nesting_countdown, const struct macro_set *macros,
1509                  const struct macro_expander *me, struct string_map *vars,
1510                  bool *expand)
1511 {
1512   const struct macro_token *p = tokens;
1513   const struct macro_token *end = tokens + n_tokens;
1514
1515   if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!LET")))
1516     return 0;
1517   p++;
1518
1519   if (p >= end || p->token.type != T_MACRO_ID)
1520     {
1521       printf ("expected macro variable name following !LET\n");
1522       return 0;
1523     }
1524   const struct substring var_name = p->token.string;
1525   if (is_macro_keyword (var_name)
1526       || macro_find_parameter_by_name (me->macro, var_name))
1527     {
1528       printf ("cannot use argument name or macro keyword as !LET variable\n");
1529       return 0;
1530     }
1531   p++;
1532
1533   if (p >= end || p->token.type != T_EQUALS)
1534     {
1535       printf ("expected = following !LET\n");
1536       return 0;
1537     }
1538   p++;
1539
1540   char *value = macro_evaluate_expression (&p, end - p,
1541                                            nesting_countdown, macros, me, vars,
1542                                            expand);
1543   if (!value)
1544     return 0;
1545
1546   string_map_replace_nocopy (vars, ss_xstrdup (var_name), value);
1547   return p - tokens;
1548 }
1549
1550 static const struct macro_token *
1551 find_doend (const struct macro_token *p, const struct macro_token *end)
1552 {
1553   size_t nesting = 0;
1554   for (; p < end; p++)
1555     {
1556       if (p->token.type != T_MACRO_ID)
1557         continue;
1558
1559       if (ss_equals_case (p->token.string, ss_cstr ("!DO")))
1560         nesting++;
1561       else if (ss_equals_case (p->token.string, ss_cstr ("!DOEND")))
1562         {
1563           if (!nesting)
1564             return p;
1565           nesting--;
1566         }
1567     }
1568   printf ("missing !DOEND\n");
1569   return NULL;
1570 }
1571
1572 static size_t
1573 macro_expand_do (const struct macro_token *tokens, size_t n_tokens,
1574                  int nesting_countdown, const struct macro_set *macros,
1575                  const struct macro_expander *me, struct string_map *vars,
1576                  bool *expand, struct macro_tokens *exp)
1577 {
1578   const struct macro_token *p = tokens;
1579   const struct macro_token *end = tokens + n_tokens;
1580
1581   if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!DO")))
1582     return 0;
1583   p++;
1584
1585   if (p >= end || p->token.type != T_MACRO_ID)
1586     {
1587       printf ("expected macro variable name following !DO\n");
1588       return 0;
1589     }
1590   const struct substring var_name = p->token.string;
1591   if (is_macro_keyword (var_name)
1592       || macro_find_parameter_by_name (me->macro, var_name))
1593     {
1594       printf ("cannot use argument name or macro keyword as !DO variable\n");
1595       return 0;
1596     }
1597   p++;
1598
1599   int miterate = settings_get_miterate ();
1600   if (p < end && p->token.type == T_MACRO_ID
1601       && ss_equals_case (p->token.string, ss_cstr ("!IN")))
1602     {
1603       p++;
1604       char *list = macro_evaluate_expression (&p, end - p,
1605                                               nesting_countdown, macros, me, vars,
1606                                               expand);
1607       if (!list)
1608         return 0;
1609
1610       struct macro_tokens items = { .n = 0 };
1611       macro_tokens_from_string (&items, ss_cstr (list),
1612                                 SEG_MODE_INTERACTIVE /* XXX */);
1613       free (list);
1614
1615       const struct macro_token *do_end = find_doend (p, end);
1616       if (!do_end)
1617         {
1618           macro_tokens_uninit (&items);
1619           return 0;
1620         }
1621
1622       const struct macro_tokens inner = {
1623         .mts = CONST_CAST (struct macro_token *, p),
1624         .n = do_end - p
1625       };
1626       for (size_t i = 0; i < items.n; i++)
1627         {
1628           if (i >= miterate)
1629             {
1630               printf ("exceeded maximum number of iterations %d\n", miterate);
1631               break;
1632             }
1633           string_map_replace_nocopy (vars, ss_xstrdup (var_name),
1634                                      ss_xstrdup (items.mts[i].representation));
1635
1636           bool break_ = false;
1637           macro_expand (&inner, nesting_countdown, macros,
1638                         me, vars, expand, &break_, exp);
1639           if (break_)
1640             break;
1641         }
1642       return do_end - tokens + 1;
1643     }
1644   else if (p < end && p->token.type == T_EQUALS)
1645     {
1646       p++;
1647       double first;
1648       if (!macro_evaluate_number (&p, end - p, nesting_countdown, macros, me,
1649                                   vars, expand, &first))
1650         return 0;
1651
1652       if (p >= end || p->token.type != T_MACRO_ID
1653           || !ss_equals_case (p->token.string, ss_cstr ("!TO")))
1654         {
1655           printf ("expecting !TO\n");
1656           return 0;
1657         }
1658       p++;
1659
1660       double last;
1661       if (!macro_evaluate_number (&p, end - p, nesting_countdown, macros, me,
1662                                   vars, expand, &last))
1663         return 0;
1664
1665       double by = 1.0;
1666       if (p < end && p->token.type == T_MACRO_ID
1667           && ss_equals_case (p->token.string, ss_cstr ("!BY")))
1668         {
1669           p++;
1670           if (!macro_evaluate_number (&p, end - p, nesting_countdown, macros, me,
1671                                       vars, expand, &by))
1672             return 0;
1673
1674           if (by == 0.0)
1675             {
1676               printf ("!BY value cannot be zero\n");
1677               return 0;
1678             }
1679         }
1680
1681       const struct macro_token *do_end = find_doend (p, end);
1682       if (!do_end)
1683         return 0;
1684       const struct macro_tokens inner = {
1685         .mts = CONST_CAST (struct macro_token *, p),
1686         .n = do_end - p
1687       };
1688
1689       if ((by > 0 && first <= last) || (by < 0 && first >= last))
1690         {
1691           int i = 0;
1692           for (double index = first;
1693                by > 0 ? (index <= last) : (index >= last);
1694                index += by)
1695             {
1696               if (i++ > miterate)
1697                 {
1698                   printf ("exceeded maximum number of iterations %d\n",
1699                           miterate);
1700                   break;
1701                 }
1702
1703               char index_s[DBL_BUFSIZE_BOUND];
1704               c_dtoastr (index_s, sizeof index_s, 0, 0, index);
1705               string_map_replace_nocopy (vars, ss_xstrdup (var_name),
1706                                          xstrdup (index_s));
1707
1708               bool break_ = false;
1709               macro_expand (&inner, nesting_countdown, macros,
1710                             me, vars, expand, &break_, exp);
1711               if (break_)
1712                 break;
1713             }
1714         }
1715
1716       return do_end - tokens + 1;
1717     }
1718   else
1719     {
1720       printf ("expecting = or !IN in !DO loop\n");
1721       return 0;
1722     }
1723 }
1724
1725 static void
1726 macro_expand (const struct macro_tokens *mts,
1727               int nesting_countdown, const struct macro_set *macros,
1728               const struct macro_expander *me, struct string_map *vars,
1729               bool *expand, bool *break_, struct macro_tokens *exp)
1730 {
1731   if (nesting_countdown <= 0)
1732     {
1733       printf ("maximum nesting level exceeded\n");
1734       for (size_t i = 0; i < mts->n; i++)
1735         macro_tokens_add (exp, &mts->mts[i]);
1736       return;
1737     }
1738
1739   struct string_map own_vars = STRING_MAP_INITIALIZER (own_vars);
1740   if (!vars)
1741     vars = &own_vars;
1742
1743   for (size_t i = 0; i < mts->n && (!break_ || !*break_); i++)
1744     {
1745       const struct macro_token *mt = &mts->mts[i];
1746       const struct token *token = &mt->token;
1747       if (token->type == T_MACRO_ID && me)
1748         {
1749           const struct macro_param *param = macro_find_parameter_by_name (
1750             me->macro, token->string);
1751           if (param)
1752             {
1753               const struct macro_tokens *arg = me->args[param - me->macro->params];
1754               //macro_tokens_print (arg, stdout);
1755               if (*expand && param->expand_arg)
1756                 macro_expand (arg, nesting_countdown, macros, NULL, NULL,
1757                               expand, break_, exp);
1758               else
1759                 for (size_t i = 0; i < arg->n; i++)
1760                   macro_tokens_add (exp, &arg->mts[i]);
1761               continue;
1762             }
1763
1764           if (is_bang_star (mts->mts, mts->n, i))
1765             {
1766               for (size_t j = 0; j < me->macro->n_params; j++)
1767                 {
1768                   const struct macro_param *param = &me->macro->params[j];
1769                   if (!param->positional)
1770                     break;
1771
1772                   const struct macro_tokens *arg = me->args[j];
1773                   if (*expand && param->expand_arg)
1774                     macro_expand (arg, nesting_countdown, macros, NULL, NULL,
1775                                   expand, break_, exp);
1776                   else
1777                     for (size_t k = 0; k < arg->n; k++)
1778                       macro_tokens_add (exp, &arg->mts[k]);
1779                 }
1780               i++;
1781               continue;
1782             }
1783
1784           size_t n = macro_expand_if (&mts->mts[i], mts->n - i,
1785                                       nesting_countdown, macros, me, vars,
1786                                       expand, break_, exp);
1787           if (n > 0)
1788             {
1789               i += n - 1;
1790               continue;
1791             }
1792         }
1793
1794       if (token->type == T_MACRO_ID && vars)
1795         {
1796           const char *value = string_map_find__ (vars, token->string.string,
1797                                                  token->string.length);
1798           if (value)
1799             {
1800               macro_tokens_from_string (exp, ss_cstr (value),
1801                                         SEG_MODE_INTERACTIVE /* XXX */);
1802               continue;
1803             }
1804         }
1805
1806       if (*expand)
1807         {
1808           struct macro_expander *subme;
1809           int retval = macro_expander_create (macros, token, &subme);
1810           for (size_t j = 1; !retval; j++)
1811             {
1812               const struct macro_token endcmd = { .token = { .type = T_ENDCMD } };
1813               retval = macro_expander_add (
1814                 subme, i + j < mts->n ? &mts->mts[i + j] : &endcmd);
1815             }
1816           if (retval > 0)
1817             {
1818               i += retval - 1;
1819               macro_expand (&subme->macro->body, nesting_countdown - 1, macros,
1820                             subme, NULL, expand, break_, exp);
1821               macro_expander_destroy (subme);
1822               continue;
1823             }
1824
1825           macro_expander_destroy (subme);
1826         }
1827
1828       if (token->type != T_MACRO_ID)
1829         {
1830           macro_tokens_add (exp, mt);
1831           continue;
1832         }
1833
1834       if (ss_equals_case (token->string, ss_cstr ("!break")))
1835         {
1836           if (!break_)
1837             printf ("!BREAK outside !DO\n");
1838           else
1839             {
1840               *break_ = true;
1841               break;
1842             }
1843         }
1844
1845       struct parse_macro_function_ctx ctx = {
1846         .input = &mts->mts[i],
1847         .n_input = mts->n - i,
1848         .nesting_countdown = nesting_countdown,
1849         .macros = macros,
1850         .me = me,
1851         .vars = vars,
1852         .expand = expand,
1853       };
1854       struct string function_output = DS_EMPTY_INITIALIZER;
1855       size_t function_consumed;
1856       if (expand_macro_function (&ctx, &function_output, &function_consumed))
1857         {
1858           i += function_consumed - 1;
1859
1860           macro_tokens_from_string (exp, function_output.ss,
1861                                     SEG_MODE_INTERACTIVE /* XXX */);
1862           ds_destroy (&function_output);
1863
1864           continue;
1865         }
1866
1867       size_t n = macro_parse_let (&mts->mts[i], mts->n - i,
1868                                   nesting_countdown, macros, me, vars,
1869                                   expand);
1870       if (n > 0)
1871         {
1872           i += n - 1;
1873           continue;
1874         }
1875
1876       n = macro_expand_do (&mts->mts[i], mts->n - i,
1877                            nesting_countdown, macros, me, vars,
1878                            expand, exp);
1879       if (n > 0)
1880         {
1881           i += n - 1;
1882           continue;
1883         }
1884
1885       if (ss_equals_case (token->string, ss_cstr ("!onexpand")))
1886         *expand = true;
1887       else if (ss_equals_case (token->string, ss_cstr ("!offexpand")))
1888         *expand = false;
1889       else
1890         macro_tokens_add (exp, mt);
1891     }
1892   if (vars == &own_vars)
1893     string_map_destroy (&own_vars);
1894 }
1895
1896 void
1897 macro_expander_get_expansion (struct macro_expander *me, struct macro_tokens *exp)
1898 {
1899 #if 0
1900   for (size_t i = 0; i < me->macro->n_params; i++)
1901     {
1902       printf ("%s:\n", me->macro->params[i].name);
1903       macro_tokens_print (me->args[i], stdout);
1904     }
1905 #endif
1906
1907   bool expand = true;
1908   macro_expand (&me->macro->body, settings_get_mnest (),
1909                 me->macros, me, NULL, &expand, NULL, exp);
1910
1911 #if 0
1912   printf ("expansion:\n");
1913   macro_tokens_print (exp, stdout);
1914 #endif
1915 }
1916