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