static void aux_lines (lua_State *L, int toclose) { int n = lua_gettop(L) - 1; /* number of arguments to read */ lua_pushinteger(L, n); /* number of arguments to read */ lua_pushboolean(L, toclose); /* close/not close file when finished */ lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */ lua_pushcclosure(L, io_readline, 3 + n); }
/** * Loads and executes a Lua file. * - Arg 1: string containing the file name. * - Ret *: values returned by executing the file body. */ int lua_kernel_base::intf_dofile(lua_State* L) { luaL_checkstring(L, 1); lua_rotate(L, 1, -1); if (lua_fileops::load_file(L) != 1) return 0; //^ should end with the file contents loaded on the stack. actually it will call lua_error otherwise, the return 0 is redundant. lua_rotate(L, 1, 1); // Using a non-protected call here appears to fix an issue in plugins. // The protected call isn't technically necessary anyway, because this function is called from Lua code, // which should already be in a protected environment. lua_call(L, lua_gettop(L) - 1, LUA_MULTRET); return lua_gettop(L); }
static int lyield_co(lua_State *L) { luaL_checktype(L, 1, LUA_TTHREAD); lua_rotate(L, 1, -1); return timing_yield(L); }
static int lresume_co(lua_State *L) { luaL_checktype(L, 2, LUA_TTHREAD); lua_rotate(L, 2, -1); return timing_resume(L); }
/* ** In function 'db_getinfo', the call to 'lua_getinfo' may push ** results on the stack; later it creates the result table to put ** these objects. Function 'treatstackoption' puts the result from ** 'lua_getinfo' on top of the result table so that it can call ** 'lua_setfield'. */ static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { if (L == L1) lua_rotate(L, -2, 1); /* exchange object and table */ else lua_xmove(L1, L, 1); /* move object to the "main" stack */ lua_setfield(L, -2, fname); /* put object into table */ }
static int db_getlocal (lua_State *L) { int arg; lua_State *L1 = getthread(L, &arg); lua_Debug ar; const char *name; int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */ if (lua_isfunction(L, arg + 1)) { /* function argument? */ lua_pushvalue(L, arg + 1); /* push function */ lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ return 1; /* return only name (there is no value) */ } else { /* stack-level argument */ int level = (int)luaL_checkinteger(L, arg + 1); if (!lua_getstack(L1, level, &ar)) /* out of range? */ return luaL_argerror(L, arg+1, "level out of range"); checkstack(L, L1, 1); name = lua_getlocal(L1, &ar, nvar); if (name) { lua_xmove(L1, L, 1); /* move local value */ lua_pushstring(L, name); /* push name */ lua_rotate(L, -2, 1); /* re-order */ return 2; } else { lua_pushnil(L); /* no name (nor value) */ return 1; } } }
static int lyield_co(lua_State *L) { // printf("%s(%d): %d\n", __FUNCTION__, __LINE__, lua_gettop(L)); luaL_checktype(L, 1, LUA_TTHREAD); // 检查类型, 不是协程会挂,不会增加stack lua_rotate(L, 1, -1); // 把1指向的协程放到栈顶 return timing_yield(L); }
static int lresume_co(lua_State *L) { // printf("%s(%d): %d\n", __FUNCTION__, __LINE__, lua_gettop(L)); luaL_checktype(L, 2, LUA_TTHREAD); lua_rotate(L, 2, -1); // 把协程指针移到栈顶 return timing_resume(L); }
/* ** Do a protected call with error handling. After 'lua_rotate', the ** stack will have <f, err, true, f, [args...]>; so, the function passes ** 2 to 'finishpcall' to skip the 2 first values when returning results. */ static int luaB_xpcall (lua_State *L) { int status; int n = lua_gettop(L); luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */ lua_pushboolean(L, 1); /* first result */ lua_pushvalue(L, 1); /* function */ lua_rotate(L, 3, 2); /* move them below function's arguments */ status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall); return finishpcall(L, status, 2); }
int LuaDB_JsonEncode(lua_State *L) { // Expect one value on the stack (argument) // Push a reference cycle table as an upvalue and create a closure lua_newtable(L); lua_pushcclosure(L, &JsonEncodePrivate, 1); // Rotate the initial argument to the top of the stack // Call the closure with the original argument lua_rotate(L, -2, 1); lua_call(L, 1, 1); return 1; }
static int l_three(lua_State* l) { // printf("%s(%d): %d\n", __FUNCTION__, __LINE__, lua_gettop(l)); lua_pushinteger(l, 1); lua_pushinteger(l, 2); lua_pushinteger(l, 3); // lua_rotate(l, 1, 2); // from 1 to top, start from top, rotate 2 -> 2 3 1 lua_rotate(l, 1, -1); // from 1 to top, start from bottom, rotate 1 -> 2 3 1 // lua_rotate(l, 1, -2); // from 1 to top, start from bottom, rotate 2 -> 3 1 2 // printf("%s(%d): %d\n", __FUNCTION__, __LINE__, lua_gettop(l)); return 3; }
int invoke_callback( lua_State* L, void* id, int callback, int args ) { int err = 0; if( L && id ) { // fetch the callback function from the registry meta data table lua_pushlightuserdata( L, id ); lua_gettable( L, LUA_REGISTRYINDEX ); lua_pushinteger( L, callback ); lua_gettable( L, -2 ); lua_rotate( L, -2, 1 ); lua_pop( L, 1 ); // not a function if( ! lua_isfunction( L, -1 ) ) { lua_pop( L, args + 1 ); return err; } // get object/self argument from registry (function argument) if( object_copy( L, id ) ) args++; // make sure things are in the right order if( args > 1 ) lua_rotate( L, -( args + 1 ), 2 ); if( lua_pcall( L, args, 1, 0 ) ) // call the callback printf( "%s\n", lua_tostring( L, -1 ) ); // print the error if( lua_isinteger( L, -1 ) ) err = lua_tointeger( L, -1 ); lua_pop( L, 1 ); } return err; }
/* ** Returns a pointer to a free area with at least 'sz' bytes in buffer ** 'B'. 'boxidx' is the relative position in the stack where the ** buffer's box is or should be. */ static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) { if (B->size - B->n >= sz) /* enough space? */ return B->b + B->n; else { lua_State *L = B->L; char *newbuff; size_t newsize = newbuffsize(B, sz); /* create larger buffer */ if (buffonstack(B)) /* buffer already has a box? */ newbuff = (char *)resizebox(L, boxidx, newsize); /* resize it */ else { /* no box yet */ lua_pushnil(L); /* reserve slot for final result */ newbox(L); /* create a new box */ /* move box (and slot) to its intended position */ lua_rotate(L, boxidx - 1, 2); lua_toclose(L, boxidx); newbuff = (char *)resizebox(L, boxidx, newsize); memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ } B->b = newbuff; B->size = newsize; return newbuff + B->n; } }
/* ** equivalent to 'lua_rawseti', but not raw */ static void seti (lua_State *L, int idx, lua_Integer n) { lua_pushinteger(L, n); lua_rotate(L, -2, 1); /* exchange key and value */ lua_settable(L, idx); /* assume 'idx' is not negative */ }