]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | /* |
11fdf7f2 | 2 | ** $Id: ldebug.c,v 2.120 2016/03/31 19:01:21 roberto Exp $ |
7c673cae FG |
3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | |
5 | */ | |
6 | ||
7 | #define ldebug_c | |
8 | #define LUA_CORE | |
9 | ||
10 | #include "lprefix.h" | |
11 | ||
12 | ||
13 | #include <stdarg.h> | |
14 | #include <stddef.h> | |
15 | #include <string.h> | |
16 | ||
17 | #include "lua.h" | |
18 | ||
19 | #include "lapi.h" | |
20 | #include "lcode.h" | |
21 | #include "ldebug.h" | |
22 | #include "ldo.h" | |
23 | #include "lfunc.h" | |
24 | #include "lobject.h" | |
25 | #include "lopcodes.h" | |
26 | #include "lstate.h" | |
27 | #include "lstring.h" | |
28 | #include "ltable.h" | |
29 | #include "ltm.h" | |
30 | #include "lvm.h" | |
31 | ||
32 | ||
33 | ||
34 | #define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) | |
35 | ||
36 | ||
37 | /* Active Lua function (given call info) */ | |
38 | #define ci_func(ci) (clLvalue((ci)->func)) | |
39 | ||
40 | ||
41 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); | |
42 | ||
43 | ||
44 | static int currentpc (CallInfo *ci) { | |
45 | lua_assert(isLua(ci)); | |
46 | return pcRel(ci->u.l.savedpc, ci_func(ci)->p); | |
47 | } | |
48 | ||
49 | ||
50 | static int currentline (CallInfo *ci) { | |
51 | return getfuncline(ci_func(ci)->p, currentpc(ci)); | |
52 | } | |
53 | ||
54 | ||
55 | /* | |
56 | ** If function yielded, its 'func' can be in the 'extra' field. The | |
57 | ** next function restores 'func' to its correct value for debugging | |
58 | ** purposes. (It exchanges 'func' and 'extra'; so, when called again, | |
59 | ** after debugging, it also "re-restores" ** 'func' to its altered value. | |
60 | */ | |
61 | static void swapextra (lua_State *L) { | |
62 | if (L->status == LUA_YIELD) { | |
63 | CallInfo *ci = L->ci; /* get function that yielded */ | |
64 | StkId temp = ci->func; /* exchange its 'func' and 'extra' values */ | |
65 | ci->func = restorestack(L, ci->extra); | |
66 | ci->extra = savestack(L, temp); | |
67 | } | |
68 | } | |
69 | ||
70 | ||
71 | /* | |
11fdf7f2 TL |
72 | ** This function can be called asynchronously (e.g. during a signal). |
73 | ** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by | |
74 | ** 'resethookcount') are for debug only, and it is no problem if they | |
75 | ** get arbitrary values (causes at most one wrong hook call). 'hookmask' | |
76 | ** is an atomic value. We assume that pointers are atomic too (e.g., gcc | |
77 | ** ensures that for all platforms where it runs). Moreover, 'hook' is | |
78 | ** always checked before being called (see 'luaD_hook'). | |
7c673cae FG |
79 | */ |
80 | LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { | |
81 | if (func == NULL || mask == 0) { /* turn off hooks? */ | |
82 | mask = 0; | |
83 | func = NULL; | |
84 | } | |
85 | if (isLua(L->ci)) | |
86 | L->oldpc = L->ci->u.l.savedpc; | |
87 | L->hook = func; | |
88 | L->basehookcount = count; | |
89 | resethookcount(L); | |
90 | L->hookmask = cast_byte(mask); | |
91 | } | |
92 | ||
93 | ||
94 | LUA_API lua_Hook lua_gethook (lua_State *L) { | |
95 | return L->hook; | |
96 | } | |
97 | ||
98 | ||
99 | LUA_API int lua_gethookmask (lua_State *L) { | |
100 | return L->hookmask; | |
101 | } | |
102 | ||
103 | ||
104 | LUA_API int lua_gethookcount (lua_State *L) { | |
105 | return L->basehookcount; | |
106 | } | |
107 | ||
108 | ||
109 | LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { | |
110 | int status; | |
111 | CallInfo *ci; | |
112 | if (level < 0) return 0; /* invalid (negative) level */ | |
113 | lua_lock(L); | |
114 | for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) | |
115 | level--; | |
116 | if (level == 0 && ci != &L->base_ci) { /* level found? */ | |
117 | status = 1; | |
118 | ar->i_ci = ci; | |
119 | } | |
120 | else status = 0; /* no such level */ | |
121 | lua_unlock(L); | |
122 | return status; | |
123 | } | |
124 | ||
125 | ||
126 | static const char *upvalname (Proto *p, int uv) { | |
127 | TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); | |
128 | if (s == NULL) return "?"; | |
129 | else return getstr(s); | |
130 | } | |
131 | ||
132 | ||
133 | static const char *findvararg (CallInfo *ci, int n, StkId *pos) { | |
134 | int nparams = clLvalue(ci->func)->p->numparams; | |
135 | if (n >= cast_int(ci->u.l.base - ci->func) - nparams) | |
136 | return NULL; /* no such vararg */ | |
137 | else { | |
138 | *pos = ci->func + nparams + n; | |
139 | return "(*vararg)"; /* generic name for any vararg */ | |
140 | } | |
141 | } | |
142 | ||
143 | ||
144 | static const char *findlocal (lua_State *L, CallInfo *ci, int n, | |
145 | StkId *pos) { | |
146 | const char *name = NULL; | |
147 | StkId base; | |
148 | if (isLua(ci)) { | |
149 | if (n < 0) /* access to vararg values? */ | |
150 | return findvararg(ci, -n, pos); | |
151 | else { | |
152 | base = ci->u.l.base; | |
153 | name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); | |
154 | } | |
155 | } | |
156 | else | |
157 | base = ci->func + 1; | |
158 | if (name == NULL) { /* no 'standard' name? */ | |
159 | StkId limit = (ci == L->ci) ? L->top : ci->next->func; | |
160 | if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ | |
161 | name = "(*temporary)"; /* generic name for any valid slot */ | |
162 | else | |
163 | return NULL; /* no name */ | |
164 | } | |
165 | *pos = base + (n - 1); | |
166 | return name; | |
167 | } | |
168 | ||
169 | ||
170 | LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { | |
171 | const char *name; | |
172 | lua_lock(L); | |
173 | swapextra(L); | |
174 | if (ar == NULL) { /* information about non-active function? */ | |
175 | if (!isLfunction(L->top - 1)) /* not a Lua function? */ | |
176 | name = NULL; | |
177 | else /* consider live variables at function start (parameters) */ | |
178 | name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); | |
179 | } | |
180 | else { /* active function; get information through 'ar' */ | |
181 | StkId pos = NULL; /* to avoid warnings */ | |
182 | name = findlocal(L, ar->i_ci, n, &pos); | |
183 | if (name) { | |
184 | setobj2s(L, L->top, pos); | |
185 | api_incr_top(L); | |
186 | } | |
187 | } | |
188 | swapextra(L); | |
189 | lua_unlock(L); | |
190 | return name; | |
191 | } | |
192 | ||
193 | ||
194 | LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { | |
195 | StkId pos = NULL; /* to avoid warnings */ | |
196 | const char *name; | |
197 | lua_lock(L); | |
198 | swapextra(L); | |
199 | name = findlocal(L, ar->i_ci, n, &pos); | |
200 | if (name) { | |
201 | setobjs2s(L, pos, L->top - 1); | |
202 | L->top--; /* pop value */ | |
203 | } | |
204 | swapextra(L); | |
205 | lua_unlock(L); | |
206 | return name; | |
207 | } | |
208 | ||
209 | ||
210 | static void funcinfo (lua_Debug *ar, Closure *cl) { | |
211 | if (noLuaClosure(cl)) { | |
212 | ar->source = "=[C]"; | |
213 | ar->linedefined = -1; | |
214 | ar->lastlinedefined = -1; | |
215 | ar->what = "C"; | |
216 | } | |
217 | else { | |
218 | Proto *p = cl->l.p; | |
219 | ar->source = p->source ? getstr(p->source) : "=?"; | |
220 | ar->linedefined = p->linedefined; | |
221 | ar->lastlinedefined = p->lastlinedefined; | |
222 | ar->what = (ar->linedefined == 0) ? "main" : "Lua"; | |
223 | } | |
224 | luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); | |
225 | } | |
226 | ||
227 | ||
228 | static void collectvalidlines (lua_State *L, Closure *f) { | |
229 | if (noLuaClosure(f)) { | |
230 | setnilvalue(L->top); | |
231 | api_incr_top(L); | |
232 | } | |
233 | else { | |
234 | int i; | |
235 | TValue v; | |
236 | int *lineinfo = f->l.p->lineinfo; | |
237 | Table *t = luaH_new(L); /* new table to store active lines */ | |
238 | sethvalue(L, L->top, t); /* push it on stack */ | |
239 | api_incr_top(L); | |
240 | setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ | |
241 | for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ | |
242 | luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ | |
243 | } | |
244 | } | |
245 | ||
246 | ||
247 | static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | |
248 | Closure *f, CallInfo *ci) { | |
249 | int status = 1; | |
250 | for (; *what; what++) { | |
251 | switch (*what) { | |
252 | case 'S': { | |
253 | funcinfo(ar, f); | |
254 | break; | |
255 | } | |
256 | case 'l': { | |
257 | ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; | |
258 | break; | |
259 | } | |
260 | case 'u': { | |
261 | ar->nups = (f == NULL) ? 0 : f->c.nupvalues; | |
262 | if (noLuaClosure(f)) { | |
263 | ar->isvararg = 1; | |
264 | ar->nparams = 0; | |
265 | } | |
266 | else { | |
267 | ar->isvararg = f->l.p->is_vararg; | |
268 | ar->nparams = f->l.p->numparams; | |
269 | } | |
270 | break; | |
271 | } | |
272 | case 't': { | |
273 | ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; | |
274 | break; | |
275 | } | |
276 | case 'n': { | |
277 | /* calling function is a known Lua function? */ | |
278 | if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) | |
279 | ar->namewhat = getfuncname(L, ci->previous, &ar->name); | |
280 | else | |
281 | ar->namewhat = NULL; | |
282 | if (ar->namewhat == NULL) { | |
283 | ar->namewhat = ""; /* not found */ | |
284 | ar->name = NULL; | |
285 | } | |
286 | break; | |
287 | } | |
288 | case 'L': | |
289 | case 'f': /* handled by lua_getinfo */ | |
290 | break; | |
291 | default: status = 0; /* invalid option */ | |
292 | } | |
293 | } | |
294 | return status; | |
295 | } | |
296 | ||
297 | ||
298 | LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | |
299 | int status; | |
300 | Closure *cl; | |
301 | CallInfo *ci; | |
302 | StkId func; | |
303 | lua_lock(L); | |
304 | swapextra(L); | |
305 | if (*what == '>') { | |
306 | ci = NULL; | |
307 | func = L->top - 1; | |
308 | api_check(L, ttisfunction(func), "function expected"); | |
309 | what++; /* skip the '>' */ | |
310 | L->top--; /* pop function */ | |
311 | } | |
312 | else { | |
313 | ci = ar->i_ci; | |
314 | func = ci->func; | |
315 | lua_assert(ttisfunction(ci->func)); | |
316 | } | |
317 | cl = ttisclosure(func) ? clvalue(func) : NULL; | |
318 | status = auxgetinfo(L, what, ar, cl, ci); | |
319 | if (strchr(what, 'f')) { | |
320 | setobjs2s(L, L->top, func); | |
321 | api_incr_top(L); | |
322 | } | |
323 | swapextra(L); /* correct before option 'L', which can raise a mem. error */ | |
324 | if (strchr(what, 'L')) | |
325 | collectvalidlines(L, cl); | |
326 | lua_unlock(L); | |
327 | return status; | |
328 | } | |
329 | ||
330 | ||
331 | /* | |
332 | ** {====================================================== | |
333 | ** Symbolic Execution | |
334 | ** ======================================================= | |
335 | */ | |
336 | ||
337 | static const char *getobjname (Proto *p, int lastpc, int reg, | |
338 | const char **name); | |
339 | ||
340 | ||
341 | /* | |
342 | ** find a "name" for the RK value 'c' | |
343 | */ | |
344 | static void kname (Proto *p, int pc, int c, const char **name) { | |
345 | if (ISK(c)) { /* is 'c' a constant? */ | |
346 | TValue *kvalue = &p->k[INDEXK(c)]; | |
347 | if (ttisstring(kvalue)) { /* literal constant? */ | |
348 | *name = svalue(kvalue); /* it is its own name */ | |
349 | return; | |
350 | } | |
351 | /* else no reasonable name found */ | |
352 | } | |
353 | else { /* 'c' is a register */ | |
354 | const char *what = getobjname(p, pc, c, name); /* search for 'c' */ | |
355 | if (what && *what == 'c') { /* found a constant name? */ | |
356 | return; /* 'name' already filled */ | |
357 | } | |
358 | /* else no reasonable name found */ | |
359 | } | |
360 | *name = "?"; /* no reasonable name found */ | |
361 | } | |
362 | ||
363 | ||
364 | static int filterpc (int pc, int jmptarget) { | |
365 | if (pc < jmptarget) /* is code conditional (inside a jump)? */ | |
366 | return -1; /* cannot know who sets that register */ | |
367 | else return pc; /* current position sets that register */ | |
368 | } | |
369 | ||
370 | ||
371 | /* | |
372 | ** try to find last instruction before 'lastpc' that modified register 'reg' | |
373 | */ | |
374 | static int findsetreg (Proto *p, int lastpc, int reg) { | |
375 | int pc; | |
376 | int setreg = -1; /* keep last instruction that changed 'reg' */ | |
377 | int jmptarget = 0; /* any code before this address is conditional */ | |
378 | for (pc = 0; pc < lastpc; pc++) { | |
379 | Instruction i = p->code[pc]; | |
380 | OpCode op = GET_OPCODE(i); | |
381 | int a = GETARG_A(i); | |
382 | switch (op) { | |
383 | case OP_LOADNIL: { | |
384 | int b = GETARG_B(i); | |
385 | if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ | |
386 | setreg = filterpc(pc, jmptarget); | |
387 | break; | |
388 | } | |
389 | case OP_TFORCALL: { | |
390 | if (reg >= a + 2) /* affect all regs above its base */ | |
391 | setreg = filterpc(pc, jmptarget); | |
392 | break; | |
393 | } | |
394 | case OP_CALL: | |
395 | case OP_TAILCALL: { | |
396 | if (reg >= a) /* affect all registers above base */ | |
397 | setreg = filterpc(pc, jmptarget); | |
398 | break; | |
399 | } | |
400 | case OP_JMP: { | |
401 | int b = GETARG_sBx(i); | |
402 | int dest = pc + 1 + b; | |
403 | /* jump is forward and do not skip 'lastpc'? */ | |
404 | if (pc < dest && dest <= lastpc) { | |
405 | if (dest > jmptarget) | |
406 | jmptarget = dest; /* update 'jmptarget' */ | |
407 | } | |
408 | break; | |
409 | } | |
410 | default: | |
411 | if (testAMode(op) && reg == a) /* any instruction that set A */ | |
412 | setreg = filterpc(pc, jmptarget); | |
413 | break; | |
414 | } | |
415 | } | |
416 | return setreg; | |
417 | } | |
418 | ||
419 | ||
420 | static const char *getobjname (Proto *p, int lastpc, int reg, | |
421 | const char **name) { | |
422 | int pc; | |
423 | *name = luaF_getlocalname(p, reg + 1, lastpc); | |
424 | if (*name) /* is a local? */ | |
425 | return "local"; | |
426 | /* else try symbolic execution */ | |
427 | pc = findsetreg(p, lastpc, reg); | |
428 | if (pc != -1) { /* could find instruction? */ | |
429 | Instruction i = p->code[pc]; | |
430 | OpCode op = GET_OPCODE(i); | |
431 | switch (op) { | |
432 | case OP_MOVE: { | |
433 | int b = GETARG_B(i); /* move from 'b' to 'a' */ | |
434 | if (b < GETARG_A(i)) | |
435 | return getobjname(p, pc, b, name); /* get name for 'b' */ | |
436 | break; | |
437 | } | |
438 | case OP_GETTABUP: | |
439 | case OP_GETTABLE: { | |
440 | int k = GETARG_C(i); /* key index */ | |
441 | int t = GETARG_B(i); /* table index */ | |
442 | const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ | |
443 | ? luaF_getlocalname(p, t + 1, pc) | |
444 | : upvalname(p, t); | |
445 | kname(p, pc, k, name); | |
446 | return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; | |
447 | } | |
448 | case OP_GETUPVAL: { | |
449 | *name = upvalname(p, GETARG_B(i)); | |
450 | return "upvalue"; | |
451 | } | |
452 | case OP_LOADK: | |
453 | case OP_LOADKX: { | |
454 | int b = (op == OP_LOADK) ? GETARG_Bx(i) | |
455 | : GETARG_Ax(p->code[pc + 1]); | |
456 | if (ttisstring(&p->k[b])) { | |
457 | *name = svalue(&p->k[b]); | |
458 | return "constant"; | |
459 | } | |
460 | break; | |
461 | } | |
462 | case OP_SELF: { | |
463 | int k = GETARG_C(i); /* key index */ | |
464 | kname(p, pc, k, name); | |
465 | return "method"; | |
466 | } | |
467 | default: break; /* go through to return NULL */ | |
468 | } | |
469 | } | |
470 | return NULL; /* could not find reasonable name */ | |
471 | } | |
472 | ||
473 | ||
474 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { | |
475 | TMS tm = (TMS)0; /* to avoid warnings */ | |
476 | Proto *p = ci_func(ci)->p; /* calling function */ | |
477 | int pc = currentpc(ci); /* calling instruction index */ | |
478 | Instruction i = p->code[pc]; /* calling instruction */ | |
479 | if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ | |
480 | *name = "?"; | |
481 | return "hook"; | |
482 | } | |
483 | switch (GET_OPCODE(i)) { | |
484 | case OP_CALL: | |
485 | case OP_TAILCALL: /* get function name */ | |
486 | return getobjname(p, pc, GETARG_A(i), name); | |
487 | case OP_TFORCALL: { /* for iterator */ | |
488 | *name = "for iterator"; | |
489 | return "for iterator"; | |
490 | } | |
491 | /* all other instructions can call only through metamethods */ | |
492 | case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: | |
493 | tm = TM_INDEX; | |
494 | break; | |
495 | case OP_SETTABUP: case OP_SETTABLE: | |
496 | tm = TM_NEWINDEX; | |
497 | break; | |
498 | case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD: | |
499 | case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND: | |
500 | case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: { | |
501 | int offset = cast_int(GET_OPCODE(i)) - cast_int(OP_ADD); /* ORDER OP */ | |
502 | tm = cast(TMS, offset + cast_int(TM_ADD)); /* ORDER TM */ | |
503 | break; | |
504 | } | |
505 | case OP_UNM: tm = TM_UNM; break; | |
506 | case OP_BNOT: tm = TM_BNOT; break; | |
507 | case OP_LEN: tm = TM_LEN; break; | |
508 | case OP_CONCAT: tm = TM_CONCAT; break; | |
509 | case OP_EQ: tm = TM_EQ; break; | |
510 | case OP_LT: tm = TM_LT; break; | |
511 | case OP_LE: tm = TM_LE; break; | |
512 | default: lua_assert(0); /* other instructions cannot call a function */ | |
513 | } | |
514 | *name = getstr(G(L)->tmname[tm]); | |
515 | return "metamethod"; | |
516 | } | |
517 | ||
518 | /* }====================================================== */ | |
519 | ||
520 | ||
521 | ||
522 | /* | |
523 | ** The subtraction of two potentially unrelated pointers is | |
524 | ** not ISO C, but it should not crash a program; the subsequent | |
525 | ** checks are ISO C and ensure a correct result. | |
526 | */ | |
527 | static int isinstack (CallInfo *ci, const TValue *o) { | |
528 | ptrdiff_t i = o - ci->u.l.base; | |
529 | return (0 <= i && i < (ci->top - ci->u.l.base) && ci->u.l.base + i == o); | |
530 | } | |
531 | ||
532 | ||
533 | /* | |
534 | ** Checks whether value 'o' came from an upvalue. (That can only happen | |
535 | ** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on | |
536 | ** upvalues.) | |
537 | */ | |
538 | static const char *getupvalname (CallInfo *ci, const TValue *o, | |
539 | const char **name) { | |
540 | LClosure *c = ci_func(ci); | |
541 | int i; | |
542 | for (i = 0; i < c->nupvalues; i++) { | |
543 | if (c->upvals[i]->v == o) { | |
544 | *name = upvalname(c->p, i); | |
545 | return "upvalue"; | |
546 | } | |
547 | } | |
548 | return NULL; | |
549 | } | |
550 | ||
551 | ||
552 | static const char *varinfo (lua_State *L, const TValue *o) { | |
553 | const char *name = NULL; /* to avoid warnings */ | |
554 | CallInfo *ci = L->ci; | |
555 | const char *kind = NULL; | |
556 | if (isLua(ci)) { | |
557 | kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ | |
558 | if (!kind && isinstack(ci, o)) /* no? try a register */ | |
559 | kind = getobjname(ci_func(ci)->p, currentpc(ci), | |
560 | cast_int(o - ci->u.l.base), &name); | |
561 | } | |
562 | return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : ""; | |
563 | } | |
564 | ||
565 | ||
566 | l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { | |
11fdf7f2 | 567 | const char *t = luaT_objtypename(L, o); |
7c673cae FG |
568 | luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o)); |
569 | } | |
570 | ||
571 | ||
572 | l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) { | |
573 | if (ttisstring(p1) || cvt2str(p1)) p1 = p2; | |
574 | luaG_typeerror(L, p1, "concatenate"); | |
575 | } | |
576 | ||
577 | ||
578 | l_noret luaG_opinterror (lua_State *L, const TValue *p1, | |
579 | const TValue *p2, const char *msg) { | |
580 | lua_Number temp; | |
581 | if (!tonumber(p1, &temp)) /* first operand is wrong? */ | |
582 | p2 = p1; /* now second is wrong */ | |
583 | luaG_typeerror(L, p2, msg); | |
584 | } | |
585 | ||
586 | ||
587 | /* | |
588 | ** Error when both values are convertible to numbers, but not to integers | |
589 | */ | |
590 | l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { | |
591 | lua_Integer temp; | |
592 | if (!tointeger(p1, &temp)) | |
593 | p2 = p1; | |
594 | luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); | |
595 | } | |
596 | ||
597 | ||
598 | l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { | |
11fdf7f2 TL |
599 | const char *t1 = luaT_objtypename(L, p1); |
600 | const char *t2 = luaT_objtypename(L, p2); | |
601 | if (strcmp(t1, t2) == 0) | |
7c673cae FG |
602 | luaG_runerror(L, "attempt to compare two %s values", t1); |
603 | else | |
604 | luaG_runerror(L, "attempt to compare %s with %s", t1, t2); | |
605 | } | |
606 | ||
607 | ||
608 | /* add src:line information to 'msg' */ | |
609 | const char *luaG_addinfo (lua_State *L, const char *msg, TString *src, | |
610 | int line) { | |
611 | char buff[LUA_IDSIZE]; | |
612 | if (src) | |
613 | luaO_chunkid(buff, getstr(src), LUA_IDSIZE); | |
614 | else { /* no source available; use "?" instead */ | |
615 | buff[0] = '?'; buff[1] = '\0'; | |
616 | } | |
617 | return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); | |
618 | } | |
619 | ||
620 | ||
621 | l_noret luaG_errormsg (lua_State *L) { | |
622 | if (L->errfunc != 0) { /* is there an error handling function? */ | |
623 | StkId errfunc = restorestack(L, L->errfunc); | |
624 | setobjs2s(L, L->top, L->top - 1); /* move argument */ | |
625 | setobjs2s(L, L->top - 1, errfunc); /* push function */ | |
626 | L->top++; /* assume EXTRA_STACK */ | |
11fdf7f2 | 627 | luaD_callnoyield(L, L->top - 2, 1); /* call it */ |
7c673cae FG |
628 | } |
629 | luaD_throw(L, LUA_ERRRUN); | |
630 | } | |
631 | ||
632 | ||
633 | l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { | |
634 | CallInfo *ci = L->ci; | |
635 | const char *msg; | |
636 | va_list argp; | |
637 | va_start(argp, fmt); | |
638 | msg = luaO_pushvfstring(L, fmt, argp); /* format message */ | |
639 | va_end(argp); | |
640 | if (isLua(ci)) /* if Lua function, add source:line information */ | |
641 | luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci)); | |
642 | luaG_errormsg(L); | |
643 | } | |
644 | ||
645 | ||
646 | void luaG_traceexec (lua_State *L) { | |
647 | CallInfo *ci = L->ci; | |
648 | lu_byte mask = L->hookmask; | |
11fdf7f2 | 649 | int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); |
7c673cae FG |
650 | if (counthook) |
651 | resethookcount(L); /* reset count */ | |
11fdf7f2 TL |
652 | else if (!(mask & LUA_MASKLINE)) |
653 | return; /* no line hook and count != 0; nothing to be done */ | |
7c673cae FG |
654 | if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ |
655 | ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ | |
656 | return; /* do not call hook again (VM yielded, so it did not move) */ | |
657 | } | |
658 | if (counthook) | |
659 | luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ | |
660 | if (mask & LUA_MASKLINE) { | |
661 | Proto *p = ci_func(ci)->p; | |
662 | int npc = pcRel(ci->u.l.savedpc, p); | |
663 | int newline = getfuncline(p, npc); | |
664 | if (npc == 0 || /* call linehook when enter a new function, */ | |
665 | ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ | |
666 | newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ | |
667 | luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ | |
668 | } | |
669 | L->oldpc = ci->u.l.savedpc; | |
670 | if (L->status == LUA_YIELD) { /* did hook yield? */ | |
671 | if (counthook) | |
672 | L->hookcount = 1; /* undo decrement to zero */ | |
673 | ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ | |
674 | ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ | |
675 | ci->func = L->top - 1; /* protect stack below results */ | |
676 | luaD_throw(L, LUA_YIELD); | |
677 | } | |
678 | } | |
679 |