static int luaB_tostring (lua_State *L) { luaL_checkany(L, 1); if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ return 1; /* use its value */ switch (lua_type(L, 1)) { case LUA_TNUMBER: lua_pushstring(L, lua_tostring(L, 1)); break; case LUA_TSTRING: lua_pushvalue(L, 1); break; case LUA_TBOOLEAN: lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); break; case LUA_TNIL: lua_pushliteral(L, "nil"); break; default: lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); break; } return 1; }
void print_luatable(lua_State *L, int index, int layer) { int i; printf("%s(%p)\n", luaL_typename(L, index), lua_topointer(L, index)); for(i=0; i<layer-1; i++) printf(" "); printf("{\n"); lua_pushnil(L); while(lua_next(L, -2) != 0) { for(i=0; i<layer; i++) printf(" "); if(lua_isinteger(L, -2)) { printf("%d : ", (int)lua_tointeger(L, -2)); } else if(lua_isnumber(L, -2)) { printf("%f : ", lua_tonumber(L, -2)); } else if(lua_isstring(L, -2)) { printf("\"%s\" : ", lua_tostring(L, -2)); } print_luavar(L, -1, layer+1); printf("\n"); lua_pop(L, 1); } for(i=0; i<layer-1; i++) printf(" "); printf("}"); }
// - LuaVariable::pushLastTable --------------------------------------------- void LuaVariable::pushLastTable() { // Push the globals table onto the stack lua_pushstring (state_, "_G"); lua_gettable (state_, LUA_GLOBALSINDEX); // Reach the "final" table (and leave it at the stack top) typedef KeyList::const_iterator iter_t; assert (keys_.size() > 0 && "At least one key should be present here."); iter_t end = keys_.end(); --end; for (iter_t p = keys_.begin(); p != end; ++p) { PushLuaValue (state_, *p); lua_gettable (state_, -2); if (!lua_istable (state_, -1)) throw TypeMismatchError ("table", luaL_typename (state_, -1)); lua_remove (state_, -2); } }
/* * Call [method] on resource [r] and return resulting Lua table * as a json-c json_object. */ static json_object * rdl_resource_method_to_json (struct resource *r, const char *method) { json_object *o = NULL; lua_State *L = r->rdl->L; if (lua_rdl_resource_method_call (r, method)) { VERR (r->rdl->rl, "json: %s\n", lua_tostring (L, -1)); return (NULL); } if (lua_type (L, -1) != LUA_TTABLE) { VERR (r->rdl->rl, "json: Failed to get table. Got %s\n", luaL_typename (L, -1)); lua_pop (L, 1); return (NULL); } if (lua_value_to_json (L, -1, &o) < 0) o = NULL; /* Keep Lua stack clean */ lua_settop (L, 0); return (o); }
static int tostring(lua_State *L, int n) { luaL_checkany(L, n); switch (lua_type(L, n)) { case LUA_TNUMBER: lua_pushstring(L, lua_tostring(L, n)); break; case LUA_TSTRING: lua_pushvalue(L, n); break; case LUA_TBOOLEAN: lua_pushstring(L, (lua_toboolean(L, n) ? "true" : "false")); break; case LUA_TNIL: lua_pushliteral(L, "nil"); break; default: lua_pushfstring(L, "%s: %p", luaL_typename(L, n), lua_topointer(L, n)); break; } return 1; }
LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */ if (!lua_isstring(L, -1)) luaL_error(L, "'__tostring' must return a string"); } else { switch (lua_type(L, idx)) { case LUA_TNUMBER: { if (lua_isinteger(L, idx)) lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx)); else lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx)); break; } case LUA_TSTRING: lua_pushvalue(L, idx); break; case LUA_TBOOLEAN: lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); break; case LUA_TNIL: lua_pushliteral(L, "nil"); break; default: { int tt = luaL_getmetafield(L, idx, "__name"); /* try name */ const char *kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : luaL_typename(L, idx); lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx)); if (tt != LUA_TNIL) lua_remove(L, -2); /* remove '__name' */ break; } } } return lua_tolstring(L, -1, len); }
static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, const char *e) { lua_State *L = ms->L; switch (lua_type(L, 3)) { case LUA_TNUMBER: case LUA_TSTRING: { add_s(ms, b, s, e); return; } case LUA_TFUNCTION: case LUA_TUSERDATA: // User data items are also callable in some circumstances (i.e. LuaInterface static methods) { int n; lua_pushvalue(L, 3); n = push_captures(ms, s, e); lua_call(L, n, 1); break; } case LUA_TTABLE: { push_onecapture(ms, 0, s, e); lua_gettable(L, 3); break; } default: { luaL_argerror(L, 3, "string/function/table expected"); return; } } if (!lua_toboolean(L, -1)) { /* nil or false? */ lua_pop(L, 1); lua_pushlstring(L, s, e - s); /* keep original text */ } else if (!lua_isstring(L, -1)) luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); luaL_addvalue(b); /* add result to accumulator */ }
LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { if (!luaL_callmeta(L, idx, "__tostring")) /* no metafield? */ { switch (lua_type(L, idx)) { case LUA_TNUMBER: case LUA_TSTRING: lua_pushvalue(L, idx); break; case LUA_TBOOLEAN: lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); break; case LUA_TNIL: lua_pushliteral(L, "nil"); break; default: lua_pushfstring(L, "%s: %p", luaL_typename(L, idx), lua_topointer(L, idx)); break; } } return lua_tolstring(L, -1, len); }
static int lua_GetAccount(lua_State *L) { const char *name = NULL; switch (lua_type(L, 1)) { case LUA_TNUMBER: name = GetContactProto(lua_tonumber(L, 1)); break; case LUA_TSTRING: name = lua_tostring(L, 1); break; default: luaL_argerror(L, 1, luaL_typename(L, 1)); } PROTOACCOUNT *pa = Proto_GetAccount(name); if (pa) MT<PROTOACCOUNT>::Set(L, pa); else lua_pushnil(L); return 1; }
static FILE *check_file(lua_State *L, int idx, const char *argname) { #if LUA_VERSION_NUM <= 501 FILE **pf; if (idx > 0) pf = luaL_checkudata(L, idx, LUA_FILEHANDLE); else { idx = absindex(L, idx); pf = lua_touserdata(L, idx); luaL_getmetatable(L, LUA_FILEHANDLE); if (!pf || !lua_getmetatable(L, idx) || !lua_rawequal(L, -1, -2)) luaL_error(L, "bad %s option (%s expected, got %s)", argname, LUA_FILEHANDLE, luaL_typename(L, idx)); lua_pop(L, 2); } if (!*pf) return luaL_error(L, "attempt to use a closed file"), NULL; return *pf; #else luaL_Stream* p; idx = absindex(L, idx); p = (luaL_Stream *)luaL_checkudata(L, idx, LUA_FILEHANDLE); if (!p || !p->f) return luaL_error(L, "attempt to use a closed file"), NULL; return p->f; #endif }
Ihandle* iuplua_checkihandle_OLD(lua_State *L, int pos) { Ihandle* ih = NULL; if (lua_getmetatable(L, pos)) /* t2 = metatable(stack(pos)) */ { /* TODO: luaL_getmetatable(L, "iupHandle"); */ lua_pushstring(L, "iupHandle"); lua_gettable(L, LUA_REGISTRYINDEX); /* t = registry["iupHandle"] */ if (lua_rawequal(L, -2, -1)) /* check (t2==t)? */ ih = *(Ihandle**)lua_touserdata(L, pos); lua_pop(L, 2); /* Pop registry["iupHandle"] and the metatable */ } if (!ih) { const char *msg = lua_pushfstring(L, "iupHandle expected, got %s", luaL_typename(L, pos)); luaL_argerror(L, pos, msg); } return ih; }
bool Load_LuaTable(lua_State& io_luaState, const char* TableName #ifdef EAE2014_SHOULDALLRETURNVALUESBECHECKED , std::string* o_errorMessage #endif ) { assert(TableName); bool wereThereErrors = false; // Right now the asset table is at -1. // After the following table operation it will be at -2 // and the "textures" table will be at -1: lua_pushstring(&io_luaState, TableName); lua_gettable(&io_luaState, -2); if (!lua_istable(&io_luaState, -1)) { wereThereErrors = true; #ifdef EAE2014_SHOULDALLRETURNVALUESBECHECKED if (o_errorMessage) { std::stringstream errorMessage; errorMessage << "The value at \"" << TableName << "\" must be a table " "(instead of a " << luaL_typename(&io_luaState, -1) << ")\n"; *o_errorMessage = errorMessage.str(); } #endif goto OnExit; } OnExit: return !wereThereErrors; }
/* args-opts -- proc/nil error */ static int ex_spawn(lua_State *L) { struct spawn_params *params; int have_options; switch (lua_type(L, 1)) { default: return luaL_typerror(L, 1, "string or table"); case LUA_TSTRING: switch (lua_type(L, 2)) { default: return luaL_typerror(L, 2, "table"); case LUA_TNONE: have_options = 0; break; case LUA_TTABLE: have_options = 1; break; } break; case LUA_TTABLE: have_options = 1; lua_getfield(L, 1, "command"); /* opts ... cmd */ if (!lua_isnil(L, -1)) { /* convert {command=command,arg1,...} to command {arg1,...} */ lua_insert(L, 1); /* cmd opts ... */ } else { /* convert {arg0,arg1,...} to arg0 {arg1,...} */ size_t i, n = lua_objlen(L, 1); lua_rawgeti(L, 1, 1); /* opts ... nil cmd */ lua_insert(L, 1); /* cmd opts ... nil */ for (i = 2; i <= n; i++) { lua_rawgeti(L, 2, i); /* cmd opts ... nil argi */ lua_rawseti(L, 2, i - 1); /* cmd opts ... nil */ } lua_rawseti(L, 2, n); /* cmd opts ... */ } if (lua_type(L, 1) != LUA_TSTRING) return luaL_error(L, "bad command option (string expected, got %s)", luaL_typename(L, 1)); break; } params = spawn_param_init(L); /* get filename to execute */ spawn_param_filename(params, lua_tostring(L, 1)); /* get arguments, environment, and redirections */ if (have_options) { lua_getfield(L, 2, "args"); /* cmd opts ... argtab */ switch (lua_type(L, -1)) { default: return luaL_error(L, "bad args option (table expected, got %s)", luaL_typename(L, -1)); case LUA_TNIL: lua_pop(L, 1); /* cmd opts ... */ lua_pushvalue(L, 2); /* cmd opts ... opts */ if (0) /*FALLTHRU*/ case LUA_TTABLE: if (lua_objlen(L, 2) > 0) return luaL_error(L, "cannot specify both the args option and array values"); spawn_param_args(params); /* cmd opts ... */ break; } lua_getfield(L, 2, "env"); /* cmd opts ... envtab */ switch (lua_type(L, -1)) { default: return luaL_error(L, "bad env option (table expected, got %s)", luaL_typename(L, -1)); case LUA_TNIL: break; case LUA_TTABLE: spawn_param_env(params); /* cmd opts ... */ break; } lua_getfield(L, 2, "show"); /* cmd opts ... envtab */ spawn_param_show(params, lua_type(L, -1) == LUA_TBOOLEAN ? lua_toboolean(L, -1) : 0); lua_getfield(L, 2, "shell"); /* cmd opts ... envtab */ spawn_param_useshell(params, lua_type(L, -1) == LUA_TBOOLEAN ? lua_toboolean(L, -1) : 1); get_redirect(L, 2, "stdin", params); /* cmd opts ... */ get_redirect(L, 2, "stdout", params); /* cmd opts ... */ get_redirect(L, 2, "stderr", params); /* cmd opts ... */ } return spawn_param_execute(params); /* proc/nil error */ }
size_t ngx_stream_lua_calc_strlen_in_table(lua_State *L, int index, int arg_i, unsigned strict) { double key; int max; int i; int type; size_t size; size_t len; const char *msg; if (index < 0) { index = lua_gettop(L) + index + 1; } dd("table index: %d", index); max = 0; lua_pushnil(L); /* stack: table key */ while (lua_next(L, index) != 0) { /* stack: table key value */ dd("key type: %s", luaL_typename(L, -2)); if (lua_type(L, -2) == LUA_TNUMBER) { key = lua_tonumber(L, -2); dd("key value: %d", (int) key); if (floor(key) == key && key >= 1) { if (key > max) { max = (int) key; } lua_pop(L, 1); /* stack: table key */ continue; } } /* not an array (non positive integer key) */ lua_pop(L, 2); /* stack: table */ luaL_argerror(L, arg_i, "non-array table found"); return 0; } size = 0; for (i = 1; i <= max; i++) { lua_rawgeti(L, index, i); /* stack: table value */ type = lua_type(L, -1); switch (type) { case LUA_TNUMBER: case LUA_TSTRING: lua_tolstring(L, -1, &len); size += len; break; case LUA_TNIL: if (strict) { goto bad_type; } size += sizeof("nil") - 1; break; case LUA_TBOOLEAN: if (strict) { goto bad_type; } if (lua_toboolean(L, -1)) { size += sizeof("true") - 1; } else { size += sizeof("false") - 1; } break; case LUA_TTABLE: size += ngx_stream_lua_calc_strlen_in_table(L, -1, arg_i, strict); break; case LUA_TLIGHTUSERDATA: if (strict) { goto bad_type; } if (lua_touserdata(L, -1) == NULL) { size += sizeof("null") - 1; break; } continue; default: bad_type: msg = lua_pushfstring(L, "bad data type %s found", lua_typename(L, type)); return luaL_argerror(L, arg_i, msg); } lua_pop(L, 1); /* stack: table */ } return size; }
static int lib_cvRegisterVar(lua_State *L) { const char *k; lua_Integer i; consvar_t *cvar; luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one. NOHUD cvar = lua_newuserdata(L, sizeof(consvar_t)); luaL_getmetatable(L, META_CVAR); lua_setmetatable(L, -2); #define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("CV_RegisterVar") " (%s)", e); #define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1))) lua_pushnil(L); while (lua_next(L, 1)) { // stack: cvar table, cvar userdata, key/index, value // 1 2 3 4 i = 0; k = NULL; if (lua_isnumber(L, 3)) i = lua_tointeger(L, 3); else if (lua_isstring(L, 3)) k = lua_tostring(L, 3); if (i == 1 || (k && fasticmp(k, "name"))) { if (!lua_isstring(L, 4)) TYPEERROR("name", LUA_TSTRING) cvar->name = Z_StrDup(lua_tostring(L, 4)); } else if (i == 2 || (k && fasticmp(k, "defaultvalue"))) { if (!lua_isstring(L, 4)) TYPEERROR("defaultvalue", LUA_TSTRING) cvar->defaultvalue = Z_StrDup(lua_tostring(L, 4)); } else if (i == 3 || (k && fasticmp(k, "flags"))) { if (!lua_isnumber(L, 4)) TYPEERROR("flags", LUA_TNUMBER) cvar->flags = (INT32)lua_tointeger(L, 4); } else if (i == 4 || (k && fasticmp(k, "PossibleValue"))) { if (lua_islightuserdata(L, 4)) { CV_PossibleValue_t *pv = lua_touserdata(L, 4); if (pv == CV_OnOff || pv == CV_YesNo || pv == CV_Unsigned || pv == CV_Natural) cvar->PossibleValue = pv; else FIELDERROR("PossibleValue", "CV_PossibleValue_t expected, got unrecognised pointer") } else if (lua_istable(L, 4)) { // Accepts tables in the form of {MIN=0, MAX=9999} or {Red=0, Green=1, Blue=2} // and converts them to CV_PossibleValue_t {{0,"MIN"},{9999,"MAX"}} or {{0,"Red"},{1,"Green"},{2,"Blue"}} // // I don't really like the way this does it because a single PossibleValue table // being used for multiple cvars will be converted and stored multiple times. // So maybe instead it should be a seperate function which must be run beforehand or something. size_t count = 0; CV_PossibleValue_t *cvpv; lua_pushnil(L); while (lua_next(L, 4)) { count++; lua_pop(L, 1); } lua_getfield(L, LUA_REGISTRYINDEX, "CV_PossibleValue"); I_Assert(lua_istable(L, 5)); lua_pushvalue(L, 2); // cvar userdata cvpv = lua_newuserdata(L, sizeof(CV_PossibleValue_t) * (count+1)); lua_rawset(L, 5); lua_pop(L, 1); // pop CV_PossibleValue registry table i = 0; lua_pushnil(L); while (lua_next(L, 4)) { // stack: [...] PossibleValue table, index, value // 4 5 6 if (lua_type(L, 5) != LUA_TSTRING || lua_type(L, 6) != LUA_TNUMBER) FIELDERROR("PossibleValue", "custom PossibleValue table requires a format of string=integer, i.e. {MIN=0, MAX=9999}"); cvpv[i].strvalue = Z_StrDup(lua_tostring(L, 5)); cvpv[i].value = (INT32)lua_tonumber(L, 6); i++; lua_pop(L, 1); } cvpv[i].value = 0; cvpv[i].strvalue = NULL; cvar->PossibleValue = cvpv; } else FIELDERROR("PossibleValue", va("%s or CV_PossibleValue_t expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1))) } else if (cvar->flags & CV_CALL && (i == 5 || (k && fasticmp(k, "func")))) {
bool LuaState::CheckBoolean(int index) const { if (lua_isnoneornil(m_state, index)) { const char* msg = lua_pushfstring(m_state, "%s expected, got %s", lua_typename(m_state, LUA_TBOOLEAN), luaL_typename(m_state, index)); luaL_argerror(m_state, index, msg); // Lance une exception return false; } return lua_toboolean(m_state, index) != 0; }
bool eae6320::cEffectBuilder::Build(const std::vector<std::string>&) { bool wereThereErrors = false; // Create a new Lua state lua_State* luaState = NULL; { luaState = luaL_newstate(); if (!luaState) { wereThereErrors = true; eae6320::OutputErrorMessage("Failed to create a new Lua state", __FILE__); goto OnExit; } } // Load the asset file as a "chunk", // meaning there will be a callable function at the top of the stack { const int luaResult = luaL_loadfile(luaState, m_path_source); if (luaResult != LUA_OK) { wereThereErrors = true; eae6320::OutputErrorMessage(lua_tostring(luaState, -1), __FILE__); // Pop the error message lua_pop(luaState, 1); goto OnExit; } } // Execute the "chunk", which should load the asset // into a table at the top of the stack { const int argumentCount = 0; const int returnValueCount = LUA_MULTRET; // Return _everything_ that the file returns const int noMessageHandler = 0; const int luaResult = lua_pcall(luaState, argumentCount, returnValueCount, noMessageHandler); if (luaResult == LUA_OK) { // A well-behaved asset file will only return a single value const int returnedValueCount = lua_gettop(luaState); if (returnedValueCount == 1) { // A correct asset file _must_ return a table if (!lua_istable(luaState, -1)) { wereThereErrors = true; std::stringstream errorMessage; errorMessage << "Asset files must return a table (instead of a " << luaL_typename(luaState, -1) << ")\n"; eae6320::OutputErrorMessage(errorMessage.str().c_str(),__FILE__); // Pop the returned non-table value lua_pop(luaState, 1); goto OnExit; } } else { wereThereErrors = true; std::stringstream errorMessage; errorMessage << "Asset files must return a single table (instead of " << returnedValueCount << " values)" "\n"; eae6320::OutputErrorMessage(errorMessage.str().c_str(),__FILE__); // Pop every value that was returned lua_pop(luaState, returnedValueCount); goto OnExit; } } else { wereThereErrors = true; std::stringstream errorMessage; errorMessage << lua_tostring(luaState, -1); eae6320::OutputErrorMessage(errorMessage.str().c_str(),__FILE__); // Pop the error message lua_pop(luaState, 1); goto OnExit; } } // If this code is reached the asset file was loaded successfully, // and its table is now at index -1 /*if (!ProcessEffectData(*luaState)) { wereThereErrors = true; }*/ FILE * oFile; fopen_s(&oFile, m_path_target, "wb"); if (oFile != NULL) { lua_pushstring(luaState, "vertex"); lua_gettable(luaState, -2); const char * vertexShader = lua_tostring(luaState, -1); fwrite(vertexShader, strlen(vertexShader) + 1, 1, oFile); lua_pop(luaState, 1); lua_pushstring(luaState, "fragment"); lua_gettable(luaState, -2); const char * fragmentShader = lua_tostring(luaState, -1); fwrite(fragmentShader, strlen(fragmentShader) + 1, 1, oFile); lua_pop(luaState, 1); //MessageBox(NULL, "", NULL, MB_OK); uint8_t renderStates = 0; //int test; lua_pushstring(luaState, "alphaTransparency"); lua_gettable(luaState, -2); if(lua_toboolean(luaState, -1)) renderStates |= RenderStates::ALPHA_TRANSPARENCY; lua_pop(luaState, 1); lua_pushstring(luaState, "depthTesting"); lua_gettable(luaState, -2); if (lua_toboolean(luaState, -1)) renderStates |= RenderStates::DEPTH_TESTING; lua_pop(luaState, 1); lua_pushstring(luaState, "depthWriting"); lua_gettable(luaState, -2); if (lua_toboolean(luaState, -1)) renderStates |= RenderStates::DEPTH_WRITING; lua_pop(luaState, 1); lua_pushstring(luaState, "faceCulling"); lua_gettable(luaState, -2); if (lua_toboolean(luaState, -1)) renderStates |= RenderStates::FACE_CULLING; lua_pop(luaState, 1); fwrite(&renderStates, sizeof(renderStates), 1, oFile); fclose(oFile); } // Pop the table lua_pop(luaState, 1); OnExit: if (luaState) { // If I haven't made any mistakes // there shouldn't be anything on the stack, // regardless of any errors encountered while loading the file: assert(lua_gettop(luaState) == 0); lua_close(luaState); luaState = NULL; } return !wereThereErrors; }
static int l_siplua_moduleFunc(lua_State *L) { struct sipapi_object *o; const char *func; int n, nargs; cmd_export_t *exp_func_struct; action_elem_t elems[MAX_ACTION_ELEMS]; const char *s, *msg; char *str; int i; struct action *act; int retval; o = luaL_checkudata(L, 1, "siplua.api"); func = luaL_checkstring(L, 2); n = lua_gettop(L); nargs = n - 2; if (n - 1 > MAX_ACTION_ELEMS) return luaL_error(L, "function '%s' called with too many arguments [%d > %d]", func, nargs, MAX_ACTION_ELEMS - 1); exp_func_struct = find_cmd_export_t((char *)func, nargs, 0); if (!exp_func_struct) { return luaL_error(L, "function '%s' called, but not available."); } elems[0].type = CMD_ST; elems[0].u.data = exp_func_struct; memset(&elems[1], '\0', nargs * sizeof(action_elem_t)); for (i = 0; i < nargs; ++i) { s = lua_tostring(L, 3 + i); if (!s) { siplua_moduleFunc_free(func, exp_func_struct, elems, nargs); msg = lua_pushfstring(L, "%s expected, got %s", lua_typename(L, LUA_TSTRING), luaL_typename(L, 3 + i)); return luaL_argerror(L, 3 + i, msg); } str = pkg_malloc(strlen(s) + 1); if (!str) { siplua_moduleFunc_free(func, exp_func_struct, elems, nargs); return luaL_error(L, "Not enough memory"); } strcpy(str, s); /* We should maybe try STR_ST and elems[].u.str.{s,len} */ elems[i + 1].type = STRING_ST; elems[i + 1].u.data = str; /* elems[].u.string */ } act = mk_action(MODULE_T, n - 2 + 1, elems, 0, "lua"); if (!act) { siplua_moduleFunc_free(func, exp_func_struct, elems, nargs); return luaL_error(L, "action structure could not be created. Error."); } /* siplua_log(L_DBG, "fixup/%p free_fixup/%p", */ /* exp_func_struct->fixup, */ /* exp_func_struct->free_fixup); */ if (exp_func_struct->fixup) { if (!siplua_unsafemodfnc && !exp_func_struct->free_fixup) { siplua_moduleFunc_free(func, exp_func_struct, act->elem, nargs); return luaL_error(L, "Module function '%s' is unsafe. Call is refused.\n", func); } if (nargs == 0) { retval = exp_func_struct->fixup(0, 0); if (retval < 0) { siplua_moduleFunc_free(func, exp_func_struct, act->elem, nargs); return luaL_error(L, "Error in fixup (0)\n"); } } for (i = 0; i < nargs; ++i) { retval = exp_func_struct->fixup(&act->elem[i + 1].u.data, i + 1); if (retval < 0) { siplua_moduleFunc_free(func, exp_func_struct, act->elem, nargs); return luaL_error(L, "Error in fixup (%d)\n", i + 1); } act->elem[i + 1].type = MODFIXUP_ST; } } retval = do_action(act, o->msg); siplua_moduleFunc_free(func, exp_func_struct, act->elem, nargs); pkg_free(act); lua_pushinteger(L, retval); return 1; }
static void _unpack_hyperspace_args(lua_State *l, int index, SystemPath* &path, double &due) { if (lua_isnone(l, index)) return; luaL_checktype(l, index, LUA_TTABLE); LUA_DEBUG_START(l); lua_pushinteger(l, 1); lua_gettable(l, index); if (!(path = LuaSystemPath::GetFromLua(-1))) luaL_error(l, "bad value for hyperspace path at position 1 (SystemPath expected, got %s)", luaL_typename(l, -1)); lua_pop(l, 1); lua_pushinteger(l, 2); lua_gettable(l, index); if (!(lua_isnumber(l, -1))) luaL_error(l, "bad value for hyperspace exit time at position 2 (%s expected, got %s)", lua_typename(l, LUA_TNUMBER), luaL_typename(l, -1)); due = lua_tonumber(l, -1); if (due < 0) luaL_error(l, "bad value for hyperspace exit time at position 2 (must be >= 0)"); lua_pop(l, 1); LUA_DEBUG_END(l, 0); }
static int ngx_http_lua_ngx_location_capture_multi(lua_State *L) { ngx_http_request_t *r; ngx_http_request_t *sr; /* subrequest object */ ngx_http_post_subrequest_t *psr; ngx_http_lua_ctx_t *sr_ctx; ngx_http_lua_ctx_t *ctx; ngx_array_t *extra_vars; ngx_str_t uri; ngx_str_t args; ngx_str_t extra_args; ngx_uint_t flags; u_char *p; u_char *q; size_t len; size_t nargs; int rc; int n; ngx_uint_t method; ngx_http_request_body_t *body; int type; ngx_buf_t *b; unsigned vars_action; ngx_uint_t nsubreqs; ngx_uint_t index; size_t sr_statuses_len; size_t sr_headers_len; size_t sr_bodies_len; size_t sr_flags_len; unsigned custom_ctx; ngx_http_lua_co_ctx_t *coctx; ngx_http_lua_post_subrequest_data_t *psr_data; n = lua_gettop(L); if (n != 1) { return luaL_error(L, "only one argument is expected, but got %d", n); } luaL_checktype(L, 1, LUA_TTABLE); nsubreqs = lua_objlen(L, 1); if (nsubreqs == 0) { return luaL_error(L, "at least one subrequest should be specified"); } r = ngx_http_lua_get_req(L); if (r == NULL) { return luaL_error(L, "no request object found"); } ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { return luaL_error(L, "no ctx found"); } ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT); coctx = ctx->cur_co_ctx; if (coctx == NULL) { return luaL_error(L, "no co ctx found"); } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua location capture, uri:\"%V\" c:%ud", &r->uri, r->main->count); sr_statuses_len = nsubreqs * sizeof(ngx_int_t); sr_headers_len = nsubreqs * sizeof(ngx_http_headers_out_t *); sr_bodies_len = nsubreqs * sizeof(ngx_str_t); sr_flags_len = nsubreqs * sizeof(uint8_t); p = ngx_pcalloc(r->pool, sr_statuses_len + sr_headers_len + sr_bodies_len + sr_flags_len); if (p == NULL) { return luaL_error(L, "out of memory"); } coctx->sr_statuses = (void *) p; p += sr_statuses_len; coctx->sr_headers = (void *) p; p += sr_headers_len; coctx->sr_bodies = (void *) p; p += sr_bodies_len; coctx->sr_flags = (void *) p; coctx->nsubreqs = nsubreqs; coctx->pending_subreqs = 0; extra_vars = NULL; for (index = 0; index < nsubreqs; index++) { coctx->pending_subreqs++; lua_rawgeti(L, 1, index + 1); if (lua_isnil(L, -1)) { return luaL_error(L, "only array-like tables are allowed"); } dd("queries query: top %d", lua_gettop(L)); if (lua_type(L, -1) != LUA_TTABLE) { return luaL_error(L, "the query argument %d is not a table, " "but a %s", index, lua_typename(L, lua_type(L, -1))); } nargs = lua_objlen(L, -1); if (nargs != 1 && nargs != 2) { return luaL_error(L, "query argument %d expecting one or " "two arguments", index); } lua_rawgeti(L, 2, 1); /* queries query uri */ dd("queries query uri: %d", lua_gettop(L)); dd("first arg in first query: %s", lua_typename(L, lua_type(L, -1))); body = NULL; extra_args.data = NULL; extra_args.len = 0; if (extra_vars != NULL) { /* flush out existing elements in the array */ extra_vars->nelts = 0; } vars_action = 0; custom_ctx = 0; if (nargs == 2) { /* check out the options table */ lua_rawgeti(L, 2, 2); /* queries query uri opts */ dd("queries query uri opts: %d", lua_gettop(L)); if (lua_type(L, 4) != LUA_TTABLE) { return luaL_error(L, "expecting table as the 2nd argument for " "subrequest %d, but got %s", index, luaL_typename(L, 4)); } dd("queries query uri opts: %d", lua_gettop(L)); /* check the args option */ lua_getfield(L, 4, "args"); type = lua_type(L, -1); switch (type) { case LUA_TTABLE: ngx_http_lua_process_args_option(r, L, -1, &extra_args); break; case LUA_TNIL: /* do nothing */ break; case LUA_TNUMBER: case LUA_TSTRING: extra_args.data = (u_char *) lua_tolstring(L, -1, &len); extra_args.len = len; break; default: return luaL_error(L, "Bad args option value"); } lua_pop(L, 1); dd("queries query uri opts: %d", lua_gettop(L)); /* check the vars option */ lua_getfield(L, 4, "vars"); switch (lua_type(L, -1)) { case LUA_TTABLE: ngx_http_lua_process_vars_option(r, L, -1, &extra_vars); dd("post process vars top: %d", lua_gettop(L)); break; case LUA_TNIL: /* do nothing */ break; default: return luaL_error(L, "Bad vars option value"); } lua_pop(L, 1); dd("queries query uri opts: %d", lua_gettop(L)); /* check the share_all_vars option */ lua_getfield(L, 4, "share_all_vars"); switch (lua_type(L, -1)) { case LUA_TNIL: /* do nothing */ break; case LUA_TBOOLEAN: if (lua_toboolean(L, -1)) { vars_action |= NGX_HTTP_LUA_SHARE_ALL_VARS; } break; default: return luaL_error(L, "Bad share_all_vars option value"); } lua_pop(L, 1); dd("queries query uri opts: %d", lua_gettop(L)); /* check the copy_all_vars option */ lua_getfield(L, 4, "copy_all_vars"); switch (lua_type(L, -1)) { case LUA_TNIL: /* do nothing */ break; case LUA_TBOOLEAN: if (lua_toboolean(L, -1)) { vars_action |= NGX_HTTP_LUA_COPY_ALL_VARS; } break; default: return luaL_error(L, "Bad copy_all_vars option value"); } lua_pop(L, 1); dd("queries query uri opts: %d", lua_gettop(L)); /* check the "method" option */ lua_getfield(L, 4, "method"); type = lua_type(L, -1); if (type == LUA_TNIL) { method = NGX_HTTP_GET; } else { if (type != LUA_TNUMBER) { return luaL_error(L, "Bad http request method"); } method = (ngx_uint_t) lua_tonumber(L, -1); } lua_pop(L, 1); dd("queries query uri opts: %d", lua_gettop(L)); /* check the "ctx" option */ lua_getfield(L, 4, "ctx"); type = lua_type(L, -1); if (type != LUA_TNIL) { if (type != LUA_TTABLE) { return luaL_error(L, "Bad ctx option value type %s, " "expected a Lua table", lua_typename(L, type)); } custom_ctx = 1; } else { lua_pop(L, 1); } dd("queries query uri opts ctx?: %d", lua_gettop(L)); /* check the "body" option */ lua_getfield(L, 4, "body"); type = lua_type(L, -1); if (type != LUA_TNIL) { if (type != LUA_TSTRING && type != LUA_TNUMBER) { return luaL_error(L, "Bad http request body"); } body = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); if (body == NULL) { return luaL_error(L, "out of memory"); } q = (u_char *) lua_tolstring(L, -1, &len); dd("request body: [%.*s]", (int) len, q); if (len) { b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return luaL_error(L, "out of memory"); } b->last = ngx_copy(b->last, q, len); body->bufs = ngx_alloc_chain_link(r->pool); if (body->bufs == NULL) { return luaL_error(L, "out of memory"); } body->bufs->buf = b; body->bufs->next = NULL; body->buf = b; } } lua_pop(L, 1); /* pop the body */ /* stack: queries query uri opts ctx? */ lua_remove(L, 4); /* stack: queries query uri ctx? */ dd("queries query uri ctx?: %d", lua_gettop(L)); } else { method = NGX_HTTP_GET; } /* stack: queries query uri ctx? */ p = (u_char *) luaL_checklstring(L, 3, &len); uri.data = ngx_palloc(r->pool, len); if (uri.data == NULL) { return luaL_error(L, "memory allocation error"); } ngx_memcpy(uri.data, p, len); uri.len = len; args.data = NULL; args.len = 0; flags = 0; rc = ngx_http_parse_unsafe_uri(r, &uri, &args, &flags); if (rc != NGX_OK) { dd("rc = %d", (int) rc); return luaL_error(L, "unsafe uri in argument #1: %s", p); } if (args.len == 0) { if (extra_args.len) { p = ngx_palloc(r->pool, extra_args.len); if (p == NULL) { return luaL_error(L, "out of memory"); } ngx_memcpy(p, extra_args.data, extra_args.len); args.data = p; args.len = extra_args.len; } } else if (extra_args.len) { /* concatenate the two parts of args together */ len = args.len + (sizeof("&") - 1) + extra_args.len; p = ngx_palloc(r->pool, len); if (p == NULL) { return luaL_error(L, "out of memory"); } q = ngx_copy(p, args.data, args.len); *q++ = '&'; ngx_memcpy(q, extra_args.data, extra_args.len); args.data = p; args.len = len; } p = ngx_pnalloc(r->pool, sizeof(ngx_http_post_subrequest_t) + sizeof(ngx_http_lua_ctx_t) + sizeof(ngx_http_lua_post_subrequest_data_t)); if (p == NULL) { return luaL_error(L, "out of memory"); } psr = (ngx_http_post_subrequest_t *) p; p += sizeof(ngx_http_post_subrequest_t); sr_ctx = (ngx_http_lua_ctx_t *) p; p += sizeof(ngx_http_lua_ctx_t); psr_data = (ngx_http_lua_post_subrequest_data_t *) p; ngx_memzero(sr_ctx, sizeof(ngx_http_lua_ctx_t)); /* set by ngx_memzero: * sr_ctx->run_post_subrequest = 0 * sr_ctx->free = NULL * sr_ctx->body = NULL */ ngx_http_lua_init_ctx(sr_ctx); sr_ctx->capture = 1; sr_ctx->index = index; sr_ctx->last_body = &sr_ctx->body; psr_data->ctx = sr_ctx; psr_data->pr_co_ctx = coctx; psr->handler = ngx_http_lua_post_subrequest; psr->data = psr_data; rc = ngx_http_lua_subrequest(r, &uri, &args, &sr, psr, 0); if (rc != NGX_OK) { return luaL_error(L, "failed to issue subrequest: %d", (int) rc); } ngx_http_set_ctx(sr, sr_ctx, ngx_http_lua_module); rc = ngx_http_lua_adjust_subrequest(sr, method, body, vars_action, extra_vars); if (rc != NGX_OK) { ngx_http_lua_cancel_subreq(sr); return luaL_error(L, "failed to adjust the subrequest: %d", (int) rc); } dd("queries query uri opts ctx? %d", lua_gettop(L)); /* stack: queries query uri ctx? */ if (custom_ctx) { ngx_http_lua_ngx_set_ctx_helper(L, sr, sr_ctx, -1); lua_pop(L, 3); } else { lua_pop(L, 2); } /* stack: queries */ } if (extra_vars) { ngx_array_destroy(extra_vars); } ctx->no_abort = 1; return lua_yield(L, 0); }
int writeObjectRaw() { lua_State *L = m_L; uint8_t iType; // Save the index to the cache lua_pushvalue(L, 2); lua_pushnumber(L, (lua_Number)(m_iNextIndex++)); lua_settable(L, 1); // Lookup the object in the permanents table lua_pushvalue(L, 2); lua_gettable(L, luaT_upvalueindex(1)); if(lua_type(L, -1) != LUA_TNIL) { // Object is in the permanents table. uint8_t iType = PERSIST_TPERMANENT; writeByteStream(&iType, 1); // Replace self's environment with self (for call to writeStackObject) lua_pushvalue(L, luaT_upvalueindex(2)); lua_replace(L, 1); // Write the key corresponding to the permanent object writeStackObject(-1); } else { // Object is not in the permanents table. lua_pop(L, 1); switch(lua_type(L, 2)) { // LUA_TNIL handled in writeStackObject // LUA_TBOOLEAN handled in writeStackObject // LUA_TNUMBER handled in writeStackObject case LUA_TSTRING: { iType = LUA_TSTRING; writeByteStream(&iType, 1); // Strings are simple: length and then bytes (not null terminated) size_t iLength; const char *sString = lua_tolstring(L, 2, &iLength); writeVUInt(iLength); writeByteStream(reinterpret_cast<const uint8_t*>(sString), iLength); break; } case LUA_TTABLE: { // Replace self's environment with self (for calls to writeStackObject) lua_pushvalue(L, luaT_upvalueindex(2)); lua_replace(L, 1); // Save env and insert prior to table lua_getfenv(L, 1); lua_insert(L, 2); int iTable = 3; table_reentry: // Handle the metatable if(lua_getmetatable(L, iTable)) { iType = PERSIST_TTABLE_WITH_META; writeByteStream(&iType, 1); writeStackObject(-1); lua_pop(L, 1); } else { iType = LUA_TTABLE; writeByteStream(&iType, 1); } // Write the children as key, value pairs lua_pushnil(L); while(lua_next(L, iTable)) { writeStackObject(-2); // The naive thing to do now would be writeStackObject(-1) // but this can easily lead to Lua's C call stack limit // being hit. To reduce the likelyhood of this happening, // we check to see if about to write another table. if(lua_type(L, -1) == LUA_TTABLE) { lua_pushvalue(L, -1); lua_rawget(L, 2); lua_pushvalue(L, -2); lua_gettable(L, luaT_upvalueindex(1)); if(lua_isnil(L, -1) && lua_isnil(L, -2)) { lua_pop(L, 2); lua_checkstack(L, 10); iTable += 2; lua_pushvalue(L, iTable); lua_pushnumber(L, (lua_Number)(m_iNextIndex++)); lua_settable(L, 2); goto table_reentry; table_resume: iTable -= 2; } else { lua_pop(L, 2); writeStackObject(-1); } } else writeStackObject(-1); lua_pop(L, 1); } // Write a nil to mark the end of the children (as nil is the // only value which cannot be used as a key in a table). iType = LUA_TNIL; writeByteStream(&iType, 1); if(iTable != 3) goto table_resume; break; } case LUA_TFUNCTION: if(lua_iscfunction(L, 2)) { setErrorObject(2); setError("Cannot persist C functions"); } else { iType = LUA_TFUNCTION; writeByteStream(&iType, 1); // Replace self's environment with self (for calls to writeStackObject) lua_pushvalue(L, luaT_upvalueindex(2)); lua_replace(L, 1); // Write the prototype (the part of a function which is common across // multiple closures - see LClosure / Proto in Lua's lobject.h). lua_Debug proto_info; lua_pushvalue(L, 2); lua_getinfo(L, ">Su", &proto_info); writePrototype(&proto_info, 2); // Write the values of the upvalues // If available, also write the upvalue IDs (so that in // the future, we could hypothetically rejoin shared // upvalues). An ID is just an opaque sequence of bytes. writeVUInt(proto_info.nups); #if LUA_VERSION_NUM >= 502 writeVUInt(sizeof(void*)); #else writeVUInt(0); #endif for(int i = 1; i <= proto_info.nups; ++i) { lua_getupvalue(L, 2, i); writeStackObject(-1); #if LUA_VERSION_NUM >= 502 void *pUpvalueID = lua_upvalueid(L, 2, i); writeByteStream((uint8_t*)&pUpvalueID, sizeof(void*)); #endif } // Write the environment table lua_getfenv(L, 2); writeStackObject(-1); lua_pop(L, 1); } break; case LUA_TUSERDATA: if(!_checkThatUserdataCanBeDepersisted(2)) break; // Replace self's environment with self (for calls to writeStackObject) lua_pushvalue(L, luaT_upvalueindex(2)); lua_replace(L, 1); // Write type, metatable, and then environment iType = LUA_TUSERDATA; writeByteStream(&iType, 1); writeStackObject(-1); lua_getfenv(L, 2); writeStackObject(-1); lua_pop(L, 1); // Write the raw data if(lua_type(L, -1) == LUA_TTABLE) { lua_getfield(L, -1, "__persist"); if(lua_isnil(L, -1)) lua_pop(L, 1); else { lua_pushvalue(L, 2); lua_pushvalue(L, luaT_upvalueindex(2)); lua_call(L, 2, 0); } } writeVUInt((uint64_t)0x42); // sync marker break; default: setError(lua_pushfstring(L, "Cannot persist %s values", luaL_typename(L, 2))); break; } } lua_pushnumber(L, 0); return 1; }
int typeerror (LuaThread *L, int narg, const char* type1) { THREAD_CHECK(L); const char* type2 = luaL_typename(L, narg); const char *msg = lua_pushfstring(L, "%s expected, got %s", type1, type2); return luaL_argerror(L, narg, msg); }
T* luaW_check(lua_State* L, int index, bool strict = false) { T* obj = NULL; if (luaW_is<T>(L, index, strict)) { luaW_Userdata* pud = (luaW_Userdata*)lua_touserdata(L, index); luaW_Userdata ud; while (!strict && LuaWrapper<T>::cast != pud->cast) { ud = pud->cast(*pud); pud = &ud; } obj = (T*)pud->data; } else { const char *msg = lua_pushfstring(L, "%s expected, got %s", LuaWrapper<T>::classname, luaL_typename(L, index)); luaL_argerror(L, index, msg); } return obj; }
static int ngx_http_lua_ngx_exec(lua_State *L) { int n; ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; ngx_str_t uri; ngx_str_t args, user_args; ngx_uint_t flags; u_char *p; u_char *q; size_t len; const char *msg; n = lua_gettop(L); if (n != 1 && n != 2) { return luaL_error(L, "expecting one or two arguments, but got %d", n); } lua_pushlightuserdata(L, &ngx_http_lua_request_key); lua_rawget(L, LUA_GLOBALSINDEX); r = lua_touserdata(L, -1); lua_pop(L, 1); if (r == NULL) { return luaL_error(L, "no request object found"); } args.data = NULL; args.len = 0; /* read the 1st argument (uri) */ p = (u_char *) luaL_checklstring(L, 1, &len); if (len == 0) { return luaL_error(L, "The uri argument is empty"); } uri.data = ngx_palloc(r->pool, len); if (uri.data == NULL) { return luaL_error(L, "out of memory"); } ngx_memcpy(uri.data, p, len); uri.len = len; ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { return luaL_error(L, "no ctx found"); } ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT); ngx_http_lua_check_if_abortable(L, ctx); if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags) != NGX_OK) { ctx->headers_sent = 1; return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (n == 2) { /* read the 2nd argument (args) */ dd("args type: %s", luaL_typename(L, 2)); switch (lua_type(L, 2)) { case LUA_TNUMBER: case LUA_TSTRING: p = (u_char *) lua_tolstring(L, 2, &len); user_args.data = ngx_palloc(r->pool, len); if (user_args.data == NULL) { return luaL_error(L, "out of memory"); } ngx_memcpy(user_args.data, p, len); user_args.len = len; break; case LUA_TTABLE: ngx_http_lua_process_args_option(r, L, 2, &user_args); dd("user_args: %.*s", (int) user_args.len, user_args.data); break; case LUA_TNIL: user_args.data = NULL; user_args.len = 0; break; default: msg = lua_pushfstring(L, "string, number, or table expected, " "but got %s", luaL_typename(L, 2)); return luaL_argerror(L, 2, msg); } } else { user_args.data = NULL; user_args.len = 0; } if (user_args.len) { if (args.len == 0) { args = user_args; } else { p = ngx_palloc(r->pool, args.len + user_args.len + 1); if (p == NULL) { return luaL_error(L, "out of memory"); } q = ngx_copy(p, args.data, args.len); *q++ = '&'; ngx_memcpy(q, user_args.data, user_args.len); args.data = p; args.len += user_args.len + 1; } } if (ctx->headers_sent) { return luaL_error(L, "attempt to call ngx.exec after " "sending out response headers"); } ctx->exec_uri = uri; ctx->exec_args = args; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua exec \"%V?%V\"", &ctx->exec_uri, &ctx->exec_args); return lua_yield(L, 0); }
bool GetStringValueFromKey(lua_State& io_luaState, const char* Key, std::string & o_Value #ifdef EAE2014_SHOULDALLRETURNVALUESBECHECKED , std::string* o_errorMessage #endif ) { assert(Key); // Get the value of "name" { // Right now, the stack only has _one_ object, // which is the table from the asset file, at index -1. // We want to look up the value associated with the key "name": lua_pushstring(&io_luaState, Key); // Now, the key is at index -1 // and the table is at index -2. // We can now call lua_gettable() to get the value associated // with the key at index -1: { const int currentIndexOfTable = -2; lua_gettable(&io_luaState, currentIndexOfTable); } // Now, the value that was at t[k] is at index -1 // and the table is still at index -2. // First, then, we will make sure that a value (_any_ value) existed for the key: if (lua_isnil(&io_luaState, -1)) { #ifdef EAE2014_SHOULDALLRETURNVALUESBECHECKED if (o_errorMessage) { std::stringstream errorMessage; errorMessage << "No value for \"" << Key << "\" was found in the asset table\n"; *o_errorMessage = errorMessage.str().c_str(); } #endif lua_pop(&io_luaState, 1); // Now the only thing on the stack is the asset table at -1, // and the calling function will deal with this // (regardless of whether this function succeeds or fails). return false; } // If we reach this code then we know that a value exists, //Check if the type is a number if (lua_type(&io_luaState, -1) != LUA_TSTRING) { #ifdef EAE2014_SHOULDALLRETURNVALUESBECHECKED if (o_errorMessage) { std::stringstream errorMessage; errorMessage << "The value for \"" << Key << "\" must be a string value " "(instead of a " << luaL_typename(&io_luaState, -1) << ")\n"; *o_errorMessage = errorMessage.str().c_str(); } #endif // Pop the value lua_pop(&io_luaState, 1); // (The asset table is now at -1) return false; } // Now we know that the value stored in the table at the key is valid: { o_Value = (lua_tostring(&io_luaState, -1)); // Pop the value lua_pop(&io_luaState, 1); // (The asset table is now at -1) } } return true; }
// Load material file from path bool Load_LuaFileAndTopTable(const char* i_Filepath, lua_State*& o_luaState #ifdef EAE2014_SHOULDALLRETURNVALUESBECHECKED , std::string* o_errorMessage #endif ) { //Lua Logic //--------- assert(i_Filepath); bool wereThereErrors = false; // Create a new Lua state o_luaState = NULL; { o_luaState = luaL_newstate(); if (!o_luaState) { wereThereErrors = true; #ifdef EAE2014_SHOULDALLRETURNVALUESBECHECKED if (o_errorMessage) { *o_errorMessage = "Failed to create a new Lua state\n"; } #endif goto OnExit; } } // Load the asset file as a "chunk", // meaning there will be a callable function at the top of the stack { const int luaResult = luaL_loadfile(o_luaState, i_Filepath); if (luaResult != LUA_OK) { wereThereErrors = true; #ifdef EAE2014_SHOULDALLRETURNVALUESBECHECKED if (o_errorMessage) { *o_errorMessage = lua_tostring(o_luaState, -1); } #endif // Pop the error message lua_pop(o_luaState, 1); goto OnExit; } } // Execute the "chunk", which should load the asset // into a table at the top of the stack { const int argumentCount = 0; const int returnValueCount = LUA_MULTRET; // Return _everything_ that the file returns const int noMessageHandler = 0; const int luaResult = lua_pcall(o_luaState, argumentCount, returnValueCount, noMessageHandler); if (luaResult == LUA_OK) { // A well-behaved asset file will only return a single value const int returnedValueCount = lua_gettop(o_luaState); if (returnedValueCount == 1) { // A correct asset file _must_ return a table if (!lua_istable(o_luaState, -1)) { wereThereErrors = true; #ifdef EAE2014_SHOULDALLRETURNVALUESBECHECKED if (o_errorMessage) { std::stringstream errorMessage; errorMessage << "Asset files must return a table (instead of a " << luaL_typename(o_luaState, -1) << ")\n"; *o_errorMessage = errorMessage.str(); } #endif // Pop the returned non-table value lua_pop(o_luaState, 1); goto OnExit; } } else { wereThereErrors = true; #ifdef EAE2014_SHOULDALLRETURNVALUESBECHECKED if (o_errorMessage) { std::stringstream errorMessage; errorMessage << "Asset files must return a single table (instead of " << returnedValueCount << " values)\n"; *o_errorMessage = errorMessage.str(); } #endif // Pop every value that was returned lua_pop(o_luaState, returnedValueCount); goto OnExit; } } else { wereThereErrors = true; #ifdef EAE2014_SHOULDALLRETURNVALUESBECHECKED if (o_errorMessage) { *o_errorMessage = lua_tostring(o_luaState, -1); } #endif // Pop the error message lua_pop(o_luaState, 1); goto OnExit; } } // If this code is reached the asset file was loaded successfully, // and its table is now at index -1 OnExit: return !wereThereErrors; }
static int typeerror (lua_State *L, int narg, const char *tname) { const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, luaL_typename(L, narg)); return luaL_argerror(L, narg, msg); }
LUALIB_API int luaL_pushtype (lua_State *L, int narg) { if (!luaL_callmeta(L, narg, "__type")) lua_pushstring (L, luaL_typename(L, narg)); return 1; }
static int luaB_type (lua_State *L) { luaL_checkany(L, 1); lua_pushstring(L, luaL_typename(L, 1)); return 1; }
/* create and schedule a new lua process */ static int luaproc_create_newproc( lua_State *L ) { size_t len; luaproc *lp; luaL_Buffer buff; const char *code; int d; int lt = lua_type( L, 1 ); /* check function argument type - must be function or string; in case it is a function, dump it into a binary string */ if ( lt == LUA_TFUNCTION ) { lua_settop( L, 1 ); luaL_buffinit( L, &buff ); d = dump( L, luaproc_buff_writer, &buff, FALSE ); if ( d != 0 ) { lua_pushnil( L ); lua_pushfstring( L, "error %d dumping function to binary string", d ); return 2; } luaL_pushresult( &buff ); lua_insert( L, 1 ); } else if ( lt != LUA_TSTRING ) { lua_pushnil( L ); lua_pushfstring( L, "cannot use '%s' to create a new process", luaL_typename( L, 1 )); return 2; } /* get pointer to code string */ code = lua_tolstring( L, 1, &len ); /* get exclusive access to recycled lua processes list */ pthread_mutex_lock( &mutex_recycle_list ); /* check if a lua process can be recycled */ if ( recyclemax > 0 ) { lp = list_remove( &recycle_list ); /* otherwise create a new lua process */ if ( lp == NULL ) { lp = luaproc_new( L ); } } else { lp = luaproc_new( L ); } /* release exclusive access to recycled lua processes list */ pthread_mutex_unlock( &mutex_recycle_list ); /* init lua process */ lp->status = LUAPROC_STATUS_IDLE; lp->args = 0; lp->chan = NULL; /* load code in lua process */ luaproc_loadbuffer( L, lp, code, len ); /* if lua process is being created from a function, copy its upvalues and remove dumped binary string from stack */ if ( lt == LUA_TFUNCTION ) { if ( luaproc_copyupvalues( L, lp->lstate, 2 ) == FALSE ) { luaproc_recycle_insert( lp ); return 2; } lua_pop( L, 1 ); } sched_inc_lpcount(); /* increase active lua process count */ sched_queue_proc( lp ); /* schedule lua process for execution */ lua_pushboolean( L, TRUE ); return 1; }