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