struct cell * cell_new(lua_State *L, const char * mainfile) { hive_getenv(L, "cell_map"); int cell_map = lua_absindex(L,-1); // cell_map luaL_requiref(L, "cell.c", cell_lib, 0); // cell_map cell_lib struct cell * c = cell_create(); c->L = L; cell_touserdata(L, cell_map, c); // cell_map cell_lib cell_ud lua_setfield(L, -2, "self"); // cell_map cell_lib hive_getenv(L, "system_pointer"); struct cell * sys = lua_touserdata(L, -1); // cell_map cell_lib system_cell lua_pop(L, 1); if (sys) { cell_touserdata(L, cell_map, sys); lua_setfield(L, -2, "system"); } lua_pop(L,2); lua_pushlightuserdata(L, c); hive_setenv(L, "cell_pointer"); int err = luaL_loadfile(L, mainfile); if (err) { printf("%d : %s\n", err, lua_tostring(L,-1)); lua_pop(L,1); goto _error; } err = lua_pcall(L, 0, 0, 0); if (err) { printf("%d : %s\n", err, lua_tostring(L,-1)); lua_pop(L,1); goto _error; } lua_pushcfunction(L, traceback); // upvalue 1 lua_pushcfunction(L, data_unpack); // upvalue 2 hive_getenv(L, "dispatcher"); // upvalue 3 if (!lua_isfunction(L, -1)) { printf("set dispatcher first\n"); goto _error; } hive_getenv(L, "cell_map"); // upvalue 4 lua_pushcclosure(L, lcallback, 4); return c; _error: scheduler_deletetask(L); c->L = NULL; cell_destroy(c); return NULL; }
/*! Create table "name" within table at index tindex */ static void subtable(lua_State *L, int tindex, const char *name, const char *mode) { //> [-0,+1,e] int abs_tindex = lua_absindex(L, tindex); lua_getfield(L, abs_tindex, name); // [-0,+1,e] if (lua_isnil(L, -1)) { // [-0,+0,-] lua_pop(L, 1); // pop(nil) // [-1,+0,-] lua_checkstack(L, 3); // [-0,+0,v] weaktable(L, mode); // pushes a table // [-0,+1,e] lua_pushvalue(L, -1); // dup // [-0,+1,-] rawsetfield(L, abs_tindex, name); // t[name] = table // [-1,+0,e] } } // leaves table on stack
/* ** ensure that stack[idx][fname] has a table and push that table ** into the stack */ LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { lua_getfield(L, idx, fname); if (lua_istable(L, -1)) return 1; /* table already there */ else { lua_pop(L, 1); /* remove previous result */ idx = lua_absindex(L, idx); lua_newtable(L); lua_pushvalue(L, -1); /* copy to be left at top */ lua_setfield(L, idx, fname); /* assign new table to field */ return 0; /* false, because did not find table there */ } }
LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) { int i, t = lua_absindex(L, -1 - nup); for (; l->name; l++) { for (i = 0; i < nup; i++) lua_pushvalue(L, -nup); lua_pushcclosure(L, l->func, nup); lua_setfield(L, t, l->name); } lua_pop(L, nup); } /* luaL_setfuncs() */
static int lua_rl_isglobaltable(lua_State *L, int idx) { #if LUA_VERSION_NUM == 501 return lua_rawequal(L, idx, LUA_GLOBALSINDEX); #else idx = lua_absindex(L, idx); lua_pushglobaltable(L); int same = lua_rawequal(L, idx, -1); lua_pop(L, 1); return same; #endif }
void l2dbus_callbackRef ( lua_State* L, int funcIdx, int userIdx, l2dbus_CallbackCtx* ctx ) { if ( funcIdx != L2DBUS_CALLBACK_NOREF_NEEDED ) { funcIdx = lua_absindex(L, funcIdx); } if ( userIdx != L2DBUS_CALLBACK_NOREF_NEEDED ) { userIdx = lua_absindex(L, userIdx); } if ( L2DBUS_CALLBACK_NOREF_NEEDED != funcIdx ) { lua_pushvalue(L, funcIdx); ctx->funcRef = luaL_ref(L, LUA_REGISTRYINDEX); } else { ctx->funcRef = LUA_NOREF; } if ( L2DBUS_CALLBACK_NOREF_NEEDED != userIdx ) { lua_pushvalue(L, userIdx); ctx->userRef = luaL_ref(L, LUA_REGISTRYINDEX); } else { ctx->userRef = LUA_NOREF; } }
static char* opt_get_string(lua_State *L, int idx, const char *name, int req, const char *err){ const char *value; idx = lua_absindex(L, idx); rawgets(L, idx, name); value = lua_tostring(L, -1); lua_pop(L, 1); if(value) return (char*)value; if(req){ lua_pushstring(L, err); lua_error(L); } return 0; }
// replaces the fifo ud by its uservalue on the stack static keeper_fifo* prepare_fifo_access( lua_State* L, int idx) { keeper_fifo* fifo = (keeper_fifo*) lua_touserdata( L, idx); if( fifo != NULL) { idx = lua_absindex( L, idx); STACK_GROW( L, 1); // we can replace the fifo userdata in the stack without fear of it being GCed, there are other references around lua_getuservalue( L, idx); lua_replace( L, idx); } return fifo; }
// Expects: Function, followed by narg arguments, on top of the stack. // Calls pcall with traceback error handler, removes error handler. // Error is left on top of the stack. // Returns the error code, and the stack index at which the return values start. inline std::tuple<int, int> pcall_helper(lua_State * L, int narg, int nret) noexcept { PRIMER_ASSERT(lua_gettop(L) >= (1 + narg), "Not enough arguments on stack for pcall!"); PRIMER_ASSERT(lua_isfunction(L, -1 - narg), "Missing function for pcall!"); primer::get_error_handler(L); lua_insert(L, -2 - narg); const int error_handler_index = lua_absindex(L, -2 - narg); const int result_code = lua_pcall(L, narg, nret, error_handler_index); lua_remove(L, error_handler_index); return std::tuple<int, int>{result_code, error_handler_index}; }
inline int luaX_abs_index(lua_State* L, int index) { #if LUA_VERSION_NUM+0 >= 502 return lua_absindex(L, index); #else if (index < 0) { int top = lua_gettop(L); if (top >= -index) { return top + index + 1; } } return index; #endif }
LUA_API void luaS_checkColor(lua_State *L, int p, float* x, float *y, float *z, float* w) { p=lua_absindex(L,p); luaL_checktype(L, p, LUA_TTABLE); lua_rawgeti(L, p, 1); *x = (float)lua_tonumber(L, -1); lua_rawgeti(L, p, 2); *y = (float)lua_tonumber(L, -1); lua_rawgeti(L, p, 3); *z = (float)lua_tonumber(L, -1); lua_rawgeti(L, p, 4); *w = (float)lua_tonumber(L, -1); lua_pop(L, 4); }
static void update_on_definition(lua_State* L, int ct_usr, int ct_idx) { ct_usr = lua_absindex(L, ct_usr); ct_idx = lua_absindex(L, ct_idx); lua_pushlightuserdata(L, &to_define_key); lua_rawget(L, ct_usr); if (lua_isnil(L, -1)) { lua_pop(L, 1); /* pop the nil */ /* {} */ lua_newtable(L); /* {__mode='k'} */ lua_newtable(L); lua_pushliteral(L, "k"); lua_setfield(L, -2, "__mode"); /* setmetatable({}, {__mode='k'}) */ lua_setmetatable(L, -2); /* usr[TO_UPDATE_KEY] = setmetatable({}, {__mode='k'}) */ lua_pushlightuserdata(L, &to_define_key); lua_pushvalue(L, -2); lua_rawset(L, ct_usr); /* leave the table on the stack */ } /* to_update[ctype or cdata] = true */ lua_pushvalue(L, ct_idx); lua_pushboolean(L, 1); lua_rawset(L, -3); /* pop the to_update table */ lua_pop(L, 1); }
COMPAT53_API void lua_rotate (lua_State *L, int idx, int n) { int n_elems = 0; idx = lua_absindex(L, idx); n_elems = lua_gettop(L)-idx+1; if (n < 0) n += n_elems; if ( n > 0 && n < n_elems) { luaL_checkstack(L, 2, "not enough stack slots available"); n = n_elems - n; compat53_reverse(L, idx, idx+n-1); compat53_reverse(L, idx+n, idx+n_elems-1); compat53_reverse(L, idx, idx+n_elems-1); } }
LUA_API int luaS_checkVector3(lua_State *L, int p, float* x, float *y, float *z) { p=lua_absindex(L,p); if(lua_type(L,p)!=LUA_TTABLE) return -1; luaL_checktype(L, p, LUA_TTABLE); lua_rawgeti(L, p, 1); *x = (float)lua_tonumber(L, -1); lua_rawgeti(L, p, 2); *y = (float)lua_tonumber(L, -1); lua_rawgeti(L, p, 3); *z = (float)lua_tonumber(L, -1); lua_pop(L, 3); return 0; }
int luaL_getsubtable (lua_State *L, int i, const char *name) { int abs_i = lua_absindex(L, i); luaL_checkstack(L, 3, "not enough stack slots"); lua_pushstring(L, name); lua_gettable(L, abs_i); if (lua_istable(L, -1)) return 1; lua_pop(L, 1); lua_newtable(L); lua_pushstring(L, name); lua_pushvalue(L, -2); lua_settable(L, abs_i); return 0; }
int lua_compare (lua_State *L, int idx1, int idx2, int op) { int result = 0; switch (op) { case LUA_OPEQ: return lua_equal(L, idx1, idx2); case LUA_OPLT: return lua_lessthan(L, idx1, idx2); case LUA_OPLE: luaL_checkstack(L, 5, "not enough stack slots"); idx1 = lua_absindex(L, idx1); idx2 = lua_absindex(L, idx2); lua_pushvalue(L, idx1); lua_pushvalue(L, idx2); compat52_call_lua(L, compat52_compare_code, sizeof(compat52_compare_code)-1, 2, 1); result = lua_toboolean(L, -1); lua_pop(L, 1); return result; default: luaL_error(L, "invalid 'op' argument for lua_compare"); } return 0; }
CellSpec CellSpec::FromLuaTable(lua_State *l, int idx) { const int table = lua_absindex(l, idx); assert(lua_istable(l, table)); const int len = lua_rawlen(l, table); std::vector<float> cellPercent(len); for (int i = 0; i < len; i++) { lua_rawgeti(l, table, i+1); cellPercent[i] = luaL_checknumber(l, -1); lua_pop(l, 1); } return CellSpec(cellPercent); }
LUA_API int luaS_checkColor(lua_State *L, int p, float* x, float *y, float *z, float* w) { p=lua_absindex(L,p); if(lua_type(L,p)!=LUA_TTABLE) return -1; lua_rawgeti(L, p, 1); *x = (float)lua_tonumber(L, -1); lua_rawgeti(L, p, 2); *y = (float)lua_tonumber(L, -1); lua_rawgeti(L, p, 3); *z = (float)lua_tonumber(L, -1); lua_rawgeti(L, p, 4); *w = (float)lua_tonumber(L, -1); lua_pop(L, 4); return 0; }
// Get the value of the property with the name on the stack on position // 'nameIndex'. // Pushes the property value on the stack. // Pre: nameIndex points to a string. void luaUqm_getProp(lua_State *luaState, int nameIndex) { nameIndex = lua_absindex(luaState, nameIndex); lua_getfield(luaState, LUA_REGISTRYINDEX, statePropRegistryKey); // [-1] -> registry[statePropRegistrykey] lua_pushvalue(luaState, nameIndex); // [-2] -> registry[statePropRegistrykey] // [-1] -> name lua_gettable(luaState, -2); // [-2] -> registry[statePropRegistrykey] // [-1] -> registry[statePropRegistrykey][name] lua_replace(luaState, -2); // [-1] -> registry[statePropRegistrykey][name] }
LUACLLIB_API int luaC_isclass(lua_State* L, int inx, const char* name /*= NULL*/) { int r = -1; int ix = lua_absindex(L, inx); lua_checkstack(L, 1); if (name == NULL) { lua_pushvalue(L, lua_upvalueindex(1)); if (!lua_isfunction(L, -1)) r = 0; // Not a class, assume in class closure not method. } else { get_class(L, name); //|CL| } r = luaC_istype(L, ix, r); lua_pop(L, 1); return r; };
bool luaW_tolocation(lua_State *L, int index, map_location& loc) { if (!lua_checkstack(L, LUA_MINSTACK)) { return false; } if (lua_isnoneornil(L, index)) { // Need this special check because luaW_tovconfig returns true in this case return false; } vconfig dummy_vcfg = vconfig::unconstructed_vconfig(); index = lua_absindex(L, index); if (lua_istable(L, index) || luaW_tounit(L, index) || luaW_tovconfig(L, index, dummy_vcfg)) { map_location result; int x_was_num = 0, y_was_num = 0; lua_getfield(L, index, "x"); result.set_wml_x(lua_tonumberx(L, -1, &x_was_num)); lua_getfield(L, index, "y"); result.set_wml_y(lua_tonumberx(L, -1, &y_was_num)); lua_pop(L, 2); if (!x_was_num || !y_was_num) { // If we get here and it was userdata, checking numeric indices won't help // (It won't help if it was a config either, but there's no easy way to check that.) if (lua_isuserdata(L, index)) { return false; } lua_rawgeti(L, index, 1); result.set_wml_x(lua_tonumberx(L, -1, &x_was_num)); lua_rawgeti(L, index, 2); result.set_wml_y(lua_tonumberx(L, -1, &y_was_num)); lua_pop(L, 2); } if (x_was_num && y_was_num) { loc = result; return true; } } else if (lua_isnumber(L, index) && lua_isnumber(L, index + 1)) { // If it's a number, then we consume two elements on the stack // Since we have no way of notifying the caller that we have // done this, we remove the first number from the stack. loc.set_wml_x(lua_tonumber(L, index)); lua_remove(L, index); loc.set_wml_y(lua_tonumber(L, index)); return true; } return false; }
void* push_cdata(lua_State* L, int ct_usr, const struct ctype* ct) { struct cdata* cd; size_t sz = ct->is_reference ? sizeof(void*) : ctype_size(L, ct); ct_usr = lua_absindex(L, ct_usr); /* This is to stop valgrind from complaining. Bitfields are accessed in 8 * byte chunks so that the code doesn't have to deal with different access * patterns, but this means that occasionally it will read past the end of * the struct. As its not setting the bits past the end (only reading and * then writing the bits back) and the read is aligned its a non-issue, * but valgrind complains nonetheless. */ if (ct->has_bitfield) { sz = ALIGN_UP(sz, 7); } cd = (struct cdata*) lua_newuserdata(L, sizeof(struct cdata) + sz); *(struct ctype*) &cd->type = *ct; memset(cd+1, 0, sz); /* TODO: handle cases where lua_newuserdata returns a pointer that is not * aligned */ #if 0 assert((uintptr_t) (cd + 1) % 8 == 0); #endif #if LUA_VERSION_NUM == 501 if (!ct_usr || lua_isnil(L, ct_usr)) { push_upval(L, &niluv_key); lua_setfenv(L, -2); } #endif if (ct_usr && !lua_isnil(L, ct_usr)) { lua_pushvalue(L, ct_usr); lua_setuservalue(L, -2); } push_upval(L, &cdata_mt_key); lua_setmetatable(L, -2); if (!ct->is_defined && ct_usr && !lua_isnil(L, ct_usr)) { update_on_definition(L, ct_usr, -1); } return cd+1; }
static void mooa_print_table(lua_State *L, int index, int indent) { index = lua_absindex(L, index); lua_pushnil(L); fprintf(stderr, "{\n"); while (lua_next(L, index) != 0) { mooa_indent(indent + 2); mooa_print_value(L, -2, indent + 2); fprintf(stderr, " = "); mooa_print_value(L, -1, indent + 2); fprintf(stderr, ",\n"); /* removes 'value'; keeps 'key' for next iteration */ lua_pop(L, 1); } mooa_indent(indent); fprintf(stderr, "}"); }
// Expects: Function, followed by narg arguments, on top of the stack. // Calls lua_resume. If an error occurs, calls the traceback error handler, // removes error handler. Error is left on top of the stack. // Returns the error code, and the stack index at which the return values start. inline std::tuple<int, int> resume_helper(lua_State * L, int narg) noexcept { PRIMER_ASSERT(lua_gettop(L) >= (narg), "Not enough arguments on stack for resume!"); const int result_index = lua_absindex(L, -1 - narg); const int result_code = lua_resume(L, nullptr, narg); if ((result_code != LUA_OK) && (result_code != LUA_YIELD)) { primer::get_error_handler(L); lua_insert(L, -2); lua_call(L, 1, 1); } return std::tuple<int, int>{result_code, result_index}; }
/* * Convert a value from the given index into the lua stack to an nvpair, adding * it to an nvlist with the given key. * * Values are converted as follows: * * string -> string * number -> int64 * boolean -> boolean * nil -> boolean (no value) * * Lua tables are converted to nvlists and then inserted. The table's keys * are converted to strings then used as keys in the nvlist to store each table * element. Keys are converted as follows: * * string -> no change * number -> "%lld" * boolean -> "true" | "false" * nil -> error * * In the case of a key collision, an error is thrown. * * If an error is encountered, a nonzero error code is returned, and an error * string will be pushed onto the Lua stack. */ static int zcp_lua_to_nvlist_impl(lua_State *state, int index, nvlist_t *nvl, const char *key, int depth) { /* * Verify that we have enough remaining space in the lua stack to parse * a key-value pair and push an error. */ if (!lua_checkstack(state, 3)) { (void) lua_pushstring(state, "Lua stack overflow"); return (1); } index = lua_absindex(state, index); switch (lua_type(state, index)) { case LUA_TNIL: fnvlist_add_boolean(nvl, key); break; case LUA_TBOOLEAN: fnvlist_add_boolean_value(nvl, key, lua_toboolean(state, index)); break; case LUA_TNUMBER: fnvlist_add_int64(nvl, key, lua_tonumber(state, index)); break; case LUA_TSTRING: fnvlist_add_string(nvl, key, lua_tostring(state, index)); break; case LUA_TTABLE: { nvlist_t *value_nvl = zcp_table_to_nvlist(state, index, depth); if (value_nvl == NULL) return (EINVAL); fnvlist_add_nvlist(nvl, key, value_nvl); fnvlist_free(value_nvl); break; } default: (void) lua_pushfstring(state, "Invalid value type '%s' for key '%s'", lua_typename(state, lua_type(state, index)), key); return (EINVAL); } return (0); }
Color4f Color4f::FromLuaTable(lua_State *l, int idx) { const int table = lua_absindex(l, idx); assert(lua_istable(l, table)); LUA_DEBUG_START(l); float r, g, b, a; _get_number(l, table, "r", r); _get_number(l, table, "g", g); _get_number(l, table, "b", b); _get_number(l, table, "a", a); LUA_DEBUG_END(l, 0); return Color4f(r, g, b, a); }
Color4ub Color4ub::FromLuaTable(lua_State *l, int idx) { const int table = lua_absindex(l, idx); assert(lua_istable(l, table)); LUA_DEBUG_START(l); float r, g, b, a; _get_number(l, table, "r", r); _get_number(l, table, "g", g); _get_number(l, table, "b", b); if (!_get_number(l, table, "a", a)) a = 1.0f; LUA_DEBUG_END(l, 0); return Color4ub(r*255, g*255, b*255, a*255); }
static void fetch_keys_from_metatable(lua_State * l, int metatable_index, const std::string & chunk, std::vector<std::string> & completion_list, bool only_functions) { metatable_index = lua_absindex(l, metatable_index); int original_height = lua_gettop(l); int recursion_count = 0; lua_pushvalue(l, metatable_index); while(true) { //First, determin whether where are stored the methods and attributes lua_pushstring(l, "__index"); lua_rawget(l, -2); // meta, meta.__index if (lua_istable(l, -1)) { fetch_keys_from_table(l, -1, chunk, completion_list, only_functions); if (lua_getmetatable(l, -1)) { // meta, meta.__index, meta^2 // Avoid the weird cases where the metatable contains itself. if (!lua_compare(l, -1, metatable_index, LUA_OPEQ) && recursion_count < COMPLETION_RECURSION_LIMIT) { recursion_count++; lua_replace(l, original_height+1); lua_pop(l, 1); continue; } else { lua_settop(l, original_height); throw RecursionLimit(); } } } else if (lua_iscfunction(l, -1)) { // Deal with the specifics of LuaObject stuff. lua_rawgeti(l, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); lua_pushstring(l, "type"); lua_rawget(l, original_height+1); // stuff, global, type lua_rawget(l, -2); // stuff, global, methods if (lua_istable(l, -1)) fetch_keys_from_table(l, -1, chunk, completion_list, only_functions); lua_pop(l, 1); // Kick out the methods. // Do the same for the parent lua_pushstring(l, "parent"); lua_rawget(l, original_height+1); if (!lua_isnil(l, -1)) { lua_rawget(l, LUA_REGISTRYINDEX); lua_replace(l, original_height+1); lua_pop(l, 2); continue; } } break; } lua_settop(l, original_height); }
static void fetch_keys_from_table(lua_State * l, int table_index, const std::string & chunk, std::vector<std::string> & completion_list, bool only_functions) { table_index = lua_absindex(l, table_index); lua_pushnil(l); while(lua_next(l, table_index)) { if (lua_type(l, -2) == LUA_TSTRING) { std::string candidate(lua_tostring(l, -2)); bool attr = false; if (candidate.substr(0, 12) == "__attribute_") { candidate = candidate.substr(12, std::string::npos); attr = true; } if (!only_functions || (lua_isfunction(l, -1) && !attr)) if (candidate.substr(0, chunk.size()) == chunk) completion_list.push_back(candidate.substr(chunk.size())); } lua_pop(l, 1); } }
static Json _lua_to_json(lua_State *l, int idx) { int data = lua_absindex(l, idx); switch (lua_type(l, data)) { case LUA_TNIL: return Json(); case LUA_TNUMBER: return Json(lua_tonumber(l, data)); case LUA_TBOOLEAN: return Json(lua_toboolean(l, data)); case LUA_TSTRING: return Json(lua_tostring(l, data)); case LUA_TTABLE: { // XXX handle arrays Json object(Json::objectValue); lua_pushnil(l); while (lua_next(l, data)) { const std::string key(luaL_checkstring(l, -2)); Json value(_lua_to_json(l, -1)); object[key] = value; lua_pop(l, 1); } return object; } default: luaL_error(l, "can't convert Lua type %s to JSON", lua_typename(l, lua_type(l, idx))); return Json(); } // shouldn't get here assert(0); return Json(); }