// static already_AddRefed<Shmem::SharedMemory> Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, const IPC::Message& aDescriptor, id_t* aId, bool aProtect) { size_t size; size_t pageSize = SharedMemory::SystemPageSize(); // |2*pageSize| is for the front and back sentinels RefPtr<SharedMemory> segment = ReadSegment(aDescriptor, aId, &size, 2*pageSize); if (!segment) { return nullptr; } Header* header = GetHeader(segment); if (size != header->mSize) { // Deallocation should zero out the header, so check for that. if (header->mSize || header->mUnsafe || header->mMagic[0] || memcmp(header->mMagic, &header->mMagic[1], sizeof(header->mMagic)-1)) { NS_ERROR("Wrong size for this Shmem!"); } else { NS_WARNING("Shmem was deallocated"); } return nullptr; } // The caller of this function may not know whether the segment is // unsafe or not if (!header->mUnsafe && aProtect) Protect(segment); return segment.forget(); }
/*----------------------------------------------*/ PLH::MemoryProtect::MemoryProtect(void* Address, size_t Size, DWORD ProtectionFlags) { m_Address = Address; m_Size = Size; m_Flags = ProtectionFlags; Protect(m_Address, m_Size, m_Flags); }
MonoBoolean ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectUser (const gunichar2 *path, MonoError *error) { gboolean ret = FALSE; /* read/write to user, no access to everyone else */ ret = Protect (path, (S_IRUSR | S_IWUSR), S_IXUSR); return (MonoBoolean)ret; }
MonoBoolean ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectMachine (const gunichar2 *path, MonoError *error) { gboolean ret = FALSE; /* read/write to owner, read to everyone else */ ret = Protect (path, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), (S_IXUSR | S_IXGRP | S_IXOTH)); return (MonoBoolean)ret; }
// static Shmem::SharedMemory* Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, const IPC::Message& aDescriptor, id_t* aId, bool aProtect) { if (SHMEM_CREATED_MESSAGE_TYPE != aDescriptor.type()) NS_RUNTIMEABORT("expected 'shmem created' message"); void* iter = 0; SharedMemory::SharedMemoryType type; size_t size; if (!ShmemCreated::ReadInfo(&aDescriptor, &iter, aId, &size, &type)) return 0; SharedMemory* segment = 0; size_t pageSize = SharedMemory::SystemPageSize(); // |2*pageSize| is for the front and back sentinels size_t segmentSize = SharedMemory::PageAlignedSize(size + 2*pageSize); if (SharedMemory::TYPE_BASIC == type) { SharedMemoryBasic::Handle handle; if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) return 0; if (!SharedMemoryBasic::IsHandleValid(handle)) NS_RUNTIMEABORT("trying to open invalid handle"); segment = CreateSegment(segmentSize, handle); } #ifdef MOZ_HAVE_SHAREDMEMORYSYSV else if (SharedMemory::TYPE_SYSV == type) { SharedMemorySysV::Handle handle; if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) return 0; if (!SharedMemorySysV::IsHandleValid(handle)) NS_RUNTIMEABORT("trying to open invalid handle"); segment = CreateSegment(segmentSize, handle); } #endif else { NS_RUNTIMEABORT("unknown shmem type"); } if (!segment) return 0; // The caller of this function may not know whether the segment is // unsafe or not Header* header = GetHeader(segment); if (!header->mUnsafe && aProtect) Protect(segment); return segment; }
quad_float sqrt(const quad_float& y) { if (y.hi < 0.0) ArithmeticError("quad_float: square root of negative number"); if (y.hi == 0.0) return quad_float(0.0,0.0); double c; c = sqrt(y.hi); ForceToMem(&c); // This is fairly paranoid, but it doesn't cost too much. START_FIX DOUBLE p,q,hx,tx,u,uu,cc; DOUBLE t1; p = Protect(NTL_QUAD_FLOAT_SPLIT*c); hx = (c-p); hx = hx+p; tx = c-hx; p = Protect(hx*hx); q = Protect(hx*tx); q = q+q; u = p+q; uu = p-u; uu = uu+q; t1 = Protect(tx*tx); uu = uu+t1; cc = y.hi-u; cc = cc-uu; cc = cc+y.lo; t1 = c+c; cc = cc/t1; hx = c+cc; tx = c-hx; tx = tx+cc; END_FIX return quad_float(hx, tx); }
MonoBoolean ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectMachine (MonoString *path) { gboolean ret = FALSE; /* read/write to owner, read to everyone else */ #ifdef HOST_WIN32 ret = ProtectMachine (mono_string_chars (path)); #else ret = Protect (path, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), (S_IXUSR | S_IXGRP | S_IXOTH)); #endif return ret; }
MonoBoolean ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectUser (MonoString *path) { gboolean ret = FALSE; /* read/write to user, no access to everyone else */ #ifdef HOST_WIN32 ret = ProtectUser (mono_string_chars (path)); #else ret = Protect (path, (S_IRUSR | S_IWUSR), S_IXUSR); #endif return ret; }
// static already_AddRefed<Shmem::SharedMemory> Shmem::Alloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, size_t aNBytes, SharedMemoryType aType, bool aUnsafe, bool aProtect) { NS_ASSERTION(aNBytes <= UINT32_MAX, "Will truncate shmem segment size!"); MOZ_ASSERT(!aProtect || !aUnsafe, "protect => !unsafe"); size_t pageSize = SharedMemory::SystemPageSize(); nsRefPtr<SharedMemory> segment; // |2*pageSize| is for the front and back sentinel size_t segmentSize = SharedMemory::PageAlignedSize(aNBytes + 2*pageSize); if (aType == SharedMemory::TYPE_BASIC) segment = CreateSegment(segmentSize, SharedMemoryBasic::NULLHandle()); #ifdef MOZ_HAVE_SHAREDMEMORYSYSV else if (aType == SharedMemory::TYPE_SYSV) segment = CreateSegment(segmentSize, SharedMemorySysV::NULLHandle()); #endif else { NS_ERROR("unknown shmem type"); return nullptr; } if (!segment) return nullptr; Header* header; char *frontSentinel; char *data; char *backSentinel; GetSections(segment, &header, &frontSentinel, &data, &backSentinel); // initialize the segment with Shmem-internal information // NB: this can't be a static assert because technically pageSize // isn't known at compile time, event though in practice it's always // going to be 4KiB MOZ_ASSERT(sizeof(Header) <= pageSize, "Shmem::Header has gotten too big"); memcpy(header->mMagic, sMagic, sizeof(sMagic)); header->mSize = static_cast<uint32_t>(aNBytes); header->mUnsafe = aUnsafe; if (aProtect) Protect(segment); return segment.forget(); }
ECode CVpnService::Protect( /* [in] */ IDatagramSocket* socket, /* [out] */ Boolean* reault) { VALIDATE_NOT_NULL(reault); AutoPtr<IFileDescriptor> descriptor; socket->GetFileDescriptor((IFileDescriptor**)&descriptor); Int32 fd; descriptor->GetDescriptor(&fd); return Protect(fd, result); }
quad_float& operator /=(quad_float& x, const quad_float& y ) { START_FIX DOUBLE hc, tc, hy, ty, C, c, U, u; DOUBLE t1; C = x.hi/y.hi; c = Protect(NTL_QUAD_FLOAT_SPLIT*C); hc = c-C; u = Protect(NTL_QUAD_FLOAT_SPLIT*y.hi); hc = c-hc; tc = C-hc; hy = u-y.hi; U = Protect(C * y.hi); hy = u-hy; ty = y.hi-hy; // u = (((hc*hy-U)+hc*ty)+tc*hy)+tc*ty; u = Protect(hc*hy); u = u-U; t1 = Protect(hc*ty); u = u+t1; t1 = Protect(tc*hy); u = u+t1; t1 = Protect(tc*ty); u = u+t1; // c = ((((x.hi-U)-u)+x.lo)-C*y.lo)/y.hi; c = x.hi-U; c = c-u; c = c+x.lo; t1 = Protect(C*y.lo); c = c - t1; c = c/y.hi; hy = C+c; ty = C-hy; ty = ty+c; x.hi = hy; x.lo = ty; END_FIX return x; }
quad_float& operator *=(quad_float& x,const quad_float& y ) { START_FIX DOUBLE hx, tx, hy, ty, C, c; DOUBLE t1, t2; C = Protect(NTL_QUAD_FLOAT_SPLIT*x.hi); hx = C-x.hi; c = Protect(NTL_QUAD_FLOAT_SPLIT*y.hi); hx = C-hx; tx = x.hi-hx; hy = c-y.hi; C = Protect(x.hi*y.hi); hy = c-hy; ty = y.hi-hy; // c = ((((hx*hy-C)+hx*ty)+tx*hy)+tx*ty)+(x.hi*y.lo+x.lo*y.hi); t1 = Protect(hx*hy); t1 = t1-C; t2 = Protect(hx*ty); t1 = t1+t2; t2 = Protect(tx*hy); t1 = t1+t2; t2 = Protect(tx*ty); c = t1+t2; t1 = Protect(x.hi*y.lo); t2 = Protect(x.lo*y.hi); t1 = t1+t2; c = c + t1; hx = C+c; tx = C-hx; tx = tx+c; x.hi = hx; x.lo = tx; END_FIX return x; }
void vm_mini_vm(lua_State *L, LClosure *cl, int count, int pseudo_ops_offset) { const Instruction *pc; StkId base; TValue *k; k = cl->p->k; pc = cl->p->code + pseudo_ops_offset; base = L->base; /* process next 'count' ops */ for (; count > 0; count--) { const Instruction i = *pc++; StkId ra = RA(i); lua_assert(base == L->base && L->base == L->ci->base); lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); switch (GET_OPCODE(i)) { case OP_MOVE: { setobjs2s(L, ra, RB(i)); continue; } case OP_LOADK: { setobj2s(L, ra, KBx(i)); continue; } case OP_GETUPVAL: { int b = GETARG_B(i); setobj2s(L, ra, cl->upvals[b]->v); continue; } case OP_SETUPVAL: { UpVal *uv = cl->upvals[GETARG_B(i)]; setobj(L, uv->v, ra); luaC_barrier(L, uv, ra); continue; } case OP_SETTABLE: { Protect(luaV_settable(L, ra, RKB(i), RKC(i))); continue; } default: { luaG_runerror(L, "Bad opcode: opcode=%d", GET_OPCODE(i)); continue; } } } }
void Shmem::RevokeRights(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead) { AssertInvariants(); size_t pageSize = SharedMemory::SystemPageSize(); Header* header = GetHeader(mSegment); // Open this up for reading temporarily mSegment->Protect(reinterpret_cast<char*>(header), pageSize, RightsRead); if (!header->mUnsafe) { Protect(mSegment); } else { mSegment->Protect(reinterpret_cast<char*>(header), pageSize, RightsNone); } }
void luaV_execute (lua_State *L) { CallInfo *ci = L->ci; LClosure *cl; TValue *k; StkId base; newframe: /* reentry point when frame changes (call/return) */ lua_assert(ci == L->ci); cl = clLvalue(ci->func); k = cl->p->k; base = ci->u.l.base; //printf( "s:%p\n", ci->u.l.savedpc ); /* main loop of interpreter */ for (;;) { Instruction i = *(ci->u.l.savedpc++); StkId ra; if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { Protect(traceexec(L)); } /* warning!! several calls may realloc the stack and invalidate `ra' */ ra = RA(i); lua_assert(base == ci->u.l.base); lua_assert(base <= L->top && L->top < L->stack + L->stacksize); // 命令出力 //printInst( ci->u.l.savedpc - 1 ); vmdispatch (GET_OPCODE(i)) { vmcase(OP_MOVE, setobjs2s(L, ra, RB(i)); ) vmcase(OP_LOADK, TValue *rb = k + GETARG_Bx(i); setobj2s(L, ra, rb); ) vmcase(OP_LOADKX, TValue *rb; lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); rb = k + GETARG_Ax(*ci->u.l.savedpc++); setobj2s(L, ra, rb); )
int vm_OP_TFORLOOP(lua_State *L, int a, int c) { TValue *base = L->base; TValue *ra = base + a; StkId cb = ra + 3; /* call base */ setobjs2s(L, cb+2, ra+2); setobjs2s(L, cb+1, ra+1); setobjs2s(L, cb, ra); L->top = cb+3; /* func. + 2 args (state and index) */ Protect(luaD_call(L, cb, c)); L->top = L->ci->top; cb = base + a + 3; /* previous call may change the stack */ if (!ttisnil(cb)) { /* continue loop? */ setobjs2s(L, cb-1, cb); /* save control variable */ dojump(GETARG_sBx(*L->savedpc)); return 1; } return 0; }
void vm_OP_VARARG(lua_State *L, LClosure *cl, int a, int b) { TValue *base = L->base; TValue *ra = base + a; int j; CallInfo *ci = L->ci; int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; b -= 1; if (b == LUA_MULTRET) { Protect(luaD_checkstack(L, n)); ra = base + a; /* previous call may change the stack */ b = n; L->top = ra + n; } for (j = 0; j < b; j++) { if (j < n) { setobjs2s(L, ra + j, ci->base - n + j); } else { setnilvalue(ra + j); } } }
// static Shmem::SharedMemory* Shmem::Alloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, size_t aNBytes, SharedMemoryType aType, bool aProtect) { size_t pageSize = SharedMemory::SystemPageSize(); SharedMemory* segment = nsnull; // |2*pageSize| is for the front and back sentinel size_t segmentSize = PageAlignedSize(aNBytes + 2*pageSize); if (aType == SharedMemory::TYPE_BASIC) segment = CreateSegment(segmentSize, SharedMemoryBasic::NULLHandle()); #ifdef MOZ_HAVE_SHAREDMEMORYSYSV else if (aType == SharedMemory::TYPE_SYSV) segment = CreateSegment(segmentSize, SharedMemorySysV::NULLHandle()); #endif else NS_RUNTIMEABORT("unknown shmem type"); if (!segment) return 0; char *frontSentinel; char *data; char *backSentinel; GetSections(segment, &frontSentinel, &data, &backSentinel); // initialize the segment with Shmem-internal information Header* header = reinterpret_cast<Header*>(frontSentinel); memcpy(header->mMagic, sMagic, sizeof(sMagic)); header->mSize = aNBytes; if (aProtect) Protect(segment); return segment; }
PLH::MemoryProtect::~MemoryProtect() { Protect(m_Address,m_Size, m_OldProtection); }
void Shmem::RevokeRights(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead) { AssertInvariants(); Protect(mSegment); }
void AI_Control( WorldStuff *world_stuff, int vehicle_number ) { Player *player; team_type team, enemy_team; short frames_till_traitor_deactivate; short frames_till_unscramble; short scramble_life; short traitor_life; /* Alias pointer to this player */ player = world_stuff->player_array; frames_till_traitor_deactivate = player[vehicle_number].tank.frames_till_traitor_deactivate; frames_till_unscramble = player[vehicle_number].tank.frames_till_unscramble; scramble_life = player[vehicle_number].tank.scramble_life; traitor_life = player[vehicle_number].tank.traitor_life; if( player[vehicle_number].tank.team == RED_TEAM ) { team = RED_TEAM; enemy_team = BLUE_TEAM; } else { team = BLUE_TEAM; enemy_team = RED_TEAM; } if( player[vehicle_number].character.skill_level > 2 && player[vehicle_number].controller != USER_CONTROL ) { if( player[vehicle_number].tank.traitor_active ) if( frames_till_traitor_deactivate < (traitor_life - 40) ) player[vehicle_number].tank.traitor_active = FALSE; /* if( player[vehicle_number].tank.controls_scrambled ) if( frames_till_unscramble < (scramble_life - 40) ) player[vehicle_number].tank.controls_scrambled = FALSE; */ } if( player[vehicle_number].tank.traitor_active ) { player[vehicle_number].tank.team = enemy_team; player[vehicle_number].team = enemy_team; } /* Clear this players input table */ Clear_Input_Table( player[vehicle_number].table ); /* Fill up this players events data structure */ Update_Player_Events( world_stuff, vehicle_number ); /* Figure out what state we are in now */ world_stuff->player_array[vehicle_number].character.state = Find_State( world_stuff, vehicle_number ); if( player[vehicle_number].tank.traitor_active ) { world_stuff->player_array[vehicle_number].character.state = ATTACK; } /* Based on the state of the ai call appropriate control function */ switch( world_stuff->player_array[vehicle_number].character.state ) { case ATTACK: Attack( world_stuff, vehicle_number ); break; case GET_ENERGY: Get_Energy( world_stuff, vehicle_number ); break; case PANIC: Panic( world_stuff, vehicle_number ); break; case BEZERK: Bezerk( world_stuff, vehicle_number ); break; case HIDE: Hide( world_stuff, vehicle_number ); break; case GROUPUP: Group( world_stuff, vehicle_number ); break; case GET_PYLONS: Get_Pylons( world_stuff, vehicle_number ); break; case PROTECT: Protect( world_stuff, vehicle_number ); break; case KILL_RADAR_BASE: Kill_Radar_Base( world_stuff, vehicle_number ); break; case PROTECT_RADAR_BASE: Protect_Radar_Base( world_stuff, vehicle_number ); break; case EVADE: Evade( world_stuff, vehicle_number ); default: break; } /* End case */ if( player[vehicle_number].tank.traitor_active ) { player[vehicle_number].tank.team = team; player[vehicle_number].team = team; } if( player[vehicle_number].tank.vtype == Dragonfly ) Cloak_Override( world_stuff, vehicle_number ); if( player[vehicle_number].tank.vtype == Roach ) Mines( world_stuff, vehicle_number ); if( player_events[vehicle_number].memory.stuck ) Stuck_Override( world_stuff, vehicle_number ); } /* End of AI_Control */
static void Arith (lua_State *L, StkId ra, const TValue *rb, const TValue *rc, TMS op) { TValue tempb, tempc; const TValue *b, *c; #if LUA_REFCOUNT luarc_newvalue(&tempb); luarc_newvalue(&tempc); if ((b = luaV_tonumber(L, rb, &tempb)) != NULL && (c = luaV_tonumber(L, rc, &tempc)) != NULL) { #else if ((b = luaV_tonumber(rb, &tempb)) != NULL && (c = luaV_tonumber(rc, &tempc)) != NULL) { #endif /* LUA_REFCOUNT */ lua_Number nb = nvalue(b), nc = nvalue(c); #if LUA_REFCOUNT luarc_cleanvalue(&tempb); luarc_cleanvalue(&tempc); #endif /* LUA_REFCOUNT */ switch (op) { case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; default: lua_assert(0); break; } } #if LUA_REFCOUNT else if (!call_binTM(L, rb, rc, ra, op)) { luarc_cleanvalue(&tempb); luarc_cleanvalue(&tempc); luaG_aritherror(L, rb, rc); } #else else if (!call_binTM(L, rb, rc, ra, op)) luaG_aritherror(L, rb, rc); #endif /* LUA_REFCOUNT */ } /* ** some macros for common tasks in `luaV_execute' */ #define runtime_check(L, c) { if (!(c)) break; } #define RA(i) (base+GETARG_A(i)) /* to be used after possible stack reallocation */ #define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) #define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) #define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) #define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) #define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) #define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} #define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } #define arith_op(op,tm) { \ TValue *rb = RKB(i); \ TValue *rc = RKC(i); \ if (ttisnumber(rb) && ttisnumber(rc)) { \ lua_Number nb = nvalue(rb), nc = nvalue(rc); \ setnvalue(ra, op(nb, nc)); \ } \ else \ Protect(Arith(L, ra, rb, rc, tm)); \ } #if LUA_BITFIELD_OPS #define bit_op(op) { \ TValue *rb = RKB(i); \ TValue *rc = RKC(i); \ if (ttisnumber(rb) && ttisnumber(rc)) { \ unsigned int nb = (unsigned int)nvalue(rb), nc = (unsigned int)nvalue(rc); \ setnvalue(ra, nb op nc); \ } \ else \ luaG_aritherror(L, rb, rc); \ } #endif /* LUA_BITFIELD_OPS */ void luaV_execute (lua_State *L, int nexeccalls) { LClosure *cl; StkId base; TValue *k; const Instruction *pc; reentry: /* entry point */ lua_assert(isLua(L->ci)); pc = L->savedpc; cl = &clvalue(L->ci->func)->l; base = L->base; k = cl->p->k; /* main loop of interpreter */ for (;;) { const Instruction i = *pc++; StkId ra; if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { traceexec(L, pc); if (L->status == LUA_YIELD) { /* did hook yield? */ L->savedpc = pc - 1; return; } base = L->base; } /* warning!! several calls may realloc the stack and invalidate `ra' */ ra = RA(i); lua_assert(base == L->base && L->base == L->ci->base); lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); switch (GET_OPCODE(i)) { case OP_MOVE: { setobjs2s(L, ra, RB(i)); continue; } case OP_LOADK: { setobj2s(L, ra, KBx(i)); continue; } case OP_LOADBOOL: { setbvalue(ra, GETARG_B(i)); if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ continue; } case OP_LOADNIL: { TValue *rb = RB(i); do { setnilvalue(rb--); } while (rb >= ra); continue; } case OP_GETUPVAL: { int b = GETARG_B(i); setobj2s(L, ra, cl->upvals[b]->v); continue; } case OP_GETGLOBAL: { TValue g; TValue *rb = KBx(i); #if LUA_REFCOUNT sethvalue2n(L, &g, cl->env); #else sethvalue(L, &g, cl->env); #endif /* LUA_REFCOUNT */ lua_assert(ttisstring(rb)); Protect(luaV_gettable(L, &g, rb, ra)); #if LUA_REFCOUNT setnilvalue(&g); #endif /* LUA_REFCOUNT */ continue; } case OP_GETTABLE: { Protect(luaV_gettable(L, RB(i), RKC(i), ra)); continue; } case OP_SETGLOBAL: { TValue g; #if LUA_REFCOUNT sethvalue2n(L, &g, cl->env); #else sethvalue(L, &g, cl->env); #endif /* LUA_REFCOUNT */ lua_assert(ttisstring(KBx(i))); Protect(luaV_settable(L, &g, KBx(i), ra)); #if LUA_REFCOUNT setnilvalue(&g); #endif /* LUA_REFCOUNT */ continue; } case OP_SETUPVAL: { UpVal *uv = cl->upvals[GETARG_B(i)]; setobj(L, uv->v, ra); luaC_barrier(L, uv, ra); continue; } case OP_SETTABLE: { Protect(luaV_settable(L, ra, RKB(i), RKC(i))); continue; } case OP_NEWTABLE: { int b = GETARG_B(i); int c = GETARG_C(i); sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); Protect(luaC_checkGC(L)); continue; } case OP_SELF: { StkId rb = RB(i); setobjs2s(L, ra+1, rb); Protect(luaV_gettable(L, rb, RKC(i), ra)); continue; } case OP_ADD: { arith_op(luai_numadd, TM_ADD); continue; } case OP_SUB: { arith_op(luai_numsub, TM_SUB); continue; } case OP_MUL: { arith_op(luai_nummul, TM_MUL); continue; } case OP_DIV: { arith_op(luai_numdiv, TM_DIV); continue; } case OP_MOD: { arith_op(luai_nummod, TM_MOD); continue; } case OP_POW: { arith_op(luai_numpow, TM_POW); continue; } case OP_UNM: { TValue *rb = RB(i); if (ttisnumber(rb)) { lua_Number nb = nvalue(rb); setnvalue(ra, luai_numunm(nb)); } else { Protect(Arith(L, ra, rb, rb, TM_UNM)); } continue; } case OP_NOT: { int res = l_isfalse(RB(i)); /* next assignment may change this value */ setbvalue(ra, res); continue; } #if LUA_BITFIELD_OPS case OP_BAND: { bit_op(&); continue; } case OP_BOR: { bit_op(|); continue; } case OP_BXOR: { bit_op(^); continue; } case OP_BSHL: { bit_op(<<); continue; } case OP_BSHR: { bit_op(>>); continue; } #endif /* LUA_BITFIELD_OPS */ case OP_LEN: { const TValue *rb = RB(i); switch (ttype(rb)) { case LUA_TTABLE: { setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); break; } case LUA_TSTRING: { setnvalue(ra, cast_num(tsvalue(rb)->len)); break; } #if LUA_WIDESTRING case LUA_TWSTRING: { setnvalue(ra, cast_num(tsvalue(rb)->len)); break; } #endif /* LUA_WIDESTRING */ default: { /* try metamethod */ Protect( if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) luaG_typeerror(L, rb, "get length of"); ) } } continue; } case OP_CONCAT: { int b = GETARG_B(i); int c = GETARG_C(i); Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); setobjs2s(L, RA(i), base+b); continue; } case OP_JMP: { dojump(L, pc, GETARG_sBx(i)); continue; } case OP_EQ: { TValue *rb = RKB(i); TValue *rc = RKC(i); Protect( if (equalobj(L, rb, rc) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; } case OP_LT: { Protect( if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; } case OP_LE: { Protect( if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; }
// 已经准备好了lua函数的调用环境,开始逐句执行lua函数的指令 void luaV_execute (lua_State *L, int nexeccalls) { LClosure *cl; StkId base; TValue *k; const Instruction *pc; reentry: /* entry point */ pc = L->savedpc; //这时候已经保存了lua函数的第一个指令位置 cl = &clvalue(L->ci->func)->l; base = L->base; k = cl->p->k; /* main loop of interpreter */ for (;;) { const Instruction i = *pc++; StkId ra; if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { traceexec(L, pc); if (L->status == LUA_YIELD) { /* did hook yield? */ L->savedpc = pc - 1; return; } base = L->base; } /* warning!! several calls may realloc the stack and invalidate `ra' */ ra = RA(i); lua_assert(base == L->base && L->base == L->ci->base); lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); // 阅读说明: // 每lua的一个函数在编译器会生成这个函数的信息:函数引用到的upvalue,函数固定参数 // 数量,是否含有可变参数,指令序列等等,这些都记录在Proto结构体中。 // 可以通过 luac -o tmp <luafile> | luac -l tmp 来函数对应的字节码以及Proto信息 // 例如以下lua代码: // -- t.lua // local x, y, z // x = x*y + y*z + x*z - (x*x + y*y + z*z) // 得到以下输出: // main <t.lua:0,0> (12 instructions, 48 bytes at 0074B6A0) // 0 + params, 6 slots, 0 upvalues, 3 locals, 0 constants, 0 functions // 1[2] MUL 3 0 1 // 2[2] MUL 4 1 2 // 3[2] ADD 3 3 4 // 4[2] MUL 4 0 2 // 5[2] ADD 3 3 4 // 6[2] MUL 4 0 0 // 7[2] MUL 5 1 1 // 8[2] ADD 4 4 5 // 9[2] MUL 5 2 2 // 10[2] ADD 4 4 5 // 11[2] SUB 0 3 4 // 12[2] RETURN 0 1 // 从输出可以得到的信息包括: // 1 生成了多少个Proto // 2 Proto对应的lua源代码在哪里 (<t.lua:0,0>) // 3 Proto中的sizecode (12 instructions, 48 bytes at 0074B6A0) // 4 Proto中的固定参数数量numparams (0 + params,这里的0) // 5 Proto是否有可变参数is_vararg (0 + params,这里的+表示带有可变参数,没有可变参数就是 0 params) // 6 Proto中在栈上用到的临时变量总数maxstacksize (6 slots,表示local变量+计算中辅助用的临时变量=6个) // 7 Proto中用到的upvalue数量nups (0 upvalues,表示用到了0个upvalue) // 8 Proto中用到的local变量数量sizelocvars (3 locals,刚好t.lua用到了x,y,z三个local变量) // 9 Proto中用到的字面常量数量sizek (0 constants) // 10 Proto中用到的Closure数量sizep (0 functions) // 11 Proto中生成的字节码指令内容code,每条指令包括: // a 指令下标 // b 指令在源代码中对应的行号 // c 指令opcode // d 指令参数 // // PS:第6条和第8条,由于计算一条表达式需要用到的辅助临时变量数目是不定的,但是是可以通过 // 分析一条表达式的AST来确定最少需要几个临时变量(后续遍历+逆波兰式拟真)。 // PS:lua是会对表达式进行常量计算优化的!例如 x = x + 5*60*60*1000,只有一个常量18000000 // PS:函数执行的时候需要用到“一段”参数栈上的空间,也就是第6条所谓的临时变量。这一段空间的 // 范围由L->base开始,到L->top结束。通过相对L->base的下标来标识具体的变量是哪个。一般来说, // 固定参数的函数,L->base指向第一个固定参数,而L->base-1指向当前正在运行的函数;而可变参数 // 的函数,L->base和当前正在运行的函数中间,保存有全部的传入参数。 switch (GET_OPCODE(i)) { // 功能:用一个已有的变量创建一个新的变量 // 将一个 lua_TValue设置成另一个lua_TValue的样子 // iABC: A待创建变量在参数栈索引,B参数栈已有lua变量的索引。 case OP_MOVE: { // local x, y -----> 记录 index(x) = 0, index(y) = 1 // x = ... // ..... // y = x -----> OP_MOVE: 1, 0 setobjs2s(L, ra, RB(i)); continue; } // 功能:用一个常量来创建一个新的变量 // 从常量池(保存在Proto类型中)中保存的常量赋值给栈上的变量 // iABx: A待创建变量在参数栈索引,Bx常量在常量池的索引 case OP_LOADK: { // local x = 9 -----> 记录 index(x) = 0, index(constval(9)) = 1 // >----> OP_LOADK: 0, 1 setobj2s(L, ra, KBx(i)); continue; } // 功能:用一个布尔值来创建一个新的变量 // iABC: A待创建变量在参数栈索引,B布尔值,C通常是0 case OP_LOADBOOL: { // 注意,local c = true这种,true就不作为一个常量放到k里面 // 而是作为字面值放到参数B里面了!所以不需要KB(i)! // local a = false -----> 记录 index(a) = 0 // >----> OP_LOADBOOL 0 0 0 // local b = true -----> 记录 index(b) = 1 // >----> OP_LOADBOOL 1 1 0 setbvalue(ra, GETARG_B(i)); if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ continue; } // 功能:用nil来初始化一个到多个变量 // 类似于bzero,这个指令会把一段内存中的变量置为nil // iABC: A第一个要置nil的变量参数栈索引,B最后一个要置nil的变量参数栈索引 case OP_LOADNIL: { // local a, b, c, d, e, f, g = 1, 2, 3, 4 -----> index(a~g) = 0~6 // >----> OP_LOADNIL 4 6 TValue *rb = RB(i); do { setnilvalue(rb--); } while (rb >= ra); continue; } // 功能:用upvalue来创建一个新的变量 // 所谓的“创建”操作,其实创建的不是副本而是引用 // iABC: A待创建变量在参数栈索引,B当前函数的upvalue表的索引 case OP_GETUPVAL: { // local x = {} // ... -- do something to x // function f() local a = x[1] end -----> 记录index(a) = 0, index(upval(x)) = 1 // >----> OP_GETUPVAL 0 1 int b = GETARG_B(i); setobj2s(L, ra, cl->upvals[b]->v); continue; } // 功能:从全局表中取某个key的值来创建一个新的变量 // iABx:A待创建变量在参数栈索引,Bxkey对应的常量在常量池的索引 case OP_GETGLOBAL: { // local a = dofile ------> 记录 index(a) = 0, index(constval("dofile")) = 1 // >-----> OP_GETGLOBAL 0 1 TValue g; TValue *rb = KBx(i); sethvalue(L, &g, cl->env); lua_assert(ttisstring(rb)); Protect(luaV_gettable(L, &g, rb, ra)); continue; } // 功能:从某个table中取某个key的值来创建一个新的变量 // iABC:A待创建变量在参数栈索引,B要取出key的table变量在参数栈的索引,Ckey对应的参数栈下标或者常量池下标 case OP_GETTABLE: { // local a = hello["world"] -----> 记录 index(a) = 0, index(hello) = 1 index(constval("world")) = 0 // >----> OP_GETTABLE 0 1 0|BITRK Protect(luaV_gettable(L, RB(i), RKC(i), ra)); continue; } // 功能:将参数栈上变量设置到全局表中 // iABx:A要写入全局表的变量在栈上的索引,Bx写入到全局表的key在常量池中的下标 case OP_SETGLOBAL: { // 假设我要替换 bit库 // local mybit = {} // mybit.band = ... // mybit.bor = ... // mybit.bxor = ... // ... // bit = mybit -----> 记录 index(mybit) = 0, index(constval("bit")) = 1 // >----> OP_SETGLOBAL 0 1 TValue g; sethvalue(L, &g, cl->env); lua_assert(ttisstring(KBx(i))); Protect(luaV_settable(L, &g, KBx(i), ra)); continue; } // 功能:修改upvalue的值 // iABC:A要写入upvalue的变量在参数栈上的索引,B待写入的upvalue在upvalue表的索引 case OP_SETUPVAL: { // local a = 5 // function p() // a = "hello" -----> 记录 index(upval(a)) = 0, index(constval("hello")) = 1 // >----> OP_SETUPVAL 0 1 // end UpVal *uv = cl->upvals[GETARG_B(i)]; setobj(L, uv->v, ra); luaC_barrier(L, uv, ra); continue; } // 功能:修改某个table对应的key // iABC:A要写入table变量在参数栈的索引,B要写入的key的变量的栈索引或者常量索引,C要写入的value的变量索引或者常量索引 case OP_SETTABLE: { // local a = {} // a[5] = 3 Protect(luaV_settable(L, ra, RKB(i), RKC(i))); continue; } // 功能:在栈上创建一个table变量 // iABC:A存放table变量的参数栈索引,B创建的table变量的数组容量,C创建的table变量的字典容量 case OP_NEWTABLE: { // local a = {} -----> index(a) = 0 // >----> OP_NEWTABLE 0 szArray szHash int b = GETARG_B(i); int c = GETARG_C(i); sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); Protect(luaC_checkGC(L)); // 注意,创建table可能会引起GC continue; } // 功能:把self.method和self放到参数栈上相邻的两个位置。 // 为成员方法调用的语法糖提供支持 // iABC:A存放self.method的参数栈索引,B存放self的参数栈索引,C需要从self中调用的方法对应的变量索引或者常量索引 // 执行完成后,栈上内容为: ... -> self.method -> self -> ... // ^ // RA // 当然,OP_SELF之后能看到OP_CALL的身影 case OP_SELF: { // CCNode:create() -> index(constants("CCNode")) = 1, index(constants("create")) = 2 // -> OP_GETGLOBAL 0 1 // -> OP_SELF 0 0 2 // -> OP_CALL 0 2 1 StkId rb = RB(i); setobjs2s(L, ra+1, rb); Protect(luaV_gettable(L, rb, RKC(i), ra)); continue; } //---------------------------------------------------------------------------运算符指令 // 功能:实现二元运算符:+, -, *, /, %, ^ // iABC:A存放运算结果的参数栈索引,B存放第一操作数的参数栈索引,C存放第二操作数的参数栈索引 case OP_ADD: { // local a, b, c = ... -----> index(a) = 0, index(b) = 1, index(c) = 2 // a = b + c -----> OP_ADD 0 1|BITRK 2|BITRK // a = 1 + b -----> index(constval(1)) = 0 // >----> OP_ADD 0 0 1|BITRK // a = 1 + 100 -----> index(constval(1)) = 0, index(constval(100)) = 1 // >----> OP_ADD 0 0 1 arith_op(luai_numadd, TM_ADD); continue; } case OP_SUB: { // see OP_ADD arith_op(luai_numsub, TM_SUB); continue; } case OP_MUL: { // see OP_ADD arith_op(luai_nummul, TM_MUL); continue; } case OP_DIV: { // see OP_ADD arith_op(luai_numdiv, TM_DIV); continue; } case OP_MOD: { // 这个很特殊!由于lua没有整数,所以mod可不是%这个运算符! // 这里定义 mod(x, y) => (x - floor(x/y)*y) // see OP_ADD arith_op(luai_nummod, TM_MOD); continue; } case OP_POW: { // see OP_ADD arith_op(luai_numpow, TM_POW); continue; } // 功能:实现一元运算符 -, not, # // iABC:A存放运算结果的参数栈索引,B存放操作数的参数栈索引 case OP_UNM: { // local a = -b -----> index(a) = 1, index(b) = 2 // >----> OP_UNM 1 2 TValue *rb = RB(i); if (ttisnumber(rb)) { lua_Number nb = nvalue(rb); setnvalue(ra, luai_numunm(nb)); } else { Protect(Arith(L, ra, rb, rb, TM_UNM)); } continue; } case OP_NOT: { // local a = not b -----> index(a) = 1, index(b) = 2 // >----> OP_NOT 1 2 // 那local a = not true呢?人家编译期就给你处理好了 int res = l_isfalse(RB(i)); /* next assignment may change this value */ setbvalue(ra, res); continue; } case OP_LEN: { // local a = #b -----> index(a) = 1, index(b) = 2 // >----> OP_LEN 1 2 const TValue *rb = RB(i); switch (ttype(rb)) { case LUA_TTABLE: { setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); break; } case LUA_TSTRING: { setnvalue(ra, cast_num(tsvalue(rb)->len)); break; } default: { /* try metamethod */ Protect( if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) luaG_typeerror(L, rb, "get length of"); ) } } continue; } // 功能:实现字符串拼接运算符 .. // iABC:A拼接后存放结果的参数栈索引,B第一个要拼接的变量的参数栈索引,C最后一个要拼接的变量的参数栈索引 // 要执行这个指令,对参数栈有特殊要求: // ... -> string1 -> string2 ... -> stringN -> ... // ^ ^ // RB RC case OP_CONCAT: { // 类似OP_LOADNIL,只不过,这次范围是[rb,rc],loadnil是[ra,rb] // local b, c, d, a = "hello", "world", "!" // a = b .. c .. d -----> index(a) = 4, index(b~d) = 1~3 // >----> OP_CONCAT 4 1 3 // 问题是如果b~d不能保证是连续的怎么办?答案是一个个MOVE上去在OP_CONCAT... int b = GETARG_B(i); int c = GETARG_C(i); Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); setobjs2s(L, RA(i), base+b); continue; } //---------------------------------------------------------------------------跳转指令 // 功能:无条件跳转 // iAsBx:A不使用,sBx跳转偏移 // 一般这个语句不单独出现,都是在一些条件控制中和其他的条件跳转指令配合使用的。 case OP_JMP: { // 无条件跳转指令。由于跳转偏移总是有正向和反向之分的,所以需要用到 // 负数。那就只能用iAsBx类型的指令了。而sBx是有长度限制的! // 所以,如果生成的指令很多,超过了sBx的长度限制,可能就会编译失败 dojump(L, pc, GETARG_sBx(i)); continue; } // 功能:检查两个变量是否相等,满足预期则跳转。配合OP_JMP使用。 // iABC:A纯数字,对比较结果的预期,满足预期则跳转,B参数1的索引,C参数2的索引 case OP_EQ: { // if a == b then -----> index(a) = 1, index(b) = 2 // >----> 这里将生成两行指令: // >----> OP_EQ 0 1 2 // 用0,因为成立的话跳过,不成立才执行 // >----> OP_JMP N // N 表示then ... end中间的指令数量 // >----> ... // Instructions between "then" and "end" TValue *rb = RKB(i); TValue *rc = RKC(i); Protect( if (equalobj(L, rb, rc) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; } // 功能:检查两个变量是否小于,满足预期则跳转。配合OP_JMP使用。 // iABC:A纯数字,对比较结果的预期,满足预期则跳转,B参数1的索引,C参数2的索引 case OP_LT: { // if a < b then -----> index(a) = 1, index(b) = 2 // >----> 这里将生成两行指令: // >----> OP_LT 0 1 2 // 用0,因为成立的话跳过,不成立才执行 // >----> OP_JMP N // N 表示then ... end中间的指令数量 // >----> ... // Instructions between "then" and "end" Protect( if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; } // 功能:检查两个变量是否小于等于,满足预期则跳转。配合OP_JMP使用。 // iABC:A纯数字,对比较结果的预期,满足预期则跳转,B参数1的索引,C参数2的索引 case OP_LE: { // if a <= b then -----> index(a) = 1, index(b) = 2 // >----> 这里将生成两行指令: // >----> OP_LE 0 1 2 // 用0,因为成立的话跳过,不成立才执行 // >----> OP_JMP N // N 表示then ... end中间的指令数量 // >----> ... // Instructions between "then" and "end" Protect( if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; }
void luaV_execute (lua_State *L, int nexeccalls) { LClosure *cl; StkId base; TValue *k; const Instruction *pc; reentry: /* entry point */ lua_assert(isLua(L->ci)); pc = L->savedpc; cl = &clvalue(L->ci->func)->l; base = L->base; k = cl->p->k; /* main loop of interpreter */ for (;;) { const Instruction i = *pc++; StkId ra; if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { traceexec(L, pc); if (L->status == LUA_YIELD) { /* did hook yield? */ L->savedpc = pc - 1; return; } base = L->base; } /* warning!! several calls may realloc the stack and invalidate `ra' */ ra = RA(i); lua_assert(base == L->base && L->base == L->ci->base); lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); switch (GET_OPCODE(i)) { case OP_MOVE: { setobjs2s(L, ra, RB(i)); continue; } case OP_LOADK: { setobj2s(L, ra, KBx(i)); continue; } case OP_LOADBOOL: { setbvalue(ra, GETARG_B(i)); if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ continue; } case OP_LOADNIL: { TValue *rb = RB(i); do { setnilvalue(rb--); } while (rb >= ra); continue; } case OP_GETUPVAL: { int b = GETARG_B(i); setobj2s(L, ra, cl->upvals[b]->v); continue; } case OP_GETGLOBAL: { TValue g; TValue *rb = KBx(i); sethvalue(L, &g, cl->env); lua_assert(ttisstring(rb)); Protect(luaV_gettable(L, &g, rb, ra)); continue; } case OP_GETTABLE: { Protect(luaV_gettable(L, RB(i), RKC(i), ra)); continue; } case OP_SETGLOBAL: { TValue g; sethvalue(L, &g, cl->env); lua_assert(ttisstring(KBx(i))); Protect(luaV_settable(L, &g, KBx(i), ra)); continue; } case OP_SETUPVAL: { UpVal *uv = cl->upvals[GETARG_B(i)]; setobj(L, uv->v, ra); luaC_barrier(L, uv, ra); continue; } case OP_SETTABLE: { Protect(luaV_settable(L, ra, RKB(i), RKC(i))); continue; } case OP_NEWTABLE: { int b = GETARG_B(i); int c = GETARG_C(i); sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); Protect(luaC_checkGC(L)); continue; } case OP_SELF: { StkId rb = RB(i); setobjs2s(L, ra+1, rb); Protect(luaV_gettable(L, rb, RKC(i), ra)); continue; } case OP_ADD: { arith_op(luai_numadd, TM_ADD); continue; } case OP_SUB: { arith_op(luai_numsub, TM_SUB); continue; } case OP_MUL: { arith_op(luai_nummul, TM_MUL); continue; } case OP_DIV: { arith_op(luai_numdiv, TM_DIV); continue; } case OP_MOD: { arith_op(luai_nummod, TM_MOD); continue; } case OP_POW: { arith_op(luai_numpow, TM_POW); continue; } case OP_UNM: { TValue *rb = RB(i); if (ttisnumber(rb)) { lua_Number nb = nvalue(rb); setnvalue(ra, luai_numunm(nb)); } else { Protect(luaV_arith(L, ra, rb, rb, TM_UNM)); } continue; } case OP_NOT: { int res = l_isfalse(RB(i)); /* next assignment may change this value */ setbvalue(ra, res); continue; } case OP_LEN: { const TValue *rb = RB(i); switch (ttype(rb)) { case LUA_TTABLE: { setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); break; } case LUA_TSTRING: { setnvalue(ra, cast_num(tsvalue(rb)->len)); break; } default: { /* try metamethod */ Protect( if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) luaG_typeerror(L, rb, "get length of"); ) } } continue; } case OP_CONCAT: { int b = GETARG_B(i); int c = GETARG_C(i); Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); setobjs2s(L, RA(i), base+b); continue; } case OP_JMP: { dojump(L, pc, GETARG_sBx(i)); continue; } case OP_EQ: { TValue *rb = RKB(i); TValue *rc = RKC(i); Protect( if (equalobj(L, rb, rc) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; } case OP_LT: { Protect( if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; } case OP_LE: { Protect( if (luaV_lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; }
bool newcontrols(dbref who, dbref what, bool true_c) { dbref index; /* No one controls invalid objects */ /* if (what < 0 || what >= db_top) -- not good enough */ if (!OkObj(what) || !OkObj(who)) return 0; /* Garbage controls nothing. */ if (Typeof(who) == TYPE_GARBAGE) return 0; /* No one controls garbage */ if (Typeof(what) == TYPE_GARBAGE) return 0; /* Puppets are based on owner */ if (Typeof(who) != TYPE_PLAYER) who = OWNER(who); /* owners control their own stuff */ /* Makes stuff faster here. -Hinoserm */ if (who == OWNER(what)) return 1; /* CONTROL_ALL controls all objects */ if ((POWERS(who) & POW_CONTROL_ALL) && !Protect(what)) return 1; /* CONTROL_MUF power controls all MUF objects */ if ((POWERS(who) & POW_CONTROL_MUF) && (Typeof(what) == TYPE_PROGRAM) && (!(Protect(what)))) return 1; /* Wizard controls (most) everything else */ if (Wiz(who) && (!(Protect(what) && MLevel(OWNER(what)) >= LBOY) || MLevel(who) >= LBOY)) if (tp_fb_controls ? (MLevel(who) >= LWIZ) : (MLevel(who) >= MLevel(OWNER(what)))) return 1; /* If realms control is enabled, the player will Control anything * contained in a parent room he owns with at W1 bit or higher on it. * This gives him power to affect any object in his w-bitted parent room. */ /* * Read the manual (help CONTROLS) about this new stuff. */ #ifdef CONTROLS_SUPPORT if (!true_c) { if (controlsEx(who, what)) return 1; if (tp_realms_control) { if (!tp_wiz_realms) { if (Typeof(what) != TYPE_PLAYER) for (index = what; index != NOTHING; index = getloc(index)) if ((controlsEx(who, index)) && (Typeof(index) == TYPE_ROOM && ((FLAGS(index) & BUILDER) || Mage(index)))) return 1; } else { if (Typeof(what) != TYPE_PLAYER) for (index = what; index != NOTHING; index = getloc(index)) if ((controlsEx(who, index)) && (Typeof(index) == TYPE_ROOM && (Mage(index)))) return 1; } } } else { #endif if (tp_realms_control && (Typeof(what) != TYPE_PLAYER)) for (index = what; index != NOTHING; index = getloc(index)) if ((OWNER(index) == who) && (Typeof(index) == TYPE_ROOM && Mage(index))) return 1; #ifdef CONTROLS_SUPPORT } #endif return 0; }