Get rid of struct parse_macro_function_ctx.
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 4 Jul 2021 23:14:46 +0000 (16:14 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 4 Jul 2021 23:14:46 +0000 (16:14 -0700)
src/language/lexer/macro.c

index c35144dc3a984bb28a3cd798d633a7afa1ab779e..0d74bae00ce50c5d5d42dcf0fd3432966dd72eee 100644 (file)
@@ -866,15 +866,20 @@ macro_call_add (struct macro_call *mc, const struct macro_token *mt)
 
 struct macro_expander
   {
-    const struct macro_set *macros;
+    /* Always available. */
+    const struct macro_set *macros;     /* Macros to expand recursively. */
+    enum segmenter_mode segmenter_mode; /* Mode for tokenization. */
+    int nesting_countdown;              /* Remaining nesting levels. */
+    const struct macro_expansion_stack *stack; /* Stack for error reporting. */
+    bool *expand;                       /* May macro calls be expanded? */
+    struct stringi_map *vars;           /* Variables from !DO and !LET. */
+
+    /* Only nonnull if inside a !DO loop. */
+    bool *break_;                       /* Set to true to break out of loop. */
+
+    /* Only nonnull if expanding a macro (and not, say, a macro argument). */
     const struct macro *macro;
     struct macro_tokens **args;
-    enum segmenter_mode segmenter_mode;
-    struct stringi_map *vars;
-    bool *expand;
-    bool *break_;
-    int nesting_countdown;
-    const struct macro_expansion_stack *stack;
   };
 
 /* Each argument to a macro function is one of:
@@ -891,19 +896,14 @@ struct macro_expander
    sequence of tokens.  The case where that character sequence is a single
    quoted string is an important special case.
 */
-struct parse_macro_function_ctx
-  {
-    const struct macro_token *input;
-    size_t n_input;
-    const struct macro_expander *me;
-  };
 
 static void
 macro_expand (const struct macro_tokens *, const struct macro_expander *,
               struct macro_tokens *);
 
 static bool
-expand_macro_function (struct parse_macro_function_ctx *ctx,
+expand_macro_function (const struct macro_expander *me,
+                       const struct macro_token *input, size_t n_input,
                        struct string *output, size_t *input_consumed);
 
 /* Returns true if the pair of tokens starting at offset OFS within MTS are !*,
@@ -918,19 +918,19 @@ is_bang_star (const struct macro_token *mts, size_t n, size_t ofs)
 }
 
 static size_t
-parse_function_arg (struct parse_macro_function_ctx *ctx,
+parse_function_arg (const struct macro_expander *me,
+                    const struct macro_token *input, size_t n_input,
                     size_t i, struct string *farg)
 {
-  const struct macro_token *tokens = ctx->input;
-  const struct token *token = &tokens[i].token;
-  if (token->type == T_MACRO_ID && ctx->me->macro)
+  const struct token *token = &input[i].token;
+  if (token->type == T_MACRO_ID && me->macro)
     {
       const struct macro_param *param = macro_find_parameter_by_name (
-        ctx->me->macro, token->string);
+        me->macro, token->string);
       if (param)
         {
-          size_t param_idx = param - ctx->me->macro->params;
-          const struct macro_tokens *marg = ctx->me->args[param_idx];
+          size_t param_idx = param - me->macro->params;
+          const struct macro_tokens *marg = me->args[param_idx];
           for (size_t i = 0; i < marg->n; i++)
             {
               if (i)
@@ -940,14 +940,14 @@ parse_function_arg (struct parse_macro_function_ctx *ctx,
           return 1;
         }
 
-      if (is_bang_star (ctx->input, ctx->n_input, i))
+      if (is_bang_star (input, n_input, i))
         {
-          for (size_t i = 0; i < ctx->me->macro->n_params; i++)
+          for (size_t i = 0; i < me->macro->n_params; i++)
             {
-              if (!ctx->me->macro->params[i].positional)
+              if (!me->macro->params[i].positional)
                 break;
 
-              const struct macro_tokens *marg = ctx->me->args[i];
+              const struct macro_tokens *marg = me->args[i];
               for (size_t j = 0; j < marg->n; j++)
                 {
                   if (i || j)
@@ -958,7 +958,7 @@ parse_function_arg (struct parse_macro_function_ctx *ctx,
           return 2;
         }
 
-      const char *value = stringi_map_find__ (ctx->me->vars,
+      const char *value = stringi_map_find__ (me->vars,
                                               token->string.string,
                                               token->string.length);
       if (value)
@@ -967,30 +967,24 @@ parse_function_arg (struct parse_macro_function_ctx *ctx,
           return 1;
         }
 
-      struct parse_macro_function_ctx subctx = {
-        .input = &ctx->input[i],
-        .n_input = ctx->n_input - i,
-        .me = ctx->me,
-      };
       size_t subinput_consumed;
-      if (expand_macro_function (&subctx, farg, &subinput_consumed))
+      if (expand_macro_function (me, &input[i], n_input - i,
+                                 farg, &subinput_consumed))
         return subinput_consumed;
     }
 
-  ds_put_substring (farg, tokens[i].representation);
+  ds_put_substring (farg, input[i].representation);
   return 1;
 }
 
 static bool
-parse_macro_function (struct parse_macro_function_ctx *ctx,
+parse_macro_function (const struct macro_expander *me,
+                      const struct macro_token *tokens, size_t n_tokens,
                       struct string_array *args,
                       struct substring function,
                       int min_args, int max_args,
                       size_t *input_consumed)
 {
-  const struct macro_token *tokens = ctx->input;
-  size_t n_tokens = ctx->n_input;
-
   if (!n_tokens
       || tokens[0].token.type != T_MACRO_ID
       || !ss_equals_case (tokens[0].token.string, function)) /* XXX abbrevs allowed */
@@ -998,7 +992,7 @@ parse_macro_function (struct parse_macro_function_ctx *ctx,
 
   if (n_tokens < 2 || tokens[1].token.type != T_LPAREN)
     {
-      macro_error (ctx->me->stack, n_tokens > 1 ? &tokens[1] : NULL,
+      macro_error (me->stack, n_tokens > 1 ? &tokens[1] : NULL,
                    _("`(' expected following %s."), function.string);
       return false;
     }
@@ -1014,7 +1008,7 @@ parse_macro_function (struct parse_macro_function_ctx *ctx,
           *input_consumed = i + 1;
           if (args->n < min_args || args->n > max_args)
             {
-              macro_error (ctx->me->stack, &tokens[i],
+              macro_error (me->stack, &tokens[i],
                            _("Wrong number of arguments to macro function %s."),
                            function.string);
               goto error;
@@ -1023,7 +1017,7 @@ parse_macro_function (struct parse_macro_function_ctx *ctx,
         }
 
       struct string s = DS_EMPTY_INITIALIZER;
-      i += parse_function_arg (ctx, i, &s);
+      i += parse_function_arg (me, tokens, n_tokens, i, &s);
       if (i >= n_tokens)
         {
           ds_destroy (&s);
@@ -1035,7 +1029,7 @@ parse_macro_function (struct parse_macro_function_ctx *ctx,
         i++;
       else if (tokens[i].token.type != T_RPAREN)
         {
-          macro_error (ctx->me->stack, &tokens[i],
+          macro_error (me->stack, &tokens[i],
                        _("`,' or `)' expected in call to macro function %s."),
                        function.string);
           goto error;
@@ -1043,7 +1037,7 @@ parse_macro_function (struct parse_macro_function_ctx *ctx,
     }
 
 unexpected_end:
-  macro_error (ctx->me->stack, NULL, _("Missing `)' in call to macro function %s."),
+  macro_error (me->stack, NULL, _("Missing `)' in call to macro function %s."),
                function.string);
   /* Fall through. */
 error:
@@ -1102,22 +1096,21 @@ parse_integer (const char *s, int *np)
 }
 
 static bool
-expand_macro_function (struct parse_macro_function_ctx *ctx,
-                       struct string *output,
-                       size_t *input_consumed)
+expand_macro_function (const struct macro_expander *me,
+                       const struct macro_token *input, size_t n_input,
+                       struct string *output, size_t *input_consumed)
 {
   struct string_array args;
-
-  if (parse_macro_function (ctx, &args, ss_cstr ("!LENGTH"), 1, 1,
+  if (parse_macro_function (me, input, n_input, &args, ss_cstr ("!LENGTH"), 1, 1,
                             input_consumed))
     ds_put_format (output, "%zu", strlen (args.strings[0]));
-  else if (parse_macro_function (ctx, &args, ss_cstr ("!BLANKS"), 1, 1,
+  else if (parse_macro_function (me, input, n_input, &args, ss_cstr ("!BLANKS"), 1, 1,
                                  input_consumed))
     {
       int n;
       if (!parse_integer (args.strings[0], &n))
         {
-          macro_error (ctx->me->stack, NULL,
+          macro_error (me->stack, NULL,
                        _("Argument to !BLANKS must be non-negative integer "
                          "(not \"%s\")."), args.strings[0]);
           string_array_destroy (&args);
@@ -1126,39 +1119,39 @@ expand_macro_function (struct parse_macro_function_ctx *ctx,
 
       ds_put_byte_multiple (output, ' ', n);
     }
-  else if (parse_macro_function (ctx, &args, ss_cstr ("!CONCAT"), 1, INT_MAX,
+  else if (parse_macro_function (me, input, n_input, &args, ss_cstr ("!CONCAT"), 1, INT_MAX,
                                  input_consumed))
     {
       for (size_t i = 0; i < args.n; i++)
-        if (!unquote_string (args.strings[i], ctx->me->segmenter_mode, output))
+        if (!unquote_string (args.strings[i], me->segmenter_mode, output))
           ds_put_cstr (output, args.strings[i]);
     }
-  else if (parse_macro_function (ctx, &args, ss_cstr ("!HEAD"), 1, 1,
+  else if (parse_macro_function (me, input, n_input, &args, ss_cstr ("!HEAD"), 1, 1,
                                  input_consumed))
     {
       struct string tmp;
       const char *s = unquote_string_in_place (args.strings[0],
-                                               ctx->me->segmenter_mode, &tmp);
+                                               me->segmenter_mode, &tmp);
 
       struct macro_tokens mts = { .n = 0 };
-      macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->me->segmenter_mode,
-                                  ctx->me->stack);
+      macro_tokens_from_string__ (&mts, ss_cstr (s), me->segmenter_mode,
+                                  me->stack);
       if (mts.n > 0)
         ds_put_substring (output, mts.mts[0].representation);
       macro_tokens_uninit (&mts);
       ds_destroy (&tmp);
     }
-  else if (parse_macro_function (ctx, &args, ss_cstr ("!INDEX"), 2, 2,
+  else if (parse_macro_function (me, input, n_input, &args, ss_cstr ("!INDEX"), 2, 2,
                                  input_consumed))
     {
       const char *haystack = args.strings[0];
       const char *needle = strstr (haystack, args.strings[1]);
       ds_put_format (output, "%zu", needle ? needle - haystack + 1 : 0);
     }
-  else if (parse_macro_function (ctx, &args, ss_cstr ("!QUOTE"), 1, 1,
+  else if (parse_macro_function (me, input, n_input, &args, ss_cstr ("!QUOTE"), 1, 1,
                                  input_consumed))
     {
-      if (unquote_string (args.strings[0], ctx->me->segmenter_mode, NULL))
+      if (unquote_string (args.strings[0], me->segmenter_mode, NULL))
         ds_put_cstr (output, args.strings[0]);
       else
         {
@@ -1173,13 +1166,13 @@ expand_macro_function (struct parse_macro_function_ctx *ctx,
           ds_put_byte (output, '\'');
         }
     }
-  else if (parse_macro_function (ctx, &args, ss_cstr ("!SUBSTR"), 2, 3,
+  else if (parse_macro_function (me, input, n_input, &args, ss_cstr ("!SUBSTR"), 2, 3,
                                  input_consumed))
     {
       int start;
       if (!parse_integer (args.strings[1], &start) || start < 1)
         {
-          macro_error (ctx->me->stack, NULL,
+          macro_error (me->stack, NULL,
                        _("Second argument of !SUBSTR must be "
                          "positive integer (not \"%s\")."),
                        args.strings[1]);
@@ -1190,7 +1183,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx,
       int count = INT_MAX;
       if (args.n > 2 && (!parse_integer (args.strings[2], &count) || count < 0))
         {
-          macro_error (ctx->me->stack, NULL,
+          macro_error (me->stack, NULL,
                        _("Third argument of !SUBSTR must be "
                          "non-negative integer (not \"%s\")."),
                        args.strings[2]);
@@ -1201,16 +1194,16 @@ expand_macro_function (struct parse_macro_function_ctx *ctx,
       struct substring s = ss_cstr (args.strings[0]);
       ds_put_substring (output, ss_substr (s, start - 1, count));
     }
-  else if (parse_macro_function (ctx, &args, ss_cstr ("!TAIL"), 1, 1,
+  else if (parse_macro_function (me, input, n_input, &args, ss_cstr ("!TAIL"), 1, 1,
                                  input_consumed))
     {
       struct string tmp;
       const char *s = unquote_string_in_place (args.strings[0],
-                                               ctx->me->segmenter_mode, &tmp);
+                                               me->segmenter_mode, &tmp);
 
       struct macro_tokens mts = { .n = 0 };
-      macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->me->segmenter_mode,
-                                  ctx->me->stack);
+      macro_tokens_from_string__ (&mts, ss_cstr (s), me->segmenter_mode,
+                                  me->stack);
       if (mts.n > 1)
         {
           struct macro_tokens tail = { .mts = mts.mts + 1, .n = mts.n - 1 };
@@ -1219,35 +1212,35 @@ expand_macro_function (struct parse_macro_function_ctx *ctx,
       macro_tokens_uninit (&mts);
       ds_destroy (&tmp);
     }
-  else if (parse_macro_function (ctx, &args, ss_cstr ("!UNQUOTE"), 1, 1,
+  else if (parse_macro_function (me, input, n_input, &args, ss_cstr ("!UNQUOTE"), 1, 1,
                                  input_consumed))
     {
-      if (!unquote_string (args.strings[0], ctx->me->segmenter_mode, output))
+      if (!unquote_string (args.strings[0], me->segmenter_mode, output))
         ds_put_cstr (output, args.strings[0]);
     }
-  else if (parse_macro_function (ctx, &args, ss_cstr ("!UPCASE"), 1, 1,
+  else if (parse_macro_function (me, input, n_input, &args, ss_cstr ("!UPCASE"), 1, 1,
                                  input_consumed))
     {
       struct string tmp;
       const char *s = unquote_string_in_place (args.strings[0],
-                                               ctx->me->segmenter_mode, &tmp);
+                                               me->segmenter_mode, &tmp);
       char *upper = utf8_to_upper (s);
       ds_put_cstr (output, upper);
       free (upper);
       ds_destroy (&tmp);
     }
-  else if (parse_macro_function (ctx, &args, ss_cstr ("!EVAL"), 1, 1,
+  else if (parse_macro_function (me, input, n_input, &args, ss_cstr ("!EVAL"), 1, 1,
                                  input_consumed))
     {
       struct macro_tokens mts = { .n = 0 };
       macro_tokens_from_string__ (&mts, ss_cstr (args.strings[0]),
-                                  ctx->me->segmenter_mode, ctx->me->stack);
+                                  me->segmenter_mode, me->stack);
       struct macro_tokens exp = { .n = 0 };
       struct macro_expansion_stack stack = {
         .name = "!EVAL",
-        .next = ctx->me->stack
+        .next = me->stack
       };
-      struct macro_expander subme = *ctx->me;
+      struct macro_expander subme = *me;
       subme.break_ = NULL;
       subme.stack = &stack;
       
@@ -1256,9 +1249,9 @@ expand_macro_function (struct parse_macro_function_ctx *ctx,
       macro_tokens_uninit (&exp);
       macro_tokens_uninit (&mts);
     }
-  else if (ctx->n_input > 0
-           && ctx->input[0].token.type == T_MACRO_ID
-           && ss_equals_case (ctx->input[0].token.string, ss_cstr ("!NULL")))
+  else if (n_input > 0
+           && input[0].token.type == T_MACRO_ID
+           && ss_equals_case (input[0].token.string, ss_cstr ("!NULL")))
     {
       *input_consumed = 1;
       return true;
@@ -1306,13 +1299,9 @@ macro_evaluate_literal (const struct macro_expander *me,
       return NULL;
     }
 
-  struct parse_macro_function_ctx fctx = {
-    .input = p,
-    .n_input = end - p,
-    .me = me,
-  };
   struct string function_output = DS_EMPTY_INITIALIZER;
-  size_t function_consumed = parse_function_arg (&fctx, 0, &function_output);
+  size_t function_consumed = parse_function_arg (me, p, end - p,
+                                                 0, &function_output);
   struct string unquoted = DS_EMPTY_INITIALIZER;
   if (unquote_string (ds_cstr (&function_output), me->segmenter_mode,
                       &unquoted))
@@ -2048,14 +2037,10 @@ macro_expand (const struct macro_tokens *mts,
             }
         }
 
-      struct parse_macro_function_ctx ctx = {
-        .input = &mts->mts[i],
-        .n_input = mts->n - i,
-        .me = me,
-      };
       struct string function_output = DS_EMPTY_INITIALIZER;
       size_t function_consumed;
-      if (expand_macro_function (&ctx, &function_output, &function_consumed))
+      if (expand_macro_function (me, &mts->mts[i], mts->n - i,
+                                 &function_output, &function_consumed))
         {
           i += function_consumed - 1;