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