/* ** Call a function (C or Lua). The parameters must be on the stack, ** between [stack+base,top). The function to be called is at stack+base-1. ** When returns, the results are on the stack, between [stack+base-1,top). ** The number of results is nResults, unless nResults=MULT_RET. */ static void do_call (StkId base, int nResults) { StkId firstResult; TObject *func = stack+base-1; int i; if (ttype(func) == LUA_T_CFUNCTION) { ttype(func) = LUA_T_CMARK; firstResult = callC(fvalue(func), base); } else if (ttype(func) == LUA_T_FUNCTION) { ttype(func) = LUA_T_MARK; firstResult = lua_execute(func->value.tf->code, base); } else { /* func is not a function */ /* Check the tag method for invalid functions */ TObject *im = luaI_getimbyObj(func, IM_FUNCTION); if (ttype(im) == LUA_T_NIL) lua_error("call expression not a function"); open_stack((top-stack)-(base-1)); stack[base-1] = *im; do_call(base, nResults); return; } /* adjust the number of results */ if (nResults != MULT_RET) adjust_top(firstResult+nResults); /* move results to base-1 (to erase parameters and function) */ base--; nResults = top - (stack+firstResult); /* actual number of results */ for (i=0; i<nResults; i++) *(stack+base+i) = *(stack+firstResult+i); top -= firstResult-base; }
/* ** Call a function (C or Lua). The parameters must be on the stack, ** between [stack+base,top). The function to be called is at stack+base-1. ** When returns, the results are on the stack, between [stack+base-1,top). ** The number of results is nResults, unless nResults=MULT_RET. */ static void do_call (StkId base, int nResults) { StkId firstResult; Object *func = stack+base-1; int i; if (tag(func) == LUA_T_CFUNCTION) { tag(func) = LUA_T_CMARK; firstResult = callC(fvalue(func), base); } else if (tag(func) == LUA_T_FUNCTION) { tag(func) = LUA_T_MARK; firstResult = lua_execute(func->value.tf->code, base); } else { /* func is not a function */ /* Call the fallback for invalid functions */ open_stack((top-stack)-(base-1)); stack[base-1] = luaI_fallBacks[FB_FUNCTION].function; do_call(base, nResults); return; } /* adjust the number of results */ if (nResults != MULT_RET && top - (stack+firstResult) != nResults) adjust_top(firstResult+nResults); /* move results to base-1 (to erase parameters and function) */ base--; nResults = top - (stack+firstResult); /* actual number of results */ for (i=0; i<nResults; i++) *(stack+base+i) = *(stack+firstResult+i); top -= firstResult-base; }
static StkId callCclosure (struct Closure *cl, lua_CFunction f, StkId base) { TObject *pbase; int nup = cl->nelems; /* number of upvalues */ luaD_checkstack(nup); pbase = L->stack.stack+base; /* care: previous call may change this */ /* open space for upvalues as extra arguments */ luaO_memup(pbase+nup, pbase, (L->stack.top-pbase)*sizeof(TObject)); /* copy upvalues into stack */ memcpy(pbase, cl->consts+1, nup*sizeof(TObject)); L->stack.top += nup; return callC(f, base); }
/* ** Call a function (C or Lua). The parameters must be on the stack, ** between [top-nArgs,top). The function to be called is right below the ** arguments. ** When returns, the results are on the stack, between [top-nArgs-1,top). ** The number of results is nResults, unless nResults=MULT_RET. */ void luaD_calln (int nArgs, int nResults) { struct Stack *S = &L->stack; /* to optimize */ StkId base = (S->top-S->stack)-nArgs; TObject *func = S->stack+base-1; StkId firstResult; int i; switch (ttype(func)) { case LUA_T_CPROTO: ttype(func) = LUA_T_CMARK; firstResult = callC(fvalue(func), base); break; case LUA_T_PROTO: ttype(func) = LUA_T_PMARK; firstResult = luaV_execute(NULL, tfvalue(func), base); break; case LUA_T_CLOSURE: { Closure *c = clvalue(func); TObject *proto = &(c->consts[0]); ttype(func) = LUA_T_CLMARK; firstResult = (ttype(proto) == LUA_T_CPROTO) ? callCclosure(c, fvalue(proto), base) : luaV_execute(c, tfvalue(proto), base); break; } default: { /* func is not a function */ /* Check the tag method for invalid functions */ TObject *im = luaT_getimbyObj(func, IM_FUNCTION); if (ttype(im) == LUA_T_NIL) lua_error("call expression not a function"); luaD_callTM(im, (S->top-S->stack)-(base-1), nResults); return; } } /* adjust the number of results */ if (nResults == MULT_RET) nResults = (S->top-S->stack)-firstResult; else luaD_adjusttop(firstResult+nResults); /* move results to base-1 (to erase parameters and function) */ base--; for (i=0; i<nResults; i++) *(S->stack+base+i) = *(S->stack+firstResult+i); S->top -= firstResult-base; }
int32 luaD_call(StkId base, int32 nResults) { lua_Task *tmpTask = lua_state->task; if (!lua_state->task || lua_state->state_counter2) { lua_Task *t = luaM_new(lua_Task); lua_taskinit(t, lua_state->task, base, nResults); lua_state->task = t; } else { tmpTask = lua_state->some_task; } while (1) { lua_CFunction function = NULL; StkId firstResult = 0; TObject *funcObj = lua_state->stack.stack + base - 1; if (ttype(funcObj) == LUA_T_CLOSURE) { Closure *c = clvalue(funcObj); TObject *proto = &(c->consts[0]); ttype(funcObj) = LUA_T_CLMARK; if (ttype(proto) == LUA_T_CPROTO) { function = fvalue(funcObj); firstResult = callCclosure(c, fvalue(proto), base); } else { lua_taskresume(lua_state->task, c, tfvalue(proto), base); firstResult = luaV_execute(lua_state->task); } } else if (ttype(funcObj) == LUA_T_PMARK) { if (!lua_state->task->some_flag) { TObject *im = luaT_getimbyObj(funcObj, IM_FUNCTION); if (ttype(im) == LUA_T_NIL) lua_error("call expression not a function"); luaD_callTM(im, (lua_state->stack.top - lua_state->stack.stack) - (base - 1), nResults); continue; } firstResult = luaV_execute(lua_state->task); } else if (ttype(funcObj) == LUA_T_CMARK) { if (!lua_state->task->some_flag) { TObject *im = luaT_getimbyObj(funcObj, IM_FUNCTION); if (ttype(im) == LUA_T_NIL) lua_error("call expression not a function"); luaD_callTM(im, (lua_state->stack.top - lua_state->stack.stack) - (base - 1), nResults); continue; } } else if (ttype(funcObj) == LUA_T_CLMARK) { Closure *c = clvalue(funcObj); TObject *proto = &(c->consts[0]); if (!lua_state->task->some_flag) { TObject *im = luaT_getimbyObj(funcObj, IM_FUNCTION); if (ttype(im) == LUA_T_NIL) lua_error("call expression not a function"); luaD_callTM(im, (lua_state->stack.top - lua_state->stack.stack) - (base - 1), nResults); continue; } if (ttype(proto) != LUA_T_CPROTO) firstResult = luaV_execute(lua_state->task); } else if (ttype(funcObj) == LUA_T_PROTO) { ttype(funcObj) = LUA_T_PMARK; lua_taskresume(lua_state->task, NULL, tfvalue(funcObj), base); firstResult = luaV_execute(lua_state->task); } else if (ttype(funcObj) == LUA_T_CPROTO) { ttype(funcObj) = LUA_T_CMARK; function = fvalue(funcObj); firstResult = callC(fvalue(funcObj), base); } else { TObject *im = luaT_getimbyObj(funcObj, IM_FUNCTION); if (ttype(im) == LUA_T_NIL) { // NOTE: Originally this throwed the lua_error. Anyway it is commented here because // when in year 4 bi.exit() calls bi.book.act:free(). But bi.book.act is nil, // hence it enters this branch and the error blocks the game. // Now we try instead to survive and go on with the function. lua_Task *t = lua_state->task; lua_state->task = t->next; lua_state->some_task = tmpTask; luaM_free(t); warning("Lua: call expression not a function"); return 1; // lua_error("call expression not a function"); } luaD_callTM(im, (lua_state->stack.top - lua_state->stack.stack) - (base - 1), nResults); continue; } if (firstResult <= 0) { nResults = lua_state->task->aux; base = -firstResult; lua_Task *t = luaM_new(lua_Task); lua_taskinit(t, lua_state->task, base, nResults); lua_state->task = t; } else { nResults = lua_state->task->some_results; base = lua_state->task->some_base; if (nResults != 255) luaD_adjusttop(firstResult + nResults); base--; nResults = lua_state->stack.top - (lua_state->stack.stack + firstResult); for (int32 i = 0; i < nResults; i++) *(lua_state->stack.stack + base + i) = *(lua_state->stack.stack + firstResult + i); lua_state->stack.top -= firstResult - base; lua_Task *tmp = lua_state->task; lua_state->task = lua_state->task->next; luaM_free(tmp); if (lua_state->task) { nResults = lua_state->task->some_results; base = lua_state->task->some_base; } if (function == break_here) { if (!lua_state->state_counter1) { lua_state->some_task = tmpTask; return 1; } } } if (lua_state->task == tmpTask) break; } return 0; }