diff options
Diffstat (limited to 'opcode.c')
| -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 | ||
