1 /*
2 ** $Id$
3 ** Internal Module for Debugging of the Lua Implementation
4 ** See Copyright Notice in lua.h
5 */
6 
7 
8 #include <ctype.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 
14 #include "lua.h"
15 
16 #include "lapi.h"
17 #include "lauxlib.h"
18 #include "lcode.h"
19 #include "ldebug.h"
20 #include "ldo.h"
21 #include "lfunc.h"
22 #include "lmem.h"
23 #include "lopcodes.h"
24 #include "lstate.h"
25 #include "lstring.h"
26 #include "ltable.h"
27 #include "luadebug.h"
28 #include "lualib.h"
29 
30 
31 void luaB_opentests (lua_State *L);
32 
33 
34 /*
35 ** The whole module only makes sense with LUA_DEBUG on
36 */
37 #ifdef LUA_DEBUG
38 
39 
40 
setnameval(lua_State * L,const char * name,int val)41 static void setnameval (lua_State *L, const char *name, int val) {
42   lua_pushstring(L, name);
43   lua_pushnumber(L, val);
44   lua_settable(L, -3);
45 }
46 
47 
48 /*
49 ** {======================================================
50 ** Disassembler
51 ** =======================================================
52 */
53 
54 
55 static const char *const instrname[NUM_OPCODES] = {
56   "END", "RETURN", "CALL", "TAILCALL", "PUSHNIL", "POP", "PUSHINT",
57   "PUSHSTRING", "PUSHNUM", "PUSHNEGNUM", "PUSHUPVALUE", "GETLOCAL",
58   "GETGLOBAL", "GETTABLE", "GETDOTTED", "GETINDEXED", "PUSHSELF",
59   "CREATETABLE", "SETLOCAL", "SETGLOBAL", "SETTABLE", "SETLIST", "SETMAP",
60   "ADD", "ADDI", "SUB", "MULT", "DIV", "POW", "CONCAT", "MINUS", "NOT",
61   "JMPNE", "JMPEQ", "JMPLT", "JMPLE", "JMPGT", "JMPGE", "JMPT", "JMPF",
62   "JMPONT", "JMPONF", "JMP", "PUSHNILJMP", "FORPREP", "FORLOOP", "LFORPREP",
63   "LFORLOOP", "CLOSURE"
64 };
65 
66 
pushop(lua_State * L,Proto * p,int pc)67 static int pushop (lua_State *L, Proto *p, int pc) {
68   char buff[100];
69   Instruction i = p->code[pc];
70   OpCode o = GET_OPCODE(i);
71   const char *name = instrname[o];
72   sprintf(buff, "%5d - ", luaG_getline(p->lineinfo, pc, 1, NULL));
73   switch ((enum Mode)luaK_opproperties[o].mode) {
74     case iO:
75       sprintf(buff+8, "%-12s", name);
76       break;
77     case iU:
78       sprintf(buff+8, "%-12s%4u", name, GETARG_U(i));
79       break;
80     case iS:
81       sprintf(buff+8, "%-12s%4d", name, GETARG_S(i));
82       break;
83     case iAB:
84       sprintf(buff+8, "%-12s%4d %4d", name, GETARG_A(i), GETARG_B(i));
85       break;
86   }
87   lua_pushstring(L, buff);
88   return (o != OP_END);
89 }
90 
91 
listcode(lua_State * L)92 static int listcode (lua_State *L) {
93   int pc;
94   Proto *p;
95   int res;
96   luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
97                  1, "Lua function expected");
98   p = clvalue(luaA_index(L, 1))->f.l;
99   lua_newtable(L);
100   setnameval(L, "maxstack", p->maxstacksize);
101   setnameval(L, "numparams", p->numparams);
102   pc = 0;
103   do {
104     lua_pushnumber(L, pc+1);
105     res = pushop(L, p, pc++);
106     lua_settable(L, -3);
107   } while (res);
108   return 1;
109 }
110 
111 
liststrings(lua_State * L)112 static int liststrings (lua_State *L) {
113   Proto *p;
114   int i;
115   luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
116                  1, "Lua function expected");
117   p = clvalue(luaA_index(L, 1))->f.l;
118   lua_newtable(L);
119   for (i=0; i<p->nkstr; i++) {
120     lua_pushnumber(L, i+1);
121     lua_pushstring(L, p->kstr[i]->str);
122     lua_settable(L, -3);
123   }
124   return 1;
125 }
126 
127 
listlocals(lua_State * L)128 static int listlocals (lua_State *L) {
129   Proto *p;
130   int pc = luaL_check_int(L, 2) - 1;
131   int i = 0;
132   const char *name;
133   luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
134                  1, "Lua function expected");
135   p = clvalue(luaA_index(L, 1))->f.l;
136   while ((name = luaF_getlocalname(p, ++i, pc)) != NULL)
137     lua_pushstring(L, name);
138   return i-1;
139 }
140 
141 /* }====================================================== */
142 
143 
144 
get_limits(lua_State * L)145 static int get_limits (lua_State *L) {
146   lua_newtable(L);
147   setnameval(L, "BITS_INT", BITS_INT);
148   setnameval(L, "LFPF", LFIELDS_PER_FLUSH);
149   setnameval(L, "MAXARG_A", MAXARG_A);
150   setnameval(L, "MAXARG_B", MAXARG_B);
151   setnameval(L, "MAXARG_S", MAXARG_S);
152   setnameval(L, "MAXARG_U", MAXARG_U);
153   setnameval(L, "MAXLOCALS", MAXLOCALS);
154   setnameval(L, "MAXPARAMS", MAXPARAMS);
155   setnameval(L, "MAXSTACK", MAXSTACK);
156   setnameval(L, "MAXUPVALUES", MAXUPVALUES);
157   setnameval(L, "MAXVARSLH", MAXVARSLH);
158   setnameval(L, "RFPF", RFIELDS_PER_FLUSH);
159   setnameval(L, "SIZE_A", SIZE_A);
160   setnameval(L, "SIZE_B", SIZE_B);
161   setnameval(L, "SIZE_OP", SIZE_OP);
162   setnameval(L, "SIZE_U", SIZE_U);
163   return 1;
164 }
165 
166 
mem_query(lua_State * L)167 static int mem_query (lua_State *L) {
168   if (lua_isnull(L, 1)) {
169     lua_pushnumber(L, memdebug_total);
170     lua_pushnumber(L, memdebug_numblocks);
171     lua_pushnumber(L, memdebug_maxmem);
172     return 3;
173   }
174   else {
175     memdebug_memlimit = luaL_check_int(L, 1);
176     return 0;
177   }
178 }
179 
180 
hash_query(lua_State * L)181 static int hash_query (lua_State *L) {
182   if (lua_isnull(L, 2)) {
183     luaL_arg_check(L, lua_tag(L, 1) == LUA_TSTRING, 1, "string expected");
184     lua_pushnumber(L, tsvalue(luaA_index(L, 1))->u.s.hash);
185   }
186   else {
187     Hash *t;
188     luaL_checktype(L, 2, LUA_TTABLE);
189     t = hvalue(luaA_index(L, 2));
190     lua_pushnumber(L, luaH_mainposition(t, luaA_index(L, 1)) - t->node);
191   }
192   return 1;
193 }
194 
195 
table_query(lua_State * L)196 static int table_query (lua_State *L) {
197   const Hash *t;
198   int i = luaL_opt_int(L, 2, -1);
199   luaL_checktype(L, 1, LUA_TTABLE);
200   t = hvalue(luaA_index(L, 1));
201   if (i == -1) {
202     lua_pushnumber(L, t->size);
203     lua_pushnumber(L, t->firstfree - t->node);
204     return 2;
205   }
206   else if (i < t->size) {
207     luaA_pushobject(L, &t->node[i].key);
208     luaA_pushobject(L, &t->node[i].val);
209     if (t->node[i].next) {
210       lua_pushnumber(L, t->node[i].next - t->node);
211       return 3;
212     }
213     else
214       return 2;
215   }
216   return 0;
217 }
218 
219 
string_query(lua_State * L)220 static int string_query (lua_State *L) {
221   stringtable *tb = (*luaL_check_string(L, 1) == 's') ? &L->strt : &L->udt;
222   int s = luaL_opt_int(L, 2, 0) - 1;
223   if (s==-1) {
224     lua_pushnumber(L ,tb->nuse);
225     lua_pushnumber(L ,tb->size);
226     return 2;
227   }
228   else if (s < tb->size) {
229     TString *ts;
230     int n = 0;
231     for (ts = tb->hash[s]; ts; ts = ts->nexthash) {
232       ttype(L->top) = LUA_TSTRING;
233       tsvalue(L->top) = ts;
234       incr_top;
235       n++;
236     }
237     return n;
238   }
239   return 0;
240 }
241 
242 
tref(lua_State * L)243 static int tref (lua_State *L) {
244   luaL_checkany(L, 1);
245   lua_pushvalue(L, 1);
246   lua_pushnumber(L, lua_ref(L, luaL_opt_int(L, 2, 1)));
247   return 1;
248 }
249 
getref(lua_State * L)250 static int getref (lua_State *L) {
251   if (lua_getref(L, luaL_check_int(L, 1)))
252     return 1;
253   else
254     return 0;
255 }
256 
unref(lua_State * L)257 static int unref (lua_State *L) {
258   lua_unref(L, luaL_check_int(L, 1));
259   return 0;
260 }
261 
newuserdata(lua_State * L)262 static int newuserdata (lua_State *L) {
263   if (lua_isnumber(L, 2))
264     lua_pushusertag(L, (void *)luaL_check_int(L, 1), luaL_check_int(L, 2));
265   else
266     lua_newuserdata(L, luaL_check_int(L, 1));
267   return 1;
268 }
269 
udataval(lua_State * L)270 static int udataval (lua_State *L) {
271   luaL_checktype(L, 1, LUA_TUSERDATA);
272   lua_pushnumber(L, (int)lua_touserdata(L, 1));
273   return 1;
274 }
275 
newstate(lua_State * L)276 static int newstate (lua_State *L) {
277   lua_State *L1 = lua_open(luaL_check_int(L, 1));
278   if (L1)
279     lua_pushuserdata(L, L1);
280   else
281     lua_pushnil(L);
282   return 1;
283 }
284 
loadlib(lua_State * L)285 static int loadlib (lua_State *L) {
286   lua_State *L1 = (lua_State *)lua_touserdata(L, 1);
287   switch (*luaL_check_string(L, 2)) {
288     case 'm': lua_mathlibopen(L1); break;
289     case 's': lua_strlibopen(L1); break;
290     case 'i': lua_iolibopen(L1); break;
291     case 'd': lua_dblibopen(L1); break;
292     case 'b': lua_baselibopen(L1); break;
293     default: luaL_argerror(L, 2, "invalid option");
294   }
295   return 0;
296 }
297 
closestate(lua_State * L)298 static int closestate (lua_State *L) {
299   luaL_checktype(L, 1, LUA_TUSERDATA);
300   lua_close((lua_State *)lua_touserdata(L, 1));
301   return 0;
302 }
303 
doremote(lua_State * L)304 static int doremote (lua_State *L) {
305   lua_State *L1;
306   const char *code = luaL_check_string(L, 2);
307   int status;
308   luaL_checktype(L, 1, LUA_TUSERDATA);
309   L1 = (lua_State *)lua_touserdata(L, 1);
310   status = lua_dostring(L1, code);
311   if (status != 0) {
312     lua_pushnil(L);
313     lua_pushnumber(L, status);
314     return 2;
315   }
316   else {
317     int i = 0;
318     while (!lua_isnull(L1, ++i))
319       lua_pushstring(L, lua_tostring(L1, i));
320     return i-1;
321   }
322 }
323 
settagmethod(lua_State * L)324 static int settagmethod (lua_State *L) {
325   int tag = luaL_check_int(L, 1);
326   const char *event = luaL_check_string(L, 2);
327   luaL_checkany(L, 3);
328   lua_gettagmethod(L, tag, event);
329   lua_pushvalue(L, 3);
330   lua_settagmethod(L, tag, event);
331   return 1;
332 }
333 
pushbool(lua_State * L,int b)334 static int pushbool (lua_State *L, int b) {
335   if (b) lua_pushnumber(L, 1);
336   else lua_pushnil(L);
337   return 1;
338 }
339 
equal(lua_State * L)340 static int equal (lua_State *L) {
341   return pushbool(L, lua_equal(L, 1, 2));
342 }
343 
344 
345 
346 /*
347 ** {======================================================
348 ** function to test the API with C. It interprets a kind of "assembler"
349 ** language with calls to the API, so the test can be driven by Lua code
350 ** =======================================================
351 */
352 
353 static const char *const delimits = " \t\n,;";
354 
skip(const char ** pc)355 static void skip (const char **pc) {
356   while (**pc != '\0' && strchr(delimits, **pc)) (*pc)++;
357 }
358 
getnum(lua_State * L,const char ** pc)359 static int getnum (lua_State *L, const char **pc) {
360   int res = 0;
361   int sig = 1;
362   skip(pc);
363   if (**pc == '.') {
364     res = (int)lua_tonumber(L, -1);
365     lua_pop(L, 1);
366     (*pc)++;
367     return res;
368   }
369   else if (**pc == '-') {
370     sig = -1;
371     (*pc)++;
372   }
373   while (isdigit(**pc)) res = res*10 + (*(*pc)++) - '0';
374   return sig*res;
375 }
376 
getname(char * buff,const char ** pc)377 static const char *getname (char *buff, const char **pc) {
378   int i = 0;
379   skip(pc);
380   while (**pc != '\0' && !strchr(delimits, **pc))
381     buff[i++] = *(*pc)++;
382   buff[i] = '\0';
383   return buff;
384 }
385 
386 
387 #define EQ(s1)	(strcmp(s1, inst) == 0)
388 
389 #define getnum	((getnum)(L, &pc))
390 #define getname	((getname)(buff, &pc))
391 
392 
testC(lua_State * L)393 static int testC (lua_State *L) {
394   char buff[30];
395   const char *pc = luaL_check_string(L, 1);
396   for (;;) {
397     const char *inst = getname;
398     if EQ("") return 0;
399     else if EQ("isnumber") {
400       lua_pushnumber(L, lua_isnumber(L, getnum));
401     }
402     else if EQ("isstring") {
403       lua_pushnumber(L, lua_isstring(L, getnum));
404     }
405     else if EQ("istable") {
406       lua_pushnumber(L, lua_istable(L, getnum));
407     }
408     else if EQ("iscfunction") {
409       lua_pushnumber(L, lua_iscfunction(L, getnum));
410     }
411     else if EQ("isfunction") {
412       lua_pushnumber(L, lua_isfunction(L, getnum));
413     }
414     else if EQ("isuserdata") {
415       lua_pushnumber(L, lua_isuserdata(L, getnum));
416     }
417     else if EQ("isnil") {
418       lua_pushnumber(L, lua_isnil(L, getnum));
419     }
420     else if EQ("isnull") {
421       lua_pushnumber(L, lua_isnull(L, getnum));
422     }
423     else if EQ("tonumber") {
424       lua_pushnumber(L, lua_tonumber(L, getnum));
425     }
426     else if EQ("tostring") {
427       lua_pushstring(L, lua_tostring(L, getnum));
428     }
429     else if EQ("tonumber") {
430       lua_pushnumber(L, lua_tonumber(L, getnum));
431     }
432     else if EQ("strlen") {
433       lua_pushnumber(L, lua_strlen(L, getnum));
434     }
435     else if EQ("tocfunction") {
436       lua_pushcfunction(L, lua_tocfunction(L, getnum));
437     }
438     else if EQ("return") {
439       return getnum;
440     }
441     else if EQ("gettop") {
442       lua_pushnumber(L, lua_gettop(L));
443     }
444     else if EQ("settop") {
445       lua_settop(L, getnum);
446     }
447     else if EQ("pop") {
448       lua_pop(L, getnum);
449     }
450     else if EQ("pushnum") {
451       lua_pushnumber(L, getnum);
452     }
453     else if EQ("pushvalue") {
454       lua_pushvalue(L, getnum);
455     }
456     else if EQ("remove") {
457       lua_remove(L, getnum);
458     }
459     else if EQ("insert") {
460       lua_insert(L, getnum);
461     }
462     else if EQ("gettable") {
463       lua_gettable(L, getnum);
464     }
465     else if EQ("settable") {
466       lua_settable(L, getnum);
467     }
468     else if EQ("next") {
469       lua_next(L, -2);
470     }
471     else if EQ("concat") {
472       lua_concat(L, getnum);
473     }
474     else if EQ("rawcall") {
475       int narg = getnum;
476       int nres = getnum;
477       lua_rawcall(L, narg, nres);
478     }
479     else if EQ("call") {
480       int narg = getnum;
481       int nres = getnum;
482       lua_call(L, narg, nres);
483     }
484     else if EQ("dostring") {
485       lua_dostring(L, luaL_check_string(L, getnum));
486     }
487     else if EQ("settagmethod") {
488       int tag = getnum;
489       const char *event = getname;
490       lua_settagmethod(L, tag, event);
491     }
492     else if EQ("gettagmethod") {
493       int tag = getnum;
494       const char *event = getname;
495       lua_gettagmethod(L, tag, event);
496     }
497     else if EQ("type") {
498       lua_pushstring(L, lua_typename(L, lua_type(L, getnum)));
499     }
500     else luaL_verror(L, "unknown instruction %.30s", buff);
501   }
502   return 0;
503 }
504 
505 /* }====================================================== */
506 
507 
508 
509 static const struct luaL_reg tests_funcs[] = {
510   {"hash", hash_query},
511   {"limits", get_limits},
512   {"listcode", listcode},
513   {"liststrings", liststrings},
514   {"listlocals", listlocals},
515   {"loadlib", loadlib},
516   {"querystr", string_query},
517   {"querytab", table_query},
518   {"testC", testC},
519   {"ref", tref},
520   {"getref", getref},
521   {"unref", unref},
522   {"newuserdata", newuserdata},
523   {"udataval", udataval},
524   {"newstate", newstate},
525   {"closestate", closestate},
526   {"doremote", doremote},
527   {"settagmethod", settagmethod},
528   {"equal", equal},
529   {"totalmem", mem_query}
530 };
531 
532 
luaB_opentests(lua_State * L)533 void luaB_opentests (lua_State *L) {
534   lua_newtable(L);
535   lua_getglobals(L);
536   lua_pushvalue(L, -2);
537   lua_setglobals(L);
538   luaL_openl(L, tests_funcs);  /* open functions inside new table */
539   lua_setglobals(L);  /* restore old table of globals */
540   lua_setglobal(L, "T");  /* set new table as global T */
541 }
542 
543 #endif
544