enum segmenter_mode segmenter_mode;
struct stringi_map *vars;
bool *expand;
+ bool *break_;
int nesting_countdown;
};
static void
macro_expand (const struct macro_tokens *, const struct macro_expander *,
- const struct macro_expansion_stack *stack,
- bool *break_, struct macro_tokens *exp);
+ const struct macro_expansion_stack *,
+ struct macro_tokens *);
static bool
expand_macro_function (struct parse_macro_function_ctx *ctx,
macro_tokens_from_string__ (&mts, ss_cstr (args.strings[0]),
ctx->me->segmenter_mode, ctx->stack);
struct macro_tokens exp = { .n = 0 };
- macro_expand (&mts, ctx->me,
+ struct macro_expander subme = *ctx->me;
+ subme.break_ = NULL;
+ macro_expand (&mts, &subme,
&(struct macro_expansion_stack) {
.name = "!EVAL",
.next = ctx->stack,
- }, NULL, &exp);
+ }, &exp);
macro_tokens_to_representation (&exp, output, NULL, NULL);
macro_tokens_uninit (&exp);
macro_tokens_uninit (&mts);
macro_expand_if (const struct macro_token *tokens, size_t n_tokens,
const struct macro_expander *me,
const struct macro_expansion_stack *stack,
- bool *break_, struct macro_tokens *exp)
+ struct macro_tokens *exp)
{
const struct macro_token *p = tokens;
const struct macro_token *end = tokens + n_tokens;
.name = "!IF",
.next = stack,
},
- break_, exp);
+ exp);
}
return (end_if + 1) - tokens;
}
.mts = CONST_CAST (struct macro_token *, p),
.n = do_end - p
};
- for (size_t i = 0; i < items.n; i++)
+
+ bool break_ = false;
+ struct macro_expander subme = *me;
+ subme.break_ = &break_;
+
+ for (size_t i = 0; i < items.n && !break_; i++)
{
if (i >= miterate)
{
stringi_map_replace_nocopy (me->vars, ss_xstrdup (var_name),
ss_xstrdup (items.mts[i].representation));
- bool break_ = false;
- macro_expand (&inner, me, &next_stack, &break_, exp);
- if (break_)
- break;
+ macro_expand (&inner, &subme, &next_stack, exp);
}
return do_end - tokens + 1;
}
.n = do_end - p
};
+ bool break_ = false;
+ struct macro_expander subme = *me;
+ subme.break_ = &break_;
+
if ((by > 0 && first <= last) || (by < 0 && first >= last))
{
int i = 0;
for (double index = first;
- by > 0 ? (index <= last) : (index >= last);
+ by > 0 ? (index <= last) : (index >= last) && !break_;
index += by)
{
if (i++ > miterate)
stringi_map_replace_nocopy (me->vars, ss_xstrdup (var_name),
xstrdup (index_s));
- bool break_ = false;
- macro_expand (&inner, me, &next_stack, &break_, exp);
- if (break_)
- break;
+ macro_expand (&inner, &subme, &next_stack, exp);
}
}
macro_expand (const struct macro_tokens *mts,
const struct macro_expander *me,
const struct macro_expansion_stack *stack,
- bool *break_, struct macro_tokens *exp)
+ struct macro_tokens *exp)
{
if (me->nesting_countdown <= 0)
{
return;
}
- for (size_t i = 0; i < mts->n && (!break_ || !*break_); i++)
+ for (size_t i = 0; i < mts->n && (!me->break_ || !*me->break_); i++)
{
const struct macro_token *mt = &mts->mts[i];
const struct token *token = &mt->token;
me->macro, token->string);
if (param)
{
- const struct macro_tokens *arg = me->args[param - me->macro->params];
+ const struct macro_tokens *arg
+ = me->args[param - me->macro->params];
if (*me->expand && param->expand_arg)
{
struct stringi_map vars = STRINGI_MAP_INITIALIZER (vars);
.args = NULL,
.segmenter_mode = me->segmenter_mode,
.expand = me->expand,
+ .break_ = NULL,
.vars = &vars,
.nesting_countdown = me->nesting_countdown,
};
macro_expand (arg, &subme, &(struct macro_expansion_stack) {
.name = param->name,
.next = stack,
- }, break_, exp);
+ }, exp);
stringi_map_destroy (&vars);
}
else
.args = NULL,
.segmenter_mode = me->segmenter_mode,
.expand = me->expand,
+ .break_ = NULL,
.vars = &vars,
.nesting_countdown = me->nesting_countdown,
};
&(struct macro_expansion_stack) {
.name = "!*",
.next = stack,
- }, break_, exp);
+ }, exp);
stringi_map_destroy (&vars);
}
else
}
size_t n = macro_expand_if (&mts->mts[i], mts->n - i, me, stack,
- break_, exp);
+ exp);
if (n > 0)
{
i += n - 1;
.args = submc->args,
.segmenter_mode = me->segmenter_mode,
.expand = me->expand,
+ .break_ = NULL,
.vars = &vars,
.nesting_countdown = me->nesting_countdown - 1,
};
.first_line = submc->macro->first_line,
.last_line = submc->macro->last_line,
.next = stack,
- }, break_, exp);
+ }, exp);
macro_call_destroy (submc);
stringi_map_destroy (&vars);
continue;
if (ss_equals_case (token->string, ss_cstr ("!break")))
{
- if (!break_)
+ if (!me->break_)
macro_error (stack, mt, _("!BREAK outside !DO."));
else
{
- *break_ = true;
+ *me->break_ = true;
break;
}
}
.args = mc->args,
.segmenter_mode = segmenter_mode,
.expand = &expand,
+ .break_ = NULL,
.vars = &vars,
.nesting_countdown = settings_get_mnest (),
};
.first_line = mc->macro->first_line,
.last_line = mc->macro->last_line,
};
- macro_expand (&mc->macro->body, &me, &stack, NULL, exp);
+ macro_expand (&mc->macro->body, &me, &stack, exp);
stringi_map_destroy (&vars);
}