diff options
| author | ruki <[email protected]> | 2017-05-03 00:47:53 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2017-05-03 00:47:53 +0800 |
| commit | de015c5f1e1fb0351d20384ac8ee28425edcfa97 (patch) | |
| tree | 1913827056c864e4a542ddf593dea611245a691f /core/src | |
| parent | 8599e843cc0ed678c0694686975467d73edc93fe (diff) | |
fix stack layout for sandbox.interactive
Diffstat (limited to 'core/src')
| -rw-r--r-- | core/src/xmake/sandbox/interactive.c | 111 |
1 files changed, 76 insertions, 35 deletions
diff --git a/core/src/xmake/sandbox/interactive.c b/core/src/xmake/sandbox/interactive.c index ac2653021..add1e0510 100644 --- a/core/src/xmake/sandbox/interactive.c +++ b/core/src/xmake/sandbox/interactive.c @@ -56,7 +56,7 @@ */ // report results -static tb_void_t report(lua_State *lua, tb_int_t status) +static tb_void_t report(lua_State *lua) { if (!lua_isnil(lua, -1)) { @@ -94,20 +94,27 @@ static tb_int_t traceback(lua_State *lua) // execute codes static tb_int_t docall(lua_State *lua, tb_int_t narg, tb_int_t clear) { - // get function index - tb_int_t base = lua_gettop(lua) - narg; + /* get error function index + * + * stack: arg1(sandbox_scope) scriptfunc(top) -> ... + */ + tb_int_t errfunc = lua_gettop(lua) - narg; // push traceback function lua_pushcfunction(lua, traceback); // put it under chunk and args - lua_insert(lua, base); + lua_insert(lua, errfunc); - // execute it - tb_int_t status = lua_pcall(lua, narg, (clear? 0 : LUA_MULTRET), base); + /* execute it + * + * stack: errfunc arg1 scriptfunc -> ... + * after: errfunc arg1 [results] -> ... + */ + tb_int_t status = lua_pcall(lua, narg, (clear? 0 : LUA_MULTRET), errfunc); // remove traceback function - lua_remove(lua, base); + lua_remove(lua, errfunc); // force a complete garbage collection in case of errors if (status != 0) lua_gc(lua, LUA_GCCOLLECT, 0); @@ -119,17 +126,9 @@ static tb_int_t docall(lua_State *lua, tb_int_t narg, tb_int_t clear) // print prompt static tb_void_t write_prompt(lua_State *lua, tb_int_t firstline) { - // get prompt characters - lua_getfield(lua, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); - tb_char_t const* p = lua_tostring(lua, -1); - if (!p) p = firstline? LUA_PROMPT : LUA_PROMPT2; - // print prompt - tb_printf(p); + tb_printf(firstline? LUA_PROMPT : LUA_PROMPT2); tb_print_sync(); - - // remove global - lua_pop(lua, 1); } // this line is incomplete? @@ -180,10 +179,12 @@ static tb_int_t pushline(lua_State *lua, tb_int_t firstline) } // load code line -static tb_int_t loadline(lua_State *lua) +static tb_int_t loadline(lua_State *lua, tb_int_t top) { + // clear stack + lua_settop(lua, top); + // get input line first - lua_settop(lua, 0); if (!pushline(lua, 1)) // no input? return -1; @@ -191,8 +192,12 @@ static tb_int_t loadline(lua_State *lua) tb_int_t status; while (1) { - // repeat until gets a complete line - status = luaL_loadbuffer(lua, lua_tostring(lua, 1), lua_strlen(lua, 1), "=stdin"); + /* repeat until gets a complete line + * + * stack: arg1(sandbox_scope) scriptbuffer(top) -> ... + * after: arg1(sandbox_scope) scriptbuffer scriptfunc(top) -> ... + */ + status = luaL_loadbuffer(lua, lua_tostring(lua, -1), lua_strlen(lua, -1), "=stdin"); // cannot try to add lines? if (!incomplete(lua, status)) break; @@ -201,18 +206,25 @@ static tb_int_t loadline(lua_State *lua) if (!pushline(lua, 0)) return -1; - // add a new line + /* add a new line + * + * stack: arg1 scriptbuffer scriptfunc scriptbuffer "\n"(top) -> ... + */ lua_pushliteral(lua, "\n"); - // cannot try to add lines? + // between the two lines lua_insert(lua, -2); - // join them + /* join them + * + * stack: arg1 scriptbuffer scriptfunc scriptbuffer scriptbuffer "\n"(top) -> ... + * after: arg1 scriptbuffer scriptfunc scriptbuffer+"\n"(top) -> ... + */ lua_concat(lua, 3); } - // remove line - lua_remove(lua, 1); + // remove redundant scriptbuffer + lua_remove(lua, -2); return status; } @@ -226,27 +238,56 @@ tb_int_t xm_sandbox_interactive(lua_State* lua) // check tb_assert_and_check_return_val(lua, 0); + /* get init stack top + * + * stack: arg1(sandbox_scope) + */ + tb_int_t top = lua_gettop(lua); + // enter interactive tb_int_t status; - while ((status = loadline(lua)) != -1) + while ((status = loadline(lua, top)) != -1) { // execute codes - if (status == 0) status = docall(lua, 0, 0); + if (status == 0) + { + /* bind sandbox + * + * stack: arg1(top) scriptfunc arg1(sandbox_scope) -> ... + */ + lua_pushvalue(lua, 1); + lua_setfenv(lua, -2); + + /* run script + * + * stack: arg1(top) scriptfunc -> ... + */ + status = docall(lua, 0, 0); + } - // report results - report(lua, status); - if (status == 0 && lua_gettop(lua) > 0) + // report errors + if (status) report(lua); + + // print any results + if (status == 0 && lua_gettop(lua) > top) { - // print errors + // get results count + tb_int_t count = lua_gettop(lua) - top; + + /* print errors + * + * stack: arg1(sandbox_scope) [results] -> ... + * after: arg1(sandbox_scope) print [results] -> ... + */ lua_getglobal(lua, "print"); - lua_insert(lua, 1); - if (lua_pcall(lua, lua_gettop(lua)-1, 0, 0) != 0) + lua_insert(lua, -(count + 1)); + if (lua_pcall(lua, count, 0, 0) != 0) tb_printl(lua_pushfstring(lua, "error calling " LUA_QL("print") " (%s)", lua_tostring(lua, -1))); } } - // clear stack - lua_settop(lua, 0); + // clear stack + lua_settop(lua, top); tb_printl(""); tb_print_sync(); |
