/* Macro expander.
- Macro expansion has two phases. The first phase uses an FSM driven by
+ Macro expansion has two phases. Phase 1 uses an FSM driven by
macro_expander_create() and macro_expander_add() to identify the macro being
called and obtain its arguments. 'state' identifies the FSM state.
- The second phase is macro expansion via macro_expander_get_expansion(). */
+ Phase 2 is macro expansion via macro_expander_get_expansion(). */
struct macro_expander
{
+ /* Phases 1 and 2. */
const struct macro_set *macros;
const struct macro *macro;
+ struct macro_tokens **args;
+ /* Phase 1 only. */
enum me_state state;
size_t n_tokens;
-
- struct macro_tokens **args;
const struct macro_param *param; /* Parameter currently being parsed. */
+
+ /* Phase 2 only. */
+ enum segmenter_mode segmenter_mode;
};
/* Completes macro expansion by initializing arguments that weren't supplied to
const struct macro_token *input;
size_t n_input;
int nesting_countdown;
- enum segmenter_mode segmenter_mode;
const struct macro_set *macros;
const struct macro_expander *me;
const struct macro_expansion_stack *stack;
static void
macro_expand (const struct macro_tokens *, int nesting_countdown,
- enum segmenter_mode segmenter_mode, const struct macro_set *,
+ const struct macro_set *,
const struct macro_expander *, struct string_map *vars,
const struct macro_expansion_stack *stack,
bool *expand, bool *break_,
.input = &ctx->input[i],
.n_input = ctx->n_input - i,
.nesting_countdown = ctx->nesting_countdown,
- .segmenter_mode = ctx->segmenter_mode,
.macros = ctx->macros,
.me = ctx->me,
.stack = ctx->stack,
input_consumed))
{
for (size_t i = 0; i < args.n; i++)
- if (!unquote_string (args.strings[i], ctx->segmenter_mode, output))
+ if (!unquote_string (args.strings[i], ctx->me->segmenter_mode, output))
ds_put_cstr (output, args.strings[i]);
}
else if (parse_macro_function (ctx, &args, ss_cstr ("!HEAD"), 1, 1,
{
struct string tmp;
const char *s = unquote_string_in_place (args.strings[0],
- ctx->segmenter_mode, &tmp);
+ ctx->me->segmenter_mode, &tmp);
struct macro_tokens mts = { .n = 0 };
- macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->segmenter_mode,
+ macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->me->segmenter_mode,
ctx->stack);
if (mts.n > 0)
ds_put_substring (output, mts.mts[0].representation);
else if (parse_macro_function (ctx, &args, ss_cstr ("!QUOTE"), 1, 1,
input_consumed))
{
- if (unquote_string (args.strings[0], ctx->segmenter_mode, NULL))
+ if (unquote_string (args.strings[0], ctx->me->segmenter_mode, NULL))
ds_put_cstr (output, args.strings[0]);
else
{
{
struct string tmp;
const char *s = unquote_string_in_place (args.strings[0],
- ctx->segmenter_mode, &tmp);
+ ctx->me->segmenter_mode, &tmp);
struct macro_tokens mts = { .n = 0 };
- macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->segmenter_mode,
+ macro_tokens_from_string__ (&mts, ss_cstr (s), ctx->me->segmenter_mode,
ctx->stack);
if (mts.n > 1)
{
else if (parse_macro_function (ctx, &args, ss_cstr ("!UNQUOTE"), 1, 1,
input_consumed))
{
- if (!unquote_string (args.strings[0], ctx->segmenter_mode, output))
+ if (!unquote_string (args.strings[0], ctx->me->segmenter_mode, output))
ds_put_cstr (output, args.strings[0]);
}
else if (parse_macro_function (ctx, &args, ss_cstr ("!UPCASE"), 1, 1,
{
struct string tmp;
const char *s = unquote_string_in_place (args.strings[0],
- ctx->segmenter_mode, &tmp);
+ ctx->me->segmenter_mode, &tmp);
char *upper = utf8_to_upper (s);
ds_put_cstr (output, upper);
free (upper);
{
struct macro_tokens mts = { .n = 0 };
macro_tokens_from_string__ (&mts, ss_cstr (args.strings[0]),
- ctx->segmenter_mode, ctx->stack);
+ ctx->me->segmenter_mode, ctx->stack);
struct macro_tokens exp = { .n = 0 };
- macro_expand (&mts, ctx->nesting_countdown - 1, ctx->segmenter_mode,
+ macro_expand (&mts, ctx->nesting_countdown - 1,
ctx->macros, ctx->me, ctx->vars,
&(struct macro_expansion_stack) {
.name = "!EVAL",
struct expr_context
{
int nesting_countdown;
- enum segmenter_mode segmenter_mode;
const struct macro_set *macros;
const struct macro_expander *me;
const struct macro_expansion_stack *stack;
.input = p,
.n_input = end - p,
.nesting_countdown = ctx->nesting_countdown,
- .segmenter_mode = ctx->segmenter_mode,
.macros = ctx->macros,
.me = ctx->me,
.stack = ctx->stack,
struct string function_output = DS_EMPTY_INITIALIZER;
size_t function_consumed = parse_function_arg (&fctx, 0, &function_output);
struct string unquoted = DS_EMPTY_INITIALIZER;
- if (unquote_string (ds_cstr (&function_output), ctx->segmenter_mode,
+ if (unquote_string (ds_cstr (&function_output), ctx->me->segmenter_mode,
&unquoted))
{
ds_swap (&function_output, &unquoted);
}
struct string lhs_tmp, rhs_tmp;
- int cmp = strcmp (unquote_string_in_place (lhs, ctx->segmenter_mode,
+ int cmp = strcmp (unquote_string_in_place (lhs, ctx->me->segmenter_mode,
&lhs_tmp),
- unquote_string_in_place (rhs, ctx->segmenter_mode,
+ unquote_string_in_place (rhs, ctx->me->segmenter_mode,
&rhs_tmp));
ds_destroy (&lhs_tmp);
ds_destroy (&rhs_tmp);
static char *
macro_evaluate_expression (const struct macro_token **tokens, size_t n_tokens,
int nesting_countdown,
- enum segmenter_mode segmenter_mode,
const struct macro_set *macros,
const struct macro_expander *me,
const struct macro_expansion_stack *stack,
{
const struct expr_context ctx = {
.nesting_countdown = nesting_countdown,
- .segmenter_mode = segmenter_mode,
.macros = macros,
.me = me,
.stack = stack,
static bool
macro_evaluate_number (const struct macro_token **tokens, size_t n_tokens,
int nesting_countdown,
- enum segmenter_mode segmenter_mode,
const struct macro_set *macros,
const struct macro_expander *me,
const struct macro_expansion_stack *stack,
bool *expand, double *number)
{
char *s = macro_evaluate_expression (tokens, n_tokens, nesting_countdown,
- segmenter_mode, macros, me, stack, vars,
- expand);
+ macros, me, stack, vars, expand);
if (!s)
return false;
struct macro_tokens mts = { .n = 0 };
- macro_tokens_from_string__ (&mts, ss_cstr (s), segmenter_mode, stack);
+ macro_tokens_from_string__ (&mts, ss_cstr (s), me->segmenter_mode, stack);
if (mts.n != 1 || !token_is_number (&mts.mts[0].token))
{
macro_error (stack, mts.n > 0 ? &mts.mts[0] : NULL,
static size_t
macro_expand_if (const struct macro_token *tokens, size_t n_tokens,
- int nesting_countdown, enum segmenter_mode segmenter_mode,
- const struct macro_set *macros,
+ int nesting_countdown, const struct macro_set *macros,
const struct macro_expander *me,
const struct macro_expansion_stack *stack,
struct string_map *vars,
p++;
char *result = macro_evaluate_expression (&p, end - p,
- nesting_countdown, segmenter_mode,
+ nesting_countdown,
macros, me,
stack, vars, expand);
if (!result)
.mts = CONST_CAST (struct macro_token *, start),
.n = n,
};
- macro_expand (&mts, nesting_countdown, segmenter_mode, macros, me, vars,
+ macro_expand (&mts, nesting_countdown, macros, me, vars,
&(struct macro_expansion_stack) {
.name = "!IF",
.next = stack,
static size_t
macro_parse_let (const struct macro_token *tokens, size_t n_tokens,
- int nesting_countdown, enum segmenter_mode segmenter_mode,
- const struct macro_set *macros,
+ int nesting_countdown, const struct macro_set *macros,
const struct macro_expander *me,
const struct macro_expansion_stack *stack,
struct string_map *vars, bool *expand)
p++;
char *value = macro_evaluate_expression (&p, end - p, nesting_countdown,
- segmenter_mode, macros, me, stack,
- vars, expand);
+ macros, me, stack, vars, expand);
if (!value)
return 0;
static size_t
macro_expand_do (const struct macro_token *tokens, size_t n_tokens,
- int nesting_countdown, enum segmenter_mode segmenter_mode,
- const struct macro_set *macros,
+ int nesting_countdown, const struct macro_set *macros,
const struct macro_expander *me,
const struct macro_expansion_stack *stack,
struct string_map *vars,
{
p++;
char *list = macro_evaluate_expression (&p, end - p, nesting_countdown,
- segmenter_mode, macros, me,
- &next_stack, vars, expand);
+ macros, me, &next_stack, vars,
+ expand);
if (!list)
return 0;
struct macro_tokens items = { .n = 0 };
- macro_tokens_from_string__ (&items, ss_cstr (list), segmenter_mode,
+ macro_tokens_from_string__ (&items, ss_cstr (list), me->segmenter_mode,
stack);
free (list);
ss_xstrdup (items.mts[i].representation));
bool break_ = false;
- macro_expand (&inner, nesting_countdown, segmenter_mode, macros,
+ macro_expand (&inner, nesting_countdown, macros,
me, vars, &next_stack, expand, &break_, exp);
if (break_)
break;
p++;
double first;
if (!macro_evaluate_number (&p, end - p, nesting_countdown,
- segmenter_mode, macros, me, &next_stack,
+ macros, me, &next_stack,
vars, expand, &first))
return 0;
double last;
if (!macro_evaluate_number (&p, end - p, nesting_countdown,
- segmenter_mode, macros, me, &next_stack,
+ macros, me, &next_stack,
vars, expand, &last))
return 0;
{
p++;
if (!macro_evaluate_number (&p, end - p, nesting_countdown,
- segmenter_mode, macros, me, &next_stack,
+ macros, me, &next_stack,
vars, expand, &by))
return 0;
xstrdup (index_s));
bool break_ = false;
- macro_expand (&inner, nesting_countdown, segmenter_mode, macros,
- me, vars, &next_stack, expand, &break_, exp);
+ macro_expand (&inner, nesting_countdown,
+ macros, me, vars, &next_stack, expand, &break_,
+ exp);
if (break_)
break;
}
static void
macro_expand (const struct macro_tokens *mts, int nesting_countdown,
- enum segmenter_mode segmenter_mode,
const struct macro_set *macros,
const struct macro_expander *me, struct string_map *vars,
const struct macro_expansion_stack *stack,
{
const struct macro_tokens *arg = me->args[param - me->macro->params];
if (*expand && param->expand_arg)
- macro_expand (arg, nesting_countdown, segmenter_mode,
+ macro_expand (arg, nesting_countdown,
macros, NULL, NULL,
&(struct macro_expansion_stack) {
.name = param->name,
const struct macro_tokens *arg = me->args[j];
if (*expand && param->expand_arg)
- macro_expand (arg, nesting_countdown, segmenter_mode,
+ macro_expand (arg, nesting_countdown,
macros, NULL, NULL,
&(struct macro_expansion_stack) {
.name = "!*",
}
size_t n = macro_expand_if (&mts->mts[i], mts->n - i,
- nesting_countdown, segmenter_mode,
+ nesting_countdown,
macros, me, stack,
vars, expand, break_, exp);
if (n > 0)
token->string.length);
if (value)
{
- macro_tokens_from_string__ (exp, ss_cstr (value), segmenter_mode,
- stack);
+ macro_tokens_from_string__ (exp, ss_cstr (value),
+ me->segmenter_mode, stack);
continue;
}
}
{
i += retval - 1;
macro_expand (&subme->macro->body, nesting_countdown - 1,
- segmenter_mode, macros, subme, NULL,
+ macros, subme, NULL,
&(struct macro_expansion_stack) {
.name = subme->macro->name,
.file_name = subme->macro->file_name,
.input = &mts->mts[i],
.n_input = mts->n - i,
.nesting_countdown = nesting_countdown,
- .segmenter_mode = segmenter_mode,
.macros = macros,
.me = me,
.stack = stack,
{
i += function_consumed - 1;
- macro_tokens_from_string__ (exp, function_output.ss, segmenter_mode,
- stack);
+ macro_tokens_from_string__ (exp, function_output.ss,
+ me->segmenter_mode, stack);
ds_destroy (&function_output);
continue;
}
size_t n = macro_parse_let (&mts->mts[i], mts->n - i,
- nesting_countdown, segmenter_mode,
+ nesting_countdown,
macros, me, stack, vars, expand);
if (n > 0)
{
}
n = macro_expand_do (&mts->mts[i], mts->n - i,
- nesting_countdown, segmenter_mode,
- macros, me, stack, vars, expand, exp);
+ nesting_countdown, macros, me, stack,
+ vars, expand, exp);
if (n > 0)
{
i += n - 1;
struct macro_tokens *exp)
{
assert (me->state == ME_FINISHED);
+ me->segmenter_mode = segmenter_mode;
+
bool expand = true;
struct macro_expansion_stack stack = {
.name = me->macro->name,
.first_line = me->macro->first_line,
.last_line = me->macro->last_line,
};
- macro_expand (&me->macro->body, settings_get_mnest (), segmenter_mode,
+ macro_expand (&me->macro->body, settings_get_mnest (),
me->macros, me, NULL, &stack, &expand, NULL, exp);
}