/** ** Define burning building missiles. ** ** @param l Lua state. */ static int CclDefineBurningBuilding(lua_State *l) { for (std::vector<BurningBuildingFrame *>::iterator i = BurningBuildingFrames.begin(); i != BurningBuildingFrames.end(); ++i) { delete *i; } BurningBuildingFrames.clear(); const int args = lua_gettop(l); for (int j = 0; j < args; ++j) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } BurningBuildingFrame *ptr = new BurningBuildingFrame; const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *value = LuaToString(l, -1); lua_pop(l, 1); ++k; if (!strcmp(value, "percent")) { lua_rawgeti(l, j + 1, k + 1); ptr->Percent = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "missile")) { lua_rawgeti(l, j + 1, k + 1); ptr->Missile = MissileTypeByIdent(LuaToString(l, -1)); lua_pop(l, 1); } } BurningBuildingFrames.insert(BurningBuildingFrames.begin(), ptr); } return 0; }
lua_ai_action_handler* lua_ai_action_handler::create(lua_State *L, char const *code, lua_ai_context &context) { int res = luaL_loadstring(L, code);//stack size is now 1 [ -1: f] if (res) { char const *m = lua_tostring(L, -1); ERR_LUA << "error while creating ai function: " <<m << '\n'; lua_pop(L, 2);//return with stack size 0 [] return NULL; } // Retrieve the ai elements table from the registry. lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey))); lua_rawget(L, LUA_REGISTRYINDEX); //stack size is now 2 [-1: ais_table -2: f] // Push the function in the table so that it is not collected. size_t length = lua_rawlen(L, -1);//length of ais_table lua_pushvalue(L, -2); //stack size is now 3: [-1: f -2: ais_table -3: f] lua_rawseti(L, -2, length + 1);// ais_table[length+1]=f. stack size is now 2 [-1: ais_table -2: f] lua_remove(L, -1);//stack size is now 1 [-1: f] lua_remove(L, -1);//stack size is now 0 [] // Create the proxy C++ action handler. return new lua_ai_action_handler(L, context, length + 1); }
static int MS_add_string(lua_State *L) { if (config.debug > 2) molua_stackDump(L); if (lua_gettop(L) != 3 || !lua_isuserdata(L, 1) || !(lua_isstring(L, 2) || lua_isinteger(L, 2)) || !lua_isstring(L, 3)) { return luaL_error(L, "usage: <session> <field string or field num(faster)> <string>"); } MolochSession_t *session = checkMolochSession(L, 1); const char *string = lua_tostring(L, 3); int len = lua_rawlen(L, 3); int pos; if (lua_isinteger(L, 2)) { pos = lua_tointeger(L, 2); } else { pos = moloch_field_by_exp(lua_tostring(L, 2)); } gboolean result; result = moloch_field_string_add(pos, session, string, len, TRUE); lua_pushboolean(L, result); return 1; }
static void load_entry_numbered(lua_State *L, layout_entry_t *entry) { #if LUA_VERSION_NUM >= 502 size_t array_len = lua_rawlen(L, -1); #else size_t array_len = lua_objlen(L, -1); #endif if (array_len >= 1) entry->offset = luau_getarray_integer(L, -1, 1); if (array_len >= 2) entry->length = luau_getarray_integer(L, -1, 2); if (array_len >= 3) { luau_getarray(L, -1, 3); load_type(L, entry); lua_pop(L, 1); } if (array_len >= 4) { luau_getarray(L, -1, 4); load_endian(L, entry); lua_pop(L, 1); } }
/* lightuserdata pattern string format "ixrsmbp" integer size */ static int _pattern_pack(lua_State *L) { struct pbc_pattern * pat = (struct pbc_pattern *)checkuserdata(L,1); if (pat == NULL) { return luaL_error(L, "pack pattern is NULL"); } size_t format_sz = 0; const char * format = lua_tolstring(L,2,&format_sz); int size = lua_tointeger(L,3); char * data = (char *)alloca(size); // A trick , we don't need default value. zero buffer for array and message field. // pbc_pattern_set_default(pat, data); memset(data, 0 , size); char * ptr = data; int i; for (i=0;i<format_sz;i++) { if (format[i] >= 'a' && format[i] <='z') { ptr = _get_value(L, 4+i, ptr, format[i]); } else { if (!lua_istable(L,4+i)) { luaL_error(L,"need table for array type"); } int j; int n = lua_rawlen(L,4+i); for (j=0;j<n;j++) { lua_rawgeti(L,4+i,j+1); _get_array_value(L,(struct _pbc_array *)ptr,format[i]); lua_pop(L,1); } ptr += sizeof(pbc_array); } } luaL_Buffer b; luaL_buffinit(L, &b); int cap = 128; for (;;) { char * temp = (char *)luaL_prepbuffsize(&b , cap); struct pbc_slice slice; slice.buffer = temp; slice.len = cap; int ret = pbc_pattern_pack(pat, data, &slice); if (ret < 0) { cap = cap * 2; continue; } luaL_addsize(&b , slice.len); break; } luaL_pushresult(&b); pbc_pattern_close_arrays(pat, data); return 1; }
bool luaW_toconfig(lua_State *L, int index, config &cfg) { if (!lua_checkstack(L, LUA_MINSTACK)) return false; // Get the absolute index of the table. index = lua_absindex(L, index); int initial_top = lua_gettop(L); switch (lua_type(L, index)) { case LUA_TTABLE: break; case LUA_TUSERDATA: { if (vconfig * ptr = static_cast<vconfig *> (luaL_testudata(L, index, vconfigKey))) { cfg = ptr->get_parsed_config(); return true; } else { return false; } } case LUA_TNONE: case LUA_TNIL: return true; default: return false; } // First convert the children (integer indices). for (int i = 1, i_end = lua_rawlen(L, index); i <= i_end; ++i) { lua_rawgeti(L, index, i); if (!lua_istable(L, -1)) return_misformed(); lua_rawgeti(L, -1, 1); char const *m = lua_tostring(L, -1); if (!m) return_misformed(); lua_rawgeti(L, -2, 2); if (!luaW_toconfig(L, -1, cfg.add_child(m))) return_misformed(); lua_pop(L, 3); } // Then convert the attributes (string indices). for (lua_pushnil(L); lua_next(L, index); lua_pop(L, 1)) { if (lua_isnumber(L, -2)) continue; if (!lua_isstring(L, -2)) return_misformed(); config::attribute_value &v = cfg[lua_tostring(L, -2)]; if (lua_istable(L, -1)) { int subindex = lua_absindex(L, -1); std::ostringstream str; for (int i = 1, i_end = lua_rawlen(L, subindex); i <= i_end; ++i, lua_pop(L, 1)) { lua_rawgeti(L, -1, i); config::attribute_value item; if (!luaW_toscalar(L, -1, item)) return_misformed(); if (i > 1) str << ','; str << item; } // If there are any string keys, it's misformed for (lua_pushnil(L); lua_next(L, subindex); lua_pop(L, 1)) { if (!lua_isnumber(L, -2)) return_misformed(); } v = str.str(); } else if (!luaW_toscalar(L, -1, v)) return_misformed(); } lua_settop(L, initial_top); return true; }
/* * Method: GetNearbySystems * * Get a list of nearby <StarSystems> that match some criteria * * > systems = system:GetNearbySystems(range, filter) * * Parameters: * * range - distance from this system to search, in light years * * filter - an optional function. If specified the function will be called * once for each candidate system with the <StarSystem> object * passed as the only parameter. If the filter function returns * true then the system will be included in the array returned by * <GetNearbySystems>, otherwise it will be omitted. If no filter * function is specified then all systems in range are returned. * * Return: * * systems - an array of systems in range that matched the filter * * Availability: * * alpha 10 * * Status: * * experimental */ static int l_starsystem_get_nearby_systems(lua_State *l) { PROFILE_SCOPED() LUA_DEBUG_START(l); const StarSystem *s = LuaObject<StarSystem>::CheckFromLua(1); const double dist_ly = luaL_checknumber(l, 2); bool filter = false; if (lua_gettop(l) >= 3) { luaL_checktype(l, 3, LUA_TFUNCTION); // any type of function filter = true; } lua_newtable(l); const SystemPath &here = s->GetPath(); const int here_x = here.sectorX; const int here_y = here.sectorY; const int here_z = here.sectorZ; const Uint32 here_idx = here.systemIndex; RefCountedPtr<const Sector> here_sec = Pi::GetGalaxy()->GetSector(here); const int diff_sec = int(ceil(dist_ly/Sector::SIZE)); for (int x = here_x-diff_sec; x <= here_x+diff_sec; x++) { for (int y = here_y-diff_sec; y <= here_y+diff_sec; y++) { for (int z = here_z-diff_sec; z <= here_z+diff_sec; z++) { RefCountedPtr<const Sector> sec = Pi::GetGalaxy()->GetSector(SystemPath(x, y, z)); for (unsigned int idx = 0; idx < sec->m_systems.size(); idx++) { if (x == here_x && y == here_y && z == here_z && idx == here_idx) continue; if (Sector::DistanceBetween(here_sec, here_idx, sec, idx) > dist_ly) continue; RefCountedPtr<StarSystem> sys = Pi::GetGalaxy()->GetStarSystem(SystemPath(x, y, z, idx)); if (filter) { lua_pushvalue(l, 3); LuaObject<StarSystem>::PushToLua(sys.Get()); lua_call(l, 1, 1); if (!lua_toboolean(l, -1)) { lua_pop(l, 1); continue; } lua_pop(l, 1); } lua_pushinteger(l, lua_rawlen(l, -1)+1); LuaObject<StarSystem>::PushToLua(sys.Get()); lua_rawset(l, -3); } } } } LUA_DEBUG_END(l, 1); return 1; }
static int LuaIO_process_fork(lua_State* L) { if (lua_type(L, 1) != LUA_TTABLE) { return luaL_argerror(L, 1, "process.fork(options) error: options must be [table]\n"); } if (!LuaIO_process_exepath_ptr) { size_t length = sizeof(LuaIO_process_exepath); int err = uv_exepath(LuaIO_process_exepath, &length); if (err < 0) { return luaL_error(L, "process.fork(options) uv_exepath() error: %s\n", uv_strerror(err)); } LuaIO_process_exepath_ptr = LuaIO_process_exepath; } lua_getfield(L, 1, "file"); const char* file; if (lua_type(L, -1) == LUA_TSTRING) { file = lua_tostring(L, -1); } else { return luaL_argerror(L, 2, "process.fork(options) error: options.file is required and must be [string]\n"); } lua_pop(L, 1); lua_getfield(L, 1, "args"); size_t args_length = 0; char** args = NULL; if (lua_type(L, -1) == LUA_TTABLE) { args_length = lua_rawlen(L, -1); /*execpath, file, null => args_length + 3*/ args = LuaIO_malloc(sizeof(char*) * (args_length + 3)); if (!args) { return luaL_error(L, "process.fork(options) error: no memory for args\n"); } for (size_t i = 1; i <= args_length; ++i) { lua_rawgeti(L, -1, i); args[i + 1] = (char*)luaL_checkstring(L, -1); lua_pop(L, 1); } } else if (lua_type(L, -1) == LUA_TNIL) { /*execpath, file, null => args_length + 3*/ args = LuaIO_malloc(sizeof(char*) * 3); if (!args) { return luaL_error(L, "process.fork(options) error: no memory for args\n"); } } else { return luaL_argerror(L, 2, "process.fork(options) error: options.args must be [table]\n"); } lua_pop(L, 1); args[0] = LuaIO_process_exepath_ptr; args[1] = (char*)file; args[args_length + 2] = NULL; if (!LuaIO_process_stdio_ptr) { LuaIO_process_stdio[0].flags = UV_INHERIT_FD; LuaIO_process_stdio[0].data.fd = 0; LuaIO_process_stdio[1].flags = UV_INHERIT_FD; LuaIO_process_stdio[1].data.fd = 1; LuaIO_process_stdio[2].flags = UV_INHERIT_FD; LuaIO_process_stdio[2].data.fd = 2; LuaIO_process_stdio_ptr = LuaIO_process_stdio; } uv_process_options_t* options = LuaIO_malloc(sizeof(uv_process_options_t)); if (!options) { LuaIO_free(args); return luaL_error(L, "process.fork(options) error: no memory for uv_process_options_t options\n"); } LuaIO_memzero(options, sizeof(uv_process_options_t)); options->exit_cb = LuaIO_process_onexit; options->file = LuaIO_process_exepath_ptr; options->args = args; options->stdio_count = 3; options->stdio = LuaIO_process_stdio_ptr; lua_getfield(L, 1, "uid"); if (lua_type(L, -1) == LUA_TNUMBER) { options->uid = lua_tointeger(L, -1); options->flags |= UV_PROCESS_SETUID; } else if (lua_type(L, -1) != LUA_TNIL) { LuaIO_process_free_options(options); return luaL_argerror(L, 2, "process.fork(options) error: options.uid must be [number]\n"); } lua_pop(L, 1); lua_getfield(L, 1, "gid"); if (lua_type(L, -1) == LUA_TNUMBER) { options->gid = lua_tointeger(L, -1); options->flags |= UV_PROCESS_SETGID; } else if (lua_type(L, -1) != LUA_TNIL) { LuaIO_process_free_options(options); return luaL_argerror(L, 2, "process.fork(options) error: options.gid must be [number]\n"); } lua_pop(L, 1); lua_getfield(L, 1, "detached"); if (lua_toboolean(L, -1)) { options->flags |= UV_PROCESS_DETACHED; } lua_pop(L, 1); lua_getfield(L, 1, "forever"); int forever = lua_toboolean(L, -1); lua_pop(L, 1); int cpu = -1; lua_getfield(L, 1, "cpu"); if (lua_type(L, -1) == LUA_TNUMBER) { cpu = lua_tointeger(L, -1); } else if (lua_type(L, -1) != LUA_TNIL) { LuaIO_process_free_options(options); return luaL_argerror(L, 2, "process.fork(options) error: options.cpu must be [number]\n"); } lua_pop(L, 1); uv_process_t* handle = LuaIO_malloc(sizeof(uv_process_t)); if (!handle) { LuaIO_process_free_options(options); return luaL_error(L, "process.fork(options) error: no memory for uv_process_t handle.\n"); } LuaIO_memzero(handle, sizeof(uv_process_t)); LuaIO_process_data_t* data = NULL; if (forever) { data = LuaIO_malloc(sizeof(LuaIO_process_data_t)); if (!data) { LuaIO_process_free_options(options); return luaL_error(L, "process.fork(options) error:no memory for LuaIO_process_data_t data.\n"); } lua_pushvalue(L, 1); data->options_ref = luaL_ref(L, LUA_REGISTRYINDEX); data->options = options; data->cpu = cpu; handle->data = data; } int ret = uv_spawn(uv_default_loop(), handle, options); if (ret < 0) { LuaIO_process_free_options(options); luaL_unref(L, LUA_REGISTRYINDEX, data->options_ref); LuaIO_free(data); uv_close((uv_handle_t*)handle, NULL); return luaL_error(L, "process.fork(options) uv_spawn() error: %s\n", uv_strerror(ret)); } if (cpu >= 0) LuaIO_set_affinity(handle->pid, cpu); if (!LuaIO_process_signal_ptr) { uv_signal_init(uv_default_loop(), &LuaIO_process_signal); LuaIO_process_signal_ptr = &LuaIO_process_signal; uv_signal_start(LuaIO_process_signal_ptr, LuaIO_process_signal_callback, SIGQUIT); } lua_pushinteger(L, handle->pid); return 1; }
/** ** Define an AI player. ** ** @param l Lua state. */ static int CclDefineAiPlayer(lua_State *l) { const unsigned int playerIdx = LuaToNumber(l, 0 + 1); Assert(playerIdx <= PlayerMax); DebugPrint("%p %d\n" _C_(void *)Players[playerIdx].Ai _C_ Players[playerIdx].AiEnabled); // FIXME: lose this: // Assert(!Players[playerIdx].Ai && Players[playerIdx].AiEnabled); PlayerAi *ai = Players[playerIdx].Ai = new PlayerAi; ai->Player = &Players[playerIdx]; // Parse the list: (still everything could be changed!) const int args = lua_gettop(l); for (int j = 1; j < args; ++j) { const char *value = LuaToString(l, j + 1); ++j; if (!strcmp(value, "ai-type")) { const char *aiName = LuaToString(l, j + 1); CAiType *ait = GetAiTypesByName(aiName); if (ait == NULL) { lua_pushfstring(l, "ai-type not found: %s", aiName); } ai->AiType = ait; ai->Script = ait->Script; } else if (!strcmp(value, "script")) { ai->Script = LuaToString(l, j + 1); } else if (!strcmp(value, "script-debug")) { ai->ScriptDebug = LuaToBoolean(l, j + 1); } else if (!strcmp(value, "sleep-cycles")) { ai->SleepCycles = LuaToNumber(l, j + 1); } else if (!strcmp(value, "force")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); lua_rawgeti(l, j + 1, 0 + 1); const int cclforceIdx = LuaToNumber(l, -1); UNUSED(cclforceIdx); const int forceIdx = ai->Force.FindFreeForce(AiForceRoleDefault); lua_pop(l, 1); for (int k = 1; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *value = LuaToString(l, -1); lua_pop(l, 1); ++k; if (!strcmp(value, "complete")) { ai->Force[forceIdx].Completed = true; --k; } else if (!strcmp(value, "recruit")) { ai->Force[forceIdx].Completed = false; --k; } else if (!strcmp(value, "attack")) { ai->Force[forceIdx].Attacking = true; --k; } else if (!strcmp(value, "defend")) { ai->Force[forceIdx].Defending = true; --k; } else if (!strcmp(value, "role")) { lua_rawgeti(l, j + 1, k + 1); value = LuaToString(l, -1); lua_pop(l, 1); if (!strcmp(value, "attack")) { ai->Force[forceIdx].Role = AiForceRoleAttack; } else if (!strcmp(value, "defend")) { ai->Force[forceIdx].Role = AiForceRoleDefend; } else { LuaError(l, "Unsupported force tag: %s" _C_ value); } } else if (!strcmp(value, "types")) { lua_rawgeti(l, j + 1, k + 1); if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subsubargs = lua_rawlen(l, -1); for (int subk = 0; subk < subsubargs; ++subk) { lua_rawgeti(l, -1, subk + 1); const int num = LuaToNumber(l, -1); lua_pop(l, 1); ++subk; lua_rawgeti(l, -1, subk + 1); const char *ident = LuaToString(l, -1); lua_pop(l, 1); AiUnitType queue; queue.Want = num; queue.Type = UnitTypeByIdent(ident); ai->Force[forceIdx].UnitTypes.push_back(queue); } lua_pop(l, 1); } else if (!strcmp(value, "units")) { lua_rawgeti(l, j + 1, k + 1); if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subsubargs = lua_rawlen(l, -1); for (int subk = 0; subk < subsubargs; ++subk) { lua_rawgeti(l, -1, subk + 1); const int num = LuaToNumber(l, -1); lua_pop(l, 1); ++subk; #if 0 lua_rawgeti(l, -1, subk + 1); const char *ident = LuaToString(l, -1); UNUSED(ident); lua_pop(l, 1); #endif ai->Force[forceIdx].Units.Insert(&UnitManager.GetSlotUnit(num)); } lua_pop(l, 1); } else if (!strcmp(value, "state")) { lua_rawgeti(l, j + 1, k + 1); ai->Force[forceIdx].State = AiForceAttackingState(LuaToNumber(l, -1)); lua_pop(l, 1); } else if (!strcmp(value, "goalx")) { lua_rawgeti(l, j + 1, k + 1); ai->Force[forceIdx].GoalPos.x = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "goaly")) { lua_rawgeti(l, j + 1, k + 1); ai->Force[forceIdx].GoalPos.y = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "must-transport")) { // Keep for backward compatibility } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } } else if (!strcmp(value, "reserve")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *type = LuaToString(l, -1); lua_pop(l, 1); ++k; lua_rawgeti(l, j + 1, k + 1); int num = LuaToNumber(l, -1); lua_pop(l, 1); const int resId = GetResourceIdByName(l, type); ai->Reserve[resId] = num; } } else if (!strcmp(value, "used")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *type = LuaToString(l, -1); lua_pop(l, 1); ++k; lua_rawgeti(l, j + 1, k + 1); const int num = LuaToNumber(l, -1); lua_pop(l, 1); const int resId = GetResourceIdByName(l, type); ai->Used[resId] = num; } } else if (!strcmp(value, "needed")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *type = LuaToString(l, -1); lua_pop(l, 1); ++k; lua_rawgeti(l, j + 1, k + 1); const int num = LuaToNumber(l, -1); lua_pop(l, 1); const int resId = GetResourceIdByName(l, type); ai->Needed[resId] = num; } } else if (!strcmp(value, "collect")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *type = LuaToString(l, -1); lua_pop(l, 1); ++k; lua_rawgeti(l, j + 1, k + 1); const int num = LuaToNumber(l, -1); lua_pop(l, 1); const int resId = GetResourceIdByName(l, type); ai->Collect[resId] = num; } } else if (!strcmp(value, "need-mask")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *type = LuaToString(l, -1); lua_pop(l, 1); const int resId = GetResourceIdByName(l, type); ai->NeededMask |= (1 << resId); } } else if (!strcmp(value, "need-supply")) { ai->NeedSupply = true; --j; } else if (!strcmp(value, "exploration")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { Vec2i pos; lua_rawgeti(l, j + 1, k + 1); if (!lua_istable(l, -1) || lua_rawlen(l, -1) != 3) { LuaError(l, "incorrect argument"); } lua_rawgeti(l, -1, 1); pos.x = LuaToNumber(l, -1); lua_pop(l, 1); lua_rawgeti(l, -1, 2); pos.y = LuaToNumber(l, -1); lua_pop(l, 1); lua_rawgeti(l, -1, 3); const int mask = LuaToNumber(l, -1); lua_pop(l, 1); lua_pop(l, 1); AiExplorationRequest queue(pos, mask); ai->FirstExplorationRequest.push_back(queue); } } else if (!strcmp(value, "last-exploration-cycle")) { ai->LastExplorationGameCycle = LuaToNumber(l, j + 1); } else if (!strcmp(value, "last-can-not-move-cycle")) { ai->LastCanNotMoveGameCycle = LuaToNumber(l, j + 1); } else if (!strcmp(value, "unit-type")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); int i = 0; if (subargs) { ai->UnitTypeRequests.resize(subargs / 2); } for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *ident = LuaToString(l, -1); lua_pop(l, 1); ++k; lua_rawgeti(l, j + 1, k + 1); const int count = LuaToNumber(l, -1); lua_pop(l, 1); ai->UnitTypeRequests[i].Type = UnitTypeByIdent(ident); ai->UnitTypeRequests[i].Count = count; ++i; } } else if (!strcmp(value, "upgrade")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *ident = LuaToString(l, -1); lua_pop(l, 1); ai->UpgradeToRequests.push_back(UnitTypeByIdent(ident)); } } else if (!strcmp(value, "research")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *ident = LuaToString(l, -1); lua_pop(l, 1); ai->ResearchRequests.push_back(CUpgrade::Get(ident)); } } else if (!strcmp(value, "building")) { CclParseBuildQueue(l, ai, j + 1); } else if (!strcmp(value, "repair-building")) { ai->LastRepairBuilding = LuaToNumber(l, j + 1); } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } return 0; }
/** ** Parse a map. ** ** @param l Lua state. */ static int CclStratagusMap(lua_State *l) { int args = lua_gettop(l); for (int j = 0; j < args; ++j) { const char *value = LuaToString(l, j + 1); ++j; if (!strcmp(value, "version")) { //Wyrmgus start // char buf[32]; char buf[64]; //Wyrmgus end const char *version = LuaToString(l, j + 1); strncpy(buf, VERSION, sizeof(buf)); if (strcmp(buf, version)) { fprintf(stderr, "Warning not saved with this version.\n"); } } else if (!strcmp(value, "uid")) { Map.Info.MapUID = LuaToNumber(l, j + 1); } else if (!strcmp(value, "description")) { Map.Info.Description = LuaToString(l, j + 1); } else if (!strcmp(value, "the-map")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { const char *value = LuaToString(l, j + 1, k + 1); ++k; if (!strcmp(value, "size")) { lua_rawgeti(l, j + 1, k + 1); CclGetPos(l, &Map.Info.MapWidth, &Map.Info.MapHeight); lua_pop(l, 1); delete[] Map.Fields; Map.Fields = new CMapField[Map.Info.MapWidth * Map.Info.MapHeight]; // FIXME: this should be CreateMap or InitMap? } else if (!strcmp(value, "fog-of-war")) { Map.NoFogOfWar = false; --k; } else if (!strcmp(value, "no-fog-of-war")) { Map.NoFogOfWar = true; --k; } else if (!strcmp(value, "filename")) { Map.Info.Filename = LuaToString(l, j + 1, k + 1); } else if (!strcmp(value, "map-fields")) { lua_rawgeti(l, j + 1, k + 1); if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subsubargs = lua_rawlen(l, -1); if (subsubargs != Map.Info.MapWidth * Map.Info.MapHeight) { fprintf(stderr, "Wrong tile table length: %d\n", subsubargs); } for (int i = 0; i < subsubargs; ++i) { lua_rawgeti(l, -1, i + 1); if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } Map.Fields[i].parse(l); lua_pop(l, 1); } lua_pop(l, 1); } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } return 0; }
/** ** Glue between c and scheme. Allows to specify some global game sounds ** in a ccl file. ** ** @param l Lua state. */ static int CclDefineGameSounds(lua_State *l) { //FIXME: should allow to define ALL the game sounds const int args = lua_gettop(l); for (int j = 0; j < args; ++j) { const char *value = LuaToString(l, j + 1); ++j; LuaUserData *data = NULL; // let's handle now the different cases if (!strcmp(value, "click")) { if (!lua_isuserdata(l, j + 1) || (data = (LuaUserData *)lua_touserdata(l, j + 1))->Type != LuaSoundType) { LuaError(l, "Sound id expected"); } GameSounds.Click.Sound = (CSound *)data->Data; } else if (!strcmp(value, "transport-docking")) { if (!lua_isuserdata(l, j + 1) || (data = (LuaUserData *)lua_touserdata(l, j + 1))->Type != LuaSoundType) { LuaError(l, "Sound id expected"); } GameSounds.Docking.Sound = (CSound *)data->Data; } else if (!strcmp(value, "placement-error")) { SetSoundConfigRace(l, j, GameSounds.PlacementError); } else if (!strcmp(value, "placement-success")) { SetSoundConfigRace(l, j, GameSounds.PlacementSuccess); } else if (!strcmp(value, "work-complete")) { SetSoundConfigRace(l, j, GameSounds.WorkComplete); } else if (!strcmp(value, "research-complete")) { SetSoundConfigRace(l, j, GameSounds.ResearchComplete); } else if (!strcmp(value, "not-enough-res")) { if (!lua_istable(l, j + 1) || lua_rawlen(l, j + 1) != 3) { LuaError(l, "incorrect argument"); } lua_rawgeti(l, j + 1, 1); const char *resName = LuaToString(l, -1); lua_pop(l, 1); const int resId = GetResourceIdByName(l, resName); lua_rawgeti(l, j + 1, 2); const char *raceName = LuaToString(l, -1); lua_pop(l, 1); const int raceIndex = PlayerRaces.GetRaceIndexByName(raceName); if (raceIndex == -1) { LuaError(l, "Unknown race: %s" _C_ raceName); } lua_rawgeti(l, j + 1, 3); if (!lua_isuserdata(l, -1) || (data = (LuaUserData *)lua_touserdata(l, -1))->Type != LuaSoundType) { LuaError(l, "Sound id expected"); } lua_pop(l, 1); GameSounds.NotEnoughRes[raceIndex][resId].Sound = (CSound *)data->Data; } else if (!strcmp(value, "not-enough-food")) { SetSoundConfigRace(l, j, GameSounds.NotEnoughFood); } else if (!strcmp(value, "rescue")) { SetSoundConfigRace(l, j, GameSounds.Rescue); } else if (!strcmp(value, "building-construction")) { SetSoundConfigRace(l, j, GameSounds.BuildingConstruction); } else if (!strcmp(value, "chat-message")) { if (!lua_isuserdata(l, j + 1) || (data = (LuaUserData *)lua_touserdata(l, j + 1))->Type != LuaSoundType) { LuaError(l, "Sound id expected"); } GameSounds.ChatMessage.Sound = (CSound *)data->Data; } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } return 0; }
/** ** Define a world map tile. ** ** @param l Lua state. */ static int CclDefineWorldMapTile(lua_State *l) { LuaCheckArgs(l, 2); if (!lua_istable(l, 2)) { LuaError(l, "incorrect argument (expected table)"); } std::pair<int,int> tile_position; CclGetPos(l, &tile_position.first, &tile_position.second, 1); WorldMapTile *tile = new WorldMapTile; tile->Position.x = tile_position.first; tile->Position.y = tile_position.second; // Parse the list: for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) { const char *value = LuaToString(l, -2); if (!strcmp(value, "World")) { CWorld *world = CWorld::GetWorld(LuaToString(l, -1)); if (world != nullptr) { tile->World = world; } else { LuaError(l, "World doesn't exist."); } } else if (!strcmp(value, "Terrain")) { int terrain = GetWorldMapTerrainTypeId(LuaToString(l, -1)); if (terrain != -1) { tile->Terrain = terrain; } else { LuaError(l, "Terrain doesn't exist."); } } else if (!strcmp(value, "Resource")) { int resource = GetResourceIdByName(LuaToString(l, -1)); if (resource != -1) { tile->Resource = resource; } else { LuaError(l, "Resource doesn't exist."); } } else if (!strcmp(value, "Capital")) { tile->Capital = LuaToBoolean(l, -1); } else if (!strcmp(value, "CulturalTerrainNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int terrain = GetWorldMapTerrainTypeId(LuaToString(l, -1, j + 1)); if (terrain == -1) { LuaError(l, "Terrain doesn't exist."); } ++j; std::string name_type = "terrain-" + NameToIdent(WorldMapTerrainTypes[terrain]->Name); CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, -1, j + 1)); ++j; if (!civilization) { continue; } std::string cultural_name = LuaToString(l, -1, j + 1); tile->CulturalTerrainNames[std::pair<int,int>(terrain, civilization->ID)].push_back(TransliterateText(cultural_name)); } } else if (!strcmp(value, "FactionCulturalTerrainNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int terrain = GetWorldMapTerrainTypeId(LuaToString(l, -1, j + 1)); if (terrain == -1) { LuaError(l, "Terrain doesn't exist."); } ++j; std::string name_type = "terrain-" + NameToIdent(WorldMapTerrainTypes[terrain]->Name); ++j; int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1)); if (faction == -1) { LuaError(l, "Faction doesn't exist."); } ++j; std::string cultural_name = LuaToString(l, -1, j + 1); tile->FactionCulturalTerrainNames[std::pair<int,CFaction *>(terrain, PlayerRaces.Factions[faction])].push_back(TransliterateText(cultural_name)); } } else if (!strcmp(value, "CulturalResourceNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int resource = GetResourceIdByName(LuaToString(l, -1, j + 1)); if (resource == -1) { LuaError(l, "Resource doesn't exist."); } ++j; std::string name_type = "resource-tile-" + DefaultResourceNames[resource]; CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, -1, j + 1)); ++j; if (!civilization) { continue; } std::string cultural_name = LuaToString(l, -1, j + 1); tile->CulturalResourceNames[std::pair<int,int>(resource, civilization->ID)].push_back(TransliterateText(cultural_name)); } } else if (!strcmp(value, "FactionCulturalResourceNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int resource = GetResourceIdByName(LuaToString(l, -1, j + 1)); if (resource == -1) { LuaError(l, "Resource doesn't exist."); } ++j; std::string name_type = "resource-tile-" + DefaultResourceNames[resource]; ++j; int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1)); if (faction == -1) { LuaError(l, "Faction doesn't exist."); } ++j; std::string cultural_name = LuaToString(l, -1, j + 1); tile->FactionCulturalResourceNames[std::pair<int,CFaction *>(resource, PlayerRaces.Factions[faction])].push_back(TransliterateText(cultural_name)); } } else if (!strcmp(value, "CulturalSettlementNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, -1, j + 1)); ++j; if (!civilization) { continue; } std::string cultural_name = LuaToString(l, -1, j + 1); tile->CulturalSettlementNames[civilization->ID].push_back(TransliterateText(cultural_name)); } } else if (!strcmp(value, "FactionCulturalSettlementNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { ++j; int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1)); if (faction == -1) { LuaError(l, "Faction doesn't exist."); } ++j; std::string cultural_name = LuaToString(l, -1, j + 1); tile->FactionCulturalSettlementNames[PlayerRaces.Factions[faction]].push_back(TransliterateText(cultural_name)); } } else if (!strcmp(value, "Claims")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { ++j; int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1)); if (faction == -1) { LuaError(l, "Faction doesn't exist."); } tile->FactionClaims.push_back(PlayerRaces.Factions[faction]); } } else if (!strcmp(value, "HistoricalOwners")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; ++j; std::string owner_faction_name = LuaToString(l, -1, j + 1); if (!owner_faction_name.empty()) { int owner_faction = PlayerRaces.GetFactionIndexByName(owner_faction_name); if (owner_faction == -1) { LuaError(l, "Faction \"%s\" doesn't exist." _C_ owner_faction_name.c_str()); } tile->HistoricalOwners[year] = PlayerRaces.Factions[owner_faction]; } else { tile->HistoricalOwners[year] = nullptr; } } } else if (!strcmp(value, "HistoricalClaims")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; ++j; std::string claimant_faction_name = LuaToString(l, -1, j + 1); int claimant_faction = PlayerRaces.GetFactionIndexByName(claimant_faction_name); if (claimant_faction == -1) { LuaError(l, "Faction \"%s\" doesn't exist." _C_ claimant_faction_name.c_str()); } tile->HistoricalClaims[year] = PlayerRaces.Factions[claimant_faction]; } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } if (tile->World == nullptr) { LuaError(l, "Tile (%d, %d) is not assigned to any world." _C_ tile->Position.x _C_ tile->Position.y); } return 0; }
/** ** Define a province. ** ** @param l Lua state. */ static int CclDefineProvince(lua_State *l) { LuaCheckArgs(l, 2); if (!lua_istable(l, 2)) { LuaError(l, "incorrect argument (expected table)"); } std::string province_name = LuaToString(l, 1); CProvince *province = GetProvince(province_name); if (!province) { province = new CProvince; province->Name = province_name; province->ID = Provinces.size(); Provinces.push_back(province); } std::string name_type = "province"; // Parse the list: for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) { const char *value = LuaToString(l, -2); if (!strcmp(value, "World")) { CWorld *world = CWorld::GetWorld(LuaToString(l, -1)); if (world != nullptr) { province->World = world; world->Provinces.push_back(province); } else { LuaError(l, "World doesn't exist."); } } else if (!strcmp(value, "Water")) { province->Water = LuaToBoolean(l, -1); } else if (!strcmp(value, "Coastal")) { province->Coastal = LuaToBoolean(l, -1); } else if (!strcmp(value, "CulturalNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, -1, j + 1)); ++j; if (!civilization) { continue; } std::string cultural_name = LuaToString(l, -1, j + 1); province->CulturalNames[civilization->ID] = TransliterateText(cultural_name); } } else if (!strcmp(value, "FactionCulturalNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { ++j; int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1)); if (faction == -1) { LuaError(l, "Faction doesn't exist."); } ++j; std::string cultural_name = LuaToString(l, -1, j + 1); province->FactionCulturalNames[PlayerRaces.Factions[faction]] = TransliterateText(cultural_name); } } else if (!strcmp(value, "Claims")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { ++j; int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1)); if (faction == -1) { LuaError(l, "Faction doesn't exist."); } province->FactionClaims.push_back(PlayerRaces.Factions[faction]); } } else if (!strcmp(value, "Regions")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { CRegion *region = GetRegion(LuaToString(l, -1, j + 1)); if (region == nullptr) { LuaError(l, "Region doesn't exist."); } province->Regions.push_back(region); region->Provinces.push_back(province); } } else if (!strcmp(value, "HistoricalOwners")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; ++j; std::string owner_faction_name = LuaToString(l, -1, j + 1); if (!owner_faction_name.empty()) { int owner_faction = PlayerRaces.GetFactionIndexByName(owner_faction_name); if (owner_faction == -1) { LuaError(l, "Faction \"%s\" doesn't exist." _C_ owner_faction_name.c_str()); } province->HistoricalOwners[year] = PlayerRaces.Factions[owner_faction]; } else { province->HistoricalOwners[year] = nullptr; } } } else if (!strcmp(value, "HistoricalClaims")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; ++j; std::string claimant_faction_name = LuaToString(l, -1, j + 1); int claimant_faction = PlayerRaces.GetFactionIndexByName(claimant_faction_name); if (claimant_faction == -1) { LuaError(l, "Faction \"%s\" doesn't exist." _C_ claimant_faction_name.c_str()); } province->HistoricalClaims[year] = PlayerRaces.Factions[claimant_faction]; } } else if (!strcmp(value, "HistoricalCultures")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; std::string historical_civilization_name = LuaToString(l, -1, j + 1); if (!historical_civilization_name.empty()) { CCivilization *historical_civilization = CCivilization::GetCivilization(historical_civilization_name); if (historical_civilization) { province->HistoricalCultures[year] = historical_civilization->ID; } } } } else if (!strcmp(value, "HistoricalPopulation")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; int historical_population = LuaToNumber(l, -1, j + 1); province->HistoricalPopulation[year] = historical_population; } } else if (!strcmp(value, "HistoricalSettlementBuildings")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; std::string building_type_ident = LuaToString(l, -1, j + 1); int building_type = UnitTypeIdByIdent(building_type_ident); if (building_type == -1) { LuaError(l, "Unit type \"%s\" doesn't exist." _C_ building_type_ident.c_str()); } ++j; province->HistoricalSettlementBuildings[building_type][year] = LuaToBoolean(l, -1, j + 1); } } else if (!strcmp(value, "HistoricalModifiers")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; std::string upgrade_ident = LuaToString(l, -1, j + 1); CUpgrade *modifier = CUpgrade::Get(upgrade_ident); if (modifier == nullptr) { LuaError(l, "Upgrade \"%s\" doesn't exist." _C_ upgrade_ident.c_str()); } ++j; province->HistoricalModifiers[modifier][year] = LuaToBoolean(l, -1, j + 1); } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } if (province->World == nullptr) { LuaError(l, "Province \"%s\" is not assigned to any world." _C_ province->Name.c_str()); } return 0; }
static int lp_create(lua_State *L) { int err; loski_Process *proc; const char *exec; const char *path = NULL; char **argv = NULL; char *const *envl = NULL; FILE *stdin = NULL; FILE *stdout = NULL; FILE *stderr = NULL; if (lua_isstring(L, 1)) { int i; int argc = lua_gettop(L); argv = allocargs(L, argc); /* TODO: memory leak in case of arg erros */ argv[0] = (char *)luaL_checkstring(L, 1); for (i = 1; i < argc; ++i) argv[i] = (char *)luaL_checkstring(L, i+1); exec = argv[0]; } else if (lua_istable(L, 1)) { lua_settop(L, 1); exec = getstrfield(L, 1, "execfile"); path = optstrfield(L, 1, "runpath", path); stdin = optfilefield(L, 1, "stdin"); stdout = optfilefield(L, 1, "stdout"); stderr = optfilefield(L, 1, "stderr"); lua_getfield(L, 1, "arguments"); if (lua_istable(L, 2)) { size_t i; size_t argc = lua_rawlen(L, 2); argv = allocargs(L, argc+1); /* TODO: memory leak in case of arg erros */ argv[0] = (char *)exec; for(i = 1; i <= argc; ++i) { lua_rawgeti(L, 2, i); luaL_argcheck(L, 1, !lua_isstring(L, 3), "field "LUA_QL("arguments")" must contain only strings"); argv[i] = (char *)lua_tostring(L, 3); lua_pop(L, 1); /* pop an argument string */ } } else if (!lua_isnil(L, 2)) { luaL_argerror(L, 1, "field "LUA_QL("arguments")" must be a table"); } lua_pop(L, 1); /* pop field 'arguments' */ lua_getfield(L, 1, "environment"); if (lua_istable(L, 2)) { envl = table2env(L); } else if (!lua_isnil(L, 2)) { luaL_argerror(L, 1, "field "LUA_QL("environment")" must be a table"); } lua_pop(L, 1); /* pop field 'environment' */ } else { return luaL_argerror(L, 1, "table or string expected"); } proc = newproc(L); /* push a new proc structure on the stack */ err = loski_createprocess(proc, exec, path, argv, envl, stdin, stdout, stderr); freememory(L, (void *)argv); freememory(L, (void *)envl); return pushresults(L, 1, err); /* return process */ }
/** ** Define a text. ** ** @param l Lua state. */ static int CclDefineText(lua_State *l) { LuaCheckArgs(l, 2); if (!lua_istable(l, 2)) { LuaError(l, "incorrect argument (expected table)"); } std::string text_name = LuaToString(l, 1); CText *text = GetText(text_name); if (!text) { text = new CText; Texts.push_back(text); text->Name = text_name; } // Parse the list: for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) { const char *value = LuaToString(l, -2); if (!strcmp(value, "Author")) { text->Author = LuaToString(l, -1); } else if (!strcmp(value, "Translator")) { text->Translator = LuaToString(l, -1); } else if (!strcmp(value, "Publisher")) { text->Publisher = LuaToString(l, -1); } else if (!strcmp(value, "CopyrightNotice")) { text->CopyrightNotice = LuaToString(l, -1); } else if (!strcmp(value, "Notes")) { text->Notes = LuaToString(l, -1); } else if (!strcmp(value, "Year")) { text->Year = LuaToNumber(l, -1); } else if (!strcmp(value, "InitialPage")) { text->InitialPage = LuaToNumber(l, -1); } else if (!strcmp(value, "Chapters")) { const int args = lua_rawlen(l, -1); for (int j = 0; j < args; ++j) { lua_rawgeti(l, -1, j + 1); CChapter *chapter = new CChapter; text->Chapters.push_back(chapter); if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table for variations)"); } const int subargs = lua_rawlen(l, -1); for (int k = 0; k < subargs; ++k) { value = LuaToString(l, -1, k + 1); ++k; lua_rawgeti(l, -1, k + 1); if (!strcmp(value, "name")) { chapter->Name = LuaToString(l, -1); } else if (!strcmp(value, "introduction")) { chapter->Introduction = LuaToBoolean(l, -1); } else if (!strcmp(value, "text")) { const int subsubargs = lua_rawlen(l, -1); for (int n = 0; n < subsubargs; ++n) { chapter->Pages.push_back(LuaToString(l, -1, n + 1)); } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } lua_pop(l, 1); } lua_pop(l, 1); } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } return 0; }
/** ** Define a button. ** ** @param l Lua state. */ static int CclDefineButton(lua_State *l) { LuaCheckArgs(l, 1); if (!lua_istable(l, 1)) { LuaError(l, "incorrect argument"); } ButtonAction ba; // // Parse the arguments // lua_pushnil(l); while (lua_next(l, 1)) { const char *value = LuaToString(l, -2); if (!strcmp(value, "Pos")) { ba.Pos = LuaToNumber(l, -1); } else if (!strcmp(value, "Level")) { ba.Level = LuaToNumber(l, -1); } else if (!strcmp(value, "AlwaysShow")) { ba.AlwaysShow = LuaToBoolean(l, -1); } else if (!strcmp(value, "Icon")) { ba.Icon.Name = LuaToString(l, -1); } else if (!strcmp(value, "Action")) { value = LuaToString(l, -1); if (!strcmp(value, "move")) { ba.Action = ButtonMove; } else if (!strcmp(value, "stop")) { ba.Action = ButtonStop; } else if (!strcmp(value, "attack")) { ba.Action = ButtonAttack; } else if (!strcmp(value, "repair")) { ba.Action = ButtonRepair; } else if (!strcmp(value, "harvest")) { ba.Action = ButtonHarvest; } else if (!strcmp(value, "button")) { ba.Action = ButtonButton; } else if (!strcmp(value, "build")) { ba.Action = ButtonBuild; } else if (!strcmp(value, "train-unit")) { ba.Action = ButtonTrain; } else if (!strcmp(value, "patrol")) { ba.Action = ButtonPatrol; } else if (!strcmp(value, "stand-ground")) { ba.Action = ButtonStandGround; } else if (!strcmp(value, "attack-ground")) { ba.Action = ButtonAttackGround; } else if (!strcmp(value, "return-goods")) { ba.Action = ButtonReturn; } else if (!strcmp(value, "cast-spell")) { ba.Action = ButtonSpellCast; } else if (!strcmp(value, "research")) { ba.Action = ButtonResearch; } else if (!strcmp(value, "upgrade-to")) { ba.Action = ButtonUpgradeTo; } else if (!strcmp(value, "unload")) { ba.Action = ButtonUnload; } else if (!strcmp(value, "cancel")) { ba.Action = ButtonCancel; } else if (!strcmp(value, "cancel-upgrade")) { ba.Action = ButtonCancelUpgrade; } else if (!strcmp(value, "cancel-train-unit")) { ba.Action = ButtonCancelTrain; } else if (!strcmp(value, "cancel-build")) { ba.Action = ButtonCancelBuild; } else { LuaError(l, "Unsupported button action: %s" _C_ value); } } else if (!strcmp(value, "Value")) { if (!lua_isnumber(l, -1) && !lua_isstring(l, -1)) { LuaError(l, "incorrect argument"); } char buf[64]; const char *s2; if (lua_isnumber(l, -1)) { snprintf(buf, sizeof(buf), "%ld", (long int)lua_tonumber(l, -1)); s2 = buf; } else { s2 = lua_tostring(l, -1); } ba.ValueStr = s2; } else if (!strcmp(value, "Allowed")) { value = LuaToString(l, -1); if (!strcmp(value, "check-true")) { ba.Allowed = ButtonCheckTrue; } else if (!strcmp(value, "check-false")) { ba.Allowed = ButtonCheckFalse; } else if (!strcmp(value, "check-upgrade")) { ba.Allowed = ButtonCheckUpgrade; } else if (!strcmp(value, "check-unit-variable")) { ba.Allowed = ButtonCheckUnitVariable; } else if (!strcmp(value, "check-units-or")) { ba.Allowed = ButtonCheckUnitsOr; } else if (!strcmp(value, "check-units-and")) { ba.Allowed = ButtonCheckUnitsAnd; } else if (!strcmp(value, "check-units-not")) { ba.Allowed = ButtonCheckUnitsNot; } else if (!strcmp(value, "check-network")) { ba.Allowed = ButtonCheckNetwork; } else if (!strcmp(value, "check-no-network")) { ba.Allowed = ButtonCheckNoNetwork; } else if (!strcmp(value, "check-no-work")) { ba.Allowed = ButtonCheckNoWork; } else if (!strcmp(value, "check-no-research")) { ba.Allowed = ButtonCheckNoResearch; } else if (!strcmp(value, "check-attack")) { ba.Allowed = ButtonCheckAttack; } else if (!strcmp(value, "check-upgrade-to")) { ba.Allowed = ButtonCheckUpgradeTo; } else if (!strcmp(value, "check-research")) { ba.Allowed = ButtonCheckResearch; } else if (!strcmp(value, "check-single-research")) { ba.Allowed = ButtonCheckSingleResearch; } else { LuaError(l, "Unsupported action: %s" _C_ value); } } else if (!strcmp(value, "AllowArg")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } std::string allowstr; const unsigned int subargs = lua_rawlen(l, -1); for (unsigned int k = 0; k < subargs; ++k) { const char *s2 = LuaToString(l, -1, k + 1); allowstr += s2; if (k != subargs - 1) { allowstr += ","; } } ba.AllowStr = allowstr; } else if (!strcmp(value, "Key")) { ba.Key = *LuaToString(l, -1); } else if (!strcmp(value, "Hint")) { ba.Hint = LuaToString(l, -1); } else if (!strcmp(value, "Description")) { ba.Description = LuaToString(l, -1); } else if (!strcmp(value, "CommentSound")) { ba.CommentSound.Name = LuaToString(l, -1); } else if (!strcmp(value, "ButtonCursor")) { ba.ButtonCursor = LuaToString(l, -1); } else if (!strcmp(value, "Popup")) { ba.Popup = LuaToString(l, -1); } else if (!strcmp(value, "ForUnit")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } // FIXME: ba.UnitMask shouldn't be a string std::string umask = ","; const unsigned subargs = lua_rawlen(l, -1); for (unsigned int k = 0; k < subargs; ++k) { const char *s2 = LuaToString(l, -1, k + 1); umask += s2; umask += ","; } ba.UnitMask = umask; if (!strncmp(ba.UnitMask.c_str(), ",*,", 3)) { ba.UnitMask = "*"; } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } lua_pop(l, 1); } AddButton(ba.Pos, ba.Level, ba.Icon.Name, ba.Action, ba.ValueStr, ba.Allowed, ba.AllowStr, ba.Key, ba.Hint, ba.Description, ba.CommentSound.Name, ba.ButtonCursor, ba.UnitMask, ba.Popup, ba.AlwaysShow); return 0; }
/* * Arguments: ..., directory (string) */ static int sys_dir_open (lua_State *L, const int idx, struct dir *dp) { const char *dir = luaL_checkstring(L, idx); #ifndef _WIN32 if (dp->data) closedir(dp->data); sys_vm_leave(L); dp->data = opendir(*dir == '\0' ? "/" : dir); sys_vm_enter(L); if (dp->data) return 1; #else char *filename = (char *) dp->data.cFileName; if (*dir == '\0' || (*dir == '/' && dir[1] == '\0')) { /* list drive letters */ *filename++ = 'A' - 1; *filename++ = ':'; *filename++ = '\\'; *filename = '\0'; dp->is_root = 1; return 1; } else { const int len = lua_rawlen(L, idx); /* build search path */ if (len >= MAX_PATH - 2) /* concat "\\*" */ return 0; memcpy(filename, dir, len); filename += len - 1; if (*filename != '\\' && *filename != '/') *(++filename) = '\\'; *(++filename) = '*'; *(++filename) = '\0'; if (dp->h != INVALID_HANDLE_VALUE) FindClose(dp->h); { void *os_path = utf8_to_filename((char *) dp->data.cFileName); if (!os_path) return sys_seterror(L, ERROR_NOT_ENOUGH_MEMORY); sys_vm_leave(L); dp->h = is_WinNT ? FindFirstFileW(os_path, &dp->data) : FindFirstFileA(os_path, (WIN32_FIND_DATAA *) &dp->data); free(os_path); sys_vm_enter(L); } if (dp->h != INVALID_HANDLE_VALUE) { dp->is_root = 0; return 1; } } #endif return sys_seterror(L, 0); }
static int openssl_ssl_ctx_verify_mode(lua_State*L) { SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx"); if (lua_gettop(L) > 1) { size_t i; int mode = 0; luaL_checktable(L, 2); for (i = 0; i < lua_rawlen(L, 2); i++) { lua_rawgeti(L, 2, i + 1); mode |= auxiliar_checkoption(L, -1, NULL, sVerifyMode_Options, iVerifyMode_Options); lua_pop(L, 1); } luaL_argcheck(L, lua_isnoneornil(L, 3) || lua_isfunction(L, 3), 3, "must be function callback"); if (lua_isfunction(L, 3)) { lua_pushvalue(L, 3); openssl_setvalue(L, ctx, "verify_cb"); SSL_CTX_set_verify(ctx, mode, openssl_verify_cb); } else { SSL_CTX_set_verify(ctx, mode, openssl_verify_cb); } return 0; } else { int i = 0; int mode = SSL_CTX_get_verify_mode(ctx); lua_pushinteger(L, mode); i += 1; if (mode == SSL_VERIFY_NONE) { lua_pushstring(L, "none"); i += 1; } else { if (mode & SSL_VERIFY_PEER) { lua_pushstring(L, "peer"); i += 1; } if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) { lua_pushstring(L, "fail_if_no_peer_cert"); i += 1; } if (mode & SSL_VERIFY_CLIENT_ONCE) { lua_pushstring(L, "client_once"); i += 1; } } return i; } return 0; }
static int lsettext(lua_State *L) { struct sprite *s = self(L); if (s->type != TYPE_LABEL) { return luaL_error(L, "Only label can set rich text"); } if (lua_isnoneornil(L, 2)) { s->data.rich_text = NULL; lua_pushnil(L); lua_setuservalue(L, 1); return 0; } if (lua_isstring(L, 2)) { s->data.rich_text = (struct rich_text*)lua_newuserdata(L, sizeof(struct rich_text)); s->data.rich_text->text = lua_tostring(L, 2); s->data.rich_text->count = 0; s->data.rich_text->fields = NULL; lua_createtable(L, 2, 0); lua_pushvalue(L, 2); lua_rawseti(L, -2, 1); lua_pushvalue(L, 3); lua_rawseti(L, -2, 2); lua_setuservalue(L, 1); return 0; } s->data.rich_text = NULL; if (!lua_istable(L, 2) || lua_rawlen(L, 2) != 2) { return luaL_error(L, "rich text must has a table with two items"); } lua_rawgeti(L, 2, 1); const char *txt = luaL_checkstring(L, -1); lua_pop(L, 1); lua_rawgeti(L, 2, 2); int cnt = lua_rawlen(L, -1); lua_pop(L, 1); struct rich_text *rich = (struct rich_text*)lua_newuserdata(L, sizeof(struct rich_text)); rich->text = txt; rich->count = cnt; int size = cnt * sizeof(struct label_field); rich->fields = (struct label_field*)lua_newuserdata(L, size); struct label_field *fields = rich->fields; int i; lua_rawgeti(L, 2, 2); for (i=0; i<cnt; i++) { lua_rawgeti(L, -1, i+1); if (!lua_istable(L,-1)) { return luaL_error(L, "rich text unit must be table"); } lua_rawgeti(L, -1, 1); //start ((struct label_field*)(fields+i))->start = luaL_checkinteger(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 2); //end ((struct label_field*)(fields+i))->end = luaL_checkinteger(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 3); //color ((struct label_field*)(fields+i))->color = luaL_checkunsigned(L, -1); lua_pop(L, 1); //extend here lua_pop(L, 1); } lua_pop(L, 1); lua_createtable(L,3,0); lua_pushvalue(L, 3); lua_rawseti(L, -2, 1); lua_pushvalue(L, 4); lua_rawseti(L, -2, 2); lua_rawgeti(L, 2, 1); lua_rawseti(L, -2, 3); lua_setuservalue(L, 1); s->data.rich_text = rich; return 0; }
static int lzlib_compress(lua_State *L) { const char *next_in = luaL_checkstring(L, 1); int avail_in = lua_rawlen(L, 1); int level = luaL_optint(L, 2, Z_DEFAULT_COMPRESSION); int method = luaL_optint(L, 3, Z_DEFLATED); int windowBits = luaL_optint(L, 4, 15); int memLevel = luaL_optint(L, 5, 8); int strategy = luaL_optint(L, 6, Z_DEFAULT_STRATEGY); int ret; z_stream zs; luaL_Buffer b; luaL_buffinit(L, &b); zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.next_out = Z_NULL; zs.avail_out = 0; zs.next_in = Z_NULL; zs.avail_in = 0; ret = deflateInit2(&zs, level, method, windowBits, memLevel, strategy); if (ret != Z_OK) { lua_pushnil(L); lua_pushnumber(L, ret); return 2; } zs.next_in = (Bytef*)next_in; zs.avail_in = avail_in; for(;;) { zs.next_out = (Bytef*)luaL_prepbuffer(&b); zs.avail_out = LUAL_BUFFERSIZE; /* munch some more */ ret = deflate(&zs, Z_FINISH); /* push gathered data */ luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out); /* done processing? */ if (ret == Z_STREAM_END) break; /* error condition? */ if (ret != Z_OK) break; } /* cleanup */ deflateEnd(&zs); luaL_pushresult(&b); lua_pushnumber(L, ret); return 2; }
/** ** Define helper for AI. ** ** @param l Lua state. ** ** @todo FIXME: the first unit could be a list see ../doc/ccl/ai.html */ static int CclDefineAiHelper(lua_State *l) { InitAiHelper(AiHelpers); const int args = lua_gettop(l); for (int j = 0; j < args; ++j) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); int k = 0; lua_rawgeti(l, j + 1, k + 1); const char *value = LuaToString(l, -1); lua_pop(l, 1); ++k; // // Type build,train,research/upgrade. // int what; if (!strcmp(value, "build")) { what = -1; } else if (!strcmp(value, "train")) { what = -1; } else if (!strcmp(value, "upgrade")) { what = -1; } else if (!strcmp(value, "research")) { what = -1; } else if (!strcmp(value, "unit-limit")) { what = -1; } else if (!strcmp(value, "unit-equiv")) { what = 5; } else if (!strcmp(value, "repair")) { what = -1; } else { LuaError(l, "unknown tag: %s" _C_ value); what = -1; } if (what == -1) { continue; } // // Get the base unit type, which could handle the action. // // FIXME: support value as list! lua_rawgeti(l, j + 1, k + 1); value = LuaToString(l, -1); lua_pop(l, 1); ++k; CUnitType *base = UnitTypeByIdent(value); if (!base) { LuaError(l, "unknown unittype: %s" _C_ value); } // // Get the unit types, which could be produced // for (; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); value = LuaToString(l, -1); lua_pop(l, 1); CUnitType *type = UnitTypeByIdent(value); if (!type) { LuaError(l, "unknown unittype: %s" _C_ value); } AiHelperInsert(AiHelpers.Equiv, base->Slot, *type); AiNewUnitTypeEquiv(base, type); } } return 0; }
int pdf_new_string(lua_State *L) { const char* s = luaL_checkstring(L, 1); int l = lua_rawlen(L, 1); lua_pushlightuserdata(L, texpdf_new_string(s, l)); return 1; }
static int luv_spawn(lua_State* L) { uv_process_t* handle; uv_process_options_t options; size_t i, len = 0; int ret; memset(&options, 0, sizeof(options)); options.exit_cb = exit_cb; options.file = luaL_checkstring(L, 1); options.flags = 0; // Make sure the 2nd argument is a table luaL_checktype(L, 2, LUA_TTABLE); // get the args list lua_getfield(L, 2, "args"); // +1 for inserted command at front if (lua_type(L, -1) == LUA_TTABLE) { len = 1 + lua_rawlen(L, -1); } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 3, "args option must be table"); } else { len = 1; } // +1 for null terminator at end options.args = malloc((len + 1) * sizeof(*options.args)); if (!options.args) { luv_clean_options(&options); return luaL_error(L, "Problem allocating args"); } options.args[0] = (char*)options.file; for (i = 1; i < len; ++i) { lua_rawgeti(L, -1, i); options.args[i] = (char*)lua_tostring(L, -1); lua_pop(L, 1); } options.args[len] = NULL; lua_pop(L, 1); // get the stdio list lua_getfield(L, 2, "stdio"); if (lua_type(L, -1) == LUA_TTABLE) { options.stdio_count = len = lua_rawlen(L, -1); options.stdio = malloc(len * sizeof(*options.stdio)); if (!options.stdio) { luv_clean_options(&options); return luaL_error(L, "Problem allocating stdio"); } for (i = 0; i < len; ++i) { lua_rawgeti(L, -1, i + 1); // integers are assumed to be file descripters if (lua_type(L, -1) == LUA_TNUMBER) { options.stdio[i].flags = UV_INHERIT_FD; options.stdio[i].data.fd = lua_tointeger(L, -1); } // userdata is assumed to be a uv_stream_t instance else if (lua_type(L, -1) == LUA_TUSERDATA) { uv_os_fd_t fd; uv_stream_t* stream = luv_check_stream(L, -1); int err = uv_fileno((uv_handle_t*)stream, &fd); if (err == UV_EINVAL || err == UV_EBADF) { options.stdio[i].flags = UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE; } else { options.stdio[i].flags = UV_INHERIT_STREAM; } options.stdio[i].data.stream = stream; } else if (lua_type(L, -1) == LUA_TNIL) { options.stdio[i].flags = UV_IGNORE; } else { luv_clean_options(&options); return luaL_argerror(L, 2, "stdio table entries must be nil, uv_stream_t, or integer"); } lua_pop(L, 1); } } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "stdio option must be table"); } lua_pop(L, 1); // Get the env lua_getfield(L, 2, "env"); if (lua_type(L, -1) == LUA_TTABLE) { len = lua_rawlen(L, -1); options.env = malloc((len + 1) * sizeof(*options.env)); if (!options.env) { luv_clean_options(&options); return luaL_error(L, "Problem allocating env"); } for (i = 0; i < len; ++i) { lua_rawgeti(L, -1, i + 1); options.env[i] = (char*)lua_tostring(L, -1); lua_pop(L, 1); } options.env[len] = NULL; } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "env option must be table"); } lua_pop(L, 1); // Get the cwd lua_getfield(L, 2, "cwd"); if (lua_type(L, -1) == LUA_TSTRING) { options.cwd = (char*)lua_tostring(L, -1); } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "cwd option must be string"); } lua_pop(L, 1); // Check for uid lua_getfield(L, 2, "uid"); if (lua_type(L, -1) == LUA_TNUMBER) { options.uid = lua_tointeger(L, -1); options.flags |= UV_PROCESS_SETUID; } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "uid option must be number"); } lua_pop(L, 1); // Check for gid lua_getfield(L, 2, "gid"); if (lua_type(L, -1) == LUA_TNUMBER) { options.gid = lua_tointeger(L, -1); options.flags |= UV_PROCESS_SETGID; } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "gid option must be number"); } lua_pop(L, 1); // Check for the boolean flags lua_getfield(L, 2, "verbatim"); if (lua_toboolean(L, -1)) { options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; } lua_pop(L, 1); lua_getfield(L, 2, "detached"); if (lua_toboolean(L, -1)) { options.flags |= UV_PROCESS_DETACHED; } lua_pop(L, 1); lua_getfield(L, 2, "hide"); if (lua_toboolean(L, -1)) { options.flags |= UV_PROCESS_WINDOWS_HIDE; } lua_pop(L, 1); handle = lua_newuserdata(L, sizeof(*handle)); handle->type = UV_PROCESS; handle->data = luv_setup_handle(L); if (!lua_isnoneornil(L, 3)) { luv_check_callback(L, handle->data, LUV_EXIT, 3); } ret = uv_spawn(luv_loop(L), handle, &options); luv_clean_options(&options); if (ret < 0) { /* The async callback is required here because luajit GC may reclaim the * luv handle before libuv is done closing it down. */ uv_close((uv_handle_t*)handle, luv_spawn_close_cb); return luv_error(L, ret); } lua_pushinteger(L, handle->pid); return 2; }
static void lua_to_image(lua_State * L, image * a, image_dict * d) { int i, t; const char *s; s = lua_tostring(L,-2); t = lua_type(L, -1); if (lua_key_eq(s,width)) { if (t == LUA_TNIL) { set_wd_running(a); } else if (t == LUA_TNUMBER) { img_width(a) = (int) lua_roundnumber(L, -1); } else if (t == LUA_TSTRING) { img_width(a) = dimen_to_number(L, lua_tostring(L, -1)); } else { luaL_error(L, "image.width needs integer or nil value or dimension string"); } } else if (lua_key_eq(s,height)) { if (t == LUA_TNIL) { set_ht_running(a); } else if (t == LUA_TNUMBER) { img_height(a) = (int) lua_roundnumber(L, -1); } else if (t == LUA_TSTRING) { img_height(a) = dimen_to_number(L, lua_tostring(L, -1)); } else { luaL_error(L, "image.height needs integer or nil value or dimension string"); } } else if (lua_key_eq(s,depth)) { if (t == LUA_TNIL) { set_dp_running(a); } else if (t == LUA_TNUMBER) { img_depth(a) = (int) lua_roundnumber(L, -1); } else if (t == LUA_TSTRING) { img_depth(a) = dimen_to_number(L, lua_tostring(L, -1)); } else { luaL_error(L, "image.depth needs integer or nil value or dimension string"); } } else if (lua_key_eq(s,transform)) { if (t == LUA_TNUMBER) { img_transform(a) = (int) lua_tointeger(L, -1); } else { luaL_error(L, "image.transform needs integer value"); } } else if (lua_key_eq(s,filename)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.filename is now read-only"); } else if (img_type(d) == IMG_TYPE_PDFSTREAM) { luaL_error(L, "image.filename can't be used with image.stream"); } else if (t == LUA_TSTRING) { xfree(img_filename(d)); img_filename(d) = xstrdup(lua_tostring(L, -1)); } else { luaL_error(L, "image.filename needs string value"); } } else if (lua_key_eq(s,visiblefilename)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.visiblefilename is now read-only"); } else if (img_type(d) == IMG_TYPE_PDFSTREAM) { luaL_error(L, "image.visiblefilename can't be used with image.stream"); } else if (t == LUA_TSTRING) { xfree(img_visiblefilename(d)); img_visiblefilename(d) = xstrdup(lua_tostring(L, -1)); } else { luaL_error(L, "image.visiblefilename needs string value"); } } else if (lua_key_eq(s,attr)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.attr is now read-only"); } else if (t == LUA_TSTRING) { xfree(img_attr(d)); img_attr(d) = xstrdup(lua_tostring(L, -1)); } else if (t == LUA_TNIL) { xfree(img_attr(d)); } else { luaL_error(L, "image.attr needs string or nil value"); } } else if (lua_key_eq(s,page)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.page is now read-only"); } else if (t == LUA_TSTRING) { xfree(img_pagename(d)); img_pagename(d) = xstrdup(lua_tostring(L, -1)); img_pagenum(d) = 0; } else if (t == LUA_TNUMBER) { img_pagenum(d) = (int) lua_tointeger(L, -1); xfree(img_pagename(d)); } else { luaL_error(L, "image.page needs integer or string value"); } } else if (lua_key_eq(s,colorspace)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.colorspace is now read-only"); } else if (t == LUA_TNIL) { img_colorspace(d) = 0; } else if (t == LUA_TNUMBER) { img_colorspace(d) = (int) lua_tointeger(L, -1); } else { luaL_error(L, "image.colorspace needs integer or nil value"); } } else if (lua_key_eq(s,pagebox)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.pagebox is now read-only"); } else if (t == LUA_TNIL) { img_pagebox(d) = PDF_BOX_SPEC_MEDIA; } else if (t == LUA_TNUMBER) { i = lua_tointeger(L,-1); if (i < 0 || i >= img_pageboxes_max) { img_pagebox(d) = PDF_BOX_SPEC_MEDIA; } else { img_pagebox(d) = i; } } else if (t == LUA_TSTRING) { img_pagebox(d) = PDF_BOX_SPEC_MEDIA; for (i = 0; i < img_pageboxes_max; i++) { lua_rawgeti(L, LUA_REGISTRYINDEX, img_pageboxes[i]); if (lua_rawequal(L,-1,-2)) { img_pagebox(d) = i; lua_pop(L, 1); break; } else { lua_pop(L, 1); } } } else { luaL_error(L, "image.pagebox needs string, number or nil value"); } } else if (lua_key_eq(s,keepopen)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.keepopen is now read-only"); } else if (t != LUA_TBOOLEAN) { luaL_error(L, "image.bbox needs boolean value"); } else { img_keepopen(d) = lua_toboolean(L, -1); } } else if (lua_key_eq(s,bbox)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.bbox is now read-only"); } else if (t != LUA_TTABLE) { luaL_error(L, "image.bbox needs table value"); } else if (lua_rawlen(L, -1) != 4) { luaL_error(L, "image.bbox table must have exactly 4 elements"); } else { for (i = 1; i <= 4; i++) { /* v k t ... */ lua_pushinteger(L, i); /* idx v k t ... */ lua_gettable(L, -2); /* int v k t ... */ t = lua_type(L, -1); if (t == LUA_TNUMBER) { img_bbox(d)[i - 1] = (int) lua_roundnumber(L, -1); } else if (t == LUA_TSTRING) { img_bbox(d)[i - 1] = dimen_to_number(L, lua_tostring(L, -1)); } else { luaL_error(L, "image.bbox table needs integer value or dimension string elements"); } lua_pop(L, 1); /* v k t ... */ } img_set_bbox(d); } } else if (lua_key_eq(s,stream)) { if (img_filename(d) != NULL) { luaL_error(L, "image.stream can't be used with image.filename"); } else if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.stream is now read-only"); } else { if (img_pdfstream_ptr(d) == NULL) { new_img_pdfstream_struct(d); } xfree(img_pdfstream_stream(d)); img_pdfstream_stream(d) = xstrdup(lua_tostring(L, -1)); img_type(d) = IMG_TYPE_PDFSTREAM; } } else { luaL_error(L, "image.%s can not be set", s); } }
std::size_t LuaState::LengthRaw(int index) const { return lua_rawlen(m_state, index); }
// 1 string data // 2 result document table // return boolean succ (false -> request id, error document) // number request_id // document first // string cursor_id // integer startfrom static int op_reply(lua_State *L) { size_t data_len = 0; const char * data = luaL_checklstring(L,1,&data_len); struct { // int32_t length; // total message size, including this int32_t request_id; // identifier for this message int32_t response_id; // requestID from the original request // (used in reponses from db) int32_t opcode; // request type int32_t flags; int32_t cursor_id[2]; int32_t starting; int32_t number; } const *reply = (const void *)data; if (data_len < sizeof(*reply)) { lua_pushboolean(L, 0); return 1; } int id = little_endian(reply->response_id); int flags = little_endian(reply->flags); if (flags & REPLY_QUERYFAILURE) { lua_pushboolean(L,0); lua_pushinteger(L, id); lua_pushlightuserdata(L, (void *)(reply+1)); return 3; } int starting_from = little_endian(reply->starting); int number = little_endian(reply->number); int sz = (int)data_len - sizeof(*reply); const uint8_t * doc = (const uint8_t *)(reply+1); if (lua_istable(L,2)) { int i = 1; while (sz > 4) { lua_pushlightuserdata(L, (void *)doc); lua_rawseti(L, 2, i); int32_t doc_len = get_length((const document)doc); doc += doc_len; sz -= doc_len; ++i; } if (i != number + 1) { lua_pushboolean(L,0); lua_pushinteger(L, id); return 2; } int c = lua_rawlen(L, 2); for (;i<=c;i++) { lua_pushnil(L); lua_rawseti(L, 2, i); } } lua_pushboolean(L,1); lua_pushinteger(L, id); if (number == 0) lua_pushnil(L); else lua_pushlightuserdata(L, (void *)(reply+1)); if (reply->cursor_id[0] == 0 && reply->cursor_id[1]==0) { // closed cursor lua_pushnil(L); } else { lua_pushlstring(L, (const char *)(reply->cursor_id), 8); } lua_pushinteger(L, starting_from); return 5; }
int _define_ship(lua_State *L, ShipType::Tag tag, std::vector<ShipType::Id> *list) { if (s_currentShipFile.empty()) return luaL_error(L, "ship file contains multiple ship definitions"); ShipType s; s.tag = tag; s.id = s_currentShipFile; LUA_DEBUG_START(L); LuaTable t(L, -1); s.name = t.Get("name", ""); s.shipClass = t.Get("ship_class", "unknown"); s.manufacturer = t.Get("manufacturer", "unknown"); s.modelName = t.Get("model", ""); s.cockpitName = t.Get("cockpit", ""); s.linThrust[ShipType::THRUSTER_REVERSE] = t.Get("reverse_thrust", 0.0f); s.linThrust[ShipType::THRUSTER_FORWARD] = t.Get("forward_thrust", 0.0f); s.linThrust[ShipType::THRUSTER_UP] = t.Get("up_thrust", 0.0f); s.linThrust[ShipType::THRUSTER_DOWN] = t.Get("down_thrust", 0.0f); s.linThrust[ShipType::THRUSTER_LEFT] = t.Get("left_thrust", 0.0f); s.linThrust[ShipType::THRUSTER_RIGHT] = t.Get("right_thrust", 0.0f); s.angThrust = t.Get("angular_thrust", 0.0f); // invert values where necessary s.linThrust[ShipType::THRUSTER_FORWARD] *= -1.f; s.linThrust[ShipType::THRUSTER_LEFT] *= -1.f; s.linThrust[ShipType::THRUSTER_DOWN] *= -1.f; // angthrust fudge (XXX: why?) s.angThrust = s.angThrust / 2; lua_pushstring(L, "camera_offset"); lua_gettable(L, -2); if (!lua_isnil(L, -1)) Output("ship definition for '%s' has deprecated 'camera_offset' field\n", s.id.c_str()); lua_pop(L, 1); s.cameraOffset = t.Get("camera_offset", vector3d(0.0)); for (int i=0; i<Equip::SLOT_MAX; i++) s.equipSlotCapacity[i] = 0; s.equipSlotCapacity[Equip::SLOT_CARGO] = t.Get("max_cargo", 0); s.equipSlotCapacity[Equip::SLOT_ENGINE] = t.Get("max_engine", 1); s.equipSlotCapacity[Equip::SLOT_LASER] = t.Get("max_laser", 1); s.equipSlotCapacity[Equip::SLOT_MISSILE] = t.Get("max_missile", 0); s.equipSlotCapacity[Equip::SLOT_ECM] = t.Get("max_ecm", 1); s.equipSlotCapacity[Equip::SLOT_SCANNER] = t.Get("max_scanner", 1); s.equipSlotCapacity[Equip::SLOT_RADARMAPPER] = t.Get("max_radarmapper", 1); s.equipSlotCapacity[Equip::SLOT_HYPERCLOUD] = t.Get("max_hypercloud", 1); s.equipSlotCapacity[Equip::SLOT_HULLAUTOREPAIR] = t.Get("max_hullautorepair", 1); s.equipSlotCapacity[Equip::SLOT_ENERGYBOOSTER] = t.Get("max_energybooster", 1); s.equipSlotCapacity[Equip::SLOT_ATMOSHIELD] = t.Get("max_atmoshield", 1); s.equipSlotCapacity[Equip::SLOT_CABIN] = t.Get("max_cabin", 50); s.equipSlotCapacity[Equip::SLOT_SHIELD] = t.Get("max_shield", 9999); s.equipSlotCapacity[Equip::SLOT_FUELSCOOP] = t.Get("max_fuelscoop", 1); s.equipSlotCapacity[Equip::SLOT_CARGOSCOOP] = t.Get("max_cargoscoop", 1); s.equipSlotCapacity[Equip::SLOT_LASERCOOLER] = t.Get("max_lasercooler", 1); s.equipSlotCapacity[Equip::SLOT_CARGOLIFESUPPORT] = t.Get("max_cargolifesupport", 1); s.equipSlotCapacity[Equip::SLOT_AUTOPILOT] = t.Get("max_autopilot", 1); s.capacity = t.Get("capacity", 0); s.hullMass = t.Get("hull_mass", 100); s.fuelTankMass = t.Get("fuel_tank_mass", 5); LuaTable slot_table = t.Sub("slots"); if (slot_table.GetLua()) { s.slots = slot_table.GetMap<std::string, int>(); } lua_pop(L, 1); // fuel_use_rate can be given in two ways float thruster_fuel_use = 0; s.effectiveExhaustVelocity = t.Get("effective_exhaust_velocity", -1.0f); thruster_fuel_use = t.Get("thruster_fuel_use", -1.0f); if(s.effectiveExhaustVelocity < 0 && thruster_fuel_use < 0) { // default value of v_c is used s.effectiveExhaustVelocity = 55000000; } else if(s.effectiveExhaustVelocity < 0 && thruster_fuel_use >= 0) { // v_c undefined and thruster fuel use defined -- use it! s.effectiveExhaustVelocity = GetEffectiveExhaustVelocity(s.fuelTankMass, thruster_fuel_use, s.linThrust[ShipType::THRUSTER_FORWARD]); } else { if(thruster_fuel_use >= 0) Output("Warning: Both thruster_fuel_use and effective_exhaust_velocity defined for %s, using effective_exhaust_velocity.\n", s.modelName.c_str()); } s.baseprice = t.Get("price", 0); s.baseprice *= 100; // in hundredths of credits s.minCrew = t.Get("min_crew", 1); s.maxCrew = t.Get("max_crew", 1); s.equipSlotCapacity[Equip::SLOT_ENGINE] = Clamp(s.equipSlotCapacity[Equip::SLOT_ENGINE], 0, 1); s.hyperdriveClass = t.Get("hyperdrive_class", 1); for (int i = 0; i < ShipType::GUNMOUNT_MAX; i++) { s.gunMount[i].pos = vector3f(0,0,0); s.gunMount[i].dir = vector3f(0,0,1); s.gunMount[i].sep = 5; s.gunMount[i].orient = ShipType::DUAL_LASERS_HORIZONTAL; } lua_pushstring(L, "gun_mounts"); lua_gettable(L, -2); if (lua_istable(L, -1)) { Output("ship definition for '%s' has deprecated 'gun_mounts' field\n", s.id.c_str()); for (unsigned int i=0; i<lua_rawlen(L,-1); i++) { lua_pushinteger(L, i+1); lua_gettable(L, -2); if (lua_istable(L, -1) && lua_rawlen(L,-1) == 4) { lua_pushinteger(L, 1); lua_gettable(L, -2); s.gunMount[i].pos = LuaVector::CheckFromLuaF(L, -1); lua_pop(L, 1); lua_pushinteger(L, 2); lua_gettable(L, -2); s.gunMount[i].dir = LuaVector::CheckFromLuaF(L, -1); lua_pop(L, 1); lua_pushinteger(L, 3); lua_gettable(L, -2); s.gunMount[i].sep = lua_tonumber(L,-1); lua_pop(L, 1); lua_pushinteger(L, 4); lua_gettable(L, -2); s.gunMount[i].orient = static_cast<ShipType::DualLaserOrientation>( LuaConstants::GetConstantFromArg(L, "DualLaserOrientation", -1)); lua_pop(L, 1); } lua_pop(L, 1); } } lua_pop(L, 1); LUA_DEBUG_END(L, 0); //sanity check if (s.name.empty()) return luaL_error(L, "Ship has no name"); if (s.modelName.empty()) return luaL_error(L, "Missing model name in ship"); if (s.minCrew < 1 || s.maxCrew < 1 || s.minCrew > s.maxCrew) return luaL_error(L, "Invalid values for min_crew and max_crew"); const std::string& id = s_currentShipFile; typedef std::map<ShipType::Id, ShipType>::iterator iter; std::pair<iter, bool> result = ShipType::types.insert(std::make_pair(id, s)); if (result.second) list->push_back(s_currentShipFile); else return luaL_error(L, "Ship '%s' was already defined by a different file", id.c_str()); s_currentShipFile.clear(); return 0; }
static int zip_openfile (lua_State *L) { ZZIP_FILE** inf; const char * ext2[LUAZIP_MAX_EXTENSIONS+1]; zzip_strings_t *ext = ext2; const char *filename = luaL_checkstring(L, 1); /*const char *mode = luaL_optstring(L, 2, "r");*/ inf = newinternalfile(L); if (lua_isstring(L, 2)) { /* creates a table with the string as the first and only (numerical) element */ lua_newtable(L); lua_pushvalue(L, 2); lua_rawseti(L, -2, 1); /* replaces the string by the table with the string inside */ lua_replace(L, 2); } if (lua_istable(L, 2)) { unsigned i, m, n; /* how many extension were specified? */ #if LUA_VERSION_NUM < 501 n = luaL_getn(L, 2); #else n = lua_rawlen(L, 2); #endif if (n > LUAZIP_MAX_EXTENSIONS) { luaL_error(L, "too many extensions specified"); } for (i = 0, m = 0; i < n; i++) { lua_rawgeti(L, 2, i+1); if (lua_isstring(L, -1)) { /* luazip specifies "zip" as the extension, but zziplib expects ".zip" */ lua_pushstring(L, "."); lua_insert(L, -2); lua_concat(L, 2); ext2[m] = lua_tostring(L, -1); m++; } lua_pop(L, 1); } ext2[m] = 0; *inf = zzip_open_ext_io(filename, 0, 0664, ext, 0); } else { *inf = zzip_open(filename, 0); } if (*inf) return 1; lua_pushnil(L); lua_pushfstring(L, "could not open file `%s'", filename); return 2; }
static int update (lua_State *p_L) { int _return; int _i,_j; int _id; _id = luaL_checkint( p_L, 1 ); // set producer vars()[_id] for ( _i=0; _i<(int)vars()[_id].size(); _i++ ) { if ( vars()[_id][_i]->com == PRODUCER ) { lua_settop( p_L, 0 ); ostringstream _oss; _oss << "return " << vars()[_id][_i]->var << ";"; luaL_dostring( p_L, _oss.str().c_str() ); if ( vars()[_id][_i]->queuing == 0 ) { switch ( vars()[_id][_i]->type ) { case TYPE_INT: if ( lua_isnumber( p_L, -1 ) ) { vars()[_id][_i]->value._i = (int)lua_tonumber( p_L, -1 ); } break; case TYPE_FLOAT: if ( lua_isnumber( p_L, -1 ) ) { vars()[_id][_i]->value._f = (float)lua_tonumber( p_L, -1 ); } break; case TYPE_STRING: if ( lua_isstring( p_L, -1 ) ) { if ( vars()[_id][_i]->value._s != 0 ) { delete [] vars()[_id][_i]->value._s; } string _value = lua_tostring( p_L, -1 ); vars()[_id][_i]->value._s = new char[ _value.length() + 1 ]; strcpy( vars()[_id][_i]->value._s, _value.c_str() ); } break; } } else if ( lua_istable( p_L, -1 ) ) // queuing producer { int _oldSize = vars()[_id][_i]->size; vars()[_id][_i]->size = lua_rawlen( p_L, -1 ); switch ( vars()[_id][_i]->type ) { case TYPE_INT: if ( vars()[_id][_i]->value._qi != 0 ) { delete [] vars()[_id][_i]->value._qi; } vars()[_id][_i]->value._qi = new int[ vars()[_id][_i]->size ]; for ( _j=0; _j<vars()[_id][_i]->size; _j++ ) { lua_pushnumber( p_L, _j+1 ); lua_gettable( p_L, -2 ); if ( lua_isnumber( p_L, -1 ) ) { vars()[_id][_i]->value._qi[ _j ] = (int)lua_tonumber( p_L, -1 ); } lua_pop( p_L, 1 ); } break; case TYPE_FLOAT: if ( vars()[_id][_i]->value._qf != 0 ) { delete [] vars()[_id][_i]->value._qf; } vars()[_id][_i]->value._qf = new float[ vars()[_id][_i]->size ]; for ( _j=0; _j<vars()[_id][_i]->size; _j++ ) { lua_pushnumber( p_L, _j+1 ); lua_gettable( p_L, -2 ); if ( lua_isnumber( p_L, -1 ) ) { vars()[_id][_i]->value._qf[ _j ] = (float)lua_tonumber( p_L, -1 ); } lua_pop( p_L, 1 ); } break; case TYPE_STRING: if ( vars()[_id][_i]->value._qs != 0 ) { for ( _j=0; _j<_oldSize; _j++ ) { delete [] vars()[_id][_i]->value._qs[ _j ]; } free( vars()[_id][_i]->value._qs ); } vars()[_id][_i]->value._qs = (char**)malloc( sizeof(char*) * vars()[_id][_i]->size ); for ( _j=0; _j<vars()[_id][_i]->size; _j++ ) { lua_pushnumber( p_L, _j+1 ); lua_gettable( p_L, -2 ); if ( lua_isstring( p_L, -1 ) ) { string _value = lua_tostring( p_L, -1 ); vars()[_id][_i]->value._qs[ _j ] = new char[ _value.size() + 1 ]; strcpy( vars()[_id][_i]->value._qs[ _j ], _value.c_str() ); } lua_pop( p_L, 1 ); } break; } ostringstream _emptyLuaVar; _emptyLuaVar << vars()[_id][_i]->var << "={};"; luaL_dostring( p_L, _emptyLuaVar.str().c_str() ); } lua_pop( p_L, 1 ); } } _return = WESBMessenger_update_full( _id ); lua_pushnumber( p_L, _return ); // get consummer vars()[_id] for ( _i=0; _i<(int)vars()[_id].size(); _i++ ) { if ( vars()[_id][_i]->com == CONSUMER ) { ostringstream _oss; _oss << vars()[_id][_i]->var << "="; if ( vars()[_id][_i]->queuing == 0 ) { switch ( vars()[_id][_i]->type ) { case TYPE_INT: _oss << vars()[_id][_i]->value._i; break; case TYPE_FLOAT: _oss << vars()[_id][_i]->value._f; break; case TYPE_STRING: _oss << "\"" << str_replace("\n", "", str_replace( "\"", "\\\"", vars()[_id][_i]->value._s )) << "\""; break; } } else { _oss << "{"; switch ( vars()[_id][_i]->type ) { case TYPE_INT: for ( _j=0; _j<vars()[_id][_i]->size; _j++) { if ( _j > 0 ) { _oss << ","; } _oss << ((int*)vars()[_id][_i]->value._qi)[_j]; } break; case TYPE_FLOAT: for ( _j=0; _j<vars()[_id][_i]->size; _j++) { if ( _j > 0 ) { _oss << ","; } _oss << ((float*)vars()[_id][_i]->value._qf)[_j]; } break; case TYPE_STRING: for ( _j=0; _j<vars()[_id][_i]->size; _j++) { if ( _j > 0 ) { _oss << ","; } string _tmp = ((char**)vars()[_id][_i]->value._qs)[_j]; _tmp = str_replace( "\"", "\\\"", _tmp ); _tmp = str_replace("\n", "", _tmp); _oss << "\"" << _tmp.c_str() << "\""; } break; } _oss << "}"; } _oss << ";"; luaL_dostring( p_L,_oss.str().c_str() ); } } return 1; }
/** ** Default title screens. ** ** @param l Lua state. */ static int CclSetTitleScreens(lua_State *l) { if (TitleScreens) { for (int i = 0; TitleScreens[i]; ++i) { delete TitleScreens[i]; } delete[] TitleScreens; TitleScreens = NULL; } const int args = lua_gettop(l); TitleScreens = new TitleScreen *[args + 1]; memset(TitleScreens, 0, (args + 1) * sizeof(TitleScreen *)); for (int j = 0; j < args; ++j) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } TitleScreens[j] = new TitleScreen; TitleScreens[j]->Iterations = 1; lua_pushnil(l); while (lua_next(l, j + 1)) { const char *value = LuaToString(l, -2); if (!strcmp(value, "Image")) { TitleScreens[j]->File = LuaToString(l, -1); } else if (!strcmp(value, "Music")) { TitleScreens[j]->Music = LuaToString(l, -1); } else if (!strcmp(value, "Timeout")) { TitleScreens[j]->Timeout = LuaToNumber(l, -1); } else if (!strcmp(value, "Iterations")) { TitleScreens[j]->Iterations = LuaToNumber(l, -1); } else if (!strcmp(value, "Editor")) { TitleScreens[j]->Editor = LuaToNumber(l, -1); } else if (!strcmp(value, "Labels")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); TitleScreens[j]->Labels = new TitleScreenLabel *[subargs + 1]; memset(TitleScreens[j]->Labels, 0, (subargs + 1) * sizeof(TitleScreenLabel *)); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, -1, k + 1); if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } TitleScreens[j]->Labels[k] = new TitleScreenLabel; lua_pushnil(l); while (lua_next(l, -2)) { const char *value = LuaToString(l, -2); if (!strcmp(value, "Text")) { TitleScreens[j]->Labels[k]->Text = LuaToString(l, -1); } else if (!strcmp(value, "Font")) { TitleScreens[j]->Labels[k]->Font = CFont::Get(LuaToString(l, -1)); } else if (!strcmp(value, "Pos")) { CclGetPos(l, &TitleScreens[j]->Labels[k]->Xofs, &TitleScreens[j]->Labels[k]->Yofs); } else if (!strcmp(value, "Flags")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subsubargs = lua_rawlen(l, -1); for (int subk = 0; subk < subsubargs; ++subk) { const char *value = LuaToString(l, -1, subk + 1); if (!strcmp(value, "center")) { TitleScreens[j]->Labels[k]->Flags |= TitleFlagCenter; } else { LuaError(l, "incorrect flag"); } } } else { LuaError(l, "Unsupported key: %s" _C_ value); } lua_pop(l, 1); } lua_pop(l, 1); } } else { LuaError(l, "Unsupported key: %s" _C_ value); } lua_pop(l, 1); } } return 0; }