static void create_proxy(lua_State *L, const void *data, int index) { const struct table * t = gettable(data, index); if (t == NULL) { luaL_error(L, "Invalid index %d", index); } lua_getfield(L, LUA_REGISTRYINDEX, NODECACHE); if (lua_rawgetp(L, -1, t) == LUA_TTABLE) { lua_replace(L, -2); return; } lua_pop(L, 1); lua_newtable(L); lua_pushvalue(L, lua_upvalueindex(1)); lua_setmetatable(L, -2); lua_pushvalue(L, -1); // NODECACHE, table, table lua_rawsetp(L, -3, t); // NODECACHE, table lua_getfield(L, LUA_REGISTRYINDEX, PROXYCACHE); // NODECACHE, table, PROXYCACHE lua_pushvalue(L, -2); // NODECACHE, table, PROXYCACHE, table struct proxy * p = lua_newuserdata(L, sizeof(struct proxy)); // NODECACHE, table, PROXYCACHE, table, proxy p->data = data; p->index = index; lua_rawset(L, -3); // NODECACHE, table, PROXYCACHE lua_pop(L, 1); // NODECACHE, table lua_replace(L, -2); // table }
static void setttymode(const char *tname, int raw) { int off = 0; gettable(tname, tabent); if (OPset || EPset || APset) APset++, OPset++, EPset++; setdefaults(); (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */ ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */ ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */ if (IS) cfsetispeed(&tmode, speed(IS)); else if (SP) cfsetispeed(&tmode, speed(SP)); if (OS) cfsetospeed(&tmode, speed(OS)); else if (SP) cfsetospeed(&tmode, speed(SP)); set_flags(0); setchars(); if (raw) cfmakeraw(&tmode); if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); exit(1); } }
static void update_cache(lua_State *L, const void *data, const void * newdata) { lua_getfield(L, LUA_REGISTRYINDEX, NODECACHE); int t = lua_gettop(L); lua_getfield(L, LUA_REGISTRYINDEX, PROXYCACHE); int pt = t + 1; lua_newtable(L); // temp table int nt = pt + 1; lua_pushnil(L); while (lua_next(L, t) != 0) { // pointer (-2) -> table (-1) lua_pushvalue(L, -1); if (lua_rawget(L, pt) == LUA_TUSERDATA) { // pointer, table, proxy struct proxy * p = lua_touserdata(L, -1); if (p->data == data) { // update to newdata p->data = newdata; const struct table * newt = gettable(newdata, p->index); lua_pop(L, 1); // pointer, table clear_table(L); lua_pushvalue(L, lua_upvalueindex(1)); // pointer, table, meta lua_setmetatable(L, -2); // pointer, table if (newt) { lua_rawsetp(L, nt, newt); } else { lua_pop(L, 1); } // pointer lua_pushvalue(L, -1); lua_pushnil(L); lua_rawset(L, t); } else { lua_pop(L, 2); } } else { lua_pop(L, 2); // pointer } } // copy nt to t lua_pushnil(L); while (lua_next(L, nt) != 0) { lua_pushvalue(L, -2); lua_insert(L, -2); // key key value lua_rawset(L, t); } // NODECACHE PROXYCACHE TEMP lua_pop(L, 3); }
static int hasRequiredTables(struct ttf_header *hdr) { static struct { int name, present; } tables[] = { { CHR('h','e','a','d') }, { CHR('h','h','e','a') }, { CHR('h','m','t','x') }, { CHR('m','a','x','p') }, /* They can leave out 'gdir' if they want, I don't need it */ /* (and I'll remove it anyway) */ { 0 }}; int i; for ( i=0; tables[i].name!=0; ++i ) { if ( gettable(hdr,tables[i].name)==NULL ) return( false ); } return( true ); }
/* * Read a gettytab database entry and perform necessary quirks. */ static void dogettytab(void) { /* Read the database entry. */ gettable(tname, tabent); /* * Avoid inheriting the parity values from the default entry * if any of them is set in the current entry. * Mixing different parity settings is unreasonable. */ if (OPset || EPset || APset || NPset) OPset = EPset = APset = NPset = 1; /* Fill in default values for unset capabilities. */ setdefaults(); }
static void copytable(lua_State *L, int tbl, struct proxy *p) { const struct document * doc = (const struct document *)p->data; if (p->index < 0 || p->index >= doc->n) { luaL_error(L, "Invalid proxy (index = %d, total = %d)", p->index, (int)doc->n); } const struct table * t = gettable(doc, p->index); if (t == NULL) { luaL_error(L, "Invalid proxy (index = %d)", p->index); } const uint32_t * v = (const uint32_t *)((const char *)t + sizeof(uint32_t) + ((t->dict*2+ 3) & ~3)); int i; for (i=0;i<t->dict;i++) { pushvalue(L, v++, t->type[2*i], doc); pushvalue(L, v++, t->type[2*i+1], doc); lua_rawset(L, tbl); } }
void exitmethod(struct heap_state *heap, struct hashtable *ht, long long uid) { //Lets show the roles!!!! int i=0; struct genhashtable * dommap; struct rolereturnstate *rrs=(struct rolereturnstate *)calloc(1, sizeof(struct rolereturnstate)); #ifdef DEBUG printf("Returning Context for method %s.%s%s:\n", heap->methodlist->methodname->classname->classname, heap->methodlist->methodname->methodname, heap->methodlist->methodname->signature); #endif doincrementalreachability(heap,ht,1); updateroleeffects(heap); /*Merge in this invocation's effects*/ dommap=builddominatormappings(heap,1); if (heap->methodlist->numobjectargs!=0) rrs->paramroles=(char **)calloc(heap->methodlist->numobjectargs, sizeof(char *)); for(;i<heap->methodlist->numobjectargs;i++) { if (heap->methodlist->params[i]!=NULL) { rrs->paramroles[i]=findrolestring(heap, dommap, heap->methodlist->params[i],1); } } if (uid!=-1) { rrs->returnrole=findrolestring(heap, dommap, gettable(ht,uid),1); } addrolereturn(heap->methodlist->rm,rrs); /* Finished building return instantiation of method*/ /* Assign roles to all objects that might have changed*/ { struct ositerator *it=getIterator(heap->changedset); while(hasNext(it)) { struct heap_object *ho=nextobject(it); free(findrolestring(heap, dommap, ho,1)); } freeIterator(it); while(!setisempty(heap->changedset)) { struct heap_object *ho=removeobject(heap->changedset, NULL); struct fieldlist *fl=ho->fl; struct fieldlist *rfl=ho->reversefield; struct arraylist *al=ho->al; struct arraylist *ral=ho->reversearray; while(fl!=NULL) { addrolerelation(heap, fl->src, fl->fieldname, fl->object); fl=fl->next; } while(rfl!=NULL) { addrolerelation(heap, rfl->src, rfl->fieldname, rfl->object); rfl=rfl->dstnext; } while(al!=NULL) { addrolerelation(heap, al->src, getfieldc(heap->namer,al->src->class,"[]", NULL),al->object); al=al->next; } while(ral!=NULL) { addrolerelation(heap, ral->src, getfieldc(heap->namer,ral->src->class,"[]", NULL),ral->object); ral=ral->dstnext; } } } genfreekeyhashtable(dommap); /* Merge in any rolechanges we've observed*/ mergerolechanges(heap); }
int main(int argc, char *argv[]) { extern char **environ; int first_sleep = 1, first_time = 1; struct rlimit limit; int rval; signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH); gethostname(hostname, sizeof(hostname) - 1); hostname[sizeof(hostname) - 1] = '\0'; if (hostname[0] == '\0') strcpy(hostname, "Amnesiac"); /* * Limit running time to deal with broken or dead lines. */ (void)signal(SIGXCPU, timeoverrun); limit.rlim_max = RLIM_INFINITY; limit.rlim_cur = GETTY_TIMEOUT; (void)setrlimit(RLIMIT_CPU, &limit); gettable("default", defent); gendefaults(); tname = "default"; if (argc > 1) tname = argv[1]; /* * The following is a work around for vhangup interactions * which cause great problems getting window systems started. * If the tty line is "-", we do the old style getty presuming * that the file descriptors are already set up for us. * J. Gettys - MIT Project Athena. */ if (argc <= 2 || strcmp(argv[2], "-") == 0) strcpy(ttyn, ttyname(STDIN_FILENO)); else { strcpy(ttyn, dev); strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); if (strcmp(argv[0], "+") != 0) { chown(ttyn, 0, 0); chmod(ttyn, 0600); revoke(ttyn); /* * Do the first scan through gettytab. * Terminal mode parameters will be wrong until * defttymode() called, but they're irrelevant for * the initial setup of the terminal device. */ dogettytab(); /* * Init or answer modem sequence has been specified. */ if (IC || AC) { if (!opentty(ttyn, O_RDWR|O_NONBLOCK)) exit(1); defttymode(); setttymode(1); } if (IC) { if (getty_chat(IC, CT, DC) > 0) { syslog(LOG_ERR, "modem init problem on %s", ttyn); (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); exit(1); } } if (AC) { int i, rfds; struct timeval to; rfds = 1 << 0; /* FD_SET */ to.tv_sec = RT; to.tv_usec = 0; i = select(32, (fd_set*)&rfds, (fd_set*)NULL, (fd_set*)NULL, RT ? &to : NULL); if (i < 0) { syslog(LOG_ERR, "select %s: %m", ttyn); } else if (i == 0) { syslog(LOG_NOTICE, "recycle tty %s", ttyn); (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); exit(0); /* recycle for init */ } i = getty_chat(AC, CT, DC); if (i > 0) { syslog(LOG_ERR, "modem answer problem on %s", ttyn); (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); exit(1); } } else { /* maybe blocking open */ if (!opentty(ttyn, O_RDWR | (NC ? O_NONBLOCK : 0 ))) exit(1); } } } defttymode(); for (;;) { /* * if a delay was specified then sleep for that * number of seconds before writing the initial prompt */ if (first_sleep && DE) { sleep(DE); /* remove any noise */ (void)tcflush(STDIN_FILENO, TCIOFLUSH); } first_sleep = 0; setttymode(0); if (AB) { tname = autobaud(); dogettytab(); continue; } if (PS) { tname = portselector(); dogettytab(); continue; } if (CL && *CL) putpad(CL); edithost(HE); /* if this is the first time through this, and an issue file has been given, then send it */ if (first_time && IF) { int fd; if ((fd = open(IF, O_RDONLY)) != -1) { char * cp; while ((cp = getline(fd)) != NULL) { putf(cp); } close(fd); } } first_time = 0; if (IM && *IM && !(PL && PP)) putf(IM); if (setjmp(timeout)) { cfsetispeed(&tmode, B0); cfsetospeed(&tmode, B0); (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); exit(1); } if (TO) { signal(SIGALRM, dingdong); alarm(TO); } rval = 0; if (AL) { const char *p = AL; char *q = name; while (*p && q < &name[sizeof name - 1]) { if (isupper(*p)) upper = 1; else if (islower(*p)) lower = 1; else if (isdigit(*p)) digit = 1; *q++ = *p++; } } else if (!(PL && PP)) rval = getname(); if (rval == 2 || (PL && PP)) { oflush(); alarm(0); limit.rlim_max = RLIM_INFINITY; limit.rlim_cur = RLIM_INFINITY; (void)setrlimit(RLIMIT_CPU, &limit); execle(PP, "ppplogin", ttyn, (char *) 0, env); syslog(LOG_ERR, "%s: %m", PP); exit(1); } else if (rval || AL) { int i; oflush(); alarm(0); signal(SIGALRM, SIG_DFL); if (name[0] == '\0') continue; if (name[0] == '-') { puts("user names may not start with '-'."); continue; } if (!(upper || lower || digit)) { if (AL) { syslog(LOG_ERR, "invalid auto-login name: %s", AL); exit(1); } else continue; } set_flags(2); if (crmod) { tmode.c_iflag |= ICRNL; tmode.c_oflag |= ONLCR; } #if REALLY_OLD_TTYS if (upper || UC) tmode.sg_flags |= LCASE; if (lower || LC) tmode.sg_flags &= ~LCASE; #endif if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); exit(1); } signal(SIGINT, SIG_DFL); for (i = 0; environ[i] != (char *)0; i++) env[i] = environ[i]; makeenv(&env[i]); limit.rlim_max = RLIM_INFINITY; limit.rlim_cur = RLIM_INFINITY; (void)setrlimit(RLIMIT_CPU, &limit); execle(LO, "login", AL ? "-fp" : "-p", name, (char *) 0, env); syslog(LOG_ERR, "%s: %m", LO); exit(1); } alarm(0); signal(SIGALRM, SIG_DFL); signal(SIGINT, SIG_IGN); if (NX && *NX) { tname = NX; dogettytab(); } } }
int main(int argc, char *argv[]) { extern char **environ; char *tname; int repcnt = 0, failopenlogged = 0; struct rlimit limit; int rval; signal(SIGINT, SIG_IGN); /* signal(SIGQUIT, SIG_DFL); */ openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH); gethostname(hostname, sizeof(hostname)); if (hostname[0] == '\0') strlcpy(hostname, "Amnesiac", sizeof hostname); uname(&kerninfo); /* * Limit running time to deal with broken or dead lines. */ (void)signal(SIGXCPU, timeoverrun); limit.rlim_max = RLIM_INFINITY; limit.rlim_cur = GETTY_TIMEOUT; (void)setrlimit(RLIMIT_CPU, &limit); /* * The following is a work around for vhangup interactions * which cause great problems getting window systems started. * If the tty line is "-", we do the old style getty presuming * that the file descriptors are already set up for us. * J. Gettys - MIT Project Athena. */ if (argc <= 2 || strcmp(argv[2], "-") == 0) { snprintf(ttyn, sizeof ttyn, "%s", ttyname(0)); } else { int i; snprintf(ttyn, sizeof ttyn, "%s%s", dev, argv[2]); if (strcmp(argv[0], "+") != 0) { chown(ttyn, 0, 0); chmod(ttyn, 0600); revoke(ttyn); /* * Delay the open so DTR stays down long enough to be detected. */ sleep(2); while ((i = open(ttyn, O_RDWR)) == -1) { if ((repcnt % 10 == 0) && (errno != ENXIO || !failopenlogged)) { syslog(LOG_ERR, "%s: %m", ttyn); closelog(); failopenlogged = 1; } repcnt++; sleep(60); } login_tty(i); } } /* Start with default tty settings */ if (tcgetattr(0, &tmode) < 0) { syslog(LOG_ERR, "%s: %m", ttyn); exit(1); } omode = tmode; gettable("default", defent); gendefaults(); tname = "default"; if (argc > 1) tname = argv[1]; for (;;) { int off; gettable(tname, tabent); if (OPset || EPset || APset) APset++, OPset++, EPset++; setdefaults(); off = 0; (void)tcflush(0, TCIOFLUSH); /* clear out the crap */ ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */ ioctl(0, FIOASYNC, &off); /* ditto for async mode */ if (IS) cfsetispeed(&tmode, IS); else if (SP) cfsetispeed(&tmode, SP); if (OS) cfsetospeed(&tmode, OS); else if (SP) cfsetospeed(&tmode, SP); setflags(0); setchars(); if (tcsetattr(0, TCSANOW, &tmode) < 0) { syslog(LOG_ERR, "%s: %m", ttyn); exit(1); } if (AB) { tname = autobaud(); continue; } if (PS) { tname = portselector(); continue; } if (CL && *CL) putpad(CL); edithost(HE); if (IM && *IM) putf(IM); if (TO) { signal(SIGALRM, dingdong); alarm(TO); } if ((rval = getname()) == 2) { oflush(); alarm(0); signal(SIGALRM, SIG_DFL); execle(PP, "ppplogin", ttyn, (char *) 0, env); syslog(LOG_ERR, "%s: %m", PP); exit(1); } else if (rval) { int i; oflush(); alarm(0); signal(SIGALRM, SIG_DFL); if (name[0] == '-') { xputs("user names may not start with '-'."); continue; } if (!(upper || lower || digit)) continue; setflags(2); if (crmod) { tmode.c_iflag |= ICRNL; tmode.c_oflag |= ONLCR; } if (upper || UC) { tmode.c_iflag |= IUCLC; tmode.c_oflag |= OLCUC; tmode.c_lflag |= XCASE; } if (lower || LC) { tmode.c_iflag &= ~IUCLC; tmode.c_oflag &= ~OLCUC; tmode.c_lflag &= ~XCASE; } if (tcsetattr(0, TCSANOW, &tmode) < 0) { syslog(LOG_ERR, "%s: %m", ttyn); exit(1); } signal(SIGINT, SIG_DFL); for (i = 0; environ[i] != (char *)0; i++) env[i] = environ[i]; makeenv(&env[i]); limit.rlim_max = RLIM_INFINITY; limit.rlim_cur = RLIM_INFINITY; (void)setrlimit(RLIMIT_CPU, &limit); execle(LO, "login", "-p", "--", name, (char *)0, env); syslog(LOG_ERR, "%s: %m", LO); exit(1); } alarm(0); signal(SIGALRM, SIG_DFL); signal(SIGINT, SIG_IGN); if (NX && *NX) tname = NX; } }
static int elfreadsyms (int fd, Elf32_Ehdr *eh, Elf32_Shdr *shtab, int flags) { Elf32_Shdr *sh, *strh, *shstrh, *ksh; Elf32_Sym *symtab; Elf32_Ehdr *keh; char *shstrtab, *strtab, *symend; int nsym, offs, size, i; int *symptr; /* Fix up twirl */ if (bootseg++ > 0) { fprintf (stderr, "\b + "); } /* * If we are loading symbols to support kernel DDB symbol handling * make room for an ELF header at _end and after that a section * header. DDB then finds the symbols using the data put here. */ if(flags & KFLAG) { tablebase = roundup(tablebase, sizeof(long)); symptr = (int *)tablebase; tablebase += sizeof(int *) * 2; keh = (Elf32_Ehdr *)tablebase; tablebase += sizeof(Elf32_Ehdr); tablebase = roundup(tablebase, sizeof(long)); ksh = (Elf32_Shdr *)tablebase; tablebase += roundup((sizeof(Elf32_Shdr) * eh->e_shnum), sizeof(long)); memcpy(ksh, shtab, roundup((sizeof(Elf32_Shdr) * eh->e_shnum), sizeof(long))); sh = ksh; } else { sh = shtab; } shstrh = &sh[eh->e_shstrndx]; for (i = 0; i < eh->e_shnum; sh++, i++) { if (sh->sh_type == SHT_SYMTAB) { break; } } if (i >= eh->e_shnum) { return (0); } if(flags & KFLAG) { strh = &ksh[sh->sh_link]; nsym = sh->sh_size / sh->sh_entsize; offs = sh->sh_offset; size = sh->sh_size; fprintf (stderr, "%d syms ", nsym); } else { strh = &shtab[sh->sh_link]; nsym = (sh->sh_size / sh->sh_entsize) - sh->sh_info; offs = sh->sh_offset + (sh->sh_info * sh->sh_entsize); size = nsym * sh->sh_entsize; fprintf (stderr, "%d syms ", nsym); } /* * Allocate tables in correct order so the kernel grooks it. * Then we read them in the order they are in the ELF file. */ shstrtab = gettable(shstrh->sh_size, "shstrtab", flags); strtab = gettable(strh->sh_size, "strtab", flags); symtab = gettable(size, "symtab", flags); symend = (char *)symtab + size; do { if(shstrh->sh_offset < offs && shstrh->sh_offset < strh->sh_offset) { #if 0 /* * We would like to read the shstrtab from the file but since this * table is located in front of the shtab it is already gone. We can't * position backwards outside the current segment when using tftp. * Instead we create the names we need in the string table because * it can be reconstructed from the info we now have access to. */ if (!readtable (shstrh->sh_offset, (void *)shstrtab, shstrh->sh_size, "shstring", flags)) { return(0); } #else memset(shstrtab, 0, shstrh->sh_size); strcpy(shstrtab + shstrh->sh_name, ".shstrtab"); strcpy(shstrtab + strh->sh_name, ".strtab"); strcpy(shstrtab + sh->sh_name, ".symtab"); #endif shstrh->sh_offset = 0x7fffffff; } if (offs < strh->sh_offset && offs < shstrh->sh_offset) { if (!(readtable(fd, offs, (void *)symtab, size, "sym", flags))) { return (0); } offs = 0x7fffffff; } if (strh->sh_offset < offs && strh->sh_offset < shstrh->sh_offset) { if (!(readtable (fd, strh->sh_offset, (void *)strtab, strh->sh_size, "string", flags))) { return (0); } strh->sh_offset = 0x7fffffff; } if (offs == 0x7fffffff && strh->sh_offset == 0x7fffffff && shstrh->sh_offset == 0x7fffffff) { break; } } while(1); if(flags & KFLAG) { /* * Update the kernel headers with the current info. */ shstrh->sh_offset = (Elf32_Off)shstrtab - (Elf32_Off)keh; strh->sh_offset = (Elf32_Off)strtab - (Elf32_Off)keh; sh->sh_offset = (Elf32_Off)symtab - (Elf32_Off)keh; memcpy(keh, eh, sizeof(Elf32_Ehdr)); keh->e_phoff = 0; keh->e_shoff = sizeof(Elf32_Ehdr); keh->e_phentsize = 0; keh->e_phnum = 0; printf("\nKernel debugger symbols ELF hdr @ %p", keh); symptr[0] = (int)keh; symptr[1] = roundup((int)symend, sizeof(int)); } else { /* * Add all global sybols to PMONs internal symbol table. */ for (i = 0; i < nsym; i++, symtab++) { int type; dotik (4000, 0); if (symtab->st_shndx == SHN_UNDEF || symtab->st_shndx == SHN_COMMON) { continue; } type = ELF_ST_TYPE (symtab->st_info); if (type == STT_SECTION || type == STT_FILE) { continue; } /* only use globals and functions */ if (ELF_ST_BIND(symtab->st_info) == STB_GLOBAL || type == STT_FUNC){ if (symtab->st_name >= strh->sh_size) { fprintf (stderr, "\ncorrupt string pointer"); return (0); } } if (!newsym (strtab + symtab->st_name, symtab->st_value)) { fprintf (stderr, "\nonly room for %d symbols", i); return (0); } } } return (1); }
static void ktap_execute(ktap_state *ks) { int exec_count = 0; ktap_callinfo *ci; ktap_lclosure *cl; ktap_value *k; unsigned int instr, opcode; StkId base; /* stack pointer */ StkId ra; /* register pointer */ int res, nresults; /* temp varible */ ci = ks->ci; newframe: cl = CLVALUE(ci->func); k = cl->p->k; base = ci->u.l.base; mainloop: /* main loop of interpreter */ /* dead loop detaction */ if (exec_count++ == 10000) { if (G(ks)->mainthread != ks) { kp_error(ks, "non-mainthread executing too much, " "please try to enlarge execution limit\n"); return; } cond_resched(); if (signal_pending(current)) { flush_signals(current); return; } exec_count = 0; } instr = *(ci->u.l.savedpc++); opcode = GET_OPCODE(instr); /* ra is target register */ ra = RA(instr); switch (opcode) { case OP_MOVE: setobj(ra, base + GETARG_B(instr)); break; case OP_LOADK: setobj(ra, k + GETARG_Bx(instr)); break; case OP_LOADKX: setobj(ra, k + GETARG_Ax(*ci->u.l.savedpc++)); break; case OP_LOADBOOL: setbvalue(ra, GETARG_B(instr)); if (GETARG_C(instr)) ci->u.l.savedpc++; break; case OP_LOADNIL: { int b = GETARG_B(instr); do { setnilvalue(ra++); } while (b--); break; } case OP_GETUPVAL: { int b = GETARG_B(instr); setobj(ra, cl->upvals[b]->v); break; } case OP_GETTABUP: { int b = GETARG_B(instr); gettable(ks, cl->upvals[b]->v, RKC(instr), ra); base = ci->u.l.base; break; } case OP_GETTABLE: gettable(ks, RB(instr), RKC(instr), ra); base = ci->u.l.base; break; case OP_SETTABUP: { int a = GETARG_A(instr); settable(ks, cl->upvals[a]->v, RKB(instr), RKC(instr)); base = ci->u.l.base; break; } case OP_SETUPVAL: { ktap_upval *uv = cl->upvals[GETARG_B(instr)]; setobj(uv->v, ra); break; } case OP_SETTABLE: settable(ks, ra, RKB(instr), RKC(instr)); base = ci->u.l.base; break; case OP_NEWTABLE: { int b = GETARG_B(instr); int c = GETARG_C(instr); ktap_table *t = kp_table_new(ks); sethvalue(ra, t); if (b != 0 || c != 0) kp_table_resize(ks, t, fb2int(b), fb2int(c)); break; } case OP_SELF: { StkId rb = RB(instr); setobj(ra+1, rb); gettable(ks, rb, RKC(instr), ra); base = ci->u.l.base; break; } case OP_ADD: arith_op(ks, NUMADD); break; case OP_SUB: arith_op(ks, NUMSUB); break; case OP_MUL: arith_op(ks, NUMMUL); break; case OP_DIV: /* divide 0 checking */ if (!nvalue(RKC(instr))) { kp_error(ks, "divide 0 arith operation\n"); return; } arith_op(ks, NUMDIV); break; case OP_MOD: /* divide 0 checking */ if (!nvalue(RKC(instr))) { kp_error(ks, "mod 0 arith operation\n"); return; } arith_op(ks, NUMMOD); break; case OP_POW: kp_error(ks, "ktap don't support pow arith in kernel\n"); return; case OP_UNM: { ktap_value *rb = RB(instr); if (ttisnumber(rb)) { ktap_number nb = nvalue(rb); setnvalue(ra, NUMUNM(nb)); } break; } case OP_NOT: res = isfalse(RB(instr)); setbvalue(ra, res); break; case OP_LEN: { int len = kp_objlen(ks, RB(instr)); if (len < 0) return; setnvalue(ra, len); break; } case OP_CONCAT: { int b = GETARG_B(instr); int c = GETARG_C(instr); ktap_concat(ks, b, c); break; } case OP_JMP: dojump(ci, instr, 0); break; case OP_EQ: { ktap_value *rb = RKB(instr); ktap_value *rc = RKC(instr); if ((int)equalobj(ks, rb, rc) != GETARG_A(instr)) ci->u.l.savedpc++; else donextjump(ci); base = ci->u.l.base; break; } case OP_LT: if (lessthan(ks, RKB(instr), RKC(instr)) != GETARG_A(instr)) ci->u.l.savedpc++; else donextjump(ci); base = ci->u.l.base; break; case OP_LE: if (lessequal(ks, RKB(instr), RKC(instr)) != GETARG_A(instr)) ci->u.l.savedpc++; else donextjump(ci); base = ci->u.l.base; break; case OP_TEST: if (GETARG_C(instr) ? isfalse(ra) : !isfalse(ra)) ci->u.l.savedpc++; else donextjump(ci); break; case OP_TESTSET: { ktap_value *rb = RB(instr); if (GETARG_C(instr) ? isfalse(rb) : !isfalse(rb)) ci->u.l.savedpc++; else { setobj(ra, rb); donextjump(ci); } break; } case OP_CALL: { int b = GETARG_B(instr); int ret; nresults = GETARG_C(instr) - 1; if (b != 0) ks->top = ra + b; ret = precall(ks, ra, nresults); if (ret) { /* C function */ if (nresults >= 0) ks->top = ci->top; base = ci->u.l.base; break; } else { /* ktap function */ ci = ks->ci; /* this flag is used for return time, see OP_RETURN */ ci->callstatus |= CIST_REENTRY; goto newframe; } break; } case OP_TAILCALL: { int b = GETARG_B(instr); if (b != 0) ks->top = ra+b; if (precall(ks, ra, -1)) /* C function? */ base = ci->u.l.base; else { int aux; /* * tail call: put called frame (n) in place of * caller one (o) */ ktap_callinfo *nci = ks->ci; /* called frame */ ktap_callinfo *oci = nci->prev; /* caller frame */ StkId nfunc = nci->func; /* called function */ StkId ofunc = oci->func; /* caller function */ /* last stack slot filled by 'precall' */ StkId lim = nci->u.l.base + CLVALUE(nfunc)->p->numparams; /* close all upvalues from previous call */ if (cl->p->sizep > 0) function_close(ks, oci->u.l.base); /* move new frame into old one */ for (aux = 0; nfunc + aux < lim; aux++) setobj(ofunc + aux, nfunc + aux); /* correct base */ oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct top */ oci->top = ks->top = ofunc + (ks->top - nfunc); oci->u.l.savedpc = nci->u.l.savedpc; /* remove new frame */ ci = ks->ci = oci; /* restart ktap_execute over new ktap function */ goto newframe; } break; } case OP_RETURN: { int b = GETARG_B(instr); if (b != 0) ks->top = ra+b-1; if (cl->p->sizep > 0) function_close(ks, base); b = poscall(ks, ra); /* if it's called from external invocation, just return */ if (!(ci->callstatus & CIST_REENTRY)) return; ci = ks->ci; if (b) ks->top = ci->top; goto newframe; } case OP_FORLOOP: { ktap_number step = nvalue(ra+2); /* increment index */ ktap_number idx = NUMADD(nvalue(ra), step); ktap_number limit = nvalue(ra+1); if (NUMLT(0, step) ? NUMLE(idx, limit) : NUMLE(limit, idx)) { ci->u.l.savedpc += GETARG_sBx(instr); /* jump back */ setnvalue(ra, idx); /* update internal index... */ setnvalue(ra+3, idx); /* ...and external index */ } break; } case OP_FORPREP: { const ktap_value *init = ra; const ktap_value *plimit = ra + 1; const ktap_value *pstep = ra + 2; if (!ktap_tonumber(init, ra)) { kp_error(ks, KTAP_QL("for") " initial value must be a number\n"); return; } else if (!ktap_tonumber(plimit, ra + 1)) { kp_error(ks, KTAP_QL("for") " limit must be a number\n"); return; } else if (!ktap_tonumber(pstep, ra + 2)) { kp_error(ks, KTAP_QL("for") " step must be a number\n"); return; } setnvalue(ra, NUMSUB(nvalue(ra), nvalue(pstep))); ci->u.l.savedpc += GETARG_sBx(instr); break; } case OP_TFORCALL: { StkId cb = ra + 3; /* call base */ setobj(cb + 2, ra + 2); setobj(cb + 1, ra + 1); setobj(cb, ra); ks->top = cb + 3; /* func. + 2 args (state and index) */ kp_call(ks, cb, GETARG_C(instr)); base = ci->u.l.base; ks->top = ci->top; instr = *(ci->u.l.savedpc++); /* go to next instruction */ ra = RA(instr); } /*go through */ case OP_TFORLOOP: if (!ttisnil(ra + 1)) { /* continue loop? */ setobj(ra, ra + 1); /* save control variable */ ci->u.l.savedpc += GETARG_sBx(instr); /* jump back */ } break; case OP_SETLIST: { int n = GETARG_B(instr); int c = GETARG_C(instr); int last; ktap_table *h; if (n == 0) n = (int)(ks->top - ra) - 1; if (c == 0) c = GETARG_Ax(*ci->u.l.savedpc++); h = hvalue(ra); last = ((c - 1) * LFIELDS_PER_FLUSH) + n; if (last > h->sizearray) /* needs more space? */ kp_table_resizearray(ks, h, last); for (; n > 0; n--) { ktap_value *val = ra+n; kp_table_setint(ks, h, last--, val); } /* correct top (in case of previous open call) */ ks->top = ci->top; break; } case OP_CLOSURE: { /* need to use closure cache? (multithread contention issue)*/ ktap_proto *p = cl->p->p[GETARG_Bx(instr)]; pushclosure(ks, p, cl->upvals, base, ra); break; } case OP_VARARG: { int b = GETARG_B(instr) - 1; int j; int n = (int)(base - ci->func) - cl->p->numparams - 1; if (b < 0) { /* B == 0? */ b = n; /* get all var. arguments */ checkstack(ks, n); /* previous call may change the stack */ ra = RA(instr); ks->top = ra + n; } for (j = 0; j < b; j++) { if (j < n) { setobj(ra + j, base - n + j); } else setnilvalue(ra + j); } break; } case OP_EXTRAARG: return; case OP_EVENT: { struct ktap_event *e = ks->current_event; if (unlikely(!e)) { kp_error(ks, "invalid event context\n"); return; } setevalue(ra, e); break; } case OP_EVENTNAME: { struct ktap_event *e = ks->current_event; if (unlikely(!e)) { kp_error(ks, "invalid event context\n"); return; } setsvalue(ra, kp_tstring_new(ks, e->call->name)); break; } case OP_EVENTARG: if (unlikely(!ks->current_event)) { kp_error(ks, "invalid event context\n"); return; } kp_event_getarg(ks, ra, GETARG_B(instr)); break; case OP_LOAD_GLOBAL: { ktap_value *cfunc = cfunction_cache_get(ks, GETARG_C(instr)); setobj(ra, cfunc); } break; case OP_EXIT: return; } goto mainloop; }