github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/testdata/lua-5.3.3-tests/ltests/ltests.c (about) 1 /* 2 ** $Id: ltests.c,v 2.209 2015/10/12 16:38:19 roberto Exp $ 3 ** Internal Module for Debugging of the Lua Implementation 4 ** See Copyright Notice in lua.h 5 */ 6 7 #define ltests_c 8 #define LUA_CORE 9 10 #include "lprefix.h" 11 12 13 #include <limits.h> 14 #include <setjmp.h> 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 19 #include "lua.h" 20 21 #include "lapi.h" 22 #include "lauxlib.h" 23 #include "lcode.h" 24 #include "lctype.h" 25 #include "ldebug.h" 26 #include "ldo.h" 27 #include "lfunc.h" 28 #include "lmem.h" 29 #include "lopcodes.h" 30 #include "lstate.h" 31 #include "lstring.h" 32 #include "ltable.h" 33 #include "lualib.h" 34 35 36 37 /* 38 ** The whole module only makes sense with LUA_DEBUG on 39 */ 40 #if defined(LUA_DEBUG) 41 42 43 void *l_Trick = 0; 44 45 46 int islocked = 0; 47 48 49 #define obj_at(L,k) (L->ci->func + (k)) 50 51 52 static int runC (lua_State *L, lua_State *L1, const char *pc); 53 54 55 static void setnameval (lua_State *L, const char *name, int val) { 56 lua_pushstring(L, name); 57 lua_pushinteger(L, val); 58 lua_settable(L, -3); 59 } 60 61 62 static void pushobject (lua_State *L, const TValue *o) { 63 setobj2s(L, L->top, o); 64 api_incr_top(L); 65 } 66 67 68 static int tpanic (lua_State *L) { 69 fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", 70 lua_tostring(L, -1)); 71 return (exit(EXIT_FAILURE), 0); /* do not return to Lua */ 72 } 73 74 75 /* 76 ** {====================================================================== 77 ** Controlled version for realloc. 78 ** ======================================================================= 79 */ 80 81 #define MARK 0x55 /* 01010101 (a nice pattern) */ 82 83 typedef union Header { 84 L_Umaxalign a; /* ensures maximum alignment for Header */ 85 struct { 86 size_t size; 87 int type; 88 } d; 89 } Header; 90 91 92 #if !defined(EXTERNMEMCHECK) 93 94 /* full memory check */ 95 #define MARKSIZE 16 /* size of marks after each block */ 96 #define fillmem(mem,size) memset(mem, -MARK, size) 97 98 #else 99 100 /* external memory check: don't do it twice */ 101 #define MARKSIZE 0 102 #define fillmem(mem,size) /* empty */ 103 104 #endif 105 106 107 Memcontrol l_memcontrol = 108 {0L, 0L, 0L, 0L, {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L}}; 109 110 111 static void freeblock (Memcontrol *mc, Header *block) { 112 if (block) { 113 size_t size = block->d.size; 114 int i; 115 for (i = 0; i < MARKSIZE; i++) /* check marks after block */ 116 lua_assert(*(cast(char *, block + 1) + size + i) == MARK); 117 mc->objcount[block->d.type]--; 118 fillmem(block, sizeof(Header) + size + MARKSIZE); /* erase block */ 119 free(block); /* actually free block */ 120 mc->numblocks--; /* update counts */ 121 mc->total -= size; 122 } 123 } 124 125 126 void *debug_realloc (void *ud, void *b, size_t oldsize, size_t size) { 127 Memcontrol *mc = cast(Memcontrol *, ud); 128 Header *block = cast(Header *, b); 129 int type; 130 if (mc->memlimit == 0) { /* first time? */ 131 char *limit = getenv("MEMLIMIT"); /* initialize memory limit */ 132 mc->memlimit = limit ? strtoul(limit, NULL, 10) : ULONG_MAX; 133 } 134 if (block == NULL) { 135 type = (oldsize < LUA_NUMTAGS) ? oldsize : 0; 136 oldsize = 0; 137 } 138 else { 139 block--; /* go to real header */ 140 type = block->d.type; 141 lua_assert(oldsize == block->d.size); 142 } 143 if (size == 0) { 144 freeblock(mc, block); 145 return NULL; 146 } 147 else if (size > oldsize && mc->total+size-oldsize > mc->memlimit) 148 return NULL; /* fake a memory allocation error */ 149 else { 150 Header *newblock; 151 int i; 152 size_t commonsize = (oldsize < size) ? oldsize : size; 153 size_t realsize = sizeof(Header) + size + MARKSIZE; 154 if (realsize < size) return NULL; /* arithmetic overflow! */ 155 newblock = cast(Header *, malloc(realsize)); /* alloc a new block */ 156 if (newblock == NULL) return NULL; /* really out of memory? */ 157 if (block) { 158 memcpy(newblock + 1, block + 1, commonsize); /* copy old contents */ 159 freeblock(mc, block); /* erase (and check) old copy */ 160 } 161 /* initialize new part of the block with something weird */ 162 fillmem(cast(char *, newblock + 1) + commonsize, size - commonsize); 163 /* initialize marks after block */ 164 for (i = 0; i < MARKSIZE; i++) 165 *(cast(char *, newblock + 1) + size + i) = MARK; 166 newblock->d.size = size; 167 newblock->d.type = type; 168 mc->total += size; 169 if (mc->total > mc->maxmem) 170 mc->maxmem = mc->total; 171 mc->numblocks++; 172 mc->objcount[type]++; 173 return newblock + 1; 174 } 175 } 176 177 178 /* }====================================================================== */ 179 180 181 182 /* 183 ** {====================================================== 184 ** Functions to check memory consistency 185 ** ======================================================= 186 */ 187 188 189 static int testobjref1 (global_State *g, GCObject *f, GCObject *t) { 190 if (isdead(g,t)) return 0; 191 if (!issweepphase(g)) 192 return !(isblack(f) && iswhite(t)); 193 else return 1; 194 } 195 196 197 static void printobj (global_State *g, GCObject *o) { 198 printf("||%s(%p)-%c(%02X)||", 199 ttypename(novariant(o->tt)), (void *)o, 200 isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', o->marked); 201 } 202 203 204 static int testobjref (global_State *g, GCObject *f, GCObject *t) { 205 int r1 = testobjref1(g, f, t); 206 if (!r1) { 207 printf("%d(%02X) - ", g->gcstate, g->currentwhite); 208 printobj(g, f); 209 printf(" -> "); 210 printobj(g, t); 211 printf("\n"); 212 } 213 return r1; 214 } 215 216 #define checkobjref(g,f,t) \ 217 { if (t) lua_longassert(testobjref(g,f,obj2gco(t))); } 218 219 220 static void checkvalref (global_State *g, GCObject *f, const TValue *t) { 221 lua_assert(!iscollectable(t) || 222 (righttt(t) && testobjref(g, f, gcvalue(t)))); 223 } 224 225 226 static void checktable (global_State *g, Table *h) { 227 unsigned int i; 228 Node *n, *limit = gnode(h, sizenode(h)); 229 GCObject *hgc = obj2gco(h); 230 checkobjref(g, hgc, h->metatable); 231 for (i = 0; i < h->sizearray; i++) 232 checkvalref(g, hgc, &h->array[i]); 233 for (n = gnode(h, 0); n < limit; n++) { 234 if (!ttisnil(gval(n))) { 235 lua_assert(!ttisnil(gkey(n))); 236 checkvalref(g, hgc, gkey(n)); 237 checkvalref(g, hgc, gval(n)); 238 } 239 } 240 } 241 242 243 /* 244 ** All marks are conditional because a GC may happen while the 245 ** prototype is still being created 246 */ 247 static void checkproto (global_State *g, Proto *f) { 248 int i; 249 GCObject *fgc = obj2gco(f); 250 checkobjref(g, fgc, f->cache); 251 checkobjref(g, fgc, f->source); 252 for (i=0; i<f->sizek; i++) { 253 if (ttisstring(f->k + i)) 254 checkobjref(g, fgc, tsvalue(f->k + i)); 255 } 256 for (i=0; i<f->sizeupvalues; i++) 257 checkobjref(g, fgc, f->upvalues[i].name); 258 for (i=0; i<f->sizep; i++) 259 checkobjref(g, fgc, f->p[i]); 260 for (i=0; i<f->sizelocvars; i++) 261 checkobjref(g, fgc, f->locvars[i].varname); 262 } 263 264 265 266 static void checkCclosure (global_State *g, CClosure *cl) { 267 GCObject *clgc = obj2gco(cl); 268 int i; 269 for (i = 0; i < cl->nupvalues; i++) 270 checkvalref(g, clgc, &cl->upvalue[i]); 271 } 272 273 274 static void checkLclosure (global_State *g, LClosure *cl) { 275 GCObject *clgc = obj2gco(cl); 276 int i; 277 checkobjref(g, clgc, cl->p); 278 for (i=0; i<cl->nupvalues; i++) { 279 UpVal *uv = cl->upvals[i]; 280 if (uv) { 281 if (!upisopen(uv)) /* only closed upvalues matter to invariant */ 282 checkvalref(g, clgc, uv->v); 283 lua_assert(uv->refcount > 0); 284 } 285 } 286 } 287 288 289 static int lua_checkpc (lua_State *L, CallInfo *ci) { 290 if (!isLua(ci)) return 1; 291 else { 292 /* if function yielded (inside a hook), real 'func' is in 'extra' field */ 293 StkId f = (L->status != LUA_YIELD || ci != L->ci) 294 ? ci->func 295 : restorestack(L, ci->extra); 296 Proto *p = clLvalue(f)->p; 297 return p->code <= ci->u.l.savedpc && 298 ci->u.l.savedpc <= p->code + p->sizecode; 299 } 300 } 301 302 303 static void checkstack (global_State *g, lua_State *L1) { 304 StkId o; 305 CallInfo *ci; 306 UpVal *uv; 307 lua_assert(!isdead(g, L1)); 308 for (uv = L1->openupval; uv != NULL; uv = uv->u.open.next) 309 lua_assert(upisopen(uv)); /* must be open */ 310 for (ci = L1->ci; ci != NULL; ci = ci->previous) { 311 lua_assert(ci->top <= L1->stack_last); 312 lua_assert(lua_checkpc(L1, ci)); 313 } 314 if (L1->stack) { /* complete thread? */ 315 for (o = L1->stack; o < L1->stack_last + EXTRA_STACK; o++) 316 checkliveness(L1, o); /* entire stack must have valid values */ 317 } 318 else lua_assert(L1->stacksize == 0); 319 } 320 321 322 static void checkobject (global_State *g, GCObject *o, int maybedead) { 323 if (isdead(g, o)) 324 lua_assert(maybedead); 325 else { 326 lua_assert(g->gcstate != GCSpause || iswhite(o)); 327 switch (o->tt) { 328 case LUA_TUSERDATA: { 329 TValue uservalue; 330 Table *mt = gco2u(o)->metatable; 331 checkobjref(g, o, mt); 332 getuservalue(g->mainthread, gco2u(o), &uservalue); 333 checkvalref(g, o, &uservalue); 334 break; 335 } 336 case LUA_TTABLE: { 337 checktable(g, gco2t(o)); 338 break; 339 } 340 case LUA_TTHREAD: { 341 checkstack(g, gco2th(o)); 342 break; 343 } 344 case LUA_TLCL: { 345 checkLclosure(g, gco2lcl(o)); 346 break; 347 } 348 case LUA_TCCL: { 349 checkCclosure(g, gco2ccl(o)); 350 break; 351 } 352 case LUA_TPROTO: { 353 checkproto(g, gco2p(o)); 354 break; 355 } 356 case LUA_TSHRSTR: 357 case LUA_TLNGSTR: { 358 lua_assert(!isgray(o)); /* strings are never gray */ 359 break; 360 } 361 default: lua_assert(0); 362 } 363 } 364 } 365 366 367 #define TESTGRAYBIT 7 368 369 static void checkgraylist (global_State *g, GCObject *o) { 370 ((void)g); /* better to keep it available if we need to print an object */ 371 while (o) { 372 lua_assert(isgray(o)); 373 lua_assert(!testbit(o->marked, TESTGRAYBIT)); 374 l_setbit(o->marked, TESTGRAYBIT); 375 switch (o->tt) { 376 case LUA_TTABLE: o = gco2t(o)->gclist; break; 377 case LUA_TLCL: o = gco2lcl(o)->gclist; break; 378 case LUA_TCCL: o = gco2ccl(o)->gclist; break; 379 case LUA_TTHREAD: o = gco2th(o)->gclist; break; 380 case LUA_TPROTO: o = gco2p(o)->gclist; break; 381 default: lua_assert(0); /* other objects cannot be gray */ 382 } 383 } 384 } 385 386 387 /* 388 ** mark all objects in gray lists with the TESTGRAYBIT, so that 389 ** 'checkmemory' can check that all gray objects are in a gray list 390 */ 391 static void markgrays (global_State *g) { 392 if (!keepinvariant(g)) return; 393 checkgraylist(g, g->gray); 394 checkgraylist(g, g->grayagain); 395 checkgraylist(g, g->weak); 396 checkgraylist(g, g->ephemeron); 397 checkgraylist(g, g->allweak); 398 } 399 400 401 static void checkgray (global_State *g, GCObject *o) { 402 for (; o != NULL; o = o->next) { 403 if (isgray(o)) { 404 lua_assert(!keepinvariant(g) || testbit(o->marked, TESTGRAYBIT)); 405 resetbit(o->marked, TESTGRAYBIT); 406 } 407 lua_assert(!testbit(o->marked, TESTGRAYBIT)); 408 } 409 } 410 411 412 int lua_checkmemory (lua_State *L) { 413 global_State *g = G(L); 414 GCObject *o; 415 int maybedead; 416 if (keepinvariant(g)) { 417 lua_assert(!iswhite(g->mainthread)); 418 lua_assert(!iswhite(gcvalue(&g->l_registry))); 419 } 420 lua_assert(!isdead(g, gcvalue(&g->l_registry))); 421 checkstack(g, g->mainthread); 422 resetbit(g->mainthread->marked, TESTGRAYBIT); 423 lua_assert(g->sweepgc == NULL || issweepphase(g)); 424 markgrays(g); 425 /* check 'fixedgc' list */ 426 for (o = g->fixedgc; o != NULL; o = o->next) { 427 lua_assert(o->tt == LUA_TSHRSTR && isgray(o)); 428 } 429 /* check 'allgc' list */ 430 checkgray(g, g->allgc); 431 maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpallgc); 432 for (o = g->allgc; o != NULL; o = o->next) { 433 checkobject(g, o, maybedead); 434 lua_assert(!tofinalize(o)); 435 } 436 /* check 'finobj' list */ 437 checkgray(g, g->finobj); 438 for (o = g->finobj; o != NULL; o = o->next) { 439 checkobject(g, o, 0); 440 lua_assert(tofinalize(o)); 441 lua_assert(o->tt == LUA_TUSERDATA || o->tt == LUA_TTABLE); 442 } 443 /* check 'tobefnz' list */ 444 checkgray(g, g->tobefnz); 445 for (o = g->tobefnz; o != NULL; o = o->next) { 446 checkobject(g, o, 0); 447 lua_assert(tofinalize(o)); 448 lua_assert(o->tt == LUA_TUSERDATA || o->tt == LUA_TTABLE); 449 } 450 return 0; 451 } 452 453 /* }====================================================== */ 454 455 456 457 /* 458 ** {====================================================== 459 ** Disassembler 460 ** ======================================================= 461 */ 462 463 464 static char *buildop (Proto *p, int pc, char *buff) { 465 Instruction i = p->code[pc]; 466 OpCode o = GET_OPCODE(i); 467 const char *name = luaP_opnames[o]; 468 int line = getfuncline(p, pc); 469 sprintf(buff, "(%4d) %4d - ", line, pc); 470 switch (getOpMode(o)) { 471 case iABC: 472 sprintf(buff+strlen(buff), "%-12s%4d %4d %4d", name, 473 GETARG_A(i), GETARG_B(i), GETARG_C(i)); 474 break; 475 case iABx: 476 sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i)); 477 break; 478 case iAsBx: 479 sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i)); 480 break; 481 case iAx: 482 sprintf(buff+strlen(buff), "%-12s%4d", name, GETARG_Ax(i)); 483 break; 484 } 485 return buff; 486 } 487 488 489 #if 0 490 void luaI_printcode (Proto *pt, int size) { 491 int pc; 492 for (pc=0; pc<size; pc++) { 493 char buff[100]; 494 printf("%s\n", buildop(pt, pc, buff)); 495 } 496 printf("-------\n"); 497 } 498 499 500 void luaI_printinst (Proto *pt, int pc) { 501 char buff[100]; 502 printf("%s\n", buildop(pt, pc, buff)); 503 } 504 #endif 505 506 507 static int listcode (lua_State *L) { 508 int pc; 509 Proto *p; 510 luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 511 1, "Lua function expected"); 512 p = getproto(obj_at(L, 1)); 513 lua_newtable(L); 514 setnameval(L, "maxstack", p->maxstacksize); 515 setnameval(L, "numparams", p->numparams); 516 for (pc=0; pc<p->sizecode; pc++) { 517 char buff[100]; 518 lua_pushinteger(L, pc+1); 519 lua_pushstring(L, buildop(p, pc, buff)); 520 lua_settable(L, -3); 521 } 522 return 1; 523 } 524 525 526 static int listk (lua_State *L) { 527 Proto *p; 528 int i; 529 luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 530 1, "Lua function expected"); 531 p = getproto(obj_at(L, 1)); 532 lua_createtable(L, p->sizek, 0); 533 for (i=0; i<p->sizek; i++) { 534 pushobject(L, p->k+i); 535 lua_rawseti(L, -2, i+1); 536 } 537 return 1; 538 } 539 540 541 static int listlocals (lua_State *L) { 542 Proto *p; 543 int pc = cast_int(luaL_checkinteger(L, 2)) - 1; 544 int i = 0; 545 const char *name; 546 luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 547 1, "Lua function expected"); 548 p = getproto(obj_at(L, 1)); 549 while ((name = luaF_getlocalname(p, ++i, pc)) != NULL) 550 lua_pushstring(L, name); 551 return i-1; 552 } 553 554 /* }====================================================== */ 555 556 557 558 static void printstack (lua_State *L) { 559 int i; 560 int n = lua_gettop(L); 561 for (i = 1; i <= n; i++) { 562 printf("%3d: %s\n", i, luaL_tolstring(L, i, NULL)); 563 lua_pop(L, 1); 564 } 565 printf("\n"); 566 } 567 568 569 static int get_limits (lua_State *L) { 570 lua_createtable(L, 0, 5); 571 setnameval(L, "BITS_INT", LUAI_BITSINT); 572 setnameval(L, "MAXARG_Ax", MAXARG_Ax); 573 setnameval(L, "MAXARG_Bx", MAXARG_Bx); 574 setnameval(L, "MAXARG_sBx", MAXARG_sBx); 575 setnameval(L, "BITS_INT", LUAI_BITSINT); 576 setnameval(L, "LFPF", LFIELDS_PER_FLUSH); 577 setnameval(L, "NUM_OPCODES", NUM_OPCODES); 578 return 1; 579 } 580 581 582 static int mem_query (lua_State *L) { 583 if (lua_isnone(L, 1)) { 584 lua_pushinteger(L, l_memcontrol.total); 585 lua_pushinteger(L, l_memcontrol.numblocks); 586 lua_pushinteger(L, l_memcontrol.maxmem); 587 return 3; 588 } 589 else if (lua_isnumber(L, 1)) { 590 unsigned long limit = cast(unsigned long, luaL_checkinteger(L, 1)); 591 if (limit == 0) limit = ULONG_MAX; 592 l_memcontrol.memlimit = limit; 593 return 0; 594 } 595 else { 596 const char *t = luaL_checkstring(L, 1); 597 int i; 598 for (i = LUA_NUMTAGS - 1; i >= 0; i--) { 599 if (strcmp(t, ttypename(i)) == 0) { 600 lua_pushinteger(L, l_memcontrol.objcount[i]); 601 return 1; 602 } 603 } 604 return luaL_error(L, "unkown type '%s'", t); 605 } 606 } 607 608 609 static int settrick (lua_State *L) { 610 if (ttisnil(obj_at(L, 1))) 611 l_Trick = NULL; 612 else 613 l_Trick = gcvalue(obj_at(L, 1)); 614 return 0; 615 } 616 617 618 static int gc_color (lua_State *L) { 619 TValue *o; 620 luaL_checkany(L, 1); 621 o = obj_at(L, 1); 622 if (!iscollectable(o)) 623 lua_pushstring(L, "no collectable"); 624 else { 625 GCObject *obj = gcvalue(o); 626 lua_pushstring(L, isdead(G(L), obj) ? "dead" : 627 iswhite(obj) ? "white" : 628 isblack(obj) ? "black" : "grey"); 629 } 630 return 1; 631 } 632 633 634 static int gc_state (lua_State *L) { 635 static const char *statenames[] = {"propagate", "atomic", "sweepallgc", 636 "sweepfinobj", "sweeptobefnz", "sweepend", "pause", ""}; 637 static const int states[] = {GCSpropagate, GCSatomic, GCSswpallgc, 638 GCSswpfinobj, GCSswptobefnz, GCSswpend, GCSpause, -1}; 639 int option = states[luaL_checkoption(L, 1, "", statenames)]; 640 if (option == -1) { 641 lua_pushstring(L, statenames[G(L)->gcstate]); 642 return 1; 643 } 644 else { 645 global_State *g = G(L); 646 lua_lock(L); 647 if (option < g->gcstate) { /* must cross 'pause'? */ 648 luaC_runtilstate(L, bitmask(GCSpause)); /* run until pause */ 649 } 650 luaC_runtilstate(L, bitmask(option)); 651 lua_assert(G(L)->gcstate == option); 652 lua_unlock(L); 653 return 0; 654 } 655 } 656 657 658 static int hash_query (lua_State *L) { 659 if (lua_isnone(L, 2)) { 660 luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected"); 661 lua_pushinteger(L, tsvalue(obj_at(L, 1))->hash); 662 } 663 else { 664 TValue *o = obj_at(L, 1); 665 Table *t; 666 luaL_checktype(L, 2, LUA_TTABLE); 667 t = hvalue(obj_at(L, 2)); 668 lua_pushinteger(L, luaH_mainposition(t, o) - t->node); 669 } 670 return 1; 671 } 672 673 674 static int stacklevel (lua_State *L) { 675 unsigned long a = 0; 676 lua_pushinteger(L, (L->top - L->stack)); 677 lua_pushinteger(L, (L->stack_last - L->stack)); 678 lua_pushinteger(L, (unsigned long)&a); 679 return 3; 680 } 681 682 683 static int table_query (lua_State *L) { 684 const Table *t; 685 int i = cast_int(luaL_optinteger(L, 2, -1)); 686 luaL_checktype(L, 1, LUA_TTABLE); 687 t = hvalue(obj_at(L, 1)); 688 if (i == -1) { 689 lua_pushinteger(L, t->sizearray); 690 lua_pushinteger(L, luaH_isdummy(t->node) ? 0 : sizenode(t)); 691 lua_pushinteger(L, t->lastfree - t->node); 692 } 693 else if ((unsigned int)i < t->sizearray) { 694 lua_pushinteger(L, i); 695 pushobject(L, &t->array[i]); 696 lua_pushnil(L); 697 } 698 else if ((i -= t->sizearray) < sizenode(t)) { 699 if (!ttisnil(gval(gnode(t, i))) || 700 ttisnil(gkey(gnode(t, i))) || 701 ttisnumber(gkey(gnode(t, i)))) { 702 pushobject(L, gkey(gnode(t, i))); 703 } 704 else 705 lua_pushliteral(L, "<undef>"); 706 pushobject(L, gval(gnode(t, i))); 707 if (gnext(&t->node[i]) != 0) 708 lua_pushinteger(L, gnext(&t->node[i])); 709 else 710 lua_pushnil(L); 711 } 712 return 3; 713 } 714 715 716 static int string_query (lua_State *L) { 717 stringtable *tb = &G(L)->strt; 718 int s = cast_int(luaL_optinteger(L, 1, 0)) - 1; 719 if (s == -1) { 720 lua_pushinteger(L ,tb->size); 721 lua_pushinteger(L ,tb->nuse); 722 return 2; 723 } 724 else if (s < tb->size) { 725 TString *ts; 726 int n = 0; 727 for (ts = tb->hash[s]; ts != NULL; ts = ts->u.hnext) { 728 setsvalue2s(L, L->top, ts); 729 api_incr_top(L); 730 n++; 731 } 732 return n; 733 } 734 else return 0; 735 } 736 737 738 static int tref (lua_State *L) { 739 int level = lua_gettop(L); 740 luaL_checkany(L, 1); 741 lua_pushvalue(L, 1); 742 lua_pushinteger(L, luaL_ref(L, LUA_REGISTRYINDEX)); 743 lua_assert(lua_gettop(L) == level+1); /* +1 for result */ 744 return 1; 745 } 746 747 static int getref (lua_State *L) { 748 int level = lua_gettop(L); 749 lua_rawgeti(L, LUA_REGISTRYINDEX, luaL_checkinteger(L, 1)); 750 lua_assert(lua_gettop(L) == level+1); 751 return 1; 752 } 753 754 static int unref (lua_State *L) { 755 int level = lua_gettop(L); 756 luaL_unref(L, LUA_REGISTRYINDEX, cast_int(luaL_checkinteger(L, 1))); 757 lua_assert(lua_gettop(L) == level); 758 return 0; 759 } 760 761 762 static int upvalue (lua_State *L) { 763 int n = cast_int(luaL_checkinteger(L, 2)); 764 luaL_checktype(L, 1, LUA_TFUNCTION); 765 if (lua_isnone(L, 3)) { 766 const char *name = lua_getupvalue(L, 1, n); 767 if (name == NULL) return 0; 768 lua_pushstring(L, name); 769 return 2; 770 } 771 else { 772 const char *name = lua_setupvalue(L, 1, n); 773 lua_pushstring(L, name); 774 return 1; 775 } 776 } 777 778 779 static int newuserdata (lua_State *L) { 780 size_t size = cast(size_t, luaL_checkinteger(L, 1)); 781 char *p = cast(char *, lua_newuserdata(L, size)); 782 while (size--) *p++ = '\0'; 783 return 1; 784 } 785 786 787 static int pushuserdata (lua_State *L) { 788 lua_Integer u = luaL_checkinteger(L, 1); 789 lua_pushlightuserdata(L, cast(void *, cast(size_t, u))); 790 return 1; 791 } 792 793 794 static int udataval (lua_State *L) { 795 lua_pushinteger(L, cast(long, lua_touserdata(L, 1))); 796 return 1; 797 } 798 799 800 static int doonnewstack (lua_State *L) { 801 lua_State *L1 = lua_newthread(L); 802 size_t l; 803 const char *s = luaL_checklstring(L, 1, &l); 804 int status = luaL_loadbuffer(L1, s, l, s); 805 if (status == LUA_OK) 806 status = lua_pcall(L1, 0, 0, 0); 807 lua_pushinteger(L, status); 808 return 1; 809 } 810 811 812 static int s2d (lua_State *L) { 813 lua_pushnumber(L, *cast(const double *, luaL_checkstring(L, 1))); 814 return 1; 815 } 816 817 818 static int d2s (lua_State *L) { 819 double d = luaL_checknumber(L, 1); 820 lua_pushlstring(L, cast(char *, &d), sizeof(d)); 821 return 1; 822 } 823 824 825 static int num2int (lua_State *L) { 826 lua_pushinteger(L, lua_tointeger(L, 1)); 827 return 1; 828 } 829 830 831 static int newstate (lua_State *L) { 832 void *ud; 833 lua_Alloc f = lua_getallocf(L, &ud); 834 lua_State *L1 = lua_newstate(f, ud); 835 if (L1) { 836 lua_atpanic(L1, tpanic); 837 lua_pushlightuserdata(L, L1); 838 } 839 else 840 lua_pushnil(L); 841 return 1; 842 } 843 844 845 static lua_State *getstate (lua_State *L) { 846 lua_State *L1 = cast(lua_State *, lua_touserdata(L, 1)); 847 luaL_argcheck(L, L1 != NULL, 1, "state expected"); 848 return L1; 849 } 850 851 852 static int loadlib (lua_State *L) { 853 static const luaL_Reg libs[] = { 854 {"_G", luaopen_base}, 855 {"coroutine", luaopen_coroutine}, 856 {"debug", luaopen_debug}, 857 {"io", luaopen_io}, 858 {"os", luaopen_os}, 859 {"math", luaopen_math}, 860 {"string", luaopen_string}, 861 {"table", luaopen_table}, 862 {NULL, NULL} 863 }; 864 lua_State *L1 = getstate(L); 865 int i; 866 luaL_requiref(L1, "package", luaopen_package, 0); 867 lua_assert(lua_type(L1, -1) == LUA_TTABLE); 868 /* 'requiref' should not reload module already loaded... */ 869 luaL_requiref(L1, "package", NULL, 1); /* seg. fault if it reloads */ 870 /* ...but should return the same module */ 871 lua_assert(lua_compare(L1, -1, -2, LUA_OPEQ)); 872 luaL_getsubtable(L1, LUA_REGISTRYINDEX, "_PRELOAD"); 873 for (i = 0; libs[i].name; i++) { 874 lua_pushcfunction(L1, libs[i].func); 875 lua_setfield(L1, -2, libs[i].name); 876 } 877 return 0; 878 } 879 880 static int closestate (lua_State *L) { 881 lua_State *L1 = getstate(L); 882 lua_close(L1); 883 return 0; 884 } 885 886 static int doremote (lua_State *L) { 887 lua_State *L1 = getstate(L); 888 size_t lcode; 889 const char *code = luaL_checklstring(L, 2, &lcode); 890 int status; 891 lua_settop(L1, 0); 892 status = luaL_loadbuffer(L1, code, lcode, code); 893 if (status == LUA_OK) 894 status = lua_pcall(L1, 0, LUA_MULTRET, 0); 895 if (status != LUA_OK) { 896 lua_pushnil(L); 897 lua_pushstring(L, lua_tostring(L1, -1)); 898 lua_pushinteger(L, status); 899 return 3; 900 } 901 else { 902 int i = 0; 903 while (!lua_isnone(L1, ++i)) 904 lua_pushstring(L, lua_tostring(L1, i)); 905 lua_pop(L1, i-1); 906 return i-1; 907 } 908 } 909 910 911 static int int2fb_aux (lua_State *L) { 912 int b = luaO_int2fb((unsigned int)luaL_checkinteger(L, 1)); 913 lua_pushinteger(L, b); 914 lua_pushinteger(L, (unsigned int)luaO_fb2int(b)); 915 return 2; 916 } 917 918 919 static int log2_aux (lua_State *L) { 920 unsigned int x = (unsigned int)luaL_checkinteger(L, 1); 921 lua_pushinteger(L, luaO_ceillog2(x)); 922 return 1; 923 } 924 925 926 struct Aux { jmp_buf jb; const char *paniccode; lua_State *L; }; 927 928 /* 929 ** does a long-jump back to "main program". 930 */ 931 static int panicback (lua_State *L) { 932 struct Aux *b; 933 lua_checkstack(L, 1); /* open space for 'Aux' struct */ 934 lua_getfield(L, LUA_REGISTRYINDEX, "_jmpbuf"); /* get 'Aux' struct */ 935 b = (struct Aux *)lua_touserdata(L, -1); 936 lua_pop(L, 1); /* remove 'Aux' struct */ 937 runC(b->L, L, b->paniccode); /* run optional panic code */ 938 longjmp(b->jb, 1); 939 return 1; /* to avoid warnings */ 940 } 941 942 static int checkpanic (lua_State *L) { 943 struct Aux b; 944 void *ud; 945 lua_State *L1; 946 const char *code = luaL_checkstring(L, 1); 947 lua_Alloc f = lua_getallocf(L, &ud); 948 b.paniccode = luaL_optstring(L, 2, ""); 949 b.L = L; 950 L1 = lua_newstate(f, ud); /* create new state */ 951 if (L1 == NULL) { /* error? */ 952 lua_pushnil(L); 953 return 1; 954 } 955 lua_atpanic(L1, panicback); /* set its panic function */ 956 lua_pushlightuserdata(L1, &b); 957 lua_setfield(L1, LUA_REGISTRYINDEX, "_jmpbuf"); /* store 'Aux' struct */ 958 if (setjmp(b.jb) == 0) { /* set jump buffer */ 959 runC(L, L1, code); /* run code unprotected */ 960 lua_pushliteral(L, "no errors"); 961 } 962 else { /* error handling */ 963 /* move error message to original state */ 964 lua_pushstring(L, lua_tostring(L1, -1)); 965 } 966 lua_close(L1); 967 return 1; 968 } 969 970 971 972 /* 973 ** {==================================================================== 974 ** function to test the API with C. It interprets a kind of assembler 975 ** language with calls to the API, so the test can be driven by Lua code 976 ** ===================================================================== 977 */ 978 979 980 static void sethookaux (lua_State *L, int mask, int count, const char *code); 981 982 static const char *const delimits = " \t\n,;"; 983 984 static void skip (const char **pc) { 985 for (;;) { 986 if (**pc != '\0' && strchr(delimits, **pc)) (*pc)++; 987 else if (**pc == '#') { 988 while (**pc != '\n' && **pc != '\0') (*pc)++; 989 } 990 else break; 991 } 992 } 993 994 static int getnum_aux (lua_State *L, lua_State *L1, const char **pc) { 995 int res = 0; 996 int sig = 1; 997 skip(pc); 998 if (**pc == '.') { 999 res = cast_int(lua_tointeger(L1, -1)); 1000 lua_pop(L1, 1); 1001 (*pc)++; 1002 return res; 1003 } 1004 else if (**pc == '*') { 1005 res = lua_gettop(L1); 1006 (*pc)++; 1007 return res; 1008 } 1009 else if (**pc == '-') { 1010 sig = -1; 1011 (*pc)++; 1012 } 1013 if (!lisdigit(cast_uchar(**pc))) 1014 luaL_error(L, "number expected (%s)", *pc); 1015 while (lisdigit(cast_uchar(**pc))) res = res*10 + (*(*pc)++) - '0'; 1016 return sig*res; 1017 } 1018 1019 static const char *getstring_aux (lua_State *L, char *buff, const char **pc) { 1020 int i = 0; 1021 skip(pc); 1022 if (**pc == '"' || **pc == '\'') { /* quoted string? */ 1023 int quote = *(*pc)++; 1024 while (**pc != quote) { 1025 if (**pc == '\0') luaL_error(L, "unfinished string in C script"); 1026 buff[i++] = *(*pc)++; 1027 } 1028 (*pc)++; 1029 } 1030 else { 1031 while (**pc != '\0' && !strchr(delimits, **pc)) 1032 buff[i++] = *(*pc)++; 1033 } 1034 buff[i] = '\0'; 1035 return buff; 1036 } 1037 1038 1039 static int getindex_aux (lua_State *L, lua_State *L1, const char **pc) { 1040 skip(pc); 1041 switch (*(*pc)++) { 1042 case 'R': return LUA_REGISTRYINDEX; 1043 case 'G': return luaL_error(L, "deprecated index 'G'"); 1044 case 'U': return lua_upvalueindex(getnum_aux(L, L1, pc)); 1045 default: (*pc)--; return getnum_aux(L, L1, pc); 1046 } 1047 } 1048 1049 1050 static void pushcode (lua_State *L, int code) { 1051 static const char *const codes[] = {"OK", "YIELD", "ERRRUN", 1052 "ERRSYNTAX", "ERRMEM", "ERRGCMM", "ERRERR"}; 1053 lua_pushstring(L, codes[code]); 1054 } 1055 1056 1057 #define EQ(s1) (strcmp(s1, inst) == 0) 1058 1059 #define getnum (getnum_aux(L, L1, &pc)) 1060 #define getstring (getstring_aux(L, buff, &pc)) 1061 #define getindex (getindex_aux(L, L1, &pc)) 1062 1063 1064 static int testC (lua_State *L); 1065 static int Cfunck (lua_State *L, int status, lua_KContext ctx); 1066 1067 /* 1068 ** arithmetic operation encoding for 'arith' instruction 1069 ** LUA_OPIDIV -> \ 1070 ** LUA_OPSHL -> < 1071 ** LUA_OPSHR -> > 1072 ** LUA_OPUNM -> _ 1073 ** LUA_OPBNOT -> ! 1074 */ 1075 static const char ops[] = "+-*%^/\\&|~<>_!"; 1076 1077 static int runC (lua_State *L, lua_State *L1, const char *pc) { 1078 char buff[300]; 1079 int status = 0; 1080 if (pc == NULL) return luaL_error(L, "attempt to runC null script"); 1081 for (;;) { 1082 const char *inst = getstring; 1083 if EQ("") return 0; 1084 else if EQ("absindex") { 1085 lua_pushnumber(L1, lua_absindex(L1, getindex)); 1086 } 1087 else if EQ("append") { 1088 int t = getindex; 1089 int i = lua_rawlen(L1, t); 1090 lua_rawseti(L1, t, i + 1); 1091 } 1092 else if EQ("arith") { 1093 int op; 1094 skip(&pc); 1095 op = strchr(ops, *pc++) - ops; 1096 lua_arith(L1, op); 1097 } 1098 else if EQ("call") { 1099 int narg = getnum; 1100 int nres = getnum; 1101 lua_call(L1, narg, nres); 1102 } 1103 else if EQ("callk") { 1104 int narg = getnum; 1105 int nres = getnum; 1106 int i = getindex; 1107 lua_callk(L1, narg, nres, i, Cfunck); 1108 } 1109 else if EQ("checkstack") { 1110 int sz = getnum; 1111 const char *msg = getstring; 1112 if (*msg == '\0') 1113 msg = NULL; /* to test 'luaL_checkstack' with no message */ 1114 luaL_checkstack(L1, sz, msg); 1115 } 1116 else if EQ("compare") { 1117 const char *opt = getstring; /* EQ, LT, or LE */ 1118 int op = (opt[0] == 'E') ? LUA_OPEQ 1119 : (opt[1] == 'T') ? LUA_OPLT : LUA_OPLE; 1120 int a = getindex; 1121 int b = getindex; 1122 lua_pushboolean(L1, lua_compare(L1, a, b, op)); 1123 } 1124 else if EQ("concat") { 1125 lua_concat(L1, getnum); 1126 } 1127 else if EQ("copy") { 1128 int f = getindex; 1129 lua_copy(L1, f, getindex); 1130 } 1131 else if EQ("func2num") { 1132 lua_CFunction func = lua_tocfunction(L1, getindex); 1133 lua_pushnumber(L1, cast(size_t, func)); 1134 } 1135 else if EQ("getfield") { 1136 int t = getindex; 1137 lua_getfield(L1, t, getstring); 1138 } 1139 else if EQ("getglobal") { 1140 lua_getglobal(L1, getstring); 1141 } 1142 else if EQ("getmetatable") { 1143 if (lua_getmetatable(L1, getindex) == 0) 1144 lua_pushnil(L1); 1145 } 1146 else if EQ("gettable") { 1147 lua_gettable(L1, getindex); 1148 } 1149 else if EQ("gettop") { 1150 lua_pushinteger(L1, lua_gettop(L1)); 1151 } 1152 else if EQ("gsub") { 1153 int a = getnum; int b = getnum; int c = getnum; 1154 luaL_gsub(L1, lua_tostring(L1, a), 1155 lua_tostring(L1, b), 1156 lua_tostring(L1, c)); 1157 } 1158 else if EQ("insert") { 1159 lua_insert(L1, getnum); 1160 } 1161 else if EQ("iscfunction") { 1162 lua_pushboolean(L1, lua_iscfunction(L1, getindex)); 1163 } 1164 else if EQ("isfunction") { 1165 lua_pushboolean(L1, lua_isfunction(L1, getindex)); 1166 } 1167 else if EQ("isnil") { 1168 lua_pushboolean(L1, lua_isnil(L1, getindex)); 1169 } 1170 else if EQ("isnull") { 1171 lua_pushboolean(L1, lua_isnone(L1, getindex)); 1172 } 1173 else if EQ("isnumber") { 1174 lua_pushboolean(L1, lua_isnumber(L1, getindex)); 1175 } 1176 else if EQ("isstring") { 1177 lua_pushboolean(L1, lua_isstring(L1, getindex)); 1178 } 1179 else if EQ("istable") { 1180 lua_pushboolean(L1, lua_istable(L1, getindex)); 1181 } 1182 else if EQ("isudataval") { 1183 lua_pushboolean(L1, lua_islightuserdata(L1, getindex)); 1184 } 1185 else if EQ("isuserdata") { 1186 lua_pushboolean(L1, lua_isuserdata(L1, getindex)); 1187 } 1188 else if EQ("len") { 1189 lua_len(L1, getindex); 1190 } 1191 else if EQ("Llen") { 1192 lua_pushinteger(L1, luaL_len(L1, getindex)); 1193 } 1194 else if EQ("loadfile") { 1195 luaL_loadfile(L1, luaL_checkstring(L1, getnum)); 1196 } 1197 else if EQ("loadstring") { 1198 const char *s = luaL_checkstring(L1, getnum); 1199 luaL_loadstring(L1, s); 1200 } 1201 else if EQ("newmetatable") { 1202 lua_pushboolean(L1, luaL_newmetatable(L1, getstring)); 1203 } 1204 else if EQ("newtable") { 1205 lua_newtable(L1); 1206 } 1207 else if EQ("newthread") { 1208 lua_newthread(L1); 1209 } 1210 else if EQ("newuserdata") { 1211 lua_newuserdata(L1, getnum); 1212 } 1213 else if EQ("next") { 1214 lua_next(L1, -2); 1215 } 1216 else if EQ("objsize") { 1217 lua_pushinteger(L1, lua_rawlen(L1, getindex)); 1218 } 1219 else if EQ("pcall") { 1220 int narg = getnum; 1221 int nres = getnum; 1222 status = lua_pcall(L1, narg, nres, getnum); 1223 } 1224 else if EQ("pcallk") { 1225 int narg = getnum; 1226 int nres = getnum; 1227 int i = getindex; 1228 status = lua_pcallk(L1, narg, nres, 0, i, Cfunck); 1229 } 1230 else if EQ("pop") { 1231 lua_pop(L1, getnum); 1232 } 1233 else if EQ("print") { 1234 int n = getnum; 1235 if (n != 0) { 1236 printf("%s\n", luaL_tolstring(L1, n, NULL)); 1237 lua_pop(L1, 1); 1238 } 1239 else printstack(L1); 1240 } 1241 else if EQ("pushbool") { 1242 lua_pushboolean(L1, getnum); 1243 } 1244 else if EQ("pushcclosure") { 1245 lua_pushcclosure(L1, testC, getnum); 1246 } 1247 else if EQ("pushint") { 1248 lua_pushinteger(L1, getnum); 1249 } 1250 else if EQ("pushnil") { 1251 lua_pushnil(L1); 1252 } 1253 else if EQ("pushnum") { 1254 lua_pushnumber(L1, (lua_Number)getnum); 1255 } 1256 else if EQ("pushstatus") { 1257 pushcode(L1, status); 1258 } 1259 else if EQ("pushstring") { 1260 lua_pushstring(L1, getstring); 1261 } 1262 else if EQ("pushupvalueindex") { 1263 lua_pushinteger(L1, lua_upvalueindex(getnum)); 1264 } 1265 else if EQ("pushvalue") { 1266 lua_pushvalue(L1, getindex); 1267 } 1268 else if EQ("rawgeti") { 1269 int t = getindex; 1270 lua_rawgeti(L1, t, getnum); 1271 } 1272 else if EQ("rawgetp") { 1273 int t = getindex; 1274 lua_rawgetp(L1, t, cast(void *, cast(size_t, getnum))); 1275 } 1276 else if EQ("rawsetp") { 1277 int t = getindex; 1278 lua_rawsetp(L1, t, cast(void *, cast(size_t, getnum))); 1279 } 1280 else if EQ("remove") { 1281 lua_remove(L1, getnum); 1282 } 1283 else if EQ("replace") { 1284 lua_replace(L1, getindex); 1285 } 1286 else if EQ("resume") { 1287 int i = getindex; 1288 status = lua_resume(lua_tothread(L1, i), L, getnum); 1289 } 1290 else if EQ("return") { 1291 int n = getnum; 1292 if (L1 != L) { 1293 int i; 1294 for (i = 0; i < n; i++) 1295 lua_pushstring(L, lua_tostring(L1, -(n - i))); 1296 } 1297 return n; 1298 } 1299 else if EQ("rotate") { 1300 int i = getindex; 1301 lua_rotate(L1, i, getnum); 1302 } 1303 else if EQ("setfield") { 1304 int t = getindex; 1305 lua_setfield(L1, t, getstring); 1306 } 1307 else if EQ("setglobal") { 1308 lua_setglobal(L1, getstring); 1309 } 1310 else if EQ("sethook") { 1311 int mask = getnum; 1312 int count = getnum; 1313 sethookaux(L1, mask, count, getstring); 1314 } 1315 else if EQ("setmetatable") { 1316 lua_setmetatable(L1, getindex); 1317 } 1318 else if EQ("settable") { 1319 lua_settable(L1, getindex); 1320 } 1321 else if EQ("settop") { 1322 lua_settop(L1, getnum); 1323 } 1324 else if EQ("testudata") { 1325 int i = getindex; 1326 lua_pushboolean(L1, luaL_testudata(L1, i, getstring) != NULL); 1327 } 1328 else if EQ("error") { 1329 lua_error(L1); 1330 } 1331 else if EQ("throw") { 1332 #if defined(__cplusplus) 1333 static struct X { int x; } x; 1334 throw x; 1335 #else 1336 luaL_error(L1, "C++"); 1337 #endif 1338 break; 1339 } 1340 else if EQ("tobool") { 1341 lua_pushboolean(L1, lua_toboolean(L1, getindex)); 1342 } 1343 else if EQ("tocfunction") { 1344 lua_pushcfunction(L1, lua_tocfunction(L1, getindex)); 1345 } 1346 else if EQ("tointeger") { 1347 lua_pushinteger(L1, lua_tointeger(L1, getindex)); 1348 } 1349 else if EQ("tonumber") { 1350 lua_pushnumber(L1, lua_tonumber(L1, getindex)); 1351 } 1352 else if EQ("topointer") { 1353 lua_pushnumber(L1, cast(size_t, lua_topointer(L1, getindex))); 1354 } 1355 else if EQ("tostring") { 1356 const char *s = lua_tostring(L1, getindex); 1357 const char *s1 = lua_pushstring(L1, s); 1358 lua_longassert((s == NULL && s1 == NULL) || strcmp(s, s1) == 0); 1359 } 1360 else if EQ("type") { 1361 lua_pushstring(L1, luaL_typename(L1, getnum)); 1362 } 1363 else if EQ("xmove") { 1364 int f = getindex; 1365 int t = getindex; 1366 lua_State *fs = (f == 0) ? L1 : lua_tothread(L1, f); 1367 lua_State *ts = (t == 0) ? L1 : lua_tothread(L1, t); 1368 int n = getnum; 1369 if (n == 0) n = lua_gettop(fs); 1370 lua_xmove(fs, ts, n); 1371 } 1372 else if EQ("yield") { 1373 return lua_yield(L1, getnum); 1374 } 1375 else if EQ("yieldk") { 1376 int nres = getnum; 1377 int i = getindex; 1378 return lua_yieldk(L1, nres, i, Cfunck); 1379 } 1380 else luaL_error(L, "unknown instruction %s", buff); 1381 } 1382 return 0; 1383 } 1384 1385 1386 static int testC (lua_State *L) { 1387 lua_State *L1; 1388 const char *pc; 1389 if (lua_isuserdata(L, 1)) { 1390 L1 = getstate(L); 1391 pc = luaL_checkstring(L, 2); 1392 } 1393 else if (lua_isthread(L, 1)) { 1394 L1 = lua_tothread(L, 1); 1395 pc = luaL_checkstring(L, 2); 1396 } 1397 else { 1398 L1 = L; 1399 pc = luaL_checkstring(L, 1); 1400 } 1401 return runC(L, L1, pc); 1402 } 1403 1404 1405 static int Cfunc (lua_State *L) { 1406 return runC(L, L, lua_tostring(L, lua_upvalueindex(1))); 1407 } 1408 1409 1410 static int Cfunck (lua_State *L, int status, lua_KContext ctx) { 1411 pushcode(L, status); 1412 lua_setglobal(L, "status"); 1413 lua_pushinteger(L, ctx); 1414 lua_setglobal(L, "ctx"); 1415 return runC(L, L, lua_tostring(L, ctx)); 1416 } 1417 1418 1419 static int makeCfunc (lua_State *L) { 1420 luaL_checkstring(L, 1); 1421 lua_pushcclosure(L, Cfunc, lua_gettop(L)); 1422 return 1; 1423 } 1424 1425 1426 /* }====================================================== */ 1427 1428 1429 /* 1430 ** {====================================================== 1431 ** tests for C hooks 1432 ** ======================================================= 1433 */ 1434 1435 /* 1436 ** C hook that runs the C script stored in registry.C_HOOK[L] 1437 */ 1438 static void Chook (lua_State *L, lua_Debug *ar) { 1439 const char *scpt; 1440 const char *const events [] = {"call", "ret", "line", "count", "tailcall"}; 1441 lua_getfield(L, LUA_REGISTRYINDEX, "C_HOOK"); 1442 lua_pushlightuserdata(L, L); 1443 lua_gettable(L, -2); /* get C_HOOK[L] (script saved by sethookaux) */ 1444 scpt = lua_tostring(L, -1); /* not very religious (string will be popped) */ 1445 lua_pop(L, 2); /* remove C_HOOK and script */ 1446 lua_pushstring(L, events[ar->event]); /* may be used by script */ 1447 lua_pushinteger(L, ar->currentline); /* may be used by script */ 1448 runC(L, L, scpt); /* run script from C_HOOK[L] */ 1449 } 1450 1451 1452 /* 1453 ** sets 'registry.C_HOOK[L] = scpt' and sets 'Chook' as a hook 1454 */ 1455 static void sethookaux (lua_State *L, int mask, int count, const char *scpt) { 1456 if (*scpt == '\0') { /* no script? */ 1457 lua_sethook(L, NULL, 0, 0); /* turn off hooks */ 1458 return; 1459 } 1460 lua_getfield(L, LUA_REGISTRYINDEX, "C_HOOK"); /* get C_HOOK table */ 1461 if (!lua_istable(L, -1)) { /* no hook table? */ 1462 lua_pop(L, 1); /* remove previous value */ 1463 lua_newtable(L); /* create new C_HOOK table */ 1464 lua_pushvalue(L, -1); 1465 lua_setfield(L, LUA_REGISTRYINDEX, "C_HOOK"); /* register it */ 1466 } 1467 lua_pushlightuserdata(L, L); 1468 lua_pushstring(L, scpt); 1469 lua_settable(L, -3); /* C_HOOK[L] = script */ 1470 lua_sethook(L, Chook, mask, count); 1471 } 1472 1473 1474 static int sethook (lua_State *L) { 1475 if (lua_isnoneornil(L, 1)) 1476 lua_sethook(L, NULL, 0, 0); /* turn off hooks */ 1477 else { 1478 const char *scpt = luaL_checkstring(L, 1); 1479 const char *smask = luaL_checkstring(L, 2); 1480 int count = cast_int(luaL_optinteger(L, 3, 0)); 1481 int mask = 0; 1482 if (strchr(smask, 'c')) mask |= LUA_MASKCALL; 1483 if (strchr(smask, 'r')) mask |= LUA_MASKRET; 1484 if (strchr(smask, 'l')) mask |= LUA_MASKLINE; 1485 if (count > 0) mask |= LUA_MASKCOUNT; 1486 sethookaux(L, mask, count, scpt); 1487 } 1488 return 0; 1489 } 1490 1491 1492 static int coresume (lua_State *L) { 1493 int status; 1494 lua_State *co = lua_tothread(L, 1); 1495 luaL_argcheck(L, co, 1, "coroutine expected"); 1496 status = lua_resume(co, L, 0); 1497 if (status != LUA_OK && status != LUA_YIELD) { 1498 lua_pushboolean(L, 0); 1499 lua_insert(L, -2); 1500 return 2; /* return false + error message */ 1501 } 1502 else { 1503 lua_pushboolean(L, 1); 1504 return 1; 1505 } 1506 } 1507 1508 /* }====================================================== */ 1509 1510 1511 1512 static const struct luaL_Reg tests_funcs[] = { 1513 {"checkmemory", lua_checkmemory}, 1514 {"closestate", closestate}, 1515 {"d2s", d2s}, 1516 {"doonnewstack", doonnewstack}, 1517 {"doremote", doremote}, 1518 {"gccolor", gc_color}, 1519 {"gcstate", gc_state}, 1520 {"getref", getref}, 1521 {"hash", hash_query}, 1522 {"int2fb", int2fb_aux}, 1523 {"log2", log2_aux}, 1524 {"limits", get_limits}, 1525 {"listcode", listcode}, 1526 {"listk", listk}, 1527 {"listlocals", listlocals}, 1528 {"loadlib", loadlib}, 1529 {"checkpanic", checkpanic}, 1530 {"newstate", newstate}, 1531 {"newuserdata", newuserdata}, 1532 {"num2int", num2int}, 1533 {"pushuserdata", pushuserdata}, 1534 {"querystr", string_query}, 1535 {"querytab", table_query}, 1536 {"ref", tref}, 1537 {"resume", coresume}, 1538 {"s2d", s2d}, 1539 {"sethook", sethook}, 1540 {"stacklevel", stacklevel}, 1541 {"testC", testC}, 1542 {"makeCfunc", makeCfunc}, 1543 {"totalmem", mem_query}, 1544 {"trick", settrick}, 1545 {"udataval", udataval}, 1546 {"unref", unref}, 1547 {"upvalue", upvalue}, 1548 {NULL, NULL} 1549 }; 1550 1551 1552 static void checkfinalmem (void) { 1553 lua_assert(l_memcontrol.numblocks == 0); 1554 lua_assert(l_memcontrol.total == 0); 1555 } 1556 1557 1558 int luaB_opentests (lua_State *L) { 1559 void *ud; 1560 lua_atpanic(L, &tpanic); 1561 atexit(checkfinalmem); 1562 lua_assert(lua_getallocf(L, &ud) == debug_realloc); 1563 lua_assert(ud == cast(void *, &l_memcontrol)); 1564 lua_setallocf(L, lua_getallocf(L, NULL), ud); 1565 luaL_newlib(L, tests_funcs); 1566 return 1; 1567 } 1568 1569 #endif 1570