diff options
-rw-r--r-- | opcode.c | 176 |
1 files changed, 101 insertions, 75 deletions
@@ -3,7 +3,7 @@ | |||
3 | ** TecCGraf - PUC-Rio | 3 | ** TecCGraf - PUC-Rio |
4 | */ | 4 | */ |
5 | 5 | ||
6 | char *rcs_opcode="$Id: opcode.c,v 3.38 1995/05/16 17:23:58 roberto Exp $"; | 6 | char *rcs_opcode="$Id: opcode.c,v 3.40 1995/10/04 14:20:26 roberto Exp roberto $"; |
7 | 7 | ||
8 | #include <setjmp.h> | 8 | #include <setjmp.h> |
9 | #include <stdlib.h> | 9 | #include <stdlib.h> |
@@ -54,7 +54,7 @@ static jmp_buf *errorJmp = NULL; /* current error recover point */ | |||
54 | 54 | ||
55 | 55 | ||
56 | static StkId lua_execute (Byte *pc, StkId base); | 56 | static StkId lua_execute (Byte *pc, StkId base); |
57 | static void do_call (Object *func, StkId base, int nResults, StkId whereRes); | 57 | static void do_call (StkId base, int nResults); |
58 | 58 | ||
59 | 59 | ||
60 | 60 | ||
@@ -64,32 +64,6 @@ Object *luaI_Address (lua_Object o) | |||
64 | } | 64 | } |
65 | 65 | ||
66 | 66 | ||
67 | /* | ||
68 | ** Error messages | ||
69 | */ | ||
70 | |||
71 | |||
72 | static void lua_message (char *s) | ||
73 | { | ||
74 | luaI_reportbug(s, 1); | ||
75 | do_call(&luaI_fallBacks[FB_ERROR].function, (top-stack)-1, 0, (top-stack)-1); | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | ** Reports an error, and jumps up to the available recover label | ||
80 | */ | ||
81 | void lua_error (char *s) | ||
82 | { | ||
83 | if (s) lua_message(s); | ||
84 | if (errorJmp) | ||
85 | longjmp(*errorJmp, 1); | ||
86 | else | ||
87 | { | ||
88 | fprintf (stderr, "lua: exit(1). Unable to recover\n"); | ||
89 | exit(1); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | 67 | ||
94 | /* | 68 | /* |
95 | ** Init stack | 69 | ** Init stack |
@@ -211,6 +185,17 @@ static void adjustC (int nParams) | |||
211 | adjust_top(CBase+nParams); | 185 | adjust_top(CBase+nParams); |
212 | } | 186 | } |
213 | 187 | ||
188 | /* | ||
189 | ** Open a hole below "nelems" from the top. | ||
190 | */ | ||
191 | static void open_stack (int nelems) | ||
192 | { | ||
193 | int i; | ||
194 | for (i=0; i<nelems; i++) | ||
195 | *(top-i) = *(top-i-1); | ||
196 | incr_top; | ||
197 | } | ||
198 | |||
214 | 199 | ||
215 | /* | 200 | /* |
216 | ** Call a C function. CBase will point to the top of the stack, | 201 | ** Call a C function. CBase will point to the top of the stack, |
@@ -233,49 +218,58 @@ static StkId callC (lua_CFunction func, StkId base) | |||
233 | } | 218 | } |
234 | 219 | ||
235 | /* | 220 | /* |
221 | ** Call the specified fallback, putting it on the stack below its arguments | ||
222 | */ | ||
223 | static void callFB (int fb) | ||
224 | { | ||
225 | int nParams = luaI_fallBacks[fb].nParams; | ||
226 | open_stack(nParams); | ||
227 | *(top-nParams-1) = luaI_fallBacks[fb].function; | ||
228 | do_call((top-stack)-nParams, luaI_fallBacks[fb].nResults); | ||
229 | } | ||
230 | |||
231 | /* | ||
236 | ** Call the fallback for invalid functions (see do_call) | 232 | ** Call the fallback for invalid functions (see do_call) |
237 | */ | 233 | */ |
238 | static void call_funcFB (Object *func, StkId base, int nResults, StkId whereRes) | 234 | static void call_funcFB (StkId base, int nResults) |
239 | { | 235 | { |
240 | StkId i; | 236 | open_stack((top-stack)-(base-1)); |
241 | /* open space for first parameter (func) */ | 237 | stack[base-1] = luaI_fallBacks[FB_FUNCTION].function; |
242 | for (i=top-stack; i>base; i--) | 238 | do_call(base, nResults); |
243 | stack[i] = stack[i-1]; | ||
244 | incr_top; | ||
245 | stack[base] = *func; | ||
246 | do_call(&luaI_fallBacks[FB_FUNCTION].function, base, nResults, whereRes); | ||
247 | } | 239 | } |
248 | 240 | ||
249 | 241 | ||
250 | /* | 242 | /* |
251 | ** Call a function (C or Lua). The parameters must be on the stack, | 243 | ** Call a function (C or Lua). The parameters must be on the stack, |
252 | ** between [stack+base,top). When returns, the results are on the stack, | 244 | ** between [stack+base,top). The function to be called is at stack+base-1. |
253 | ** between [stack+whereRes,top). The number of results is nResults, unless | 245 | ** When returns, the results are on the stack, between [stack+base-1,top). |
254 | ** nResults=MULT_RET. | 246 | ** The number of results is nResults, unless nResults=MULT_RET. |
255 | */ | 247 | */ |
256 | static void do_call (Object *func, StkId base, int nResults, StkId whereRes) | 248 | static void do_call (StkId base, int nResults) |
257 | { | 249 | { |
258 | StkId firstResult; | 250 | StkId firstResult; |
251 | Object *func = stack+base-1; | ||
259 | if (tag(func) == LUA_T_CFUNCTION) | 252 | if (tag(func) == LUA_T_CFUNCTION) |
260 | firstResult = callC(fvalue(func), base); | 253 | firstResult = callC(fvalue(func), base); |
261 | else if (tag(func) == LUA_T_FUNCTION) | 254 | else if (tag(func) == LUA_T_FUNCTION) |
262 | firstResult = lua_execute(func->value.tf->code, base); | 255 | firstResult = lua_execute(func->value.tf->code, base); |
263 | else | 256 | else |
264 | { /* func is not a function */ | 257 | { /* func is not a function */ |
265 | call_funcFB(func, base, nResults, whereRes); | 258 | call_funcFB(base, nResults); |
266 | return; | 259 | return; |
267 | } | 260 | } |
268 | /* adjust the number of results */ | 261 | /* adjust the number of results */ |
269 | if (nResults != MULT_RET && top - (stack+firstResult) != nResults) | 262 | if (nResults != MULT_RET && top - (stack+firstResult) != nResults) |
270 | adjust_top(firstResult+nResults); | 263 | adjust_top(firstResult+nResults); |
271 | /* move results to the given position */ | 264 | /* move results to base-1 (to erase parameters and function) */ |
272 | if (firstResult != whereRes) | 265 | base--; |
266 | if (firstResult != base) | ||
273 | { | 267 | { |
274 | int i; | 268 | int i; |
275 | nResults = top - (stack+firstResult); /* actual number of results */ | 269 | nResults = top - (stack+firstResult); /* actual number of results */ |
276 | for (i=0; i<nResults; i++) | 270 | for (i=0; i<nResults; i++) |
277 | *(stack+whereRes+i) = *(stack+firstResult+i); | 271 | *(stack+base+i) = *(stack+firstResult+i); |
278 | top -= firstResult-whereRes; | 272 | top -= firstResult-base; |
279 | } | 273 | } |
280 | } | 274 | } |
281 | 275 | ||
@@ -287,12 +281,12 @@ static void do_call (Object *func, StkId base, int nResults, StkId whereRes) | |||
287 | static void pushsubscript (void) | 281 | static void pushsubscript (void) |
288 | { | 282 | { |
289 | if (tag(top-2) != LUA_T_ARRAY) | 283 | if (tag(top-2) != LUA_T_ARRAY) |
290 | do_call(&luaI_fallBacks[FB_GETTABLE].function, (top-stack)-2, 1, (top-stack)-2); | 284 | callFB(FB_GETTABLE); |
291 | else | 285 | else |
292 | { | 286 | { |
293 | Object *h = lua_hashget(avalue(top-2), top-1); | 287 | Object *h = lua_hashget(avalue(top-2), top-1); |
294 | if (h == NULL || tag(h) == LUA_T_NIL) | 288 | if (h == NULL || tag(h) == LUA_T_NIL) |
295 | do_call(&luaI_fallBacks[FB_INDEX].function, (top-stack)-2, 1, (top-stack)-2); | 289 | callFB(FB_INDEX); |
296 | else | 290 | else |
297 | { | 291 | { |
298 | --top; | 292 | --top; |
@@ -308,7 +302,7 @@ static void pushsubscript (void) | |||
308 | static void storesubscript (void) | 302 | static void storesubscript (void) |
309 | { | 303 | { |
310 | if (tag(top-3) != LUA_T_ARRAY) | 304 | if (tag(top-3) != LUA_T_ARRAY) |
311 | do_call(&luaI_fallBacks[FB_SETTABLE].function, (top-stack)-3, 0, (top-stack)-3); | 305 | callFB(FB_SETTABLE); |
312 | else | 306 | else |
313 | { | 307 | { |
314 | Object *h = lua_hashdefine (avalue(top-3), top-2); | 308 | Object *h = lua_hashdefine (avalue(top-3), top-2); |
@@ -330,10 +324,36 @@ void lua_travstack (void (*fn)(Object *)) | |||
330 | 324 | ||
331 | 325 | ||
332 | /* | 326 | /* |
333 | ** Execute a protected call. If function is null compiles the pre-set input. | 327 | ** Error messages |
334 | ** Leave nResults on the stack. | 328 | */ |
329 | |||
330 | static void lua_message (char *s) | ||
331 | { | ||
332 | luaI_reportbug(s, 1); | ||
333 | callFB(FB_ERROR); | ||
334 | } | ||
335 | |||
336 | /* | ||
337 | ** Reports an error, and jumps up to the available recover label | ||
338 | */ | ||
339 | void lua_error (char *s) | ||
340 | { | ||
341 | if (s) lua_message(s); | ||
342 | if (errorJmp) | ||
343 | longjmp(*errorJmp, 1); | ||
344 | else | ||
345 | { | ||
346 | fprintf (stderr, "lua: exit(1). Unable to recover\n"); | ||
347 | exit(1); | ||
348 | } | ||
349 | } | ||
350 | |||
351 | |||
352 | /* | ||
353 | ** Execute a protected call. Assumes that function is at CBase and | ||
354 | ** parameters are on top of it. Leave nResults on the stack. | ||
335 | */ | 355 | */ |
336 | static int do_protectedrun (Object *function, int nResults) | 356 | static int do_protectedrun (int nResults) |
337 | { | 357 | { |
338 | jmp_buf myErrorJmp; | 358 | jmp_buf myErrorJmp; |
339 | int status; | 359 | int status; |
@@ -342,13 +362,13 @@ static int do_protectedrun (Object *function, int nResults) | |||
342 | errorJmp = &myErrorJmp; | 362 | errorJmp = &myErrorJmp; |
343 | if (setjmp(myErrorJmp) == 0) | 363 | if (setjmp(myErrorJmp) == 0) |
344 | { | 364 | { |
345 | do_call(function, CBase, nResults, CBase); | 365 | do_call(CBase+1, nResults); |
346 | CnResults = (top-stack) - CBase; /* number of results */ | 366 | CnResults = (top-stack) - CBase; /* number of results */ |
347 | CBase += CnResults; /* incorporate results on the stack */ | 367 | CBase += CnResults; /* incorporate results on the stack */ |
348 | status = 0; | 368 | status = 0; |
349 | } | 369 | } |
350 | else | 370 | else |
351 | { | 371 | { /* an error occurred: restore CBase and top */ |
352 | CBase = oldCBase; | 372 | CBase = oldCBase; |
353 | top = stack+CBase; | 373 | top = stack+CBase; |
354 | status = 1; | 374 | status = 1; |
@@ -362,27 +382,26 @@ static int do_protectedmain (void) | |||
362 | { | 382 | { |
363 | TFunc tf; | 383 | TFunc tf; |
364 | int status; | 384 | int status; |
365 | StkId oldCBase = CBase; | ||
366 | jmp_buf myErrorJmp; | 385 | jmp_buf myErrorJmp; |
367 | jmp_buf *oldErr = errorJmp; | 386 | jmp_buf *oldErr = errorJmp; |
368 | errorJmp = &myErrorJmp; | 387 | errorJmp = &myErrorJmp; |
388 | adjustC(1); /* one slot for the pseudo-function */ | ||
389 | stack[CBase].tag = LUA_T_FUNCTION; | ||
390 | stack[CBase].value.tf = &tf; | ||
369 | tf.code = NULL; | 391 | tf.code = NULL; |
370 | if (setjmp(myErrorJmp) == 0) | 392 | if (setjmp(myErrorJmp) == 0) |
371 | { | 393 | { |
372 | Object f; | ||
373 | f.tag = LUA_T_FUNCTION; | ||
374 | f.value.tf = &tf; | ||
375 | lua_parse(&tf); | 394 | lua_parse(&tf); |
376 | do_call(&f, CBase, 0, CBase); | 395 | status = do_protectedrun(0); |
377 | status = 0; | ||
378 | } | 396 | } |
379 | else | 397 | else |
398 | { | ||
380 | status = 1; | 399 | status = 1; |
400 | adjustC(0); /* erase extra slot */ | ||
401 | } | ||
402 | errorJmp = oldErr; | ||
381 | if (tf.code) | 403 | if (tf.code) |
382 | luaI_free(tf.code); | 404 | luaI_free(tf.code); |
383 | errorJmp = oldErr; | ||
384 | CBase = oldCBase; | ||
385 | top = stack+CBase; | ||
386 | return status; | 405 | return status; |
387 | } | 406 | } |
388 | 407 | ||
@@ -395,14 +414,20 @@ int lua_callfunction (lua_Object function) | |||
395 | if (function == LUA_NOOBJECT) | 414 | if (function == LUA_NOOBJECT) |
396 | return 1; | 415 | return 1; |
397 | else | 416 | else |
398 | return do_protectedrun (Address(function), MULT_RET); | 417 | { |
418 | open_stack((top-stack)-CBase); | ||
419 | stack[CBase] = *Address(function); | ||
420 | return do_protectedrun (MULT_RET); | ||
421 | } | ||
399 | } | 422 | } |
400 | 423 | ||
401 | 424 | ||
402 | int lua_call (char *funcname) | 425 | int lua_call (char *funcname) |
403 | { | 426 | { |
404 | Word n = luaI_findsymbolbyname(funcname); | 427 | Word n = luaI_findsymbolbyname(funcname); |
405 | return do_protectedrun(&s_object(n), MULT_RET); | 428 | open_stack((top-stack)-CBase); |
429 | stack[CBase] = s_object(n); | ||
430 | return do_protectedrun(MULT_RET); | ||
406 | } | 431 | } |
407 | 432 | ||
408 | 433 | ||
@@ -448,11 +473,12 @@ int lua_dostring (char *string) | |||
448 | */ | 473 | */ |
449 | lua_Object lua_setfallback (char *name, lua_CFunction fallback) | 474 | lua_Object lua_setfallback (char *name, lua_CFunction fallback) |
450 | { | 475 | { |
451 | static Object func = {LUA_T_CFUNCTION, {luaI_setfallback}}; | 476 | adjustC(1); /* one slot for the pseudo-function */ |
452 | adjustC(0); | 477 | stack[CBase].tag = LUA_T_CFUNCTION; |
478 | stack[CBase].value.f = luaI_setfallback; | ||
453 | lua_pushstring(name); | 479 | lua_pushstring(name); |
454 | lua_pushcfunction(fallback); | 480 | lua_pushcfunction(fallback); |
455 | do_protectedrun(&func, 1); | 481 | do_protectedrun(1); |
456 | return (Ref(top-1)); | 482 | return (Ref(top-1)); |
457 | } | 483 | } |
458 | 484 | ||
@@ -597,8 +623,9 @@ int lua_lock (void) | |||
597 | } | 623 | } |
598 | 624 | ||
599 | 625 | ||
626 | |||
600 | /* | 627 | /* |
601 | ** Get a global object. Return the object handle or NULL on error. | 628 | ** Get a global object. |
602 | */ | 629 | */ |
603 | lua_Object lua_getglobal (char *name) | 630 | lua_Object lua_getglobal (char *name) |
604 | { | 631 | { |
@@ -708,14 +735,14 @@ void luaI_gcFB (Object *o) | |||
708 | { | 735 | { |
709 | *top = *o; | 736 | *top = *o; |
710 | incr_top; | 737 | incr_top; |
711 | do_call(&luaI_fallBacks[FB_GC].function, (top-stack)-1, 0, (top-stack)-1); | 738 | callFB(FB_GC); |
712 | } | 739 | } |
713 | 740 | ||
714 | 741 | ||
715 | static void call_arith (char *op) | 742 | static void call_arith (char *op) |
716 | { | 743 | { |
717 | lua_pushstring(op); | 744 | lua_pushstring(op); |
718 | do_call(&luaI_fallBacks[FB_ARITH].function, (top-stack)-3, 1, (top-stack)-3); | 745 | callFB(FB_ARITH); |
719 | } | 746 | } |
720 | 747 | ||
721 | static void comparison (lua_Type tag_less, lua_Type tag_equal, | 748 | static void comparison (lua_Type tag_less, lua_Type tag_equal, |
@@ -729,7 +756,7 @@ static void comparison (lua_Type tag_less, lua_Type tag_equal, | |||
729 | else if (tostring(l) || tostring(r)) | 756 | else if (tostring(l) || tostring(r)) |
730 | { | 757 | { |
731 | lua_pushstring(op); | 758 | lua_pushstring(op); |
732 | do_call(&luaI_fallBacks[FB_ORDER].function, (top-stack)-3, 1, (top-stack)-3); | 759 | callFB(FB_ORDER); |
733 | return; | 760 | return; |
734 | } | 761 | } |
735 | else | 762 | else |
@@ -867,7 +894,7 @@ static StkId lua_execute (Byte *pc, StkId base) | |||
867 | *(top) = *(top-2-n); | 894 | *(top) = *(top-2-n); |
868 | *(top-1) = *(top-3-n); | 895 | *(top-1) = *(top-3-n); |
869 | top += 2; | 896 | top += 2; |
870 | do_call(&luaI_fallBacks[FB_SETTABLE].function, (top-stack)-3, 0, (top-stack)-3); | 897 | callFB(FB_SETTABLE); |
871 | } | 898 | } |
872 | else | 899 | else |
873 | { | 900 | { |
@@ -1021,7 +1048,7 @@ static StkId lua_execute (Byte *pc, StkId base) | |||
1021 | Object *l = top-2; | 1048 | Object *l = top-2; |
1022 | Object *r = top-1; | 1049 | Object *r = top-1; |
1023 | if (tostring(r) || tostring(l)) | 1050 | if (tostring(r) || tostring(l)) |
1024 | do_call(&luaI_fallBacks[FB_CONCAT].function, (top-stack)-2, 1, (top-stack)-2); | 1051 | callFB(FB_CONCAT); |
1025 | else | 1052 | else |
1026 | { | 1053 | { |
1027 | tsvalue(l) = lua_createstring (lua_strconc(svalue(l),svalue(r))); | 1054 | tsvalue(l) = lua_createstring (lua_strconc(svalue(l),svalue(r))); |
@@ -1102,9 +1129,8 @@ static StkId lua_execute (Byte *pc, StkId base) | |||
1102 | { | 1129 | { |
1103 | int nParams = *(pc++); | 1130 | int nParams = *(pc++); |
1104 | int nResults = *(pc++); | 1131 | int nResults = *(pc++); |
1105 | Object *func = top-1-nParams; /* function is below parameters */ | ||
1106 | StkId newBase = (top-stack)-nParams; | 1132 | StkId newBase = (top-stack)-nParams; |
1107 | do_call(func, newBase, nResults, newBase-1); | 1133 | do_call(newBase, nResults); |
1108 | } | 1134 | } |
1109 | break; | 1135 | break; |
1110 | 1136 | ||