00001
00002
00003
00004
00005
00006 #define FORBIDDEN_SYMBOL_EXCEPTION_setjmp
00007 #define FORBIDDEN_SYMBOL_EXCEPTION_longjmp
00008 #define FORBIDDEN_SYMBOL_EXCEPTION_fprintf
00009 #define FORBIDDEN_SYMBOL_EXCEPTION_stderr
00010 #define FORBIDDEN_SYMBOL_EXCEPTION_exit
00011
00012 #ifdef _MSC_VER
00013 #pragma warning(disable:4611)
00014 #endif
00015
00016 #include "engines/grim/lua/ldo.h"
00017 #include "engines/grim/lua/lfunc.h"
00018 #include "engines/grim/lua/lgc.h"
00019 #include "engines/grim/lua/lmem.h"
00020 #include "engines/grim/lua/lobject.h"
00021 #include "engines/grim/lua/lopcodes.h"
00022 #include "engines/grim/lua/lparser.h"
00023 #include "engines/grim/lua/lstate.h"
00024 #include "engines/grim/lua/ltask.h"
00025 #include "engines/grim/lua/ltm.h"
00026 #include "engines/grim/lua/lua.h"
00027 #include "engines/grim/lua/luadebug.h"
00028 #include "engines/grim/lua/lundump.h"
00029 #include "engines/grim/lua/lvm.h"
00030 #include "engines/grim/lua/lzio.h"
00031
00032 #include "common/file.h"
00033 #include "common/textconsole.h"
00034
00035 namespace Grim {
00036
00037 #ifndef STACK_LIMIT
00038 #define STACK_LIMIT 6000
00039 #endif
00040
00041
00042 #define EXTRA_STACK 5
00043
00044
00045
00046
00047
00048 void stderrorim() {
00049 fprintf(stderr, "lua error: %s\n", lua_getstring(lua_getparam(1)));
00050 }
00051
00052 #define STACK_UNIT 256
00053
00054
00055 #define BASIC_CI_SIZE 8
00056
00057 void luaD_init() {
00058 ttype(&errorim) = LUA_T_CPROTO;
00059 fvalue(&errorim) = stderrorim;
00060 }
00061
00062 void luaD_checkstack(int32 n) {
00063 struct Stack *S = &lua_state->stack;
00064 if (S->last-S->top <= n) {
00065 StkId top = S->top-S->stack;
00066 int32 stacksize = (S->last-S->stack) + 1 + STACK_UNIT + n;
00067 S->stack = luaM_reallocvector(S->stack, stacksize, TObject);
00068 S->last = S->stack + (stacksize - 1);
00069 S->top = S->stack + top;
00070 if (stacksize >= STACK_LIMIT) {
00071 if (lua_stackedfunction(100) == LUA_NOOBJECT)
00072 lua_error("Lua2C - C2Lua overflow");
00073 else
00074 lua_error("stack size overflow");
00075 }
00076 }
00077 }
00078
00079
00080
00081
00082 void luaD_adjusttop(StkId newtop) {
00083 int32 diff = newtop-(lua_state->stack.top-lua_state->stack.stack);
00084 if (diff <= 0)
00085 lua_state->stack.top += diff;
00086 else {
00087 luaD_checkstack(diff);
00088 while (diff--)
00089 ttype(lua_state->stack.top++) = LUA_T_NIL;
00090 }
00091 }
00092
00093
00094
00095
00096 void luaD_openstack(int32 nelems) {
00097 luaO_memup(lua_state->stack.top - nelems + 1, lua_state->stack.top - nelems, nelems * sizeof(TObject));
00098 incr_top;
00099 }
00100
00101 void luaD_lineHook(int32 line) {
00102 struct C_Lua_Stack oldCLS = lua_state->Cstack;
00103 StkId old_top = lua_state->Cstack.lua2C = lua_state->Cstack.base = lua_state->stack.top-lua_state->stack.stack;
00104 lua_state->Cstack.num = 0;
00105 (*lua_linehook)(line);
00106 lua_state->stack.top = lua_state->stack.stack + old_top;
00107 lua_state->Cstack = oldCLS;
00108 }
00109
00110 void luaD_callHook(StkId base, TProtoFunc *tf, int32 isreturn) {
00111 struct C_Lua_Stack oldCLS = lua_state->Cstack;
00112 StkId old_top = lua_state->Cstack.lua2C = lua_state->Cstack.base = lua_state->stack.top - lua_state->stack.stack;
00113 lua_state->Cstack.num = 0;
00114 if (isreturn)
00115 (*lua_callhook)(LUA_NOOBJECT, "(return)", 0);
00116 else {
00117 TObject *f = lua_state->stack.stack + base - 1;
00118 if (tf)
00119 (*lua_callhook)(Ref(f), tf->fileName->str, tf->lineDefined);
00120 else
00121 (*lua_callhook)(Ref(f), "(C)", -1);
00122 }
00123 lua_state->stack.top = lua_state->stack.stack + old_top;
00124 lua_state->Cstack = oldCLS;
00125 }
00126
00127
00128
00129
00130
00131
00132 static StkId callC(lua_CFunction f, StkId base) {
00133 struct C_Lua_Stack *CS = &lua_state->Cstack;
00134 struct C_Lua_Stack oldCLS = *CS;
00135 StkId firstResult;
00136 int32 numarg = (lua_state->stack.top - lua_state->stack.stack) - base;
00137 CS->num = numarg;
00138 CS->lua2C = base;
00139 CS->base = base + numarg;
00140 if (lua_callhook) {
00141 TObject *r = lua_state->stack.stack + base - 1;
00142 (*lua_callhook)(Ref(r), "(C)", -1);
00143 }
00144 lua_state->state_counter2++;
00145 (*f)();
00146 lua_state->state_counter2--;
00147
00148
00149 firstResult = CS->base;
00150 *CS = oldCLS;
00151 return firstResult;
00152 }
00153
00154 static StkId callCclosure(struct Closure *cl, lua_CFunction f, StkId base) {
00155 TObject *pbase;
00156 int32 nup = cl->nelems;
00157 luaD_checkstack(nup);
00158 pbase = lua_state->stack.stack + base;
00159
00160 luaO_memup(pbase+nup, pbase, (lua_state->stack.top - pbase) * sizeof(TObject));
00161
00162 memcpy(pbase, cl->consts + 1, nup * sizeof(TObject));
00163 lua_state->stack.top += nup;
00164 return callC(f, base);
00165 }
00166
00167 void luaD_callTM(TObject *f, int32 nParams, int32 nResults) {
00168 luaD_openstack(nParams);
00169 *(lua_state->stack.top - nParams - 1) = *f;
00170 lua_state->state_counter1++;
00171 lua_state->state_counter2++;
00172 luaD_call((lua_state->stack.top - lua_state->stack.stack) - nParams, nResults);
00173 lua_state->state_counter2--;
00174 lua_state->state_counter1--;
00175 }
00176
00177 int32 luaD_call(StkId base, int32 nResults) {
00178 lua_Task *tmpTask = lua_state->task;
00179 if (!lua_state->task || lua_state->state_counter2) {
00180 lua_Task *t = luaM_new(lua_Task);
00181 lua_taskinit(t, lua_state->task, base, nResults);
00182 lua_state->task = t;
00183 } else {
00184 tmpTask = lua_state->some_task;
00185 }
00186
00187 while (1) {
00188 lua_CFunction function = nullptr;
00189 StkId firstResult = 0;
00190 TObject *funcObj = lua_state->stack.stack + base - 1;
00191 if (ttype(funcObj) == LUA_T_CLOSURE) {
00192 Closure *c = clvalue(funcObj);
00193 TObject *proto = &(c->consts[0]);
00194 ttype(funcObj) = LUA_T_CLMARK;
00195 if (ttype(proto) == LUA_T_CPROTO) {
00196 function = fvalue(funcObj);
00197 firstResult = callCclosure(c, fvalue(proto), base);
00198 } else {
00199 lua_taskresume(lua_state->task, c, tfvalue(proto), base);
00200 firstResult = luaV_execute(lua_state->task);
00201 }
00202 } else if (ttype(funcObj) == LUA_T_PMARK) {
00203 if (!lua_state->task->some_flag) {
00204 TObject *im = luaT_getimbyObj(funcObj, IM_FUNCTION);
00205 if (ttype(im) == LUA_T_NIL)
00206 lua_error("call expression not a function");
00207 luaD_callTM(im, (lua_state->stack.top - lua_state->stack.stack) - (base - 1), nResults);
00208 continue;
00209 }
00210 firstResult = luaV_execute(lua_state->task);
00211 } else if (ttype(funcObj) == LUA_T_CMARK) {
00212 if (!lua_state->task->some_flag) {
00213 TObject *im = luaT_getimbyObj(funcObj, IM_FUNCTION);
00214 if (ttype(im) == LUA_T_NIL)
00215 lua_error("call expression not a function");
00216 luaD_callTM(im, (lua_state->stack.top - lua_state->stack.stack) - (base - 1), nResults);
00217 continue;
00218 }
00219 } else if (ttype(funcObj) == LUA_T_CLMARK) {
00220 Closure *c = clvalue(funcObj);
00221 TObject *proto = &(c->consts[0]);
00222 if (!lua_state->task->some_flag) {
00223 TObject *im = luaT_getimbyObj(funcObj, IM_FUNCTION);
00224 if (ttype(im) == LUA_T_NIL)
00225 lua_error("call expression not a function");
00226 luaD_callTM(im, (lua_state->stack.top - lua_state->stack.stack) - (base - 1), nResults);
00227 continue;
00228 }
00229 if (ttype(proto) != LUA_T_CPROTO)
00230 firstResult = luaV_execute(lua_state->task);
00231 } else if (ttype(funcObj) == LUA_T_PROTO) {
00232 ttype(funcObj) = LUA_T_PMARK;
00233 lua_taskresume(lua_state->task, nullptr, tfvalue(funcObj), base);
00234 firstResult = luaV_execute(lua_state->task);
00235 } else if (ttype(funcObj) == LUA_T_CPROTO) {
00236 ttype(funcObj) = LUA_T_CMARK;
00237 function = fvalue(funcObj);
00238 firstResult = callC(fvalue(funcObj), base);
00239 } else {
00240 TObject *im = luaT_getimbyObj(funcObj, IM_FUNCTION);
00241 if (ttype(im) == LUA_T_NIL) {
00242
00243
00244
00245
00246 lua_Task *t = lua_state->task;
00247 lua_state->task = t->next;
00248 lua_state->some_task = tmpTask;
00249 luaM_free(t);
00250
00251 warning("Lua: call expression not a function");
00252 return 1;
00253
00254 }
00255 luaD_callTM(im, (lua_state->stack.top - lua_state->stack.stack) - (base - 1), nResults);
00256 continue;
00257 }
00258
00259 if (firstResult <= 0) {
00260 nResults = lua_state->task->aux;
00261 base = -firstResult;
00262 lua_Task *t = luaM_new(lua_Task);
00263 lua_taskinit(t, lua_state->task, base, nResults);
00264 lua_state->task = t;
00265 } else {
00266 nResults = lua_state->task->some_results;
00267 base = lua_state->task->some_base;
00268 if (nResults != 255)
00269 luaD_adjusttop(firstResult + nResults);
00270 base--;
00271 nResults = lua_state->stack.top - (lua_state->stack.stack + firstResult);
00272 for (int32 i = 0; i < nResults; i++)
00273 *(lua_state->stack.stack + base + i) = *(lua_state->stack.stack + firstResult + i);
00274 lua_state->stack.top -= firstResult - base;
00275
00276 lua_Task *tmp = lua_state->task;
00277 lua_state->task = lua_state->task->next;
00278 luaM_free(tmp);
00279 if (lua_state->task) {
00280 nResults = lua_state->task->some_results;
00281 base = lua_state->task->some_base;
00282 }
00283
00284 if (function == break_here || function == sleep_for) {
00285 if (!lua_state->state_counter1) {
00286 lua_state->some_task = tmpTask;
00287 return 1;
00288 }
00289 }
00290 }
00291
00292 if (lua_state->task == tmpTask)
00293 break;
00294 }
00295
00296 return 0;
00297 }
00298
00299 static void travstack(struct Stack *S, int32 (*fn)(TObject *)) {
00300 StkId i;
00301 for (i = (S->top - 1) - S->stack; i >= 0; i--)
00302 fn(S->stack + i);
00303 }
00304
00305
00306
00307
00308 void luaD_travstack(int32(*fn)(TObject *)) {
00309 LState *t;
00310 for (t = lua_rootState; t != nullptr; t = t->next) {
00311 travstack(&t->stack, fn);
00312 }
00313 }
00314
00315 static void message(const char *s) {
00316 TObject im = errorim;
00317 if (ttype(&im) != LUA_T_NIL) {
00318 lua_pushstring(s);
00319 luaD_callTM(&im, 1, 0);
00320 }
00321 }
00322
00323
00324
00325
00326 void lua_error(const char *s) {
00327 if (s)
00328 message(s);
00329 if (lua_state->errorJmp) {
00330 longjmp(*((jmp_buf *)lua_state->errorJmp), 1);
00331 } else {
00332 fprintf(stderr, "lua: exit(1). Unable to recover\n");
00333 exit(1);
00334 }
00335 }
00336
00337
00338
00339
00340
00341 static void do_callinc(int32 nResults) {
00342 StkId base = lua_state->Cstack.base;
00343 luaD_call(base + 1, nResults);
00344 lua_state->Cstack.lua2C = base;
00345 lua_state->Cstack.num = (lua_state->stack.top - lua_state->stack.stack) - base;
00346 lua_state->Cstack.base = base + lua_state->Cstack.num;
00347 }
00348
00349
00350
00351
00352
00353 int32 luaD_protectedrun(int32 nResults) {
00354 jmp_buf myErrorJmp;
00355 int32 status;
00356 struct C_Lua_Stack oldCLS = lua_state->Cstack;
00357 jmp_buf *oldErr = lua_state->errorJmp;
00358 lua_state->errorJmp = &myErrorJmp;
00359 lua_state->state_counter1++;
00360 lua_Task *tmpTask = lua_state->task;
00361 if (setjmp(myErrorJmp) == 0) {
00362 do_callinc(nResults);
00363 status = 0;
00364 } else {
00365 lua_state->Cstack = oldCLS;
00366 lua_state->stack.top = lua_state->stack.stack + lua_state->Cstack.base;
00367 while (tmpTask != lua_state->task) {
00368 lua_Task *t = lua_state->task;
00369 lua_state->task = lua_state->task->next;
00370 luaM_free(t);
00371 }
00372 status = 1;
00373 }
00374 lua_state->state_counter1--;
00375 lua_state->errorJmp = oldErr;
00376 return status;
00377 }
00378
00379
00380
00381
00382 static int32 protectedparser(ZIO *z, int32 bin) {
00383 int32 status;
00384 TProtoFunc *tf;
00385 jmp_buf myErrorJmp;
00386 jmp_buf *oldErr = lua_state->errorJmp;
00387 lua_state->errorJmp = &myErrorJmp;
00388 if (setjmp(myErrorJmp) == 0) {
00389 tf = bin ? luaU_undump1(z) : luaY_parser(z);
00390 status = 0;
00391 } else {
00392 tf = nullptr;
00393 status = 1;
00394 }
00395 lua_state->errorJmp = oldErr;
00396 if (status)
00397 return 1;
00398 if (tf == nullptr)
00399 return 2;
00400 luaD_adjusttop(lua_state->Cstack.base + 1);
00401 lua_state->stack.stack[lua_state->Cstack.base].ttype = LUA_T_PROTO;
00402 lua_state->stack.stack[lua_state->Cstack.base].value.tf = tf;
00403 luaV_closure(0);
00404 return 0;
00405 }
00406
00407 static int32 do_main(ZIO *z, int32 bin) {
00408 int32 status;
00409 do {
00410 int32 old_blocks = (luaC_checkGC(), nblocks);
00411 status = protectedparser(z, bin);
00412 if (status == 1)
00413 return 1;
00414 else if (status == 2)
00415 return 0;
00416 else {
00417 int32 newelems2 = 2 * (nblocks - old_blocks);
00418 GCthreshold += newelems2;
00419 status = luaD_protectedrun(MULT_RET);
00420 GCthreshold -= newelems2;
00421 }
00422 } while (bin && status == 0);
00423 return status;
00424 }
00425
00426 void luaD_gcIM(TObject *o) {
00427 TObject *im = luaT_getimbyObj(o, IM_GC);
00428 if (ttype(im) != LUA_T_NIL) {
00429 *lua_state->stack.top = *o;
00430 incr_top;
00431 luaD_callTM(im, 1, 0);
00432 }
00433 }
00434
00435 #define SIZE_PREF 20 // size of string prefix to appear in error messages
00436 #define SSIZE_PREF "20"
00437
00438 static void build_name (const char *str, char *name) {
00439 if (str == nullptr || *str == ID_CHUNK)
00440 strcpy(name, "(buffer)");
00441 else {
00442 char *temp;
00443 sprintf(name, "(dostring) >> \"%." SSIZE_PREF "s\"", str);
00444 temp = strchr(name, '\n');
00445 if (temp) {
00446 *temp = '"';
00447 *(temp + 1) = 0;
00448 }
00449 }
00450 }
00451
00452 int32 lua_dostring(const char *str) {
00453 return lua_dobuffer(str, strlen(str), nullptr);
00454 }
00455
00456 int32 lua_dobuffer(const char *buff, int32 size, const char *name) {
00457 char newname[SIZE_PREF + 25];
00458 ZIO z;
00459 int32 status;
00460
00461 if (!name) {
00462 build_name(buff, newname);
00463 name = newname;
00464 }
00465 luaZ_mopen(&z, buff, size, name);
00466 status = do_main(&z, buff[0] == ID_CHUNK);
00467 return status;
00468 }
00469
00470 }