static const char *getobjname (lua_State *L, StkId obj, const char **name) { StkId func = aux_stackedfunction(L, 0, obj); if (!isLmark(func)) return NULL; /* not an active Lua function */ else { Proto *p = infovalue(func)->func->f.l; int pc = currentpc(func); int stackpos = obj - (func+1); /* func+1 == function base */ Instruction i = luaG_symbexec(p, pc, stackpos); LUA_ASSERT(pc != -1, "function must be active"); switch (GET_OPCODE(i)) { case OP_GETGLOBAL: { *name = p->kstr[GETARG_U(i)]->str; return "global"; } case OP_GETLOCAL: { *name = luaF_getlocalname(p, GETARG_U(i)+1, pc); LUA_ASSERT(*name, "local must exist"); return "local"; } case OP_PUSHSELF: case OP_GETDOTTED: { *name = p->kstr[GETARG_U(i)]->str; return "field"; } default: return NULL; /* no useful name found */ } } }
/* copied from ldebug.c */ int luaG_getline (int *lineinfo, int pc, int refline, int *prefi) { int refi; if (lineinfo == NULL || pc == -1) return -1; /* no line info or function is not active */ refi = prefi ? *prefi : 0; if (lineinfo[refi] < 0) refline += -lineinfo[refi++]; LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info"); while (lineinfo[refi] > pc) { refline--; refi--; if (lineinfo[refi] < 0) refline -= -lineinfo[refi--]; LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info"); } for (;;) { int nextline = refline + 1; int nextref = refi + 1; if (lineinfo[nextref] < 0) nextline += -lineinfo[nextref++]; LUA_ASSERT(lineinfo[nextref] >= 0, "invalid line info"); if (lineinfo[nextref] > pc) break; refline = nextline; refi = nextref; } if (prefi) *prefi = refi; return refline; }
static int Vector2_New(lua_State* aLuaState) { float x = 0.f; float y = 0.f; int nrOfArguments = lua_gettop(aLuaState)-1; if(nrOfArguments == 0 || nrOfArguments == 2) { if(nrOfArguments == 2) { x = (float)(lua_tonumber(aLuaState,-2)); y = (float)(lua_tonumber(aLuaState,-1)); } } else { LUA_ASSERT(aLuaState,"Too many or too few arguments in Vector declaration"); } lua_pop(aLuaState,3); lua_newtable(aLuaState); lua_pushstring(aLuaState,"x"); lua_pushnumber(aLuaState,x); lua_settable(aLuaState,-3); lua_pushstring(aLuaState,"y"); lua_pushnumber(aLuaState,y); lua_settable(aLuaState,-3); luaL_getmetatable(aLuaState,"Vector2"); lua_setmetatable(aLuaState,-2); return 1; }
/* ** returns the `main' position of an element in a table (that is, the index ** of its hash value) */ Node *luaH_mainposition (const Hash *t, const TObject *key) { unsigned h; switch (ttype(key)) { case LUA_TNUMBER: h = (unsigned)(int)nvalue(key); break; case LUA_TSTRING: h = tsvalue(key)->u.s.hash; break; case LUA_TUSERDATA: h = IntPoint(tsvalue(key)); break; case LUA_TTABLE: h = IntPoint(hvalue(key)); break; case LUA_TFUNCTION: h = IntPoint(clvalue(key)); break; default: return NULL; /* invalid key */ } LUA_ASSERT(h%(unsigned int)t->size == (h&((unsigned int)t->size-1)), "a&(x-1) == a%x, for x power of 2"); return &t->node[h&(t->size-1)]; }
static void invalidaterefs (lua_State *L) { int n = L->refSize; int i; for (i=0; i<n; i++) { struct Ref *r = &L->refArray[i]; if (r->st == HOLD && !hasmark(&r->o)) r->st = COLLECTED; LUA_ASSERT((r->st == LOCK && hasmark(&r->o)) || (r->st == HOLD && hasmark(&r->o)) || r->st == COLLECTED || r->st == NONEXT || (r->st < n && VALIDLINK(L, L->refArray[r->st].st, n)), "inconsistent ref table"); } LUA_ASSERT(VALIDLINK(L, L->refFree, n), "inconsistent ref table"); }
LUA_API void lua_unref (lua_State *L, int ref) { if (ref >= 0) { LUA_ASSERT(ref < L->refSize && L->refArray[ref].st < 0, "invalid ref"); L->refArray[ref].st = L->refFree; L->refFree = ref; } }
static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { int prevpos; /* position of last instruction */ Instruction *previous; int *golist, *exitlist; if (!invert) { golist = &v->u.l.f; /* go if false */ exitlist = &v->u.l.t; /* exit if true */ } else { golist = &v->u.l.t; /* go if true */ exitlist = &v->u.l.f; /* exit if false */ } discharge1(fs, v); prevpos = fs->pc-1; previous = &fs->f->code[prevpos]; LUA_ASSERT(*previous==previous_instruction(fs), "no jump allowed here"); if (!ISJUMP(GET_OPCODE(*previous))) prevpos = luaK_code1(fs, jump, NO_JUMP); else { /* last instruction is already a jump */ if (invert) SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); } luaK_concat(fs, exitlist, prevpos); /* insert last jump in `exitlist' */ luaK_patchlist(fs, *golist, luaK_getlabel(fs)); *golist = NO_JUMP; }
static int Vector2_Normalize(lua_State* aLuaState) { int nrOfArguments = lua_gettop(aLuaState)-1; float length; float x; float y; if(nrOfArguments > 0) { LUA_ASSERT(aLuaState,"Vector2.Normalize should not take any arguments"); } Vector2_Length(aLuaState); length = (float)lua_tonumber(aLuaState,-1); lua_getfield(aLuaState,-2,"x"); x = (float)lua_tonumber(aLuaState,-1); lua_getfield(aLuaState,-3,"y"); y = (float)lua_tonumber(aLuaState,-1); lua_pop(aLuaState,3); lua_pushstring(aLuaState,"x"); lua_pushnumber(aLuaState,x/length); lua_settable(aLuaState,-3); lua_pushstring(aLuaState,"y"); lua_pushnumber(aLuaState,y/length); lua_settable(aLuaState,-3); return 0; }
static int world_load_level(lua_State* L) { LuaStack stack(L); StringId64 name = stack.get_resource_id(2); LUA_ASSERT(device()->resource_manager()->can_get(LEVEL_TYPE, name), stack, "Level not found"); stack.get_world(1)->load_level(name); return 0; }
static int currentpc (StkId f) { CallInfo *ci = infovalue(f); LUA_ASSERT(isLmark(f), "function has no pc"); if (ci->pc) return (*ci->pc - ci->func->f.l->code) - 1; else return -1; /* function is not active */ }
LUA_API void lua_rawseti (lua_State *L, int index, int n) { StkId o = Index(L, index); LUA_ASSERT(ttype(o) == LUA_TTABLE, "table expected"); *luaH_setint(L, hvalue(o), n) = *(L->top-1); markobject(L->top - 1, L, 0); L->top--; }
LUA_API void lua_rawset (lua_State *L, int index) { StkId t = Index(L, index); LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected"); *luaH_set(L, hvalue(t), L->top-2) = *(L->top-1); markobject(L->top - 1, L, 0); markobject(L->top - 2, L, 0); L->top -= 2; }
static int tolua_region_get_resource(lua_State * L) { region *r; const char *type; const resource_type *rtype; int result = 0; void * match; critbit_tree * cb = special_resources(); r = (region *)tolua_tousertype(L, 1, 0); LUA_ASSERT(r != NULL, "invalid parameter"); type = tolua_tostring(L, 2, 0); LUA_ASSERT(type != NULL, "invalid parameter"); if (cb_find_prefix(cb, type, strlen(type) + 1, &match, 1, 0)) { cb_get_kv(match, &result, sizeof(result)); switch (result) { case 0: case 1: case 2: result = rtrees(r, result); break; case 3: result = deathcount(r); break; case 4: result = get_chaoscount(r); break; } } else { rtype = rt_find(type); if (rtype) { result = region_getresource(r, rtype); } else { result = -1; } } lua_pushinteger(L, result); return 1; }
static void globalmark (void) { TaggedString *g; for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next){ LUA_ASSERT(g->constindex >= 0, "userdata in global list"); if (g->u.s.globalval.ttype != LUA_T_NIL) { markobject(&g->u.s.globalval); strmark(g); /* cannot collect non nil global variables */ } } }
static void dohook (lua_State *L, lua_Debug *ar, lua_Hook hook) { StkId old_Cbase = L->Cbase; StkId old_top = L->Cbase = L->top; luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ L->allowhooks = 0; /* cannot call hooks inside a hook */ (*hook)(L, ar); LUA_ASSERT(L->allowhooks == 0, "invalid allow"); L->allowhooks = 1; L->top = old_top; L->Cbase = old_Cbase; }
static int world_spawn_unit(lua_State* L) { LuaStack stack(L); World* world = stack.get_world(1); const StringId64 name = stack.get_resource_id(2); const Vector3& pos = stack.num_args() > 2 ? stack.get_vector3(3) : vector3::ZERO; const Quaternion& rot = stack.num_args() > 3 ? stack.get_quaternion(4) : quaternion::IDENTITY; LUA_ASSERT(device()->resource_manager()->can_get(UNIT_TYPE, name), stack, "Unit not found"); UnitId unit = world->spawn_unit(name, pos, rot); stack.push_unit(world->get_unit(unit)); return 1; }
static void *checkblock (void *block) { if (block == NULL) return NULL; else { unsigned long *b = blocksize(block); unsigned long size = *b; int i; for (i=0;i<MARKSIZE;i++) LUA_ASSERT(*(((char *)b)+HEADER+size+i) == MARK+i, "corrupted block"); numblocks--; totalmem -= size; return b; } }
/* * Bytecode optimization */ static int MapConstant(Hash* t, int j, const TObject* key) { const TObject* o=luaH_get(compile_lua_state,t,key); if (ttype(o)==LUA_TNUMBER) return (int) nvalue(o); else { TObject val; ttype(&val)=LUA_TNUMBER; nvalue(&val)=j; *luaH_set(compile_lua_state,t,key)=val; LUA_ASSERT(j>=0,"MapConstant returns negative!"); return j; } }
int luaO_equalval (const TObject *t1, const TObject *t2) { switch (ttype(t1)) { case TAG_NUMBER: return nvalue(t1) == nvalue(t2); case TAG_STRING: case TAG_USERDATA: return svalue(t1) == svalue(t2); case TAG_TABLE: return avalue(t1) == avalue(t2); case TAG_CCLOSURE: case TAG_LCLOSURE: return clvalue(t1) == clvalue(t2); default: LUA_ASSERT(L, ttype(t1) == TAG_NIL, "invalid type"); return 1; /* TAG_NIL */ } }
LUA_API int lua_next (lua_State *L, int index) { StkId t = luaA_index(L, index); Node *n; LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected"); n = luaH_next(L, hvalue(t), luaA_index(L, -1)); if (n) { *(L->top-1) = *key(n); *L->top = *val(n); api_incr_top(L); return 1; } else { /* no more elements */ L->top -= 1; /* remove key */ return 0; } }
static int world_play_sound(lua_State* L) { LuaStack stack(L); World* world = stack.get_world(1); const StringId64 name = stack.get_resource_id(2); const int32_t nargs = stack.num_args(); const bool loop = nargs > 2 ? stack.get_bool(3) : false; const float volume = nargs > 3 ? stack.get_float(4) : 1.0f; const Vector3& pos = nargs > 4 ? stack.get_vector3(5) : vector3::ZERO; const float range = nargs > 5 ? stack.get_float(6) : 1000.0f; LUA_ASSERT(device()->resource_manager()->can_get(SOUND_TYPE, name), stack, "Sound not found"); stack.push_sound_instance_id(world->play_sound(name, loop, volume, pos, range)); return 1; }
int luaO_equalObj (const TObject *t1, const TObject *t2) { if (ttype(t1) != ttype(t2)) return 0; switch (ttype(t1)) { case LUA_TNUMBER: return nvalue(t1) == nvalue(t2); case LUA_TSTRING: case LUA_TUSERDATA: return tsvalue(t1) == tsvalue(t2); case LUA_TTABLE: return hvalue(t1) == hvalue(t2); case LUA_TFUNCTION: return clvalue(t1) == clvalue(t2); default: LUA_ASSERT(ttype(t1) == LUA_TNIL, "invalid type"); return 1; /* LUA_TNIL */ } }
static int Vector2_GetNormalize(lua_State* aLuaState) { int nrOfArguments = lua_gettop(aLuaState)-1; if(nrOfArguments > 0) { LUA_ASSERT(aLuaState,"Vector2.GetNormalize should not take any arguments"); } lua_getfield(aLuaState,-1,"x"); lua_getfield(aLuaState,-2,"y"); Vector2_New(aLuaState); Vector2_Normalize(aLuaState); return 1; }
static int vector3box_get_value(lua_State* L) { LuaStack stack(L); Vector3& v = stack.get_vector3box(1); const char* s = stack.get_string(2); switch (s[0]) { case 'x': stack.push_float(v.x); return 1; case 'y': stack.push_float(v.y); return 1; case 'z': stack.push_float(v.z); return 1; default: LUA_ASSERT(false, stack, "Bad index: '%c'", s[0]); break; } return 0; }
static int vector3box_set_value(lua_State* L) { LuaStack stack(L); Vector3& v = stack.get_vector3box(1); const char* s = stack.get_string(2); const float value = stack.get_float(3); switch (s[0]) { case 'x': v.x = value; break; case 'y': v.y = value; break; case 'z': v.z = value; break; default: LUA_ASSERT(false, stack, "Bad index: '%c'", s[0]); break; } return 0; }
/* ** try to remove a key without value from a table. To avoid problems with ** hash, change `key' for a number with the same hash. */ void luaH_remove (Hash *t, TObject *key) { if (ttype(key) == LUA_TNUMBER || (ttype(key) == LUA_TSTRING && tsvalue(key)->len <= 30)) return; /* do not remove numbers nor small strings */ else { /* try to find a number `n' with the same hash as `key' */ Node *mp = luaH_mainposition(t, key); int n = mp - &t->node[0]; /* make sure `n' is not in `t' */ while (luaH_getnum(t, n) != &luaO_nilobject) { if (n >= MAX_INT - t->size) return; /* give up; (to avoid overflow) */ n += t->size; } ttype(key) = LUA_TNUMBER; nvalue(key) = n; LUA_ASSERT(luaH_mainposition(t, key) == mp, "cannot change hash"); } }
/* ** Call a function (C or Lua). The function to be called is at *func. ** The arguments are on the stack, right after the function. ** When returns, the results are on the stack, starting at the original ** function position. ** The number of results is nResults, unless nResults=LUA_MULTRET. */ void luaD_call (lua_State *L, StkId func, int nResults) { lua_Hook callhook; StkId firstResult; CallInfo ci; Closure *cl; if (ttype(func) != LUA_TFUNCTION) { /* `func' is not a function; check the `function' tag method */ Closure *tm = luaT_gettmbyObj(L, func, TM_FUNCTION); if (tm == NULL) luaG_typeerror(L, func, "call"); luaD_openstack(L, func); clvalue(func) = tm; /* tag method is the new function to be called */ ttype(func) = LUA_TFUNCTION; } cl = clvalue(func); ci.func = cl; infovalue(func) = &ci; ttype(func) = LUA_TMARK; callhook = L->callhook; if (callhook) luaD_callHook(L, func, callhook, "call"); firstResult = (cl->isC ? callCclosure(L, cl, func+1) : luaV_execute(L, cl, func+1)); if (callhook) /* same hook that was active at entry */ luaD_callHook(L, func, callhook, "return"); LUA_ASSERT(ttype(func) == LUA_TMARK, "invalid tag"); /* move results to `func' (to erase parameters and function) */ if (nResults == LUA_MULTRET) { while (firstResult < L->top) /* copy all results */ *func++ = *firstResult++; L->top = func; } else { /* copy at most `nResults' */ for (; nResults > 0 && firstResult < L->top; nResults--) *func++ = *firstResult++; L->top = func; for (; nResults > 0; nResults--) { /* if there are not enough results */ ttype(L->top) = LUA_TNIL; /* adjust the stack */ incr_top; /* must check stack space */ } } luaC_checkGC(L); }
/* ** open parts that may cause memory-allocation errors */ static void f_luaopen (lua_State *L, void *ud) { int stacksize = *(int *)ud; if (stacksize == 0) stacksize = DEFAULT_STACK_SIZE; else stacksize += LUA_MINSTACK; L->gt = luaH_new(L, 10); /* table of globals */ luaD_init(L, stacksize); luaS_init(L); luaX_init(L); luaT_init(L); lua_newtable(L); lua_ref(L, 1); /* create registry */ lua_register(L, LUA_ERRORMESSAGE, errormessage); #ifdef LUA_DEBUG luaB_opentests(L); if (lua_state == NULL) lua_state = L; /* keep first state to be opened */ #endif LUA_ASSERT(lua_gettop(L) == 0, "wrong API stack"); }
static void rehash (lua_State *L, Hash *t) { int oldsize = t->size; Node *nold = t->node; int nelems = numuse(t); int i; LUA_ASSERT(nelems<=oldsize, "wrong count"); if (nelems >= oldsize-oldsize/4) /* using more than 3/4? */ setnodevector(L, t, (lint32)oldsize*2); else if (nelems <= oldsize/4 && /* less than 1/4? */ oldsize > MINPOWER2) setnodevector(L, t, oldsize/2); else setnodevector(L, t, oldsize); for (i=0; i<oldsize; i++) { Node *old = nold+i; if (ttype(&old->val) != LUA_TNIL) *luaH_set(L, t, &old->key) = old->val; } luaM_free(L, nold); /* free old array */ }
static void invalidaterefs (lua_State *L) { int n = L->refSize; int i; for (i=0; i<n; i++) { struct Ref *r = &L->refArray[i]; if (r->st == HOLD && !hasmark(&r->o)) r->st = COLLECTED; /* ** this test must be disabled, since the refArray could have been ** modified during the garbage collection. LUA_ASSERT((r->st == LOCK && hasmark(&r->o)) || (r->st == HOLD && hasmark(&r->o)) || r->st == COLLECTED || r->st == NONEXT || (r->st < n && VALIDLINK(L, L->refArray[r->st].st, n)), "inconsistent ref table"); */ } LUA_ASSERT(VALIDLINK(L, L->refFree, n), "inconsistent ref table"); }