gateway: simplify stopping the cleanup timer
[olsrd.git] / lib / tas / src / lua / ltests.c
1
2 /*
3 ** $Id: ltests.c,v 1.158 2003/04/07 14:35:00 roberto Exp $
4 ** Internal Module for Debugging of the Lua Implementation
5 ** See Copyright Notice in lua.h
6 */
7
8
9 #include <ctype.h>
10 #include <limits.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #define ltests_c
16
17 #include "lua.h"
18
19 #include "lapi.h"
20 #include "lauxlib.h"
21 #include "lcode.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 #ifdef LUA_DEBUG
38
39
40 #define lua_pushintegral(L,i)   lua_pushnumber(L, cast(lua_Number, (i)))
41
42
43 static lua_State *lua_state = NULL;
44
45 int islocked = 0;
46
47
48 #define func_at(L,k)    (L->ci->base+(k) - 1)
49
50
51 static void
52 setnameval(lua_State * L, const char *name, int val)
53 {
54   lua_pushstring(L, name);
55   lua_pushintegral(L, val);
56   lua_settable(L, -3);
57 }
58
59
60 /*
61 ** {======================================================================
62 ** Controlled version for realloc.
63 ** =======================================================================
64 */
65
66 #define MARK            0x55    /* 01010101 (a nice pattern) */
67
68 #ifndef EXTERNMEMCHECK
69
70 /* full memory check */
71 #define HEADER  (sizeof(L_Umaxalign))   /* ensures maximum alignment for HEADER */
72 #define MARKSIZE        16      /* size of marks after each block */
73 #define blockhead(b)    (cast(char *, b) - HEADER)
74 #define setsize(newblock, size) (*cast(size_t *, newblock) = size)
75 #define checkblocksize(b, size) (size == (*cast(size_t *, blockhead(b))))
76 #define fillmem(mem,size)       memset(mem, -MARK, size)
77 #else
78
79 /* external memory check: don't do it twice */
80 #define HEADER          0
81 #define MARKSIZE        0
82 #define blockhead(b)    (b)
83 #define setsize(newblock, size) /* empty */
84 #define checkblocksize(b,size)  (1)
85 #define fillmem(mem,size)       /* empty */
86 #endif
87
88 unsigned long memdebug_numblocks = 0;
89 unsigned long memdebug_total = 0;
90 unsigned long memdebug_maxmem = 0;
91 unsigned long memdebug_memlimit = ULONG_MAX;
92
93
94 static void *
95 checkblock(void *block, size_t size)
96 {
97   void *b = blockhead(block);
98   int i;
99   for (i = 0; i < MARKSIZE; i++)
100     lua_assert(*(cast(char *, b) + HEADER + size + i) == MARK + i);     /* corrupted block? */
101   return b;
102 }
103
104
105 static void
106 freeblock(void *block, size_t size)
107 {
108   if (block) {
109     lua_assert(checkblocksize(block, size));
110     block = checkblock(block, size);
111     fillmem(block, size + HEADER + MARKSIZE);   /* erase block */
112     free(block);                /* free original block */
113     memdebug_numblocks--;
114     memdebug_total -= size;
115   }
116 }
117
118
119 void *
120 debug_realloc(void *block, size_t oldsize, size_t size)
121 {
122   lua_assert(oldsize == 0 || checkblocksize(block, oldsize));
123   /* ISO does not specify what realloc(NULL, 0) does */
124   lua_assert(block != NULL || size > 0);
125   if (size == 0) {
126     freeblock(block, oldsize);
127     return NULL;
128   } else if (size > oldsize && memdebug_total + size - oldsize > memdebug_memlimit)
129     return NULL;                /* to test memory allocation errors */
130   else {
131     void *newblock;
132     int i;
133     size_t realsize = HEADER + size + MARKSIZE;
134     size_t commonsize = (oldsize < size) ? oldsize : size;
135     if (realsize < size)
136       return NULL;              /* overflow! */
137     newblock = malloc(realsize);        /* alloc a new block */
138     if (newblock == NULL)
139       return NULL;
140     if (block) {
141       memcpy(cast(char *, newblock) + HEADER, block, commonsize);
142       freeblock(block, oldsize);        /* erase (and check) old copy */
143     }
144     /* initialize new part of the block with something `weird' */
145     fillmem(cast(char *, newblock) + HEADER + commonsize, size - commonsize);
146     memdebug_total += size;
147     if (memdebug_total > memdebug_maxmem)
148       memdebug_maxmem = memdebug_total;
149     memdebug_numblocks++;
150     setsize(newblock, size);
151     for (i = 0; i < MARKSIZE; i++)
152       *(cast(char *, newblock) + HEADER + size + i) = cast(char, MARK + i);
153     return cast(char *, newblock)+HEADER;
154   }
155 }
156
157
158 /* }====================================================================== */
159
160
161
162 /*
163 ** {======================================================
164 ** Disassembler
165 ** =======================================================
166 */
167
168
169 static char *
170 buildop(Proto * p, int pc, char *buff)
171 {
172   Instruction i = p->code[pc];
173   OpCode o = GET_OPCODE(i);
174   const char *name = luaP_opnames[o];
175   int line = getline(p, pc);
176   sprintf(buff, "(%4d) %4d - ", line, pc);
177   switch (getOpMode(o)) {
178   case iABC:
179     sprintf(buff + strlen(buff), "%-12s%4d %4d %4d", name, GETARG_A(i), GETARG_B(i), GETARG_C(i));
180     break;
181   case iABx:
182     sprintf(buff + strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i));
183     break;
184   case iAsBx:
185     sprintf(buff + strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i));
186     break;
187   }
188   return buff;
189 }
190
191
192 #if 0
193 void
194 luaI_printcode(Proto * pt, int size)
195 {
196   int pc;
197   for (pc = 0; pc < size; pc++) {
198     char buff[100];
199     printf("%s\n", buildop(pt, pc, buff));
200   }
201   printf("-------\n");
202 }
203 #endif
204
205
206 static int
207 listcode(lua_State * L)
208 {
209   int pc;
210   Proto *p;
211   luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, "Lua function expected");
212   p = clvalue(func_at(L, 1))->l.p;
213   lua_newtable(L);
214   setnameval(L, "maxstack", p->maxstacksize);
215   setnameval(L, "numparams", p->numparams);
216   for (pc = 0; pc < p->sizecode; pc++) {
217     char buff[100];
218     lua_pushintegral(L, pc + 1);
219     lua_pushstring(L, buildop(p, pc, buff));
220     lua_settable(L, -3);
221   }
222   return 1;
223 }
224
225
226 static int
227 listk(lua_State * L)
228 {
229   Proto *p;
230   int i;
231   luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, "Lua function expected");
232   p = clvalue(func_at(L, 1))->l.p;
233   lua_newtable(L);
234   for (i = 0; i < p->sizek; i++) {
235     lua_pushintegral(L, i + 1);
236     luaA_pushobject(L, p->k + i);
237     lua_settable(L, -3);
238   }
239   return 1;
240 }
241
242
243 static int
244 listlocals(lua_State * L)
245 {
246   Proto *p;
247   int pc = luaL_checkint(L, 2) - 1;
248   int i = 0;
249   const char *name;
250   luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, "Lua function expected");
251   p = clvalue(func_at(L, 1))->l.p;
252   while ((name = luaF_getlocalname(p, ++i, pc)) != NULL)
253     lua_pushstring(L, name);
254   return i - 1;
255 }
256
257 /* }====================================================== */
258
259
260
261
262 static int
263 get_limits(lua_State * L)
264 {
265   lua_newtable(L);
266   setnameval(L, "BITS_INT", BITS_INT);
267   setnameval(L, "LFPF", LFIELDS_PER_FLUSH);
268   setnameval(L, "MAXVARS", MAXVARS);
269   setnameval(L, "MAXPARAMS", MAXPARAMS);
270   setnameval(L, "MAXSTACK", MAXSTACK);
271   setnameval(L, "MAXUPVALUES", MAXUPVALUES);
272   return 1;
273 }
274
275
276 static int
277 mem_query(lua_State * L)
278 {
279   if (lua_isnone(L, 1)) {
280     lua_pushintegral(L, memdebug_total);
281     lua_pushintegral(L, memdebug_numblocks);
282     lua_pushintegral(L, memdebug_maxmem);
283     return 3;
284   } else {
285     memdebug_memlimit = luaL_checkint(L, 1);
286     return 0;
287   }
288 }
289
290
291 static int
292 hash_query(lua_State * L)
293 {
294   if (lua_isnone(L, 2)) {
295     luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected");
296     lua_pushintegral(L, tsvalue(func_at(L, 1))->tsv.hash);
297   } else {
298     TObject *o = func_at(L, 1);
299     Table *t;
300     luaL_checktype(L, 2, LUA_TTABLE);
301     t = hvalue(func_at(L, 2));
302     lua_pushintegral(L, luaH_mainposition(t, o) - t->node);
303   }
304   return 1;
305 }
306
307
308 static int
309 stacklevel(lua_State * L)
310 {
311   unsigned long a = 0;
312   lua_pushintegral(L, (int)(L->top - L->stack));
313   lua_pushintegral(L, (int)(L->stack_last - L->stack));
314   lua_pushintegral(L, (int)(L->ci - L->base_ci));
315   lua_pushintegral(L, (int)(L->end_ci - L->base_ci));
316   lua_pushintegral(L, (unsigned long)&a);
317   return 5;
318 }
319
320
321 static int
322 table_query(lua_State * L)
323 {
324   const Table *t;
325   int i = luaL_optint(L, 2, -1);
326   luaL_checktype(L, 1, LUA_TTABLE);
327   t = hvalue(func_at(L, 1));
328   if (i == -1) {
329     lua_pushintegral(L, t->sizearray);
330     lua_pushintegral(L, sizenode(t));
331     lua_pushintegral(L, t->firstfree - t->node);
332   } else if (i < t->sizearray) {
333     lua_pushintegral(L, i);
334     luaA_pushobject(L, &t->array[i]);
335     lua_pushnil(L);
336   } else if ((i -= t->sizearray) < sizenode(t)) {
337     if (!ttisnil(gval(gnode(t, i))) || ttisnil(gkey(gnode(t, i))) || ttisnumber(gkey(gnode(t, i)))) {
338       luaA_pushobject(L, gkey(gnode(t, i)));
339     } else
340       lua_pushstring(L, "<undef>");
341     luaA_pushobject(L, gval(gnode(t, i)));
342     if (t->node[i].next)
343       lua_pushintegral(L, t->node[i].next - t->node);
344     else
345       lua_pushnil(L);
346   }
347   return 3;
348 }
349
350
351 static int
352 string_query(lua_State * L)
353 {
354   stringtable *tb = &G(L)->strt;
355   int s = luaL_optint(L, 2, 0) - 1;
356   if (s == -1) {
357     lua_pushintegral(L, tb->nuse);
358     lua_pushintegral(L, tb->size);
359     return 2;
360   } else if (s < tb->size) {
361     GCObject *ts;
362     int n = 0;
363     for (ts = tb->hash[s]; ts; ts = ts->gch.next) {
364       setsvalue2s(L->top, gcotots(ts));
365       incr_top(L);
366       n++;
367     }
368     return n;
369   }
370   return 0;
371 }
372
373
374 static int
375 tref(lua_State * L)
376 {
377   int level = lua_gettop(L);
378   int lock = luaL_optint(L, 2, 1);
379   luaL_checkany(L, 1);
380   lua_pushvalue(L, 1);
381   lua_pushintegral(L, lua_ref(L, lock));
382   assert(lua_gettop(L) == level + 1);   /* +1 for result */
383   return 1;
384 }
385
386 static int
387 getref(lua_State * L)
388 {
389   int level = lua_gettop(L);
390   lua_getref(L, luaL_checkint(L, 1));
391   assert(lua_gettop(L) == level + 1);
392   return 1;
393 }
394
395 static int
396 unref(lua_State * L)
397 {
398   int level = lua_gettop(L);
399   lua_unref(L, luaL_checkint(L, 1));
400   assert(lua_gettop(L) == level);
401   return 0;
402 }
403
404 static int
405 metatable(lua_State * L)
406 {
407   luaL_checkany(L, 1);
408   if (lua_isnone(L, 2)) {
409     if (lua_getmetatable(L, 1) == 0)
410       lua_pushnil(L);
411   } else {
412     lua_settop(L, 2);
413     luaL_checktype(L, 2, LUA_TTABLE);
414     lua_setmetatable(L, 1);
415   }
416   return 1;
417 }
418
419
420 static int
421 upvalue(lua_State * L)
422 {
423   int n = luaL_checkint(L, 2);
424   luaL_checktype(L, 1, LUA_TFUNCTION);
425   if (lua_isnone(L, 3)) {
426     const char *name = lua_getupvalue(L, 1, n);
427     if (name == NULL)
428       return 0;
429     lua_pushstring(L, name);
430     return 2;
431   } else {
432     const char *name = lua_setupvalue(L, 1, n);
433     lua_pushstring(L, name);
434     return 1;
435   }
436 }
437
438
439 static int
440 newuserdata(lua_State * L)
441 {
442   size_t size = luaL_checkint(L, 1);
443   char *p = cast(char *, lua_newuserdata(L, size));
444   while (size--)
445     *p++ = '\0';
446   return 1;
447 }
448
449
450 static int
451 pushuserdata(lua_State * L)
452 {
453   lua_pushlightuserdata(L, cast(void *, luaL_checkint(L, 1)));
454   return 1;
455 }
456
457
458 static int
459 udataval(lua_State * L)
460 {
461   lua_pushintegral(L, cast(int, lua_touserdata(L, 1)));
462   return 1;
463 }
464
465
466 static int
467 doonnewstack(lua_State * L)
468 {
469   lua_State *L1 = lua_newthread(L);
470   size_t l;
471   const char *s = luaL_checklstring(L, 1, &l);
472   int status = luaL_loadbuffer(L1, s, l, s);
473   if (status == 0)
474     status = lua_pcall(L1, 0, 0, 0);
475   lua_pushintegral(L, status);
476   return 1;
477 }
478
479
480 static int
481 s2d(lua_State * L)
482 {
483   lua_pushnumber(L, *cast(const double *, luaL_checkstring(L, 1)));
484   return 1;
485 }
486
487 static int
488 d2s(lua_State * L)
489 {
490   double d = luaL_checknumber(L, 1);
491   lua_pushlstring(L, cast(char *, &d), sizeof(d));
492   return 1;
493 }
494
495
496 static int
497 newstate(lua_State * L)
498 {
499   lua_State *L1 = lua_open();
500   if (L1) {
501     lua_userstateopen(L1);      /* init lock */
502     lua_pushintegral(L, (unsigned long)L1);
503   } else
504     lua_pushnil(L);
505   return 1;
506 }
507
508
509 static int
510 loadlib(lua_State * L)
511 {
512   static const luaL_reg libs[] = {
513     {"mathlibopen", luaopen_math},
514     {"strlibopen", luaopen_string},
515     {"iolibopen", luaopen_io},
516     {"tablibopen", luaopen_table},
517     {"dblibopen", luaopen_debug},
518     {"baselibopen", luaopen_base},
519     {NULL, NULL}
520   };
521   lua_State *L1 = cast(lua_State *,
522                        cast(unsigned long, luaL_checknumber(L, 1)));
523   lua_pushvalue(L1, LUA_GLOBALSINDEX);
524   luaL_openlib(L1, NULL, libs, 0);
525   return 0;
526 }
527
528 static int
529 closestate(lua_State * L)
530 {
531   lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_checknumber(L, 1)));
532   lua_close(L1);
533   lua_unlock(L);                /* close cannot unlock that */
534   return 0;
535 }
536
537 static int
538 doremote(lua_State * L)
539 {
540   lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_checknumber(L, 1)));
541   size_t lcode;
542   const char *code = luaL_checklstring(L, 2, &lcode);
543   int status;
544   lua_settop(L1, 0);
545   status = luaL_loadbuffer(L1, code, lcode, code);
546   if (status == 0)
547     status = lua_pcall(L1, 0, LUA_MULTRET, 0);
548   if (status != 0) {
549     lua_pushnil(L);
550     lua_pushintegral(L, status);
551     lua_pushstring(L, lua_tostring(L1, -1));
552     return 3;
553   } else {
554     int i = 0;
555     while (!lua_isnone(L1, ++i))
556       lua_pushstring(L, lua_tostring(L1, i));
557     lua_pop(L1, i - 1);
558     return i - 1;
559   }
560 }
561
562
563 static int
564 log2_aux(lua_State * L)
565 {
566   lua_pushintegral(L, luaO_log2(luaL_checkint(L, 1)));
567   return 1;
568 }
569
570 static int
571 int2fb_aux(lua_State * L)
572 {
573   int b = luaO_int2fb(luaL_checkint(L, 1));
574   lua_pushintegral(L, b);
575   lua_pushintegral(L, fb2int(b));
576   return 2;
577 }
578
579
580 static int
581 test_do(lua_State * L)
582 {
583   const char *p = luaL_checkstring(L, 1);
584   if (*p == '@')
585     lua_dofile(L, p + 1);
586   else
587     lua_dostring(L, p);
588   return lua_gettop(L);
589 }
590
591
592
593 /*
594 ** {======================================================
595 ** function to test the API with C. It interprets a kind of assembler
596 ** language with calls to the API, so the test can be driven by Lua code
597 ** =======================================================
598 */
599
600 static const char *const delimits = " \t\n,;";
601
602 static void
603 skip(const char **pc)
604 {
605   while (**pc != '\0' && strchr(delimits, **pc))
606     (*pc)++;
607 }
608
609 static int
610 getnum_aux(lua_State * L, const char **pc)
611 {
612   int res = 0;
613   int sig = 1;
614   skip(pc);
615   if (**pc == '.') {
616     res = cast(int, lua_tonumber(L, -1));
617     lua_pop(L, 1);
618     (*pc)++;
619     return res;
620   } else if (**pc == '-') {
621     sig = -1;
622     (*pc)++;
623   }
624   while (isdigit(cast(int, **pc)))
625       res = res * 10 + (*(*pc)++) - '0';
626   return sig * res;
627 }
628
629 static const char *
630 getname_aux(char *buff, const char **pc)
631 {
632   int i = 0;
633   skip(pc);
634   while (**pc != '\0' && !strchr(delimits, **pc))
635     buff[i++] = *(*pc)++;
636   buff[i] = '\0';
637   return buff;
638 }
639
640
641 #define EQ(s1)  (strcmp(s1, inst) == 0)
642
643 #define getnum  (getnum_aux(L, &pc))
644 #define getname (getname_aux(buff, &pc))
645
646
647 static int
648 testC(lua_State * L)
649 {
650   char buff[30];
651   const char *pc = luaL_checkstring(L, 1);
652   for (;;) {
653     const char *inst = getname;
654     if EQ
655       ("") return 0;
656     else if EQ
657       ("isnumber") {
658       lua_pushintegral(L, lua_isnumber(L, getnum));
659     } else if EQ
660       ("isstring") {
661       lua_pushintegral(L, lua_isstring(L, getnum));
662     } else if EQ
663       ("istable") {
664       lua_pushintegral(L, lua_istable(L, getnum));
665     } else if EQ
666       ("iscfunction") {
667       lua_pushintegral(L, lua_iscfunction(L, getnum));
668     } else if EQ
669       ("isfunction") {
670       lua_pushintegral(L, lua_isfunction(L, getnum));
671     } else if EQ
672       ("isuserdata") {
673       lua_pushintegral(L, lua_isuserdata(L, getnum));
674     } else if EQ
675       ("isudataval") {
676       lua_pushintegral(L, lua_islightuserdata(L, getnum));
677     } else if EQ
678       ("isnil") {
679       lua_pushintegral(L, lua_isnil(L, getnum));
680     } else if EQ
681       ("isnull") {
682       lua_pushintegral(L, lua_isnone(L, getnum));
683     } else if EQ
684       ("tonumber") {
685       lua_pushnumber(L, lua_tonumber(L, getnum));
686     } else if EQ
687       ("tostring") {
688       const char *s = lua_tostring(L, getnum);
689       lua_pushstring(L, s);
690     } else if EQ
691       ("strlen") {
692       lua_pushintegral(L, lua_strlen(L, getnum));
693     } else if EQ
694       ("tocfunction") {
695       lua_pushcfunction(L, lua_tocfunction(L, getnum));
696     } else if EQ
697       ("return") {
698       return getnum;
699     } else if EQ
700       ("gettop") {
701       lua_pushintegral(L, lua_gettop(L));
702     } else if EQ
703       ("settop") {
704       lua_settop(L, getnum);
705     } else if EQ
706       ("pop") {
707       lua_pop(L, getnum);
708     } else if EQ
709       ("pushnum") {
710       lua_pushintegral(L, getnum);
711     } else if EQ
712       ("pushnil") {
713       lua_pushnil(L);
714     } else if EQ
715       ("pushbool") {
716       lua_pushboolean(L, getnum);
717     } else if EQ
718       ("tobool") {
719       lua_pushintegral(L, lua_toboolean(L, getnum));
720     } else if EQ
721       ("pushvalue") {
722       lua_pushvalue(L, getnum);
723     } else if EQ
724       ("pushcclosure") {
725       lua_pushcclosure(L, testC, getnum);
726     } else if EQ
727       ("pushupvalues") {
728       lua_pushupvalues(L);
729     } else if EQ
730       ("remove") {
731       lua_remove(L, getnum);
732     } else if EQ
733       ("insert") {
734       lua_insert(L, getnum);
735     } else if EQ
736       ("replace") {
737       lua_replace(L, getnum);
738     } else if EQ
739       ("gettable") {
740       lua_gettable(L, getnum);
741     } else if EQ
742       ("settable") {
743       lua_settable(L, getnum);
744     } else if EQ
745       ("next") {
746       lua_next(L, -2);
747     } else if EQ
748       ("concat") {
749       lua_concat(L, getnum);
750     } else if EQ
751       ("lessthan") {
752       int a = getnum;
753       lua_pushboolean(L, lua_lessthan(L, a, getnum));
754     } else if EQ
755       ("equal") {
756       int a = getnum;
757       lua_pushboolean(L, lua_equal(L, a, getnum));
758     } else if EQ
759       ("rawcall") {
760       int narg = getnum;
761       int nres = getnum;
762       lua_call(L, narg, nres);
763     } else if EQ
764       ("call") {
765       int narg = getnum;
766       int nres = getnum;
767       lua_pcall(L, narg, nres, 0);
768     } else if EQ
769       ("loadstring") {
770       size_t sl;
771       const char *s = luaL_checklstring(L, getnum, &sl);
772       luaL_loadbuffer(L, s, sl, s);
773     } else if EQ
774       ("loadfile") {
775       luaL_loadfile(L, luaL_checkstring(L, getnum));
776     } else if EQ
777       ("setmetatable") {
778       lua_setmetatable(L, getnum);
779     } else if EQ
780       ("getmetatable") {
781       if (lua_getmetatable(L, getnum) == 0)
782         lua_pushnil(L);
783     } else if EQ
784       ("type") {
785       lua_pushstring(L, lua_typename(L, lua_type(L, getnum)));
786     } else if EQ
787       ("getn") {
788       int i = getnum;
789       lua_pushintegral(L, luaL_getn(L, i));
790     } else if EQ
791       ("setn") {
792       int i = getnum;
793       int n = cast(int, lua_tonumber(L, -1));
794       luaL_setn(L, i, n);
795       lua_pop(L, 1);
796     } else
797       luaL_error(L, "unknown instruction %s", buff);
798   }
799   return 0;
800 }
801
802 /* }====================================================== */
803
804
805 /*
806 ** {======================================================
807 ** tests for yield inside hooks
808 ** =======================================================
809 */
810
811 static void
812 yieldf(lua_State * L, lua_Debug * ar)
813 {
814   lua_yield(L, 0);
815 }
816
817 static int
818 setyhook(lua_State * L)
819 {
820   if (lua_isnoneornil(L, 1))
821     lua_sethook(L, NULL, 0, 0); /* turn off hooks */
822   else {
823     const char *smask = luaL_checkstring(L, 1);
824     int count = luaL_optint(L, 2, 0);
825     int mask = 0;
826     if (strchr(smask, 'l'))
827       mask |= LUA_MASKLINE;
828     if (count > 0)
829       mask |= LUA_MASKCOUNT;
830     lua_sethook(L, yieldf, mask, count);
831   }
832   return 0;
833 }
834
835
836 static int
837 coresume(lua_State * L)
838 {
839   int status;
840   lua_State *co = lua_tothread(L, 1);
841   luaL_argcheck(L, co, 1, "coroutine expected");
842   status = lua_resume(co, 0);
843   if (status != 0) {
844     lua_pushboolean(L, 0);
845     lua_insert(L, -2);
846     return 2;                   /* return false + error message */
847   } else {
848     lua_pushboolean(L, 1);
849     return 1;
850   }
851 }
852
853 /* }====================================================== */
854
855
856
857 static const struct luaL_reg tests_funcs[] = {
858   {"hash", hash_query},
859   {"limits", get_limits},
860   {"listcode", listcode},
861   {"listk", listk},
862   {"listlocals", listlocals},
863   {"loadlib", loadlib},
864   {"stacklevel", stacklevel},
865   {"querystr", string_query},
866   {"querytab", table_query},
867   {"doit", test_do},
868   {"testC", testC},
869   {"ref", tref},
870   {"getref", getref},
871   {"unref", unref},
872   {"d2s", d2s},
873   {"s2d", s2d},
874   {"metatable", metatable},
875   {"upvalue", upvalue},
876   {"newuserdata", newuserdata},
877   {"pushuserdata", pushuserdata},
878   {"udataval", udataval},
879   {"doonnewstack", doonnewstack},
880   {"newstate", newstate},
881   {"closestate", closestate},
882   {"doremote", doremote},
883   {"log2", log2_aux},
884   {"int2fb", int2fb_aux},
885   {"totalmem", mem_query},
886   {"resume", coresume},
887   {"setyhook", setyhook},
888   {NULL, NULL}
889 };
890
891
892 static void
893 fim(void)
894 {
895   if (!islocked)
896     lua_close(lua_state);
897   lua_assert(memdebug_numblocks == 0);
898   lua_assert(memdebug_total == 0);
899 }
900
901
902 static int
903 l_panic(lua_State * L)
904 {
905   UNUSED(L);
906   fprintf(stderr, "unable to recover; exiting\n");
907   return 0;
908 }
909
910
911 int
912 luaB_opentests(lua_State * L)
913 {
914   lua_atpanic(L, l_panic);
915   lua_userstateopen(L);         /* init lock */
916   lua_state = L;                /* keep first state to be opened */
917   luaL_openlib(L, "T", tests_funcs, 0);
918   atexit(fim);
919   return 0;
920 }
921
922
923 #undef main
924 int
925 main(int argc, char *argv[])
926 {
927   char *limit = getenv("MEMLIMIT");
928   if (limit)
929     memdebug_memlimit = strtoul(limit, NULL, 10);
930   l_main(argc, argv);
931   return 0;
932 }
933
934 #endif