Add environment variable access with $NAME syntax

Lexes $NAME as TK_ENVVAR, compiles reads as __getenv("NAME") calls
and writes ($NAME = expr) as __setenv("NAME", expr) calls. Runtime
functions wrap getenv/setenv/unsetenv with automatic tostring coercion.
This commit is contained in:
Cormac Shannon
2026-02-28 18:08:09 +00:00
parent a773398cab
commit 882a90be48
4 changed files with 94 additions and 17 deletions

17
llex.c
View File

@@ -50,7 +50,7 @@ static const char *const luaX_tokens [] = {
"//", "..", "...", "==", ">=", "<=", "~=",
"<<", ">>", "::", "<eof>",
"<number>", "<integer>", "<name>", "<string>",
"<command>", "<command_interp>"
"<command>", "<command_interp>", "<envvar>"
};
@@ -108,6 +108,9 @@ static const char *txtToken (LexState *ls, int token) {
case TK_FLT: case TK_INT:
save(ls, '\0');
return luaO_pushfstring(ls->L, "'%s'", luaZ_buffer(ls->buff));
case TK_ENVVAR:
save(ls, '\0');
return luaO_pushfstring(ls->L, "'$%s'", luaZ_buffer(ls->buff));
default:
return luaX_token2str(ls, token);
}
@@ -633,6 +636,18 @@ static int llex (LexState *ls, SemInfo *seminfo) {
case '`': { /* explicit command `ls -l` with ${} interpolation */
return read_command(ls, seminfo);
}
case '$': { /* environment variable $NAME */
next(ls);
if (lislalpha(ls->current)) { /* $NAME */
do {
save_and_next(ls);
} while (lislalnum(ls->current));
seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
luaZ_bufflen(ls->buff));
return TK_ENVVAR;
}
else return '$'; /* bare $ as single-char token */
}
case '.': { /* '.', '..', '...', or number */
save_and_next(ls);
if (check_next1(ls, '.')) {