1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2021 Free Software Foundation, Inc.
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.
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.
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/>. */
19 #include "language/lexer/macro.h"
25 #include "data/settings.h"
26 #include "language/lexer/segment.h"
27 #include "language/lexer/scan.h"
28 #include "libpspp/assertion.h"
29 #include "libpspp/cast.h"
30 #include "libpspp/i18n.h"
31 #include "libpspp/message.h"
32 #include "libpspp/str.h"
33 #include "libpspp/string-array.h"
34 #include "libpspp/string-map.h"
35 #include "libpspp/stringi-set.h"
37 #include "gl/c-ctype.h"
38 #include "gl/ftoastr.h"
41 #define _(msgid) gettext (msgid)
44 macro_token_copy (struct macro_token *dst, const struct macro_token *src)
46 token_copy (&dst->token, &src->token);
47 ss_alloc_substring (&dst->representation, src->representation);
51 macro_token_uninit (struct macro_token *mt)
53 token_uninit (&mt->token);
54 ss_dealloc (&mt->representation);
58 macro_token_to_representation (struct macro_token *mt, struct string *s)
60 ds_put_substring (s, mt->representation);
64 is_macro_keyword (struct substring s)
66 static struct stringi_set keywords = STRINGI_SET_INITIALIZER (keywords);
67 if (stringi_set_is_empty (&keywords))
69 static const char *kws[] = {
90 for (size_t i = 0; i < sizeof kws / sizeof *kws; i++)
91 stringi_set_insert (&keywords, kws[i]);
94 ss_ltrim (&s, ss_cstr ("!"));
95 return stringi_set_contains_len (&keywords, s.string, s.length);
99 macro_tokens_copy (struct macro_tokens *dst, const struct macro_tokens *src)
101 *dst = (struct macro_tokens) {
102 .mts = xmalloc (src->n * sizeof *dst->mts),
106 for (size_t i = 0; i < src->n; i++)
107 macro_token_copy (&dst->mts[i], &src->mts[i]);
111 macro_tokens_uninit (struct macro_tokens *mts)
113 for (size_t i = 0; i < mts->n; i++)
114 macro_token_uninit (&mts->mts[i]);
119 macro_tokens_add_uninit (struct macro_tokens *mts)
121 if (mts->n >= mts->allocated)
122 mts->mts = x2nrealloc (mts->mts, &mts->allocated, sizeof *mts->mts);
123 return &mts->mts[mts->n++];
127 macro_tokens_add (struct macro_tokens *mts, const struct macro_token *mt)
129 macro_token_copy (macro_tokens_add_uninit (mts), mt);
133 macro_tokens_from_string (struct macro_tokens *mts, const struct substring src,
134 enum segmenter_mode mode)
138 struct segmenter segmenter;
139 struct substring body;
142 struct state state = {
143 .segmenter = segmenter_init (mode, true),
146 struct state saved = state;
148 while (state.body.length > 0)
150 struct macro_token mt = {
151 .token = { .type = T_STOP },
152 .representation = { .string = state.body.string },
154 struct token *token = &mt.token;
156 struct scanner scanner;
157 scanner_init (&scanner, token);
161 enum segment_type type;
162 int seg_len = segmenter_push (&state.segmenter, state.body.string,
163 state.body.length, true, &type);
164 assert (seg_len >= 0);
166 struct substring segment = ss_head (state.body, seg_len);
167 ss_advance (&state.body, seg_len);
169 enum scan_result result = scanner_push (&scanner, type, segment, token);
170 if (result == SCAN_SAVE)
172 else if (result == SCAN_BACK)
177 else if (result == SCAN_DONE)
181 /* We have a token in 'token'. */
182 if (is_scan_type (token->type))
184 if (token->type != SCAN_SKIP)
187 /* XXX report error */
192 mt.representation.length = state.body.string - mt.representation.string;
193 macro_tokens_add (mts, &mt);
195 token_uninit (token);
200 macro_tokens_print (const struct macro_tokens *mts, FILE *stream)
202 for (size_t i = 0; i < mts->n; i++)
203 token_print (&mts->mts[i].token, stream);
208 TC_ENDCMD, /* No space before or after (new-line after). */
209 TC_BINOP, /* Space on both sides. */
210 TC_COMMA, /* Space afterward. */
211 TC_ID, /* Don't need spaces except sequentially. */
212 TC_PUNCT, /* Don't need spaces except sequentially. */
216 needs_space (enum token_class prev, enum token_class next)
218 /* Don't need a space before or after the end of a command.
219 (A new-line is needed afterward as a special case.) */
220 if (prev == TC_ENDCMD || next == TC_ENDCMD)
223 /* Binary operators always have a space on both sides. */
224 if (prev == TC_BINOP || next == TC_BINOP)
227 /* A comma always has a space afterward. */
228 if (prev == TC_COMMA)
231 /* Otherwise, PREV is TC_ID or TC_PUNCT, which only need a space if there are
232 two or them in a row. */
236 static enum token_class
237 classify_token (enum token_type type)
290 macro_tokens_to_representation (struct macro_tokens *mts, struct string *s,
291 size_t *ofs, size_t *len)
293 assert ((ofs != NULL) == (len != NULL));
298 for (size_t i = 0; i < mts->n; i++)
302 enum token_type prev = mts->mts[i - 1].token.type;
303 enum token_type next = mts->mts[i].token.type;
305 if (prev == T_ENDCMD)
306 ds_put_byte (s, '\n');
309 enum token_class pc = classify_token (prev);
310 enum token_class nc = classify_token (next);
311 if (needs_space (pc, nc))
312 ds_put_byte (s, ' ');
317 ofs[i] = s->ss.length;
318 macro_token_to_representation (&mts->mts[i], s);
320 len[i] = s->ss.length - ofs[i];
325 macro_destroy (struct macro *m)
332 for (size_t i = 0; i < m->n_params; i++)
334 struct macro_param *p = &m->params[i];
337 macro_tokens_uninit (&p->def);
345 token_uninit (&p->charend);
349 token_uninit (&p->enclose[0]);
350 token_uninit (&p->enclose[1]);
358 macro_tokens_uninit (&m->body);
363 macro_set_create (void)
365 struct macro_set *set = xmalloc (sizeof *set);
366 *set = (struct macro_set) {
367 .macros = HMAP_INITIALIZER (set->macros),
373 macro_set_destroy (struct macro_set *set)
378 struct macro *macro, *next;
379 HMAP_FOR_EACH_SAFE (macro, next, struct macro, hmap_node, &set->macros)
381 hmap_delete (&set->macros, ¯o->hmap_node);
382 macro_destroy (macro);
384 hmap_destroy (&set->macros);
389 hash_macro_name (const char *name)
391 return utf8_hash_case_string (name, 0);
394 static struct macro *
395 macro_set_find__ (struct macro_set *set, const char *name)
398 HMAP_FOR_EACH_WITH_HASH (macro, struct macro, hmap_node,
399 hash_macro_name (name), &set->macros)
400 if (!utf8_strcasecmp (macro->name, name))
407 macro_set_find (const struct macro_set *set, const char *name)
409 return macro_set_find__ (CONST_CAST (struct macro_set *, set), name);
412 /* Adds M to SET. M replaces any existing macro with the same name. Takes
415 macro_set_add (struct macro_set *set, struct macro *m)
417 struct macro *victim = macro_set_find__ (set, m->name);
420 hmap_delete (&set->macros, &victim->hmap_node);
421 macro_destroy (victim);
424 hmap_insert (&set->macros, &m->hmap_node, hash_macro_name (m->name));
427 struct macro_expansion_stack
429 const struct macro_expansion_stack *next;
431 const char *file_name;
442 /* Accumulating tokens in me->params toward the end of any type of
446 /* Expecting the opening delimiter of an ARG_ENCLOSE argument. */
449 /* Expecting a keyword for a keyword argument. */
452 /* Expecting an equal sign for a keyword argument. */
457 struct macro_expander
459 const struct macro_set *macros;
464 const struct macro *macro;
465 struct macro_tokens **args;
466 const struct macro_param *param;
470 me_finished (struct macro_expander *me)
472 for (size_t i = 0; i < me->macro->n_params; i++)
475 me->args[i] = xmalloc (sizeof *me->args[i]);
476 macro_tokens_copy (me->args[i], &me->macro->params[i].def);
482 me_next_arg (struct macro_expander *me)
486 assert (!me->macro->n_params);
487 return me_finished (me);
489 else if (me->param->positional)
492 if (me->param >= &me->macro->params[me->macro->n_params])
493 return me_finished (me);
496 me->state = (!me->param->positional ? ME_KEYWORD
497 : me->param->arg_type == ARG_ENCLOSE ? ME_ENCLOSE
504 for (size_t i = 0; i < me->macro->n_params; i++)
507 me->state = ME_KEYWORD;
510 return me_finished (me);
515 me_error (struct macro_expander *me)
517 me->state = ME_ERROR;
522 me_add_arg (struct macro_expander *me, const struct macro_token *mt)
524 const struct macro_param *p = me->param;
526 const struct token *token = &mt->token;
527 if ((token->type == T_ENDCMD || token->type == T_STOP)
528 && p->arg_type != ARG_CMDEND)
530 msg (SE, _("Unexpected end of command reading argument %s "
531 "to macro %s."), me->param->name, me->macro->name);
533 return me_error (me);
538 struct macro_tokens **argp = &me->args[p - me->macro->params];
540 *argp = xzalloc (sizeof **argp);
541 struct macro_tokens *arg = *argp;
542 if (p->arg_type == ARG_N_TOKENS)
544 macro_tokens_add (arg, mt);
545 if (arg->n >= p->n_tokens)
546 return me_next_arg (me);
549 else if (p->arg_type == ARG_CMDEND)
551 if (token->type == T_ENDCMD || token->type == T_STOP)
552 return me_next_arg (me);
553 macro_tokens_add (arg, mt);
558 const struct token *end
559 = p->arg_type == ARG_CHAREND ? &p->charend : &p->enclose[1];
560 if (token_equal (token, end))
561 return me_next_arg (me);
562 macro_tokens_add (arg, mt);
568 me_expected (struct macro_expander *me, const struct macro_token *actual,
569 const struct token *expected)
571 const struct substring actual_s
572 = (actual->representation.length ? actual->representation
573 : ss_cstr (_("<end of input>")));
574 char *expected_s = token_to_string (expected);
575 msg (SE, _("Found `%.*s' while expecting `%s' reading argument %s "
577 (int) actual_s.length, actual_s.string, expected_s,
578 me->param->name, me->macro->name);
581 return me_error (me);
585 me_enclose (struct macro_expander *me, const struct macro_token *mt)
587 const struct token *token = &mt->token;
590 if (token_equal (&me->param->enclose[0], token))
596 return me_expected (me, mt, &me->param->enclose[0]);
599 static const struct macro_param *
600 macro_find_parameter_by_name (const struct macro *m, struct substring name)
602 ss_ltrim (&name, ss_cstr ("!"));
604 for (size_t i = 0; i < m->n_params; i++)
606 const struct macro_param *p = &m->params[i];
607 struct substring p_name = ss_cstr (p->name + 1);
608 if (!utf8_strncasecmp (p_name.string, p_name.length,
609 name.string, name.length))
616 me_keyword (struct macro_expander *me, const struct macro_token *mt)
618 const struct token *token = &mt->token;
619 if (token->type != T_ID)
620 return me_finished (me);
622 const struct macro_param *p = macro_find_parameter_by_name (me->macro,
626 size_t arg_index = p - me->macro->params;
628 if (me->args[arg_index])
631 _("Argument %s multiply specified in call to macro %s."),
632 p->name, me->macro->name);
633 return me_error (me);
637 me->state = ME_EQUALS;
641 return me_finished (me);
645 me_equals (struct macro_expander *me, const struct macro_token *mt)
647 const struct token *token = &mt->token;
650 if (token->type == T_EQUALS)
656 return me_expected (me, mt, &(struct token) { .type = T_EQUALS });
660 macro_expander_create (const struct macro_set *macros,
661 const struct token *token,
662 struct macro_expander **mep)
665 if (macro_set_is_empty (macros))
667 if (token->type != T_ID && token->type != T_MACRO_ID)
670 const struct macro *macro = macro_set_find (macros, token->string.string);
674 struct macro_expander *me = xmalloc (sizeof *me);
675 *me = (struct macro_expander) {
682 if (!macro->n_params)
686 me->state = (!macro->params[0].positional ? ME_KEYWORD
687 : macro->params[0].arg_type == ARG_ENCLOSE ? ME_ENCLOSE
689 me->args = xcalloc (macro->n_params, sizeof *me->args);
690 me->param = macro->params;
696 macro_expander_destroy (struct macro_expander *me)
701 for (size_t i = 0; i < me->macro->n_params; i++)
704 macro_tokens_uninit (me->args[i]);
711 /* Adds TOKEN to the collection of tokens in ME that potentially need to be
714 Returns -1 if the tokens added do not actually invoke a macro. The caller
715 should consume the first token without expanding it.
717 Returns 0 if the macro expander needs more tokens, for macro arguments or to
718 decide whether this is actually a macro invocation. The caller should call
719 macro_expander_add() again with the next token.
721 Returns a positive number to indicate that the returned number of tokens
722 invoke a macro. The number returned might be less than the number of tokens
723 added because it can take a few tokens of lookahead to determine whether the
724 macro invocation is finished. The caller should call
725 macro_expander_get_expansion() to obtain the expansion. */
727 macro_expander_add (struct macro_expander *me, const struct macro_token *mt)
735 return me_add_arg (me, mt);
738 return me_enclose (me, mt);
741 return me_keyword (me, mt);
744 return me_equals (me, mt);
751 /* Each argument to a macro function is one of:
753 - A quoted string or other single literal token.
755 - An argument to the macro being expanded, e.g. !1 or a named argument.
759 - A function invocation.
761 Each function invocation yields a character sequence to be turned into a
762 sequence of tokens. The case where that character sequence is a single
763 quoted string is an important special case.
765 struct parse_macro_function_ctx
767 const struct macro_token *input;
769 int nesting_countdown;
770 const struct macro_set *macros;
771 const struct macro_expander *me;
772 const struct macro_expansion_stack *stack;
773 struct string_map *vars;
778 macro_expand (const struct macro_tokens *,
779 int nesting_countdown, const struct macro_set *,
780 const struct macro_expander *, struct string_map *vars,
781 const struct macro_expansion_stack *stack,
782 bool *expand, bool *break_,
783 struct macro_tokens *exp);
786 expand_macro_function (struct parse_macro_function_ctx *ctx,
787 struct string *output, size_t *input_consumed);
789 /* Returns true if the pair of tokens starting at offset OFS within MTS are !*,
792 is_bang_star (const struct macro_token *mts, size_t n, size_t ofs)
795 && mts[ofs].token.type == T_MACRO_ID
796 && ss_equals (mts[ofs].token.string, ss_cstr ("!"))
797 && mts[ofs + 1].token.type == T_ASTERISK);
801 parse_function_arg (struct parse_macro_function_ctx *ctx,
802 size_t i, struct string *farg)
804 const struct macro_token *tokens = ctx->input;
805 const struct token *token = &tokens[i].token;
806 if (token->type == T_MACRO_ID)
808 const struct macro_param *param = macro_find_parameter_by_name (
809 ctx->me->macro, token->string);
812 size_t param_idx = param - ctx->me->macro->params;
813 const struct macro_tokens *marg = ctx->me->args[param_idx];
814 for (size_t i = 0; i < marg->n; i++)
817 ds_put_byte (farg, ' ');
818 ds_put_substring (farg, marg->mts[i].representation);
823 if (is_bang_star (ctx->input, ctx->n_input, i))
825 for (size_t i = 0; i < ctx->me->macro->n_params; i++)
827 if (!ctx->me->macro->params[i].positional)
830 const struct macro_tokens *marg = ctx->me->args[i];
831 for (size_t j = 0; j < marg->n; j++)
834 ds_put_byte (farg, ' ');
835 ds_put_substring (farg, marg->mts[j].representation);
843 const char *value = string_map_find__ (ctx->vars,
844 token->string.string,
845 token->string.length);
848 ds_put_cstr (farg, value);
853 struct parse_macro_function_ctx subctx = {
854 .input = &ctx->input[i],
855 .n_input = ctx->n_input - i,
856 .nesting_countdown = ctx->nesting_countdown,
857 .macros = ctx->macros,
861 .expand = ctx->expand,
863 size_t subinput_consumed;
864 if (expand_macro_function (&subctx, farg, &subinput_consumed))
865 return subinput_consumed;
868 ds_put_substring (farg, tokens[i].representation);
873 parse_macro_function (struct parse_macro_function_ctx *ctx,
874 struct string_array *args,
875 struct substring function,
876 int min_args, int max_args,
877 size_t *input_consumed)
879 const struct macro_token *tokens = ctx->input;
880 size_t n_tokens = ctx->n_input;
883 || tokens[0].token.type != T_MACRO_ID
884 || !ss_equals_case (tokens[0].token.string, function)) /* XXX abbrevs allowed */
887 if (n_tokens < 2 || tokens[1].token.type != T_LPAREN)
889 printf ("`(' expected following %s'\n", function.string);
893 string_array_init (args);
895 for (size_t i = 2;; )
899 if (tokens[i].token.type == T_RPAREN)
901 *input_consumed = i + 1;
902 if (args->n < min_args || args->n > max_args)
904 printf ("Wrong number of arguments to %s.\n", function.string);
910 struct string s = DS_EMPTY_INITIALIZER;
911 i += parse_function_arg (ctx, i, &s);
917 string_array_append_nocopy (args, ds_steal_cstr (&s));
919 if (tokens[i].token.type == T_COMMA)
921 else if (tokens[i].token.type != T_RPAREN)
923 printf ("Expecting `,' or `)' in %s invocation.", function.string);
929 printf ("Missing closing parenthesis in arguments to %s.\n",
933 string_array_destroy (args);
938 unquote_string (const char *s, struct string *content)
940 struct string_lexer slex;
941 string_lexer_init (&slex, s, strlen (s), SEG_MODE_INTERACTIVE /* XXX */,
945 if (!string_lexer_next (&slex, &token1))
948 if (token1.type != T_STRING)
950 token_uninit (&token1);
955 if (string_lexer_next (&slex, &token2))
957 token_uninit (&token1);
958 token_uninit (&token2);
962 ds_put_substring (content, token1.string);
963 token_uninit (&token1);
968 unquote_string_in_place (const char *s, struct string *tmp)
971 return unquote_string (s, tmp) ? ds_cstr (tmp) : s;
975 parse_integer (const char *s, int *np)
980 long int n = strtol (s, &tail, 10);
981 *np = n < INT_MIN ? INT_MIN : n > INT_MAX ? INT_MAX : n;
982 tail += strspn (tail, CC_SPACES);
983 return *tail == '\0' && errno != ERANGE && n == *np;
987 expand_macro_function (struct parse_macro_function_ctx *ctx,
988 struct string *output,
989 size_t *input_consumed)
991 struct string_array args;
993 if (parse_macro_function (ctx, &args, ss_cstr ("!length"), 1, 1,
995 ds_put_format (output, "%zu", strlen (args.strings[0]));
996 else if (parse_macro_function (ctx, &args, ss_cstr ("!blanks"), 1, 1,
1000 if (!parse_integer (args.strings[0], &n))
1002 printf ("argument to !BLANKS must be non-negative integer (not \"%s\")\n", args.strings[0]);
1003 string_array_destroy (&args);
1007 ds_put_byte_multiple (output, ' ', n);
1009 else if (parse_macro_function (ctx, &args, ss_cstr ("!concat"), 1, INT_MAX,
1012 for (size_t i = 0; i < args.n; i++)
1013 if (!unquote_string (args.strings[i], output))
1014 ds_put_cstr (output, args.strings[i]);
1016 else if (parse_macro_function (ctx, &args, ss_cstr ("!head"), 1, 1,
1020 const char *s = unquote_string_in_place (args.strings[0], &tmp);
1022 struct macro_tokens mts = { .n = 0 };
1023 macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */);
1025 ds_put_substring (output, mts.mts[0].representation);
1026 macro_tokens_uninit (&mts);
1029 else if (parse_macro_function (ctx, &args, ss_cstr ("!index"), 2, 2,
1032 const char *haystack = args.strings[0];
1033 const char *needle = strstr (haystack, args.strings[1]);
1034 ds_put_format (output, "%zu", needle ? needle - haystack + 1 : 0);
1036 else if (parse_macro_function (ctx, &args, ss_cstr ("!quote"), 1, 1,
1039 if (unquote_string (args.strings[0], NULL))
1040 ds_put_cstr (output, args.strings[0]);
1043 ds_extend (output, strlen (args.strings[0]) + 2);
1044 ds_put_byte (output, '\'');
1045 for (const char *p = args.strings[0]; *p; p++)
1048 ds_put_byte (output, '\'');
1049 ds_put_byte (output, *p);
1051 ds_put_byte (output, '\'');
1054 else if (parse_macro_function (ctx, &args, ss_cstr ("!substr"), 2, 3,
1058 if (!parse_integer (args.strings[1], &start) || start < 1)
1060 printf ("second argument to !SUBSTR must be positive integer (not \"%s\")\n", args.strings[1]);
1061 string_array_destroy (&args);
1065 int count = INT_MAX;
1066 if (args.n > 2 && (!parse_integer (args.strings[2], &count) || count < 0))
1068 printf ("third argument to !SUBSTR must be non-negative integer (not \"%s\")\n", args.strings[1]);
1069 string_array_destroy (&args);
1073 struct substring s = ss_cstr (args.strings[0]);
1074 ds_put_substring (output, ss_substr (s, start - 1, count));
1076 else if (parse_macro_function (ctx, &args, ss_cstr ("!tail"), 1, 1,
1080 const char *s = unquote_string_in_place (args.strings[0], &tmp);
1082 struct macro_tokens mts = { .n = 0 };
1083 macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */);
1086 struct macro_tokens tail = { .mts = mts.mts + 1, .n = mts.n - 1 };
1087 macro_tokens_to_representation (&tail, output, NULL, NULL);
1089 macro_tokens_uninit (&mts);
1092 else if (parse_macro_function (ctx, &args, ss_cstr ("!unquote"), 1, 1,
1095 if (!unquote_string (args.strings[0], output))
1096 ds_put_cstr (output, args.strings[0]);
1098 else if (parse_macro_function (ctx, &args, ss_cstr ("!upcase"), 1, 1,
1102 const char *s = unquote_string_in_place (args.strings[0], &tmp);
1103 char *upper = utf8_to_upper (s);
1104 ds_put_cstr (output, upper);
1108 else if (parse_macro_function (ctx, &args, ss_cstr ("!eval"), 1, 1,
1111 struct macro_tokens mts = { .n = 0 };
1112 macro_tokens_from_string (&mts, ss_cstr (args.strings[0]),
1113 SEG_MODE_INTERACTIVE /* XXX */);
1114 struct macro_tokens exp = { .n = 0 };
1115 macro_expand (&mts, ctx->nesting_countdown - 1, ctx->macros, ctx->me,
1117 &(struct macro_expansion_stack) {
1120 }, ctx->expand, NULL, &exp);
1121 macro_tokens_to_representation (&exp, output, NULL, NULL);
1122 macro_tokens_uninit (&exp);
1123 macro_tokens_uninit (&mts);
1125 else if (ctx->n_input > 0
1126 && ctx->input[0].token.type == T_MACRO_ID
1127 && ss_equals_case (ctx->input[0].token.string, ss_cstr ("!null")))
1129 *input_consumed = 1;
1135 string_array_destroy (&args);
1141 int nesting_countdown;
1142 const struct macro_set *macros;
1143 const struct macro_expander *me;
1144 const struct macro_expansion_stack *stack;
1145 struct string_map *vars;
1149 static char *macro_evaluate_or (const struct expr_context *ctx,
1150 const struct macro_token **tokens,
1151 const struct macro_token *end);
1154 macro_evaluate_literal (const struct expr_context *ctx,
1155 const struct macro_token **tokens,
1156 const struct macro_token *end)
1158 const struct macro_token *p = *tokens;
1161 if (p->token.type == T_LPAREN)
1164 char *value = macro_evaluate_or (ctx, &p, end);
1167 if (p >= end || p->token.type != T_RPAREN)
1170 printf ("expecting ')' in macro expression\n");
1178 struct parse_macro_function_ctx fctx = {
1181 .nesting_countdown = ctx->nesting_countdown,
1182 .macros = ctx->macros,
1184 .stack = ctx->stack,
1186 .expand = ctx->expand,
1188 struct string function_output = DS_EMPTY_INITIALIZER;
1189 size_t function_consumed = parse_function_arg (&fctx, 0, &function_output);
1190 struct string unquoted = DS_EMPTY_INITIALIZER;
1191 if (unquote_string (ds_cstr (&function_output), &unquoted))
1193 ds_swap (&function_output, &unquoted);
1194 ds_destroy (&unquoted);
1196 *tokens = p + function_consumed;
1197 return ds_steal_cstr (&function_output);
1200 /* Returns true if MT is valid as a macro operator. Only operators written as
1201 symbols (e.g. <>) are usable in macro expressions, not operator written as
1202 letters (e.g. EQ). */
1204 is_macro_operator (const struct macro_token *mt)
1206 return (mt->representation.length > 0
1207 && !c_isalpha (mt->representation.string[0]));
1210 static enum token_type
1211 parse_relational_op (const struct macro_token *mt)
1213 switch (mt->token.type)
1223 return is_macro_operator (mt) ? mt->token.type : T_STOP;
1226 return (ss_equals_case (mt->token.string, ss_cstr ("!EQ")) ? T_EQ
1227 : ss_equals_case (mt->token.string, ss_cstr ("!NE")) ? T_NE
1228 : ss_equals_case (mt->token.string, ss_cstr ("!LT")) ? T_LT
1229 : ss_equals_case (mt->token.string, ss_cstr ("!GT")) ? T_GT
1230 : ss_equals_case (mt->token.string, ss_cstr ("!LE")) ? T_LE
1231 : ss_equals_case (mt->token.string, ss_cstr ("!GE")) ? T_GE
1240 macro_evaluate_relational (const struct expr_context *ctx,
1241 const struct macro_token **tokens,
1242 const struct macro_token *end)
1244 const struct macro_token *p = *tokens;
1245 char *lhs = macro_evaluate_literal (ctx, &p, end);
1249 enum token_type op = p >= end ? T_STOP : parse_relational_op (p);
1257 char *rhs = macro_evaluate_literal (ctx, &p, end);
1264 struct string lhs_tmp, rhs_tmp;
1265 int cmp = strcmp/*XXX*/ (unquote_string_in_place (lhs, &lhs_tmp),
1266 unquote_string_in_place (rhs, &rhs_tmp));
1267 ds_destroy (&lhs_tmp);
1268 ds_destroy (&rhs_tmp);
1273 bool b = (op == T_EQUALS || op == T_EQ ? !cmp
1275 : op == T_LT ? cmp < 0
1276 : op == T_GT ? cmp > 0
1277 : op == T_LE ? cmp <= 0
1278 :/*op == T_GE*/cmp >= 0);
1281 return xstrdup (b ? "1" : "0");
1285 macro_evaluate_not (const struct expr_context *ctx,
1286 const struct macro_token **tokens,
1287 const struct macro_token *end)
1289 const struct macro_token *p = *tokens;
1291 unsigned int negations = 0;
1293 && (ss_equals_case (p->representation, ss_cstr ("!NOT"))
1294 || ss_equals (p->representation, ss_cstr ("~"))))
1300 char *operand = macro_evaluate_relational (ctx, &p, end);
1301 if (!operand || !negations)
1307 bool b = strcmp (operand, "0") ^ (negations & 1);
1310 return xstrdup (b ? "1" : "0");
1314 macro_evaluate_and (const struct expr_context *ctx,
1315 const struct macro_token **tokens,
1316 const struct macro_token *end)
1318 const struct macro_token *p = *tokens;
1319 char *lhs = macro_evaluate_not (ctx, &p, end);
1324 && (ss_equals_case (p->representation, ss_cstr ("!AND"))
1325 || ss_equals (p->representation, ss_cstr ("&"))))
1328 char *rhs = macro_evaluate_not (ctx, &p, end);
1335 bool b = strcmp (lhs, "0") && strcmp (rhs, "0");
1338 lhs = xstrdup (b ? "1" : "0");
1345 macro_evaluate_or (const struct expr_context *ctx,
1346 const struct macro_token **tokens,
1347 const struct macro_token *end)
1349 const struct macro_token *p = *tokens;
1350 char *lhs = macro_evaluate_and (ctx, &p, end);
1355 && (ss_equals_case (p->representation, ss_cstr ("!OR"))
1356 || ss_equals (p->representation, ss_cstr ("|"))))
1359 char *rhs = macro_evaluate_and (ctx, &p, end);
1366 bool b = strcmp (lhs, "0") || strcmp (rhs, "0");
1369 lhs = xstrdup (b ? "1" : "0");
1376 macro_evaluate_expression (const struct macro_token **tokens, size_t n_tokens,
1377 int nesting_countdown, const struct macro_set *macros,
1378 const struct macro_expander *me,
1379 const struct macro_expansion_stack *stack,
1380 struct string_map *vars, bool *expand)
1382 const struct expr_context ctx = {
1383 .nesting_countdown = nesting_countdown,
1390 return macro_evaluate_or (&ctx, tokens, *tokens + n_tokens);
1394 macro_evaluate_number (const struct macro_token **tokens, size_t n_tokens,
1395 int nesting_countdown, const struct macro_set *macros,
1396 const struct macro_expander *me,
1397 const struct macro_expansion_stack *stack,
1398 struct string_map *vars,
1399 bool *expand, double *number)
1401 char *s = macro_evaluate_expression (tokens, n_tokens, nesting_countdown,
1402 macros, me, stack, vars, expand);
1406 struct macro_tokens mts = { .n = 0 };
1407 macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */);
1408 if (mts.n != 1 || !token_is_number (&mts.mts[0].token))
1410 macro_tokens_print (&mts, stdout);
1411 printf ("expression must evaluate to a number (not %s)\n", s);
1413 macro_tokens_uninit (&mts);
1417 *number = token_number (&mts.mts[0].token);
1419 macro_tokens_uninit (&mts);
1423 static const struct macro_token *
1424 find_ifend_clause (const struct macro_token *p, const struct macro_token *end)
1427 for (; p < end; p++)
1429 if (p->token.type != T_MACRO_ID)
1432 if (ss_equals_case (p->token.string, ss_cstr ("!IF")))
1434 else if (ss_equals_case (p->token.string, ss_cstr ("!IFEND")))
1440 else if (ss_equals_case (p->token.string, ss_cstr ("!ELSE")) && !nesting)
1447 macro_expand_if (const struct macro_token *tokens, size_t n_tokens,
1448 int nesting_countdown, const struct macro_set *macros,
1449 const struct macro_expander *me,
1450 const struct macro_expansion_stack *stack,
1451 struct string_map *vars,
1452 bool *expand, bool *break_, struct macro_tokens *exp)
1454 const struct macro_token *p = tokens;
1455 const struct macro_token *end = tokens + n_tokens;
1457 if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!IF")))
1461 char *result = macro_evaluate_expression (&p, end - p,
1462 nesting_countdown, macros, me,
1463 stack, vars, expand);
1466 bool b = strcmp (result, "0");
1470 || p->token.type != T_MACRO_ID
1471 || !ss_equals_case (p->token.string, ss_cstr ("!THEN")))
1473 printf ("!THEN expected\n");
1477 const struct macro_token *start_then = p + 1;
1478 const struct macro_token *end_then = find_ifend_clause (start_then, end);
1481 printf ("!ELSE or !IFEND expected\n");
1485 const struct macro_token *start_else, *end_if;
1486 if (ss_equals_case (end_then->token.string, ss_cstr ("!ELSE")))
1488 start_else = end_then + 1;
1489 end_if = find_ifend_clause (start_else, end);
1491 || !ss_equals_case (end_if->token.string, ss_cstr ("!IFEND")))
1493 printf ("!IFEND expected\n");
1503 const struct macro_token *start;
1508 n = end_then - start_then;
1510 else if (start_else)
1513 n = end_if - start_else;
1523 struct macro_tokens mts = {
1524 .mts = CONST_CAST (struct macro_token *, start),
1527 macro_expand (&mts, nesting_countdown, macros, me, vars,
1528 &(struct macro_expansion_stack) {
1532 expand, break_, exp);
1534 return (end_if + 1) - tokens;
1537 static void PRINTF_FORMAT (2, 3)
1538 macro_error (const struct macro_expansion_stack *stack,
1539 const char *format, ...)
1542 va_start (args, format);
1543 char *s = xvasprintf (format, args);
1546 /* foo.sps:12: While expanding 'innermost',
1547 foo.sps:23: inside expansion of 'next_inner',
1548 foo.sps:34: inside expansion of 'next_inner2',
1549 foo.sps:45: inside expansion of 'outermost':
1551 struct string header = DS_EMPTY_INITIALIZER;
1552 if (stack->file_name || stack->first_line)
1554 if (stack->file_name)
1555 ds_put_format (&header, "%s:", stack->file_name);
1556 if (stack->first_line)
1558 if (stack->last_line > stack->first_line)
1559 ds_put_format (&header, "%d-%d:",
1560 stack->first_line, stack->last_line);
1562 ds_put_format (&header, "%d", stack->first_line);
1564 ds_put_byte (&header, ' ');
1566 ds_put_format (&header, "While expanding \"%s\"\n", stack->name);
1567 while ((stack = stack->next) != NULL)
1569 if (stack->file_name || stack->first_line)
1571 if (stack->file_name)
1572 ds_put_format (&header, "%s:", stack->file_name);
1573 if (stack->first_line)
1575 if (stack->last_line > stack->first_line)
1576 ds_put_format (&header, "%d-%d:",
1577 stack->first_line, stack->last_line);
1579 ds_put_format (&header, "%d", stack->first_line);
1581 ds_put_byte (&header, ' ');
1583 ds_put_format (&header, ", inside expansion of \"%s\"\n", stack->name);
1585 msg (SE, "%s: %s", ds_cstr (&header), s);
1587 ds_destroy (&header);
1592 macro_parse_let (const struct macro_token *tokens, size_t n_tokens,
1593 int nesting_countdown, const struct macro_set *macros,
1594 const struct macro_expander *me,
1595 const struct macro_expansion_stack *stack,
1596 struct string_map *vars, bool *expand)
1598 const struct macro_token *p = tokens;
1599 const struct macro_token *end = tokens + n_tokens;
1601 if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!LET")))
1605 if (p >= end || p->token.type != T_MACRO_ID)
1607 macro_error (stack, "expected macro variable name following !LET");
1610 const struct substring var_name = p->token.string;
1611 if (is_macro_keyword (var_name)
1612 || macro_find_parameter_by_name (me->macro, var_name))
1614 printf ("cannot use argument name or macro keyword %.*s as !LET variable\n", (int) var_name.length, var_name.string);
1619 if (p >= end || p->token.type != T_EQUALS)
1621 printf ("expected = following !LET\n");
1626 char *value = macro_evaluate_expression (&p, end - p,
1627 nesting_countdown, macros, me, stack,
1632 string_map_replace_nocopy (vars, ss_xstrdup (var_name), value);
1636 static const struct macro_token *
1637 find_doend (const struct macro_token *p, const struct macro_token *end)
1640 for (; p < end; p++)
1642 if (p->token.type != T_MACRO_ID)
1645 if (ss_equals_case (p->token.string, ss_cstr ("!DO")))
1647 else if (ss_equals_case (p->token.string, ss_cstr ("!DOEND")))
1654 printf ("missing !DOEND\n");
1659 macro_expand_do (const struct macro_token *tokens, size_t n_tokens,
1660 int nesting_countdown, const struct macro_set *macros,
1661 const struct macro_expander *me,
1662 const struct macro_expansion_stack *stack,
1663 struct string_map *vars,
1664 bool *expand, struct macro_tokens *exp)
1666 const struct macro_token *p = tokens;
1667 const struct macro_token *end = tokens + n_tokens;
1669 if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!DO")))
1673 if (p >= end || p->token.type != T_MACRO_ID)
1675 printf ("expected macro variable name following !DO\n");
1678 const struct substring var_name = p->token.string;
1679 if (is_macro_keyword (var_name)
1680 || macro_find_parameter_by_name (me->macro, var_name))
1682 printf ("cannot use argument name or macro keyword %.*s as !DO variable\n", (int) var_name.length, var_name.string);
1687 struct macro_expansion_stack next_stack = {
1688 .name = "!DO", .next = stack,
1690 int miterate = settings_get_miterate ();
1691 if (p < end && p->token.type == T_MACRO_ID
1692 && ss_equals_case (p->token.string, ss_cstr ("!IN")))
1695 char *list = macro_evaluate_expression (&p, end - p,
1696 nesting_countdown, macros, me,
1697 &next_stack, vars, expand);
1701 struct macro_tokens items = { .n = 0 };
1702 macro_tokens_from_string (&items, ss_cstr (list),
1703 SEG_MODE_INTERACTIVE /* XXX */);
1706 const struct macro_token *do_end = find_doend (p, end);
1709 macro_tokens_uninit (&items);
1713 const struct macro_tokens inner = {
1714 .mts = CONST_CAST (struct macro_token *, p),
1717 for (size_t i = 0; i < items.n; i++)
1721 printf ("exceeded maximum number of iterations %d\n", miterate);
1724 string_map_replace_nocopy (vars, ss_xstrdup (var_name),
1725 ss_xstrdup (items.mts[i].representation));
1727 bool break_ = false;
1728 macro_expand (&inner, nesting_countdown, macros,
1729 me, vars, &next_stack, expand, &break_, exp);
1733 return do_end - tokens + 1;
1735 else if (p < end && p->token.type == T_EQUALS)
1739 if (!macro_evaluate_number (&p, end - p, nesting_countdown, macros, me,
1740 &next_stack, vars, expand, &first))
1743 if (p >= end || p->token.type != T_MACRO_ID
1744 || !ss_equals_case (p->token.string, ss_cstr ("!TO")))
1746 printf ("expecting !TO\n");
1752 if (!macro_evaluate_number (&p, end - p, nesting_countdown, macros, me,
1753 &next_stack, vars, expand, &last))
1757 if (p < end && p->token.type == T_MACRO_ID
1758 && ss_equals_case (p->token.string, ss_cstr ("!BY")))
1761 if (!macro_evaluate_number (&p, end - p, nesting_countdown, macros, me,
1762 &next_stack, vars, expand, &by))
1767 printf ("!BY value cannot be zero\n");
1772 const struct macro_token *do_end = find_doend (p, end);
1775 const struct macro_tokens inner = {
1776 .mts = CONST_CAST (struct macro_token *, p),
1780 if ((by > 0 && first <= last) || (by < 0 && first >= last))
1783 for (double index = first;
1784 by > 0 ? (index <= last) : (index >= last);
1789 printf ("exceeded maximum number of iterations %d\n",
1794 char index_s[DBL_BUFSIZE_BOUND];
1795 c_dtoastr (index_s, sizeof index_s, 0, 0, index);
1796 string_map_replace_nocopy (vars, ss_xstrdup (var_name),
1799 bool break_ = false;
1800 macro_expand (&inner, nesting_countdown, macros,
1801 me, vars, &next_stack, expand, &break_, exp);
1807 return do_end - tokens + 1;
1811 printf ("expecting = or !IN in !DO loop\n");
1817 macro_expand (const struct macro_tokens *mts,
1818 int nesting_countdown, const struct macro_set *macros,
1819 const struct macro_expander *me, struct string_map *vars,
1820 const struct macro_expansion_stack *stack,
1821 bool *expand, bool *break_, struct macro_tokens *exp)
1823 if (nesting_countdown <= 0)
1825 printf ("maximum nesting level exceeded\n");
1826 for (size_t i = 0; i < mts->n; i++)
1827 macro_tokens_add (exp, &mts->mts[i]);
1831 struct string_map own_vars = STRING_MAP_INITIALIZER (own_vars);
1835 for (size_t i = 0; i < mts->n && (!break_ || !*break_); i++)
1837 const struct macro_token *mt = &mts->mts[i];
1838 const struct token *token = &mt->token;
1839 if (token->type == T_MACRO_ID && me)
1841 const struct macro_param *param = macro_find_parameter_by_name (
1842 me->macro, token->string);
1845 const struct macro_tokens *arg = me->args[param - me->macro->params];
1846 //macro_tokens_print (arg, stdout);
1847 if (*expand && param->expand_arg)
1848 macro_expand (arg, nesting_countdown, macros, NULL, NULL,
1849 &(struct macro_expansion_stack) {
1850 .name = param->name,
1852 }, expand, break_, exp);
1854 for (size_t i = 0; i < arg->n; i++)
1855 macro_tokens_add (exp, &arg->mts[i]);
1859 if (is_bang_star (mts->mts, mts->n, i))
1861 for (size_t j = 0; j < me->macro->n_params; j++)
1863 const struct macro_param *param = &me->macro->params[j];
1864 if (!param->positional)
1867 const struct macro_tokens *arg = me->args[j];
1868 if (*expand && param->expand_arg)
1869 macro_expand (arg, nesting_countdown, macros, NULL, NULL,
1870 &(struct macro_expansion_stack) {
1873 }, expand, break_, exp);
1875 for (size_t k = 0; k < arg->n; k++)
1876 macro_tokens_add (exp, &arg->mts[k]);
1882 size_t n = macro_expand_if (&mts->mts[i], mts->n - i,
1883 nesting_countdown, macros, me, stack,
1884 vars, expand, break_, exp);
1892 if (token->type == T_MACRO_ID && vars)
1894 const char *value = string_map_find__ (vars, token->string.string,
1895 token->string.length);
1898 macro_tokens_from_string (exp, ss_cstr (value),
1899 SEG_MODE_INTERACTIVE /* XXX */);
1906 struct macro_expander *subme;
1907 int retval = macro_expander_create (macros, token, &subme);
1908 for (size_t j = 1; !retval; j++)
1910 const struct macro_token endcmd = { .token = { .type = T_ENDCMD } };
1911 retval = macro_expander_add (
1912 subme, i + j < mts->n ? &mts->mts[i + j] : &endcmd);
1917 macro_expand (&subme->macro->body, nesting_countdown - 1, macros,
1919 &(struct macro_expansion_stack) {
1920 .name = subme->macro->name,
1921 .file_name = subme->macro->file_name,
1922 .first_line = subme->macro->first_line,
1923 .last_line = subme->macro->last_line,
1925 }, expand, break_, exp);
1926 macro_expander_destroy (subme);
1930 macro_expander_destroy (subme);
1933 if (token->type != T_MACRO_ID)
1935 macro_tokens_add (exp, mt);
1939 if (ss_equals_case (token->string, ss_cstr ("!break")))
1942 printf ("!BREAK outside !DO\n");
1950 struct parse_macro_function_ctx ctx = {
1951 .input = &mts->mts[i],
1952 .n_input = mts->n - i,
1953 .nesting_countdown = nesting_countdown,
1960 struct string function_output = DS_EMPTY_INITIALIZER;
1961 size_t function_consumed;
1962 if (expand_macro_function (&ctx, &function_output, &function_consumed))
1964 i += function_consumed - 1;
1966 macro_tokens_from_string (exp, function_output.ss,
1967 SEG_MODE_INTERACTIVE /* XXX */);
1968 ds_destroy (&function_output);
1973 size_t n = macro_parse_let (&mts->mts[i], mts->n - i,
1974 nesting_countdown, macros, me, stack,
1982 n = macro_expand_do (&mts->mts[i], mts->n - i,
1983 nesting_countdown, macros, me, stack, vars,
1991 if (ss_equals_case (token->string, ss_cstr ("!onexpand")))
1993 else if (ss_equals_case (token->string, ss_cstr ("!offexpand")))
1996 macro_tokens_add (exp, mt);
1998 if (vars == &own_vars)
1999 string_map_destroy (&own_vars);
2003 macro_expander_get_expansion (struct macro_expander *me, struct macro_tokens *exp)
2006 struct macro_expansion_stack stack = {
2007 .name = me->macro->name,
2008 .file_name = me->macro->file_name,
2009 .first_line = me->macro->first_line,
2010 .last_line = me->macro->last_line,
2012 macro_expand (&me->macro->body, settings_get_mnest (),
2013 me->macros, me, NULL, &stack, &expand, NULL, exp);