Refactor: extract lookup_lush_func, reorder helpers, eliminate forward decl
Extract lookup_lush_func() in lcmd.c to deduplicate the registry lookup pattern shared by try_builtin and exec_user_command. Move exec_user_command after exec_failed to group helpers together. Move codeenvget definition in lparser.c to replace its forward declaration.
This commit is contained in:
408
lcmd.c
408
lcmd.c
@@ -607,6 +607,74 @@ static void read_pipes (int fd_out, int fd_err,
|
||||
}
|
||||
|
||||
|
||||
/* ===== pipeline execution ===== */
|
||||
|
||||
/*
|
||||
** Build result table {code=N, stdout=S, stderr=S} on the Lua stack.
|
||||
*/
|
||||
static void push_result_table (lua_State *L, int code,
|
||||
DynBuf *buf_out, DynBuf *buf_err) {
|
||||
lua_createtable(L, 0, 3);
|
||||
lua_pushinteger(L, code);
|
||||
lua_setfield(L, -2, "code");
|
||||
lua_pushlstring(L, buf_out->data ? buf_out->data : "", buf_out->len);
|
||||
lua_setfield(L, -2, "stdout");
|
||||
lua_pushlstring(L, buf_err->data ? buf_err->data : "", buf_err->len);
|
||||
lua_setfield(L, -2, "stderr");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Extract exit code from wait status.
|
||||
*/
|
||||
static int exit_code_from_status (int status) {
|
||||
if (WIFEXITED(status))
|
||||
return WEXITSTATUS(status);
|
||||
else if (WIFSIGNALED(status))
|
||||
return 128 + WTERMSIG(status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Write "name: strerror(errno)\n" to stderr after exec failure.
|
||||
** Only called in forked child processes.
|
||||
*/
|
||||
static void exec_failed (const char *name) {
|
||||
const char *err = strerror(errno);
|
||||
(void)write(STDERR_FILENO, name, strlen(name));
|
||||
(void)write(STDERR_FILENO, ": ", 2);
|
||||
(void)write(STDERR_FILENO, err, strlen(err));
|
||||
(void)write(STDERR_FILENO, "\n", 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Look up a function in lush[table][key].
|
||||
** On success, pushes the function and returns 1.
|
||||
** On failure, cleans the stack and returns 0.
|
||||
*/
|
||||
static int lookup_lush_func (lua_State *L, const char *table,
|
||||
const char *key) {
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_LUSH);
|
||||
if (!lua_istable(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
}
|
||||
if (lua_getfield(L, -1, table) != LUA_TTABLE) {
|
||||
lua_pop(L, 2);
|
||||
return 0;
|
||||
}
|
||||
if (lua_getfield(L, -1, key) != LUA_TFUNCTION) {
|
||||
lua_pop(L, 3);
|
||||
return 0;
|
||||
}
|
||||
lua_remove(L, -2); /* remove subtable */
|
||||
lua_remove(L, -2); /* remove lush table */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ===== user command dispatch (runs in forked child) ===== */
|
||||
|
||||
/*
|
||||
@@ -617,21 +685,8 @@ static void read_pipes (int fd_out, int fd_err,
|
||||
*/
|
||||
static int exec_user_command (lua_State *L, ParsedArgs *pa) {
|
||||
int i, code = 0;
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_LUSH);
|
||||
if (!lua_istable(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
if (!lookup_lush_func(L, "commands", pa->argv[0]))
|
||||
return 0;
|
||||
}
|
||||
if (lua_getfield(L, -1, "commands") != LUA_TTABLE) {
|
||||
lua_pop(L, 2);
|
||||
return 0;
|
||||
}
|
||||
if (lua_getfield(L, -1, pa->argv[0]) != LUA_TFUNCTION) {
|
||||
lua_pop(L, 3);
|
||||
return 0;
|
||||
}
|
||||
lua_remove(L, -2); /* remove commands table */
|
||||
lua_remove(L, -2); /* remove lush table */
|
||||
for (i = 0; i < pa->argc; i++)
|
||||
lua_pushstring(L, pa->argv[i]);
|
||||
if (lua_pcall(L, pa->argc, 1, 0) != LUA_OK) {
|
||||
@@ -658,23 +713,6 @@ static int exec_user_command (lua_State *L, ParsedArgs *pa) {
|
||||
}
|
||||
|
||||
|
||||
/* ===== pipeline execution ===== */
|
||||
|
||||
/*
|
||||
** Build result table {code=N, stdout=S, stderr=S} on the Lua stack.
|
||||
*/
|
||||
static void push_result_table (lua_State *L, int code,
|
||||
DynBuf *buf_out, DynBuf *buf_err) {
|
||||
lua_createtable(L, 0, 3);
|
||||
lua_pushinteger(L, code);
|
||||
lua_setfield(L, -2, "code");
|
||||
lua_pushlstring(L, buf_out->data ? buf_out->data : "", buf_out->len);
|
||||
lua_setfield(L, -2, "stdout");
|
||||
lua_pushlstring(L, buf_err->data ? buf_err->data : "", buf_err->len);
|
||||
lua_setfield(L, -2, "stderr");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Execute a multi-stage pipeline.
|
||||
** stages[0..nstages-1] are command strings. Each is parsed with parse_argv().
|
||||
@@ -850,17 +888,7 @@ static int exec_pipeline (lua_State *L, char **stages, int nstages,
|
||||
|
||||
exec_user_command(L, &pa[i]);
|
||||
execvp(pa[i].argv[0], pa[i].argv);
|
||||
|
||||
/* exec failed */
|
||||
{
|
||||
const char *err = strerror(errno);
|
||||
size_t namelen = strlen(pa[i].argv[0]);
|
||||
size_t errlen = strlen(err);
|
||||
(void)write(STDERR_FILENO, pa[i].argv[0], namelen);
|
||||
(void)write(STDERR_FILENO, ": ", 2);
|
||||
(void)write(STDERR_FILENO, err, errlen);
|
||||
(void)write(STDERR_FILENO, "\n", 1);
|
||||
}
|
||||
exec_failed(pa[i].argv[0]);
|
||||
_exit(127);
|
||||
}
|
||||
}
|
||||
@@ -892,14 +920,8 @@ static int exec_pipeline (lua_State *L, char **stages, int nstages,
|
||||
for (i = 0; i < nstages; i++) {
|
||||
int status;
|
||||
waitpid(pids[i], &status, 0);
|
||||
if (i == nstages - 1) {
|
||||
if (WIFEXITED(status))
|
||||
last_code = WEXITSTATUS(status);
|
||||
else if (WIFSIGNALED(status))
|
||||
last_code = 128 + WTERMSIG(status);
|
||||
else
|
||||
last_code = -1;
|
||||
}
|
||||
if (i == nstages - 1)
|
||||
last_code = exit_code_from_status(status);
|
||||
}
|
||||
free(pids);
|
||||
|
||||
@@ -927,21 +949,8 @@ static int exec_pipeline (lua_State *L, char **stages, int nstages,
|
||||
*/
|
||||
static int try_builtin (lua_State *L, ParsedArgs *pa) {
|
||||
int i;
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_LUSH);
|
||||
if (!lua_istable(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
if (!lookup_lush_func(L, "builtins", pa->argv[0]))
|
||||
return 0;
|
||||
}
|
||||
if (lua_getfield(L, -1, "builtins") != LUA_TTABLE) {
|
||||
lua_pop(L, 2);
|
||||
return 0;
|
||||
}
|
||||
if (lua_getfield(L, -1, pa->argv[0]) != LUA_TFUNCTION) {
|
||||
lua_pop(L, 3);
|
||||
return 0;
|
||||
}
|
||||
lua_remove(L, -2); /* remove builtins table */
|
||||
lua_remove(L, -2); /* remove lush table */
|
||||
for (i = 0; i < pa->argc; i++)
|
||||
lua_pushstring(L, pa->argv[i]);
|
||||
lua_call(L, pa->argc, 1);
|
||||
@@ -1010,6 +1019,97 @@ static int expand_alias (lua_State *L, const char **cmd) {
|
||||
}
|
||||
|
||||
|
||||
/* ===== single-command fork/exec/wait ===== */
|
||||
|
||||
/*
|
||||
** Fork, exec a single command, wait, and push a result table.
|
||||
** If capture is true, stdout/stderr are captured via pipes.
|
||||
** If capture is false, the child inherits the terminal.
|
||||
*/
|
||||
static void fork_exec_single (lua_State *L, ParsedArgs *pa, int capture) {
|
||||
int out_pipe[2], err_pipe[2];
|
||||
pid_t pid;
|
||||
int status;
|
||||
DynBuf buf_out, buf_err;
|
||||
struct sigaction sa_old_pipe, sa_old_int, sa_old_quit, sa_new;
|
||||
|
||||
if (capture) {
|
||||
if (pipe(out_pipe) != 0)
|
||||
luaL_error(L, "pipe() failed: %s", strerror(errno));
|
||||
if (pipe(err_pipe) != 0) {
|
||||
close(out_pipe[0]); close(out_pipe[1]);
|
||||
luaL_error(L, "pipe() failed: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
memset(&sa_new, 0, sizeof(sa_new));
|
||||
sa_new.sa_handler = SIG_IGN;
|
||||
sigemptyset(&sa_new.sa_mask);
|
||||
sigaction(SIGPIPE, &sa_new, &sa_old_pipe);
|
||||
if (!capture) {
|
||||
sigaction(SIGINT, &sa_new, &sa_old_int);
|
||||
sigaction(SIGQUIT, &sa_new, &sa_old_quit);
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
if (capture) {
|
||||
close(out_pipe[0]); close(out_pipe[1]);
|
||||
close(err_pipe[0]); close(err_pipe[1]);
|
||||
}
|
||||
sigaction(SIGPIPE, &sa_old_pipe, NULL);
|
||||
if (!capture) {
|
||||
sigaction(SIGINT, &sa_old_int, NULL);
|
||||
sigaction(SIGQUIT, &sa_old_quit, NULL);
|
||||
}
|
||||
luaL_error(L, "fork() failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
/* child */
|
||||
sa_new.sa_handler = SIG_DFL;
|
||||
sigaction(SIGPIPE, &sa_new, NULL);
|
||||
if (!capture) {
|
||||
sigaction(SIGINT, &sa_new, NULL);
|
||||
sigaction(SIGQUIT, &sa_new, NULL);
|
||||
}
|
||||
if (capture) {
|
||||
close(out_pipe[0]);
|
||||
close(err_pipe[0]);
|
||||
dup2(out_pipe[1], STDOUT_FILENO);
|
||||
dup2(err_pipe[1], STDERR_FILENO);
|
||||
close(out_pipe[1]);
|
||||
close(err_pipe[1]);
|
||||
}
|
||||
exec_user_command(L, pa);
|
||||
execvp(pa->argv[0], pa->argv);
|
||||
exec_failed(pa->argv[0]);
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
/* parent */
|
||||
dynbuf_init(&buf_out);
|
||||
dynbuf_init(&buf_err);
|
||||
if (capture) {
|
||||
close(out_pipe[1]);
|
||||
close(err_pipe[1]);
|
||||
read_pipes(out_pipe[0], err_pipe[0], &buf_out, &buf_err);
|
||||
}
|
||||
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
sigaction(SIGPIPE, &sa_old_pipe, NULL);
|
||||
if (!capture) {
|
||||
sigaction(SIGINT, &sa_old_int, NULL);
|
||||
sigaction(SIGQUIT, &sa_old_quit, NULL);
|
||||
}
|
||||
|
||||
push_result_table(L, exit_code_from_status(status), &buf_out, &buf_err);
|
||||
dynbuf_free(&buf_out);
|
||||
dynbuf_free(&buf_err);
|
||||
}
|
||||
|
||||
|
||||
/* ===== lushCmd_command ===== */
|
||||
|
||||
int lushCmd_command (lua_State *L) {
|
||||
@@ -1017,11 +1117,7 @@ int lushCmd_command (lua_State *L) {
|
||||
char *stages[MAX_PIPELINE_STAGES];
|
||||
int nstages;
|
||||
ParsedArgs pa;
|
||||
int out_pipe[2], err_pipe[2];
|
||||
pid_t pid;
|
||||
int status;
|
||||
DynBuf buf_out, buf_err;
|
||||
struct sigaction sa_old, sa_new;
|
||||
DynBuf empty_out, empty_err;
|
||||
|
||||
/* expand alias before pipeline splitting */
|
||||
expand_alias(L, &cmd);
|
||||
@@ -1047,13 +1143,9 @@ int lushCmd_command (lua_State *L) {
|
||||
/* empty command: return {code=0, stdout="", stderr=""} */
|
||||
if (pa.argc == 0) {
|
||||
free_argv(&pa);
|
||||
lua_createtable(L, 0, 3);
|
||||
lua_pushinteger(L, 0);
|
||||
lua_setfield(L, -2, "code");
|
||||
lua_pushliteral(L, "");
|
||||
lua_setfield(L, -2, "stdout");
|
||||
lua_pushliteral(L, "");
|
||||
lua_setfield(L, -2, "stderr");
|
||||
dynbuf_init(&empty_out);
|
||||
dynbuf_init(&empty_err);
|
||||
push_result_table(L, 0, &empty_out, &empty_err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1063,96 +1155,8 @@ int lushCmd_command (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* create pipes */
|
||||
if (pipe(out_pipe) != 0) {
|
||||
free_argv(&pa);
|
||||
return luaL_error(L, "pipe() failed: %s", strerror(errno));
|
||||
}
|
||||
if (pipe(err_pipe) != 0) {
|
||||
close(out_pipe[0]); close(out_pipe[1]);
|
||||
free_argv(&pa);
|
||||
return luaL_error(L, "pipe() failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
/* ignore SIGPIPE so parent doesn't crash if child exits early */
|
||||
memset(&sa_new, 0, sizeof(sa_new));
|
||||
sa_new.sa_handler = SIG_IGN;
|
||||
sigemptyset(&sa_new.sa_mask);
|
||||
sigaction(SIGPIPE, &sa_new, &sa_old);
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
close(out_pipe[0]); close(out_pipe[1]);
|
||||
close(err_pipe[0]); close(err_pipe[1]);
|
||||
free_argv(&pa);
|
||||
sigaction(SIGPIPE, &sa_old, NULL);
|
||||
return luaL_error(L, "fork() failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
/* child */
|
||||
close(out_pipe[0]);
|
||||
close(err_pipe[0]);
|
||||
dup2(out_pipe[1], STDOUT_FILENO);
|
||||
dup2(err_pipe[1], STDERR_FILENO);
|
||||
close(out_pipe[1]);
|
||||
close(err_pipe[1]);
|
||||
|
||||
/* restore default SIGPIPE for child */
|
||||
sa_new.sa_handler = SIG_DFL;
|
||||
sigaction(SIGPIPE, &sa_new, NULL);
|
||||
|
||||
exec_user_command(L, &pa);
|
||||
execvp(pa.argv[0], pa.argv);
|
||||
|
||||
/* exec failed — write error to stderr and exit */
|
||||
{
|
||||
const char *err = strerror(errno);
|
||||
size_t namelen = strlen(pa.argv[0]);
|
||||
size_t errlen = strlen(err);
|
||||
/* write "cmd: error\n" */
|
||||
(void)write(STDERR_FILENO, pa.argv[0], namelen);
|
||||
(void)write(STDERR_FILENO, ": ", 2);
|
||||
(void)write(STDERR_FILENO, err, errlen);
|
||||
(void)write(STDERR_FILENO, "\n", 1);
|
||||
}
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
/* parent */
|
||||
close(out_pipe[1]);
|
||||
close(err_pipe[1]);
|
||||
fork_exec_single(L, &pa, 1);
|
||||
free_argv(&pa);
|
||||
|
||||
dynbuf_init(&buf_out);
|
||||
dynbuf_init(&buf_err);
|
||||
read_pipes(out_pipe[0], err_pipe[0], &buf_out, &buf_err);
|
||||
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
/* restore old SIGPIPE handler */
|
||||
sigaction(SIGPIPE, &sa_old, NULL);
|
||||
|
||||
/* build result table */
|
||||
lua_createtable(L, 0, 3);
|
||||
|
||||
if (WIFEXITED(status))
|
||||
lua_pushinteger(L, WEXITSTATUS(status));
|
||||
else if (WIFSIGNALED(status))
|
||||
lua_pushinteger(L, 128 + WTERMSIG(status));
|
||||
else
|
||||
lua_pushinteger(L, -1);
|
||||
lua_setfield(L, -2, "code");
|
||||
|
||||
lua_pushlstring(L, buf_out.data ? buf_out.data : "", buf_out.len);
|
||||
lua_setfield(L, -2, "stdout");
|
||||
|
||||
lua_pushlstring(L, buf_err.data ? buf_err.data : "", buf_err.len);
|
||||
lua_setfield(L, -2, "stderr");
|
||||
|
||||
dynbuf_free(&buf_out);
|
||||
dynbuf_free(&buf_err);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1188,10 +1192,7 @@ int lushCmd_interactive (lua_State *L) {
|
||||
char *stages[MAX_PIPELINE_STAGES];
|
||||
int nstages;
|
||||
ParsedArgs pa;
|
||||
pid_t pid;
|
||||
int status, code;
|
||||
struct sigaction sa_old_pipe, sa_old_int, sa_old_quit, sa_new;
|
||||
DynBuf buf_out, buf_err;
|
||||
DynBuf empty_out, empty_err;
|
||||
|
||||
/* expand alias before pipeline splitting */
|
||||
expand_alias(L, &cmd);
|
||||
@@ -1216,9 +1217,9 @@ int lushCmd_interactive (lua_State *L) {
|
||||
|
||||
if (pa.argc == 0) {
|
||||
free_argv(&pa);
|
||||
dynbuf_init(&buf_out);
|
||||
dynbuf_init(&buf_err);
|
||||
push_result_table(L, 0, &buf_out, &buf_err);
|
||||
dynbuf_init(&empty_out);
|
||||
dynbuf_init(&empty_err);
|
||||
push_result_table(L, 0, &empty_out, &empty_err);
|
||||
lua_setglobal(L, "_");
|
||||
return 0;
|
||||
}
|
||||
@@ -1230,69 +1231,10 @@ int lushCmd_interactive (lua_State *L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ignore SIGINT, SIGQUIT, SIGPIPE in parent */
|
||||
memset(&sa_new, 0, sizeof(sa_new));
|
||||
sa_new.sa_handler = SIG_IGN;
|
||||
sigemptyset(&sa_new.sa_mask);
|
||||
sigaction(SIGPIPE, &sa_new, &sa_old_pipe);
|
||||
sigaction(SIGINT, &sa_new, &sa_old_int);
|
||||
sigaction(SIGQUIT, &sa_new, &sa_old_quit);
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
free_argv(&pa);
|
||||
sigaction(SIGPIPE, &sa_old_pipe, NULL);
|
||||
sigaction(SIGINT, &sa_old_int, NULL);
|
||||
sigaction(SIGQUIT, &sa_old_quit, NULL);
|
||||
return luaL_error(L, "fork() failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
/* child: restore signal defaults, inherit terminal */
|
||||
sa_new.sa_handler = SIG_DFL;
|
||||
sigaction(SIGPIPE, &sa_new, NULL);
|
||||
sigaction(SIGINT, &sa_new, NULL);
|
||||
sigaction(SIGQUIT, &sa_new, NULL);
|
||||
|
||||
exec_user_command(L, &pa);
|
||||
execvp(pa.argv[0], pa.argv);
|
||||
|
||||
/* exec failed */
|
||||
{
|
||||
const char *err = strerror(errno);
|
||||
size_t namelen = strlen(pa.argv[0]);
|
||||
size_t errlen = strlen(err);
|
||||
(void)write(STDERR_FILENO, pa.argv[0], namelen);
|
||||
(void)write(STDERR_FILENO, ": ", 2);
|
||||
(void)write(STDERR_FILENO, err, errlen);
|
||||
(void)write(STDERR_FILENO, "\n", 1);
|
||||
}
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
/* parent */
|
||||
fork_exec_single(L, &pa, 0);
|
||||
free_argv(&pa);
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
/* restore signals */
|
||||
sigaction(SIGPIPE, &sa_old_pipe, NULL);
|
||||
sigaction(SIGINT, &sa_old_int, NULL);
|
||||
sigaction(SIGQUIT, &sa_old_quit, NULL);
|
||||
|
||||
if (WIFEXITED(status))
|
||||
code = WEXITSTATUS(status);
|
||||
else if (WIFSIGNALED(status))
|
||||
code = 128 + WTERMSIG(status);
|
||||
else
|
||||
code = -1;
|
||||
|
||||
/* build {code=N, stdout="", stderr=""} and set as global _ */
|
||||
dynbuf_init(&buf_out);
|
||||
dynbuf_init(&buf_err);
|
||||
push_result_table(L, code, &buf_out, &buf_err);
|
||||
lua_setglobal(L, "_");
|
||||
|
||||
return 0; /* void — no Lua return values */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
30
lparser.c
30
lparser.c
@@ -553,7 +553,20 @@ static void singlevar (LexState *ls, expdesc *var) {
|
||||
}
|
||||
|
||||
|
||||
static void codeenvget (LexState *ls, expdesc *v, TString *name);
|
||||
static void codeenvget (LexState *ls, expdesc *v, TString *name) {
|
||||
FuncState *fs = ls->fs;
|
||||
int base, line;
|
||||
expdesc func, arg;
|
||||
line = ls->linenumber;
|
||||
codelushfunc(fs, LUSH_OP_GETENV, &func);
|
||||
base = func.u.info;
|
||||
codestring(&arg, name);
|
||||
luaK_exp2nextreg(fs, &arg);
|
||||
init_exp(v, VCALL, luaK_codeABC(fs, OP_CALL, base, 2, 2));
|
||||
luaK_fixline(fs, line);
|
||||
fs->freereg = cast_byte(base + 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Parse a single interpolation fragment in a command: ${expr}, $NAME,
|
||||
@@ -1323,21 +1336,6 @@ static void commandexp (LexState *ls, expdesc *v) {
|
||||
}
|
||||
|
||||
|
||||
static void codeenvget (LexState *ls, expdesc *v, TString *name) {
|
||||
FuncState *fs = ls->fs;
|
||||
int base, line;
|
||||
expdesc func, arg;
|
||||
line = ls->linenumber;
|
||||
codelushfunc(fs, LUSH_OP_GETENV, &func);
|
||||
base = func.u.info;
|
||||
codestring(&arg, name);
|
||||
luaK_exp2nextreg(fs, &arg);
|
||||
init_exp(v, VCALL, luaK_codeABC(fs, OP_CALL, base, 2, 2));
|
||||
luaK_fixline(fs, line);
|
||||
fs->freereg = cast_byte(base + 1);
|
||||
}
|
||||
|
||||
|
||||
static void primaryexp (LexState *ls, expdesc *v) {
|
||||
/* primaryexp -> NAME | '(' expr ')' | COMMAND | ENVVAR */
|
||||
switch (ls->t.token) {
|
||||
|
||||
Reference in New Issue
Block a user