diff options
author | Richard Quirk <richard.quirk@gmail.com> | 2014-03-19 19:31:31 +0100 |
---|---|---|
committer | Marcin Bukat <marcin.bukat@gmail.com> | 2014-04-02 20:31:54 +0200 |
commit | 36378988ad4059982742f05f5eb50580b456840a (patch) | |
tree | ee70be810d894566c5e351f21a1ebb79be742a85 /apps/plugins/lua/ldo.c | |
parent | 020f16a1c7d5bc9a302671cef03f56ac735e20c5 (diff) | |
download | rockbox-36378988ad4059982742f05f5eb50580b456840a.tar.gz rockbox-36378988ad4059982742f05f5eb50580b456840a.zip |
Update lua plugin to 5.2.3
Prior to this patch the Lua plugin used version 5.1.4. This change
reduces the number of modifications in the Lua source using some new
defines and because the upstream source is now more flexible.
Unless otherwise stated, l*.[ch] files are taken unmodified from the
upstream lua-5.2.3.
fscanf.c:
file descriptors in rockbox are just ints, they are hidden behind a
void* now so liolib requires less modifications. fscanf is updated to
use void* too.
getc.c: this is a new file required for getc implementation in lauxlib.c
lauxlib.c: LoadF replaced FILE* with int, the rockbox file
descriptor int are cast to FILE* (actually void* due to typedef).
getc uses the PREFIX version. stdin is not used, as per 5.1.4.
lbaselib.c: now uses strspn in the number parsing. print uses DEBUGF now
rather than being commented out.
lbitlib.c: use the built-in version from 5.2.3 rather than Reuben
Thomas's external library. Backwards compatible and adds some new bit
operations.
ldo.c: the LUAI_THROW/TRY defines are now in the core lua code, so have
been removed from rockconf.h
liolib.c: here the implementation has changed to use the LStream from
the original source, and cast the FILE* pointers to int. This has
reduced the number of modifications from the upstream version.
llex.c: the only change from upstream is to remove the locale include.
lmathlib.c: updated from the 5.2.3 version and re-applied the changes
that were made vs 5.1.4 for random numbers and to remove unsupported
float functions.
loadlib.c: upstream version, with the 5.1.4 changes for missing
functions.
lobject.c: upstream version, with ctype.h added and sprintf changed to
snprintf.
loslib.c: upstream version with locale.h removed and 5.1.4 changes for
unsupportable functions.
lstrlib.c: sprintf changed to snprintf.
ltable.c: upstream with the hashnum function from 5.1.4 to avoid frexp
in luai_hashnum.
luaconf.h: updated to 5.2.3 version, restored relevant parts from the
original 5.1.4 configuration. The COMPAT defines that are no longer
available are not included.
lundump.c: VERSION macro conflicts with the core Rockbox equivalent.
rocklib.c: luaL_reg is no longer available, replaced by luaL_Reg
equivalent. Moved checkboolean/optboolean functions to this file and out
of core lua files. luaL_getn is no longer available, replaced by
luaL_rawlen. luaL_register is deprecated, use the newlib/setfuncs
replacements. rli_init has to be called before setting up the newlib to
avoid overwriting the rb table.
rocklib_aux.pl: use rli_checkboolean from rocklib.c.
rocklua.c: new default bits library used, update the library loading
code with idiomatic 5.2 code.
strcspn.c: no longer needed, but strspn.c is required for strspn in
lbaselib.c
Change-Id: I0c7945c755f79083afe98ec117e1e8cf13de2651
Reviewed-on: http://gerrit.rockbox.org/774
Tested: Richard Quirk <richard.quirk@gmail.com>
Reviewed-by: Marcin Bukat <marcin.bukat@gmail.com>
Diffstat (limited to 'apps/plugins/lua/ldo.c')
-rw-r--r-- | apps/plugins/lua/ldo.c | 671 |
1 files changed, 417 insertions, 254 deletions
diff --git a/apps/plugins/lua/ldo.c b/apps/plugins/lua/ldo.c index f303c744c7..e9dd5fa951 100644 --- a/apps/plugins/lua/ldo.c +++ b/apps/plugins/lua/ldo.c | |||
@@ -1,11 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ | 2 | ** $Id: ldo.c,v 2.108.1.3 2013/11/08 18:22:50 roberto Exp $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
6 | 6 | ||
7 | 7 | ||
8 | /* #include <setjmp.h> */ | 8 | #include <setjmp.h> |
9 | #include <stdlib.h> | 9 | #include <stdlib.h> |
10 | #include <string.h> | 10 | #include <string.h> |
11 | 11 | ||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include "lua.h" | 15 | #include "lua.h" |
16 | 16 | ||
17 | #include "lapi.h" | ||
17 | #include "ldebug.h" | 18 | #include "ldebug.h" |
18 | #include "ldo.h" | 19 | #include "ldo.h" |
19 | #include "lfunc.h" | 20 | #include "lfunc.h" |
@@ -39,6 +40,38 @@ | |||
39 | ** ======================================================= | 40 | ** ======================================================= |
40 | */ | 41 | */ |
41 | 42 | ||
43 | /* | ||
44 | ** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By | ||
45 | ** default, Lua handles errors with exceptions when compiling as | ||
46 | ** C++ code, with _longjmp/_setjmp when asked to use them, and with | ||
47 | ** longjmp/setjmp otherwise. | ||
48 | */ | ||
49 | #if !defined(LUAI_THROW) | ||
50 | |||
51 | #if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) | ||
52 | /* C++ exceptions */ | ||
53 | #define LUAI_THROW(L,c) throw(c) | ||
54 | #define LUAI_TRY(L,c,a) \ | ||
55 | try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } | ||
56 | #define luai_jmpbuf int /* dummy variable */ | ||
57 | |||
58 | #elif defined(LUA_USE_ULONGJMP) | ||
59 | /* in Unix, try _longjmp/_setjmp (more efficient) */ | ||
60 | #define LUAI_THROW(L,c) _longjmp((c)->b, 1) | ||
61 | #define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } | ||
62 | #define luai_jmpbuf jmp_buf | ||
63 | |||
64 | #else | ||
65 | /* default handling with long jumps */ | ||
66 | #define LUAI_THROW(L,c) longjmp((c)->b, 1) | ||
67 | #define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } | ||
68 | #define luai_jmpbuf jmp_buf | ||
69 | |||
70 | #endif | ||
71 | |||
72 | #endif | ||
73 | |||
74 | |||
42 | 75 | ||
43 | /* chain list of long jump buffers */ | 76 | /* chain list of long jump buffers */ |
44 | struct lua_longjmp { | 77 | struct lua_longjmp { |
@@ -48,18 +81,17 @@ struct lua_longjmp { | |||
48 | }; | 81 | }; |
49 | 82 | ||
50 | 83 | ||
51 | void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { | 84 | static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { |
52 | switch (errcode) { | 85 | switch (errcode) { |
53 | case LUA_ERRMEM: { | 86 | case LUA_ERRMEM: { /* memory error? */ |
54 | setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); | 87 | setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ |
55 | break; | 88 | break; |
56 | } | 89 | } |
57 | case LUA_ERRERR: { | 90 | case LUA_ERRERR: { |
58 | setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); | 91 | setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); |
59 | break; | 92 | break; |
60 | } | 93 | } |
61 | case LUA_ERRSYNTAX: | 94 | default: { |
62 | case LUA_ERRRUN: { | ||
63 | setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ | 95 | setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ |
64 | break; | 96 | break; |
65 | } | 97 | } |
@@ -68,55 +100,39 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { | |||
68 | } | 100 | } |
69 | 101 | ||
70 | 102 | ||
71 | static void restore_stack_limit (lua_State *L) { | 103 | l_noret luaD_throw (lua_State *L, int errcode) { |
72 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); | 104 | if (L->errorJmp) { /* thread has an error handler? */ |
73 | if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ | 105 | L->errorJmp->status = errcode; /* set status */ |
74 | int inuse = cast_int(L->ci - L->base_ci); | 106 | LUAI_THROW(L, L->errorJmp); /* jump to it */ |
75 | if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ | ||
76 | luaD_reallocCI(L, LUAI_MAXCALLS); | ||
77 | } | 107 | } |
78 | } | 108 | else { /* thread has no error handler */ |
79 | 109 | L->status = cast_byte(errcode); /* mark it as dead */ | |
80 | 110 | if (G(L)->mainthread->errorJmp) { /* main thread has a handler? */ | |
81 | static void resetstack (lua_State *L, int status) { | 111 | setobjs2s(L, G(L)->mainthread->top++, L->top - 1); /* copy error obj. */ |
82 | L->ci = L->base_ci; | 112 | luaD_throw(G(L)->mainthread, errcode); /* re-throw in main thread */ |
83 | L->base = L->ci->base; | 113 | } |
84 | luaF_close(L, L->base); /* close eventual pending closures */ | 114 | else { /* no handler at all; abort */ |
85 | luaD_seterrorobj(L, status, L->base); | 115 | if (G(L)->panic) { /* panic function? */ |
86 | L->nCcalls = L->baseCcalls; | 116 | lua_unlock(L); |
87 | L->allowhook = 1; | 117 | G(L)->panic(L); /* call it (last chance to jump out) */ |
88 | restore_stack_limit(L); | 118 | } |
89 | L->errfunc = 0; | 119 | abort(); |
90 | L->errorJmp = NULL; | ||
91 | } | ||
92 | |||
93 | |||
94 | void luaD_throw (lua_State *L, int errcode) { | ||
95 | if (L->errorJmp) { | ||
96 | L->errorJmp->status = errcode; | ||
97 | LUAI_THROW(L, L->errorJmp); | ||
98 | } | ||
99 | else { | ||
100 | L->status = cast_byte(errcode); | ||
101 | if (G(L)->panic) { | ||
102 | resetstack(L, errcode); | ||
103 | lua_unlock(L); | ||
104 | G(L)->panic(L); | ||
105 | } | 120 | } |
106 | exit(EXIT_FAILURE); | ||
107 | } | 121 | } |
108 | } | 122 | } |
109 | 123 | ||
110 | 124 | ||
111 | int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | 125 | int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { |
126 | unsigned short oldnCcalls = L->nCcalls; | ||
112 | struct lua_longjmp lj; | 127 | struct lua_longjmp lj; |
113 | lj.status = 0; | 128 | lj.status = LUA_OK; |
114 | lj.previous = L->errorJmp; /* chain new error handler */ | 129 | lj.previous = L->errorJmp; /* chain new error handler */ |
115 | L->errorJmp = &lj; | 130 | L->errorJmp = &lj; |
116 | LUAI_TRY(L, &lj, | 131 | LUAI_TRY(L, &lj, |
117 | (*f)(L, ud); | 132 | (*f)(L, ud); |
118 | ); | 133 | ); |
119 | L->errorJmp = lj.previous; /* restore old error handler */ | 134 | L->errorJmp = lj.previous; /* restore old error handler */ |
135 | L->nCcalls = oldnCcalls; | ||
120 | return lj.status; | 136 | return lj.status; |
121 | } | 137 | } |
122 | 138 | ||
@@ -129,112 +145,127 @@ static void correctstack (lua_State *L, TValue *oldstack) { | |||
129 | L->top = (L->top - oldstack) + L->stack; | 145 | L->top = (L->top - oldstack) + L->stack; |
130 | for (up = L->openupval; up != NULL; up = up->gch.next) | 146 | for (up = L->openupval; up != NULL; up = up->gch.next) |
131 | gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; | 147 | gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; |
132 | for (ci = L->base_ci; ci <= L->ci; ci++) { | 148 | for (ci = L->ci; ci != NULL; ci = ci->previous) { |
133 | ci->top = (ci->top - oldstack) + L->stack; | 149 | ci->top = (ci->top - oldstack) + L->stack; |
134 | ci->base = (ci->base - oldstack) + L->stack; | ||
135 | ci->func = (ci->func - oldstack) + L->stack; | 150 | ci->func = (ci->func - oldstack) + L->stack; |
151 | if (isLua(ci)) | ||
152 | ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; | ||
136 | } | 153 | } |
137 | L->base = (L->base - oldstack) + L->stack; | ||
138 | } | 154 | } |
139 | 155 | ||
140 | 156 | ||
157 | /* some space for error handling */ | ||
158 | #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) | ||
159 | |||
160 | |||
141 | void luaD_reallocstack (lua_State *L, int newsize) { | 161 | void luaD_reallocstack (lua_State *L, int newsize) { |
142 | TValue *oldstack = L->stack; | 162 | TValue *oldstack = L->stack; |
143 | int realsize = newsize + 1 + EXTRA_STACK; | 163 | int lim = L->stacksize; |
144 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); | 164 | lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); |
145 | luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); | 165 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); |
146 | L->stacksize = realsize; | 166 | luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); |
147 | L->stack_last = L->stack+newsize; | 167 | for (; lim < newsize; lim++) |
168 | setnilvalue(L->stack + lim); /* erase new segment */ | ||
169 | L->stacksize = newsize; | ||
170 | L->stack_last = L->stack + newsize - EXTRA_STACK; | ||
148 | correctstack(L, oldstack); | 171 | correctstack(L, oldstack); |
149 | } | 172 | } |
150 | 173 | ||
151 | 174 | ||
152 | void luaD_reallocCI (lua_State *L, int newsize) { | 175 | void luaD_growstack (lua_State *L, int n) { |
153 | CallInfo *oldci = L->base_ci; | 176 | int size = L->stacksize; |
154 | luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); | 177 | if (size > LUAI_MAXSTACK) /* error after extra size? */ |
155 | L->size_ci = newsize; | 178 | luaD_throw(L, LUA_ERRERR); |
156 | L->ci = (L->ci - oldci) + L->base_ci; | 179 | else { |
157 | L->end_ci = L->base_ci + L->size_ci - 1; | 180 | int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; |
181 | int newsize = 2 * size; | ||
182 | if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; | ||
183 | if (newsize < needed) newsize = needed; | ||
184 | if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ | ||
185 | luaD_reallocstack(L, ERRORSTACKSIZE); | ||
186 | luaG_runerror(L, "stack overflow"); | ||
187 | } | ||
188 | else | ||
189 | luaD_reallocstack(L, newsize); | ||
190 | } | ||
158 | } | 191 | } |
159 | 192 | ||
160 | 193 | ||
161 | void luaD_growstack (lua_State *L, int n) { | 194 | static int stackinuse (lua_State *L) { |
162 | if (n <= L->stacksize) /* double size is enough? */ | 195 | CallInfo *ci; |
163 | luaD_reallocstack(L, 2*L->stacksize); | 196 | StkId lim = L->top; |
164 | else | 197 | for (ci = L->ci; ci != NULL; ci = ci->previous) { |
165 | luaD_reallocstack(L, L->stacksize + n); | 198 | lua_assert(ci->top <= L->stack_last); |
199 | if (lim < ci->top) lim = ci->top; | ||
200 | } | ||
201 | return cast_int(lim - L->stack) + 1; /* part of stack in use */ | ||
166 | } | 202 | } |
167 | 203 | ||
168 | 204 | ||
169 | static CallInfo *growCI (lua_State *L) { | 205 | void luaD_shrinkstack (lua_State *L) { |
170 | if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ | 206 | int inuse = stackinuse(L); |
171 | luaD_throw(L, LUA_ERRERR); | 207 | int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; |
172 | else { | 208 | if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK; |
173 | luaD_reallocCI(L, 2*L->size_ci); | 209 | if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */ |
174 | if (L->size_ci > LUAI_MAXCALLS) | 210 | goodsize >= L->stacksize) /* would grow instead of shrink? */ |
175 | luaG_runerror(L, "stack overflow"); | 211 | condmovestack(L); /* don't change stack (change only for debugging) */ |
176 | } | 212 | else |
177 | return ++L->ci; | 213 | luaD_reallocstack(L, goodsize); /* shrink it */ |
178 | } | 214 | } |
179 | 215 | ||
180 | 216 | ||
181 | void luaD_callhook (lua_State *L, int event, int line) { | 217 | void luaD_hook (lua_State *L, int event, int line) { |
182 | lua_Hook hook = L->hook; | 218 | lua_Hook hook = L->hook; |
183 | if (hook && L->allowhook) { | 219 | if (hook && L->allowhook) { |
220 | CallInfo *ci = L->ci; | ||
184 | ptrdiff_t top = savestack(L, L->top); | 221 | ptrdiff_t top = savestack(L, L->top); |
185 | ptrdiff_t ci_top = savestack(L, L->ci->top); | 222 | ptrdiff_t ci_top = savestack(L, ci->top); |
186 | lua_Debug ar; | 223 | lua_Debug ar; |
187 | ar.event = event; | 224 | ar.event = event; |
188 | ar.currentline = line; | 225 | ar.currentline = line; |
189 | if (event == LUA_HOOKTAILRET) | 226 | ar.i_ci = ci; |
190 | ar.i_ci = 0; /* tail call; no debug information about it */ | ||
191 | else | ||
192 | ar.i_ci = cast_int(L->ci - L->base_ci); | ||
193 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 227 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
194 | L->ci->top = L->top + LUA_MINSTACK; | 228 | ci->top = L->top + LUA_MINSTACK; |
195 | lua_assert(L->ci->top <= L->stack_last); | 229 | lua_assert(ci->top <= L->stack_last); |
196 | L->allowhook = 0; /* cannot call hooks inside a hook */ | 230 | L->allowhook = 0; /* cannot call hooks inside a hook */ |
231 | ci->callstatus |= CIST_HOOKED; | ||
197 | lua_unlock(L); | 232 | lua_unlock(L); |
198 | (*hook)(L, &ar); | 233 | (*hook)(L, &ar); |
199 | lua_lock(L); | 234 | lua_lock(L); |
200 | lua_assert(!L->allowhook); | 235 | lua_assert(!L->allowhook); |
201 | L->allowhook = 1; | 236 | L->allowhook = 1; |
202 | L->ci->top = restorestack(L, ci_top); | 237 | ci->top = restorestack(L, ci_top); |
203 | L->top = restorestack(L, top); | 238 | L->top = restorestack(L, top); |
239 | ci->callstatus &= ~CIST_HOOKED; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | |||
244 | static void callhook (lua_State *L, CallInfo *ci) { | ||
245 | int hook = LUA_HOOKCALL; | ||
246 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ | ||
247 | if (isLua(ci->previous) && | ||
248 | GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { | ||
249 | ci->callstatus |= CIST_TAIL; | ||
250 | hook = LUA_HOOKTAILCALL; | ||
204 | } | 251 | } |
252 | luaD_hook(L, hook, -1); | ||
253 | ci->u.l.savedpc--; /* correct 'pc' */ | ||
205 | } | 254 | } |
206 | 255 | ||
207 | 256 | ||
208 | static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { | 257 | static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { |
209 | int i; | 258 | int i; |
210 | int nfixargs = p->numparams; | 259 | int nfixargs = p->numparams; |
211 | Table *htab = NULL; | ||
212 | StkId base, fixed; | 260 | StkId base, fixed; |
213 | for (; actual < nfixargs; ++actual) | 261 | lua_assert(actual >= nfixargs); |
214 | setnilvalue(L->top++); | ||
215 | #if defined(LUA_COMPAT_VARARG) | ||
216 | if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ | ||
217 | int nvar = actual - nfixargs; /* number of extra arguments */ | ||
218 | lua_assert(p->is_vararg & VARARG_HASARG); | ||
219 | luaC_checkGC(L); | ||
220 | htab = luaH_new(L, nvar, 1); /* create `arg' table */ | ||
221 | for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */ | ||
222 | setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i); | ||
223 | /* store counter in field `n' */ | ||
224 | setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); | ||
225 | } | ||
226 | #endif | ||
227 | /* move fixed parameters to final position */ | 262 | /* move fixed parameters to final position */ |
263 | luaD_checkstack(L, p->maxstacksize); /* check again for new 'base' */ | ||
228 | fixed = L->top - actual; /* first fixed argument */ | 264 | fixed = L->top - actual; /* first fixed argument */ |
229 | base = L->top; /* final position of first argument */ | 265 | base = L->top; /* final position of first argument */ |
230 | for (i=0; i<nfixargs; i++) { | 266 | for (i=0; i<nfixargs; i++) { |
231 | setobjs2s(L, L->top++, fixed+i); | 267 | setobjs2s(L, L->top++, fixed + i); |
232 | setnilvalue(fixed+i); | 268 | setnilvalue(fixed + i); |
233 | } | ||
234 | /* add `arg' parameter */ | ||
235 | if (htab) { | ||
236 | sethvalue(L, L->top++, htab); | ||
237 | lua_assert(iswhite(obj2gco(htab))); | ||
238 | } | 269 | } |
239 | return base; | 270 | return base; |
240 | } | 271 | } |
@@ -256,100 +287,93 @@ static StkId tryfuncTM (lua_State *L, StkId func) { | |||
256 | 287 | ||
257 | 288 | ||
258 | 289 | ||
259 | #define inc_ci(L) \ | 290 | #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) |
260 | ((L->ci == L->end_ci) ? growCI(L) : \ | ||
261 | (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) | ||
262 | 291 | ||
263 | 292 | ||
293 | /* | ||
294 | ** returns true if function has been executed (C function) | ||
295 | */ | ||
264 | int luaD_precall (lua_State *L, StkId func, int nresults) { | 296 | int luaD_precall (lua_State *L, StkId func, int nresults) { |
265 | LClosure *cl; | 297 | lua_CFunction f; |
266 | ptrdiff_t funcr; | 298 | CallInfo *ci; |
267 | if (!ttisfunction(func)) /* `func' is not a function? */ | 299 | int n; /* number of arguments (Lua) or returns (C) */ |
268 | func = tryfuncTM(L, func); /* check the `function' tag method */ | 300 | ptrdiff_t funcr = savestack(L, func); |
269 | funcr = savestack(L, func); | 301 | switch (ttype(func)) { |
270 | cl = &clvalue(func)->l; | 302 | case LUA_TLCF: /* light C function */ |
271 | L->ci->savedpc = L->savedpc; | 303 | f = fvalue(func); |
272 | if (!cl->isC) { /* Lua function? prepare its call */ | 304 | goto Cfunc; |
273 | CallInfo *ci; | 305 | case LUA_TCCL: { /* C closure */ |
274 | StkId st, base; | 306 | f = clCvalue(func)->f; |
275 | Proto *p = cl->p; | 307 | Cfunc: |
276 | luaD_checkstack(L, p->maxstacksize); | 308 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
277 | func = restorestack(L, funcr); | 309 | ci = next_ci(L); /* now 'enter' new function */ |
278 | if (!p->is_vararg) { /* no varargs? */ | 310 | ci->nresults = nresults; |
279 | base = func + 1; | 311 | ci->func = restorestack(L, funcr); |
280 | if (L->top > base + p->numparams) | 312 | ci->top = L->top + LUA_MINSTACK; |
281 | L->top = base + p->numparams; | 313 | lua_assert(ci->top <= L->stack_last); |
282 | } | 314 | ci->callstatus = 0; |
283 | else { /* vararg function */ | 315 | luaC_checkGC(L); /* stack grow uses memory */ |
284 | int nargs = cast_int(L->top - func) - 1; | 316 | if (L->hookmask & LUA_MASKCALL) |
285 | base = adjust_varargs(L, p, nargs); | 317 | luaD_hook(L, LUA_HOOKCALL, -1); |
286 | func = restorestack(L, funcr); /* previous call may change the stack */ | 318 | lua_unlock(L); |
319 | n = (*f)(L); /* do the actual call */ | ||
320 | lua_lock(L); | ||
321 | api_checknelems(L, n); | ||
322 | luaD_poscall(L, L->top - n); | ||
323 | return 1; | ||
287 | } | 324 | } |
288 | ci = inc_ci(L); /* now `enter' new function */ | 325 | case LUA_TLCL: { /* Lua function: prepare its call */ |
289 | ci->func = func; | 326 | StkId base; |
290 | L->base = ci->base = base; | 327 | Proto *p = clLvalue(func)->p; |
291 | ci->top = L->base + p->maxstacksize; | 328 | n = cast_int(L->top - func) - 1; /* number of real arguments */ |
292 | lua_assert(ci->top <= L->stack_last); | 329 | luaD_checkstack(L, p->maxstacksize); |
293 | L->savedpc = p->code; /* starting point */ | 330 | for (; n < p->numparams; n++) |
294 | ci->tailcalls = 0; | 331 | setnilvalue(L->top++); /* complete missing arguments */ |
295 | ci->nresults = nresults; | 332 | if (!p->is_vararg) { |
296 | for (st = L->top; st < ci->top; st++) | 333 | func = restorestack(L, funcr); |
297 | setnilvalue(st); | 334 | base = func + 1; |
298 | L->top = ci->top; | 335 | } |
299 | if (L->hookmask & LUA_MASKCALL) { | 336 | else { |
300 | L->savedpc++; /* hooks assume 'pc' is already incremented */ | 337 | base = adjust_varargs(L, p, n); |
301 | luaD_callhook(L, LUA_HOOKCALL, -1); | 338 | func = restorestack(L, funcr); /* previous call can change stack */ |
302 | L->savedpc--; /* correct 'pc' */ | 339 | } |
340 | ci = next_ci(L); /* now 'enter' new function */ | ||
341 | ci->nresults = nresults; | ||
342 | ci->func = func; | ||
343 | ci->u.l.base = base; | ||
344 | ci->top = base + p->maxstacksize; | ||
345 | lua_assert(ci->top <= L->stack_last); | ||
346 | ci->u.l.savedpc = p->code; /* starting point */ | ||
347 | ci->callstatus = CIST_LUA; | ||
348 | L->top = ci->top; | ||
349 | luaC_checkGC(L); /* stack grow uses memory */ | ||
350 | if (L->hookmask & LUA_MASKCALL) | ||
351 | callhook(L, ci); | ||
352 | return 0; | ||
303 | } | 353 | } |
304 | return PCRLUA; | 354 | default: { /* not a function */ |
305 | } | 355 | func = tryfuncTM(L, func); /* retry with 'function' tag method */ |
306 | else { /* if is a C function, call it */ | 356 | return luaD_precall(L, func, nresults); /* now it must be a function */ |
307 | CallInfo *ci; | ||
308 | int n; | ||
309 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | ||
310 | ci = inc_ci(L); /* now `enter' new function */ | ||
311 | ci->func = restorestack(L, funcr); | ||
312 | L->base = ci->base = ci->func + 1; | ||
313 | ci->top = L->top + LUA_MINSTACK; | ||
314 | lua_assert(ci->top <= L->stack_last); | ||
315 | ci->nresults = nresults; | ||
316 | if (L->hookmask & LUA_MASKCALL) | ||
317 | luaD_callhook(L, LUA_HOOKCALL, -1); | ||
318 | lua_unlock(L); | ||
319 | n = (*curr_func(L)->c.f)(L); /* do the actual call */ | ||
320 | lua_lock(L); | ||
321 | if (n < 0) /* yielding? */ | ||
322 | return PCRYIELD; | ||
323 | else { | ||
324 | luaD_poscall(L, L->top - n); | ||
325 | return PCRC; | ||
326 | } | 357 | } |
327 | } | 358 | } |
328 | } | 359 | } |
329 | 360 | ||
330 | 361 | ||
331 | static StkId callrethooks (lua_State *L, StkId firstResult) { | ||
332 | ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ | ||
333 | luaD_callhook(L, LUA_HOOKRET, -1); | ||
334 | if (f_isLua(L->ci)) { /* Lua function? */ | ||
335 | while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ | ||
336 | luaD_callhook(L, LUA_HOOKTAILRET, -1); | ||
337 | } | ||
338 | return restorestack(L, fr); | ||
339 | } | ||
340 | |||
341 | |||
342 | int luaD_poscall (lua_State *L, StkId firstResult) { | 362 | int luaD_poscall (lua_State *L, StkId firstResult) { |
343 | StkId res; | 363 | StkId res; |
344 | int wanted, i; | 364 | int wanted, i; |
345 | CallInfo *ci; | 365 | CallInfo *ci = L->ci; |
346 | if (L->hookmask & LUA_MASKRET) | 366 | if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { |
347 | firstResult = callrethooks(L, firstResult); | 367 | if (L->hookmask & LUA_MASKRET) { |
348 | ci = L->ci--; | 368 | ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ |
369 | luaD_hook(L, LUA_HOOKRET, -1); | ||
370 | firstResult = restorestack(L, fr); | ||
371 | } | ||
372 | L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ | ||
373 | } | ||
349 | res = ci->func; /* res == final position of 1st result */ | 374 | res = ci->func; /* res == final position of 1st result */ |
350 | wanted = ci->nresults; | 375 | wanted = ci->nresults; |
351 | L->base = (ci - 1)->base; /* restore base */ | 376 | L->ci = ci = ci->previous; /* back to caller */ |
352 | L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ | ||
353 | /* move results to correct place */ | 377 | /* move results to correct place */ |
354 | for (i = wanted; i != 0 && firstResult < L->top; i--) | 378 | for (i = wanted; i != 0 && firstResult < L->top; i--) |
355 | setobjs2s(L, res++, firstResult++); | 379 | setobjs2s(L, res++, firstResult++); |
@@ -365,112 +389,226 @@ int luaD_poscall (lua_State *L, StkId firstResult) { | |||
365 | ** The arguments are on the stack, right after the function. | 389 | ** The arguments are on the stack, right after the function. |
366 | ** When returns, all the results are on the stack, starting at the original | 390 | ** When returns, all the results are on the stack, starting at the original |
367 | ** function position. | 391 | ** function position. |
368 | */ | 392 | */ |
369 | void luaD_call (lua_State *L, StkId func, int nResults) { | 393 | void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) { |
370 | if (++L->nCcalls >= LUAI_MAXCCALLS) { | 394 | if (++L->nCcalls >= LUAI_MAXCCALLS) { |
371 | if (L->nCcalls == LUAI_MAXCCALLS) | 395 | if (L->nCcalls == LUAI_MAXCCALLS) |
372 | luaG_runerror(L, "C stack overflow"); | 396 | luaG_runerror(L, "C stack overflow"); |
373 | else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) | 397 | else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) |
374 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ | 398 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ |
375 | } | 399 | } |
376 | if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ | 400 | if (!allowyield) L->nny++; |
377 | luaV_execute(L, 1); /* call it */ | 401 | if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ |
402 | luaV_execute(L); /* call it */ | ||
403 | if (!allowyield) L->nny--; | ||
378 | L->nCcalls--; | 404 | L->nCcalls--; |
379 | luaC_checkGC(L); | ||
380 | } | 405 | } |
381 | 406 | ||
382 | 407 | ||
383 | static void resume (lua_State *L, void *ud) { | 408 | static void finishCcall (lua_State *L) { |
384 | StkId firstArg = cast(StkId, ud); | ||
385 | CallInfo *ci = L->ci; | 409 | CallInfo *ci = L->ci; |
386 | if (L->status == 0) { /* start coroutine? */ | 410 | int n; |
387 | lua_assert(ci == L->base_ci && firstArg > L->base); | 411 | lua_assert(ci->u.c.k != NULL); /* must have a continuation */ |
388 | if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) | 412 | lua_assert(L->nny == 0); |
389 | return; | 413 | if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ |
414 | ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */ | ||
415 | L->errfunc = ci->u.c.old_errfunc; | ||
390 | } | 416 | } |
391 | else { /* resuming from previous yield */ | 417 | /* finish 'lua_callk'/'lua_pcall' */ |
392 | lua_assert(L->status == LUA_YIELD); | 418 | adjustresults(L, ci->nresults); |
393 | L->status = 0; | 419 | /* call continuation function */ |
394 | if (!f_isLua(ci)) { /* `common' yield? */ | 420 | if (!(ci->callstatus & CIST_STAT)) /* no call status? */ |
395 | /* finish interrupted execution of `OP_CALL' */ | 421 | ci->u.c.status = LUA_YIELD; /* 'default' status */ |
396 | lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || | 422 | lua_assert(ci->u.c.status != LUA_OK); |
397 | GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); | 423 | ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED; |
398 | if (luaD_poscall(L, firstArg)) /* complete it... */ | 424 | lua_unlock(L); |
399 | L->top = L->ci->top; /* and correct top if not multiple results */ | 425 | n = (*ci->u.c.k)(L); |
426 | lua_lock(L); | ||
427 | api_checknelems(L, n); | ||
428 | /* finish 'luaD_precall' */ | ||
429 | luaD_poscall(L, L->top - n); | ||
430 | } | ||
431 | |||
432 | |||
433 | static void unroll (lua_State *L, void *ud) { | ||
434 | UNUSED(ud); | ||
435 | for (;;) { | ||
436 | if (L->ci == &L->base_ci) /* stack is empty? */ | ||
437 | return; /* coroutine finished normally */ | ||
438 | if (!isLua(L->ci)) /* C function? */ | ||
439 | finishCcall(L); | ||
440 | else { /* Lua function */ | ||
441 | luaV_finishOp(L); /* finish interrupted instruction */ | ||
442 | luaV_execute(L); /* execute down to higher C 'boundary' */ | ||
400 | } | 443 | } |
401 | else /* yielded inside a hook: just continue its execution */ | ||
402 | L->base = L->ci->base; | ||
403 | } | 444 | } |
404 | luaV_execute(L, cast_int(L->ci - L->base_ci)); | ||
405 | } | 445 | } |
406 | 446 | ||
407 | 447 | ||
408 | static int resume_error (lua_State *L, const char *msg) { | 448 | /* |
409 | L->top = L->ci->base; | 449 | ** check whether thread has a suspended protected call |
410 | setsvalue2s(L, L->top, luaS_new(L, msg)); | 450 | */ |
411 | incr_top(L); | 451 | static CallInfo *findpcall (lua_State *L) { |
412 | lua_unlock(L); | 452 | CallInfo *ci; |
413 | return LUA_ERRRUN; | 453 | for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ |
454 | if (ci->callstatus & CIST_YPCALL) | ||
455 | return ci; | ||
456 | } | ||
457 | return NULL; /* no pending pcall */ | ||
458 | } | ||
459 | |||
460 | |||
461 | static int recover (lua_State *L, int status) { | ||
462 | StkId oldtop; | ||
463 | CallInfo *ci = findpcall(L); | ||
464 | if (ci == NULL) return 0; /* no recovery point */ | ||
465 | /* "finish" luaD_pcall */ | ||
466 | oldtop = restorestack(L, ci->extra); | ||
467 | luaF_close(L, oldtop); | ||
468 | seterrorobj(L, status, oldtop); | ||
469 | L->ci = ci; | ||
470 | L->allowhook = ci->u.c.old_allowhook; | ||
471 | L->nny = 0; /* should be zero to be yieldable */ | ||
472 | luaD_shrinkstack(L); | ||
473 | L->errfunc = ci->u.c.old_errfunc; | ||
474 | ci->callstatus |= CIST_STAT; /* call has error status */ | ||
475 | ci->u.c.status = status; /* (here it is) */ | ||
476 | return 1; /* continue running the coroutine */ | ||
477 | } | ||
478 | |||
479 | |||
480 | /* | ||
481 | ** signal an error in the call to 'resume', not in the execution of the | ||
482 | ** coroutine itself. (Such errors should not be handled by any coroutine | ||
483 | ** error handler and should not kill the coroutine.) | ||
484 | */ | ||
485 | static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) { | ||
486 | L->top = firstArg; /* remove args from the stack */ | ||
487 | setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ | ||
488 | api_incr_top(L); | ||
489 | luaD_throw(L, -1); /* jump back to 'lua_resume' */ | ||
414 | } | 490 | } |
415 | 491 | ||
416 | 492 | ||
417 | LUA_API int lua_resume (lua_State *L, int nargs) { | 493 | /* |
494 | ** do the work for 'lua_resume' in protected mode | ||
495 | */ | ||
496 | static void resume (lua_State *L, void *ud) { | ||
497 | int nCcalls = L->nCcalls; | ||
498 | StkId firstArg = cast(StkId, ud); | ||
499 | CallInfo *ci = L->ci; | ||
500 | if (nCcalls >= LUAI_MAXCCALLS) | ||
501 | resume_error(L, "C stack overflow", firstArg); | ||
502 | if (L->status == LUA_OK) { /* may be starting a coroutine */ | ||
503 | if (ci != &L->base_ci) /* not in base level? */ | ||
504 | resume_error(L, "cannot resume non-suspended coroutine", firstArg); | ||
505 | /* coroutine is in base level; start running it */ | ||
506 | if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ | ||
507 | luaV_execute(L); /* call it */ | ||
508 | } | ||
509 | else if (L->status != LUA_YIELD) | ||
510 | resume_error(L, "cannot resume dead coroutine", firstArg); | ||
511 | else { /* resuming from previous yield */ | ||
512 | L->status = LUA_OK; | ||
513 | ci->func = restorestack(L, ci->extra); | ||
514 | if (isLua(ci)) /* yielded inside a hook? */ | ||
515 | luaV_execute(L); /* just continue running Lua code */ | ||
516 | else { /* 'common' yield */ | ||
517 | if (ci->u.c.k != NULL) { /* does it have a continuation? */ | ||
518 | int n; | ||
519 | ci->u.c.status = LUA_YIELD; /* 'default' status */ | ||
520 | ci->callstatus |= CIST_YIELDED; | ||
521 | lua_unlock(L); | ||
522 | n = (*ci->u.c.k)(L); /* call continuation */ | ||
523 | lua_lock(L); | ||
524 | api_checknelems(L, n); | ||
525 | firstArg = L->top - n; /* yield results come from continuation */ | ||
526 | } | ||
527 | luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ | ||
528 | } | ||
529 | unroll(L, NULL); | ||
530 | } | ||
531 | lua_assert(nCcalls == L->nCcalls); | ||
532 | } | ||
533 | |||
534 | |||
535 | LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { | ||
418 | int status; | 536 | int status; |
537 | int oldnny = L->nny; /* save 'nny' */ | ||
419 | lua_lock(L); | 538 | lua_lock(L); |
420 | if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) | ||
421 | return resume_error(L, "cannot resume non-suspended coroutine"); | ||
422 | if (L->nCcalls >= LUAI_MAXCCALLS) | ||
423 | return resume_error(L, "C stack overflow"); | ||
424 | luai_userstateresume(L, nargs); | 539 | luai_userstateresume(L, nargs); |
425 | lua_assert(L->errfunc == 0); | 540 | L->nCcalls = (from) ? from->nCcalls + 1 : 1; |
426 | L->baseCcalls = ++L->nCcalls; | 541 | L->nny = 0; /* allow yields */ |
542 | api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); | ||
427 | status = luaD_rawrunprotected(L, resume, L->top - nargs); | 543 | status = luaD_rawrunprotected(L, resume, L->top - nargs); |
428 | if (status != 0) { /* error? */ | 544 | if (status == -1) /* error calling 'lua_resume'? */ |
429 | L->status = cast_byte(status); /* mark thread as `dead' */ | 545 | status = LUA_ERRRUN; |
430 | luaD_seterrorobj(L, status, L->top); | 546 | else { /* yield or regular error */ |
431 | L->ci->top = L->top; | 547 | while (status != LUA_OK && status != LUA_YIELD) { /* error? */ |
432 | } | 548 | if (recover(L, status)) /* recover point? */ |
433 | else { | 549 | status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */ |
434 | lua_assert(L->nCcalls == L->baseCcalls); | 550 | else { /* unrecoverable error */ |
435 | status = L->status; | 551 | L->status = cast_byte(status); /* mark thread as `dead' */ |
552 | seterrorobj(L, status, L->top); | ||
553 | L->ci->top = L->top; | ||
554 | break; | ||
555 | } | ||
556 | } | ||
557 | lua_assert(status == L->status); | ||
436 | } | 558 | } |
437 | --L->nCcalls; | 559 | L->nny = oldnny; /* restore 'nny' */ |
560 | L->nCcalls--; | ||
561 | lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); | ||
438 | lua_unlock(L); | 562 | lua_unlock(L); |
439 | return status; | 563 | return status; |
440 | } | 564 | } |
441 | 565 | ||
442 | 566 | ||
443 | LUA_API int lua_yield (lua_State *L, int nresults) { | 567 | LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) { |
568 | CallInfo *ci = L->ci; | ||
444 | luai_userstateyield(L, nresults); | 569 | luai_userstateyield(L, nresults); |
445 | lua_lock(L); | 570 | lua_lock(L); |
446 | if (L->nCcalls > L->baseCcalls) | 571 | api_checknelems(L, nresults); |
447 | luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); | 572 | if (L->nny > 0) { |
448 | L->base = L->top - nresults; /* protect stack slots below */ | 573 | if (L != G(L)->mainthread) |
574 | luaG_runerror(L, "attempt to yield across a C-call boundary"); | ||
575 | else | ||
576 | luaG_runerror(L, "attempt to yield from outside a coroutine"); | ||
577 | } | ||
449 | L->status = LUA_YIELD; | 578 | L->status = LUA_YIELD; |
579 | ci->extra = savestack(L, ci->func); /* save current 'func' */ | ||
580 | if (isLua(ci)) { /* inside a hook? */ | ||
581 | api_check(L, k == NULL, "hooks cannot continue after yielding"); | ||
582 | } | ||
583 | else { | ||
584 | if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ | ||
585 | ci->u.c.ctx = ctx; /* save context */ | ||
586 | ci->func = L->top - nresults - 1; /* protect stack below results */ | ||
587 | luaD_throw(L, LUA_YIELD); | ||
588 | } | ||
589 | lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ | ||
450 | lua_unlock(L); | 590 | lua_unlock(L); |
451 | return -1; | 591 | return 0; /* return to 'luaD_hook' */ |
452 | } | 592 | } |
453 | 593 | ||
454 | 594 | ||
455 | int luaD_pcall (lua_State *L, Pfunc func, void *u, | 595 | int luaD_pcall (lua_State *L, Pfunc func, void *u, |
456 | ptrdiff_t old_top, ptrdiff_t ef) { | 596 | ptrdiff_t old_top, ptrdiff_t ef) { |
457 | int status; | 597 | int status; |
458 | unsigned short oldnCcalls = L->nCcalls; | 598 | CallInfo *old_ci = L->ci; |
459 | ptrdiff_t old_ci = saveci(L, L->ci); | ||
460 | lu_byte old_allowhooks = L->allowhook; | 599 | lu_byte old_allowhooks = L->allowhook; |
600 | unsigned short old_nny = L->nny; | ||
461 | ptrdiff_t old_errfunc = L->errfunc; | 601 | ptrdiff_t old_errfunc = L->errfunc; |
462 | L->errfunc = ef; | 602 | L->errfunc = ef; |
463 | status = luaD_rawrunprotected(L, func, u); | 603 | status = luaD_rawrunprotected(L, func, u); |
464 | if (status != 0) { /* an error occurred? */ | 604 | if (status != LUA_OK) { /* an error occurred? */ |
465 | StkId oldtop = restorestack(L, old_top); | 605 | StkId oldtop = restorestack(L, old_top); |
466 | luaF_close(L, oldtop); /* close eventual pending closures */ | 606 | luaF_close(L, oldtop); /* close possible pending closures */ |
467 | luaD_seterrorobj(L, status, oldtop); | 607 | seterrorobj(L, status, oldtop); |
468 | L->nCcalls = oldnCcalls; | 608 | L->ci = old_ci; |
469 | L->ci = restoreci(L, old_ci); | ||
470 | L->base = L->ci->base; | ||
471 | L->savedpc = L->ci->savedpc; | ||
472 | L->allowhook = old_allowhooks; | 609 | L->allowhook = old_allowhooks; |
473 | restore_stack_limit(L); | 610 | L->nny = old_nny; |
611 | luaD_shrinkstack(L); | ||
474 | } | 612 | } |
475 | L->errfunc = old_errfunc; | 613 | L->errfunc = old_errfunc; |
476 | return status; | 614 | return status; |
@@ -483,35 +621,60 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, | |||
483 | */ | 621 | */ |
484 | struct SParser { /* data to `f_parser' */ | 622 | struct SParser { /* data to `f_parser' */ |
485 | ZIO *z; | 623 | ZIO *z; |
486 | Mbuffer buff; /* buffer to be used by the scanner */ | 624 | Mbuffer buff; /* dynamic structure used by the scanner */ |
625 | Dyndata dyd; /* dynamic structures used by the parser */ | ||
626 | const char *mode; | ||
487 | const char *name; | 627 | const char *name; |
488 | }; | 628 | }; |
489 | 629 | ||
630 | |||
631 | static void checkmode (lua_State *L, const char *mode, const char *x) { | ||
632 | if (mode && strchr(mode, x[0]) == NULL) { | ||
633 | luaO_pushfstring(L, | ||
634 | "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode); | ||
635 | luaD_throw(L, LUA_ERRSYNTAX); | ||
636 | } | ||
637 | } | ||
638 | |||
639 | |||
490 | static void f_parser (lua_State *L, void *ud) { | 640 | static void f_parser (lua_State *L, void *ud) { |
491 | int i; | 641 | int i; |
492 | Proto *tf; | ||
493 | Closure *cl; | 642 | Closure *cl; |
494 | struct SParser *p = cast(struct SParser *, ud); | 643 | struct SParser *p = cast(struct SParser *, ud); |
495 | int c = luaZ_lookahead(p->z); | 644 | int c = zgetc(p->z); /* read first character */ |
496 | luaC_checkGC(L); | 645 | if (c == LUA_SIGNATURE[0]) { |
497 | tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, | 646 | checkmode(L, p->mode, "binary"); |
498 | &p->buff, p->name); | 647 | cl = luaU_undump(L, p->z, &p->buff, p->name); |
499 | cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); | 648 | } |
500 | cl->l.p = tf; | 649 | else { |
501 | for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ | 650 | checkmode(L, p->mode, "text"); |
502 | cl->l.upvals[i] = luaF_newupval(L); | 651 | cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); |
503 | setclvalue(L, L->top, cl); | 652 | } |
504 | incr_top(L); | 653 | lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues); |
654 | for (i = 0; i < cl->l.nupvalues; i++) { /* initialize upvalues */ | ||
655 | UpVal *up = luaF_newupval(L); | ||
656 | cl->l.upvals[i] = up; | ||
657 | luaC_objbarrier(L, cl, up); | ||
658 | } | ||
505 | } | 659 | } |
506 | 660 | ||
507 | 661 | ||
508 | int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { | 662 | int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, |
663 | const char *mode) { | ||
509 | struct SParser p; | 664 | struct SParser p; |
510 | int status; | 665 | int status; |
511 | p.z = z; p.name = name; | 666 | L->nny++; /* cannot yield during parsing */ |
667 | p.z = z; p.name = name; p.mode = mode; | ||
668 | p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; | ||
669 | p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; | ||
670 | p.dyd.label.arr = NULL; p.dyd.label.size = 0; | ||
512 | luaZ_initbuffer(L, &p.buff); | 671 | luaZ_initbuffer(L, &p.buff); |
513 | status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); | 672 | status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); |
514 | luaZ_freebuffer(L, &p.buff); | 673 | luaZ_freebuffer(L, &p.buff); |
674 | luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); | ||
675 | luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); | ||
676 | luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); | ||
677 | L->nny--; | ||
515 | return status; | 678 | return status; |
516 | } | 679 | } |
517 | 680 | ||