ldo.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /*
  2. ** $Id: ldo.c,v 1.1 1997/09/16 19:25:59 roberto Exp roberto $
  3. ** Stack and Call structure of Lua
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <setjmp.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include "lbuiltin.h"
  10. #include "ldo.h"
  11. #include "lgc.h"
  12. #include "lmem.h"
  13. #include "lobject.h"
  14. #include "lparser.h"
  15. #include "ltm.h"
  16. #include "lua.h"
  17. #include "luadebug.h"
  18. #include "lundump.h"
  19. #include "lvm.h"
  20. #include "lzio.h"
  21. #ifndef STACK_LIMIT
  22. #define STACK_LIMIT 6000
  23. #endif
  24. static TObject initial_stack;
  25. struct Stack luaD_stack = {&initial_stack+1, &initial_stack, &initial_stack};
  26. struct C_Lua_Stack luaD_Cstack = {0, 0, 0};
  27. static jmp_buf *errorJmp = NULL; /* current error recover point */
  28. #define STACK_EXTRA 32
  29. static void initstack (int n)
  30. {
  31. int maxstack = STACK_EXTRA+n;
  32. luaD_stack.stack = luaM_newvector(maxstack, TObject);
  33. luaD_stack.last = luaD_stack.stack+(maxstack-1);
  34. luaD_stack.top = luaD_stack.stack;
  35. *(luaD_stack.top++) = initial_stack;
  36. luaB_predefine();
  37. }
  38. void luaD_checkstack (int n)
  39. {
  40. if (luaD_stack.stack == &initial_stack)
  41. initstack(n);
  42. else if (luaD_stack.last-luaD_stack.top <= n) {
  43. static int limit = STACK_LIMIT;
  44. StkId top = luaD_stack.top-luaD_stack.stack;
  45. int stacksize = (luaD_stack.last-luaD_stack.stack)+1+STACK_EXTRA+n;
  46. luaD_stack.stack = luaM_reallocvector(luaD_stack.stack, stacksize,TObject);
  47. luaD_stack.last = luaD_stack.stack+(stacksize-1);
  48. luaD_stack.top = luaD_stack.stack + top;
  49. if (stacksize >= limit) {
  50. limit = stacksize+STACK_EXTRA; /* extra space to run error handler */
  51. if (lua_stackedfunction(100) == LUA_NOOBJECT) {
  52. /* less than 100 functions on the stack: cannot be recursive loop */
  53. lua_error("Lua2C - C2Lua overflow");
  54. }
  55. else
  56. lua_error(stackEM);
  57. }
  58. }
  59. }
  60. /*
  61. ** Adjust stack. Set top to the given value, pushing NILs if needed.
  62. */
  63. void luaD_adjusttop (StkId newtop)
  64. {
  65. int diff = newtop-(luaD_stack.top-luaD_stack.stack);
  66. if (diff <= 0)
  67. luaD_stack.top += diff;
  68. else {
  69. luaD_checkstack(diff);
  70. while (diff--)
  71. ttype(luaD_stack.top++) = LUA_T_NIL;
  72. }
  73. }
  74. /*
  75. ** Open a hole below "nelems" from the luaD_stack.top.
  76. */
  77. void luaD_openstack (int nelems)
  78. {
  79. int i;
  80. for (i=0; i<nelems; i++)
  81. *(luaD_stack.top-i) = *(luaD_stack.top-i-1);
  82. incr_top;
  83. }
  84. void luaD_lineHook (int line)
  85. {
  86. struct C_Lua_Stack oldCLS = luaD_Cstack;
  87. StkId old_top = luaD_Cstack.lua2C = luaD_Cstack.base = luaD_stack.top-luaD_stack.stack;
  88. luaD_Cstack.num = 0;
  89. (*lua_linehook)(line);
  90. luaD_stack.top = luaD_stack.stack+old_top;
  91. luaD_Cstack = oldCLS;
  92. }
  93. void luaD_callHook (StkId base, lua_Type type, int isreturn)
  94. {
  95. struct C_Lua_Stack oldCLS = luaD_Cstack;
  96. StkId old_top = luaD_Cstack.lua2C = luaD_Cstack.base = luaD_stack.top-luaD_stack.stack;
  97. luaD_Cstack.num = 0;
  98. if (isreturn)
  99. (*lua_callhook)(LUA_NOOBJECT, "(return)", 0);
  100. else {
  101. TObject *f = luaD_stack.stack+base-1;
  102. if (type == LUA_T_MARK)
  103. (*lua_callhook)(Ref(f), f->value.tf->fileName->str,
  104. f->value.tf->lineDefined);
  105. else
  106. (*lua_callhook)(Ref(f), "(C)", -1);
  107. }
  108. luaD_stack.top = luaD_stack.stack+old_top;
  109. luaD_Cstack = oldCLS;
  110. }
  111. /*
  112. ** Call a C function. luaD_Cstack.base will point to the luaD_stack.top of the luaD_stack.stack,
  113. ** and luaD_Cstack.num is the number of parameters. Returns an index
  114. ** to the first result from C.
  115. */
  116. static StkId callC (lua_CFunction func, StkId base)
  117. {
  118. struct C_Lua_Stack oldCLS = luaD_Cstack;
  119. StkId firstResult;
  120. luaD_Cstack.num = (luaD_stack.top-luaD_stack.stack) - base;
  121. /* incorporate parameters on the luaD_stack.stack */
  122. luaD_Cstack.lua2C = base;
  123. luaD_Cstack.base = base+luaD_Cstack.num; /* == luaD_stack.top-luaD_stack.stack */
  124. if (lua_callhook)
  125. luaD_callHook(base, LUA_T_CMARK, 0);
  126. (*func)();
  127. if (lua_callhook) /* func may have changed lua_callhook */
  128. luaD_callHook(base, LUA_T_CMARK, 1);
  129. firstResult = luaD_Cstack.base;
  130. luaD_Cstack = oldCLS;
  131. return firstResult;
  132. }
  133. void luaD_callTM (TObject *f, int nParams, int nResults)
  134. {
  135. luaD_openstack(nParams);
  136. *(luaD_stack.top-nParams-1) = *f;
  137. luaD_call((luaD_stack.top-luaD_stack.stack)-nParams, nResults);
  138. }
  139. /*
  140. ** Call a function (C or Lua). The parameters must be on the luaD_stack.stack,
  141. ** between [luaD_stack.stack+base,luaD_stack.top). The function to be called is at luaD_stack.stack+base-1.
  142. ** When returns, the results are on the luaD_stack.stack, between [luaD_stack.stack+base-1,luaD_stack.top).
  143. ** The number of results is nResults, unless nResults=MULT_RET.
  144. */
  145. void luaD_call (StkId base, int nResults)
  146. {
  147. StkId firstResult;
  148. TObject *func = luaD_stack.stack+base-1;
  149. int i;
  150. if (ttype(func) == LUA_T_CFUNCTION) {
  151. ttype(func) = LUA_T_CMARK;
  152. firstResult = callC(fvalue(func), base);
  153. }
  154. else if (ttype(func) == LUA_T_FUNCTION) {
  155. ttype(func) = LUA_T_MARK;
  156. firstResult = luaV_execute(func->value.cl, base);
  157. }
  158. else { /* func is not a function */
  159. /* Check the tag method for invalid functions */
  160. TObject *im = luaT_getimbyObj(func, IM_FUNCTION);
  161. if (ttype(im) == LUA_T_NIL)
  162. lua_error("call expression not a function");
  163. luaD_callTM(im, (luaD_stack.top-luaD_stack.stack)-(base-1), nResults);
  164. return;
  165. }
  166. /* adjust the number of results */
  167. if (nResults != MULT_RET)
  168. luaD_adjusttop(firstResult+nResults);
  169. /* move results to base-1 (to erase parameters and function) */
  170. base--;
  171. nResults = luaD_stack.top - (luaD_stack.stack+firstResult); /* actual number of results */
  172. for (i=0; i<nResults; i++)
  173. *(luaD_stack.stack+base+i) = *(luaD_stack.stack+firstResult+i);
  174. luaD_stack.top -= firstResult-base;
  175. }
  176. /*
  177. ** Traverse all objects on luaD_stack.stack
  178. */
  179. void luaD_travstack (int (*fn)(TObject *))
  180. {
  181. StkId i;
  182. for (i = (luaD_stack.top-1)-luaD_stack.stack; i>=0; i--)
  183. fn (luaD_stack.stack+i);
  184. }
  185. /*
  186. ** Error messages
  187. */
  188. static void auxerrorim (char *form)
  189. {
  190. lua_Object s = lua_getparam(1);
  191. if (lua_isstring(s))
  192. fprintf(stderr, form, lua_getstring(s));
  193. }
  194. static void emergencyerrorf (void)
  195. {
  196. auxerrorim("THERE WAS AN ERROR INSIDE AN ERROR METHOD:\n%s\n");
  197. }
  198. static void stderrorim (void)
  199. {
  200. auxerrorim("lua: %s\n");
  201. }
  202. TObject luaD_errorim = {LUA_T_CFUNCTION, {stderrorim}};
  203. static void message (char *s)
  204. {
  205. TObject im = luaD_errorim;
  206. if (ttype(&im) != LUA_T_NIL) {
  207. luaD_errorim.ttype = LUA_T_CFUNCTION;
  208. luaD_errorim.value.f = emergencyerrorf;
  209. lua_pushstring(s);
  210. luaD_callTM(&im, 1, 0);
  211. luaD_errorim = im;
  212. }
  213. }
  214. /*
  215. ** Reports an error, and jumps up to the available recover label
  216. */
  217. void lua_error (char *s)
  218. {
  219. if (s) message(s);
  220. if (errorJmp)
  221. longjmp(*errorJmp, 1);
  222. else {
  223. fprintf (stderr, "lua: exit(1). Unable to recover\n");
  224. exit(1);
  225. }
  226. }
  227. /*
  228. ** Call the function at luaD_Cstack.base, and incorporate results on
  229. ** the Lua2C structure.
  230. */
  231. static void do_callinc (int nResults)
  232. {
  233. StkId base = luaD_Cstack.base;
  234. luaD_call(base+1, nResults);
  235. luaD_Cstack.lua2C = base; /* position of the luaM_new results */
  236. luaD_Cstack.num = (luaD_stack.top-luaD_stack.stack) - base; /* number of results */
  237. luaD_Cstack.base = base + luaD_Cstack.num; /* incorporate results on luaD_stack.stack */
  238. }
  239. /*
  240. ** Execute a protected call. Assumes that function is at luaD_Cstack.base and
  241. ** parameters are on luaD_stack.top of it. Leave nResults on the luaD_stack.stack.
  242. */
  243. int luaD_protectedrun (int nResults)
  244. {
  245. jmp_buf myErrorJmp;
  246. int status;
  247. struct C_Lua_Stack oldCLS = luaD_Cstack;
  248. jmp_buf *oldErr = errorJmp;
  249. errorJmp = &myErrorJmp;
  250. if (setjmp(myErrorJmp) == 0) {
  251. do_callinc(nResults);
  252. status = 0;
  253. }
  254. else { /* an error occurred: restore luaD_Cstack and luaD_stack.top */
  255. luaD_Cstack = oldCLS;
  256. luaD_stack.top = luaD_stack.stack+luaD_Cstack.base;
  257. status = 1;
  258. }
  259. errorJmp = oldErr;
  260. return status;
  261. }
  262. /*
  263. ** returns 0 = chunk loaded; 1 = error; 2 = no more chunks to load
  264. */
  265. static int protectedparser (ZIO *z, char *chunkname, int bin)
  266. {
  267. int status;
  268. TProtoFunc *tf;
  269. jmp_buf myErrorJmp;
  270. jmp_buf *oldErr = errorJmp;
  271. errorJmp = &myErrorJmp;
  272. if (setjmp(myErrorJmp) == 0) {
  273. tf = bin ? luaU_undump1(z, chunkname) : luaY_parser(z, chunkname);
  274. status = 0;
  275. }
  276. else {
  277. tf = NULL;
  278. status = 1;
  279. }
  280. errorJmp = oldErr;
  281. if (status) return 1; /* error code */
  282. if (tf == NULL) return 2; /* 'natural' end */
  283. luaD_adjusttop(luaD_Cstack.base+1); /* one slot for the pseudo-function */
  284. luaD_stack.stack[luaD_Cstack.base].ttype = LUA_T_PROTO;
  285. luaD_stack.stack[luaD_Cstack.base].value.tf = tf;
  286. luaV_closure();
  287. return 0;
  288. }
  289. static int do_main (ZIO *z, char *chunkname, int bin)
  290. {
  291. int status;
  292. do {
  293. long old_entities = (luaC_checkGC(), luaO_nentities);
  294. status = protectedparser(z, chunkname, bin);
  295. if (status == 1) return 1; /* error */
  296. else if (status == 2) return 0; /* 'natural' end */
  297. else {
  298. long newelems2 = 2*(luaO_nentities-old_entities);
  299. luaC_threshold += newelems2;
  300. status = luaD_protectedrun(MULT_RET);
  301. luaC_threshold -= newelems2;
  302. }
  303. } while (bin && status == 0);
  304. return status;
  305. }
  306. void luaD_gcIM (TObject *o)
  307. {
  308. TObject *im = luaT_getimbyObj(o, IM_GC);
  309. if (ttype(im) != LUA_T_NIL) {
  310. *luaD_stack.top = *o;
  311. incr_top;
  312. luaD_callTM(im, 1, 0);
  313. }
  314. }
  315. int lua_dofile (char *filename)
  316. {
  317. ZIO z;
  318. int status;
  319. int c;
  320. int bin;
  321. FILE *f = (filename == NULL) ? stdin : fopen(filename, "r");
  322. if (f == NULL)
  323. return 2;
  324. if (filename == NULL)
  325. filename = "(stdin)";
  326. c = fgetc(f);
  327. ungetc(c, f);
  328. bin = (c == ID_CHUNK);
  329. if (bin)
  330. f = freopen(filename, "rb", f); /* set binary mode */
  331. luaZ_Fopen(&z, f);
  332. status = do_main(&z, filename, bin);
  333. if (f != stdin)
  334. fclose(f);
  335. return status;
  336. }
  337. #define SIZE_PREF 20 /* size of string prefix to appear in error messages */
  338. int lua_dostring (char *str)
  339. {
  340. int status;
  341. char buff[SIZE_PREF+25];
  342. char *temp;
  343. ZIO z;
  344. if (str == NULL) return 1;
  345. sprintf(buff, "(dostring) >> %.20s", str);
  346. temp = strchr(buff, '\n');
  347. if (temp) *temp = 0; /* end string after first line */
  348. luaZ_sopen(&z, str);
  349. status = do_main(&z, buff, 0);
  350. return status;
  351. }