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"
35 #include "gl/c-ctype.h"
38 #define _(msgid) gettext (msgid)
41 macro_token_copy (struct macro_token *dst, const struct macro_token *src)
43 token_copy (&dst->token, &src->token);
44 ss_alloc_substring (&dst->representation, src->representation);
48 macro_token_uninit (struct macro_token *mt)
50 token_uninit (&mt->token);
51 ss_dealloc (&mt->representation);
55 macro_token_to_representation (struct macro_token *mt, struct string *s)
57 ds_put_substring (s, mt->representation);
61 macro_tokens_copy (struct macro_tokens *dst, const struct macro_tokens *src)
63 *dst = (struct macro_tokens) {
64 .mts = xmalloc (src->n * sizeof *dst->mts),
68 for (size_t i = 0; i < src->n; i++)
69 macro_token_copy (&dst->mts[i], &src->mts[i]);
73 macro_tokens_uninit (struct macro_tokens *mts)
75 for (size_t i = 0; i < mts->n; i++)
76 macro_token_uninit (&mts->mts[i]);
81 macro_tokens_add_uninit (struct macro_tokens *mts)
83 if (mts->n >= mts->allocated)
84 mts->mts = x2nrealloc (mts->mts, &mts->allocated, sizeof *mts->mts);
85 return &mts->mts[mts->n++];
89 macro_tokens_add (struct macro_tokens *mts, const struct macro_token *mt)
91 macro_token_copy (macro_tokens_add_uninit (mts), mt);
95 macro_tokens_from_string (struct macro_tokens *mts, const struct substring src,
96 enum segmenter_mode mode)
100 struct segmenter segmenter;
101 struct substring body;
104 struct state state = {
105 .segmenter = SEGMENTER_INIT (mode),
108 struct state saved = state;
110 while (state.body.length > 0)
112 struct macro_token mt = {
113 .token = { .type = T_STOP },
114 .representation = { .string = state.body.string },
116 struct token *token = &mt.token;
118 struct scanner scanner;
119 scanner_init (&scanner, token);
123 enum segment_type type;
124 int seg_len = segmenter_push (&state.segmenter, state.body.string,
125 state.body.length, true, &type);
126 assert (seg_len >= 0);
128 struct substring segment = ss_head (state.body, seg_len);
129 ss_advance (&state.body, seg_len);
131 enum scan_result result = scanner_push (&scanner, type, segment, token);
132 if (result == SCAN_SAVE)
134 else if (result == SCAN_BACK)
139 else if (result == SCAN_DONE)
143 /* We have a token in 'token'. */
144 if (is_scan_type (token->type))
146 if (token->type != SCAN_SKIP)
149 /* XXX report error */
154 mt.representation.length = state.body.string - mt.representation.string;
155 macro_tokens_add (mts, &mt);
157 token_uninit (token);
162 macro_tokens_print (const struct macro_tokens *mts, FILE *stream)
164 for (size_t i = 0; i < mts->n; i++)
165 token_print (&mts->mts[i].token, stream);
170 TC_ENDCMD, /* No space before or after (new-line after). */
171 TC_BINOP, /* Space on both sides. */
172 TC_COMMA, /* Space afterward. */
173 TC_ID, /* Don't need spaces except sequentially. */
174 TC_PUNCT, /* Don't need spaces except sequentially. */
178 needs_space (enum token_class prev, enum token_class next)
180 /* Don't need a space before or after the end of a command.
181 (A new-line is needed afterward as a special case.) */
182 if (prev == TC_ENDCMD || next == TC_ENDCMD)
185 /* Binary operators always have a space on both sides. */
186 if (prev == TC_BINOP || next == TC_BINOP)
189 /* A comma always has a space afterward. */
190 if (prev == TC_COMMA)
193 /* Otherwise, PREV is TC_ID or TC_PUNCT, which only need a space if there are
194 two or them in a row. */
198 static enum token_class
199 classify_token (enum token_type type)
252 macro_tokens_to_representation (struct macro_tokens *mts, struct string *s)
257 macro_token_to_representation (&mts->mts[0], s);
258 for (size_t i = 1; i < mts->n; i++)
260 enum token_type prev = mts->mts[i - 1].token.type;
261 enum token_type next = mts->mts[i].token.type;
263 if (prev == T_ENDCMD)
264 ds_put_byte (s, '\n');
267 enum token_class pc = classify_token (prev);
268 enum token_class nc = classify_token (next);
269 if (needs_space (pc, nc))
270 ds_put_byte (s, ' ');
273 macro_token_to_representation (&mts->mts[i], s);
278 macro_destroy (struct macro *m)
284 for (size_t i = 0; i < m->n_params; i++)
286 struct macro_param *p = &m->params[i];
289 macro_tokens_uninit (&p->def);
297 token_uninit (&p->charend);
301 token_uninit (&p->enclose[0]);
302 token_uninit (&p->enclose[1]);
310 macro_tokens_uninit (&m->body);
315 macro_set_create (void)
317 struct macro_set *set = xmalloc (sizeof *set);
318 *set = (struct macro_set) {
319 .macros = HMAP_INITIALIZER (set->macros),
325 macro_set_destroy (struct macro_set *set)
330 struct macro *macro, *next;
331 HMAP_FOR_EACH_SAFE (macro, next, struct macro, hmap_node, &set->macros)
333 hmap_delete (&set->macros, ¯o->hmap_node);
334 macro_destroy (macro);
336 hmap_destroy (&set->macros);
341 hash_macro_name (const char *name)
343 return utf8_hash_case_string (name, 0);
346 static struct macro *
347 macro_set_find__ (struct macro_set *set, const char *name)
350 HMAP_FOR_EACH_WITH_HASH (macro, struct macro, hmap_node,
351 hash_macro_name (name), &set->macros)
352 if (!utf8_strcasecmp (macro->name, name))
359 macro_set_find (const struct macro_set *set, const char *name)
361 return macro_set_find__ (CONST_CAST (struct macro_set *, set), name);
364 /* Adds M to SET. M replaces any existing macro with the same name. Takes
367 macro_set_add (struct macro_set *set, struct macro *m)
369 struct macro *victim = macro_set_find__ (set, m->name);
372 hmap_delete (&set->macros, &victim->hmap_node);
373 macro_destroy (victim);
376 hmap_insert (&set->macros, &m->hmap_node, hash_macro_name (m->name));
384 /* Accumulating tokens in me->params toward the end of any type of
388 /* Expecting the opening delimiter of an ARG_ENCLOSE argument. */
391 /* Expecting a keyword for a keyword argument. */
394 /* Expecting an equal sign for a keyword argument. */
399 struct macro_expander
401 const struct macro_set *macros;
406 const struct macro *macro;
407 struct macro_tokens **args;
408 const struct macro_param *param;
412 me_finished (struct macro_expander *me)
414 for (size_t i = 0; i < me->macro->n_params; i++)
417 me->args[i] = xmalloc (sizeof *me->args[i]);
418 macro_tokens_copy (me->args[i], &me->macro->params[i].def);
424 me_next_arg (struct macro_expander *me)
428 assert (!me->macro->n_params);
429 return me_finished (me);
431 else if (me->param->positional)
434 if (me->param >= &me->macro->params[me->macro->n_params])
435 return me_finished (me);
438 me->state = (!me->param->positional ? ME_KEYWORD
439 : me->param->arg_type == ARG_ENCLOSE ? ME_ENCLOSE
446 for (size_t i = 0; i < me->macro->n_params; i++)
449 me->state = ME_KEYWORD;
452 return me_finished (me);
457 me_error (struct macro_expander *me)
459 me->state = ME_ERROR;
464 me_add_arg (struct macro_expander *me, const struct macro_token *mt)
466 const struct macro_param *p = me->param;
468 const struct token *token = &mt->token;
469 if ((token->type == T_ENDCMD || token->type == T_STOP)
470 && p->arg_type != ARG_CMDEND)
472 msg (SE, _("Unexpected end of command reading argument %s "
473 "to macro %s."), me->param->name, me->macro->name);
475 return me_error (me);
480 struct macro_tokens **argp = &me->args[p - me->macro->params];
482 *argp = xzalloc (sizeof **argp);
483 struct macro_tokens *arg = *argp;
484 if (p->arg_type == ARG_N_TOKENS)
486 macro_tokens_add (arg, mt);
487 if (arg->n >= p->n_tokens)
488 return me_next_arg (me);
491 else if (p->arg_type == ARG_CMDEND)
493 if (token->type == T_ENDCMD || token->type == T_STOP)
494 return me_next_arg (me);
495 macro_tokens_add (arg, mt);
500 const struct token *end
501 = p->arg_type == ARG_CHAREND ? &p->charend : &p->enclose[1];
502 if (token_equal (token, end))
503 return me_next_arg (me);
504 macro_tokens_add (arg, mt);
510 me_expected (struct macro_expander *me, const struct macro_token *actual,
511 const struct token *expected)
513 const struct substring actual_s
514 = (actual->representation.length ? actual->representation
515 : ss_cstr (_("<end of input>")));
516 char *expected_s = token_to_string (expected);
517 msg (SE, _("Found `%.*s' while expecting `%s' reading argument %s "
519 (int) actual_s.length, actual_s.string, expected_s,
520 me->param->name, me->macro->name);
523 return me_error (me);
527 me_enclose (struct macro_expander *me, const struct macro_token *mt)
529 const struct token *token = &mt->token;
532 if (token_equal (&me->param->enclose[0], token))
538 return me_expected (me, mt, &me->param->enclose[0]);
541 static const struct macro_param *
542 macro_find_parameter_by_name (const struct macro *m, struct substring name)
544 if (ss_first (name) == '!')
545 ss_advance (&name, 1);
547 for (size_t i = 0; i < m->n_params; i++)
549 const struct macro_param *p = &m->params[i];
550 struct substring p_name = ss_cstr (p->name + 1);
551 if (!utf8_strncasecmp (p_name.string, p_name.length,
552 name.string, name.length))
559 me_keyword (struct macro_expander *me, const struct macro_token *mt)
561 const struct token *token = &mt->token;
562 if (token->type != T_ID)
563 return me_finished (me);
565 const struct macro_param *p = macro_find_parameter_by_name (me->macro,
569 size_t arg_index = p - me->macro->params;
571 if (me->args[arg_index])
574 _("Argument %s multiply specified in call to macro %s."),
575 p->name, me->macro->name);
576 return me_error (me);
580 me->state = ME_EQUALS;
584 return me_finished (me);
588 me_equals (struct macro_expander *me, const struct macro_token *mt)
590 const struct token *token = &mt->token;
593 if (token->type == T_EQUALS)
599 return me_expected (me, mt, &(struct token) { .type = T_EQUALS });
603 macro_expander_create (const struct macro_set *macros,
604 const struct token *token,
605 struct macro_expander **mep)
608 if (macro_set_is_empty (macros))
610 if (token->type != T_ID && token->type != T_MACRO_ID)
613 const struct macro *macro = macro_set_find (macros, token->string.string);
617 struct macro_expander *me = xmalloc (sizeof *me);
618 *me = (struct macro_expander) {
625 if (!macro->n_params)
629 me->state = (!macro->params[0].positional ? ME_KEYWORD
630 : macro->params[0].arg_type == ARG_ENCLOSE ? ME_ENCLOSE
632 me->args = xcalloc (macro->n_params, sizeof *me->args);
633 me->param = macro->params;
639 macro_expander_destroy (struct macro_expander *me)
644 for (size_t i = 0; i < me->macro->n_params; i++)
647 macro_tokens_uninit (me->args[i]);
654 /* Adds TOKEN to the collection of tokens in ME that potentially need to be
657 Returns -1 if the tokens added do not actually invoke a macro. The caller
658 should consume the first token without expanding it.
660 Returns 0 if the macro expander needs more tokens, for macro arguments or to
661 decide whether this is actually a macro invocation. The caller should call
662 macro_expander_add() again with the next token.
664 Returns a positive number to indicate that the returned number of tokens
665 invoke a macro. The number returned might be less than the number of tokens
666 added because it can take a few tokens of lookahead to determine whether the
667 macro invocation is finished. The caller should call
668 macro_expander_get_expansion() to obtain the expansion. */
670 macro_expander_add (struct macro_expander *me, const struct macro_token *mt)
678 return me_add_arg (me, mt);
681 return me_enclose (me, mt);
684 return me_keyword (me, mt);
687 return me_equals (me, mt);
694 /* Each argument to a macro function is one of:
696 - A quoted string or other single literal token.
698 - An argument to the macro being expanded, e.g. !1 or a named argument.
702 - A function invocation.
704 Each function invocation yields a character sequence to be turned into a
705 sequence of tokens. The case where that character sequence is a single
706 quoted string is an important special case.
708 struct parse_macro_function_ctx
710 const struct macro_token *input;
712 int nesting_countdown;
713 const struct macro_set *macros;
714 const struct macro_expander *me;
719 macro_expand (const struct macro_tokens *,
720 int nesting_countdown, const struct macro_set *,
721 const struct macro_expander *, bool *expand, struct macro_tokens *exp);
724 expand_macro_function (struct parse_macro_function_ctx *ctx,
725 struct string *output, size_t *input_consumed);
727 /* Returns true if the pair of tokens starting at offset OFS within MTS are !*,
730 is_bang_star (const struct macro_token *mts, size_t n, size_t ofs)
733 && mts[ofs].token.type == T_MACRO_ID
734 && ss_equals (mts[ofs].token.string, ss_cstr ("!"))
735 && mts[ofs + 1].token.type == T_ASTERISK);
739 parse_function_arg (struct parse_macro_function_ctx *ctx,
740 size_t i, struct string *farg)
742 const struct macro_token *tokens = ctx->input;
743 const struct token *token = &tokens[i].token;
744 if (token->type == T_MACRO_ID)
746 const struct macro_param *param = macro_find_parameter_by_name (
747 ctx->me->macro, token->string);
750 size_t param_idx = param - ctx->me->macro->params;
751 const struct macro_tokens *marg = ctx->me->args[param_idx];
752 for (size_t i = 0; i < marg->n; i++)
755 ds_put_byte (farg, ' ');
756 ds_put_substring (farg, marg->mts[i].representation);
761 if (is_bang_star (ctx->input, ctx->n_input, i))
763 for (size_t i = 0; i < ctx->me->macro->n_params; i++)
765 if (!ctx->me->macro->params[i].positional)
768 const struct macro_tokens *marg = ctx->me->args[i];
769 for (size_t j = 0; j < marg->n; j++)
772 ds_put_byte (farg, ' ');
773 ds_put_substring (farg, marg->mts[j].representation);
779 struct parse_macro_function_ctx subctx = {
780 .input = &ctx->input[i],
781 .n_input = ctx->n_input - i,
782 .nesting_countdown = ctx->nesting_countdown,
783 .macros = ctx->macros,
785 .expand = ctx->expand,
787 size_t subinput_consumed;
788 if (expand_macro_function (&subctx, farg, &subinput_consumed))
789 return subinput_consumed;
792 ds_put_substring (farg, tokens[i].representation);
797 parse_macro_function (struct parse_macro_function_ctx *ctx,
798 struct string_array *args,
799 struct substring function,
800 int min_args, int max_args,
801 size_t *input_consumed)
803 const struct macro_token *tokens = ctx->input;
804 size_t n_tokens = ctx->n_input;
807 || tokens[0].token.type != T_MACRO_ID
808 || !ss_equals_case (tokens[0].token.string, function))
811 if (n_tokens < 2 || tokens[1].token.type != T_LPAREN)
813 printf ("`(' expected following %s'\n", function.string);
817 string_array_init (args);
819 for (size_t i = 2;; )
823 if (tokens[i].token.type == T_RPAREN)
825 *input_consumed = i + 1;
826 if (args->n < min_args || args->n > max_args)
828 printf ("Wrong number of arguments to %s.\n", function.string);
834 struct string s = DS_EMPTY_INITIALIZER;
835 i += parse_function_arg (ctx, i, &s);
841 string_array_append_nocopy (args, ds_steal_cstr (&s));
843 if (tokens[i].token.type == T_COMMA)
845 else if (tokens[i].token.type != T_RPAREN)
847 printf ("Expecting `,' or `)' in %s invocation.", function.string);
853 printf ("Missing closing parenthesis in arguments to %s.\n",
857 string_array_destroy (args);
862 unquote_string (const char *s, struct string *content)
864 struct string_lexer slex;
865 string_lexer_init (&slex, s, strlen (s), SEG_MODE_INTERACTIVE /* XXX */);
868 if (!string_lexer_next (&slex, &token1))
871 if (token1.type != T_STRING)
873 token_uninit (&token1);
878 if (string_lexer_next (&slex, &token2))
880 token_uninit (&token1);
881 token_uninit (&token2);
885 ds_put_substring (content, token1.string);
886 token_uninit (&token1);
891 unquote_string_in_place (const char *s, struct string *tmp)
894 return unquote_string (s, tmp) ? ds_cstr (tmp) : s;
898 parse_integer (const char *s, int *np)
903 long int n = strtol (s, &tail, 10);
904 *np = n < INT_MIN ? INT_MIN : n > INT_MAX ? INT_MAX : n;
905 tail += strspn (tail, CC_SPACES);
906 return *tail == '\0' && errno != ERANGE && n == *np;
910 expand_macro_function (struct parse_macro_function_ctx *ctx,
911 struct string *output,
912 size_t *input_consumed)
914 struct string_array args;
916 if (parse_macro_function (ctx, &args, ss_cstr ("!length"), 1, 1,
918 ds_put_format (output, "%zu", strlen (args.strings[0]));
919 else if (parse_macro_function (ctx, &args, ss_cstr ("!blanks"), 1, 1,
923 if (!parse_integer (args.strings[0], &n))
925 printf ("argument to !BLANKS must be non-negative integer (not \"%s\")\n", args.strings[0]);
926 string_array_destroy (&args);
930 ds_put_byte_multiple (output, ' ', n);
932 else if (parse_macro_function (ctx, &args, ss_cstr ("!concat"), 1, INT_MAX,
935 for (size_t i = 0; i < args.n; i++)
936 if (!unquote_string (args.strings[i], output))
937 ds_put_cstr (output, args.strings[i]);
939 else if (parse_macro_function (ctx, &args, ss_cstr ("!head"), 1, 1,
943 const char *s = unquote_string_in_place (args.strings[0], &tmp);
945 struct macro_tokens mts = { .n = 0 };
946 macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */);
948 ds_put_substring (output, mts.mts[0].representation);
949 macro_tokens_uninit (&mts);
952 else if (parse_macro_function (ctx, &args, ss_cstr ("!index"), 2, 2,
955 const char *haystack = args.strings[0];
956 const char *needle = strstr (haystack, args.strings[1]);
957 ds_put_format (output, "%zu", needle ? needle - haystack + 1 : 0);
959 else if (parse_macro_function (ctx, &args, ss_cstr ("!quote"), 1, 1,
962 if (unquote_string (args.strings[0], NULL))
963 ds_put_cstr (output, args.strings[0]);
966 ds_extend (output, strlen (args.strings[0]) + 2);
967 ds_put_byte (output, '\'');
968 for (const char *p = args.strings[0]; *p; p++)
971 ds_put_byte (output, '\'');
972 ds_put_byte (output, *p);
974 ds_put_byte (output, '\'');
977 else if (parse_macro_function (ctx, &args, ss_cstr ("!substr"), 2, 3,
981 if (!parse_integer (args.strings[1], &start) || start < 1)
983 printf ("second argument to !SUBSTR must be positive integer (not \"%s\")\n", args.strings[1]);
984 string_array_destroy (&args);
989 if (args.n > 2 && (!parse_integer (args.strings[2], &count) || count < 0))
991 printf ("third argument to !SUBSTR must be non-negative integer (not \"%s\")\n", args.strings[1]);
992 string_array_destroy (&args);
996 struct substring s = ss_cstr (args.strings[0]);
997 ds_put_substring (output, ss_substr (s, start - 1, count));
999 else if (parse_macro_function (ctx, &args, ss_cstr ("!tail"), 1, 1,
1003 const char *s = unquote_string_in_place (args.strings[0], &tmp);
1005 struct macro_tokens mts = { .n = 0 };
1006 macro_tokens_from_string (&mts, ss_cstr (s), SEG_MODE_INTERACTIVE /* XXX */);
1009 struct macro_tokens tail = { .mts = mts.mts + 1, .n = mts.n - 1 };
1010 macro_tokens_to_representation (&tail, output);
1012 macro_tokens_uninit (&mts);
1015 else if (parse_macro_function (ctx, &args, ss_cstr ("!unquote"), 1, 1,
1018 if (!unquote_string (args.strings[0], output))
1019 ds_put_cstr (output, args.strings[0]);
1021 else if (parse_macro_function (ctx, &args, ss_cstr ("!upcase"), 1, 1,
1025 const char *s = unquote_string_in_place (args.strings[0], &tmp);
1026 char *upper = utf8_to_upper (s);
1027 ds_put_cstr (output, upper);
1031 else if (parse_macro_function (ctx, &args, ss_cstr ("!eval"), 1, 1,
1034 struct macro_tokens mts = { .n = 0 };
1035 macro_tokens_from_string (&mts, ss_cstr (args.strings[0]),
1036 SEG_MODE_INTERACTIVE /* XXX */);
1037 struct macro_tokens exp = { .n = 0 };
1038 macro_expand (&mts, ctx->nesting_countdown - 1, ctx->macros,
1039 ctx->me, ctx->expand, &exp);
1040 macro_tokens_to_representation (&exp, output);
1041 macro_tokens_uninit (&exp);
1042 macro_tokens_uninit (&mts);
1044 else if (ctx->n_input > 0
1045 && ctx->input[0].token.type == T_MACRO_ID
1046 && ss_equals_case (ctx->input[0].token.string, ss_cstr ("!null")))
1048 *input_consumed = 1;
1054 string_array_destroy (&args);
1060 int nesting_countdown;
1061 const struct macro_set *macros;
1062 const struct macro_expander *me;
1066 static char *macro_evaluate_or (const struct expr_context *ctx,
1067 const struct macro_token **tokens,
1068 const struct macro_token *end);
1071 macro_evaluate_literal (const struct expr_context *ctx,
1072 const struct macro_token **tokens,
1073 const struct macro_token *end)
1075 const struct macro_token *p = *tokens;
1078 if (p->token.type == T_LPAREN)
1081 char *value = macro_evaluate_or (ctx, &p, end);
1084 if (p >= end || p->token.type != T_RPAREN)
1087 printf ("expecting ')' in macro expression\n");
1095 struct parse_macro_function_ctx fctx = {
1098 .nesting_countdown = ctx->nesting_countdown,
1099 .macros = ctx->macros,
1101 .expand = ctx->expand,
1103 struct string function_output = DS_EMPTY_INITIALIZER;
1104 size_t function_consumed = parse_function_arg (&fctx, 0, &function_output);
1105 *tokens = p + function_consumed;
1106 return ds_steal_cstr (&function_output);
1109 /* Returns true if MT is valid as a macro operator. Only operators written as
1110 symbols (e.g. <>) are usable in macro expressions, not operator written as
1111 letters (e.g. EQ). */
1113 is_macro_operator (const struct macro_token *mt)
1115 return (mt->representation.length > 0
1116 && !c_isalpha (mt->representation.string[0]));
1119 static enum token_type
1120 parse_relational_op (const struct macro_token *mt)
1122 switch (mt->token.type)
1132 return is_macro_operator (mt) ? mt->token.type : T_STOP;
1135 return (ss_equals_case (mt->token.string, ss_cstr ("!EQ")) ? T_EQ
1136 : ss_equals_case (mt->token.string, ss_cstr ("!NE")) ? T_NE
1137 : ss_equals_case (mt->token.string, ss_cstr ("!LT")) ? T_LT
1138 : ss_equals_case (mt->token.string, ss_cstr ("!GT")) ? T_GT
1139 : ss_equals_case (mt->token.string, ss_cstr ("!LE")) ? T_LE
1140 : ss_equals_case (mt->token.string, ss_cstr ("!GE")) ? T_GE
1149 macro_evaluate_relational (const struct expr_context *ctx,
1150 const struct macro_token **tokens,
1151 const struct macro_token *end)
1153 const struct macro_token *p = *tokens;
1154 char *lhs = macro_evaluate_literal (ctx, &p, end);
1158 enum token_type op = p >= end ? T_STOP : parse_relational_op (p);
1166 char *rhs = macro_evaluate_literal (ctx, &p, end);
1173 struct string lhs_tmp, rhs_tmp;
1174 int cmp = strcmp/*XXX*/ (unquote_string_in_place (lhs, &lhs_tmp),
1175 unquote_string_in_place (rhs, &rhs_tmp));
1176 ds_destroy (&lhs_tmp);
1177 ds_destroy (&rhs_tmp);
1182 bool b = (op == T_EQUALS || op == T_EQ ? !cmp
1184 : op == T_LT ? cmp < 0
1185 : op == T_GT ? cmp > 0
1186 : op == T_LE ? cmp <= 0
1187 :/*op == T_GE*/cmp >= 0);
1190 return xstrdup (b ? "1" : "0");
1194 macro_evaluate_not (const struct expr_context *ctx,
1195 const struct macro_token **tokens,
1196 const struct macro_token *end)
1198 const struct macro_token *p = *tokens;
1200 unsigned int negations = 0;
1202 && (ss_equals_case (p->representation, ss_cstr ("!NOT"))
1203 || ss_equals (p->representation, ss_cstr ("~"))))
1209 char *operand = macro_evaluate_relational (ctx, &p, end);
1210 if (!operand || !negations)
1216 bool b = strcmp (operand, "0") ^ (negations & 1);
1219 return xstrdup (b ? "1" : "0");
1223 macro_evaluate_and (const struct expr_context *ctx,
1224 const struct macro_token **tokens,
1225 const struct macro_token *end)
1227 const struct macro_token *p = *tokens;
1228 char *lhs = macro_evaluate_not (ctx, &p, end);
1233 && (ss_equals_case (p->representation, ss_cstr ("!AND"))
1234 || ss_equals (p->representation, ss_cstr ("&"))))
1237 char *rhs = macro_evaluate_not (ctx, &p, end);
1244 bool b = strcmp (lhs, "0") && strcmp (rhs, "0");
1247 lhs = xstrdup (b ? "1" : "0");
1254 macro_evaluate_or (const struct expr_context *ctx,
1255 const struct macro_token **tokens,
1256 const struct macro_token *end)
1258 const struct macro_token *p = *tokens;
1259 char *lhs = macro_evaluate_and (ctx, &p, end);
1264 && (ss_equals_case (p->representation, ss_cstr ("!OR"))
1265 || ss_equals (p->representation, ss_cstr ("|"))))
1268 char *rhs = macro_evaluate_and (ctx, &p, end);
1275 bool b = strcmp (lhs, "0") || strcmp (rhs, "0");
1278 lhs = xstrdup (b ? "1" : "0");
1285 macro_evaluate_expression (const struct macro_token **tokens, size_t n_tokens,
1286 int nesting_countdown, const struct macro_set *macros,
1287 const struct macro_expander *me, bool *expand)
1289 const struct expr_context ctx = {
1290 .nesting_countdown = nesting_countdown,
1295 return macro_evaluate_or (&ctx, tokens, *tokens + n_tokens);
1298 static const struct macro_token *
1299 find_ifend_clause (const struct macro_token *p, const struct macro_token *end)
1302 for (; p < end; p++)
1304 if (p->token.type != T_MACRO_ID)
1307 if (ss_equals_case (p->token.string, ss_cstr ("!IF")))
1309 else if (ss_equals_case (p->token.string, ss_cstr ("!IFEND")))
1315 else if (ss_equals_case (p->token.string, ss_cstr ("!ELSE")) && !nesting)
1322 macro_expand_if (const struct macro_token *tokens, size_t n_tokens,
1323 int nesting_countdown, const struct macro_set *macros,
1324 const struct macro_expander *me, bool *expand,
1325 struct macro_tokens *exp)
1327 const struct macro_token *p = tokens;
1328 const struct macro_token *end = tokens + n_tokens;
1330 if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!IF")))
1334 char *result = macro_evaluate_expression (&p, end - p,
1335 nesting_countdown, macros, me, expand);
1338 bool b = strcmp (result, "0");
1342 || p->token.type != T_MACRO_ID
1343 || !ss_equals_case (p->token.string, ss_cstr ("!THEN")))
1345 printf ("!THEN expected\n");
1349 const struct macro_token *start_then = p + 1;
1350 const struct macro_token *end_then = find_ifend_clause (start_then, end);
1353 printf ("!ELSE or !IFEND expected\n");
1357 const struct macro_token *start_else, *end_if;
1358 if (ss_equals_case (end_then->token.string, ss_cstr ("!ELSE")))
1360 start_else = end_then + 1;
1361 end_if = find_ifend_clause (start_else, end);
1363 || !ss_equals_case (end_if->token.string, ss_cstr ("!IFEND")))
1365 printf ("!IFEND expected\n");
1375 const struct macro_token *start;
1380 n = end_then - start_then;
1382 else if (start_else)
1385 n = end_if - start_else;
1395 struct macro_tokens mts = {
1396 .mts = CONST_CAST (struct macro_token *, start),
1399 macro_expand (&mts, nesting_countdown, macros, me, expand, exp);
1401 return (end_if + 1) - tokens;
1405 macro_expand (const struct macro_tokens *mts,
1406 int nesting_countdown, const struct macro_set *macros,
1407 const struct macro_expander *me, bool *expand,
1408 struct macro_tokens *exp)
1410 if (nesting_countdown <= 0)
1412 printf ("maximum nesting level exceeded\n");
1413 for (size_t i = 0; i < mts->n; i++)
1414 macro_tokens_add (exp, &mts->mts[i]);
1418 for (size_t i = 0; i < mts->n; i++)
1420 const struct macro_token *mt = &mts->mts[i];
1421 const struct token *token = &mt->token;
1422 if (token->type == T_MACRO_ID && me)
1424 const struct macro_param *param = macro_find_parameter_by_name (
1425 me->macro, token->string);
1428 const struct macro_tokens *arg = me->args[param - me->macro->params];
1429 //macro_tokens_print (arg, stdout);
1430 if (*expand && param->expand_arg)
1431 macro_expand (arg, nesting_countdown, macros, NULL, expand, exp);
1433 for (size_t i = 0; i < arg->n; i++)
1434 macro_tokens_add (exp, &arg->mts[i]);
1438 if (is_bang_star (mts->mts, mts->n, i))
1440 for (size_t j = 0; j < me->macro->n_params; j++)
1442 const struct macro_param *param = &me->macro->params[j];
1443 if (!param->positional)
1446 const struct macro_tokens *arg = me->args[j];
1447 if (*expand && param->expand_arg)
1448 macro_expand (arg, nesting_countdown, macros, NULL, expand, exp);
1450 for (size_t k = 0; k < arg->n; k++)
1451 macro_tokens_add (exp, &arg->mts[k]);
1457 size_t n = macro_expand_if (&mts->mts[i], mts->n - i,
1458 nesting_countdown, macros, me, expand,
1469 struct macro_expander *subme;
1470 int retval = macro_expander_create (macros, token, &subme);
1471 for (size_t j = 1; !retval; j++)
1473 const struct macro_token endcmd = { .token = { .type = T_ENDCMD } };
1474 retval = macro_expander_add (
1475 subme, i + j < mts->n ? &mts->mts[i + j] : &endcmd);
1480 macro_expand (&subme->macro->body, nesting_countdown - 1, macros,
1481 subme, expand, exp);
1482 macro_expander_destroy (subme);
1486 macro_expander_destroy (subme);
1489 if (token->type != T_MACRO_ID)
1491 macro_tokens_add (exp, mt);
1495 struct parse_macro_function_ctx ctx = {
1496 .input = &mts->mts[i],
1497 .n_input = mts->n - i,
1498 .nesting_countdown = nesting_countdown,
1503 struct string function_output = DS_EMPTY_INITIALIZER;
1504 size_t function_consumed;
1505 if (expand_macro_function (&ctx, &function_output, &function_consumed))
1507 i += function_consumed - 1;
1509 macro_tokens_from_string (exp, function_output.ss,
1510 SEG_MODE_INTERACTIVE /* XXX */);
1511 ds_destroy (&function_output);
1516 if (ss_equals_case (token->string, ss_cstr ("!onexpand")))
1518 else if (ss_equals_case (token->string, ss_cstr ("!offexpand")))
1521 macro_tokens_add (exp, mt);
1526 macro_expander_get_expansion (struct macro_expander *me, struct macro_tokens *exp)
1529 for (size_t i = 0; i < me->macro->n_params; i++)
1531 printf ("%s:\n", me->macro->params[i].name);
1532 macro_tokens_print (me->args[i], stdout);
1537 macro_expand (&me->macro->body, settings_get_mnest (),
1538 me->macros, me, &expand, exp);
1541 printf ("expansion:\n");
1542 macro_tokens_print (exp, stdout);