/* 创建一个4元数 mat.newQuaternion(x,y,z,w) mat.newQuaternion(mat3) mat.newQuaternion(axis,radian) axis是Vector3,radian是一个角度 mat.newQuaternion() */ static int newQuaternion(lua_State* L) { const char* meta = "mat.Quaternion"; if( lua_isnumber(L,1) ) { lua_bindComplete(L,meta,new Ogre::Quaternion( tonumber(1),tonumber(2),tonumber(3),tonumber(4) )); } else if( lua_isuserdata(L,1) ) { Ogre::Matrix3* m3 = (Ogre::Matrix3*)lua_isa(L,1,"Matrix3"); if( m3 ) { lua_bindComplete(L,meta,new Ogre::Quaternion(*m3)); } else { Ogre::Vector3* v3 = (Ogre::Vector3*)lua_cast(L,1,"Vector3"); if( v3 ) { lua_bindComplete(L,meta,new Ogre::Quaternion(Ogre::Radian(tonumber(2)),*v3)); } } } else { lua_bindComplete(L,meta,new Ogre::Quaternion()); } return 1; }
static void lll_forprep (lua_State *L, TValue *ra) { TValue *init = ra; TValue *plimit = ra + 1; TValue *pstep = ra + 2; lua_Integer ilimit; int stopnow; if (ttisinteger(init) && ttisinteger(pstep) && forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) { /* all values are integer */ lua_Integer initv = (stopnow ? 0 : ivalue(init)); setivalue(plimit, ilimit); setivalue(init, initv - ivalue(pstep)); } else { /* try making all values floats */ lua_Number ninit; lua_Number nlimit; lua_Number nstep; if (!tonumber(plimit, &nlimit)) luaG_runerror(L, "'for' limit must be a number"); setfltvalue(plimit, nlimit); if (!tonumber(pstep, &nstep)) luaG_runerror(L, "'for' step must be a number"); setfltvalue(pstep, nstep); if (!tonumber(init, &ninit)) luaG_runerror(L, "'for' initial value must be a number"); setfltvalue(init, luai_numsub(L, ninit, nstep)); } }
//处理两种情况,x,y,z和vec3 static Ogre::Vector3 get_vector3(lua_State* L,int n ) { if( lua_isnumber(L,n) ) { return Ogre::Vector3(tonumber(n),tonumber(n+1),tonumber(n+2)); } else { Ogre::Vector3* v3 = (Ogre::Vector3*)lua_cast(L,n,"Vector3"); if( v3 ) return *v3; } return Ogre::Vector3(); }
/* * Notes: split function into two copies, one with number checks + (init - step) + jmp, * and the other with the same number checks + slow error throwing code. */ void vm_OP_FORPREP_slow(lua_State *L, int a, int sbx) { TValue *base = L->base; TValue *ra = base + a; const TValue *init = ra; const TValue *plimit = ra+1; const TValue *pstep = ra+2; (void)sbx; if (!tonumber(init, ra)) luaG_runerror(L, LUA_QL("for") " initial value must be a number"); else if (!tonumber(plimit, ra+1)) luaG_runerror(L, LUA_QL("for") " limit must be a number"); else if (!tonumber(pstep, ra+2)) luaG_runerror(L, LUA_QL("for") " step must be a number"); }
LUA_API int lua_isnumber (lua_State *L, int idx) { #if LUA_REFCOUNT int ret; TObject n; const TObject *o = luaA_indexAcceptable(L, idx); setnilvalue2n(&n); ret = (o != NULL && tonumber(o, &n)); setnilvalue(&n); return ret; #else !LUA_REFCOUNT TObject n; const TObject *o = luaA_indexAcceptable(L, idx); return (o != NULL && tonumber(o, &n)); #endif LUA_REFCOUNT }
void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, TValue *res) { switch (op) { case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* operate only on integers */ lua_Integer i1; lua_Integer i2; if (tointeger(p1, &i1) && tointeger(p2, &i2)) { setivalue(res, intarith(L, op, i1, i2)); return; } else break; /* go to the end */ } #ifndef _KERNEL case LUA_OPDIV: case LUA_OPPOW: { /* operate only on floats */ lua_Number n1; lua_Number n2; if (tonumber(p1, &n1) && tonumber(p2, &n2)) { setfltvalue(res, numarith(L, op, n1, n2)); return; } else break; /* go to the end */ } #endif default: { /* other operations */ #ifndef _KERNEL lua_Number n1; lua_Number n2; if (ttisinteger(p1) && ttisinteger(p2)) { setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); return; } else if (tonumber(p1, &n1) && tonumber(p2, &n2)) { setfltvalue(res, numarith(L, op, n1, n2)); return; } #else /* _KERNEL */ lua_Integer i1; lua_Integer i2; if (tointeger(p1, &i1) && tointeger(p2, &i2)) { setivalue(res, intarith(L, op, i1, i2)); return; } #endif else break; /* go to the end */ } } /* could not perform raw operation; try metamethod */ lua_assert(L != NULL); /* should not fail when folding (compile time) */ luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD)); }
long int strtoi(char *s,int base,char **scan_end) { int sign,value,overflow = 0; long int result = 0,oldresult; /* Evaluate sign */ if (*s == '-') { sign = -1; s++; } else if (*s == '+') { sign = 1; s++; } else sign = 1; /* Skip trailing zeros */ while (*s == '0') s++; /* Convert number */ while (isnumber(*s,base)) { value = tonumber(*s++); if (value > base || value < 0) return(0); oldresult = result; result *= base; result += value; /* Detect overflow */ if (oldresult > result) overflow = 1; } if (scan_end != 0L) *scan_end = s; if (overflow) result = INT_MAX; result *= sign; return(result); }
l_noret luaG_opinterror (lua_State *L, const TValue *p1, const TValue *p2, const char *msg) { lua_Number temp; if (!tonumber(p1, &temp)) /* first operand is wrong? */ p2 = p1; /* now second is wrong */ luaG_typeerror(L, p2, msg); }
float lua_getnumber(lua_Object object) { if (object == LUA_NOOBJECT) return 0.0f; if (tonumber(Address(object))) return 0.0f; else return (nvalue(Address(object))); }
LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { TObject n; const TObject *o = luaA_indexAcceptable(L, idx); #if LUA_REFCOUNT setnilvalue2n(&n); if (o != NULL && tonumber(o, &n)) { lua_Number theNumber = nvalue(o); setnilvalue(&n); return theNumber; } #else !LUA_REFCOUNT if (o != NULL && tonumber(o, &n)) return nvalue(o); #endif LUA_REFCOUNT else return 0; }
LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { TObject n; const TObject *o = luaA_indexAcceptable(L, idx); if (o != NULL && tonumber(o, &n)) return nvalue(o); else return 0; }
int main() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); int ans,mod,now,len; now=1; int i=1; while(now<99999){ ban1[i]=tochar(now,ban0[i]); i++; now<<=1; } while(gets(str1) && (str1[0]!='\n') ){ gets(str2); //printf("1 %s %s 2\n",str1,str2); a=tonumber(str1); b=tonumber(str2); ans=a*b; now=1; //printf("%d %d %d \n",a,b,ans); while(b){ mod=b&1; b>>=1; len=ban1[now]; strcpy(tmp,ban0[now]); tmp[len++]=' '; if(mod){ tmp[len++]='*'; } while(len<34)tmp[len++]=' '; tmp[len]='\0'; printf("%s",tmp); len=tochar(a,tmp); printf("%s \n",tmp); now++; a<<=1; } tochar(ans,tmp); printf("The solution is: %s\n",tmp); } //getchar();getchar(); return 0; }
void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, StkId res, TMS event) { if (!luaT_callbinTM(L, p1, p2, res, event)) { switch (event) { case TM_CONCAT: luaG_concaterror(L, p1, p2); case TM_IDIV: case TM_BAND: case TM_BOR: case TM_BXOR: case TM_SHL: case TM_SHR: case TM_BNOT: { lua_Number dummy; if (tonumber(p1, &dummy) && tonumber(p2, &dummy)) luaG_tointerror(L, p1, p2); /* else go through */ } default: luaG_aritherror(L, p1, p2); } } }
LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) { lua_Number n; const TValue *o = index2addr(L, idx); int isnum = tonumber(o, &n); if (!isnum) n = 0; /* call to 'tonumber' may change 'n' even if it fails */ if (pisnum) *pisnum = isnum; return n; }
/* ** return false if folding can raise an error */ static int validop (int op, TValue *v1, TValue *v2) { lua_Number a, b; lua_Integer i; cast_void(a); cast_void(b); /* macro may not use its arguments */ if (luai_numinvalidop(op, (cast_void(tonumber(v1, &a)), a), (cast_void(tonumber(v2, &b)), b))) return 0; switch (op) { case LUA_OPIDIV: /* division by 0 and conversion errors */ return (tointeger(v1, &i) && tointeger(v2, &i) && i != 0); case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: /* conversion errors */ return (tointeger(v1, &i) && tointeger(v2, &i)); case LUA_OPMOD: /* integer module by 0 */ return !(ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) == 0); default: return 1; /* everything else is valid */ } }
/* ** try to convert a non-integer value to an integer */ int luaV_tointeger_ (const TValue *obj, lua_Integer *p) { lua_Number n; lua_assert(!ttisinteger(obj)); if (tonumber(obj, &n)) { n = l_floor(n); return luaV_numtointeger(n, p); } else return 0; }
void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, StkId res, TMS event) { if (!luaT_callbinTM(L, p1, p2, res, event)) { switch (event) { case TM_CONCAT: luaG_concaterror(L, p1, p2); /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ case TM_BAND: case TM_BOR: case TM_BXOR: case TM_SHL: case TM_SHR: case TM_BNOT: { lua_Number dummy; if (tonumber(p1, &dummy) && tonumber(p2, &dummy)) luaG_tointerror(L, p1, p2); else luaG_opinterror(L, p1, p2, "perform bitwise operation on"); } /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ default: luaG_opinterror(L, p1, p2, "perform arithmetic on"); } } }
LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) { TValue n; const TValue *o = index2addr(L, idx); if (tonumber(o, &n)) { if (isnum) *isnum = 1; return nvalue(o); } else { if (isnum) *isnum = 0; return 0; } }
/* Lua可以用3种方法创建一个Vec3向量 v = mat.newVec3() v = mat.newVec3(x,y,z) v = mat.newVec3(v3) */ static int newVec3(lua_State* L) { const char* meta = "mat.Vector3"; if( lua_isnumber(L,1) ) { lua_bindComplete(L,meta,new Ogre::Vector3( tonumber(1),tonumber(2),tonumber(3))); } else if( lua_isuserdata(L,1) ) { Ogre::Vector3* v3 = (Ogre::Vector3*)lua_cast(L,1,"Vector3"); if( v3 ) { lua_bindComplete(L,meta,new Ogre::Vector3(*v3)); } } else { lua_bindComplete(L,meta,new Ogre::Vector3(Ogre::Vector3::ZERO)); } return 1; }
int main () { int n, width; char *buffer = myalloc(100); char *s = myalloc(100); printf("Please input a number \n"); getLine(buffer, 100); n = tonumber(buffer); printf("Please enter a width\n"); getLine(buffer, 100); width = tonumber(buffer); printf("Setting number to fit width now... \n"); itoa(n, s, width); printf("Padded number is %s \n", s); myfree(buffer); myfree(s); return 0; }
int main(){ int i; char buffer[100]; printf("Please enter an integer\n"); getLine(buffer, 100); i = tonumber (buffer); buffer[0] = '\0'; tostring(i, buffer); printf("The number is %s \n", buffer); return 0; }
int main() { int start[9]; int i; int product; struct node *tree = NULL; for (i = 0; i < 9; i++) start[i] = i+1; while (next(start, 9)) { product = tonumber(start+5, 4); if (product == tonumber(start, 1) * tonumber(start+1, 4) || product == tonumber(start, 2) * tonumber(start+2, 3) || product == tonumber(start, 3) * tonumber(start+3, 2) || product == tonumber(start, 4) * tonumber(start+4, 1)) tree = insert(tree, product); } printf("%d\n", sum_tree(tree)); return 0; }
LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *isnum) { TValue n; const TValue *o = index2addr(L, idx); if (tonumber(o, &n)) { lua_Unsigned res; lua_Number num = nvalue(o); lua_number2unsigned(res, num); if (isnum) *isnum = 1; return res; } else { if (isnum) *isnum = 0; return 0; } }
LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) { TValue n; const TValue *o = index2addr(L, idx); if (tonumber(o, &n)) { lua_Integer res; lua_Number num = nvalue(o); lua_number2integer(res, num); if (isnum) *isnum = 1; return res; } else { if (isnum) *isnum = 0; return 0; } }
/* ** Try to convert a 'for' limit to an integer, preserving the ** semantics of the loop. ** (The following explanation assumes a non-negative step; it is valid ** for negative steps mutatis mutandis.) ** If the limit can be converted to an integer, rounding down, that is ** it. ** Otherwise, check whether the limit can be converted to a number. If ** the number is too large, it is OK to set the limit as LUA_MAXINTEGER, ** which means no limit. If the number is too negative, the loop ** should not run, because any initial integer value is larger than the ** limit. So, it sets the limit to LUA_MININTEGER. 'stopnow' corrects ** the extreme case when the initial value is LUA_MININTEGER, in which ** case the LUA_MININTEGER limit would still run the loop once. */ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, int *stopnow) { *stopnow = 0; /* usually, let loops run */ if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */ lua_Number n; /* try to convert to float */ if (!tonumber(obj, &n)) /* cannot convert to float? */ return 0; /* not a number */ if (luai_numlt(0, n)) { /* if true, float is larger than max integer */ *p = LUA_MAXINTEGER; if (step < 0) *stopnow = 1; } else { /* float is smaller than min integer */ *p = LUA_MININTEGER; if (step >= 0) *stopnow = 1; } } return 1; }
StkId luaV_execute (lua_State *L) { LClosure *cl; TObject *k; const Instruction *pc; callentry: /* entry point when calling new functions */ L->ci->u.l.pc = &pc; if (L->hookmask & LUA_MASKCALL) luaD_callhook(L, LUA_HOOKCALL, -1); retentry: /* entry point when returning to old functions */ lua_assert(L->ci->state == CI_SAVEDPC || L->ci->state == (CI_SAVEDPC | CI_CALLING)); L->ci->state = CI_HASFRAME; /* activate frame */ pc = L->ci->u.l.savedpc; cl = &clvalue(L->base - 1)->l; k = cl->p->k; /* main loop of interpreter */ for (;;) { const Instruction i = *pc++; StkId base, ra; if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { traceexec(L); if (L->ci->state & CI_YIELD) { /* did hook yield? */ L->ci->u.l.savedpc = pc - 1; L->ci->state = CI_YIELD | CI_SAVEDPC; return NULL; } } /* warning!! several calls may realloc the stack and invalidate `ra' */ base = L->base; ra = RA(i); lua_assert(L->ci->state & CI_HASFRAME); lua_assert(base == L->ci->base); lua_assert(L->top <= L->stack + L->stacksize && L->top >= base); lua_assert(L->top == L->ci->top || GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO); switch (GET_OPCODE(i)) { case OP_MOVE: { setobjs2s(ra, RB(i)); break; } case OP_LOADK: { setobj2s(ra, KBx(i)); break; } case OP_LOADBOOL: { setbvalue(ra, GETARG_B(i)); if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ break; } case OP_LOADNIL: { TObject *rb = RB(i); do { setnilvalue(rb--); } while (rb >= ra); break; } case OP_GETUPVAL: { int b = GETARG_B(i); setobj2s(ra, cl->upvals[b]->v); break; } case OP_GETGLOBAL: { TObject *rb = KBx(i); const TObject *v; lua_assert(ttisstring(rb) && ttistable(&cl->g)); v = luaH_getstr(hvalue(&cl->g), tsvalue(rb)); if (!ttisnil(v)) { setobj2s(ra, v); } else setobj2s(XRA(i), luaV_index(L, &cl->g, rb, 0)); break; } case OP_GETTABLE: { StkId rb = RB(i); TObject *rc = RKC(i); if (ttistable(rb)) { const TObject *v = luaH_get(hvalue(rb), rc); if (!ttisnil(v)) { setobj2s(ra, v); } else setobj2s(XRA(i), luaV_index(L, rb, rc, 0)); } else setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0)); break; } case OP_SETGLOBAL: { lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g)); luaV_settable(L, &cl->g, KBx(i), ra); break; } case OP_SETUPVAL: { int b = GETARG_B(i); setobj(cl->upvals[b]->v, ra); /* write barrier */ break; } case OP_SETTABLE: { luaV_settable(L, ra, RKB(i), RKC(i)); break; } case OP_NEWTABLE: { int b = GETARG_B(i); b = fb2int(b); sethvalue(ra, luaH_new(L, b, GETARG_C(i))); luaC_checkGC(L); break; } case OP_SELF: { StkId rb = RB(i); TObject *rc = RKC(i); runtime_check(L, ttisstring(rc)); setobjs2s(ra+1, rb); if (ttistable(rb)) { const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc)); if (!ttisnil(v)) { setobj2s(ra, v); } else setobj2s(XRA(i), luaV_index(L, rb, rc, 0)); } else setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0)); break; } case OP_ADD: { TObject *rb = RKB(i); TObject *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { setnvalue(ra, nvalue(rb) + nvalue(rc)); } else Arith(L, ra, rb, rc, TM_ADD); break; } case OP_SUB: { TObject *rb = RKB(i); TObject *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { setnvalue(ra, nvalue(rb) - nvalue(rc)); } else Arith(L, ra, rb, rc, TM_SUB); break; } case OP_MUL: { TObject *rb = RKB(i); TObject *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { setnvalue(ra, nvalue(rb) * nvalue(rc)); } else Arith(L, ra, rb, rc, TM_MUL); break; } case OP_DIV: { TObject *rb = RKB(i); TObject *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { setnvalue(ra, nvalue(rb) / nvalue(rc)); } else Arith(L, ra, rb, rc, TM_DIV); break; } case OP_POW: { Arith(L, ra, RKB(i), RKC(i), TM_POW); break; } case OP_UNM: { const TObject *rb = RB(i); TObject temp; if (tonumber(rb, &temp)) { setnvalue(ra, -nvalue(rb)); } else { setnilvalue(&temp); if (!call_binTM(L, RB(i), &temp, ra, TM_UNM)) luaG_aritherror(L, RB(i), &temp); } break; } case OP_NOT: { int res = l_isfalse(RB(i)); /* next assignment may change this value */ setbvalue(ra, res); break; } case OP_CONCAT: { int b = GETARG_B(i); int c = GETARG_C(i); luaV_concat(L, c-b+1, c); /* may change `base' (and `ra') */ base = L->base; setobjs2s(RA(i), base+b); luaC_checkGC(L); break; } case OP_JMP: { dojump(pc, GETARG_sBx(i)); break; } case OP_EQ: { if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; else dojump(pc, GETARG_sBx(*pc) + 1); break; } case OP_LT: { if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; else dojump(pc, GETARG_sBx(*pc) + 1); break; } case OP_LE: { if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; else dojump(pc, GETARG_sBx(*pc) + 1); break; } case OP_TEST: { TObject *rb = RB(i); if (l_isfalse(rb) == GETARG_C(i)) pc++; else { setobjs2s(ra, rb); dojump(pc, GETARG_sBx(*pc) + 1); } break; } case OP_CALL: case OP_TAILCALL: { StkId firstResult; int b = GETARG_B(i); int nresults; if (b != 0) L->top = ra+b; /* else previous instruction set top */ nresults = GETARG_C(i) - 1; firstResult = luaD_precall(L, ra); if (firstResult) { if (firstResult > L->top) { /* yield? */ lua_assert(L->ci->state == (CI_C | CI_YIELD)); (L->ci - 1)->u.l.savedpc = pc; (L->ci - 1)->state = CI_SAVEDPC; return NULL; } /* it was a C function (`precall' called it); adjust results */ luaD_poscall(L, nresults, firstResult); if (nresults >= 0) L->top = L->ci->top; } else { /* it is a Lua function */ if (GET_OPCODE(i) == OP_CALL) { /* regular call? */ (L->ci-1)->u.l.savedpc = pc; /* save `pc' to return later */ (L->ci-1)->state = (CI_SAVEDPC | CI_CALLING); } else { /* tail call: put new frame in place of previous one */ int aux; base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */ ra = RA(i); if (L->openupval) luaF_close(L, base); for (aux = 0; ra+aux < L->top; aux++) /* move frame down */ setobjs2s(base+aux-1, ra+aux); (L->ci - 1)->top = L->top = base+aux; /* correct top */ lua_assert(L->ci->state & CI_SAVEDPC); (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc; (L->ci - 1)->u.l.tailcalls++; /* one more call lost */ (L->ci - 1)->state = CI_SAVEDPC; L->ci--; /* remove new frame */ L->base = L->ci->base; } goto callentry; } break; } case OP_RETURN: { CallInfo *ci = L->ci - 1; /* previous function frame */ int b = GETARG_B(i); if (b != 0) L->top = ra+b-1; lua_assert(L->ci->state & CI_HASFRAME); if (L->openupval) luaF_close(L, base); L->ci->state = CI_SAVEDPC; /* deactivate current function */ L->ci->u.l.savedpc = pc; /* previous function was running `here'? */ if (!(ci->state & CI_CALLING)) { lua_assert((ci->state & CI_C) || ci->u.l.pc != &pc); return ra; /* no: return */ } else { /* yes: continue its execution */ int nresults; lua_assert(ci->u.l.pc == &pc && ttisfunction(ci->base - 1) && (ci->state & CI_SAVEDPC)); lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL); nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1; luaD_poscall(L, nresults, ra); if (nresults >= 0) L->top = L->ci->top; goto retentry; } } case OP_FORLOOP: { lua_Number step, idx, limit; const TObject *plimit = ra+1; const TObject *pstep = ra+2; if (!ttisnumber(ra)) luaG_runerror(L, "`for' initial value must be a number"); if (!tonumber(plimit, ra+1)) luaG_runerror(L, "`for' limit must be a number"); if (!tonumber(pstep, ra+2)) luaG_runerror(L, "`for' step must be a number"); step = nvalue(pstep); idx = nvalue(ra) + step; /* increment index */ limit = nvalue(plimit); if (step > 0 ? idx <= limit : idx >= limit) { dojump(pc, GETARG_sBx(i)); /* jump back */ chgnvalue(ra, idx); /* update index */ } break; } case OP_TFORLOOP: { int nvar = GETARG_C(i) + 1; StkId cb = ra + nvar + 2; /* call base */ setobjs2s(cb, ra); setobjs2s(cb+1, ra+1); setobjs2s(cb+2, ra+2); L->top = cb+3; /* func. + 2 args (state and index) */ luaD_call(L, cb, nvar); L->top = L->ci->top; ra = XRA(i) + 2; /* final position of first result */ cb = ra + nvar; do { /* move results to proper positions */ nvar--; setobjs2s(ra+nvar, cb+nvar); } while (nvar > 0); if (ttisnil(ra)) /* break loop? */ pc++; /* skip jump (break loop) */ else dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */ break; } case OP_TFORPREP: { /* for compatibility only */ if (ttistable(ra)) { setobjs2s(ra+1, ra); setobj2s(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next"))); } dojump(pc, GETARG_sBx(i)); break; } case OP_SETLIST: case OP_SETLISTO: { int bc; int n; Table *h; runtime_check(L, ttistable(ra)); h = hvalue(ra); bc = GETARG_Bx(i); if (GET_OPCODE(i) == OP_SETLIST) n = (bc&(LFIELDS_PER_FLUSH-1)) + 1; else { n = L->top - ra - 1; L->top = L->ci->top; } bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */ for (; n > 0; n--) setobj2t(luaH_setnum(L, h, bc+n), ra+n); /* write barrier */ break; } case OP_CLOSE: { luaF_close(L, ra); break; } case OP_CLOSURE: { Proto *p; Closure *ncl; int nup, j; p = cl->p->p[GETARG_Bx(i)]; nup = p->nups; ncl = luaF_newLclosure(L, nup, &cl->g); ncl->l.p = p; for (j=0; j<nup; j++, pc++) { if (GET_OPCODE(*pc) == OP_GETUPVAL) ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)]; else { lua_assert(GET_OPCODE(*pc) == OP_MOVE); ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); } } setclvalue(ra, ncl); luaC_checkGC(L); break; } } } }
LUA_API int lua_isnumber (lua_State *L, int idx) { TValue n; const TValue *o = index2addr(L, idx); return tonumber(o, &n); }
/* ** Executes the given Lua function. Parameters are between [base,top). ** Returns n such that the the results are between [n,top). */ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { const Proto *const tf = cl->f.l; StkId top; /* keep top local, for performance */ const Instruction *pc = tf->code; TString **const kstr = tf->kstr; const lua_Hook linehook = L->linehook; infovalue(base-1)->pc = &pc; luaD_checkstack(L, tf->maxstacksize+EXTRA_STACK); if (tf->is_vararg) /* varargs? */ adjust_varargs(L, base, tf->numparams); else luaD_adjusttop(L, base, tf->numparams); top = L->top; /* main loop of interpreter */ for (;;) { const Instruction i = *pc++; if (linehook) traceexec(L, base, top, linehook); switch (GET_OPCODE(i)) { case OP_END: { L->top = top; return top; } case OP_RETURN: { L->top = top; return base+GETARG_U(i); } case OP_CALL: { int nres = GETARG_B(i); if (nres == MULT_RET) nres = LUA_MULTRET; L->top = top; luaD_call(L, base+GETARG_A(i), nres); top = L->top; break; } case OP_TAILCALL: { L->top = top; luaD_call(L, base+GETARG_A(i), LUA_MULTRET); return base+GETARG_B(i); } case OP_PUSHNIL: { int n = GETARG_U(i); LUA_ASSERT(n>0, "invalid argument"); do { ttype(top++) = LUA_TNIL; } while (--n > 0); break; } case OP_POP: { top -= GETARG_U(i); break; } case OP_PUSHINT: { ttype(top) = LUA_TNUMBER; nvalue(top) = (Number)GETARG_S(i); top++; break; } case OP_PUSHSTRING: { ttype(top) = LUA_TSTRING; tsvalue(top) = kstr[GETARG_U(i)]; top++; break; } case OP_PUSHNUM: { ttype(top) = LUA_TNUMBER; nvalue(top) = tf->knum[GETARG_U(i)]; top++; break; } case OP_PUSHNEGNUM: { ttype(top) = LUA_TNUMBER; nvalue(top) = -tf->knum[GETARG_U(i)]; top++; break; } case OP_PUSHUPVALUE: { *top++ = cl->upvalue[GETARG_U(i)]; break; } case OP_GETLOCAL: { *top++ = *(base+GETARG_U(i)); break; } case OP_GETGLOBAL: { L->top = top; *top = *luaV_getglobal(L, kstr[GETARG_U(i)]); top++; break; } case OP_GETTABLE: { L->top = top; top--; *(top-1) = *luaV_gettable(L, top-1); break; } case OP_GETDOTTED: { ttype(top) = LUA_TSTRING; tsvalue(top) = kstr[GETARG_U(i)]; L->top = top+1; *(top-1) = *luaV_gettable(L, top-1); break; } case OP_GETINDEXED: { *top = *(base+GETARG_U(i)); L->top = top+1; *(top-1) = *luaV_gettable(L, top-1); break; } case OP_PUSHSELF: { TObject receiver; receiver = *(top-1); ttype(top) = LUA_TSTRING; tsvalue(top++) = kstr[GETARG_U(i)]; L->top = top; *(top-2) = *luaV_gettable(L, top-2); *(top-1) = receiver; break; } case OP_CREATETABLE: { L->top = top; luaC_checkGC(L); hvalue(top) = luaH_new(L, GETARG_U(i)); ttype(top) = LUA_TTABLE; top++; break; } case OP_SETLOCAL: { *(base+GETARG_U(i)) = *(--top); break; } case OP_SETGLOBAL: { L->top = top; luaV_setglobal(L, kstr[GETARG_U(i)]); top--; break; } case OP_SETTABLE: { StkId t = top-GETARG_A(i); L->top = top; luaV_settable(L, t, t+1); top -= GETARG_B(i); /* pop values */ break; } case OP_SETLIST: { int aux = GETARG_A(i) * LFIELDS_PER_FLUSH; int n = GETARG_B(i); Hash *arr = hvalue(top-n-1); L->top = top-n; /* final value of `top' (in case of errors) */ for (; n; n--) *luaH_setint(L, arr, n+aux) = *(--top); break; } case OP_SETMAP: { int n = GETARG_U(i); StkId finaltop = top-2*n; Hash *arr = hvalue(finaltop-1); L->top = finaltop; /* final value of `top' (in case of errors) */ for (; n; n--) { top-=2; *luaH_set(L, arr, top) = *(top+1); } break; } case OP_ADD: { if (tonumber(top-2) || tonumber(top-1)) call_arith(L, top, TM_ADD); else nvalue(top-2) += nvalue(top-1); top--; break; } case OP_ADDI: { if (tonumber(top-1)) { ttype(top) = LUA_TNUMBER; nvalue(top) = (Number)GETARG_S(i); call_arith(L, top+1, TM_ADD); } else nvalue(top-1) += (Number)GETARG_S(i); break; } case OP_SUB: { if (tonumber(top-2) || tonumber(top-1)) call_arith(L, top, TM_SUB); else nvalue(top-2) -= nvalue(top-1); top--; break; } case OP_MULT: { if (tonumber(top-2) || tonumber(top-1)) call_arith(L, top, TM_MUL); else nvalue(top-2) *= nvalue(top-1); top--; break; } case OP_DIV: { if (tonumber(top-2) || tonumber(top-1)) call_arith(L, top, TM_DIV); else nvalue(top-2) /= nvalue(top-1); top--; break; } case OP_POW: { if (!call_binTM(L, top, TM_POW)) lua_error(L, "undefined operation"); top--; break; } case OP_CONCAT: { int n = GETARG_U(i); luaV_strconc(L, n, top); top -= n-1; L->top = top; luaC_checkGC(L); break; } case OP_MINUS: { if (tonumber(top-1)) { ttype(top) = LUA_TNIL; call_arith(L, top+1, TM_UNM); } else nvalue(top-1) = -nvalue(top-1); break; } case OP_NOT: { ttype(top-1) = (ttype(top-1) == LUA_TNIL) ? LUA_TNUMBER : LUA_TNIL; nvalue(top-1) = 1; break; } case OP_JMPNE: { top -= 2; if (!luaO_equalObj(top, top+1)) dojump(pc, i); break; } case OP_JMPEQ: { top -= 2; if (luaO_equalObj(top, top+1)) dojump(pc, i); break; } case OP_JMPLT: { top -= 2; if (luaV_lessthan(L, top, top+1, top+2)) dojump(pc, i); break; } case OP_JMPLE: { /* a <= b === !(b<a) */ top -= 2; if (!luaV_lessthan(L, top+1, top, top+2)) dojump(pc, i); break; } case OP_JMPGT: { /* a > b === (b<a) */ top -= 2; if (luaV_lessthan(L, top+1, top, top+2)) dojump(pc, i); break; } case OP_JMPGE: { /* a >= b === !(a<b) */ top -= 2; if (!luaV_lessthan(L, top, top+1, top+2)) dojump(pc, i); break; } case OP_JMPT: { if (ttype(--top) != LUA_TNIL) dojump(pc, i); break; } case OP_JMPF: { if (ttype(--top) == LUA_TNIL) dojump(pc, i); break; } case OP_JMPONT: { if (ttype(top-1) == LUA_TNIL) top--; else dojump(pc, i); break; } case OP_JMPONF: { if (ttype(top-1) != LUA_TNIL) top--; else dojump(pc, i); break; } case OP_JMP: { dojump(pc, i); break; } case OP_PUSHNILJMP: { ttype(top++) = LUA_TNIL; pc++; break; } case OP_FORPREP: { if (tonumber(top-1)) lua_error(L, "`for' step must be a number"); if (tonumber(top-2)) lua_error(L, "`for' limit must be a number"); if (tonumber(top-3)) lua_error(L, "`for' initial value must be a number"); if (nvalue(top-1) > 0 ? nvalue(top-3) > nvalue(top-2) : nvalue(top-3) < nvalue(top-2)) { /* `empty' loop? */ top -= 3; /* remove control variables */ dojump(pc, i); /* jump to loop end */ } break; } case OP_FORLOOP: { LUA_ASSERT(ttype(top-1) == LUA_TNUMBER, "invalid step"); LUA_ASSERT(ttype(top-2) == LUA_TNUMBER, "invalid limit"); if (ttype(top-3) != LUA_TNUMBER) lua_error(L, "`for' index must be a number"); nvalue(top-3) += nvalue(top-1); /* increment index */ if (nvalue(top-1) > 0 ? nvalue(top-3) > nvalue(top-2) : nvalue(top-3) < nvalue(top-2)) top -= 3; /* end loop: remove control variables */ else dojump(pc, i); /* repeat loop */ break; } case OP_LFORPREP: { Node *node; if (ttype(top-1) != LUA_TTABLE) lua_error(L, "`for' table must be a table"); node = luaH_next(L, hvalue(top-1), &luaO_nilobject); if (node == NULL) { /* `empty' loop? */ top--; /* remove table */ dojump(pc, i); /* jump to loop end */ } else { top += 2; /* index,value */ *(top-2) = *key(node); *(top-1) = *val(node); } break; } case OP_LFORLOOP: { Node *node; LUA_ASSERT(ttype(top-3) == LUA_TTABLE, "invalid table"); node = luaH_next(L, hvalue(top-3), top-2); if (node == NULL) /* end loop? */ top -= 3; /* remove table, key, and value */ else { *(top-2) = *key(node); *(top-1) = *val(node); dojump(pc, i); /* repeat loop */ } break; } case OP_CLOSURE: { L->top = top; luaV_Lclosure(L, tf->kproto[GETARG_A(i)], GETARG_B(i)); top = L->top; luaC_checkGC(L); break; } } } }
LUA_API int lua_isnumber (lua_State *L, int idx) { TObject n; const TObject *o = luaA_indexAcceptable(L, idx); return (o != NULL && tonumber(o, &n)); }
/* ** try to convert a value to an integer, rounding according to 'mode': ** mode == 0: accepts only integral values ** mode == 1: takes the floor of the number ** mode == 2: takes the ceil of the number */ int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { TValue v; again: #ifndef _KERNEL if (ttisfloat(obj)) { lua_Number n = fltvalue(obj); lua_Number f = l_floor(n); if (n != f) { /* not an integral value? */ if (mode == 0) return 0; /* fails if mode demands integral value */ else if (mode > 1) /* needs ceil? */ f += 1; /* convert floor to ceil (remember: n != f) */ } return lua_numbertointeger(f, p); } else if (ttisinteger(obj)) { #else /* _KERNEL */ if (ttisinteger(obj)) { UNUSED(mode); #endif *p = ivalue(obj); return 1; } else if (cvt2num(obj) && luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { obj = &v; goto again; /* convert result from 'luaO_str2num' to an integer */ } return 0; /* conversion failed */ } #ifndef _KERNEL /* ** Try to convert a 'for' limit to an integer, preserving the ** semantics of the loop. ** (The following explanation assumes a non-negative step; it is valid ** for negative steps mutatis mutandis.) ** If the limit can be converted to an integer, rounding down, that is ** it. ** Otherwise, check whether the limit can be converted to a number. If ** the number is too large, it is OK to set the limit as LUA_MAXINTEGER, ** which means no limit. If the number is too negative, the loop ** should not run, because any initial integer value is larger than the ** limit. So, it sets the limit to LUA_MININTEGER. 'stopnow' corrects ** the extreme case when the initial value is LUA_MININTEGER, in which ** case the LUA_MININTEGER limit would still run the loop once. */ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, int *stopnow) { *stopnow = 0; /* usually, let loops run */ if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */ lua_Number n; /* try to convert to float */ if (!tonumber(obj, &n)) /* cannot convert to float? */ return 0; /* not a number */ if (luai_numlt(0, n)) { /* if true, float is larger than max integer */ *p = LUA_MAXINTEGER; if (step < 0) *stopnow = 1; } else { /* float is smaller than min integer */ *p = LUA_MININTEGER; if (step >= 0) *stopnow = 1; } } return 1; }