+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_token *p = tokens;
+ const struct macro_token *end = tokens + n_tokens;
+
+ if (p >= end || !ss_equals_case (p->token.string, ss_cstr ("!LET")))
+ return 0;
+ p++;
+
+ if (p >= end || p->token.type != T_MACRO_ID)
+ {
+ printf ("expected macro variable name following !LET\n");
+ return 0;
+ }
+ const struct substring var_name = p->token.string;
+ p++;
+
+ if (p >= end || p->token.type != T_EQUALS)
+ {
+ printf ("expected = following !LET\n");
+ return 0;
+ }
+ p++;
+
+ char *value = macro_evaluate_expression (&p, end - p,
+ nesting_countdown, macros, me, vars,
+ expand);
+ if (!value)
+ return 0;
+
+ string_map_replace_nocopy (vars, ss_xstrdup (var_name), value);
+ return p - tokens;
+}
+