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