hmap_insert (&set->macros, &m->hmap_node, hash_macro_name (m->name));
}
\f
+struct macro_expansion_stack
+ {
+ const struct macro_expansion_stack *next;
+ const char *name;
+ };
+
+
enum me_state
{
/* Error state. */
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;
};
macro_expand (const struct macro_tokens *,
int nesting_countdown, const struct macro_set *,
const struct macro_expander *, struct string_map *vars,
- bool *expand, bool *break_, struct macro_tokens *exp);
+ const struct macro_expansion_stack *stack,
+ bool *expand, bool *break_,
+ struct macro_tokens *exp);
static bool
expand_macro_function (struct parse_macro_function_ctx *ctx,
.nesting_countdown = ctx->nesting_countdown,
.macros = ctx->macros,
.me = ctx->me,
+ .stack = ctx->stack,
.vars = ctx->vars,
.expand = ctx->expand,
};
SEG_MODE_INTERACTIVE /* XXX */);
struct macro_tokens exp = { .n = 0 };
macro_expand (&mts, ctx->nesting_countdown - 1, ctx->macros, ctx->me,
- ctx->vars, ctx->expand, NULL, &exp);
+ ctx->vars,
+ &(struct macro_expansion_stack) {
+ .name = "!EVAL",
+ .next = ctx->stack,
+ }, ctx->expand, NULL, &exp);
macro_tokens_to_representation (&exp, output, NULL, NULL);
macro_tokens_uninit (&exp);
macro_tokens_uninit (&mts);
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;
};
.nesting_countdown = ctx->nesting_countdown,
.macros = ctx->macros,
.me = ctx->me,
+ .stack = ctx->stack,
.vars = ctx->vars,
.expand = ctx->expand,
};
static char *
macro_evaluate_expression (const struct macro_token **tokens, size_t n_tokens,
int nesting_countdown, const struct macro_set *macros,
- const struct macro_expander *me, struct string_map *vars,
- bool *expand)
+ const struct macro_expander *me,
+ const struct macro_expansion_stack *stack,
+ struct string_map *vars, bool *expand)
{
const struct expr_context ctx = {
.nesting_countdown = nesting_countdown,
.macros = macros,
.me = me,
+ .stack = stack,
.vars = vars,
.expand = expand,
};
static bool
macro_evaluate_number (const struct macro_token **tokens, size_t n_tokens,
int nesting_countdown, const struct macro_set *macros,
- const struct macro_expander *me, struct string_map *vars,
+ const struct macro_expander *me,
+ const struct macro_expansion_stack *stack,
+ struct string_map *vars,
bool *expand, double *number)
{
char *s = macro_evaluate_expression (tokens, n_tokens, nesting_countdown,
- macros, me, vars, expand);
+ macros, me, stack, vars, expand);
if (!s)
return false;
static size_t
macro_expand_if (const struct macro_token *tokens, size_t n_tokens,
int nesting_countdown, const struct macro_set *macros,
- const struct macro_expander *me, struct string_map *vars,
+ const struct macro_expander *me,
+ const struct macro_expansion_stack *stack,
+ struct string_map *vars,
bool *expand, bool *break_, struct macro_tokens *exp)
{
const struct macro_token *p = tokens;
p++;
char *result = macro_evaluate_expression (&p, end - p,
- nesting_countdown, macros, me, vars,
- expand);
+ nesting_countdown, macros, me,
+ stack, vars, expand);
if (!result)
return 0;
bool b = strcmp (result, "0");
.mts = CONST_CAST (struct macro_token *, start),
.n = n,
};
- macro_expand (&mts, nesting_countdown, macros, me, vars, expand,
- break_, exp);
+ macro_expand (&mts, nesting_countdown, macros, me, vars,
+ &(struct macro_expansion_stack) {
+ .name = "!IF",
+ .next = stack,
+ },
+ expand, break_, exp);
}
return (end_if + 1) - tokens;
}
+static void PRINTF_FORMAT (2, 3)
+macro_error (const struct macro_expansion_stack *stack,
+ const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ char *s = xvasprintf (format, args);
+ va_end (args);
+
+ /* foo.sps:12: While expanding macro 'innermost',
+ foo.sps:23: inside expansion of 'next_inner',
+ foo.sps:34: inside expansion of 'next_inner2',
+ foo.sps:45: inside expansion of 'outermost':
+ error. */
+ struct string header = DS_EMPTY_INITIALIZER;
+ ds_put_format (&header, "While expanding \"%s\"", stack->name);
+ while ((stack = stack->next) != NULL)
+ ds_put_format (&header, ", inside expansion of \"%s\"", stack->name);
+
+ msg (SE, "%s: %s", ds_cstr (&header), s);
+
+ ds_destroy (&header);
+ free (s);
+}
+
static size_t
macro_parse_let (const struct macro_token *tokens, size_t n_tokens,
int nesting_countdown, const struct macro_set *macros,
- const struct macro_expander *me, struct string_map *vars,
- bool *expand)
+ const struct macro_expander *me,
+ const struct macro_expansion_stack *stack,
+ struct string_map *vars, bool *expand)
{
const struct macro_token *p = tokens;
const struct macro_token *end = tokens + n_tokens;
if (p >= end || p->token.type != T_MACRO_ID)
{
- printf ("expected macro variable name following !LET\n");
+ macro_error (stack, "expected macro variable name following !LET");
return 0;
}
const struct substring var_name = p->token.string;
p++;
char *value = macro_evaluate_expression (&p, end - p,
- nesting_countdown, macros, me, vars,
- expand);
+ nesting_countdown, 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, const struct macro_set *macros,
- const struct macro_expander *me, struct string_map *vars,
+ const struct macro_expander *me,
+ const struct macro_expansion_stack *stack,
+ struct string_map *vars,
bool *expand, struct macro_tokens *exp)
{
const struct macro_token *p = tokens;
}
p++;
+ struct macro_expansion_stack next_stack = {
+ .name = "!DO", .next = stack,
+ };
int miterate = settings_get_miterate ();
if (p < end && p->token.type == T_MACRO_ID
&& ss_equals_case (p->token.string, ss_cstr ("!IN")))
{
p++;
char *list = macro_evaluate_expression (&p, end - p,
- nesting_countdown, macros, me, vars,
- expand);
+ nesting_countdown, macros, me,
+ &next_stack, vars, expand);
if (!list)
return 0;
bool break_ = false;
macro_expand (&inner, nesting_countdown, macros,
- me, vars, expand, &break_, exp);
+ me, vars, &next_stack, expand, &break_, exp);
if (break_)
break;
}
p++;
double first;
if (!macro_evaluate_number (&p, end - p, nesting_countdown, macros, me,
- vars, expand, &first))
+ &next_stack, vars, expand, &first))
return 0;
if (p >= end || p->token.type != T_MACRO_ID
double last;
if (!macro_evaluate_number (&p, end - p, nesting_countdown, macros, me,
- vars, expand, &last))
+ &next_stack, vars, expand, &last))
return 0;
double by = 1.0;
{
p++;
if (!macro_evaluate_number (&p, end - p, nesting_countdown, macros, me,
- vars, expand, &by))
+ &next_stack, vars, expand, &by))
return 0;
if (by == 0.0)
bool break_ = false;
macro_expand (&inner, nesting_countdown, macros,
- me, vars, expand, &break_, exp);
+ me, vars, &next_stack, expand, &break_, exp);
if (break_)
break;
}
macro_expand (const struct macro_tokens *mts,
int nesting_countdown, const struct macro_set *macros,
const struct macro_expander *me, struct string_map *vars,
+ const struct macro_expansion_stack *stack,
bool *expand, bool *break_, struct macro_tokens *exp)
{
if (nesting_countdown <= 0)
//macro_tokens_print (arg, stdout);
if (*expand && param->expand_arg)
macro_expand (arg, nesting_countdown, macros, NULL, NULL,
- expand, break_, exp);
+ &(struct macro_expansion_stack) {
+ .name = param->name,
+ .next = stack,
+ }, expand, break_, exp);
else
for (size_t i = 0; i < arg->n; i++)
macro_tokens_add (exp, &arg->mts[i]);
const struct macro_tokens *arg = me->args[j];
if (*expand && param->expand_arg)
macro_expand (arg, nesting_countdown, macros, NULL, NULL,
- expand, break_, exp);
+ &(struct macro_expansion_stack) {
+ .name = "!*",
+ .next = stack,
+ }, expand, break_, exp);
else
for (size_t k = 0; k < arg->n; k++)
macro_tokens_add (exp, &arg->mts[k]);
}
size_t n = macro_expand_if (&mts->mts[i], mts->n - i,
- nesting_countdown, macros, me, vars,
- expand, break_, exp);
+ nesting_countdown, macros, me, stack,
+ vars, expand, break_, exp);
if (n > 0)
{
i += n - 1;
{
i += retval - 1;
macro_expand (&subme->macro->body, nesting_countdown - 1, macros,
- subme, NULL, expand, break_, exp);
+ subme, NULL,
+ &(struct macro_expansion_stack) {
+ .name = subme->macro->name,
+ .next = stack,
+ }, expand, break_, exp);
macro_expander_destroy (subme);
continue;
}
.nesting_countdown = nesting_countdown,
.macros = macros,
.me = me,
+ .stack = stack,
.vars = vars,
.expand = expand,
};
}
size_t n = macro_parse_let (&mts->mts[i], mts->n - i,
- nesting_countdown, macros, me, vars,
- expand);
+ nesting_countdown, macros, me, stack,
+ vars, expand);
if (n > 0)
{
i += n - 1;
}
n = macro_expand_do (&mts->mts[i], mts->n - i,
- nesting_countdown, macros, me, vars,
+ nesting_countdown, macros, me, stack, vars,
expand, exp);
if (n > 0)
{
void
macro_expander_get_expansion (struct macro_expander *me, struct macro_tokens *exp)
{
-#if 0
- for (size_t i = 0; i < me->macro->n_params; i++)
- {
- printf ("%s:\n", me->macro->params[i].name);
- macro_tokens_print (me->args[i], stdout);
- }
-#endif
-
bool expand = true;
+ struct macro_expansion_stack stack = { .name = me->macro->name };
macro_expand (&me->macro->body, settings_get_mnest (),
- me->macros, me, NULL, &expand, NULL, exp);
-
-#if 0
- printf ("expansion:\n");
- macro_tokens_print (exp, stdout);
-#endif
+ me->macros, me, NULL, &stack, &expand, NULL, exp);
}