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