Implement $VAR expansion in commands (issue #25)
Extend read_command_body() to detect $NAME and trigger interpolation
using the same fragment-split mechanism as ${expr}. The lexer collects
the identifier into cmd_envvar; the parser's unified parseinterp()
branches on it to emit tostring(getenv(NAME)).
This commit is contained in:
28
lparser.c
28
lparser.c
@@ -553,23 +553,35 @@ static void singlevar (LexState *ls, expdesc *var) {
|
||||
}
|
||||
|
||||
|
||||
static void codeenvget (LexState *ls, expdesc *v, TString *name);
|
||||
|
||||
/*
|
||||
** Helper: parse a single ${expr} interpolation fragment.
|
||||
** Emits tostring(expr), reads the next command continuation fragment,
|
||||
** and pushes it as a string constant. Returns with the continuation
|
||||
** token already set (TK_COMMAND or TK_INTERACTIVE).
|
||||
** Parse a single interpolation fragment in a command: either ${expr}
|
||||
** or $NAME. Emits tostring(<value>), reads the continuation fragment,
|
||||
** and pushes it as a string constant.
|
||||
** For ${expr}: advances past the command token, parses expr, checks '}'.
|
||||
** For $NAME: the identifier was already collected by the lexer into
|
||||
** cmd_envvar — no tokens to consume, just emit getenv(name).
|
||||
*/
|
||||
static void parseinterp (LexState *ls, TString *tsname, int *nconcat) {
|
||||
FuncState *fs = ls->fs;
|
||||
expdesc interp, tostrfn;
|
||||
int tostr_base;
|
||||
luaX_next(ls); /* advance past TK_COMMAND / TK_INTERACTIVE */
|
||||
/* emit tostring(expr) */
|
||||
TString *envname = ls->cmd_envvar;
|
||||
ls->cmd_envvar = NULL;
|
||||
buildglobal(ls, tsname, &tostrfn);
|
||||
luaK_exp2nextreg(fs, &tostrfn);
|
||||
tostr_base = tostrfn.u.info;
|
||||
expr(ls, &interp);
|
||||
check(ls, '}');
|
||||
if (envname != NULL) {
|
||||
/* $NAME — emit getenv(name) */
|
||||
codeenvget(ls, &interp, envname);
|
||||
}
|
||||
else {
|
||||
/* ${expr} — parse the expression */
|
||||
luaX_next(ls); /* advance past TK_COMMAND / TK_INTERACTIVE */
|
||||
expr(ls, &interp);
|
||||
check(ls, '}');
|
||||
}
|
||||
luaK_exp2nextreg(fs, &interp);
|
||||
luaK_codeABC(fs, OP_CALL, tostr_base, 2, 2);
|
||||
fs->freereg = cast_byte(tostr_base + 1);
|
||||
|
||||
Reference in New Issue
Block a user