ldo.c 9.7 KB

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