!*
[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/i18n.h"
30 #include "libpspp/message.h"
31 #include "libpspp/str.h"
32 #include "libpspp/string-array.h"
33
34 #include "gettext.h"
35 #define _(msgid) gettext (msgid)
36
37 void
38 macro_token_copy (struct macro_token *dst, const struct macro_token *src)
39 {
40   token_copy (&dst->token, &src->token);
41   ss_alloc_substring (&dst->representation, src->representation);
42 }
43
44 void
45 macro_token_uninit (struct macro_token *mt)
46 {
47   token_uninit (&mt->token);
48   ss_dealloc (&mt->representation);
49 }
50
51 void
52 macro_token_to_representation (struct macro_token *mt, struct string *s)
53 {
54   ds_put_substring (s, mt->representation);
55 }
56
57 void
58 macro_tokens_copy (struct macro_tokens *dst, const struct macro_tokens *src)
59 {
60   *dst = (struct macro_tokens) {
61     .mts = xmalloc (src->n * sizeof *dst->mts),
62     .n = src->n,
63     .allocated = src->n,
64   };
65   for (size_t i = 0; i < src->n; i++)
66     macro_token_copy (&dst->mts[i], &src->mts[i]);
67 }
68
69 void
70 macro_tokens_uninit (struct macro_tokens *mts)
71 {
72   for (size_t i = 0; i < mts->n; i++)
73     macro_token_uninit (&mts->mts[i]);
74   free (mts->mts);
75 }
76
77 struct macro_token *
78 macro_tokens_add_uninit (struct macro_tokens *mts)
79 {
80   if (mts->n >= mts->allocated)
81     mts->mts = x2nrealloc (mts->mts, &mts->allocated, sizeof *mts->mts);
82   return &mts->mts[mts->n++];
83 }
84
85 void
86 macro_tokens_add (struct macro_tokens *mts, const struct macro_token *mt)
87 {
88   macro_token_copy (macro_tokens_add_uninit (mts), mt);
89 }
90
91 void
92 macro_tokens_from_string (struct macro_tokens *mts, const struct substring src,
93                           enum segmenter_mode mode)
94 {
95   struct state
96     {
97       struct segmenter segmenter;
98       struct substring body;
99     };
100
101   struct state state = {
102     .segmenter = SEGMENTER_INIT (mode),
103     .body = src,
104   };
105   struct state saved = state;
106
107   while (state.body.length > 0)
108     {
109       struct macro_token mt = {
110         .token = { .type = T_STOP },
111         .representation = { .string = state.body.string },
112       };
113       struct token *token = &mt.token;
114
115       struct scanner scanner;
116       scanner_init (&scanner, token);
117
118       for (;;)
119         {
120           enum segment_type type;
121           int seg_len = segmenter_push (&state.segmenter, state.body.string,
122                                         state.body.length, true, &type);
123           assert (seg_len >= 0);
124
125           struct substring segment = ss_head (state.body, seg_len);
126           ss_advance (&state.body, seg_len);
127
128           enum scan_result result = scanner_push (&scanner, type, segment, token);
129           if (result == SCAN_SAVE)
130             saved = state;
131           else if (result == SCAN_BACK)
132             {
133               state = saved;
134               break;
135             }
136           else if (result == SCAN_DONE)
137             break;
138         }
139
140       /* We have a token in 'token'. */
141       if (is_scan_type (token->type))
142         {
143           if (token->type != SCAN_SKIP)
144             {
145               printf ("error\n");
146               /* XXX report error */
147             }
148         }
149       else
150         {
151           mt.representation.length = state.body.string - mt.representation.string;
152           macro_tokens_add (mts, &mt);
153         }
154       token_uninit (token);
155     }
156 }
157
158 void
159 macro_tokens_print (const struct macro_tokens *mts, FILE *stream)
160 {
161   for (size_t i = 0; i < mts->n; i++)
162     token_print (&mts->mts[i].token, stream);
163 }
164
165 enum token_class
166   {
167     TC_ENDCMD,                  /* No space before or after (new-line after). */
168     TC_BINOP,                   /* Space on both sides. */
169     TC_COMMA,                   /* Space afterward. */
170     TC_ID,                      /* Don't need spaces except sequentially. */
171     TC_PUNCT,                   /* Don't need spaces except sequentially. */
172   };
173
174 static bool
175 needs_space (enum token_class prev, enum token_class next)
176 {
177   /* Don't need a space before or after the end of a command.
178      (A new-line is needed afterward as a special case.) */
179   if (prev == TC_ENDCMD || next == TC_ENDCMD)
180     return false;
181
182   /* Binary operators always have a space on both sides. */
183   if (prev == TC_BINOP || next == TC_BINOP)
184     return true;
185
186   /* A comma always has a space afterward. */
187   if (prev == TC_COMMA)
188     return true;
189
190   /* Otherwise, PREV is TC_ID or TC_PUNCT, which only need a space if there are
191      two or them in a row. */
192   return prev == next;
193 }
194
195 static enum token_class
196 classify_token (enum token_type type)
197 {
198   switch (type)
199     {
200     case T_ID:
201     case T_MACRO_ID:
202     case T_POS_NUM:
203     case T_NEG_NUM:
204     case T_STRING:
205       return TC_ID;
206
207     case T_STOP:
208       return TC_PUNCT;
209
210     case T_ENDCMD:
211       return TC_ENDCMD;
212
213     case T_LPAREN:
214     case T_RPAREN:
215     case T_LBRACK:
216     case T_RBRACK:
217       return TC_PUNCT;
218
219     case T_PLUS:
220     case T_DASH:
221     case T_ASTERISK:
222     case T_SLASH:
223     case T_EQUALS:
224     case T_AND:
225     case T_OR:
226     case T_NOT:
227     case T_EQ:
228     case T_GE:
229     case T_GT:
230     case T_LE:
231     case T_LT:
232     case T_NE:
233     case T_ALL:
234     case T_BY:
235     case T_TO:
236     case T_WITH:
237     case T_EXP:
238     case T_MACRO_PUNCT:
239       return TC_BINOP;
240
241     case T_COMMA:
242       return TC_COMMA;
243     }
244
245   NOT_REACHED ();
246 }
247
248 void
249 macro_tokens_to_representation (struct macro_tokens *mts, struct string *s)
250 {
251   if (!mts->n)
252     return;
253
254   macro_token_to_representation (&mts->mts[0], s);
255   for (size_t i = 1; i < mts->n; i++)
256     {
257       enum token_type prev = mts->mts[i - 1].token.type;
258       enum token_type next = mts->mts[i].token.type;
259
260       if (prev == T_ENDCMD)
261         ds_put_byte (s, '\n');
262       else
263         {
264           enum token_class pc = classify_token (prev);
265           enum token_class nc = classify_token (next);
266           if (needs_space (pc, nc))
267             ds_put_byte (s, ' ');
268         }
269
270       macro_token_to_representation (&mts->mts[i], s);
271     }
272 }
273
274 void
275 macro_destroy (struct macro *m)
276 {
277   if (!m)
278     return;
279
280   free (m->name);
281   for (size_t i = 0; i < m->n_params; i++)
282     {
283       struct macro_param *p = &m->params[i];
284       free (p->name);
285
286       macro_tokens_uninit (&p->def);
287
288       switch (p->arg_type)
289         {
290         case ARG_N_TOKENS:
291           break;
292
293         case ARG_CHAREND:
294           token_uninit (&p->charend);
295           break;
296
297         case ARG_ENCLOSE:
298           token_uninit (&p->enclose[0]);
299           token_uninit (&p->enclose[1]);
300           break;
301
302         case ARG_CMDEND:
303           break;
304         }
305     }
306   free (m->params);
307   macro_tokens_uninit (&m->body);
308   free (m);
309 }
310 \f
311 struct macro_set *
312 macro_set_create (void)
313 {
314   struct macro_set *set = xmalloc (sizeof *set);
315   *set = (struct macro_set) {
316     .macros = HMAP_INITIALIZER (set->macros),
317   };
318   return set;
319 }
320
321 void
322 macro_set_destroy (struct macro_set *set)
323 {
324   if (!set)
325     return;
326
327   struct macro *macro, *next;
328   HMAP_FOR_EACH_SAFE (macro, next, struct macro, hmap_node, &set->macros)
329     {
330       hmap_delete (&set->macros, &macro->hmap_node);
331       macro_destroy (macro);
332     }
333   hmap_destroy (&set->macros);
334   free (set);
335 }
336
337 static unsigned int
338 hash_macro_name (const char *name)
339 {
340   return utf8_hash_case_string (name, 0);
341 }
342
343 static struct macro *
344 macro_set_find__ (struct macro_set *set, const char *name)
345 {
346   struct macro *macro;
347   HMAP_FOR_EACH_WITH_HASH (macro, struct macro, hmap_node,
348                            hash_macro_name (name), &set->macros)
349     if (!utf8_strcasecmp (macro->name, name))
350       return macro;
351
352   return NULL;
353 }
354
355 const struct macro *
356 macro_set_find (const struct macro_set *set, const char *name)
357 {
358   return macro_set_find__ (CONST_CAST (struct macro_set *, set), name);
359 }
360
361 /* Adds M to SET.  M replaces any existing macro with the same name.  Takes
362    ownership of M. */
363 void
364 macro_set_add (struct macro_set *set, struct macro *m)
365 {
366   struct macro *victim = macro_set_find__ (set, m->name);
367   if (victim)
368     {
369       hmap_delete (&set->macros, &victim->hmap_node);
370       macro_destroy (victim);
371     }
372
373   hmap_insert (&set->macros, &m->hmap_node, hash_macro_name (m->name));
374 }
375 \f
376 enum me_state
377   {
378     /* Error state. */
379     ME_ERROR,
380
381     /* Accumulating tokens in me->params toward the end of any type of
382        argument. */
383     ME_ARG,
384
385     /* Expecting the opening delimiter of an ARG_ENCLOSE argument. */
386     ME_ENCLOSE,
387
388     /* Expecting a keyword for a keyword argument. */
389     ME_KEYWORD,
390
391     /* Expecting an equal sign for a keyword argument. */
392     ME_EQUALS,
393   };
394
395
396 struct macro_expander
397   {
398     const struct macro_set *macros;
399
400     enum me_state state;
401     size_t n_tokens;
402
403     const struct macro *macro;
404     struct macro_tokens **args;
405     const struct macro_param *param;
406   };
407
408 static int
409 me_finished (struct macro_expander *me)
410 {
411   for (size_t i = 0; i < me->macro->n_params; i++)
412     if (!me->args[i])
413       {
414         me->args[i] = xmalloc (sizeof *me->args[i]);
415         macro_tokens_copy (me->args[i], &me->macro->params[i].def);
416       }
417   return me->n_tokens;
418 }
419
420 static int
421 me_next_arg (struct macro_expander *me)
422 {
423   if (!me->param)
424     {
425       assert (!me->macro->n_params);
426       return me_finished (me);
427     }
428   else if (me->param->positional)
429     {
430       me->param++;
431       if (me->param >= &me->macro->params[me->macro->n_params])
432         return me_finished (me);
433       else
434         {
435           me->state = (!me->param->positional ? ME_KEYWORD
436                        : me->param->arg_type == ARG_ENCLOSE ? ME_ENCLOSE
437                        : ME_ARG);
438           return 0;
439         }
440     }
441   else
442     {
443       for (size_t i = 0; i < me->macro->n_params; i++)
444         if (!me->args[i])
445           {
446             me->state = ME_KEYWORD;
447             return 0;
448           }
449       return me_finished (me);
450     }
451 }
452
453 static int
454 me_error (struct macro_expander *me)
455 {
456   me->state = ME_ERROR;
457   return -1;
458 }
459
460 static int
461 me_add_arg (struct macro_expander *me, const struct macro_token *mt)
462 {
463   const struct macro_param *p = me->param;
464
465   const struct token *token = &mt->token;
466   if ((token->type == T_ENDCMD || token->type == T_STOP)
467       && p->arg_type != ARG_CMDEND)
468     {
469       msg (SE, _("Unexpected end of command reading argument %s "
470                  "to macro %s."), me->param->name, me->macro->name);
471
472       return me_error (me);
473     }
474
475   me->n_tokens++;
476
477   struct macro_tokens **argp = &me->args[p - me->macro->params];
478   if (!*argp)
479     *argp = xzalloc (sizeof **argp);
480   struct macro_tokens *arg = *argp;
481   if (p->arg_type == ARG_N_TOKENS)
482     {
483       macro_tokens_add (arg, mt);
484       if (arg->n >= p->n_tokens)
485         return me_next_arg (me);
486       return 0;
487     }
488   else if (p->arg_type == ARG_CMDEND)
489     {
490       if (token->type == T_ENDCMD || token->type == T_STOP)
491         return me_next_arg (me);
492       macro_tokens_add (arg, mt);
493       return 0;
494     }
495   else
496     {
497       const struct token *end
498         = p->arg_type == ARG_CHAREND ? &p->charend : &p->enclose[1];
499       if (token_equal (token, end))
500         return me_next_arg (me);
501       macro_tokens_add (arg, mt);
502       return 0;
503     }
504 }
505
506 static int
507 me_expected (struct macro_expander *me, const struct macro_token *actual,
508              const struct token *expected)
509 {
510   const struct substring actual_s
511     = (actual->representation.length ? actual->representation
512        : ss_cstr (_("<end of input>")));
513   char *expected_s = token_to_string (expected);
514   msg (SE, _("Found `%.*s' while expecting `%s' reading argument %s "
515              "to macro %s."),
516        (int) actual_s.length, actual_s.string, expected_s,
517        me->param->name, me->macro->name);
518   free (expected_s);
519
520   return me_error (me);
521 }
522
523 static int
524 me_enclose (struct macro_expander *me, const struct macro_token *mt)
525 {
526   const struct token *token = &mt->token;
527   me->n_tokens++;
528
529   if (token_equal (&me->param->enclose[0], token))
530     {
531       me->state = ME_ARG;
532       return 0;
533     }
534
535   return me_expected (me, mt, &me->param->enclose[0]);
536 }
537
538 static const struct macro_param *
539 macro_find_parameter_by_name (const struct macro *m, struct substring name)
540 {
541   if (ss_first (name) == '!')
542     ss_advance (&name, 1);
543
544   for (size_t i = 0; i < m->n_params; i++)
545     {
546       const struct macro_param *p = &m->params[i];
547       struct substring p_name = ss_cstr (p->name + 1);
548       if (!utf8_strncasecmp (p_name.string, p_name.length,
549                              name.string, name.length))
550         return p;
551     }
552   return NULL;
553 }
554
555 static int
556 me_keyword (struct macro_expander *me, const struct macro_token *mt)
557 {
558   const struct token *token = &mt->token;
559   if (token->type != T_ID)
560     return me_finished (me);
561
562   const struct macro_param *p = macro_find_parameter_by_name (me->macro,
563                                                               token->string);
564   if (p)
565     {
566       size_t arg_index = p - me->macro->params;
567       me->param = p;
568       if (me->args[arg_index])
569         {
570           msg (SE,
571                _("Argument %s multiply specified in call to macro %s."),
572                p->name, me->macro->name);
573           return me_error (me);
574         }
575
576       me->n_tokens++;
577       me->state = ME_EQUALS;
578       return 0;
579     }
580
581   return me_finished (me);
582 }
583
584 static int
585 me_equals (struct macro_expander *me, const struct macro_token *mt)
586 {
587   const struct token *token = &mt->token;
588   me->n_tokens++;
589
590   if (token->type == T_EQUALS)
591     {
592       me->state = ME_ARG;
593       return 0;
594     }
595
596   return me_expected (me, mt, &(struct token) { .type = T_EQUALS });
597 }
598
599 int
600 macro_expander_create (const struct macro_set *macros,
601                        const struct token *token,
602                        struct macro_expander **mep)
603 {
604   *mep = NULL;
605   if (macro_set_is_empty (macros))
606     return -1;
607   if (token->type != T_ID && token->type != T_MACRO_ID)
608     return -1;
609
610   const struct macro *macro = macro_set_find (macros, token->string.string);
611   if (!macro)
612     return -1;
613
614   struct macro_expander *me = xmalloc (sizeof *me);
615   *me = (struct macro_expander) {
616     .macros = macros,
617     .n_tokens = 1,
618     .macro = macro,
619   };
620   *mep = me;
621
622   if (!macro->n_params)
623     return 1;
624   else
625     {
626       me->state = (!macro->params[0].positional ? ME_KEYWORD
627                    : macro->params[0].arg_type == ARG_ENCLOSE ? ME_ENCLOSE
628                    : ME_ARG);
629       me->args = xcalloc (macro->n_params, sizeof *me->args);
630       me->param = macro->params;
631       return 0;
632     }
633 }
634
635 void
636 macro_expander_destroy (struct macro_expander *me)
637 {
638   if (!me)
639     return;
640
641   for (size_t i = 0; i < me->macro->n_params; i++)
642     if (me->args[i])
643       {
644         macro_tokens_uninit (me->args[i]);
645         free (me->args[i]);
646       }
647   free (me->args);
648   free (me);
649 }
650
651 /* Adds TOKEN to the collection of tokens in ME that potentially need to be
652    macro expanded.
653
654    Returns -1 if the tokens added do not actually invoke a macro.  The caller
655    should consume the first token without expanding it.
656
657    Returns 0 if the macro expander needs more tokens, for macro arguments or to
658    decide whether this is actually a macro invocation.  The caller should call
659    macro_expander_add() again with the next token.
660
661    Returns a positive number to indicate that the returned number of tokens
662    invoke a macro.  The number returned might be less than the number of tokens
663    added because it can take a few tokens of lookahead to determine whether the
664    macro invocation is finished.  The caller should call
665    macro_expander_get_expansion() to obtain the expansion. */
666 int
667 macro_expander_add (struct macro_expander *me, const struct macro_token *mt)
668 {
669   switch (me->state)
670     {
671     case ME_ERROR:
672       return -1;
673
674     case ME_ARG:
675       return me_add_arg (me, mt);
676
677     case ME_ENCLOSE:
678       return me_enclose (me, mt);
679
680     case ME_KEYWORD:
681       return me_keyword (me, mt);
682
683     case ME_EQUALS:
684       return me_equals (me, mt);
685
686     default:
687       NOT_REACHED ();
688     }
689 }
690
691 /* Each argument to a macro function is one of:
692
693        - A quoted string or other single literal token.
694
695        - An argument to the macro being expanded, e.g. !1 or a named argument.
696
697        - !*.
698
699        - A function invocation.
700
701    Each function invocation yields a character sequence to be turned into a
702    sequence of tokens.  The case where that character sequence is a single
703    quoted string is an important special case.
704 */
705 struct parse_macro_function_ctx
706   {
707     struct macro_token *input;
708     size_t n_input;
709     int nesting_countdown;
710     const struct macro_set *macros;
711     const struct macro_expander *me;
712     bool *expand;
713   };
714
715 static void
716 macro_expand (const struct macro_tokens *,
717               int nesting_countdown, const struct macro_set *,
718               const struct macro_expander *, bool *expand, struct macro_tokens *exp);
719
720 static bool
721 expand_macro_function (struct parse_macro_function_ctx *ctx,
722                        struct string *output, size_t *input_consumed);
723
724 /* Returns true if the pair of tokens starting at offset OFS within MTS are !*,
725    false otherwise. */
726 static bool
727 is_bang_star (const struct macro_token *mts, size_t n, size_t ofs)
728 {
729   return (ofs + 1 < n
730           && mts[ofs].token.type == T_MACRO_ID
731           && ss_equals (mts[ofs].token.string, ss_cstr ("!"))
732           && mts[ofs + 1].token.type == T_ASTERISK);
733 }
734
735 static size_t
736 parse_function_arg (struct parse_macro_function_ctx *ctx,
737                     size_t i, struct string *farg)
738 {
739   struct macro_token *tokens = ctx->input;
740   const struct token *token = &tokens[i].token;
741   if (token->type == T_MACRO_ID)
742     {
743       const struct macro_param *param = macro_find_parameter_by_name (
744         ctx->me->macro, token->string);
745       if (param)
746         {
747           size_t param_idx = param - ctx->me->macro->params;
748           const struct macro_tokens *marg = ctx->me->args[param_idx];
749           for (size_t i = 0; i < marg->n; i++)
750             {
751               if (i)
752                 ds_put_byte (farg, ' ');
753               ds_put_substring (farg, marg->mts[i].representation);
754             }
755           return 1;
756         }
757
758       if (is_bang_star (ctx->input, ctx->n_input, i))
759         {
760           for (size_t i = 0; i < ctx->me->macro->n_params; i++)
761             {
762               if (!ctx->me->macro->params[i].positional)
763                 break;
764
765               const struct macro_tokens *marg = ctx->me->args[i];
766               for (size_t j = 0; j < marg->n; j++)
767                 {
768                   if (i || j)
769                     ds_put_byte (farg, ' ');
770                   ds_put_substring (farg, marg->mts[j].representation);
771                 }
772             }
773           return 2;
774         }
775
776       struct parse_macro_function_ctx subctx = {
777         .input = &ctx->input[i],
778         .n_input = ctx->n_input - i,
779         .nesting_countdown = ctx->nesting_countdown,
780         .macros = ctx->macros,
781         .me = ctx->me,
782         .expand = ctx->expand,
783       };
784       size_t subinput_consumed;
785       if (expand_macro_function (&subctx, farg, &subinput_consumed))
786         return subinput_consumed;
787     }
788
789   ds_put_substring (farg, tokens[i].representation);
790   return 1;
791 }
792
793 static bool
794 parse_macro_function (struct parse_macro_function_ctx *ctx,
795                       struct string_array *args,
796                       struct substring function,
797                       int min_args, int max_args,
798                       size_t *input_consumed)
799 {
800   struct macro_token *tokens = ctx->input;
801   size_t n_tokens = ctx->n_input;
802
803   if (!n_tokens
804       || tokens[0].token.type != T_MACRO_ID
805       || !ss_equals_case (tokens[0].token.string, function))
806     return false;
807
808   if (n_tokens < 2 || tokens[1].token.type != T_LPAREN)
809     {
810       printf ("`(' expected following %s'\n", function.string);
811       return false;
812     }
813
814   string_array_init (args);
815
816   for (size_t i = 2;; )
817     {
818       if (i >= n_tokens)
819         goto unexpected_end;
820       if (tokens[i].token.type == T_RPAREN)
821         {
822           *input_consumed = i + 1;
823           if (args->n < min_args || args->n > max_args)
824             {
825               printf ("Wrong number of arguments to %s.\n", function.string);
826               goto error;
827             }
828           return true;
829         }
830
831       struct string s = DS_EMPTY_INITIALIZER;
832       i += parse_function_arg (ctx, i, &s);
833       if (i >= n_tokens)
834         {
835           ds_destroy (&s);
836           goto unexpected_end;
837         }
838       string_array_append_nocopy (args, ds_steal_cstr (&s));
839
840       if (tokens[i].token.type == T_COMMA)
841         i++;
842       else if (tokens[i].token.type != T_RPAREN)
843         {
844           printf ("Expecting `,' or `)' in %s invocation.", function.string);
845           goto error;
846         }
847     }
848
849 unexpected_end:
850   printf ("Missing closing parenthesis in arguments to %s.\n",
851           function.string);
852   /* Fall through. */
853 error:
854   string_array_destroy (args);
855   return false;
856 }
857
858 static bool
859 unquote_string (const char *s, struct string *content)
860 {
861   struct string_lexer slex;
862   string_lexer_init (&slex, s, strlen (s), SEG_MODE_INTERACTIVE /* XXX */);
863
864   struct token token1;
865   if (!string_lexer_next (&slex, &token1))
866     return false;
867
868   if (token1.type != T_STRING)
869     {
870       token_uninit (&token1);
871       return false;
872     }
873
874   struct token token2;
875   if (string_lexer_next (&slex, &token2))
876     {
877       token_uninit (&token1);
878       token_uninit (&token2);
879       return false;
880     }
881
882   ds_put_substring (content, token1.string);
883   token_uninit (&token1);
884   return true;
885 }
886
887 static const char *
888 unquote_string_in_place (const char *s, struct string *tmp)
889 {
890   ds_init_empty (tmp);
891   return unquote_string (s, tmp) ? ds_cstr (tmp) : s;
892 }
893
894 static bool
895 parse_integer (const char *s, int *np)
896 {
897   errno = 0;
898
899   char *tail;
900   long int n = strtol (s, &tail, 10);
901   *np = n < INT_MIN ? INT_MIN : n > INT_MAX ? INT_MAX : n;
902   tail += strspn (tail, CC_SPACES);
903   return *tail == '\0' && errno != ERANGE && n == *np;
904 }
905
906 static bool
907 expand_macro_function (struct parse_macro_function_ctx *ctx,
908                        struct string *output,
909                        size_t *input_consumed)
910 {
911   struct string_array args;
912
913   if (parse_macro_function (ctx, &args, ss_cstr ("!length"), 1, 1,
914                             input_consumed))
915     ds_put_format (output, "%zu", strlen (args.strings[0]));
916   else if (parse_macro_function (ctx, &args, ss_cstr ("!blanks"), 1, 1,
917                                  input_consumed))
918     {
919       int n;
920       if (!parse_integer (args.strings[0], &n))
921         {
922           printf ("argument to !BLANKS must be non-negative integer (not \"%s\")\n", args.strings[0]);
923           string_array_destroy (&args);
924           return false;
925         }
926
927       ds_put_byte_multiple (output, ' ', n);
928     }
929   else if (parse_macro_function (ctx, &args, ss_cstr ("!concat"), 1, INT_MAX,
930                                  input_consumed))
931     {
932       for (size_t i = 0; i < args.n; i++)
933         if (!unquote_string (args.strings[i], output))
934           ds_put_cstr (output, args.strings[i]);
935     }
936   else if (parse_macro_function (ctx, &args, ss_cstr ("!head"), 1, 1,
937                                  input_consumed))
938     {
939       struct string tmp;
940       const char *s = unquote_string_in_place (args.strings[0], &tmp);
941
942       struct macro_tokens mts = { .n = 0 };
943       macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */);
944       if (mts.n > 0)
945         ds_put_substring (output, mts.mts[0].representation);
946       macro_tokens_uninit (&mts);
947       ds_destroy (&tmp);
948     }
949   else if (parse_macro_function (ctx, &args, ss_cstr ("!index"), 2, 2,
950                                  input_consumed))
951     {
952       const char *haystack = args.strings[0];
953       const char *needle = strstr (haystack, args.strings[1]);
954       ds_put_format (output, "%zu", needle ? needle - haystack + 1 : 0);
955     }
956   else if (parse_macro_function (ctx, &args, ss_cstr ("!quote"), 1, 1,
957                                  input_consumed))
958     {
959       if (unquote_string (args.strings[0], NULL))
960         ds_put_cstr (output, args.strings[0]);
961       else
962         {
963           ds_extend (output, strlen (args.strings[0]) + 2);
964           ds_put_byte (output, '\'');
965           for (const char *p = args.strings[0]; *p; p++)
966             {
967               if (*p == '\'')
968                 ds_put_byte (output, '\'');
969               ds_put_byte (output, *p);
970             }
971           ds_put_byte (output, '\'');
972         }
973     }
974   else if (parse_macro_function (ctx, &args, ss_cstr ("!substr"), 2, 3,
975                                  input_consumed))
976     {
977       int start;
978       if (!parse_integer (args.strings[1], &start) || start < 1)
979         {
980           printf ("second argument to !SUBSTR must be positive integer (not \"%s\")\n", args.strings[1]);
981           string_array_destroy (&args);
982           return false;
983         }
984
985       int count = INT_MAX;
986       if (args.n > 2 && (!parse_integer (args.strings[2], &count) || count < 0))
987         {
988           printf ("third argument to !SUBSTR must be non-negative integer (not \"%s\")\n", args.strings[1]);
989           string_array_destroy (&args);
990           return false;
991         }
992
993       struct substring s = ss_cstr (args.strings[0]);
994       ds_put_substring (output, ss_substr (s, start - 1, count));
995     }
996   else if (parse_macro_function (ctx, &args, ss_cstr ("!tail"), 1, 1,
997                                  input_consumed))
998     {
999       struct string tmp;
1000       const char *s = unquote_string_in_place (args.strings[0], &tmp);
1001
1002       struct macro_tokens mts = { .n = 0 };
1003       macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */);
1004       if (mts.n > 1)
1005         {
1006           struct macro_tokens tail = { .mts = mts.mts + 1, .n = mts.n - 1 };
1007           macro_tokens_to_representation (&tail, output);
1008         }
1009       macro_tokens_uninit (&mts);
1010       ds_destroy (&tmp);
1011     }
1012   else if (parse_macro_function (ctx, &args, ss_cstr ("!unquote"), 1, 1,
1013                                  input_consumed))
1014     {
1015       if (!unquote_string (args.strings[0], output))
1016         ds_put_cstr (output, args.strings[0]);
1017     }
1018   else if (parse_macro_function (ctx, &args, ss_cstr ("!upcase"), 1, 1,
1019                                  input_consumed))
1020     {
1021       struct string tmp;
1022       const char *s = unquote_string_in_place (args.strings[0], &tmp);
1023       char *upper = utf8_to_upper (s);
1024       ds_put_cstr (output, upper);
1025       free (upper);
1026       ds_destroy (&tmp);
1027     }
1028   else if (parse_macro_function (ctx, &args, ss_cstr ("!eval"), 1, 1,
1029                                  input_consumed))
1030     {
1031       struct macro_tokens mts = { .n = 0 };
1032       macro_tokens_from_string (&mts, ss_cstr (args.strings[0]),
1033                                 SEG_MODE_INTERACTIVE /* XXX */);
1034       struct macro_tokens exp = { .n = 0 };
1035       macro_expand (&mts, ctx->nesting_countdown - 1, ctx->macros,
1036                     ctx->me, ctx->expand, &exp);
1037       macro_tokens_to_representation (&exp, output);
1038       macro_tokens_uninit (&exp);
1039       macro_tokens_uninit (&mts);
1040     }
1041   else if (ctx->n_input > 0
1042            && ctx->input[0].token.type == T_MACRO_ID
1043            && ss_equals_case (ctx->input[0].token.string, ss_cstr ("!null")))
1044     {
1045       *input_consumed = 1;
1046       return true;
1047     }
1048   else
1049     return false;
1050
1051   string_array_destroy (&args);
1052   return true;
1053 }
1054
1055 static void
1056 macro_expand (const struct macro_tokens *mts,
1057               int nesting_countdown, const struct macro_set *macros,
1058               const struct macro_expander *me, bool *expand,
1059               struct macro_tokens *exp)
1060 {
1061   if (nesting_countdown <= 0)
1062     {
1063       printf ("maximum nesting level exceeded\n");
1064       for (size_t i = 0; i < mts->n; i++)
1065         macro_tokens_add (exp, &mts->mts[i]);
1066       return;
1067     }
1068
1069   for (size_t i = 0; i < mts->n; i++)
1070     {
1071       const struct macro_token *mt = &mts->mts[i];
1072       const struct token *token = &mt->token;
1073       if (token->type == T_MACRO_ID && me)
1074         {
1075           const struct macro_param *param = macro_find_parameter_by_name (
1076             me->macro, token->string);
1077           if (param)
1078             {
1079               const struct macro_tokens *arg = me->args[param - me->macro->params];
1080               //macro_tokens_print (arg, stdout);
1081               if (*expand && param->expand_arg)
1082                 macro_expand (arg, nesting_countdown, macros, NULL, expand, exp);
1083               else
1084                 for (size_t i = 0; i < arg->n; i++)
1085                   macro_tokens_add (exp, &arg->mts[i]);
1086               continue;
1087             }
1088
1089           if (is_bang_star (mts->mts, mts->n, i))
1090             {
1091               for (size_t j = 0; j < me->macro->n_params; j++)
1092                 {
1093                   const struct macro_param *param = &me->macro->params[j];
1094                   if (!param->positional)
1095                     break;
1096
1097                   const struct macro_tokens *arg = me->args[j];
1098                   if (*expand && param->expand_arg)
1099                     macro_expand (arg, nesting_countdown, macros, NULL, expand, exp);
1100                   else
1101                     for (size_t k = 0; k < arg->n; k++)
1102                       macro_tokens_add (exp, &arg->mts[k]);
1103                 }
1104               i++;
1105               continue;
1106             }
1107         }
1108
1109       if (*expand)
1110         {
1111           struct macro_expander *subme;
1112           int retval = macro_expander_create (macros, token, &subme);
1113           for (size_t j = 1; !retval; j++)
1114             {
1115               const struct macro_token endcmd = { .token = { .type = T_ENDCMD } };
1116               retval = macro_expander_add (
1117                 subme, i + j < mts->n ? &mts->mts[i + j] : &endcmd);
1118             }
1119           if (retval > 0)
1120             {
1121               i += retval - 1;
1122               macro_expand (&subme->macro->body, nesting_countdown - 1, macros,
1123                             subme, expand, exp);
1124               macro_expander_destroy (subme);
1125               continue;
1126             }
1127
1128           macro_expander_destroy (subme);
1129         }
1130
1131       if (token->type != T_MACRO_ID)
1132         {
1133           macro_tokens_add (exp, mt);
1134           continue;
1135         }
1136
1137       /* Maybe each arg should just be a string, either a quoted string or a
1138          non-quoted string containing tokens. */
1139       struct parse_macro_function_ctx ctx = {
1140         .input = &mts->mts[i],
1141         .n_input = mts->n - i,
1142         .nesting_countdown = nesting_countdown,
1143         .macros = macros,
1144         .me = me,
1145         .expand = expand,
1146       };
1147       struct string function_output = DS_EMPTY_INITIALIZER;
1148       size_t function_consumed;
1149       if (expand_macro_function (&ctx, &function_output, &function_consumed))
1150         {
1151           i += function_consumed - 1;
1152
1153           macro_tokens_from_string (exp, function_output.ss,
1154                                     SEG_MODE_INTERACTIVE /* XXX */);
1155           ds_destroy (&function_output);
1156
1157           continue;
1158         }
1159
1160       if (ss_equals_case (token->string, ss_cstr ("!onexpand")))
1161         *expand = true;
1162       else if (ss_equals_case (token->string, ss_cstr ("!offexpand")))
1163         *expand = false;
1164       else
1165         macro_tokens_add (exp, mt);
1166     }
1167 }
1168
1169 void
1170 macro_expander_get_expansion (struct macro_expander *me, struct macro_tokens *exp)
1171 {
1172 #if 0
1173   for (size_t i = 0; i < me->macro->n_params; i++)
1174     {
1175       printf ("%s:\n", me->macro->params[i].name);
1176       macro_tokens_print (me->args[i], stdout);
1177     }
1178 #endif
1179
1180   bool expand = true;
1181   macro_expand (&me->macro->body, settings_get_mnest (),
1182                 me->macros, me, &expand, exp);
1183
1184 #if 0
1185   printf ("expansion:\n");
1186   macro_tokens_print (exp, stdout);
1187 #endif
1188 }
1189