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:
Cormac Shannon
2026-03-18 08:35:46 +00:00
parent 635569961e
commit 42baabde34
7 changed files with 98 additions and 13 deletions

12
llex.c
View File

@@ -192,6 +192,7 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
/* all three strings here ("_ENV", "break", "global") were fixed,
so they cannot be collected */
ls->cmd_mode = 0;
ls->cmd_envvar = NULL;
ls->envn = luaS_newliteral(L, LUA_ENV); /* get env string */
ls->brkn = luaS_newliteral(L, "break"); /* get "break" string */
#if defined(LUA_COMPAT_GLOBAL)
@@ -515,6 +516,17 @@ static int read_command_body (LexState *ls, SemInfo *seminfo) {
ls->saved_cmd_mode = ls->cmd_mode; /* save for readcommandcont */
return interactive ? TK_INTERACTIVE : TK_COMMAND;
}
else if (lislalpha(ls->current)) {
/* $NAME envvar expansion */
seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
luaZ_bufflen(ls->buff));
ls->saved_cmd_mode = ls->cmd_mode;
luaZ_resetbuffer(ls->buff);
do { save_and_next(ls); } while (lislalnum(ls->current));
ls->cmd_envvar = luaX_newstring(ls, luaZ_buffer(ls->buff),
luaZ_bufflen(ls->buff));
return interactive ? TK_INTERACTIVE : TK_COMMAND;
}
else {
save(ls, '$'); /* not an interpolation, keep literal '$' */
}