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