diff options
Diffstat (limited to 'apps/plugins')
64 files changed, 8838 insertions, 5483 deletions
diff --git a/apps/plugins/lua/SOURCES b/apps/plugins/lua/SOURCES index baebfabe65..e3d9947e1e 100644 --- a/apps/plugins/lua/SOURCES +++ b/apps/plugins/lua/SOURCES | |||
@@ -31,12 +31,13 @@ rocklib.c | |||
31 | tlsf_helper.c | 31 | tlsf_helper.c |
32 | fscanf.c | 32 | fscanf.c |
33 | gmtime.c | 33 | gmtime.c |
34 | strcspn.c | 34 | strspn.c |
35 | strftime.c | 35 | strftime.c |
36 | strncat.c | 36 | strncat.c |
37 | strpbrk.c | 37 | strpbrk.c |
38 | strtoul.c | 38 | strtoul.c |
39 | strtol.c | 39 | strtol.c |
40 | strstr.c | 40 | strstr.c |
41 | getc.c | ||
41 | rocklua.c | 42 | rocklua.c |
42 | luadir.c | 43 | luadir.c |
diff --git a/apps/plugins/lua/fscanf.c b/apps/plugins/lua/fscanf.c index 9f5f129d3c..ee42daeab7 100644 --- a/apps/plugins/lua/fscanf.c +++ b/apps/plugins/lua/fscanf.c | |||
@@ -266,7 +266,7 @@ static int scan(int (*peek)(void *userp), | |||
266 | 266 | ||
267 | static int fspeek(void *userp) | 267 | static int fspeek(void *userp) |
268 | { | 268 | { |
269 | int fd = *((int*) userp); | 269 | int fd = ((int) userp); |
270 | char buf = 0; | 270 | char buf = 0; |
271 | if(rb->read(fd, &buf, 1) == 1) | 271 | if(rb->read(fd, &buf, 1) == 1) |
272 | rb->lseek(fd, -1, SEEK_CUR); | 272 | rb->lseek(fd, -1, SEEK_CUR); |
@@ -275,11 +275,11 @@ static int fspeek(void *userp) | |||
275 | 275 | ||
276 | static void fspop(void *userp) | 276 | static void fspop(void *userp) |
277 | { | 277 | { |
278 | int fd = *((int*) userp); | 278 | int fd = ((int) userp); |
279 | rb->lseek(fd, 1, SEEK_CUR); | 279 | rb->lseek(fd, 1, SEEK_CUR); |
280 | } | 280 | } |
281 | 281 | ||
282 | int PREFIX(fscanf)(int fd, const char *fmt, ...) | 282 | int PREFIX(fscanf)(void *fd, const char *fmt, ...) |
283 | { | 283 | { |
284 | int r; | 284 | int r; |
285 | va_list ap; | 285 | va_list ap; |
diff --git a/apps/plugins/lua/getc.c b/apps/plugins/lua/getc.c new file mode 100644 index 0000000000..84a280e2c2 --- /dev/null +++ b/apps/plugins/lua/getc.c | |||
@@ -0,0 +1,10 @@ | |||
1 | #include "rocklibc.h" | ||
2 | |||
3 | int PREFIX(getc)(int fd) | ||
4 | { | ||
5 | unsigned char c; | ||
6 | if (rb->read(fd, &c, 1)) | ||
7 | return c; | ||
8 | else | ||
9 | return EOF; | ||
10 | } | ||
diff --git a/apps/plugins/lua/lapi.c b/apps/plugins/lua/lapi.c index 487d6b173a..d011431ead 100644 --- a/apps/plugins/lua/lapi.c +++ b/apps/plugins/lua/lapi.c | |||
@@ -1,12 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ | 2 | ** $Id: lapi.c,v 2.171.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Lua API | 3 | ** Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
6 | 6 | ||
7 | 7 | ||
8 | /* #include <assert.h> */ | ||
9 | #include <math.h> | ||
10 | #include <stdarg.h> | 8 | #include <stdarg.h> |
11 | #include <string.h> | 9 | #include <string.h> |
12 | 10 | ||
@@ -32,76 +30,80 @@ | |||
32 | 30 | ||
33 | 31 | ||
34 | const char lua_ident[] = | 32 | const char lua_ident[] = |
35 | "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" | 33 | "$LuaVersion: " LUA_COPYRIGHT " $" |
36 | "$Authors: " LUA_AUTHORS " $\n" | 34 | "$LuaAuthors: " LUA_AUTHORS " $"; |
37 | "$URL: www.lua.org $\n"; | ||
38 | 35 | ||
39 | 36 | ||
37 | /* value at a non-valid index */ | ||
38 | #define NONVALIDVALUE cast(TValue *, luaO_nilobject) | ||
40 | 39 | ||
41 | #define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) | 40 | /* corresponding test */ |
41 | #define isvalid(o) ((o) != luaO_nilobject) | ||
42 | 42 | ||
43 | #define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) | 43 | /* test for pseudo index */ |
44 | #define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) | ||
44 | 45 | ||
45 | #define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} | 46 | /* test for valid but not pseudo index */ |
47 | #define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) | ||
46 | 48 | ||
49 | #define api_checkvalidindex(L, o) api_check(L, isvalid(o), "invalid index") | ||
47 | 50 | ||
51 | #define api_checkstackindex(L, i, o) \ | ||
52 | api_check(L, isstackindex(i, o), "index not in the stack") | ||
48 | 53 | ||
49 | static TValue *index2adr (lua_State *L, int idx) { | 54 | |
55 | static TValue *index2addr (lua_State *L, int idx) { | ||
56 | CallInfo *ci = L->ci; | ||
50 | if (idx > 0) { | 57 | if (idx > 0) { |
51 | TValue *o = L->base + (idx - 1); | 58 | TValue *o = ci->func + idx; |
52 | api_check(L, idx <= L->ci->top - L->base); | 59 | api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); |
53 | if (o >= L->top) return cast(TValue *, luaO_nilobject); | 60 | if (o >= L->top) return NONVALIDVALUE; |
54 | else return o; | 61 | else return o; |
55 | } | 62 | } |
56 | else if (idx > LUA_REGISTRYINDEX) { | 63 | else if (!ispseudo(idx)) { /* negative index */ |
57 | api_check(L, idx != 0 && -idx <= L->top - L->base); | 64 | api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); |
58 | return L->top + idx; | 65 | return L->top + idx; |
59 | } | 66 | } |
60 | else switch (idx) { /* pseudo-indices */ | 67 | else if (idx == LUA_REGISTRYINDEX) |
61 | case LUA_REGISTRYINDEX: return registry(L); | 68 | return &G(L)->l_registry; |
62 | case LUA_ENVIRONINDEX: { | 69 | else { /* upvalues */ |
63 | Closure *func = curr_func(L); | 70 | idx = LUA_REGISTRYINDEX - idx; |
64 | sethvalue(L, &L->env, func->c.env); | 71 | api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); |
65 | return &L->env; | 72 | if (ttislcf(ci->func)) /* light C function? */ |
66 | } | 73 | return NONVALIDVALUE; /* it has no upvalues */ |
67 | case LUA_GLOBALSINDEX: return gt(L); | 74 | else { |
68 | default: { | 75 | CClosure *func = clCvalue(ci->func); |
69 | Closure *func = curr_func(L); | 76 | return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; |
70 | idx = LUA_GLOBALSINDEX - idx; | ||
71 | return (idx <= func->c.nupvalues) | ||
72 | ? &func->c.upvalue[idx-1] | ||
73 | : cast(TValue *, luaO_nilobject); | ||
74 | } | 77 | } |
75 | } | 78 | } |
76 | } | 79 | } |
77 | 80 | ||
78 | 81 | ||
79 | static Table *getcurrenv (lua_State *L) { | 82 | /* |
80 | if (L->ci == L->base_ci) /* no enclosing function? */ | 83 | ** to be called by 'lua_checkstack' in protected mode, to grow stack |
81 | return hvalue(gt(L)); /* use global table as environment */ | 84 | ** capturing memory errors |
82 | else { | 85 | */ |
83 | Closure *func = curr_func(L); | 86 | static void growstack (lua_State *L, void *ud) { |
84 | return func->c.env; | 87 | int size = *(int *)ud; |
85 | } | 88 | luaD_growstack(L, size); |
86 | } | ||
87 | |||
88 | |||
89 | void luaA_pushobject (lua_State *L, const TValue *o) { | ||
90 | setobj2s(L, L->top, o); | ||
91 | api_incr_top(L); | ||
92 | } | 89 | } |
93 | 90 | ||
94 | 91 | ||
95 | LUA_API int lua_checkstack (lua_State *L, int size) { | 92 | LUA_API int lua_checkstack (lua_State *L, int size) { |
96 | int res = 1; | 93 | int res; |
94 | CallInfo *ci = L->ci; | ||
97 | lua_lock(L); | 95 | lua_lock(L); |
98 | if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) | 96 | if (L->stack_last - L->top > size) /* stack large enough? */ |
99 | res = 0; /* stack overflow */ | 97 | res = 1; /* yes; check is OK */ |
100 | else if (size > 0) { | 98 | else { /* no; need to grow stack */ |
101 | luaD_checkstack(L, size); | 99 | int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; |
102 | if (L->ci->top < L->top + size) | 100 | if (inuse > LUAI_MAXSTACK - size) /* can grow without overflow? */ |
103 | L->ci->top = L->top + size; | 101 | res = 0; /* no */ |
102 | else /* try to grow stack */ | ||
103 | res = (luaD_rawrunprotected(L, &growstack, &size) == LUA_OK); | ||
104 | } | 104 | } |
105 | if (res && ci->top < L->top + size) | ||
106 | ci->top = L->top + size; /* adjust frame top */ | ||
105 | lua_unlock(L); | 107 | lua_unlock(L); |
106 | return res; | 108 | return res; |
107 | } | 109 | } |
@@ -112,8 +114,8 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { | |||
112 | if (from == to) return; | 114 | if (from == to) return; |
113 | lua_lock(to); | 115 | lua_lock(to); |
114 | api_checknelems(from, n); | 116 | api_checknelems(from, n); |
115 | api_check(from, G(from) == G(to)); | 117 | api_check(from, G(from) == G(to), "moving among independent states"); |
116 | api_check(from, to->ci->top - to->top >= n); | 118 | api_check(from, to->ci->top - to->top >= n, "not enough elements to move"); |
117 | from->top -= n; | 119 | from->top -= n; |
118 | for (i = 0; i < n; i++) { | 120 | for (i = 0; i < n; i++) { |
119 | setobj2s(to, to->top++, from->top + i); | 121 | setobj2s(to, to->top++, from->top + i); |
@@ -122,11 +124,6 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { | |||
122 | } | 124 | } |
123 | 125 | ||
124 | 126 | ||
125 | LUA_API void lua_setlevel (lua_State *from, lua_State *to) { | ||
126 | to->nCcalls = from->nCcalls; | ||
127 | } | ||
128 | |||
129 | |||
130 | LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { | 127 | LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { |
131 | lua_CFunction old; | 128 | lua_CFunction old; |
132 | lua_lock(L); | 129 | lua_lock(L); |
@@ -137,16 +134,10 @@ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { | |||
137 | } | 134 | } |
138 | 135 | ||
139 | 136 | ||
140 | LUA_API lua_State *lua_newthread (lua_State *L) { | 137 | LUA_API const lua_Number *lua_version (lua_State *L) { |
141 | lua_State *L1; | 138 | static const lua_Number version = LUA_VERSION_NUM; |
142 | lua_lock(L); | 139 | if (L == NULL) return &version; |
143 | luaC_checkGC(L); | 140 | else return G(L)->version; |
144 | L1 = luaE_newthread(L); | ||
145 | setthvalue(L, L->top, L1); | ||
146 | api_incr_top(L); | ||
147 | lua_unlock(L); | ||
148 | luai_userstatethread(L, L1); | ||
149 | return L1; | ||
150 | } | 141 | } |
151 | 142 | ||
152 | 143 | ||
@@ -156,21 +147,32 @@ LUA_API lua_State *lua_newthread (lua_State *L) { | |||
156 | */ | 147 | */ |
157 | 148 | ||
158 | 149 | ||
150 | /* | ||
151 | ** convert an acceptable stack index into an absolute index | ||
152 | */ | ||
153 | LUA_API int lua_absindex (lua_State *L, int idx) { | ||
154 | return (idx > 0 || ispseudo(idx)) | ||
155 | ? idx | ||
156 | : cast_int(L->top - L->ci->func + idx); | ||
157 | } | ||
158 | |||
159 | |||
159 | LUA_API int lua_gettop (lua_State *L) { | 160 | LUA_API int lua_gettop (lua_State *L) { |
160 | return cast_int(L->top - L->base); | 161 | return cast_int(L->top - (L->ci->func + 1)); |
161 | } | 162 | } |
162 | 163 | ||
163 | 164 | ||
164 | LUA_API void lua_settop (lua_State *L, int idx) { | 165 | LUA_API void lua_settop (lua_State *L, int idx) { |
166 | StkId func = L->ci->func; | ||
165 | lua_lock(L); | 167 | lua_lock(L); |
166 | if (idx >= 0) { | 168 | if (idx >= 0) { |
167 | api_check(L, idx <= L->stack_last - L->base); | 169 | api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); |
168 | while (L->top < L->base + idx) | 170 | while (L->top < (func + 1) + idx) |
169 | setnilvalue(L->top++); | 171 | setnilvalue(L->top++); |
170 | L->top = L->base + idx; | 172 | L->top = (func + 1) + idx; |
171 | } | 173 | } |
172 | else { | 174 | else { |
173 | api_check(L, -(idx+1) <= (L->top - L->base)); | 175 | api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); |
174 | L->top += idx+1; /* `subtract' index (index is negative) */ | 176 | L->top += idx+1; /* `subtract' index (index is negative) */ |
175 | } | 177 | } |
176 | lua_unlock(L); | 178 | lua_unlock(L); |
@@ -180,8 +182,8 @@ LUA_API void lua_settop (lua_State *L, int idx) { | |||
180 | LUA_API void lua_remove (lua_State *L, int idx) { | 182 | LUA_API void lua_remove (lua_State *L, int idx) { |
181 | StkId p; | 183 | StkId p; |
182 | lua_lock(L); | 184 | lua_lock(L); |
183 | p = index2adr(L, idx); | 185 | p = index2addr(L, idx); |
184 | api_checkvalidindex(L, p); | 186 | api_checkstackindex(L, idx, p); |
185 | while (++p < L->top) setobjs2s(L, p-1, p); | 187 | while (++p < L->top) setobjs2s(L, p-1, p); |
186 | L->top--; | 188 | L->top--; |
187 | lua_unlock(L); | 189 | lua_unlock(L); |
@@ -192,42 +194,47 @@ LUA_API void lua_insert (lua_State *L, int idx) { | |||
192 | StkId p; | 194 | StkId p; |
193 | StkId q; | 195 | StkId q; |
194 | lua_lock(L); | 196 | lua_lock(L); |
195 | p = index2adr(L, idx); | 197 | p = index2addr(L, idx); |
196 | api_checkvalidindex(L, p); | 198 | api_checkstackindex(L, idx, p); |
197 | for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); | 199 | for (q = L->top; q > p; q--) /* use L->top as a temporary */ |
200 | setobjs2s(L, q, q - 1); | ||
198 | setobjs2s(L, p, L->top); | 201 | setobjs2s(L, p, L->top); |
199 | lua_unlock(L); | 202 | lua_unlock(L); |
200 | } | 203 | } |
201 | 204 | ||
202 | 205 | ||
206 | static void moveto (lua_State *L, TValue *fr, int idx) { | ||
207 | TValue *to = index2addr(L, idx); | ||
208 | api_checkvalidindex(L, to); | ||
209 | setobj(L, to, fr); | ||
210 | if (idx < LUA_REGISTRYINDEX) /* function upvalue? */ | ||
211 | luaC_barrier(L, clCvalue(L->ci->func), fr); | ||
212 | /* LUA_REGISTRYINDEX does not need gc barrier | ||
213 | (collector revisits it before finishing collection) */ | ||
214 | } | ||
215 | |||
216 | |||
203 | LUA_API void lua_replace (lua_State *L, int idx) { | 217 | LUA_API void lua_replace (lua_State *L, int idx) { |
204 | StkId o; | ||
205 | lua_lock(L); | 218 | lua_lock(L); |
206 | /* explicit test for incompatible code */ | ||
207 | if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) | ||
208 | luaG_runerror(L, "no calling environment"); | ||
209 | api_checknelems(L, 1); | 219 | api_checknelems(L, 1); |
210 | o = index2adr(L, idx); | 220 | moveto(L, L->top - 1, idx); |
211 | api_checkvalidindex(L, o); | ||
212 | if (idx == LUA_ENVIRONINDEX) { | ||
213 | Closure *func = curr_func(L); | ||
214 | api_check(L, ttistable(L->top - 1)); | ||
215 | func->c.env = hvalue(L->top - 1); | ||
216 | luaC_barrier(L, func, L->top - 1); | ||
217 | } | ||
218 | else { | ||
219 | setobj(L, o, L->top - 1); | ||
220 | if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ | ||
221 | luaC_barrier(L, curr_func(L), L->top - 1); | ||
222 | } | ||
223 | L->top--; | 221 | L->top--; |
224 | lua_unlock(L); | 222 | lua_unlock(L); |
225 | } | 223 | } |
226 | 224 | ||
227 | 225 | ||
226 | LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { | ||
227 | TValue *fr; | ||
228 | lua_lock(L); | ||
229 | fr = index2addr(L, fromidx); | ||
230 | moveto(L, fr, toidx); | ||
231 | lua_unlock(L); | ||
232 | } | ||
233 | |||
234 | |||
228 | LUA_API void lua_pushvalue (lua_State *L, int idx) { | 235 | LUA_API void lua_pushvalue (lua_State *L, int idx) { |
229 | lua_lock(L); | 236 | lua_lock(L); |
230 | setobj2s(L, L->top, index2adr(L, idx)); | 237 | setobj2s(L, L->top, index2addr(L, idx)); |
231 | api_incr_top(L); | 238 | api_incr_top(L); |
232 | lua_unlock(L); | 239 | lua_unlock(L); |
233 | } | 240 | } |
@@ -240,26 +247,26 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) { | |||
240 | 247 | ||
241 | 248 | ||
242 | LUA_API int lua_type (lua_State *L, int idx) { | 249 | LUA_API int lua_type (lua_State *L, int idx) { |
243 | StkId o = index2adr(L, idx); | 250 | StkId o = index2addr(L, idx); |
244 | return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); | 251 | return (isvalid(o) ? ttypenv(o) : LUA_TNONE); |
245 | } | 252 | } |
246 | 253 | ||
247 | 254 | ||
248 | LUA_API const char *lua_typename (lua_State *L, int t) { | 255 | LUA_API const char *lua_typename (lua_State *L, int t) { |
249 | UNUSED(L); | 256 | UNUSED(L); |
250 | return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; | 257 | return ttypename(t); |
251 | } | 258 | } |
252 | 259 | ||
253 | 260 | ||
254 | LUA_API int lua_iscfunction (lua_State *L, int idx) { | 261 | LUA_API int lua_iscfunction (lua_State *L, int idx) { |
255 | StkId o = index2adr(L, idx); | 262 | StkId o = index2addr(L, idx); |
256 | return iscfunction(o); | 263 | return (ttislcf(o) || (ttisCclosure(o))); |
257 | } | 264 | } |
258 | 265 | ||
259 | 266 | ||
260 | LUA_API int lua_isnumber (lua_State *L, int idx) { | 267 | LUA_API int lua_isnumber (lua_State *L, int idx) { |
261 | TValue n; | 268 | TValue n; |
262 | const TValue *o = index2adr(L, idx); | 269 | const TValue *o = index2addr(L, idx); |
263 | return tonumber(o, &n); | 270 | return tonumber(o, &n); |
264 | } | 271 | } |
265 | 272 | ||
@@ -271,77 +278,116 @@ LUA_API int lua_isstring (lua_State *L, int idx) { | |||
271 | 278 | ||
272 | 279 | ||
273 | LUA_API int lua_isuserdata (lua_State *L, int idx) { | 280 | LUA_API int lua_isuserdata (lua_State *L, int idx) { |
274 | const TValue *o = index2adr(L, idx); | 281 | const TValue *o = index2addr(L, idx); |
275 | return (ttisuserdata(o) || ttislightuserdata(o)); | 282 | return (ttisuserdata(o) || ttislightuserdata(o)); |
276 | } | 283 | } |
277 | 284 | ||
278 | 285 | ||
279 | LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { | 286 | LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { |
280 | StkId o1 = index2adr(L, index1); | 287 | StkId o1 = index2addr(L, index1); |
281 | StkId o2 = index2adr(L, index2); | 288 | StkId o2 = index2addr(L, index2); |
282 | return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 | 289 | return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; |
283 | : luaO_rawequalObj(o1, o2); | ||
284 | } | 290 | } |
285 | 291 | ||
286 | 292 | ||
287 | LUA_API int lua_equal (lua_State *L, int index1, int index2) { | 293 | LUA_API void lua_arith (lua_State *L, int op) { |
288 | StkId o1, o2; | 294 | StkId o1; /* 1st operand */ |
289 | int i; | 295 | StkId o2; /* 2nd operand */ |
290 | lua_lock(L); /* may call tag method */ | 296 | lua_lock(L); |
291 | o1 = index2adr(L, index1); | 297 | if (op != LUA_OPUNM) /* all other operations expect two operands */ |
292 | o2 = index2adr(L, index2); | 298 | api_checknelems(L, 2); |
293 | i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); | 299 | else { /* for unary minus, add fake 2nd operand */ |
300 | api_checknelems(L, 1); | ||
301 | setobjs2s(L, L->top, L->top - 1); | ||
302 | L->top++; | ||
303 | } | ||
304 | o1 = L->top - 2; | ||
305 | o2 = L->top - 1; | ||
306 | if (ttisnumber(o1) && ttisnumber(o2)) { | ||
307 | setnvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2))); | ||
308 | } | ||
309 | else | ||
310 | luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD)); | ||
311 | L->top--; | ||
294 | lua_unlock(L); | 312 | lua_unlock(L); |
295 | return i; | ||
296 | } | 313 | } |
297 | 314 | ||
298 | 315 | ||
299 | LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { | 316 | LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { |
300 | StkId o1, o2; | 317 | StkId o1, o2; |
301 | int i; | 318 | int i = 0; |
302 | lua_lock(L); /* may call tag method */ | 319 | lua_lock(L); /* may call tag method */ |
303 | o1 = index2adr(L, index1); | 320 | o1 = index2addr(L, index1); |
304 | o2 = index2adr(L, index2); | 321 | o2 = index2addr(L, index2); |
305 | i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 | 322 | if (isvalid(o1) && isvalid(o2)) { |
306 | : luaV_lessthan(L, o1, o2); | 323 | switch (op) { |
324 | case LUA_OPEQ: i = equalobj(L, o1, o2); break; | ||
325 | case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; | ||
326 | case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; | ||
327 | default: api_check(L, 0, "invalid option"); | ||
328 | } | ||
329 | } | ||
307 | lua_unlock(L); | 330 | lua_unlock(L); |
308 | return i; | 331 | return i; |
309 | } | 332 | } |
310 | 333 | ||
311 | 334 | ||
312 | 335 | LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) { | |
313 | LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { | ||
314 | TValue n; | 336 | TValue n; |
315 | const TValue *o = index2adr(L, idx); | 337 | const TValue *o = index2addr(L, idx); |
316 | if (tonumber(o, &n)) | 338 | if (tonumber(o, &n)) { |
339 | if (isnum) *isnum = 1; | ||
317 | return nvalue(o); | 340 | return nvalue(o); |
318 | else | 341 | } |
342 | else { | ||
343 | if (isnum) *isnum = 0; | ||
319 | return 0; | 344 | return 0; |
345 | } | ||
320 | } | 346 | } |
321 | 347 | ||
322 | 348 | ||
323 | LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { | 349 | LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) { |
324 | TValue n; | 350 | TValue n; |
325 | const TValue *o = index2adr(L, idx); | 351 | const TValue *o = index2addr(L, idx); |
326 | if (tonumber(o, &n)) { | 352 | if (tonumber(o, &n)) { |
327 | lua_Integer res; | 353 | lua_Integer res; |
328 | lua_Number num = nvalue(o); | 354 | lua_Number num = nvalue(o); |
329 | lua_number2integer(res, num); | 355 | lua_number2integer(res, num); |
356 | if (isnum) *isnum = 1; | ||
330 | return res; | 357 | return res; |
331 | } | 358 | } |
332 | else | 359 | else { |
360 | if (isnum) *isnum = 0; | ||
361 | return 0; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | |||
366 | LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *isnum) { | ||
367 | TValue n; | ||
368 | const TValue *o = index2addr(L, idx); | ||
369 | if (tonumber(o, &n)) { | ||
370 | lua_Unsigned res; | ||
371 | lua_Number num = nvalue(o); | ||
372 | lua_number2unsigned(res, num); | ||
373 | if (isnum) *isnum = 1; | ||
374 | return res; | ||
375 | } | ||
376 | else { | ||
377 | if (isnum) *isnum = 0; | ||
333 | return 0; | 378 | return 0; |
379 | } | ||
334 | } | 380 | } |
335 | 381 | ||
336 | 382 | ||
337 | LUA_API int lua_toboolean (lua_State *L, int idx) { | 383 | LUA_API int lua_toboolean (lua_State *L, int idx) { |
338 | const TValue *o = index2adr(L, idx); | 384 | const TValue *o = index2addr(L, idx); |
339 | return !l_isfalse(o); | 385 | return !l_isfalse(o); |
340 | } | 386 | } |
341 | 387 | ||
342 | 388 | ||
343 | LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { | 389 | LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { |
344 | StkId o = index2adr(L, idx); | 390 | StkId o = index2addr(L, idx); |
345 | if (!ttisstring(o)) { | 391 | if (!ttisstring(o)) { |
346 | lua_lock(L); /* `luaV_tostring' may create a new string */ | 392 | lua_lock(L); /* `luaV_tostring' may create a new string */ |
347 | if (!luaV_tostring(L, o)) { /* conversion failed? */ | 393 | if (!luaV_tostring(L, o)) { /* conversion failed? */ |
@@ -350,7 +396,7 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { | |||
350 | return NULL; | 396 | return NULL; |
351 | } | 397 | } |
352 | luaC_checkGC(L); | 398 | luaC_checkGC(L); |
353 | o = index2adr(L, idx); /* previous call may reallocate the stack */ | 399 | o = index2addr(L, idx); /* previous call may reallocate the stack */ |
354 | lua_unlock(L); | 400 | lua_unlock(L); |
355 | } | 401 | } |
356 | if (len != NULL) *len = tsvalue(o)->len; | 402 | if (len != NULL) *len = tsvalue(o)->len; |
@@ -358,33 +404,29 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { | |||
358 | } | 404 | } |
359 | 405 | ||
360 | 406 | ||
361 | LUA_API size_t lua_objlen (lua_State *L, int idx) { | 407 | LUA_API size_t lua_rawlen (lua_State *L, int idx) { |
362 | StkId o = index2adr(L, idx); | 408 | StkId o = index2addr(L, idx); |
363 | switch (ttype(o)) { | 409 | switch (ttypenv(o)) { |
364 | case LUA_TSTRING: return tsvalue(o)->len; | 410 | case LUA_TSTRING: return tsvalue(o)->len; |
365 | case LUA_TUSERDATA: return uvalue(o)->len; | 411 | case LUA_TUSERDATA: return uvalue(o)->len; |
366 | case LUA_TTABLE: return luaH_getn(hvalue(o)); | 412 | case LUA_TTABLE: return luaH_getn(hvalue(o)); |
367 | case LUA_TNUMBER: { | ||
368 | size_t l; | ||
369 | lua_lock(L); /* `luaV_tostring' may create a new string */ | ||
370 | l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); | ||
371 | lua_unlock(L); | ||
372 | return l; | ||
373 | } | ||
374 | default: return 0; | 413 | default: return 0; |
375 | } | 414 | } |
376 | } | 415 | } |
377 | 416 | ||
378 | 417 | ||
379 | LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { | 418 | LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { |
380 | StkId o = index2adr(L, idx); | 419 | StkId o = index2addr(L, idx); |
381 | return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; | 420 | if (ttislcf(o)) return fvalue(o); |
421 | else if (ttisCclosure(o)) | ||
422 | return clCvalue(o)->f; | ||
423 | else return NULL; /* not a C function */ | ||
382 | } | 424 | } |
383 | 425 | ||
384 | 426 | ||
385 | LUA_API void *lua_touserdata (lua_State *L, int idx) { | 427 | LUA_API void *lua_touserdata (lua_State *L, int idx) { |
386 | StkId o = index2adr(L, idx); | 428 | StkId o = index2addr(L, idx); |
387 | switch (ttype(o)) { | 429 | switch (ttypenv(o)) { |
388 | case LUA_TUSERDATA: return (rawuvalue(o) + 1); | 430 | case LUA_TUSERDATA: return (rawuvalue(o) + 1); |
389 | case LUA_TLIGHTUSERDATA: return pvalue(o); | 431 | case LUA_TLIGHTUSERDATA: return pvalue(o); |
390 | default: return NULL; | 432 | default: return NULL; |
@@ -393,16 +435,18 @@ LUA_API void *lua_touserdata (lua_State *L, int idx) { | |||
393 | 435 | ||
394 | 436 | ||
395 | LUA_API lua_State *lua_tothread (lua_State *L, int idx) { | 437 | LUA_API lua_State *lua_tothread (lua_State *L, int idx) { |
396 | StkId o = index2adr(L, idx); | 438 | StkId o = index2addr(L, idx); |
397 | return (!ttisthread(o)) ? NULL : thvalue(o); | 439 | return (!ttisthread(o)) ? NULL : thvalue(o); |
398 | } | 440 | } |
399 | 441 | ||
400 | 442 | ||
401 | LUA_API const void *lua_topointer (lua_State *L, int idx) { | 443 | LUA_API const void *lua_topointer (lua_State *L, int idx) { |
402 | StkId o = index2adr(L, idx); | 444 | StkId o = index2addr(L, idx); |
403 | switch (ttype(o)) { | 445 | switch (ttype(o)) { |
404 | case LUA_TTABLE: return hvalue(o); | 446 | case LUA_TTABLE: return hvalue(o); |
405 | case LUA_TFUNCTION: return clvalue(o); | 447 | case LUA_TLCL: return clLvalue(o); |
448 | case LUA_TCCL: return clCvalue(o); | ||
449 | case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); | ||
406 | case LUA_TTHREAD: return thvalue(o); | 450 | case LUA_TTHREAD: return thvalue(o); |
407 | case LUA_TUSERDATA: | 451 | case LUA_TUSERDATA: |
408 | case LUA_TLIGHTUSERDATA: | 452 | case LUA_TLIGHTUSERDATA: |
@@ -429,6 +473,8 @@ LUA_API void lua_pushnil (lua_State *L) { | |||
429 | LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { | 473 | LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { |
430 | lua_lock(L); | 474 | lua_lock(L); |
431 | setnvalue(L->top, n); | 475 | setnvalue(L->top, n); |
476 | luai_checknum(L, L->top, | ||
477 | luaG_runerror(L, "C API - attempt to push a signaling NaN")); | ||
432 | api_incr_top(L); | 478 | api_incr_top(L); |
433 | lua_unlock(L); | 479 | lua_unlock(L); |
434 | } | 480 | } |
@@ -442,20 +488,43 @@ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { | |||
442 | } | 488 | } |
443 | 489 | ||
444 | 490 | ||
445 | LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { | 491 | LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) { |
492 | lua_Number n; | ||
493 | lua_lock(L); | ||
494 | n = lua_unsigned2number(u); | ||
495 | setnvalue(L->top, n); | ||
496 | api_incr_top(L); | ||
497 | lua_unlock(L); | ||
498 | } | ||
499 | |||
500 | |||
501 | LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { | ||
502 | TString *ts; | ||
446 | lua_lock(L); | 503 | lua_lock(L); |
447 | luaC_checkGC(L); | 504 | luaC_checkGC(L); |
448 | setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); | 505 | ts = luaS_newlstr(L, s, len); |
506 | setsvalue2s(L, L->top, ts); | ||
449 | api_incr_top(L); | 507 | api_incr_top(L); |
450 | lua_unlock(L); | 508 | lua_unlock(L); |
509 | return getstr(ts); | ||
451 | } | 510 | } |
452 | 511 | ||
453 | 512 | ||
454 | LUA_API void lua_pushstring (lua_State *L, const char *s) { | 513 | LUA_API const char *lua_pushstring (lua_State *L, const char *s) { |
455 | if (s == NULL) | 514 | if (s == NULL) { |
456 | lua_pushnil(L); | 515 | lua_pushnil(L); |
457 | else | 516 | return NULL; |
458 | lua_pushlstring(L, s, strlen(s)); | 517 | } |
518 | else { | ||
519 | TString *ts; | ||
520 | lua_lock(L); | ||
521 | luaC_checkGC(L); | ||
522 | ts = luaS_new(L, s); | ||
523 | setsvalue2s(L, L->top, ts); | ||
524 | api_incr_top(L); | ||
525 | lua_unlock(L); | ||
526 | return getstr(ts); | ||
527 | } | ||
459 | } | 528 | } |
460 | 529 | ||
461 | 530 | ||
@@ -484,17 +553,22 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { | |||
484 | 553 | ||
485 | 554 | ||
486 | LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { | 555 | LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { |
487 | Closure *cl; | ||
488 | lua_lock(L); | 556 | lua_lock(L); |
489 | luaC_checkGC(L); | 557 | if (n == 0) { |
490 | api_checknelems(L, n); | 558 | setfvalue(L->top, fn); |
491 | cl = luaF_newCclosure(L, n, getcurrenv(L)); | 559 | } |
492 | cl->c.f = fn; | 560 | else { |
493 | L->top -= n; | 561 | Closure *cl; |
494 | while (n--) | 562 | api_checknelems(L, n); |
495 | setobj2n(L, &cl->c.upvalue[n], L->top+n); | 563 | api_check(L, n <= MAXUPVAL, "upvalue index too large"); |
496 | setclvalue(L, L->top, cl); | 564 | luaC_checkGC(L); |
497 | lua_assert(iswhite(obj2gco(cl))); | 565 | cl = luaF_newCclosure(L, n); |
566 | cl->c.f = fn; | ||
567 | L->top -= n; | ||
568 | while (n--) | ||
569 | setobj2n(L, &cl->c.upvalue[n], L->top + n); | ||
570 | setclCvalue(L, L->top, cl); | ||
571 | } | ||
498 | api_incr_top(L); | 572 | api_incr_top(L); |
499 | lua_unlock(L); | 573 | lua_unlock(L); |
500 | } | 574 | } |
@@ -531,11 +605,21 @@ LUA_API int lua_pushthread (lua_State *L) { | |||
531 | */ | 605 | */ |
532 | 606 | ||
533 | 607 | ||
608 | LUA_API void lua_getglobal (lua_State *L, const char *var) { | ||
609 | Table *reg = hvalue(&G(L)->l_registry); | ||
610 | const TValue *gt; /* global table */ | ||
611 | lua_lock(L); | ||
612 | gt = luaH_getint(reg, LUA_RIDX_GLOBALS); | ||
613 | setsvalue2s(L, L->top++, luaS_new(L, var)); | ||
614 | luaV_gettable(L, gt, L->top - 1, L->top - 1); | ||
615 | lua_unlock(L); | ||
616 | } | ||
617 | |||
618 | |||
534 | LUA_API void lua_gettable (lua_State *L, int idx) { | 619 | LUA_API void lua_gettable (lua_State *L, int idx) { |
535 | StkId t; | 620 | StkId t; |
536 | lua_lock(L); | 621 | lua_lock(L); |
537 | t = index2adr(L, idx); | 622 | t = index2addr(L, idx); |
538 | api_checkvalidindex(L, t); | ||
539 | luaV_gettable(L, t, L->top - 1, L->top - 1); | 623 | luaV_gettable(L, t, L->top - 1, L->top - 1); |
540 | lua_unlock(L); | 624 | lua_unlock(L); |
541 | } | 625 | } |
@@ -543,13 +627,11 @@ LUA_API void lua_gettable (lua_State *L, int idx) { | |||
543 | 627 | ||
544 | LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { | 628 | LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { |
545 | StkId t; | 629 | StkId t; |
546 | TValue key; | ||
547 | lua_lock(L); | 630 | lua_lock(L); |
548 | t = index2adr(L, idx); | 631 | t = index2addr(L, idx); |
549 | api_checkvalidindex(L, t); | 632 | setsvalue2s(L, L->top, luaS_new(L, k)); |
550 | setsvalue(L, &key, luaS_new(L, k)); | ||
551 | luaV_gettable(L, t, &key, L->top); | ||
552 | api_incr_top(L); | 633 | api_incr_top(L); |
634 | luaV_gettable(L, t, L->top - 1, L->top - 1); | ||
553 | lua_unlock(L); | 635 | lua_unlock(L); |
554 | } | 636 | } |
555 | 637 | ||
@@ -557,29 +639,46 @@ LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { | |||
557 | LUA_API void lua_rawget (lua_State *L, int idx) { | 639 | LUA_API void lua_rawget (lua_State *L, int idx) { |
558 | StkId t; | 640 | StkId t; |
559 | lua_lock(L); | 641 | lua_lock(L); |
560 | t = index2adr(L, idx); | 642 | t = index2addr(L, idx); |
561 | api_check(L, ttistable(t)); | 643 | api_check(L, ttistable(t), "table expected"); |
562 | setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); | 644 | setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); |
563 | lua_unlock(L); | 645 | lua_unlock(L); |
564 | } | 646 | } |
565 | 647 | ||
566 | 648 | ||
567 | LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { | 649 | LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { |
568 | StkId o; | 650 | StkId t; |
569 | lua_lock(L); | 651 | lua_lock(L); |
570 | o = index2adr(L, idx); | 652 | t = index2addr(L, idx); |
571 | api_check(L, ttistable(o)); | 653 | api_check(L, ttistable(t), "table expected"); |
572 | setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); | 654 | setobj2s(L, L->top, luaH_getint(hvalue(t), n)); |
655 | api_incr_top(L); | ||
656 | lua_unlock(L); | ||
657 | } | ||
658 | |||
659 | |||
660 | LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) { | ||
661 | StkId t; | ||
662 | TValue k; | ||
663 | lua_lock(L); | ||
664 | t = index2addr(L, idx); | ||
665 | api_check(L, ttistable(t), "table expected"); | ||
666 | setpvalue(&k, cast(void *, p)); | ||
667 | setobj2s(L, L->top, luaH_get(hvalue(t), &k)); | ||
573 | api_incr_top(L); | 668 | api_incr_top(L); |
574 | lua_unlock(L); | 669 | lua_unlock(L); |
575 | } | 670 | } |
576 | 671 | ||
577 | 672 | ||
578 | LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { | 673 | LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { |
674 | Table *t; | ||
579 | lua_lock(L); | 675 | lua_lock(L); |
580 | luaC_checkGC(L); | 676 | luaC_checkGC(L); |
581 | sethvalue(L, L->top, luaH_new(L, narray, nrec)); | 677 | t = luaH_new(L); |
678 | sethvalue(L, L->top, t); | ||
582 | api_incr_top(L); | 679 | api_incr_top(L); |
680 | if (narray > 0 || nrec > 0) | ||
681 | luaH_resize(L, t, narray, nrec); | ||
583 | lua_unlock(L); | 682 | lua_unlock(L); |
584 | } | 683 | } |
585 | 684 | ||
@@ -589,8 +688,8 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { | |||
589 | Table *mt = NULL; | 688 | Table *mt = NULL; |
590 | int res; | 689 | int res; |
591 | lua_lock(L); | 690 | lua_lock(L); |
592 | obj = index2adr(L, objindex); | 691 | obj = index2addr(L, objindex); |
593 | switch (ttype(obj)) { | 692 | switch (ttypenv(obj)) { |
594 | case LUA_TTABLE: | 693 | case LUA_TTABLE: |
595 | mt = hvalue(obj)->metatable; | 694 | mt = hvalue(obj)->metatable; |
596 | break; | 695 | break; |
@@ -598,7 +697,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { | |||
598 | mt = uvalue(obj)->metatable; | 697 | mt = uvalue(obj)->metatable; |
599 | break; | 698 | break; |
600 | default: | 699 | default: |
601 | mt = G(L)->mt[ttype(obj)]; | 700 | mt = G(L)->mt[ttypenv(obj)]; |
602 | break; | 701 | break; |
603 | } | 702 | } |
604 | if (mt == NULL) | 703 | if (mt == NULL) |
@@ -613,25 +712,15 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { | |||
613 | } | 712 | } |
614 | 713 | ||
615 | 714 | ||
616 | LUA_API void lua_getfenv (lua_State *L, int idx) { | 715 | LUA_API void lua_getuservalue (lua_State *L, int idx) { |
617 | StkId o; | 716 | StkId o; |
618 | lua_lock(L); | 717 | lua_lock(L); |
619 | o = index2adr(L, idx); | 718 | o = index2addr(L, idx); |
620 | api_checkvalidindex(L, o); | 719 | api_check(L, ttisuserdata(o), "userdata expected"); |
621 | switch (ttype(o)) { | 720 | if (uvalue(o)->env) { |
622 | case LUA_TFUNCTION: | 721 | sethvalue(L, L->top, uvalue(o)->env); |
623 | sethvalue(L, L->top, clvalue(o)->c.env); | 722 | } else |
624 | break; | 723 | setnilvalue(L->top); |
625 | case LUA_TUSERDATA: | ||
626 | sethvalue(L, L->top, uvalue(o)->env); | ||
627 | break; | ||
628 | case LUA_TTHREAD: | ||
629 | setobj2s(L, L->top, gt(thvalue(o))); | ||
630 | break; | ||
631 | default: | ||
632 | setnilvalue(L->top); | ||
633 | break; | ||
634 | } | ||
635 | api_incr_top(L); | 724 | api_incr_top(L); |
636 | lua_unlock(L); | 725 | lua_unlock(L); |
637 | } | 726 | } |
@@ -642,12 +731,24 @@ LUA_API void lua_getfenv (lua_State *L, int idx) { | |||
642 | */ | 731 | */ |
643 | 732 | ||
644 | 733 | ||
734 | LUA_API void lua_setglobal (lua_State *L, const char *var) { | ||
735 | Table *reg = hvalue(&G(L)->l_registry); | ||
736 | const TValue *gt; /* global table */ | ||
737 | lua_lock(L); | ||
738 | api_checknelems(L, 1); | ||
739 | gt = luaH_getint(reg, LUA_RIDX_GLOBALS); | ||
740 | setsvalue2s(L, L->top++, luaS_new(L, var)); | ||
741 | luaV_settable(L, gt, L->top - 1, L->top - 2); | ||
742 | L->top -= 2; /* pop value and key */ | ||
743 | lua_unlock(L); | ||
744 | } | ||
745 | |||
746 | |||
645 | LUA_API void lua_settable (lua_State *L, int idx) { | 747 | LUA_API void lua_settable (lua_State *L, int idx) { |
646 | StkId t; | 748 | StkId t; |
647 | lua_lock(L); | 749 | lua_lock(L); |
648 | api_checknelems(L, 2); | 750 | api_checknelems(L, 2); |
649 | t = index2adr(L, idx); | 751 | t = index2addr(L, idx); |
650 | api_checkvalidindex(L, t); | ||
651 | luaV_settable(L, t, L->top - 2, L->top - 1); | 752 | luaV_settable(L, t, L->top - 2, L->top - 1); |
652 | L->top -= 2; /* pop index and value */ | 753 | L->top -= 2; /* pop index and value */ |
653 | lua_unlock(L); | 754 | lua_unlock(L); |
@@ -656,14 +757,12 @@ LUA_API void lua_settable (lua_State *L, int idx) { | |||
656 | 757 | ||
657 | LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { | 758 | LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { |
658 | StkId t; | 759 | StkId t; |
659 | TValue key; | ||
660 | lua_lock(L); | 760 | lua_lock(L); |
661 | api_checknelems(L, 1); | 761 | api_checknelems(L, 1); |
662 | t = index2adr(L, idx); | 762 | t = index2addr(L, idx); |
663 | api_checkvalidindex(L, t); | 763 | setsvalue2s(L, L->top++, luaS_new(L, k)); |
664 | setsvalue(L, &key, luaS_new(L, k)); | 764 | luaV_settable(L, t, L->top - 1, L->top - 2); |
665 | luaV_settable(L, t, &key, L->top - 1); | 765 | L->top -= 2; /* pop value and key */ |
666 | L->top--; /* pop value */ | ||
667 | lua_unlock(L); | 766 | lua_unlock(L); |
668 | } | 767 | } |
669 | 768 | ||
@@ -672,23 +771,39 @@ LUA_API void lua_rawset (lua_State *L, int idx) { | |||
672 | StkId t; | 771 | StkId t; |
673 | lua_lock(L); | 772 | lua_lock(L); |
674 | api_checknelems(L, 2); | 773 | api_checknelems(L, 2); |
675 | t = index2adr(L, idx); | 774 | t = index2addr(L, idx); |
676 | api_check(L, ttistable(t)); | 775 | api_check(L, ttistable(t), "table expected"); |
677 | setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); | 776 | setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); |
678 | luaC_barriert(L, hvalue(t), L->top-1); | 777 | invalidateTMcache(hvalue(t)); |
778 | luaC_barrierback(L, gcvalue(t), L->top-1); | ||
679 | L->top -= 2; | 779 | L->top -= 2; |
680 | lua_unlock(L); | 780 | lua_unlock(L); |
681 | } | 781 | } |
682 | 782 | ||
683 | 783 | ||
684 | LUA_API void lua_rawseti (lua_State *L, int idx, int n) { | 784 | LUA_API void lua_rawseti (lua_State *L, int idx, int n) { |
685 | StkId o; | 785 | StkId t; |
786 | lua_lock(L); | ||
787 | api_checknelems(L, 1); | ||
788 | t = index2addr(L, idx); | ||
789 | api_check(L, ttistable(t), "table expected"); | ||
790 | luaH_setint(L, hvalue(t), n, L->top - 1); | ||
791 | luaC_barrierback(L, gcvalue(t), L->top-1); | ||
792 | L->top--; | ||
793 | lua_unlock(L); | ||
794 | } | ||
795 | |||
796 | |||
797 | LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { | ||
798 | StkId t; | ||
799 | TValue k; | ||
686 | lua_lock(L); | 800 | lua_lock(L); |
687 | api_checknelems(L, 1); | 801 | api_checknelems(L, 1); |
688 | o = index2adr(L, idx); | 802 | t = index2addr(L, idx); |
689 | api_check(L, ttistable(o)); | 803 | api_check(L, ttistable(t), "table expected"); |
690 | setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); | 804 | setpvalue(&k, cast(void *, p)); |
691 | luaC_barriert(L, hvalue(o), L->top-1); | 805 | setobj2t(L, luaH_set(L, hvalue(t), &k), L->top - 1); |
806 | luaC_barrierback(L, gcvalue(t), L->top - 1); | ||
692 | L->top--; | 807 | L->top--; |
693 | lua_unlock(L); | 808 | lua_unlock(L); |
694 | } | 809 | } |
@@ -699,29 +814,32 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |||
699 | Table *mt; | 814 | Table *mt; |
700 | lua_lock(L); | 815 | lua_lock(L); |
701 | api_checknelems(L, 1); | 816 | api_checknelems(L, 1); |
702 | obj = index2adr(L, objindex); | 817 | obj = index2addr(L, objindex); |
703 | api_checkvalidindex(L, obj); | ||
704 | if (ttisnil(L->top - 1)) | 818 | if (ttisnil(L->top - 1)) |
705 | mt = NULL; | 819 | mt = NULL; |
706 | else { | 820 | else { |
707 | api_check(L, ttistable(L->top - 1)); | 821 | api_check(L, ttistable(L->top - 1), "table expected"); |
708 | mt = hvalue(L->top - 1); | 822 | mt = hvalue(L->top - 1); |
709 | } | 823 | } |
710 | switch (ttype(obj)) { | 824 | switch (ttypenv(obj)) { |
711 | case LUA_TTABLE: { | 825 | case LUA_TTABLE: { |
712 | hvalue(obj)->metatable = mt; | 826 | hvalue(obj)->metatable = mt; |
713 | if (mt) | 827 | if (mt) { |
714 | luaC_objbarriert(L, hvalue(obj), mt); | 828 | luaC_objbarrierback(L, gcvalue(obj), mt); |
829 | luaC_checkfinalizer(L, gcvalue(obj), mt); | ||
830 | } | ||
715 | break; | 831 | break; |
716 | } | 832 | } |
717 | case LUA_TUSERDATA: { | 833 | case LUA_TUSERDATA: { |
718 | uvalue(obj)->metatable = mt; | 834 | uvalue(obj)->metatable = mt; |
719 | if (mt) | 835 | if (mt) { |
720 | luaC_objbarrier(L, rawuvalue(obj), mt); | 836 | luaC_objbarrier(L, rawuvalue(obj), mt); |
837 | luaC_checkfinalizer(L, gcvalue(obj), mt); | ||
838 | } | ||
721 | break; | 839 | break; |
722 | } | 840 | } |
723 | default: { | 841 | default: { |
724 | G(L)->mt[ttype(obj)] = mt; | 842 | G(L)->mt[ttypenv(obj)] = mt; |
725 | break; | 843 | break; |
726 | } | 844 | } |
727 | } | 845 | } |
@@ -731,32 +849,21 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |||
731 | } | 849 | } |
732 | 850 | ||
733 | 851 | ||
734 | LUA_API int lua_setfenv (lua_State *L, int idx) { | 852 | LUA_API void lua_setuservalue (lua_State *L, int idx) { |
735 | StkId o; | 853 | StkId o; |
736 | int res = 1; | ||
737 | lua_lock(L); | 854 | lua_lock(L); |
738 | api_checknelems(L, 1); | 855 | api_checknelems(L, 1); |
739 | o = index2adr(L, idx); | 856 | o = index2addr(L, idx); |
740 | api_checkvalidindex(L, o); | 857 | api_check(L, ttisuserdata(o), "userdata expected"); |
741 | api_check(L, ttistable(L->top - 1)); | 858 | if (ttisnil(L->top - 1)) |
742 | switch (ttype(o)) { | 859 | uvalue(o)->env = NULL; |
743 | case LUA_TFUNCTION: | 860 | else { |
744 | clvalue(o)->c.env = hvalue(L->top - 1); | 861 | api_check(L, ttistable(L->top - 1), "table expected"); |
745 | break; | 862 | uvalue(o)->env = hvalue(L->top - 1); |
746 | case LUA_TUSERDATA: | 863 | luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); |
747 | uvalue(o)->env = hvalue(L->top - 1); | ||
748 | break; | ||
749 | case LUA_TTHREAD: | ||
750 | sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); | ||
751 | break; | ||
752 | default: | ||
753 | res = 0; | ||
754 | break; | ||
755 | } | 864 | } |
756 | if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); | ||
757 | L->top--; | 865 | L->top--; |
758 | lua_unlock(L); | 866 | lua_unlock(L); |
759 | return res; | ||
760 | } | 867 | } |
761 | 868 | ||
762 | 869 | ||
@@ -765,21 +872,37 @@ LUA_API int lua_setfenv (lua_State *L, int idx) { | |||
765 | */ | 872 | */ |
766 | 873 | ||
767 | 874 | ||
768 | #define adjustresults(L,nres) \ | 875 | #define checkresults(L,na,nr) \ |
769 | { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } | 876 | api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ |
877 | "results from function overflow current stack size") | ||
770 | 878 | ||
771 | 879 | ||
772 | #define checkresults(L,na,nr) \ | 880 | LUA_API int lua_getctx (lua_State *L, int *ctx) { |
773 | api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) | 881 | if (L->ci->callstatus & CIST_YIELDED) { |
774 | 882 | if (ctx) *ctx = L->ci->u.c.ctx; | |
883 | return L->ci->u.c.status; | ||
884 | } | ||
885 | else return LUA_OK; | ||
886 | } | ||
775 | 887 | ||
776 | LUA_API void lua_call (lua_State *L, int nargs, int nresults) { | 888 | |
889 | LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx, | ||
890 | lua_CFunction k) { | ||
777 | StkId func; | 891 | StkId func; |
778 | lua_lock(L); | 892 | lua_lock(L); |
893 | api_check(L, k == NULL || !isLua(L->ci), | ||
894 | "cannot use continuations inside hooks"); | ||
779 | api_checknelems(L, nargs+1); | 895 | api_checknelems(L, nargs+1); |
896 | api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); | ||
780 | checkresults(L, nargs, nresults); | 897 | checkresults(L, nargs, nresults); |
781 | func = L->top - (nargs+1); | 898 | func = L->top - (nargs+1); |
782 | luaD_call(L, func, nresults); | 899 | if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ |
900 | L->ci->u.c.k = k; /* save continuation */ | ||
901 | L->ci->u.c.ctx = ctx; /* save context */ | ||
902 | luaD_call(L, func, nresults, 1); /* do the call */ | ||
903 | } | ||
904 | else /* no continuation or no yieldable */ | ||
905 | luaD_call(L, func, nresults, 0); /* just do the call */ | ||
783 | adjustresults(L, nresults); | 906 | adjustresults(L, nresults); |
784 | lua_unlock(L); | 907 | lua_unlock(L); |
785 | } | 908 | } |
@@ -797,76 +920,75 @@ struct CallS { /* data to `f_call' */ | |||
797 | 920 | ||
798 | static void f_call (lua_State *L, void *ud) { | 921 | static void f_call (lua_State *L, void *ud) { |
799 | struct CallS *c = cast(struct CallS *, ud); | 922 | struct CallS *c = cast(struct CallS *, ud); |
800 | luaD_call(L, c->func, c->nresults); | 923 | luaD_call(L, c->func, c->nresults, 0); |
801 | } | 924 | } |
802 | 925 | ||
803 | 926 | ||
804 | 927 | ||
805 | LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { | 928 | LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, |
929 | int ctx, lua_CFunction k) { | ||
806 | struct CallS c; | 930 | struct CallS c; |
807 | int status; | 931 | int status; |
808 | ptrdiff_t func; | 932 | ptrdiff_t func; |
809 | lua_lock(L); | 933 | lua_lock(L); |
934 | api_check(L, k == NULL || !isLua(L->ci), | ||
935 | "cannot use continuations inside hooks"); | ||
810 | api_checknelems(L, nargs+1); | 936 | api_checknelems(L, nargs+1); |
937 | api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); | ||
811 | checkresults(L, nargs, nresults); | 938 | checkresults(L, nargs, nresults); |
812 | if (errfunc == 0) | 939 | if (errfunc == 0) |
813 | func = 0; | 940 | func = 0; |
814 | else { | 941 | else { |
815 | StkId o = index2adr(L, errfunc); | 942 | StkId o = index2addr(L, errfunc); |
816 | api_checkvalidindex(L, o); | 943 | api_checkstackindex(L, errfunc, o); |
817 | func = savestack(L, o); | 944 | func = savestack(L, o); |
818 | } | 945 | } |
819 | c.func = L->top - (nargs+1); /* function to be called */ | 946 | c.func = L->top - (nargs+1); /* function to be called */ |
820 | c.nresults = nresults; | 947 | if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ |
821 | status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); | 948 | c.nresults = nresults; /* do a 'conventional' protected call */ |
949 | status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); | ||
950 | } | ||
951 | else { /* prepare continuation (call is already protected by 'resume') */ | ||
952 | CallInfo *ci = L->ci; | ||
953 | ci->u.c.k = k; /* save continuation */ | ||
954 | ci->u.c.ctx = ctx; /* save context */ | ||
955 | /* save information for error recovery */ | ||
956 | ci->extra = savestack(L, c.func); | ||
957 | ci->u.c.old_allowhook = L->allowhook; | ||
958 | ci->u.c.old_errfunc = L->errfunc; | ||
959 | L->errfunc = func; | ||
960 | /* mark that function may do error recovery */ | ||
961 | ci->callstatus |= CIST_YPCALL; | ||
962 | luaD_call(L, c.func, nresults, 1); /* do the call */ | ||
963 | ci->callstatus &= ~CIST_YPCALL; | ||
964 | L->errfunc = ci->u.c.old_errfunc; | ||
965 | status = LUA_OK; /* if it is here, there were no errors */ | ||
966 | } | ||
822 | adjustresults(L, nresults); | 967 | adjustresults(L, nresults); |
823 | lua_unlock(L); | 968 | lua_unlock(L); |
824 | return status; | 969 | return status; |
825 | } | 970 | } |
826 | 971 | ||
827 | 972 | ||
828 | /* | ||
829 | ** Execute a protected C call. | ||
830 | */ | ||
831 | struct CCallS { /* data to `f_Ccall' */ | ||
832 | lua_CFunction func; | ||
833 | void *ud; | ||
834 | }; | ||
835 | |||
836 | |||
837 | static void f_Ccall (lua_State *L, void *ud) { | ||
838 | struct CCallS *c = cast(struct CCallS *, ud); | ||
839 | Closure *cl; | ||
840 | cl = luaF_newCclosure(L, 0, getcurrenv(L)); | ||
841 | cl->c.f = c->func; | ||
842 | setclvalue(L, L->top, cl); /* push function */ | ||
843 | api_incr_top(L); | ||
844 | setpvalue(L->top, c->ud); /* push only argument */ | ||
845 | api_incr_top(L); | ||
846 | luaD_call(L, L->top - 2, 0); | ||
847 | } | ||
848 | |||
849 | |||
850 | LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { | ||
851 | struct CCallS c; | ||
852 | int status; | ||
853 | lua_lock(L); | ||
854 | c.func = func; | ||
855 | c.ud = ud; | ||
856 | status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); | ||
857 | lua_unlock(L); | ||
858 | return status; | ||
859 | } | ||
860 | |||
861 | |||
862 | LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, | 973 | LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, |
863 | const char *chunkname) { | 974 | const char *chunkname, const char *mode) { |
864 | ZIO z; | 975 | ZIO z; |
865 | int status; | 976 | int status; |
866 | lua_lock(L); | 977 | lua_lock(L); |
867 | if (!chunkname) chunkname = "?"; | 978 | if (!chunkname) chunkname = "?"; |
868 | luaZ_init(L, &z, reader, data); | 979 | luaZ_init(L, &z, reader, data); |
869 | status = luaD_protectedparser(L, &z, chunkname); | 980 | status = luaD_protectedparser(L, &z, chunkname, mode); |
981 | if (status == LUA_OK) { /* no errors? */ | ||
982 | LClosure *f = clLvalue(L->top - 1); /* get newly created function */ | ||
983 | if (f->nupvalues == 1) { /* does it have one upvalue? */ | ||
984 | /* get global table from registry */ | ||
985 | Table *reg = hvalue(&G(L)->l_registry); | ||
986 | const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); | ||
987 | /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ | ||
988 | setobj(L, f->upvals[0]->v, gt); | ||
989 | luaC_barrier(L, f->upvals[0], gt); | ||
990 | } | ||
991 | } | ||
870 | lua_unlock(L); | 992 | lua_unlock(L); |
871 | return status; | 993 | return status; |
872 | } | 994 | } |
@@ -879,7 +1001,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { | |||
879 | api_checknelems(L, 1); | 1001 | api_checknelems(L, 1); |
880 | o = L->top - 1; | 1002 | o = L->top - 1; |
881 | if (isLfunction(o)) | 1003 | if (isLfunction(o)) |
882 | status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); | 1004 | status = luaU_dump(L, getproto(o), writer, data, 0); |
883 | else | 1005 | else |
884 | status = 1; | 1006 | status = 1; |
885 | lua_unlock(L); | 1007 | lua_unlock(L); |
@@ -887,7 +1009,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { | |||
887 | } | 1009 | } |
888 | 1010 | ||
889 | 1011 | ||
890 | LUA_API int lua_status (lua_State *L) { | 1012 | LUA_API int lua_status (lua_State *L) { |
891 | return L->status; | 1013 | return L->status; |
892 | } | 1014 | } |
893 | 1015 | ||
@@ -903,38 +1025,40 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { | |||
903 | g = G(L); | 1025 | g = G(L); |
904 | switch (what) { | 1026 | switch (what) { |
905 | case LUA_GCSTOP: { | 1027 | case LUA_GCSTOP: { |
906 | g->GCthreshold = MAX_LUMEM; | 1028 | g->gcrunning = 0; |
907 | break; | 1029 | break; |
908 | } | 1030 | } |
909 | case LUA_GCRESTART: { | 1031 | case LUA_GCRESTART: { |
910 | g->GCthreshold = g->totalbytes; | 1032 | luaE_setdebt(g, 0); |
1033 | g->gcrunning = 1; | ||
911 | break; | 1034 | break; |
912 | } | 1035 | } |
913 | case LUA_GCCOLLECT: { | 1036 | case LUA_GCCOLLECT: { |
914 | luaC_fullgc(L); | 1037 | luaC_fullgc(L, 0); |
915 | break; | 1038 | break; |
916 | } | 1039 | } |
917 | case LUA_GCCOUNT: { | 1040 | case LUA_GCCOUNT: { |
918 | /* GC values are expressed in Kbytes: #bytes/2^10 */ | 1041 | /* GC values are expressed in Kbytes: #bytes/2^10 */ |
919 | res = cast_int(g->totalbytes >> 10); | 1042 | res = cast_int(gettotalbytes(g) >> 10); |
920 | break; | 1043 | break; |
921 | } | 1044 | } |
922 | case LUA_GCCOUNTB: { | 1045 | case LUA_GCCOUNTB: { |
923 | res = cast_int(g->totalbytes & 0x3ff); | 1046 | res = cast_int(gettotalbytes(g) & 0x3ff); |
924 | break; | 1047 | break; |
925 | } | 1048 | } |
926 | case LUA_GCSTEP: { | 1049 | case LUA_GCSTEP: { |
927 | lu_mem a = (cast(lu_mem, data) << 10); | 1050 | if (g->gckind == KGC_GEN) { /* generational mode? */ |
928 | if (a <= g->totalbytes) | 1051 | res = (g->GCestimate == 0); /* true if it will do major collection */ |
929 | g->GCthreshold = g->totalbytes - a; | 1052 | luaC_forcestep(L); /* do a single step */ |
930 | else | 1053 | } |
931 | g->GCthreshold = 0; | 1054 | else { |
932 | while (g->GCthreshold <= g->totalbytes) { | 1055 | lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE; |
933 | luaC_step(L); | 1056 | if (g->gcrunning) |
934 | if (g->gcstate == GCSpause) { /* end of cycle? */ | 1057 | debt += g->GCdebt; /* include current debt */ |
935 | res = 1; /* signal it */ | 1058 | luaE_setdebt(g, debt); |
936 | break; | 1059 | luaC_forcestep(L); |
937 | } | 1060 | if (g->gcstate == GCSpause) /* end of cycle? */ |
1061 | res = 1; /* signal it */ | ||
938 | } | 1062 | } |
939 | break; | 1063 | break; |
940 | } | 1064 | } |
@@ -943,11 +1067,28 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { | |||
943 | g->gcpause = data; | 1067 | g->gcpause = data; |
944 | break; | 1068 | break; |
945 | } | 1069 | } |
1070 | case LUA_GCSETMAJORINC: { | ||
1071 | res = g->gcmajorinc; | ||
1072 | g->gcmajorinc = data; | ||
1073 | break; | ||
1074 | } | ||
946 | case LUA_GCSETSTEPMUL: { | 1075 | case LUA_GCSETSTEPMUL: { |
947 | res = g->gcstepmul; | 1076 | res = g->gcstepmul; |
948 | g->gcstepmul = data; | 1077 | g->gcstepmul = data; |
949 | break; | 1078 | break; |
950 | } | 1079 | } |
1080 | case LUA_GCISRUNNING: { | ||
1081 | res = g->gcrunning; | ||
1082 | break; | ||
1083 | } | ||
1084 | case LUA_GCGEN: { /* change collector to generational mode */ | ||
1085 | luaC_changemode(L, KGC_GEN); | ||
1086 | break; | ||
1087 | } | ||
1088 | case LUA_GCINC: { /* change collector to incremental mode */ | ||
1089 | luaC_changemode(L, KGC_NORMAL); | ||
1090 | break; | ||
1091 | } | ||
951 | default: res = -1; /* invalid option */ | 1092 | default: res = -1; /* invalid option */ |
952 | } | 1093 | } |
953 | lua_unlock(L); | 1094 | lua_unlock(L); |
@@ -965,7 +1106,7 @@ LUA_API int lua_error (lua_State *L) { | |||
965 | lua_lock(L); | 1106 | lua_lock(L); |
966 | api_checknelems(L, 1); | 1107 | api_checknelems(L, 1); |
967 | luaG_errormsg(L); | 1108 | luaG_errormsg(L); |
968 | lua_unlock(L); | 1109 | /* code unreachable; will unlock when control actually leaves the kernel */ |
969 | return 0; /* to avoid warnings */ | 1110 | return 0; /* to avoid warnings */ |
970 | } | 1111 | } |
971 | 1112 | ||
@@ -974,8 +1115,8 @@ LUA_API int lua_next (lua_State *L, int idx) { | |||
974 | StkId t; | 1115 | StkId t; |
975 | int more; | 1116 | int more; |
976 | lua_lock(L); | 1117 | lua_lock(L); |
977 | t = index2adr(L, idx); | 1118 | t = index2addr(L, idx); |
978 | api_check(L, ttistable(t)); | 1119 | api_check(L, ttistable(t), "table expected"); |
979 | more = luaH_next(L, hvalue(t), L->top - 1); | 1120 | more = luaH_next(L, hvalue(t), L->top - 1); |
980 | if (more) { | 1121 | if (more) { |
981 | api_incr_top(L); | 1122 | api_incr_top(L); |
@@ -992,8 +1133,7 @@ LUA_API void lua_concat (lua_State *L, int n) { | |||
992 | api_checknelems(L, n); | 1133 | api_checknelems(L, n); |
993 | if (n >= 2) { | 1134 | if (n >= 2) { |
994 | luaC_checkGC(L); | 1135 | luaC_checkGC(L); |
995 | luaV_concat(L, n, cast_int(L->top - L->base) - 1); | 1136 | luaV_concat(L, n); |
996 | L->top -= (n-1); | ||
997 | } | 1137 | } |
998 | else if (n == 0) { /* push empty string */ | 1138 | else if (n == 0) { /* push empty string */ |
999 | setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); | 1139 | setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); |
@@ -1004,6 +1144,16 @@ LUA_API void lua_concat (lua_State *L, int n) { | |||
1004 | } | 1144 | } |
1005 | 1145 | ||
1006 | 1146 | ||
1147 | LUA_API void lua_len (lua_State *L, int idx) { | ||
1148 | StkId t; | ||
1149 | lua_lock(L); | ||
1150 | t = index2addr(L, idx); | ||
1151 | luaV_objlen(L, L->top, t); | ||
1152 | api_incr_top(L); | ||
1153 | lua_unlock(L); | ||
1154 | } | ||
1155 | |||
1156 | |||
1007 | LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { | 1157 | LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { |
1008 | lua_Alloc f; | 1158 | lua_Alloc f; |
1009 | lua_lock(L); | 1159 | lua_lock(L); |
@@ -1026,7 +1176,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { | |||
1026 | Udata *u; | 1176 | Udata *u; |
1027 | lua_lock(L); | 1177 | lua_lock(L); |
1028 | luaC_checkGC(L); | 1178 | luaC_checkGC(L); |
1029 | u = luaS_newudata(L, size, getcurrenv(L)); | 1179 | u = luaS_newudata(L, size, NULL); |
1030 | setuvalue(L, L->top, u); | 1180 | setuvalue(L, L->top, u); |
1031 | api_incr_top(L); | 1181 | api_incr_top(L); |
1032 | lua_unlock(L); | 1182 | lua_unlock(L); |
@@ -1035,30 +1185,36 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { | |||
1035 | 1185 | ||
1036 | 1186 | ||
1037 | 1187 | ||
1038 | 1188 | static const char *aux_upvalue (StkId fi, int n, TValue **val, | |
1039 | static const char *aux_upvalue (StkId fi, int n, TValue **val) { | 1189 | GCObject **owner) { |
1040 | Closure *f; | 1190 | switch (ttype(fi)) { |
1041 | if (!ttisfunction(fi)) return NULL; | 1191 | case LUA_TCCL: { /* C closure */ |
1042 | f = clvalue(fi); | 1192 | CClosure *f = clCvalue(fi); |
1043 | if (f->c.isC) { | 1193 | if (!(1 <= n && n <= f->nupvalues)) return NULL; |
1044 | if (!(1 <= n && n <= f->c.nupvalues)) return NULL; | 1194 | *val = &f->upvalue[n-1]; |
1045 | *val = &f->c.upvalue[n-1]; | 1195 | if (owner) *owner = obj2gco(f); |
1046 | return ""; | 1196 | return ""; |
1047 | } | 1197 | } |
1048 | else { | 1198 | case LUA_TLCL: { /* Lua closure */ |
1049 | Proto *p = f->l.p; | 1199 | LClosure *f = clLvalue(fi); |
1050 | if (!(1 <= n && n <= p->sizeupvalues)) return NULL; | 1200 | TString *name; |
1051 | *val = f->l.upvals[n-1]->v; | 1201 | Proto *p = f->p; |
1052 | return getstr(p->upvalues[n-1]); | 1202 | if (!(1 <= n && n <= p->sizeupvalues)) return NULL; |
1203 | *val = f->upvals[n-1]->v; | ||
1204 | if (owner) *owner = obj2gco(f->upvals[n - 1]); | ||
1205 | name = p->upvalues[n-1].name; | ||
1206 | return (name == NULL) ? "" : getstr(name); | ||
1207 | } | ||
1208 | default: return NULL; /* not a closure */ | ||
1053 | } | 1209 | } |
1054 | } | 1210 | } |
1055 | 1211 | ||
1056 | 1212 | ||
1057 | LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { | 1213 | LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { |
1058 | const char *name; | 1214 | const char *name; |
1059 | TValue *val; | 1215 | TValue *val = NULL; /* to avoid warnings */ |
1060 | lua_lock(L); | 1216 | lua_lock(L); |
1061 | name = aux_upvalue(index2adr(L, funcindex), n, &val); | 1217 | name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL); |
1062 | if (name) { | 1218 | if (name) { |
1063 | setobj2s(L, L->top, val); | 1219 | setobj2s(L, L->top, val); |
1064 | api_incr_top(L); | 1220 | api_incr_top(L); |
@@ -1070,18 +1226,59 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { | |||
1070 | 1226 | ||
1071 | LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { | 1227 | LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { |
1072 | const char *name; | 1228 | const char *name; |
1073 | TValue *val; | 1229 | TValue *val = NULL; /* to avoid warnings */ |
1230 | GCObject *owner = NULL; /* to avoid warnings */ | ||
1074 | StkId fi; | 1231 | StkId fi; |
1075 | lua_lock(L); | 1232 | lua_lock(L); |
1076 | fi = index2adr(L, funcindex); | 1233 | fi = index2addr(L, funcindex); |
1077 | api_checknelems(L, 1); | 1234 | api_checknelems(L, 1); |
1078 | name = aux_upvalue(fi, n, &val); | 1235 | name = aux_upvalue(fi, n, &val, &owner); |
1079 | if (name) { | 1236 | if (name) { |
1080 | L->top--; | 1237 | L->top--; |
1081 | setobj(L, val, L->top); | 1238 | setobj(L, val, L->top); |
1082 | luaC_barrier(L, clvalue(fi), L->top); | 1239 | luaC_barrier(L, owner, L->top); |
1083 | } | 1240 | } |
1084 | lua_unlock(L); | 1241 | lua_unlock(L); |
1085 | return name; | 1242 | return name; |
1086 | } | 1243 | } |
1087 | 1244 | ||
1245 | |||
1246 | static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { | ||
1247 | LClosure *f; | ||
1248 | StkId fi = index2addr(L, fidx); | ||
1249 | api_check(L, ttisLclosure(fi), "Lua function expected"); | ||
1250 | f = clLvalue(fi); | ||
1251 | api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); | ||
1252 | if (pf) *pf = f; | ||
1253 | return &f->upvals[n - 1]; /* get its upvalue pointer */ | ||
1254 | } | ||
1255 | |||
1256 | |||
1257 | LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { | ||
1258 | StkId fi = index2addr(L, fidx); | ||
1259 | switch (ttype(fi)) { | ||
1260 | case LUA_TLCL: { /* lua closure */ | ||
1261 | return *getupvalref(L, fidx, n, NULL); | ||
1262 | } | ||
1263 | case LUA_TCCL: { /* C closure */ | ||
1264 | CClosure *f = clCvalue(fi); | ||
1265 | api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); | ||
1266 | return &f->upvalue[n - 1]; | ||
1267 | } | ||
1268 | default: { | ||
1269 | api_check(L, 0, "closure expected"); | ||
1270 | return NULL; | ||
1271 | } | ||
1272 | } | ||
1273 | } | ||
1274 | |||
1275 | |||
1276 | LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, | ||
1277 | int fidx2, int n2) { | ||
1278 | LClosure *f1; | ||
1279 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); | ||
1280 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); | ||
1281 | *up1 = *up2; | ||
1282 | luaC_objbarrier(L, f1, *up2); | ||
1283 | } | ||
1284 | |||
diff --git a/apps/plugins/lua/lapi.h b/apps/plugins/lua/lapi.h index f968ffc992..c7d34ad848 100644 --- a/apps/plugins/lua/lapi.h +++ b/apps/plugins/lua/lapi.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lapi.h,v 2.7.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Auxiliary functions from Lua API | 3 | ** Auxiliary functions from Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -8,9 +8,17 @@ | |||
8 | #define lapi_h | 8 | #define lapi_h |
9 | 9 | ||
10 | 10 | ||
11 | #include "lobject.h" | 11 | #include "llimits.h" |
12 | #include "lstate.h" | ||
12 | 13 | ||
14 | #define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ | ||
15 | "stack overflow");} | ||
16 | |||
17 | #define adjustresults(L,nres) \ | ||
18 | { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } | ||
19 | |||
20 | #define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ | ||
21 | "not enough elements in the stack") | ||
13 | 22 | ||
14 | LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); | ||
15 | 23 | ||
16 | #endif | 24 | #endif |
diff --git a/apps/plugins/lua/lauxlib.c b/apps/plugins/lua/lauxlib.c index b8020b7475..f451fb7c9e 100644 --- a/apps/plugins/lua/lauxlib.c +++ b/apps/plugins/lua/lauxlib.c | |||
@@ -1,11 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ | 2 | ** $Id: lauxlib.c,v 1.248.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Auxiliary functions for building Lua libraries | 3 | ** Auxiliary functions for building Lua libraries |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
6 | 6 | ||
7 | 7 | ||
8 | #include <ctype.h> | ||
9 | #include <errno.h> | 8 | #include <errno.h> |
10 | #include <stdarg.h> | 9 | #include <stdarg.h> |
11 | #include <stdio.h> | 10 | #include <stdio.h> |
@@ -23,14 +22,127 @@ | |||
23 | #include "lua.h" | 22 | #include "lua.h" |
24 | 23 | ||
25 | #include "lauxlib.h" | 24 | #include "lauxlib.h" |
25 | #include "rocklibc.h" | ||
26 | 26 | ||
27 | 27 | ||
28 | #define FREELIST_REF 0 /* free list of references */ | 28 | /* |
29 | ** {====================================================== | ||
30 | ** Traceback | ||
31 | ** ======================================================= | ||
32 | */ | ||
33 | |||
34 | |||
35 | #define LEVELS1 12 /* size of the first part of the stack */ | ||
36 | #define LEVELS2 10 /* size of the second part of the stack */ | ||
37 | |||
38 | |||
39 | |||
40 | /* | ||
41 | ** search for 'objidx' in table at index -1. | ||
42 | ** return 1 + string at top if find a good name. | ||
43 | */ | ||
44 | static int findfield (lua_State *L, int objidx, int level) { | ||
45 | if (level == 0 || !lua_istable(L, -1)) | ||
46 | return 0; /* not found */ | ||
47 | lua_pushnil(L); /* start 'next' loop */ | ||
48 | while (lua_next(L, -2)) { /* for each pair in table */ | ||
49 | if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ | ||
50 | if (lua_rawequal(L, objidx, -1)) { /* found object? */ | ||
51 | lua_pop(L, 1); /* remove value (but keep name) */ | ||
52 | return 1; | ||
53 | } | ||
54 | else if (findfield(L, objidx, level - 1)) { /* try recursively */ | ||
55 | lua_remove(L, -2); /* remove table (but keep name) */ | ||
56 | lua_pushliteral(L, "."); | ||
57 | lua_insert(L, -2); /* place '.' between the two names */ | ||
58 | lua_concat(L, 3); | ||
59 | return 1; | ||
60 | } | ||
61 | } | ||
62 | lua_pop(L, 1); /* remove value */ | ||
63 | } | ||
64 | return 0; /* not found */ | ||
65 | } | ||
66 | |||
67 | |||
68 | static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { | ||
69 | int top = lua_gettop(L); | ||
70 | lua_getinfo(L, "f", ar); /* push function */ | ||
71 | lua_pushglobaltable(L); | ||
72 | if (findfield(L, top + 1, 2)) { | ||
73 | lua_copy(L, -1, top + 1); /* move name to proper place */ | ||
74 | lua_pop(L, 2); /* remove pushed values */ | ||
75 | return 1; | ||
76 | } | ||
77 | else { | ||
78 | lua_settop(L, top); /* remove function and global table */ | ||
79 | return 0; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | |||
84 | static void pushfuncname (lua_State *L, lua_Debug *ar) { | ||
85 | if (*ar->namewhat != '\0') /* is there a name? */ | ||
86 | lua_pushfstring(L, "function " LUA_QS, ar->name); | ||
87 | else if (*ar->what == 'm') /* main? */ | ||
88 | lua_pushliteral(L, "main chunk"); | ||
89 | else if (*ar->what == 'C') { | ||
90 | if (pushglobalfuncname(L, ar)) { | ||
91 | lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); | ||
92 | lua_remove(L, -2); /* remove name */ | ||
93 | } | ||
94 | else | ||
95 | lua_pushliteral(L, "?"); | ||
96 | } | ||
97 | else | ||
98 | lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); | ||
99 | } | ||
29 | 100 | ||
30 | 101 | ||
31 | /* convert a stack index to positive */ | 102 | static int countlevels (lua_State *L) { |
32 | #define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ | 103 | lua_Debug ar; |
33 | lua_gettop(L) + (i) + 1) | 104 | int li = 1, le = 1; |
105 | /* find an upper bound */ | ||
106 | while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } | ||
107 | /* do a binary search */ | ||
108 | while (li < le) { | ||
109 | int m = (li + le)/2; | ||
110 | if (lua_getstack(L, m, &ar)) li = m + 1; | ||
111 | else le = m; | ||
112 | } | ||
113 | return le - 1; | ||
114 | } | ||
115 | |||
116 | |||
117 | LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, | ||
118 | const char *msg, int level) { | ||
119 | lua_Debug ar; | ||
120 | int top = lua_gettop(L); | ||
121 | int numlevels = countlevels(L1); | ||
122 | int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; | ||
123 | if (msg) lua_pushfstring(L, "%s\n", msg); | ||
124 | lua_pushliteral(L, "stack traceback:"); | ||
125 | while (lua_getstack(L1, level++, &ar)) { | ||
126 | if (level == mark) { /* too many levels? */ | ||
127 | lua_pushliteral(L, "\n\t..."); /* add a '...' */ | ||
128 | level = numlevels - LEVELS2; /* and skip to last ones */ | ||
129 | } | ||
130 | else { | ||
131 | lua_getinfo(L1, "Slnt", &ar); | ||
132 | lua_pushfstring(L, "\n\t%s:", ar.short_src); | ||
133 | if (ar.currentline > 0) | ||
134 | lua_pushfstring(L, "%d:", ar.currentline); | ||
135 | lua_pushliteral(L, " in "); | ||
136 | pushfuncname(L, &ar); | ||
137 | if (ar.istailcall) | ||
138 | lua_pushliteral(L, "\n\t(...tail calls...)"); | ||
139 | lua_concat(L, lua_gettop(L) - top); | ||
140 | } | ||
141 | } | ||
142 | lua_concat(L, lua_gettop(L) - top); | ||
143 | } | ||
144 | |||
145 | /* }====================================================== */ | ||
34 | 146 | ||
35 | 147 | ||
36 | /* | 148 | /* |
@@ -39,7 +151,6 @@ | |||
39 | ** ======================================================= | 151 | ** ======================================================= |
40 | */ | 152 | */ |
41 | 153 | ||
42 | |||
43 | LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { | 154 | LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { |
44 | lua_Debug ar; | 155 | lua_Debug ar; |
45 | if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ | 156 | if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ |
@@ -52,13 +163,13 @@ LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { | |||
52 | ar.name, extramsg); | 163 | ar.name, extramsg); |
53 | } | 164 | } |
54 | if (ar.name == NULL) | 165 | if (ar.name == NULL) |
55 | ar.name = "?"; | 166 | ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; |
56 | return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", | 167 | return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", |
57 | narg, ar.name, extramsg); | 168 | narg, ar.name, extramsg); |
58 | } | 169 | } |
59 | 170 | ||
60 | 171 | ||
61 | LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { | 172 | static int typeerror (lua_State *L, int narg, const char *tname) { |
62 | const char *msg = lua_pushfstring(L, "%s expected, got %s", | 173 | const char *msg = lua_pushfstring(L, "%s expected, got %s", |
63 | tname, luaL_typename(L, narg)); | 174 | tname, luaL_typename(L, narg)); |
64 | return luaL_argerror(L, narg, msg); | 175 | return luaL_argerror(L, narg, msg); |
@@ -66,7 +177,7 @@ LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { | |||
66 | 177 | ||
67 | 178 | ||
68 | static void tag_error (lua_State *L, int narg, int tag) { | 179 | static void tag_error (lua_State *L, int narg, int tag) { |
69 | luaL_typerror(L, narg, lua_typename(L, tag)); | 180 | typeerror(L, narg, lua_typename(L, tag)); |
70 | } | 181 | } |
71 | 182 | ||
72 | 183 | ||
@@ -93,24 +204,74 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { | |||
93 | return lua_error(L); | 204 | return lua_error(L); |
94 | } | 205 | } |
95 | 206 | ||
96 | /* }====================================================== */ | ||
97 | 207 | ||
208 | LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { | ||
209 | int en = errno; /* calls to Lua API may change this value */ | ||
210 | if (stat) { | ||
211 | lua_pushboolean(L, 1); | ||
212 | return 1; | ||
213 | } | ||
214 | else { | ||
215 | lua_pushnil(L); | ||
216 | if (fname) | ||
217 | lua_pushfstring(L, "%s: %s", fname, strerror(en)); | ||
218 | else | ||
219 | lua_pushstring(L, strerror(en)); | ||
220 | lua_pushinteger(L, en); | ||
221 | return 3; | ||
222 | } | ||
223 | } | ||
98 | 224 | ||
99 | LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, | 225 | |
100 | const char *const lst[]) { | 226 | #if !defined(inspectstat) /* { */ |
101 | const char *name = (def) ? luaL_optstring(L, narg, def) : | 227 | |
102 | luaL_checkstring(L, narg); | 228 | #if defined(LUA_USE_POSIX) |
103 | int i; | 229 | |
104 | for (i=0; lst[i]; i++) | 230 | #include <sys/wait.h> |
105 | if (strcmp(lst[i], name) == 0) | 231 | |
106 | return i; | 232 | /* |
107 | return luaL_argerror(L, narg, | 233 | ** use appropriate macros to interpret 'pclose' return status |
108 | lua_pushfstring(L, "invalid option " LUA_QS, name)); | 234 | */ |
235 | #define inspectstat(stat,what) \ | ||
236 | if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ | ||
237 | else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } | ||
238 | |||
239 | #else | ||
240 | |||
241 | #define inspectstat(stat,what) /* no op */ | ||
242 | |||
243 | #endif | ||
244 | |||
245 | #endif /* } */ | ||
246 | |||
247 | |||
248 | LUALIB_API int luaL_execresult (lua_State *L, int stat) { | ||
249 | const char *what = "exit"; /* type of termination */ | ||
250 | if (stat == -1) /* error? */ | ||
251 | return luaL_fileresult(L, 0, NULL); | ||
252 | else { | ||
253 | inspectstat(stat, what); /* interpret result */ | ||
254 | if (*what == 'e' && stat == 0) /* successful termination? */ | ||
255 | lua_pushboolean(L, 1); | ||
256 | else | ||
257 | lua_pushnil(L); | ||
258 | lua_pushstring(L, what); | ||
259 | lua_pushinteger(L, stat); | ||
260 | return 3; /* return true/nil,what,code */ | ||
261 | } | ||
109 | } | 262 | } |
110 | 263 | ||
264 | /* }====================================================== */ | ||
265 | |||
266 | |||
267 | /* | ||
268 | ** {====================================================== | ||
269 | ** Userdata's metatable manipulation | ||
270 | ** ======================================================= | ||
271 | */ | ||
111 | 272 | ||
112 | LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { | 273 | LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { |
113 | lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ | 274 | luaL_getmetatable(L, tname); /* try to get metatable */ |
114 | if (!lua_isnil(L, -1)) /* name already in use? */ | 275 | if (!lua_isnil(L, -1)) /* name already in use? */ |
115 | return 0; /* leave previous value on top, but return 0 */ | 276 | return 0; /* leave previous value on top, but return 0 */ |
116 | lua_pop(L, 1); | 277 | lua_pop(L, 1); |
@@ -121,25 +282,64 @@ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { | |||
121 | } | 282 | } |
122 | 283 | ||
123 | 284 | ||
124 | LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { | 285 | LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) { |
286 | luaL_getmetatable(L, tname); | ||
287 | lua_setmetatable(L, -2); | ||
288 | } | ||
289 | |||
290 | |||
291 | LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { | ||
125 | void *p = lua_touserdata(L, ud); | 292 | void *p = lua_touserdata(L, ud); |
126 | if (p != NULL) { /* value is a userdata? */ | 293 | if (p != NULL) { /* value is a userdata? */ |
127 | if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ | 294 | if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ |
128 | lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ | 295 | luaL_getmetatable(L, tname); /* get correct metatable */ |
129 | if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ | 296 | if (!lua_rawequal(L, -1, -2)) /* not the same? */ |
130 | lua_pop(L, 2); /* remove both metatables */ | 297 | p = NULL; /* value is a userdata with wrong metatable */ |
131 | return p; | 298 | lua_pop(L, 2); /* remove both metatables */ |
132 | } | 299 | return p; |
133 | } | 300 | } |
134 | } | 301 | } |
135 | luaL_typerror(L, ud, tname); /* else error */ | 302 | return NULL; /* value is not a userdata with a metatable */ |
136 | return NULL; /* to avoid warnings */ | ||
137 | } | 303 | } |
138 | 304 | ||
139 | 305 | ||
140 | LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { | 306 | LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { |
141 | if (!lua_checkstack(L, space)) | 307 | void *p = luaL_testudata(L, ud, tname); |
142 | luaL_error(L, "stack overflow (%s)", mes); | 308 | if (p == NULL) typeerror(L, ud, tname); |
309 | return p; | ||
310 | } | ||
311 | |||
312 | /* }====================================================== */ | ||
313 | |||
314 | |||
315 | /* | ||
316 | ** {====================================================== | ||
317 | ** Argument check functions | ||
318 | ** ======================================================= | ||
319 | */ | ||
320 | |||
321 | LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, | ||
322 | const char *const lst[]) { | ||
323 | const char *name = (def) ? luaL_optstring(L, narg, def) : | ||
324 | luaL_checkstring(L, narg); | ||
325 | int i; | ||
326 | for (i=0; lst[i]; i++) | ||
327 | if (strcmp(lst[i], name) == 0) | ||
328 | return i; | ||
329 | return luaL_argerror(L, narg, | ||
330 | lua_pushfstring(L, "invalid option " LUA_QS, name)); | ||
331 | } | ||
332 | |||
333 | |||
334 | LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { | ||
335 | /* keep some extra space to run error routines, if needed */ | ||
336 | const int extra = LUA_MINSTACK; | ||
337 | if (!lua_checkstack(L, space + extra)) { | ||
338 | if (msg) | ||
339 | luaL_error(L, "stack overflow (%s)", msg); | ||
340 | else | ||
341 | luaL_error(L, "stack overflow"); | ||
342 | } | ||
143 | } | 343 | } |
144 | 344 | ||
145 | 345 | ||
@@ -174,8 +374,9 @@ LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, | |||
174 | 374 | ||
175 | 375 | ||
176 | LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { | 376 | LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { |
177 | lua_Number d = lua_tonumber(L, narg); | 377 | int isnum; |
178 | if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ | 378 | lua_Number d = lua_tonumberx(L, narg, &isnum); |
379 | if (!isnum) | ||
179 | tag_error(L, narg, LUA_TNUMBER); | 380 | tag_error(L, narg, LUA_TNUMBER); |
180 | return d; | 381 | return d; |
181 | } | 382 | } |
@@ -187,268 +388,79 @@ LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { | |||
187 | 388 | ||
188 | 389 | ||
189 | LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { | 390 | LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { |
190 | lua_Integer d = lua_tointeger(L, narg); | 391 | int isnum; |
191 | if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ | 392 | lua_Integer d = lua_tointegerx(L, narg, &isnum); |
393 | if (!isnum) | ||
192 | tag_error(L, narg, LUA_TNUMBER); | 394 | tag_error(L, narg, LUA_TNUMBER); |
193 | return d; | 395 | return d; |
194 | } | 396 | } |
195 | 397 | ||
196 | 398 | ||
197 | LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, | 399 | LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) { |
198 | lua_Integer def) { | 400 | int isnum; |
199 | return luaL_opt(L, luaL_checkinteger, narg, def); | 401 | lua_Unsigned d = lua_tounsignedx(L, narg, &isnum); |
200 | } | 402 | if (!isnum) |
201 | 403 | tag_error(L, narg, LUA_TNUMBER); | |
202 | 404 | return d; | |
203 | LUALIB_API int luaL_checkboolean (lua_State *L, int narg) { | ||
204 | int b = lua_toboolean(L, narg); | ||
205 | if( b == 0 && !lua_isboolean(L, narg)) | ||
206 | tag_error(L, narg, LUA_TBOOLEAN); | ||
207 | return b; | ||
208 | } | ||
209 | |||
210 | |||
211 | LUALIB_API int luaL_optboolean (lua_State *L, int narg, int def) { | ||
212 | return luaL_opt(L, luaL_checkboolean, narg, def); | ||
213 | } | ||
214 | |||
215 | |||
216 | LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { | ||
217 | if (!lua_getmetatable(L, obj)) /* no metatable? */ | ||
218 | return 0; | ||
219 | lua_pushstring(L, event); | ||
220 | lua_rawget(L, -2); | ||
221 | if (lua_isnil(L, -1)) { | ||
222 | lua_pop(L, 2); /* remove metatable and metafield */ | ||
223 | return 0; | ||
224 | } | ||
225 | else { | ||
226 | lua_remove(L, -2); /* remove only metatable */ | ||
227 | return 1; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | |||
232 | LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { | ||
233 | obj = abs_index(L, obj); | ||
234 | if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ | ||
235 | return 0; | ||
236 | lua_pushvalue(L, obj); | ||
237 | lua_call(L, 1, 1); | ||
238 | return 1; | ||
239 | } | ||
240 | |||
241 | |||
242 | LUALIB_API void (luaL_register) (lua_State *L, const char *libname, | ||
243 | const luaL_Reg *l) { | ||
244 | luaI_openlib(L, libname, l, 0); | ||
245 | } | ||
246 | |||
247 | |||
248 | static int libsize (const luaL_Reg *l) { | ||
249 | int size = 0; | ||
250 | for (; l->name; l++) size++; | ||
251 | return size; | ||
252 | } | ||
253 | |||
254 | |||
255 | LUALIB_API void luaI_openlib (lua_State *L, const char *libname, | ||
256 | const luaL_Reg *l, int nup) { | ||
257 | if (libname) { | ||
258 | int size = libsize(l); | ||
259 | /* check whether lib already exists */ | ||
260 | luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); | ||
261 | lua_getfield(L, -1, libname); /* get _LOADED[libname] */ | ||
262 | if (!lua_istable(L, -1)) { /* not found? */ | ||
263 | lua_pop(L, 1); /* remove previous result */ | ||
264 | /* try global variable (and create one if it does not exist) */ | ||
265 | if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) | ||
266 | luaL_error(L, "name conflict for module " LUA_QS, libname); | ||
267 | lua_pushvalue(L, -1); | ||
268 | lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ | ||
269 | } | ||
270 | lua_remove(L, -2); /* remove _LOADED table */ | ||
271 | lua_insert(L, -(nup+1)); /* move library table to below upvalues */ | ||
272 | } | ||
273 | for (; l->name; l++) { | ||
274 | int i; | ||
275 | for (i=0; i<nup; i++) /* copy upvalues to the top */ | ||
276 | lua_pushvalue(L, -nup); | ||
277 | lua_pushcclosure(L, l->func, nup); | ||
278 | lua_setfield(L, -(nup+2), l->name); | ||
279 | } | ||
280 | lua_pop(L, nup); /* remove upvalues */ | ||
281 | } | ||
282 | |||
283 | |||
284 | |||
285 | /* | ||
286 | ** {====================================================== | ||
287 | ** getn-setn: size for arrays | ||
288 | ** ======================================================= | ||
289 | */ | ||
290 | |||
291 | #if defined(LUA_COMPAT_GETN) | ||
292 | |||
293 | static int checkint (lua_State *L, int topop) { | ||
294 | int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; | ||
295 | lua_pop(L, topop); | ||
296 | return n; | ||
297 | } | ||
298 | |||
299 | |||
300 | static void getsizes (lua_State *L) { | ||
301 | lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); | ||
302 | if (lua_isnil(L, -1)) { /* no `size' table? */ | ||
303 | lua_pop(L, 1); /* remove nil */ | ||
304 | lua_newtable(L); /* create it */ | ||
305 | lua_pushvalue(L, -1); /* `size' will be its own metatable */ | ||
306 | lua_setmetatable(L, -2); | ||
307 | lua_pushliteral(L, "kv"); | ||
308 | lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ | ||
309 | lua_pushvalue(L, -1); | ||
310 | lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ | ||
311 | } | ||
312 | } | 405 | } |
313 | 406 | ||
314 | 407 | ||
315 | LUALIB_API void luaL_setn (lua_State *L, int t, int n) { | 408 | LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, |
316 | t = abs_index(L, t); | 409 | lua_Integer def) { |
317 | lua_pushliteral(L, "n"); | 410 | return luaL_opt(L, luaL_checkinteger, narg, def); |
318 | lua_rawget(L, t); | ||
319 | if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ | ||
320 | lua_pushliteral(L, "n"); /* use it */ | ||
321 | lua_pushinteger(L, n); | ||
322 | lua_rawset(L, t); | ||
323 | } | ||
324 | else { /* use `sizes' */ | ||
325 | getsizes(L); | ||
326 | lua_pushvalue(L, t); | ||
327 | lua_pushinteger(L, n); | ||
328 | lua_rawset(L, -3); /* sizes[t] = n */ | ||
329 | lua_pop(L, 1); /* remove `sizes' */ | ||
330 | } | ||
331 | } | 411 | } |
332 | 412 | ||
333 | 413 | ||
334 | LUALIB_API int luaL_getn (lua_State *L, int t) { | 414 | LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg, |
335 | int n; | 415 | lua_Unsigned def) { |
336 | t = abs_index(L, t); | 416 | return luaL_opt(L, luaL_checkunsigned, narg, def); |
337 | lua_pushliteral(L, "n"); /* try t.n */ | ||
338 | lua_rawget(L, t); | ||
339 | if ((n = checkint(L, 1)) >= 0) return n; | ||
340 | getsizes(L); /* else try sizes[t] */ | ||
341 | lua_pushvalue(L, t); | ||
342 | lua_rawget(L, -2); | ||
343 | if ((n = checkint(L, 2)) >= 0) return n; | ||
344 | return (int)lua_objlen(L, t); | ||
345 | } | 417 | } |
346 | 418 | ||
347 | #endif | ||
348 | |||
349 | /* }====================================================== */ | 419 | /* }====================================================== */ |
350 | 420 | ||
351 | 421 | ||
352 | |||
353 | LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, | ||
354 | const char *r) { | ||
355 | const char *wild; | ||
356 | size_t l = strlen(p); | ||
357 | luaL_Buffer b; | ||
358 | luaL_buffinit(L, &b); | ||
359 | while ((wild = strstr(s, p)) != NULL) { | ||
360 | luaL_addlstring(&b, s, wild - s); /* push prefix */ | ||
361 | luaL_addstring(&b, r); /* push replacement in place of pattern */ | ||
362 | s = wild + l; /* continue after `p' */ | ||
363 | } | ||
364 | luaL_addstring(&b, s); /* push last suffix */ | ||
365 | luaL_pushresult(&b); | ||
366 | return lua_tostring(L, -1); | ||
367 | } | ||
368 | |||
369 | |||
370 | LUALIB_API const char *luaL_findtable (lua_State *L, int idx, | ||
371 | const char *fname, int szhint) { | ||
372 | const char *e; | ||
373 | lua_pushvalue(L, idx); | ||
374 | do { | ||
375 | e = strchr(fname, '.'); | ||
376 | if (e == NULL) e = fname + strlen(fname); | ||
377 | lua_pushlstring(L, fname, e - fname); | ||
378 | lua_rawget(L, -2); | ||
379 | if (lua_isnil(L, -1)) { /* no such field? */ | ||
380 | lua_pop(L, 1); /* remove this nil */ | ||
381 | lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ | ||
382 | lua_pushlstring(L, fname, e - fname); | ||
383 | lua_pushvalue(L, -2); | ||
384 | lua_settable(L, -4); /* set new table into field */ | ||
385 | } | ||
386 | else if (!lua_istable(L, -1)) { /* field has a non-table value? */ | ||
387 | lua_pop(L, 2); /* remove table and value */ | ||
388 | return fname; /* return problematic part of the name */ | ||
389 | } | ||
390 | lua_remove(L, -2); /* remove previous table */ | ||
391 | fname = e + 1; | ||
392 | } while (*e == '.'); | ||
393 | return NULL; | ||
394 | } | ||
395 | |||
396 | |||
397 | |||
398 | /* | 422 | /* |
399 | ** {====================================================== | 423 | ** {====================================================== |
400 | ** Generic Buffer manipulation | 424 | ** Generic Buffer manipulation |
401 | ** ======================================================= | 425 | ** ======================================================= |
402 | */ | 426 | */ |
403 | 427 | ||
404 | 428 | /* | |
405 | #define bufflen(B) ((B)->p - (B)->buffer) | 429 | ** check whether buffer is using a userdata on the stack as a temporary |
406 | #define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) | 430 | ** buffer |
407 | 431 | */ | |
408 | #define LIMIT (LUA_MINSTACK/2) | 432 | #define buffonstack(B) ((B)->b != (B)->initb) |
409 | |||
410 | |||
411 | static int emptybuffer (luaL_Buffer *B) { | ||
412 | size_t l = bufflen(B); | ||
413 | if (l == 0) return 0; /* put nothing on stack */ | ||
414 | else { | ||
415 | lua_pushlstring(B->L, B->buffer, l); | ||
416 | B->p = B->buffer; | ||
417 | B->lvl++; | ||
418 | return 1; | ||
419 | } | ||
420 | } | ||
421 | 433 | ||
422 | 434 | ||
423 | static void adjuststack (luaL_Buffer *B) { | 435 | /* |
424 | if (B->lvl > 1) { | 436 | ** returns a pointer to a free area with at least 'sz' bytes |
425 | lua_State *L = B->L; | 437 | */ |
426 | int toget = 1; /* number of levels to concat */ | 438 | LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { |
427 | size_t toplen = lua_strlen(L, -1); | 439 | lua_State *L = B->L; |
428 | do { | 440 | if (B->size - B->n < sz) { /* not enough space? */ |
429 | size_t l = lua_strlen(L, -(toget+1)); | 441 | char *newbuff; |
430 | if (B->lvl - toget + 1 >= LIMIT || toplen > l) { | 442 | size_t newsize = B->size * 2; /* double buffer size */ |
431 | toplen += l; | 443 | if (newsize - B->n < sz) /* not big enough? */ |
432 | toget++; | 444 | newsize = B->n + sz; |
433 | } | 445 | if (newsize < B->n || newsize - B->n < sz) |
434 | else break; | 446 | luaL_error(L, "buffer too large"); |
435 | } while (toget < B->lvl); | 447 | /* create larger buffer */ |
436 | lua_concat(L, toget); | 448 | newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char)); |
437 | B->lvl = B->lvl - toget + 1; | 449 | /* move content to new buffer */ |
450 | memcpy(newbuff, B->b, B->n * sizeof(char)); | ||
451 | if (buffonstack(B)) | ||
452 | lua_remove(L, -2); /* remove old buffer */ | ||
453 | B->b = newbuff; | ||
454 | B->size = newsize; | ||
438 | } | 455 | } |
439 | } | 456 | return &B->b[B->n]; |
440 | |||
441 | |||
442 | LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { | ||
443 | if (emptybuffer(B)) | ||
444 | adjuststack(B); | ||
445 | return B->buffer; | ||
446 | } | 457 | } |
447 | 458 | ||
448 | 459 | ||
449 | LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { | 460 | LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { |
450 | while (l--) | 461 | char *b = luaL_prepbuffsize(B, l); |
451 | luaL_addchar(B, *s++); | 462 | memcpy(b, s, l * sizeof(char)); |
463 | luaL_addsize(B, l); | ||
452 | } | 464 | } |
453 | 465 | ||
454 | 466 | ||
@@ -458,57 +470,72 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { | |||
458 | 470 | ||
459 | 471 | ||
460 | LUALIB_API void luaL_pushresult (luaL_Buffer *B) { | 472 | LUALIB_API void luaL_pushresult (luaL_Buffer *B) { |
461 | emptybuffer(B); | 473 | lua_State *L = B->L; |
462 | lua_concat(B->L, B->lvl); | 474 | lua_pushlstring(L, B->b, B->n); |
463 | B->lvl = 1; | 475 | if (buffonstack(B)) |
476 | lua_remove(L, -2); /* remove old buffer */ | ||
477 | } | ||
478 | |||
479 | |||
480 | LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { | ||
481 | luaL_addsize(B, sz); | ||
482 | luaL_pushresult(B); | ||
464 | } | 483 | } |
465 | 484 | ||
466 | 485 | ||
467 | LUALIB_API void luaL_addvalue (luaL_Buffer *B) { | 486 | LUALIB_API void luaL_addvalue (luaL_Buffer *B) { |
468 | lua_State *L = B->L; | 487 | lua_State *L = B->L; |
469 | size_t vl; | 488 | size_t l; |
470 | const char *s = lua_tolstring(L, -1, &vl); | 489 | const char *s = lua_tolstring(L, -1, &l); |
471 | if (vl <= bufffree(B)) { /* fit into buffer? */ | 490 | if (buffonstack(B)) |
472 | memcpy(B->p, s, vl); /* put it there */ | 491 | lua_insert(L, -2); /* put value below buffer */ |
473 | B->p += vl; | 492 | luaL_addlstring(B, s, l); |
474 | lua_pop(L, 1); /* remove from stack */ | 493 | lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ |
475 | } | ||
476 | else { | ||
477 | if (emptybuffer(B)) | ||
478 | lua_insert(L, -2); /* put buffer before new value */ | ||
479 | B->lvl++; /* add new value into B stack */ | ||
480 | adjuststack(B); | ||
481 | } | ||
482 | } | 494 | } |
483 | 495 | ||
484 | 496 | ||
485 | LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { | 497 | LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { |
486 | B->L = L; | 498 | B->L = L; |
487 | B->p = B->buffer; | 499 | B->b = B->initb; |
488 | B->lvl = 0; | 500 | B->n = 0; |
501 | B->size = LUAL_BUFFERSIZE; | ||
502 | } | ||
503 | |||
504 | |||
505 | LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { | ||
506 | luaL_buffinit(L, B); | ||
507 | return luaL_prepbuffsize(B, sz); | ||
489 | } | 508 | } |
490 | 509 | ||
491 | /* }====================================================== */ | 510 | /* }====================================================== */ |
492 | 511 | ||
493 | 512 | ||
513 | /* | ||
514 | ** {====================================================== | ||
515 | ** Reference system | ||
516 | ** ======================================================= | ||
517 | */ | ||
518 | |||
519 | /* index of free-list header */ | ||
520 | #define freelist 0 | ||
521 | |||
522 | |||
494 | LUALIB_API int luaL_ref (lua_State *L, int t) { | 523 | LUALIB_API int luaL_ref (lua_State *L, int t) { |
495 | int ref; | 524 | int ref; |
496 | t = abs_index(L, t); | ||
497 | if (lua_isnil(L, -1)) { | 525 | if (lua_isnil(L, -1)) { |
498 | lua_pop(L, 1); /* remove from stack */ | 526 | lua_pop(L, 1); /* remove from stack */ |
499 | return LUA_REFNIL; /* `nil' has a unique fixed reference */ | 527 | return LUA_REFNIL; /* `nil' has a unique fixed reference */ |
500 | } | 528 | } |
501 | lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ | 529 | t = lua_absindex(L, t); |
502 | ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ | 530 | lua_rawgeti(L, t, freelist); /* get first free element */ |
531 | ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ | ||
503 | lua_pop(L, 1); /* remove it from stack */ | 532 | lua_pop(L, 1); /* remove it from stack */ |
504 | if (ref != 0) { /* any free element? */ | 533 | if (ref != 0) { /* any free element? */ |
505 | lua_rawgeti(L, t, ref); /* remove it from list */ | 534 | lua_rawgeti(L, t, ref); /* remove it from list */ |
506 | lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ | 535 | lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ |
507 | } | ||
508 | else { /* no free elements */ | ||
509 | ref = (int)lua_objlen(L, t); | ||
510 | ref++; /* create new reference */ | ||
511 | } | 536 | } |
537 | else /* no free elements */ | ||
538 | ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ | ||
512 | lua_rawseti(L, t, ref); | 539 | lua_rawseti(L, t, ref); |
513 | return ref; | 540 | return ref; |
514 | } | 541 | } |
@@ -516,14 +543,15 @@ LUALIB_API int luaL_ref (lua_State *L, int t) { | |||
516 | 543 | ||
517 | LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { | 544 | LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { |
518 | if (ref >= 0) { | 545 | if (ref >= 0) { |
519 | t = abs_index(L, t); | 546 | t = lua_absindex(L, t); |
520 | lua_rawgeti(L, t, FREELIST_REF); | 547 | lua_rawgeti(L, t, freelist); |
521 | lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ | 548 | lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ |
522 | lua_pushinteger(L, ref); | 549 | lua_pushinteger(L, ref); |
523 | lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ | 550 | lua_rawseti(L, t, freelist); /* t[freelist] = ref */ |
524 | } | 551 | } |
525 | } | 552 | } |
526 | 553 | ||
554 | /* }====================================================== */ | ||
527 | 555 | ||
528 | 556 | ||
529 | /* | 557 | /* |
@@ -533,22 +561,28 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { | |||
533 | */ | 561 | */ |
534 | 562 | ||
535 | typedef struct LoadF { | 563 | typedef struct LoadF { |
536 | int extraline; | 564 | int n; /* number of pre-read characters */ |
537 | int f; | 565 | int f; |
538 | char buff[LUAL_BUFFERSIZE]; | 566 | char buff[LUAL_BUFFERSIZE]; /* area for reading file */ |
539 | } LoadF; | 567 | } LoadF; |
540 | 568 | ||
541 | static const char *getF(lua_State *L, void *ud, size_t *size) { | 569 | |
570 | static const char *getF (lua_State *L, void *ud, size_t *size) { | ||
542 | LoadF *lf = (LoadF *)ud; | 571 | LoadF *lf = (LoadF *)ud; |
543 | (void)L; | 572 | (void)L; /* not used */ |
544 | if (lf->extraline) { | 573 | if (lf->n > 0) { /* are there pre-read characters to be read? */ |
545 | lf->extraline = 0; | 574 | *size = lf->n; /* return them (chars already in buffer) */ |
546 | *size = 1; | 575 | lf->n = 0; /* no more pre-read characters */ |
547 | return "\n"; | 576 | } |
577 | else { /* read a block from file */ | ||
578 | /* 'fread' can return > 0 *and* set the EOF flag. If next call to | ||
579 | 'getF' called 'fread', it might still wait for user input. | ||
580 | The next check avoids this problem. */ | ||
581 | *size = rb->read(lf->f, lf->buff, LUAL_BUFFERSIZE); | ||
582 | if (*size <= 0) return NULL; | ||
583 | return (*size > 0) ? lf->buff : NULL; | ||
548 | } | 584 | } |
549 | *size = rb->read(lf->f, lf->buff, LUAL_BUFFERSIZE); | 585 | return lf->buff; |
550 | if (*size <= 0) return NULL; | ||
551 | return (*size > 0) ? lf->buff : NULL; | ||
552 | } | 586 | } |
553 | 587 | ||
554 | 588 | ||
@@ -560,16 +594,68 @@ static int errfile (lua_State *L, const char *what, int fnameindex) { | |||
560 | return LUA_ERRFILE; | 594 | return LUA_ERRFILE; |
561 | } | 595 | } |
562 | 596 | ||
563 | LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { | 597 | |
598 | static int skipBOM (LoadF *lf) { | ||
599 | const char *p = "\xEF\xBB\xBF"; /* Utf8 BOM mark */ | ||
600 | int c; | ||
601 | lf->n = 0; | ||
602 | do { | ||
603 | c = PREFIX(getc)(lf->f); | ||
604 | if (c == EOF || c != *(const unsigned char *)p++) return c; | ||
605 | lf->buff[lf->n++] = c; /* to be read by the parser */ | ||
606 | } while (*p != '\0'); | ||
607 | lf->n = 0; /* prefix matched; discard it */ | ||
608 | return PREFIX(getc)(lf->f); /* return next character */ | ||
609 | } | ||
610 | |||
611 | |||
612 | /* | ||
613 | ** reads the first character of file 'f' and skips an optional BOM mark | ||
614 | ** in its beginning plus its first line if it starts with '#'. Returns | ||
615 | ** true if it skipped the first line. In any case, '*cp' has the | ||
616 | ** first "valid" character of the file (after the optional BOM and | ||
617 | ** a first-line comment). | ||
618 | */ | ||
619 | static int skipcomment (LoadF *lf, int *cp) { | ||
620 | int c = *cp = skipBOM(lf); | ||
621 | if (c == '#') { /* first line is a comment (Unix exec. file)? */ | ||
622 | do { /* skip first line */ | ||
623 | c = PREFIX(getc)(lf->f); | ||
624 | } while (c != EOF && c != '\n') ; | ||
625 | *cp = PREFIX(getc)(lf->f); /* skip end-of-line, if present */ | ||
626 | return 1; /* there was a comment */ | ||
627 | } | ||
628 | else return 0; /* no comment */ | ||
629 | } | ||
630 | |||
631 | |||
632 | LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, | ||
633 | const char *mode) { | ||
564 | LoadF lf; | 634 | LoadF lf; |
565 | int status; | 635 | int status, readstatus; |
636 | int c; | ||
566 | int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ | 637 | int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ |
567 | lf.extraline = 0; | ||
568 | lf.f = rb->open(filename, O_RDONLY); | ||
569 | lua_pushfstring(L, "@%s", filename); | 638 | lua_pushfstring(L, "@%s", filename); |
639 | lf.n = 0; | ||
640 | lf.f = rb->open(filename, O_RDONLY); | ||
570 | if (lf.f < 0) return errfile(L, "open", fnameindex); | 641 | if (lf.f < 0) return errfile(L, "open", fnameindex); |
571 | status = lua_load(L, getF, &lf, lua_tostring(L, -1)); | 642 | if (skipcomment(&lf, &c)) /* read initial portion */ |
572 | rb->close(lf.f); | 643 | lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ |
644 | if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ | ||
645 | rb->close(lf.f); | ||
646 | lf.f = rb->open(filename, O_RDONLY); | ||
647 | if (lf.f < 0) return errfile(L, "reopen", fnameindex); | ||
648 | skipcomment(&lf, &c); /* re-read initial portion */ | ||
649 | } | ||
650 | if (c != EOF) | ||
651 | lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ | ||
652 | status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); | ||
653 | readstatus = 0;/*ferror(lf.f);*/ | ||
654 | if (filename) rb->close(lf.f); /* close file (even in case of errors) */ | ||
655 | if (readstatus) { | ||
656 | lua_settop(L, fnameindex); /* ignore results from `lua_load' */ | ||
657 | return errfile(L, "read", fnameindex); | ||
658 | } | ||
573 | lua_remove(L, fnameindex); | 659 | lua_remove(L, fnameindex); |
574 | return status; | 660 | return status; |
575 | } | 661 | } |
@@ -583,7 +669,7 @@ typedef struct LoadS { | |||
583 | 669 | ||
584 | static const char *getS (lua_State *L, void *ud, size_t *size) { | 670 | static const char *getS (lua_State *L, void *ud, size_t *size) { |
585 | LoadS *ls = (LoadS *)ud; | 671 | LoadS *ls = (LoadS *)ud; |
586 | (void)L; | 672 | (void)L; /* not used */ |
587 | if (ls->size == 0) return NULL; | 673 | if (ls->size == 0) return NULL; |
588 | *size = ls->size; | 674 | *size = ls->size; |
589 | ls->size = 0; | 675 | ls->size = 0; |
@@ -591,27 +677,245 @@ static const char *getS (lua_State *L, void *ud, size_t *size) { | |||
591 | } | 677 | } |
592 | 678 | ||
593 | 679 | ||
594 | LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, | 680 | LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, |
595 | const char *name) { | 681 | const char *name, const char *mode) { |
596 | LoadS ls; | 682 | LoadS ls; |
597 | ls.s = buff; | 683 | ls.s = buff; |
598 | ls.size = size; | 684 | ls.size = size; |
599 | return lua_load(L, getS, &ls, name); | 685 | return lua_load(L, getS, &ls, name, mode); |
600 | } | 686 | } |
601 | 687 | ||
602 | 688 | ||
603 | LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { | 689 | LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { |
604 | return luaL_loadbuffer(L, s, strlen(s), s); | 690 | return luaL_loadbuffer(L, s, strlen(s), s); |
605 | } | 691 | } |
606 | 692 | ||
693 | /* }====================================================== */ | ||
694 | |||
695 | |||
696 | |||
697 | LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { | ||
698 | if (!lua_getmetatable(L, obj)) /* no metatable? */ | ||
699 | return 0; | ||
700 | lua_pushstring(L, event); | ||
701 | lua_rawget(L, -2); | ||
702 | if (lua_isnil(L, -1)) { | ||
703 | lua_pop(L, 2); /* remove metatable and metafield */ | ||
704 | return 0; | ||
705 | } | ||
706 | else { | ||
707 | lua_remove(L, -2); /* remove only metatable */ | ||
708 | return 1; | ||
709 | } | ||
710 | } | ||
711 | |||
712 | |||
713 | LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { | ||
714 | obj = lua_absindex(L, obj); | ||
715 | if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ | ||
716 | return 0; | ||
717 | lua_pushvalue(L, obj); | ||
718 | lua_call(L, 1, 1); | ||
719 | return 1; | ||
720 | } | ||
721 | |||
722 | |||
723 | LUALIB_API int luaL_len (lua_State *L, int idx) { | ||
724 | int l; | ||
725 | int isnum; | ||
726 | lua_len(L, idx); | ||
727 | l = (int)lua_tointegerx(L, -1, &isnum); | ||
728 | if (!isnum) | ||
729 | luaL_error(L, "object length is not a number"); | ||
730 | lua_pop(L, 1); /* remove object */ | ||
731 | return l; | ||
732 | } | ||
733 | |||
734 | |||
735 | LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { | ||
736 | if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ | ||
737 | switch (lua_type(L, idx)) { | ||
738 | case LUA_TNUMBER: | ||
739 | case LUA_TSTRING: | ||
740 | lua_pushvalue(L, idx); | ||
741 | break; | ||
742 | case LUA_TBOOLEAN: | ||
743 | lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); | ||
744 | break; | ||
745 | case LUA_TNIL: | ||
746 | lua_pushliteral(L, "nil"); | ||
747 | break; | ||
748 | default: | ||
749 | lua_pushfstring(L, "%s: %p", luaL_typename(L, idx), | ||
750 | lua_topointer(L, idx)); | ||
751 | break; | ||
752 | } | ||
753 | } | ||
754 | return lua_tolstring(L, -1, len); | ||
755 | } | ||
756 | |||
757 | |||
758 | /* | ||
759 | ** {====================================================== | ||
760 | ** Compatibility with 5.1 module functions | ||
761 | ** ======================================================= | ||
762 | */ | ||
763 | #if defined(LUA_COMPAT_MODULE) | ||
764 | |||
765 | static const char *luaL_findtable (lua_State *L, int idx, | ||
766 | const char *fname, int szhint) { | ||
767 | const char *e; | ||
768 | if (idx) lua_pushvalue(L, idx); | ||
769 | do { | ||
770 | e = strchr(fname, '.'); | ||
771 | if (e == NULL) e = fname + strlen(fname); | ||
772 | lua_pushlstring(L, fname, e - fname); | ||
773 | lua_rawget(L, -2); | ||
774 | if (lua_isnil(L, -1)) { /* no such field? */ | ||
775 | lua_pop(L, 1); /* remove this nil */ | ||
776 | lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ | ||
777 | lua_pushlstring(L, fname, e - fname); | ||
778 | lua_pushvalue(L, -2); | ||
779 | lua_settable(L, -4); /* set new table into field */ | ||
780 | } | ||
781 | else if (!lua_istable(L, -1)) { /* field has a non-table value? */ | ||
782 | lua_pop(L, 2); /* remove table and value */ | ||
783 | return fname; /* return problematic part of the name */ | ||
784 | } | ||
785 | lua_remove(L, -2); /* remove previous table */ | ||
786 | fname = e + 1; | ||
787 | } while (*e == '.'); | ||
788 | return NULL; | ||
789 | } | ||
790 | |||
791 | |||
792 | /* | ||
793 | ** Count number of elements in a luaL_Reg list. | ||
794 | */ | ||
795 | static int libsize (const luaL_Reg *l) { | ||
796 | int size = 0; | ||
797 | for (; l && l->name; l++) size++; | ||
798 | return size; | ||
799 | } | ||
800 | |||
801 | |||
802 | /* | ||
803 | ** Find or create a module table with a given name. The function | ||
804 | ** first looks at the _LOADED table and, if that fails, try a | ||
805 | ** global variable with that name. In any case, leaves on the stack | ||
806 | ** the module table. | ||
807 | */ | ||
808 | LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname, | ||
809 | int sizehint) { | ||
810 | luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); /* get _LOADED table */ | ||
811 | lua_getfield(L, -1, modname); /* get _LOADED[modname] */ | ||
812 | if (!lua_istable(L, -1)) { /* not found? */ | ||
813 | lua_pop(L, 1); /* remove previous result */ | ||
814 | /* try global variable (and create one if it does not exist) */ | ||
815 | lua_pushglobaltable(L); | ||
816 | if (luaL_findtable(L, 0, modname, sizehint) != NULL) | ||
817 | luaL_error(L, "name conflict for module " LUA_QS, modname); | ||
818 | lua_pushvalue(L, -1); | ||
819 | lua_setfield(L, -3, modname); /* _LOADED[modname] = new table */ | ||
820 | } | ||
821 | lua_remove(L, -2); /* remove _LOADED table */ | ||
822 | } | ||
607 | 823 | ||
608 | 824 | ||
825 | LUALIB_API void luaL_openlib (lua_State *L, const char *libname, | ||
826 | const luaL_Reg *l, int nup) { | ||
827 | luaL_checkversion(L); | ||
828 | if (libname) { | ||
829 | luaL_pushmodule(L, libname, libsize(l)); /* get/create library table */ | ||
830 | lua_insert(L, -(nup + 1)); /* move library table to below upvalues */ | ||
831 | } | ||
832 | if (l) | ||
833 | luaL_setfuncs(L, l, nup); | ||
834 | else | ||
835 | lua_pop(L, nup); /* remove upvalues */ | ||
836 | } | ||
837 | |||
838 | #endif | ||
609 | /* }====================================================== */ | 839 | /* }====================================================== */ |
610 | 840 | ||
841 | /* | ||
842 | ** set functions from list 'l' into table at top - 'nup'; each | ||
843 | ** function gets the 'nup' elements at the top as upvalues. | ||
844 | ** Returns with only the table at the stack. | ||
845 | */ | ||
846 | LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { | ||
847 | luaL_checkversion(L); | ||
848 | luaL_checkstack(L, nup, "too many upvalues"); | ||
849 | for (; l->name != NULL; l++) { /* fill the table with given functions */ | ||
850 | int i; | ||
851 | for (i = 0; i < nup; i++) /* copy upvalues to the top */ | ||
852 | lua_pushvalue(L, -nup); | ||
853 | lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ | ||
854 | lua_setfield(L, -(nup + 2), l->name); | ||
855 | } | ||
856 | lua_pop(L, nup); /* remove upvalues */ | ||
857 | } | ||
858 | |||
859 | |||
860 | /* | ||
861 | ** ensure that stack[idx][fname] has a table and push that table | ||
862 | ** into the stack | ||
863 | */ | ||
864 | LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { | ||
865 | lua_getfield(L, idx, fname); | ||
866 | if (lua_istable(L, -1)) return 1; /* table already there */ | ||
867 | else { | ||
868 | lua_pop(L, 1); /* remove previous result */ | ||
869 | idx = lua_absindex(L, idx); | ||
870 | lua_newtable(L); | ||
871 | lua_pushvalue(L, -1); /* copy to be left at top */ | ||
872 | lua_setfield(L, idx, fname); /* assign new table to field */ | ||
873 | return 0; /* false, because did not find table there */ | ||
874 | } | ||
875 | } | ||
876 | |||
877 | |||
878 | /* | ||
879 | ** stripped-down 'require'. Calls 'openf' to open a module, | ||
880 | ** registers the result in 'package.loaded' table and, if 'glb' | ||
881 | ** is true, also registers the result in the global table. | ||
882 | ** Leaves resulting module on the top. | ||
883 | */ | ||
884 | LUALIB_API void luaL_requiref (lua_State *L, const char *modname, | ||
885 | lua_CFunction openf, int glb) { | ||
886 | lua_pushcfunction(L, openf); | ||
887 | lua_pushstring(L, modname); /* argument to open function */ | ||
888 | lua_call(L, 1, 1); /* open module */ | ||
889 | luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); | ||
890 | lua_pushvalue(L, -2); /* make copy of module (call result) */ | ||
891 | lua_setfield(L, -2, modname); /* _LOADED[modname] = module */ | ||
892 | lua_pop(L, 1); /* remove _LOADED table */ | ||
893 | if (glb) { | ||
894 | lua_pushvalue(L, -1); /* copy of 'mod' */ | ||
895 | lua_setglobal(L, modname); /* _G[modname] = module */ | ||
896 | } | ||
897 | } | ||
898 | |||
899 | |||
900 | LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, | ||
901 | const char *r) { | ||
902 | const char *wild; | ||
903 | size_t l = strlen(p); | ||
904 | luaL_Buffer b; | ||
905 | luaL_buffinit(L, &b); | ||
906 | while ((wild = strstr(s, p)) != NULL) { | ||
907 | luaL_addlstring(&b, s, wild - s); /* push prefix */ | ||
908 | luaL_addstring(&b, r); /* push replacement in place of pattern */ | ||
909 | s = wild + l; /* continue after `p' */ | ||
910 | } | ||
911 | luaL_addstring(&b, s); /* push last suffix */ | ||
912 | luaL_pushresult(&b); | ||
913 | return lua_tostring(L, -1); | ||
914 | } | ||
915 | |||
611 | 916 | ||
612 | static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { | 917 | static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { |
613 | (void)ud; | 918 | (void)ud; (void)osize; /* not used */ |
614 | (void)osize; | ||
615 | if (nsize == 0) { | 919 | if (nsize == 0) { |
616 | free(ptr); | 920 | free(ptr); |
617 | return NULL; | 921 | return NULL; |
@@ -622,12 +926,11 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { | |||
622 | 926 | ||
623 | 927 | ||
624 | static int panic (lua_State *L) { | 928 | static int panic (lua_State *L) { |
625 | DEBUGF("PANIC: unprotected error in call to Lua API (%s)\n", | 929 | DEBUGF("PANIC: unprotected error in call to Lua API (%s)\n", |
626 | lua_tostring(L, -1)); | 930 | lua_tostring(L, -1)); |
627 | rb->splashf(5 * HZ, "PANIC: unprotected error in call to Lua API (%s)", | 931 | rb->splashf(5 * HZ, "PANIC: unprotected error in call to Lua API (%s)", |
628 | lua_tostring(L, -1)); | 932 | lua_tostring(L, -1)); |
629 | 933 | return 0; /* return to Lua to abort */ | |
630 | return 0; | ||
631 | } | 934 | } |
632 | 935 | ||
633 | 936 | ||
@@ -637,3 +940,20 @@ LUALIB_API lua_State *luaL_newstate (void) { | |||
637 | return L; | 940 | return L; |
638 | } | 941 | } |
639 | 942 | ||
943 | |||
944 | LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) { | ||
945 | const lua_Number *v = lua_version(L); | ||
946 | if (v != lua_version(NULL)) | ||
947 | luaL_error(L, "multiple Lua VMs detected"); | ||
948 | else if (*v != ver) | ||
949 | luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", | ||
950 | ver, *v); | ||
951 | /* check conversions number -> integer types */ | ||
952 | lua_pushnumber(L, -(lua_Number)0x1234); | ||
953 | if (lua_tointeger(L, -1) != -0x1234 || | ||
954 | lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) | ||
955 | luaL_error(L, "bad conversion number->int;" | ||
956 | " must recompile Lua with proper settings"); | ||
957 | lua_pop(L, 1); | ||
958 | } | ||
959 | |||
diff --git a/apps/plugins/lua/lauxlib.h b/apps/plugins/lua/lauxlib.h index a36de351fe..0fb023b8e7 100644 --- a/apps/plugins/lua/lauxlib.h +++ b/apps/plugins/lua/lauxlib.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lauxlib.h,v 1.120.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Auxiliary functions for building Lua libraries | 3 | ** Auxiliary functions for building Lua libraries |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -15,18 +15,6 @@ | |||
15 | #include "lua.h" | 15 | #include "lua.h" |
16 | 16 | ||
17 | 17 | ||
18 | #if defined(LUA_COMPAT_GETN) | ||
19 | LUALIB_API int (luaL_getn) (lua_State *L, int t); | ||
20 | LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); | ||
21 | #else | ||
22 | #define luaL_getn(L,i) ((int)lua_objlen(L, i)) | ||
23 | #define luaL_setn(L,i,j) ((void)0) /* no op! */ | ||
24 | #endif | ||
25 | |||
26 | #if defined(LUA_COMPAT_OPENLIB) | ||
27 | #define luaI_openlib luaL_openlib | ||
28 | #endif | ||
29 | |||
30 | 18 | ||
31 | /* extra error code for `luaL_load' */ | 19 | /* extra error code for `luaL_load' */ |
32 | #define LUA_ERRFILE (LUA_ERRERR+1) | 20 | #define LUA_ERRFILE (LUA_ERRERR+1) |
@@ -38,14 +26,12 @@ typedef struct luaL_Reg { | |||
38 | } luaL_Reg; | 26 | } luaL_Reg; |
39 | 27 | ||
40 | 28 | ||
29 | LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver); | ||
30 | #define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) | ||
41 | 31 | ||
42 | LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, | ||
43 | const luaL_Reg *l, int nup); | ||
44 | LUALIB_API void (luaL_register) (lua_State *L, const char *libname, | ||
45 | const luaL_Reg *l); | ||
46 | LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); | 32 | LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); |
47 | LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); | 33 | LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); |
48 | LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); | 34 | LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); |
49 | LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); | 35 | LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); |
50 | LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, | 36 | LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, |
51 | size_t *l); | 37 | size_t *l); |
@@ -57,16 +43,17 @@ LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); | |||
57 | LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); | 43 | LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); |
58 | LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, | 44 | LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, |
59 | lua_Integer def); | 45 | lua_Integer def); |
60 | 46 | LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg); | |
61 | LUALIB_API int (luaL_checkboolean) (lua_State *L, int numArg); | 47 | LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg, |
62 | LUALIB_API int (luaL_optboolean) (lua_State *L, int nArg, | 48 | lua_Unsigned def); |
63 | int def); | ||
64 | 49 | ||
65 | LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); | 50 | LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); |
66 | LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); | 51 | LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); |
67 | LUALIB_API void (luaL_checkany) (lua_State *L, int narg); | 52 | LUALIB_API void (luaL_checkany) (lua_State *L, int narg); |
68 | 53 | ||
69 | LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); | 54 | LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); |
55 | LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); | ||
56 | LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); | ||
70 | LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); | 57 | LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); |
71 | 58 | ||
72 | LUALIB_API void (luaL_where) (lua_State *L, int lvl); | 59 | LUALIB_API void (luaL_where) (lua_State *L, int lvl); |
@@ -75,25 +62,41 @@ LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); | |||
75 | LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, | 62 | LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, |
76 | const char *const lst[]); | 63 | const char *const lst[]); |
77 | 64 | ||
65 | LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); | ||
66 | LUALIB_API int (luaL_execresult) (lua_State *L, int stat); | ||
67 | |||
68 | /* pre-defined references */ | ||
69 | #define LUA_NOREF (-2) | ||
70 | #define LUA_REFNIL (-1) | ||
71 | |||
78 | LUALIB_API int (luaL_ref) (lua_State *L, int t); | 72 | LUALIB_API int (luaL_ref) (lua_State *L, int t); |
79 | LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); | 73 | LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); |
80 | 74 | ||
81 | LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); | 75 | LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, |
82 | LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, | 76 | const char *mode); |
83 | const char *name); | 77 | |
78 | #define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) | ||
79 | |||
80 | LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, | ||
81 | const char *name, const char *mode); | ||
84 | LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); | 82 | LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); |
85 | 83 | ||
86 | LUALIB_API lua_State *(luaL_newstate) (void); | 84 | LUALIB_API lua_State *(luaL_newstate) (void); |
87 | 85 | ||
86 | LUALIB_API int (luaL_len) (lua_State *L, int idx); | ||
88 | 87 | ||
89 | LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, | 88 | LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, |
90 | const char *r); | 89 | const char *r); |
91 | 90 | ||
92 | LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, | 91 | LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); |
93 | const char *fname, int szhint); | ||
94 | 92 | ||
93 | LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); | ||
95 | 94 | ||
95 | LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, | ||
96 | const char *msg, int level); | ||
96 | 97 | ||
98 | LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, | ||
99 | lua_CFunction openf, int glb); | ||
97 | 100 | ||
98 | /* | 101 | /* |
99 | ** =============================================================== | 102 | ** =============================================================== |
@@ -101,6 +104,12 @@ LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, | |||
101 | ** =============================================================== | 104 | ** =============================================================== |
102 | */ | 105 | */ |
103 | 106 | ||
107 | |||
108 | #define luaL_newlibtable(L,l) \ | ||
109 | lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) | ||
110 | |||
111 | #define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) | ||
112 | |||
104 | #define luaL_argcheck(L, cond,numarg,extramsg) \ | 113 | #define luaL_argcheck(L, cond,numarg,extramsg) \ |
105 | ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) | 114 | ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) |
106 | #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) | 115 | #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) |
@@ -122,56 +131,81 @@ LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, | |||
122 | 131 | ||
123 | #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) | 132 | #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) |
124 | 133 | ||
134 | #define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) | ||
135 | |||
136 | |||
125 | /* | 137 | /* |
126 | ** {====================================================== | 138 | ** {====================================================== |
127 | ** Generic Buffer manipulation | 139 | ** Generic Buffer manipulation |
128 | ** ======================================================= | 140 | ** ======================================================= |
129 | */ | 141 | */ |
130 | 142 | ||
131 | |||
132 | |||
133 | typedef struct luaL_Buffer { | 143 | typedef struct luaL_Buffer { |
134 | char *p; /* current position in buffer */ | 144 | char *b; /* buffer address */ |
135 | int lvl; /* number of strings in the stack (level) */ | 145 | size_t size; /* buffer size */ |
146 | size_t n; /* number of characters in buffer */ | ||
136 | lua_State *L; | 147 | lua_State *L; |
137 | char buffer[LUAL_BUFFERSIZE]; | 148 | char initb[LUAL_BUFFERSIZE]; /* initial buffer */ |
138 | } luaL_Buffer; | 149 | } luaL_Buffer; |
139 | 150 | ||
140 | #define luaL_addchar(B,c) \ | ||
141 | ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ | ||
142 | (*(B)->p++ = (char)(c))) | ||
143 | 151 | ||
144 | /* compatibility only */ | 152 | #define luaL_addchar(B,c) \ |
145 | #define luaL_putchar(B,c) luaL_addchar(B,c) | 153 | ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ |
154 | ((B)->b[(B)->n++] = (c))) | ||
146 | 155 | ||
147 | #define luaL_addsize(B,n) ((B)->p += (n)) | 156 | #define luaL_addsize(B,s) ((B)->n += (s)) |
148 | 157 | ||
149 | LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); | 158 | LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); |
150 | LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); | 159 | LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); |
151 | LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); | 160 | LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); |
152 | LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); | 161 | LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); |
153 | LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); | 162 | LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); |
154 | LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); | 163 | LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); |
164 | LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); | ||
165 | LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); | ||
155 | 166 | ||
167 | #define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) | ||
156 | 168 | ||
157 | /* }====================================================== */ | 169 | /* }====================================================== */ |
158 | 170 | ||
159 | 171 | ||
160 | /* compatibility with ref system */ | ||
161 | 172 | ||
162 | /* pre-defined references */ | 173 | /* |
163 | #define LUA_NOREF (-2) | 174 | ** {====================================================== |
164 | #define LUA_REFNIL (-1) | 175 | ** File handles for IO library |
176 | ** ======================================================= | ||
177 | */ | ||
178 | |||
179 | /* | ||
180 | ** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and | ||
181 | ** initial structure 'luaL_Stream' (it may contain other fields | ||
182 | ** after that initial structure). | ||
183 | */ | ||
184 | |||
185 | #define LUA_FILEHANDLE "FILE*" | ||
186 | |||
187 | |||
188 | typedef struct luaL_Stream { | ||
189 | FILE *f; /* stream (NULL for incompletely created streams) */ | ||
190 | lua_CFunction closef; /* to close stream (NULL for closed streams) */ | ||
191 | } luaL_Stream; | ||
192 | |||
193 | /* }====================================================== */ | ||
194 | |||
165 | 195 | ||
166 | #define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ | ||
167 | (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) | ||
168 | 196 | ||
169 | #define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) | 197 | /* compatibility with old module system */ |
198 | #if defined(LUA_COMPAT_MODULE) | ||
170 | 199 | ||
171 | #define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) | 200 | LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, |
201 | int sizehint); | ||
202 | LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, | ||
203 | const luaL_Reg *l, int nup); | ||
172 | 204 | ||
205 | #define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) | ||
206 | |||
207 | #endif | ||
173 | 208 | ||
174 | #define luaL_reg luaL_Reg | ||
175 | 209 | ||
176 | #endif | 210 | #endif |
177 | 211 | ||
diff --git a/apps/plugins/lua/lbaselib.c b/apps/plugins/lua/lbaselib.c index 008e3629fe..5255b3cd9b 100644 --- a/apps/plugins/lua/lbaselib.c +++ b/apps/plugins/lua/lbaselib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ | 2 | ** $Id: lbaselib.c,v 1.276.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Basic library | 3 | ** Basic library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -20,62 +20,68 @@ | |||
20 | #include "lualib.h" | 20 | #include "lualib.h" |
21 | 21 | ||
22 | 22 | ||
23 | |||
24 | |||
25 | /* | ||
26 | ** If your system does not support `stdout', you can just remove this function. | ||
27 | ** If you need, you can define your own `print' function, following this | ||
28 | ** model but changing `fputs' to put the strings at a proper place | ||
29 | ** (a console window or a log file, for instance). | ||
30 | */ | ||
31 | #if 0 | ||
32 | static int luaB_print (lua_State *L) { | 23 | static int luaB_print (lua_State *L) { |
33 | int n = lua_gettop(L); /* number of arguments */ | 24 | int n = lua_gettop(L); /* number of arguments */ |
34 | int i; | 25 | int i; |
35 | lua_getglobal(L, "tostring"); | 26 | lua_getglobal(L, "tostring"); |
36 | for (i=1; i<=n; i++) { | 27 | for (i=1; i<=n; i++) { |
37 | const char *s; | 28 | const char *s; |
29 | size_t l; | ||
38 | lua_pushvalue(L, -1); /* function to be called */ | 30 | lua_pushvalue(L, -1); /* function to be called */ |
39 | lua_pushvalue(L, i); /* value to print */ | 31 | lua_pushvalue(L, i); /* value to print */ |
40 | lua_call(L, 1, 1); | 32 | lua_call(L, 1, 1); |
41 | s = lua_tostring(L, -1); /* get result */ | 33 | s = lua_tolstring(L, -1, &l); /* get result */ |
42 | if (s == NULL) | 34 | if (s == NULL) |
43 | return luaL_error(L, LUA_QL("tostring") " must return a string to " | 35 | return luaL_error(L, |
44 | LUA_QL("print")); | 36 | LUA_QL("tostring") " must return a string to " LUA_QL("print")); |
45 | if (i>1) fputs("\t", stdout); | 37 | if (i>1) luai_writestring("\t", 1); |
46 | fputs(s, stdout); | 38 | luai_writestring(s, l); |
47 | lua_pop(L, 1); /* pop result */ | 39 | lua_pop(L, 1); /* pop result */ |
48 | } | 40 | } |
49 | fputs("\n", stdout); | 41 | luai_writeline(); |
50 | return 0; | 42 | return 0; |
51 | } | 43 | } |
52 | #endif | ||
53 | 44 | ||
54 | 45 | ||
46 | #define SPACECHARS " \f\n\r\t\v" | ||
47 | |||
55 | static int luaB_tonumber (lua_State *L) { | 48 | static int luaB_tonumber (lua_State *L) { |
56 | int base = luaL_optint(L, 2, 10); | 49 | if (lua_isnoneornil(L, 2)) { /* standard conversion */ |
57 | if (base == 10) { /* standard conversion */ | 50 | int isnum; |
58 | luaL_checkany(L, 1); | 51 | lua_Number n = lua_tonumberx(L, 1, &isnum); |
59 | if (lua_isnumber(L, 1)) { | 52 | if (isnum) { |
60 | lua_pushnumber(L, lua_tonumber(L, 1)); | 53 | lua_pushnumber(L, n); |
61 | return 1; | 54 | return 1; |
62 | } | 55 | } /* else not a number; must be something */ |
56 | luaL_checkany(L, 1); | ||
63 | } | 57 | } |
64 | else { | 58 | else { |
65 | const char *s1 = luaL_checkstring(L, 1); | 59 | size_t l; |
66 | char *s2; | 60 | const char *s = luaL_checklstring(L, 1, &l); |
67 | unsigned long n; | 61 | const char *e = s + l; /* end point for 's' */ |
62 | int base = luaL_checkint(L, 2); | ||
63 | int neg = 0; | ||
68 | luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); | 64 | luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); |
69 | n = strtoul(s1, &s2, base); | 65 | s += strspn(s, SPACECHARS); /* skip initial spaces */ |
70 | if (s1 != s2) { /* at least one valid digit? */ | 66 | if (*s == '-') { s++; neg = 1; } /* handle signal */ |
71 | while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ | 67 | else if (*s == '+') s++; |
72 | if (*s2 == '\0') { /* no invalid trailing characters? */ | 68 | if (isalnum((unsigned char)*s)) { |
73 | lua_pushnumber(L, (lua_Number)n); | 69 | lua_Number n = 0; |
70 | do { | ||
71 | int digit = (isdigit((unsigned char)*s)) ? *s - '0' | ||
72 | : toupper((unsigned char)*s) - 'A' + 10; | ||
73 | if (digit >= base) break; /* invalid numeral; force a fail */ | ||
74 | n = n * (lua_Number)base + (lua_Number)digit; | ||
75 | s++; | ||
76 | } while (isalnum((unsigned char)*s)); | ||
77 | s += strspn(s, SPACECHARS); /* skip trailing spaces */ | ||
78 | if (s == e) { /* no invalid trailing characters? */ | ||
79 | lua_pushnumber(L, (neg) ? -n : n); | ||
74 | return 1; | 80 | return 1; |
75 | } | 81 | } /* else not a number */ |
76 | } | 82 | } /* else not a number */ |
77 | } | 83 | } |
78 | lua_pushnil(L); /* else not a number */ | 84 | lua_pushnil(L); /* not a number */ |
79 | return 1; | 85 | return 1; |
80 | } | 86 | } |
81 | 87 | ||
@@ -109,57 +115,13 @@ static int luaB_setmetatable (lua_State *L) { | |||
109 | luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, | 115 | luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, |
110 | "nil or table expected"); | 116 | "nil or table expected"); |
111 | if (luaL_getmetafield(L, 1, "__metatable")) | 117 | if (luaL_getmetafield(L, 1, "__metatable")) |
112 | luaL_error(L, "cannot change a protected metatable"); | 118 | return luaL_error(L, "cannot change a protected metatable"); |
113 | lua_settop(L, 2); | 119 | lua_settop(L, 2); |
114 | lua_setmetatable(L, 1); | 120 | lua_setmetatable(L, 1); |
115 | return 1; | 121 | return 1; |
116 | } | 122 | } |
117 | 123 | ||
118 | 124 | ||
119 | static void getfunc (lua_State *L, int opt) { | ||
120 | if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); | ||
121 | else { | ||
122 | lua_Debug ar; | ||
123 | int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); | ||
124 | luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); | ||
125 | if (lua_getstack(L, level, &ar) == 0) | ||
126 | luaL_argerror(L, 1, "invalid level"); | ||
127 | lua_getinfo(L, "f", &ar); | ||
128 | if (lua_isnil(L, -1)) | ||
129 | luaL_error(L, "no function environment for tail call at level %d", | ||
130 | level); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | |||
135 | static int luaB_getfenv (lua_State *L) { | ||
136 | getfunc(L, 1); | ||
137 | if (lua_iscfunction(L, -1)) /* is a C function? */ | ||
138 | lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ | ||
139 | else | ||
140 | lua_getfenv(L, -1); | ||
141 | return 1; | ||
142 | } | ||
143 | |||
144 | |||
145 | static int luaB_setfenv (lua_State *L) { | ||
146 | luaL_checktype(L, 2, LUA_TTABLE); | ||
147 | getfunc(L, 0); | ||
148 | lua_pushvalue(L, 2); | ||
149 | if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { | ||
150 | /* change environment of current thread */ | ||
151 | lua_pushthread(L); | ||
152 | lua_insert(L, -2); | ||
153 | lua_setfenv(L, -2); | ||
154 | return 0; | ||
155 | } | ||
156 | else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) | ||
157 | luaL_error(L, | ||
158 | LUA_QL("setfenv") " cannot change environment of given object"); | ||
159 | return 1; | ||
160 | } | ||
161 | |||
162 | |||
163 | static int luaB_rawequal (lua_State *L) { | 125 | static int luaB_rawequal (lua_State *L) { |
164 | luaL_checkany(L, 1); | 126 | luaL_checkany(L, 1); |
165 | luaL_checkany(L, 2); | 127 | luaL_checkany(L, 2); |
@@ -168,6 +130,15 @@ static int luaB_rawequal (lua_State *L) { | |||
168 | } | 130 | } |
169 | 131 | ||
170 | 132 | ||
133 | static int luaB_rawlen (lua_State *L) { | ||
134 | int t = lua_type(L, 1); | ||
135 | luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, | ||
136 | "table or string expected"); | ||
137 | lua_pushinteger(L, lua_rawlen(L, 1)); | ||
138 | return 1; | ||
139 | } | ||
140 | |||
141 | |||
171 | static int luaB_rawget (lua_State *L) { | 142 | static int luaB_rawget (lua_State *L) { |
172 | luaL_checktype(L, 1, LUA_TTABLE); | 143 | luaL_checktype(L, 1, LUA_TTABLE); |
173 | luaL_checkany(L, 2); | 144 | luaL_checkany(L, 2); |
@@ -186,32 +157,29 @@ static int luaB_rawset (lua_State *L) { | |||
186 | } | 157 | } |
187 | 158 | ||
188 | 159 | ||
189 | static int luaB_gcinfo (lua_State *L) { | ||
190 | lua_pushinteger(L, lua_getgccount(L)); | ||
191 | return 1; | ||
192 | } | ||
193 | |||
194 | |||
195 | static int luaB_collectgarbage (lua_State *L) { | 160 | static int luaB_collectgarbage (lua_State *L) { |
196 | static const char *const opts[] = {"stop", "restart", "collect", | 161 | static const char *const opts[] = {"stop", "restart", "collect", |
197 | "count", "step", "setpause", "setstepmul", NULL}; | 162 | "count", "step", "setpause", "setstepmul", |
163 | "setmajorinc", "isrunning", "generational", "incremental", NULL}; | ||
198 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, | 164 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, |
199 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; | 165 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, |
200 | int o = luaL_checkoption(L, 1, "collect", opts); | 166 | LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; |
167 | int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; | ||
201 | int ex = luaL_optint(L, 2, 0); | 168 | int ex = luaL_optint(L, 2, 0); |
202 | int res = lua_gc(L, optsnum[o], ex); | 169 | int res = lua_gc(L, o, ex); |
203 | switch (optsnum[o]) { | 170 | switch (o) { |
204 | case LUA_GCCOUNT: { | 171 | case LUA_GCCOUNT: { |
205 | int b = lua_gc(L, LUA_GCCOUNTB, 0); | 172 | int b = lua_gc(L, LUA_GCCOUNTB, 0); |
206 | lua_pushnumber(L, res + ((lua_Number)b/1024)); | 173 | lua_pushnumber(L, res + ((lua_Number)b/1024)); |
207 | return 1; | 174 | lua_pushinteger(L, b); |
175 | return 2; | ||
208 | } | 176 | } |
209 | case LUA_GCSTEP: { | 177 | case LUA_GCSTEP: case LUA_GCISRUNNING: { |
210 | lua_pushboolean(L, res); | 178 | lua_pushboolean(L, res); |
211 | return 1; | 179 | return 1; |
212 | } | 180 | } |
213 | default: { | 181 | default: { |
214 | lua_pushnumber(L, res); | 182 | lua_pushinteger(L, res); |
215 | return 1; | 183 | return 1; |
216 | } | 184 | } |
217 | } | 185 | } |
@@ -225,6 +193,23 @@ static int luaB_type (lua_State *L) { | |||
225 | } | 193 | } |
226 | 194 | ||
227 | 195 | ||
196 | static int pairsmeta (lua_State *L, const char *method, int iszero, | ||
197 | lua_CFunction iter) { | ||
198 | if (!luaL_getmetafield(L, 1, method)) { /* no metamethod? */ | ||
199 | luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */ | ||
200 | lua_pushcfunction(L, iter); /* will return generator, */ | ||
201 | lua_pushvalue(L, 1); /* state, */ | ||
202 | if (iszero) lua_pushinteger(L, 0); /* and initial value */ | ||
203 | else lua_pushnil(L); | ||
204 | } | ||
205 | else { | ||
206 | lua_pushvalue(L, 1); /* argument 'self' to metamethod */ | ||
207 | lua_call(L, 1, 3); /* get 3 values from metamethod */ | ||
208 | } | ||
209 | return 3; | ||
210 | } | ||
211 | |||
212 | |||
228 | static int luaB_next (lua_State *L) { | 213 | static int luaB_next (lua_State *L) { |
229 | luaL_checktype(L, 1, LUA_TTABLE); | 214 | luaL_checktype(L, 1, LUA_TTABLE); |
230 | lua_settop(L, 2); /* create a 2nd argument if there isn't one */ | 215 | lua_settop(L, 2); /* create a 2nd argument if there isn't one */ |
@@ -238,11 +223,7 @@ static int luaB_next (lua_State *L) { | |||
238 | 223 | ||
239 | 224 | ||
240 | static int luaB_pairs (lua_State *L) { | 225 | static int luaB_pairs (lua_State *L) { |
241 | luaL_checktype(L, 1, LUA_TTABLE); | 226 | return pairsmeta(L, "__pairs", 0, luaB_next); |
242 | lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ | ||
243 | lua_pushvalue(L, 1); /* state, */ | ||
244 | lua_pushnil(L); /* and initial value */ | ||
245 | return 3; | ||
246 | } | 227 | } |
247 | 228 | ||
248 | 229 | ||
@@ -252,23 +233,25 @@ static int ipairsaux (lua_State *L) { | |||
252 | i++; /* next value */ | 233 | i++; /* next value */ |
253 | lua_pushinteger(L, i); | 234 | lua_pushinteger(L, i); |
254 | lua_rawgeti(L, 1, i); | 235 | lua_rawgeti(L, 1, i); |
255 | return (lua_isnil(L, -1)) ? 0 : 2; | 236 | return (lua_isnil(L, -1)) ? 1 : 2; |
256 | } | 237 | } |
257 | 238 | ||
258 | 239 | ||
259 | static int luaB_ipairs (lua_State *L) { | 240 | static int luaB_ipairs (lua_State *L) { |
260 | luaL_checktype(L, 1, LUA_TTABLE); | 241 | return pairsmeta(L, "__ipairs", 1, ipairsaux); |
261 | lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ | ||
262 | lua_pushvalue(L, 1); /* state, */ | ||
263 | lua_pushinteger(L, 0); /* and initial value */ | ||
264 | return 3; | ||
265 | } | 242 | } |
266 | 243 | ||
267 | 244 | ||
268 | static int load_aux (lua_State *L, int status) { | 245 | static int load_aux (lua_State *L, int status, int envidx) { |
269 | if (status == 0) /* OK? */ | 246 | if (status == LUA_OK) { |
247 | if (envidx != 0) { /* 'env' parameter? */ | ||
248 | lua_pushvalue(L, envidx); /* environment for loaded function */ | ||
249 | if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ | ||
250 | lua_pop(L, 1); /* remove 'env' if not used by previous call */ | ||
251 | } | ||
270 | return 1; | 252 | return 1; |
271 | else { | 253 | } |
254 | else { /* error (message is on top of the stack) */ | ||
272 | lua_pushnil(L); | 255 | lua_pushnil(L); |
273 | lua_insert(L, -2); /* put before error message */ | 256 | lua_insert(L, -2); /* put before error message */ |
274 | return 2; /* return nil plus error message */ | 257 | return 2; /* return nil plus error message */ |
@@ -276,87 +259,97 @@ static int load_aux (lua_State *L, int status) { | |||
276 | } | 259 | } |
277 | 260 | ||
278 | 261 | ||
279 | static int luaB_loadstring (lua_State *L) { | ||
280 | size_t l; | ||
281 | const char *s = luaL_checklstring(L, 1, &l); | ||
282 | const char *chunkname = luaL_optstring(L, 2, s); | ||
283 | return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); | ||
284 | } | ||
285 | |||
286 | |||
287 | static int luaB_loadfile (lua_State *L) { | 262 | static int luaB_loadfile (lua_State *L) { |
288 | const char *fname = luaL_optstring(L, 1, NULL); | 263 | const char *fname = luaL_optstring(L, 1, NULL); |
289 | return load_aux(L, luaL_loadfile(L, fname)); | 264 | const char *mode = luaL_optstring(L, 2, NULL); |
265 | int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ | ||
266 | int status = luaL_loadfilex(L, fname, mode); | ||
267 | return load_aux(L, status, env); | ||
290 | } | 268 | } |
291 | 269 | ||
292 | 270 | ||
293 | /* | 271 | /* |
272 | ** {====================================================== | ||
273 | ** Generic Read function | ||
274 | ** ======================================================= | ||
275 | */ | ||
276 | |||
277 | |||
278 | /* | ||
279 | ** reserved slot, above all arguments, to hold a copy of the returned | ||
280 | ** string to avoid it being collected while parsed. 'load' has four | ||
281 | ** optional arguments (chunk, source name, mode, and environment). | ||
282 | */ | ||
283 | #define RESERVEDSLOT 5 | ||
284 | |||
285 | |||
286 | /* | ||
294 | ** Reader for generic `load' function: `lua_load' uses the | 287 | ** Reader for generic `load' function: `lua_load' uses the |
295 | ** stack for internal stuff, so the reader cannot change the | 288 | ** stack for internal stuff, so the reader cannot change the |
296 | ** stack top. Instead, it keeps its resulting string in a | 289 | ** stack top. Instead, it keeps its resulting string in a |
297 | ** reserved slot inside the stack. | 290 | ** reserved slot inside the stack. |
298 | */ | 291 | */ |
299 | static const char *generic_reader (lua_State *L, void *ud, size_t *size) { | 292 | static const char *generic_reader (lua_State *L, void *ud, size_t *size) { |
300 | (void)ud; /* to avoid warnings */ | 293 | (void)(ud); /* not used */ |
301 | luaL_checkstack(L, 2, "too many nested functions"); | 294 | luaL_checkstack(L, 2, "too many nested functions"); |
302 | lua_pushvalue(L, 1); /* get function */ | 295 | lua_pushvalue(L, 1); /* get function */ |
303 | lua_call(L, 0, 1); /* call it */ | 296 | lua_call(L, 0, 1); /* call it */ |
304 | if (lua_isnil(L, -1)) { | 297 | if (lua_isnil(L, -1)) { |
298 | lua_pop(L, 1); /* pop result */ | ||
305 | *size = 0; | 299 | *size = 0; |
306 | return NULL; | 300 | return NULL; |
307 | } | 301 | } |
308 | else if (lua_isstring(L, -1)) { | 302 | else if (!lua_isstring(L, -1)) |
309 | lua_replace(L, 3); /* save string in a reserved stack slot */ | 303 | luaL_error(L, "reader function must return a string"); |
310 | return lua_tolstring(L, 3, size); | 304 | lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ |
311 | } | 305 | return lua_tolstring(L, RESERVEDSLOT, size); |
312 | else luaL_error(L, "reader function must return a string"); | ||
313 | return NULL; /* to avoid warnings */ | ||
314 | } | 306 | } |
315 | 307 | ||
316 | 308 | ||
317 | static int luaB_load (lua_State *L) { | 309 | static int luaB_load (lua_State *L) { |
318 | int status; | 310 | int status; |
319 | const char *cname = luaL_optstring(L, 2, "=(load)"); | 311 | size_t l; |
320 | luaL_checktype(L, 1, LUA_TFUNCTION); | 312 | const char *s = lua_tolstring(L, 1, &l); |
321 | lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ | 313 | const char *mode = luaL_optstring(L, 3, "bt"); |
322 | status = lua_load(L, generic_reader, NULL, cname); | 314 | int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ |
323 | return load_aux(L, status); | 315 | if (s != NULL) { /* loading a string? */ |
316 | const char *chunkname = luaL_optstring(L, 2, s); | ||
317 | status = luaL_loadbufferx(L, s, l, chunkname, mode); | ||
318 | } | ||
319 | else { /* loading from a reader function */ | ||
320 | const char *chunkname = luaL_optstring(L, 2, "=(load)"); | ||
321 | luaL_checktype(L, 1, LUA_TFUNCTION); | ||
322 | lua_settop(L, RESERVEDSLOT); /* create reserved slot */ | ||
323 | status = lua_load(L, generic_reader, NULL, chunkname, mode); | ||
324 | } | ||
325 | return load_aux(L, status, env); | ||
326 | } | ||
327 | |||
328 | /* }====================================================== */ | ||
329 | |||
330 | |||
331 | static int dofilecont (lua_State *L) { | ||
332 | return lua_gettop(L) - 1; | ||
324 | } | 333 | } |
325 | 334 | ||
326 | 335 | ||
327 | static int luaB_dofile (lua_State *L) { | 336 | static int luaB_dofile (lua_State *L) { |
328 | const char *fname = luaL_optstring(L, 1, NULL); | 337 | const char *fname = luaL_optstring(L, 1, NULL); |
329 | int n = lua_gettop(L); | 338 | lua_settop(L, 1); |
330 | if (luaL_loadfile(L, fname) != 0) lua_error(L); | 339 | if (luaL_loadfile(L, fname) != LUA_OK) |
331 | lua_call(L, 0, LUA_MULTRET); | 340 | return lua_error(L); |
332 | return lua_gettop(L) - n; | 341 | lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); |
342 | return dofilecont(L); | ||
333 | } | 343 | } |
334 | 344 | ||
335 | 345 | ||
336 | static int luaB_assert (lua_State *L) { | 346 | static int luaB_assert (lua_State *L) { |
337 | luaL_checkany(L, 1); | ||
338 | if (!lua_toboolean(L, 1)) | 347 | if (!lua_toboolean(L, 1)) |
339 | return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); | 348 | return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); |
340 | return lua_gettop(L); | 349 | return lua_gettop(L); |
341 | } | 350 | } |
342 | 351 | ||
343 | 352 | ||
344 | static int luaB_unpack (lua_State *L) { | ||
345 | int i, e, n; | ||
346 | luaL_checktype(L, 1, LUA_TTABLE); | ||
347 | i = luaL_optint(L, 2, 1); | ||
348 | e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); | ||
349 | if (i > e) return 0; /* empty range */ | ||
350 | n = e - i + 1; /* number of elements */ | ||
351 | if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ | ||
352 | return luaL_error(L, "too many results to unpack"); | ||
353 | lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ | ||
354 | while (i++ < e) /* push arg[i + 1...e] */ | ||
355 | lua_rawgeti(L, 1, i); | ||
356 | return n; | ||
357 | } | ||
358 | |||
359 | |||
360 | static int luaB_select (lua_State *L) { | 353 | static int luaB_select (lua_State *L) { |
361 | int n = lua_gettop(L); | 354 | int n = lua_gettop(L); |
362 | if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { | 355 | if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { |
@@ -373,75 +366,50 @@ static int luaB_select (lua_State *L) { | |||
373 | } | 366 | } |
374 | 367 | ||
375 | 368 | ||
369 | static int finishpcall (lua_State *L, int status) { | ||
370 | if (!lua_checkstack(L, 1)) { /* no space for extra boolean? */ | ||
371 | lua_settop(L, 0); /* create space for return values */ | ||
372 | lua_pushboolean(L, 0); | ||
373 | lua_pushstring(L, "stack overflow"); | ||
374 | return 2; /* return false, msg */ | ||
375 | } | ||
376 | lua_pushboolean(L, status); /* first result (status) */ | ||
377 | lua_replace(L, 1); /* put first result in first slot */ | ||
378 | return lua_gettop(L); | ||
379 | } | ||
380 | |||
381 | |||
382 | static int pcallcont (lua_State *L) { | ||
383 | int status = lua_getctx(L, NULL); | ||
384 | return finishpcall(L, (status == LUA_YIELD)); | ||
385 | } | ||
386 | |||
387 | |||
376 | static int luaB_pcall (lua_State *L) { | 388 | static int luaB_pcall (lua_State *L) { |
377 | int status; | 389 | int status; |
378 | luaL_checkany(L, 1); | 390 | luaL_checkany(L, 1); |
379 | status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); | 391 | lua_pushnil(L); |
380 | lua_pushboolean(L, (status == 0)); | 392 | lua_insert(L, 1); /* create space for status result */ |
381 | lua_insert(L, 1); | 393 | status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont); |
382 | return lua_gettop(L); /* return status + all results */ | 394 | return finishpcall(L, (status == LUA_OK)); |
383 | } | 395 | } |
384 | 396 | ||
385 | 397 | ||
386 | static int luaB_xpcall (lua_State *L) { | 398 | static int luaB_xpcall (lua_State *L) { |
387 | int status; | 399 | int status; |
388 | luaL_checkany(L, 2); | 400 | int n = lua_gettop(L); |
389 | lua_settop(L, 2); | 401 | luaL_argcheck(L, n >= 2, 2, "value expected"); |
390 | lua_insert(L, 1); /* put error function under function to be called */ | 402 | lua_pushvalue(L, 1); /* exchange function... */ |
391 | status = lua_pcall(L, 0, LUA_MULTRET, 1); | 403 | lua_copy(L, 2, 1); /* ...and error handler */ |
392 | lua_pushboolean(L, (status == 0)); | 404 | lua_replace(L, 2); |
393 | lua_replace(L, 1); | 405 | status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont); |
394 | return lua_gettop(L); /* return status + all results */ | 406 | return finishpcall(L, (status == LUA_OK)); |
395 | } | 407 | } |
396 | 408 | ||
397 | 409 | ||
398 | static int luaB_tostring (lua_State *L) { | 410 | static int luaB_tostring (lua_State *L) { |
399 | luaL_checkany(L, 1); | 411 | luaL_checkany(L, 1); |
400 | if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ | 412 | luaL_tolstring(L, 1, NULL); |
401 | return 1; /* use its value */ | ||
402 | switch (lua_type(L, 1)) { | ||
403 | case LUA_TNUMBER: | ||
404 | lua_pushstring(L, lua_tostring(L, 1)); | ||
405 | break; | ||
406 | case LUA_TSTRING: | ||
407 | lua_pushvalue(L, 1); | ||
408 | break; | ||
409 | case LUA_TBOOLEAN: | ||
410 | lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); | ||
411 | break; | ||
412 | case LUA_TNIL: | ||
413 | lua_pushliteral(L, "nil"); | ||
414 | break; | ||
415 | default: | ||
416 | lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); | ||
417 | break; | ||
418 | } | ||
419 | return 1; | ||
420 | } | ||
421 | |||
422 | |||
423 | static int luaB_newproxy (lua_State *L) { | ||
424 | lua_settop(L, 1); | ||
425 | lua_newuserdata(L, 0); /* create proxy */ | ||
426 | if (lua_toboolean(L, 1) == 0) | ||
427 | return 1; /* no metatable */ | ||
428 | else if (lua_isboolean(L, 1)) { | ||
429 | lua_newtable(L); /* create a new metatable `m' ... */ | ||
430 | lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ | ||
431 | lua_pushboolean(L, 1); | ||
432 | lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ | ||
433 | } | ||
434 | else { | ||
435 | int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ | ||
436 | if (lua_getmetatable(L, 1)) { | ||
437 | lua_rawget(L, lua_upvalueindex(1)); | ||
438 | validproxy = lua_toboolean(L, -1); | ||
439 | lua_pop(L, 1); /* remove value */ | ||
440 | } | ||
441 | luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); | ||
442 | lua_getmetatable(L, 1); /* metatable is valid; get it */ | ||
443 | } | ||
444 | lua_setmetatable(L, 2); | ||
445 | return 1; | 413 | return 1; |
446 | } | 414 | } |
447 | 415 | ||
@@ -451,207 +419,40 @@ static const luaL_Reg base_funcs[] = { | |||
451 | {"collectgarbage", luaB_collectgarbage}, | 419 | {"collectgarbage", luaB_collectgarbage}, |
452 | {"dofile", luaB_dofile}, | 420 | {"dofile", luaB_dofile}, |
453 | {"error", luaB_error}, | 421 | {"error", luaB_error}, |
454 | {"gcinfo", luaB_gcinfo}, | ||
455 | {"getfenv", luaB_getfenv}, | ||
456 | {"getmetatable", luaB_getmetatable}, | 422 | {"getmetatable", luaB_getmetatable}, |
423 | {"ipairs", luaB_ipairs}, | ||
457 | {"loadfile", luaB_loadfile}, | 424 | {"loadfile", luaB_loadfile}, |
458 | {"load", luaB_load}, | 425 | {"load", luaB_load}, |
459 | {"loadstring", luaB_loadstring}, | 426 | #if defined(LUA_COMPAT_LOADSTRING) |
427 | {"loadstring", luaB_load}, | ||
428 | #endif | ||
460 | {"next", luaB_next}, | 429 | {"next", luaB_next}, |
430 | {"pairs", luaB_pairs}, | ||
461 | {"pcall", luaB_pcall}, | 431 | {"pcall", luaB_pcall}, |
462 | #if 0 | ||
463 | {"print", luaB_print}, | 432 | {"print", luaB_print}, |
464 | #endif | ||
465 | {"rawequal", luaB_rawequal}, | 433 | {"rawequal", luaB_rawequal}, |
434 | {"rawlen", luaB_rawlen}, | ||
466 | {"rawget", luaB_rawget}, | 435 | {"rawget", luaB_rawget}, |
467 | {"rawset", luaB_rawset}, | 436 | {"rawset", luaB_rawset}, |
468 | {"select", luaB_select}, | 437 | {"select", luaB_select}, |
469 | {"setfenv", luaB_setfenv}, | ||
470 | {"setmetatable", luaB_setmetatable}, | 438 | {"setmetatable", luaB_setmetatable}, |
471 | {"tonumber", luaB_tonumber}, | 439 | {"tonumber", luaB_tonumber}, |
472 | {"tostring", luaB_tostring}, | 440 | {"tostring", luaB_tostring}, |
473 | {"type", luaB_type}, | 441 | {"type", luaB_type}, |
474 | {"unpack", luaB_unpack}, | ||
475 | {"xpcall", luaB_xpcall}, | 442 | {"xpcall", luaB_xpcall}, |
476 | {NULL, NULL} | 443 | {NULL, NULL} |
477 | }; | 444 | }; |
478 | 445 | ||
479 | 446 | ||
480 | /* | 447 | LUAMOD_API int luaopen_base (lua_State *L) { |
481 | ** {====================================================== | ||
482 | ** Coroutine library | ||
483 | ** ======================================================= | ||
484 | */ | ||
485 | |||
486 | #define CO_RUN 0 /* running */ | ||
487 | #define CO_SUS 1 /* suspended */ | ||
488 | #define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ | ||
489 | #define CO_DEAD 3 | ||
490 | |||
491 | static const char *const statnames[] = | ||
492 | {"running", "suspended", "normal", "dead"}; | ||
493 | |||
494 | static int costatus (lua_State *L, lua_State *co) { | ||
495 | if (L == co) return CO_RUN; | ||
496 | switch (lua_status(co)) { | ||
497 | case LUA_YIELD: | ||
498 | return CO_SUS; | ||
499 | case 0: { | ||
500 | lua_Debug ar; | ||
501 | if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ | ||
502 | return CO_NOR; /* it is running */ | ||
503 | else if (lua_gettop(co) == 0) | ||
504 | return CO_DEAD; | ||
505 | else | ||
506 | return CO_SUS; /* initial state */ | ||
507 | } | ||
508 | default: /* some error occured */ | ||
509 | return CO_DEAD; | ||
510 | } | ||
511 | } | ||
512 | |||
513 | |||
514 | static int luaB_costatus (lua_State *L) { | ||
515 | lua_State *co = lua_tothread(L, 1); | ||
516 | luaL_argcheck(L, co, 1, "coroutine expected"); | ||
517 | lua_pushstring(L, statnames[costatus(L, co)]); | ||
518 | return 1; | ||
519 | } | ||
520 | |||
521 | |||
522 | static int auxresume (lua_State *L, lua_State *co, int narg) { | ||
523 | int status = costatus(L, co); | ||
524 | if (!lua_checkstack(co, narg)) | ||
525 | luaL_error(L, "too many arguments to resume"); | ||
526 | if (status != CO_SUS) { | ||
527 | lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); | ||
528 | return -1; /* error flag */ | ||
529 | } | ||
530 | lua_xmove(L, co, narg); | ||
531 | lua_setlevel(L, co); | ||
532 | status = lua_resume(co, narg); | ||
533 | if (status == 0 || status == LUA_YIELD) { | ||
534 | int nres = lua_gettop(co); | ||
535 | if (!lua_checkstack(L, nres + 1)) | ||
536 | luaL_error(L, "too many results to resume"); | ||
537 | lua_xmove(co, L, nres); /* move yielded values */ | ||
538 | return nres; | ||
539 | } | ||
540 | else { | ||
541 | lua_xmove(co, L, 1); /* move error message */ | ||
542 | return -1; /* error flag */ | ||
543 | } | ||
544 | } | ||
545 | |||
546 | |||
547 | static int luaB_coresume (lua_State *L) { | ||
548 | lua_State *co = lua_tothread(L, 1); | ||
549 | int r; | ||
550 | luaL_argcheck(L, co, 1, "coroutine expected"); | ||
551 | r = auxresume(L, co, lua_gettop(L) - 1); | ||
552 | if (r < 0) { | ||
553 | lua_pushboolean(L, 0); | ||
554 | lua_insert(L, -2); | ||
555 | return 2; /* return false + error message */ | ||
556 | } | ||
557 | else { | ||
558 | lua_pushboolean(L, 1); | ||
559 | lua_insert(L, -(r + 1)); | ||
560 | return r + 1; /* return true + `resume' returns */ | ||
561 | } | ||
562 | } | ||
563 | |||
564 | |||
565 | static int luaB_auxwrap (lua_State *L) { | ||
566 | lua_State *co = lua_tothread(L, lua_upvalueindex(1)); | ||
567 | int r = auxresume(L, co, lua_gettop(L)); | ||
568 | if (r < 0) { | ||
569 | if (lua_isstring(L, -1)) { /* error object is a string? */ | ||
570 | luaL_where(L, 1); /* add extra info */ | ||
571 | lua_insert(L, -2); | ||
572 | lua_concat(L, 2); | ||
573 | } | ||
574 | lua_error(L); /* propagate error */ | ||
575 | } | ||
576 | return r; | ||
577 | } | ||
578 | |||
579 | |||
580 | static int luaB_cocreate (lua_State *L) { | ||
581 | lua_State *NL = lua_newthread(L); | ||
582 | luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, | ||
583 | "Lua function expected"); | ||
584 | lua_pushvalue(L, 1); /* move function to top */ | ||
585 | lua_xmove(L, NL, 1); /* move function from L to NL */ | ||
586 | return 1; | ||
587 | } | ||
588 | |||
589 | |||
590 | static int luaB_cowrap (lua_State *L) { | ||
591 | luaB_cocreate(L); | ||
592 | lua_pushcclosure(L, luaB_auxwrap, 1); | ||
593 | return 1; | ||
594 | } | ||
595 | |||
596 | |||
597 | static int luaB_yield (lua_State *L) { | ||
598 | return lua_yield(L, lua_gettop(L)); | ||
599 | } | ||
600 | |||
601 | |||
602 | static int luaB_corunning (lua_State *L) { | ||
603 | if (lua_pushthread(L)) | ||
604 | lua_pushnil(L); /* main thread is not a coroutine */ | ||
605 | return 1; | ||
606 | } | ||
607 | |||
608 | |||
609 | static const luaL_Reg co_funcs[] = { | ||
610 | {"create", luaB_cocreate}, | ||
611 | {"resume", luaB_coresume}, | ||
612 | {"running", luaB_corunning}, | ||
613 | {"status", luaB_costatus}, | ||
614 | {"wrap", luaB_cowrap}, | ||
615 | {"yield", luaB_yield}, | ||
616 | {NULL, NULL} | ||
617 | }; | ||
618 | |||
619 | /* }====================================================== */ | ||
620 | |||
621 | |||
622 | static void auxopen (lua_State *L, const char *name, | ||
623 | lua_CFunction f, lua_CFunction u) { | ||
624 | lua_pushcfunction(L, u); | ||
625 | lua_pushcclosure(L, f, 1); | ||
626 | lua_setfield(L, -2, name); | ||
627 | } | ||
628 | |||
629 | |||
630 | static void base_open (lua_State *L) { | ||
631 | /* set global _G */ | 448 | /* set global _G */ |
632 | lua_pushvalue(L, LUA_GLOBALSINDEX); | 449 | lua_pushglobaltable(L); |
633 | lua_setglobal(L, "_G"); | 450 | lua_pushglobaltable(L); |
451 | lua_setfield(L, -2, "_G"); | ||
634 | /* open lib into global table */ | 452 | /* open lib into global table */ |
635 | luaL_register(L, "_G", base_funcs); | 453 | luaL_setfuncs(L, base_funcs, 0); |
636 | lua_pushliteral(L, LUA_VERSION); | 454 | lua_pushliteral(L, LUA_VERSION); |
637 | lua_setglobal(L, "_VERSION"); /* set global _VERSION */ | 455 | lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */ |
638 | /* `ipairs' and `pairs' need auxliliary functions as upvalues */ | 456 | return 1; |
639 | auxopen(L, "ipairs", luaB_ipairs, ipairsaux); | ||
640 | auxopen(L, "pairs", luaB_pairs, luaB_next); | ||
641 | /* `newproxy' needs a weaktable as upvalue */ | ||
642 | lua_createtable(L, 0, 1); /* new table `w' */ | ||
643 | lua_pushvalue(L, -1); /* `w' will be its own metatable */ | ||
644 | lua_setmetatable(L, -2); | ||
645 | lua_pushliteral(L, "kv"); | ||
646 | lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ | ||
647 | lua_pushcclosure(L, luaB_newproxy, 1); | ||
648 | lua_setglobal(L, "newproxy"); /* set global `newproxy' */ | ||
649 | } | ||
650 | |||
651 | |||
652 | LUALIB_API int luaopen_base (lua_State *L) { | ||
653 | base_open(L); | ||
654 | luaL_register(L, LUA_COLIBNAME, co_funcs); | ||
655 | return 2; | ||
656 | } | 457 | } |
657 | 458 | ||
diff --git a/apps/plugins/lua/lbitlib.c b/apps/plugins/lua/lbitlib.c index 76c8d1d39b..31c7b66f12 100644 --- a/apps/plugins/lua/lbitlib.c +++ b/apps/plugins/lua/lbitlib.c | |||
@@ -1,126 +1,212 @@ | |||
1 | /* Bitwise operations library */ | 1 | /* |
2 | /* (c) Reuben Thomas 2000-2008 */ | 2 | ** $Id: lbitlib.c,v 1.18.1.2 2013/07/09 18:01:41 roberto Exp $ |
3 | /* bitlib is copyright Reuben Thomas 2000-2008, and is released under the MIT | 3 | ** Standard library for bitwise operations |
4 | license, like Lua (see http://www.lua.org/copyright.html; it's | 4 | ** See Copyright Notice in lua.h |
5 | basically the same as the BSD license). There is no warranty. */ | 5 | */ |
6 | 6 | ||
7 | #include "config.h" | 7 | #define lbitlib_c |
8 | #define LUA_LIB | ||
8 | 9 | ||
9 | #include "lua.h" | 10 | #include "lua.h" |
11 | |||
10 | #include "lauxlib.h" | 12 | #include "lauxlib.h" |
11 | #include "lualib.h" | 13 | #include "lualib.h" |
12 | #include <limits.h> | ||
13 | 14 | ||
14 | 15 | ||
15 | /* FIXME: Assume lua_Integer is ptrdiff_t */ | 16 | /* number of bits to consider in a number */ |
16 | #define LUA_INTEGER_MAX INTPTR_MAX | 17 | #if !defined(LUA_NBITS) |
17 | #define LUA_INTEGER_MIN INTPTR_MIN | 18 | #define LUA_NBITS 32 |
19 | #endif | ||
18 | 20 | ||
19 | /* FIXME: Assume size_t is an unsigned lua_Integer */ | ||
20 | typedef size_t lua_UInteger; | ||
21 | #define LUA_UINTEGER_MAX UINT_MAX | ||
22 | 21 | ||
22 | #define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) | ||
23 | 23 | ||
24 | /* Bit type size and limits */ | 24 | /* macro to trim extra bits */ |
25 | #define trim(x) ((x) & ALLONES) | ||
25 | 26 | ||
26 | #define BIT_BITS (CHAR_BIT * sizeof(lua_Integer)) | ||
27 | 27 | ||
28 | /* This code may give warnings if BITLIB_FLOAT_* are too big to fit in | 28 | /* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ |
29 | long, but that doesn't matter since in that case they won't be | 29 | #define mask(n) (~((ALLONES << 1) << ((n) - 1))) |
30 | used. */ | ||
31 | #define BIT_MAX (LUA_INTEGER_MAX) | ||
32 | 30 | ||
33 | #define BIT_MIN (LUA_INTEGER_MIN) | ||
34 | 31 | ||
35 | #define BIT_UMAX (LUA_UINTEGER_MAX) | 32 | typedef lua_Unsigned b_uint; |
36 | 33 | ||
37 | 34 | ||
38 | /* Define TOBIT to get a bit value */ | ||
39 | #ifdef BUILTIN_CAST | ||
40 | #define | ||
41 | #define TOBIT(L, n, res) \ | ||
42 | ((void)(res), luaL_checkinteger((L), (n))) | ||
43 | #else | ||
44 | 35 | ||
45 | #define TOBIT(L, n, res) \ | 36 | static b_uint andaux (lua_State *L) { |
46 | ((lua_Integer)(((res) = luaL_checknumber(L, (n)) % BIT_UMAX), \ | 37 | int i, n = lua_gettop(L); |
47 | (res) > BIT_MAX ? ((res) -= BIT_UMAX, (res) -= 1) : \ | 38 | b_uint r = ~(b_uint)0; |
48 | ((res) < BIT_MIN ? ((res) += BIT_UMAX, (res) += 1) : (res)))) | 39 | for (i = 1; i <= n; i++) |
49 | #endif | 40 | r &= luaL_checkunsigned(L, i); |
41 | return trim(r); | ||
42 | } | ||
50 | 43 | ||
51 | 44 | ||
52 | #define BIT_TRUNCATE(i) \ | 45 | static int b_and (lua_State *L) { |
53 | ((i) & BIT_UMAX) | 46 | b_uint r = andaux(L); |
47 | lua_pushunsigned(L, r); | ||
48 | return 1; | ||
49 | } | ||
54 | 50 | ||
55 | 51 | ||
56 | /* Operations | 52 | static int b_test (lua_State *L) { |
53 | b_uint r = andaux(L); | ||
54 | lua_pushboolean(L, r != 0); | ||
55 | return 1; | ||
56 | } | ||
57 | 57 | ||
58 | The macros MONADIC and VARIADIC only deal with bitwise operations. | ||
59 | 58 | ||
60 | LOGICAL_SHIFT truncates its left-hand operand before shifting so | 59 | static int b_or (lua_State *L) { |
61 | that any extra bits at the most-significant end are not shifted | 60 | int i, n = lua_gettop(L); |
62 | into the result. | 61 | b_uint r = 0; |
62 | for (i = 1; i <= n; i++) | ||
63 | r |= luaL_checkunsigned(L, i); | ||
64 | lua_pushunsigned(L, trim(r)); | ||
65 | return 1; | ||
66 | } | ||
63 | 67 | ||
64 | ARITHMETIC_SHIFT does not truncate its left-hand operand, so that | ||
65 | the sign bits are not removed and right shift work properly. | ||
66 | */ | ||
67 | |||
68 | #define MONADIC(name, op) \ | ||
69 | static int bit_ ## name(lua_State *L) { \ | ||
70 | lua_Number f; \ | ||
71 | lua_pushinteger(L, BIT_TRUNCATE(op TOBIT(L, 1, f))); \ | ||
72 | return 1; \ | ||
73 | } | ||
74 | 68 | ||
75 | #define VARIADIC(name, op) \ | 69 | static int b_xor (lua_State *L) { |
76 | static int bit_ ## name(lua_State *L) { \ | 70 | int i, n = lua_gettop(L); |
77 | lua_Number f; \ | 71 | b_uint r = 0; |
78 | int n = lua_gettop(L), i; \ | 72 | for (i = 1; i <= n; i++) |
79 | lua_Integer w = TOBIT(L, 1, f); \ | 73 | r ^= luaL_checkunsigned(L, i); |
80 | for (i = 2; i <= n; i++) \ | 74 | lua_pushunsigned(L, trim(r)); |
81 | w op TOBIT(L, i, f); \ | 75 | return 1; |
82 | lua_pushinteger(L, BIT_TRUNCATE(w)); \ | 76 | } |
83 | return 1; \ | ||
84 | } | ||
85 | 77 | ||
86 | #define LOGICAL_SHIFT(name, op) \ | 78 | |
87 | static int bit_ ## name(lua_State *L) { \ | 79 | static int b_not (lua_State *L) { |
88 | lua_Number f; \ | 80 | b_uint r = ~luaL_checkunsigned(L, 1); |
89 | lua_pushinteger(L, BIT_TRUNCATE(BIT_TRUNCATE((lua_UInteger)TOBIT(L, 1, f)) op \ | 81 | lua_pushunsigned(L, trim(r)); |
90 | (unsigned)luaL_checknumber(L, 2))); \ | 82 | return 1; |
91 | return 1; \ | 83 | } |
84 | |||
85 | |||
86 | static int b_shift (lua_State *L, b_uint r, int i) { | ||
87 | if (i < 0) { /* shift right? */ | ||
88 | i = -i; | ||
89 | r = trim(r); | ||
90 | if (i >= LUA_NBITS) r = 0; | ||
91 | else r >>= i; | ||
92 | } | ||
93 | else { /* shift left */ | ||
94 | if (i >= LUA_NBITS) r = 0; | ||
95 | else r <<= i; | ||
96 | r = trim(r); | ||
92 | } | 97 | } |
98 | lua_pushunsigned(L, r); | ||
99 | return 1; | ||
100 | } | ||
101 | |||
102 | |||
103 | static int b_lshift (lua_State *L) { | ||
104 | return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2)); | ||
105 | } | ||
106 | |||
107 | |||
108 | static int b_rshift (lua_State *L) { | ||
109 | return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2)); | ||
110 | } | ||
93 | 111 | ||
94 | #define ARITHMETIC_SHIFT(name, op) \ | 112 | |
95 | static int bit_ ## name(lua_State *L) { \ | 113 | static int b_arshift (lua_State *L) { |
96 | lua_Number f; \ | 114 | b_uint r = luaL_checkunsigned(L, 1); |
97 | lua_pushinteger(L, BIT_TRUNCATE((lua_Integer)TOBIT(L, 1, f) op \ | 115 | int i = luaL_checkint(L, 2); |
98 | (unsigned)luaL_checknumber(L, 2))); \ | 116 | if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1)))) |
99 | return 1; \ | 117 | return b_shift(L, r, -i); |
118 | else { /* arithmetic shift for 'negative' number */ | ||
119 | if (i >= LUA_NBITS) r = ALLONES; | ||
120 | else | ||
121 | r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */ | ||
122 | lua_pushunsigned(L, r); | ||
123 | return 1; | ||
100 | } | 124 | } |
125 | } | ||
126 | |||
127 | |||
128 | static int b_rot (lua_State *L, int i) { | ||
129 | b_uint r = luaL_checkunsigned(L, 1); | ||
130 | i &= (LUA_NBITS - 1); /* i = i % NBITS */ | ||
131 | r = trim(r); | ||
132 | if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */ | ||
133 | r = (r << i) | (r >> (LUA_NBITS - i)); | ||
134 | lua_pushunsigned(L, trim(r)); | ||
135 | return 1; | ||
136 | } | ||
137 | |||
101 | 138 | ||
102 | MONADIC(bnot, ~) | 139 | static int b_lrot (lua_State *L) { |
103 | VARIADIC(band, &=) | 140 | return b_rot(L, luaL_checkint(L, 2)); |
104 | VARIADIC(bor, |=) | 141 | } |
105 | VARIADIC(bxor, ^=) | 142 | |
106 | ARITHMETIC_SHIFT(lshift, <<) | 143 | |
107 | LOGICAL_SHIFT(rshift, >>) | 144 | static int b_rrot (lua_State *L) { |
108 | ARITHMETIC_SHIFT(arshift, >>) | 145 | return b_rot(L, -luaL_checkint(L, 2)); |
109 | 146 | } | |
110 | static const struct luaL_reg bitlib[] = { | 147 | |
111 | {"bnot", bit_bnot}, | 148 | |
112 | {"band", bit_band}, | 149 | /* |
113 | {"bor", bit_bor}, | 150 | ** get field and width arguments for field-manipulation functions, |
114 | {"bxor", bit_bxor}, | 151 | ** checking whether they are valid. |
115 | {"lshift", bit_lshift}, | 152 | ** ('luaL_error' called without 'return' to avoid later warnings about |
116 | {"rshift", bit_rshift}, | 153 | ** 'width' being used uninitialized.) |
117 | {"arshift", bit_arshift}, | 154 | */ |
155 | static int fieldargs (lua_State *L, int farg, int *width) { | ||
156 | int f = luaL_checkint(L, farg); | ||
157 | int w = luaL_optint(L, farg + 1, 1); | ||
158 | luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); | ||
159 | luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); | ||
160 | if (f + w > LUA_NBITS) | ||
161 | luaL_error(L, "trying to access non-existent bits"); | ||
162 | *width = w; | ||
163 | return f; | ||
164 | } | ||
165 | |||
166 | |||
167 | static int b_extract (lua_State *L) { | ||
168 | int w; | ||
169 | b_uint r = luaL_checkunsigned(L, 1); | ||
170 | int f = fieldargs(L, 2, &w); | ||
171 | r = (r >> f) & mask(w); | ||
172 | lua_pushunsigned(L, r); | ||
173 | return 1; | ||
174 | } | ||
175 | |||
176 | |||
177 | static int b_replace (lua_State *L) { | ||
178 | int w; | ||
179 | b_uint r = luaL_checkunsigned(L, 1); | ||
180 | b_uint v = luaL_checkunsigned(L, 2); | ||
181 | int f = fieldargs(L, 3, &w); | ||
182 | int m = mask(w); | ||
183 | v &= m; /* erase bits outside given width */ | ||
184 | r = (r & ~(m << f)) | (v << f); | ||
185 | lua_pushunsigned(L, r); | ||
186 | return 1; | ||
187 | } | ||
188 | |||
189 | |||
190 | static const luaL_Reg bitlib[] = { | ||
191 | {"arshift", b_arshift}, | ||
192 | {"band", b_and}, | ||
193 | {"bnot", b_not}, | ||
194 | {"bor", b_or}, | ||
195 | {"bxor", b_xor}, | ||
196 | {"btest", b_test}, | ||
197 | {"extract", b_extract}, | ||
198 | {"lrotate", b_lrot}, | ||
199 | {"lshift", b_lshift}, | ||
200 | {"replace", b_replace}, | ||
201 | {"rrotate", b_rrot}, | ||
202 | {"rshift", b_rshift}, | ||
118 | {NULL, NULL} | 203 | {NULL, NULL} |
119 | }; | 204 | }; |
120 | 205 | ||
121 | LUALIB_API int luaopen_bit (lua_State *L) { | 206 | |
122 | luaL_register(L, "bit", bitlib); | 207 | |
123 | lua_pushnumber(L, BIT_BITS); | 208 | LUAMOD_API int luaopen_bit32 (lua_State *L) { |
124 | lua_setfield(L, -2, "bits"); | 209 | luaL_newlib(L, bitlib); |
125 | return 1; | 210 | return 1; |
126 | } | 211 | } |
212 | |||
diff --git a/apps/plugins/lua/lcode.c b/apps/plugins/lua/lcode.c index cff626b7fa..820b95c0e1 100644 --- a/apps/plugins/lua/lcode.c +++ b/apps/plugins/lua/lcode.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ | 2 | ** $Id: lcode.c,v 2.62.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -21,7 +21,9 @@ | |||
21 | #include "lobject.h" | 21 | #include "lobject.h" |
22 | #include "lopcodes.h" | 22 | #include "lopcodes.h" |
23 | #include "lparser.h" | 23 | #include "lparser.h" |
24 | #include "lstring.h" | ||
24 | #include "ltable.h" | 25 | #include "ltable.h" |
26 | #include "lvm.h" | ||
25 | 27 | ||
26 | 28 | ||
27 | #define hasjumps(e) ((e)->t != (e)->f) | 29 | #define hasjumps(e) ((e)->t != (e)->f) |
@@ -34,25 +36,23 @@ static int isnumeral(expdesc *e) { | |||
34 | 36 | ||
35 | void luaK_nil (FuncState *fs, int from, int n) { | 37 | void luaK_nil (FuncState *fs, int from, int n) { |
36 | Instruction *previous; | 38 | Instruction *previous; |
39 | int l = from + n - 1; /* last register to set nil */ | ||
37 | if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ | 40 | if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ |
38 | if (fs->pc == 0) { /* function start? */ | 41 | previous = &fs->f->code[fs->pc-1]; |
39 | if (from >= fs->nactvar) | 42 | if (GET_OPCODE(*previous) == OP_LOADNIL) { |
40 | return; /* positions are already clean */ | 43 | int pfrom = GETARG_A(*previous); |
41 | } | 44 | int pl = pfrom + GETARG_B(*previous); |
42 | else { | 45 | if ((pfrom <= from && from <= pl + 1) || |
43 | previous = &fs->f->code[fs->pc-1]; | 46 | (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ |
44 | if (GET_OPCODE(*previous) == OP_LOADNIL) { | 47 | if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ |
45 | int pfrom = GETARG_A(*previous); | 48 | if (pl > l) l = pl; /* l = max(l, pl) */ |
46 | int pto = GETARG_B(*previous); | 49 | SETARG_A(*previous, from); |
47 | if (pfrom <= from && from <= pto+1) { /* can connect both? */ | 50 | SETARG_B(*previous, l - from); |
48 | if (from+n-1 > pto) | 51 | return; |
49 | SETARG_B(*previous, from+n-1); | ||
50 | return; | ||
51 | } | ||
52 | } | 52 | } |
53 | } | 53 | } /* else go through */ |
54 | } | 54 | } |
55 | luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ | 55 | luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ |
56 | } | 56 | } |
57 | 57 | ||
58 | 58 | ||
@@ -176,6 +176,19 @@ void luaK_patchlist (FuncState *fs, int list, int target) { | |||
176 | } | 176 | } |
177 | 177 | ||
178 | 178 | ||
179 | LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) { | ||
180 | level++; /* argument is +1 to reserve 0 as non-op */ | ||
181 | while (list != NO_JUMP) { | ||
182 | int next = getjump(fs, list); | ||
183 | lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && | ||
184 | (GETARG_A(fs->f->code[list]) == 0 || | ||
185 | GETARG_A(fs->f->code[list]) >= level)); | ||
186 | SETARG_A(fs->f->code[list], level); | ||
187 | list = next; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | |||
179 | void luaK_patchtohere (FuncState *fs, int list) { | 192 | void luaK_patchtohere (FuncState *fs, int list) { |
180 | luaK_getlabel(fs); | 193 | luaK_getlabel(fs); |
181 | luaK_concat(fs, &fs->jpc, list); | 194 | luaK_concat(fs, &fs->jpc, list); |
@@ -196,6 +209,55 @@ void luaK_concat (FuncState *fs, int *l1, int l2) { | |||
196 | } | 209 | } |
197 | 210 | ||
198 | 211 | ||
212 | static int luaK_code (FuncState *fs, Instruction i) { | ||
213 | Proto *f = fs->f; | ||
214 | dischargejpc(fs); /* `pc' will change */ | ||
215 | /* put new instruction in code array */ | ||
216 | luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, | ||
217 | MAX_INT, "opcodes"); | ||
218 | f->code[fs->pc] = i; | ||
219 | /* save corresponding line information */ | ||
220 | luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, | ||
221 | MAX_INT, "opcodes"); | ||
222 | f->lineinfo[fs->pc] = fs->ls->lastline; | ||
223 | return fs->pc++; | ||
224 | } | ||
225 | |||
226 | |||
227 | int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { | ||
228 | lua_assert(getOpMode(o) == iABC); | ||
229 | lua_assert(getBMode(o) != OpArgN || b == 0); | ||
230 | lua_assert(getCMode(o) != OpArgN || c == 0); | ||
231 | lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); | ||
232 | return luaK_code(fs, CREATE_ABC(o, a, b, c)); | ||
233 | } | ||
234 | |||
235 | |||
236 | int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { | ||
237 | lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); | ||
238 | lua_assert(getCMode(o) == OpArgN); | ||
239 | lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); | ||
240 | return luaK_code(fs, CREATE_ABx(o, a, bc)); | ||
241 | } | ||
242 | |||
243 | |||
244 | static int codeextraarg (FuncState *fs, int a) { | ||
245 | lua_assert(a <= MAXARG_Ax); | ||
246 | return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); | ||
247 | } | ||
248 | |||
249 | |||
250 | int luaK_codek (FuncState *fs, int reg, int k) { | ||
251 | if (k <= MAXARG_Bx) | ||
252 | return luaK_codeABx(fs, OP_LOADK, reg, k); | ||
253 | else { | ||
254 | int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); | ||
255 | codeextraarg(fs, k); | ||
256 | return p; | ||
257 | } | ||
258 | } | ||
259 | |||
260 | |||
199 | void luaK_checkstack (FuncState *fs, int n) { | 261 | void luaK_checkstack (FuncState *fs, int n) { |
200 | int newstack = fs->freereg + n; | 262 | int newstack = fs->freereg + n; |
201 | if (newstack > fs->f->maxstacksize) { | 263 | if (newstack > fs->f->maxstacksize) { |
@@ -222,42 +284,59 @@ static void freereg (FuncState *fs, int reg) { | |||
222 | 284 | ||
223 | static void freeexp (FuncState *fs, expdesc *e) { | 285 | static void freeexp (FuncState *fs, expdesc *e) { |
224 | if (e->k == VNONRELOC) | 286 | if (e->k == VNONRELOC) |
225 | freereg(fs, e->u.s.info); | 287 | freereg(fs, e->u.info); |
226 | } | 288 | } |
227 | 289 | ||
228 | 290 | ||
229 | static int addk (FuncState *fs, TValue *k, TValue *v) { | 291 | static int addk (FuncState *fs, TValue *key, TValue *v) { |
230 | lua_State *L = fs->L; | 292 | lua_State *L = fs->ls->L; |
231 | TValue *idx = luaH_set(L, fs->h, k); | 293 | TValue *idx = luaH_set(L, fs->h, key); |
232 | Proto *f = fs->f; | 294 | Proto *f = fs->f; |
233 | int oldsize = f->sizek; | 295 | int k, oldsize; |
234 | if (ttisnumber(idx)) { | 296 | if (ttisnumber(idx)) { |
235 | lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); | 297 | lua_Number n = nvalue(idx); |
236 | return cast_int(nvalue(idx)); | 298 | lua_number2int(k, n); |
237 | } | 299 | if (luaV_rawequalobj(&f->k[k], v)) |
238 | else { /* constant not found; create a new entry */ | 300 | return k; |
239 | setnvalue(idx, cast_num(fs->nk)); | 301 | /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); |
240 | luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, | 302 | go through and create a new entry for this value */ |
241 | MAXARG_Bx, "constant table overflow"); | ||
242 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); | ||
243 | setobj(L, &f->k[fs->nk], v); | ||
244 | luaC_barrier(L, f, v); | ||
245 | return fs->nk++; | ||
246 | } | 303 | } |
304 | /* constant not found; create a new entry */ | ||
305 | oldsize = f->sizek; | ||
306 | k = fs->nk; | ||
307 | /* numerical value does not need GC barrier; | ||
308 | table has no metatable, so it does not need to invalidate cache */ | ||
309 | setnvalue(idx, cast_num(k)); | ||
310 | luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); | ||
311 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); | ||
312 | setobj(L, &f->k[k], v); | ||
313 | fs->nk++; | ||
314 | luaC_barrier(L, f, v); | ||
315 | return k; | ||
247 | } | 316 | } |
248 | 317 | ||
249 | 318 | ||
250 | int luaK_stringK (FuncState *fs, TString *s) { | 319 | int luaK_stringK (FuncState *fs, TString *s) { |
251 | TValue o; | 320 | TValue o; |
252 | setsvalue(fs->L, &o, s); | 321 | setsvalue(fs->ls->L, &o, s); |
253 | return addk(fs, &o, &o); | 322 | return addk(fs, &o, &o); |
254 | } | 323 | } |
255 | 324 | ||
256 | 325 | ||
257 | int luaK_numberK (FuncState *fs, lua_Number r) { | 326 | int luaK_numberK (FuncState *fs, lua_Number r) { |
327 | int n; | ||
328 | lua_State *L = fs->ls->L; | ||
258 | TValue o; | 329 | TValue o; |
259 | setnvalue(&o, r); | 330 | setnvalue(&o, r); |
260 | return addk(fs, &o, &o); | 331 | if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ |
332 | /* use raw representation as key to avoid numeric problems */ | ||
333 | setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r))); | ||
334 | n = addk(fs, L->top - 1, &o); | ||
335 | L->top--; | ||
336 | } | ||
337 | else | ||
338 | n = addk(fs, &o, &o); /* regular case */ | ||
339 | return n; | ||
261 | } | 340 | } |
262 | 341 | ||
263 | 342 | ||
@@ -272,7 +351,7 @@ static int nilK (FuncState *fs) { | |||
272 | TValue k, v; | 351 | TValue k, v; |
273 | setnilvalue(&v); | 352 | setnilvalue(&v); |
274 | /* cannot use nil as key; instead use table itself to represent nil */ | 353 | /* cannot use nil as key; instead use table itself to represent nil */ |
275 | sethvalue(fs->L, &k, fs->h); | 354 | sethvalue(fs->ls->L, &k, fs->h); |
276 | return addk(fs, &k, &v); | 355 | return addk(fs, &k, &v); |
277 | } | 356 | } |
278 | 357 | ||
@@ -292,7 +371,7 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { | |||
292 | void luaK_setoneret (FuncState *fs, expdesc *e) { | 371 | void luaK_setoneret (FuncState *fs, expdesc *e) { |
293 | if (e->k == VCALL) { /* expression is an open function call? */ | 372 | if (e->k == VCALL) { /* expression is an open function call? */ |
294 | e->k = VNONRELOC; | 373 | e->k = VNONRELOC; |
295 | e->u.s.info = GETARG_A(getcode(fs, e)); | 374 | e->u.info = GETARG_A(getcode(fs, e)); |
296 | } | 375 | } |
297 | else if (e->k == VVARARG) { | 376 | else if (e->k == VVARARG) { |
298 | SETARG_B(getcode(fs, e), 2); | 377 | SETARG_B(getcode(fs, e), 2); |
@@ -308,19 +387,18 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
308 | break; | 387 | break; |
309 | } | 388 | } |
310 | case VUPVAL: { | 389 | case VUPVAL: { |
311 | e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); | 390 | e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); |
312 | e->k = VRELOCABLE; | ||
313 | break; | ||
314 | } | ||
315 | case VGLOBAL: { | ||
316 | e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); | ||
317 | e->k = VRELOCABLE; | 391 | e->k = VRELOCABLE; |
318 | break; | 392 | break; |
319 | } | 393 | } |
320 | case VINDEXED: { | 394 | case VINDEXED: { |
321 | freereg(fs, e->u.s.aux); | 395 | OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ |
322 | freereg(fs, e->u.s.info); | 396 | freereg(fs, e->u.ind.idx); |
323 | e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); | 397 | if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ |
398 | freereg(fs, e->u.ind.t); | ||
399 | op = OP_GETTABLE; | ||
400 | } | ||
401 | e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); | ||
324 | e->k = VRELOCABLE; | 402 | e->k = VRELOCABLE; |
325 | break; | 403 | break; |
326 | } | 404 | } |
@@ -347,16 +425,16 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
347 | luaK_nil(fs, reg, 1); | 425 | luaK_nil(fs, reg, 1); |
348 | break; | 426 | break; |
349 | } | 427 | } |
350 | case VFALSE: case VTRUE: { | 428 | case VFALSE: case VTRUE: { |
351 | luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); | 429 | luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); |
352 | break; | 430 | break; |
353 | } | 431 | } |
354 | case VK: { | 432 | case VK: { |
355 | luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); | 433 | luaK_codek(fs, reg, e->u.info); |
356 | break; | 434 | break; |
357 | } | 435 | } |
358 | case VKNUM: { | 436 | case VKNUM: { |
359 | luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); | 437 | luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); |
360 | break; | 438 | break; |
361 | } | 439 | } |
362 | case VRELOCABLE: { | 440 | case VRELOCABLE: { |
@@ -365,8 +443,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
365 | break; | 443 | break; |
366 | } | 444 | } |
367 | case VNONRELOC: { | 445 | case VNONRELOC: { |
368 | if (reg != e->u.s.info) | 446 | if (reg != e->u.info) |
369 | luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); | 447 | luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); |
370 | break; | 448 | break; |
371 | } | 449 | } |
372 | default: { | 450 | default: { |
@@ -374,7 +452,7 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
374 | return; /* nothing to do... */ | 452 | return; /* nothing to do... */ |
375 | } | 453 | } |
376 | } | 454 | } |
377 | e->u.s.info = reg; | 455 | e->u.info = reg; |
378 | e->k = VNONRELOC; | 456 | e->k = VNONRELOC; |
379 | } | 457 | } |
380 | 458 | ||
@@ -390,7 +468,7 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) { | |||
390 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { | 468 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { |
391 | discharge2reg(fs, e, reg); | 469 | discharge2reg(fs, e, reg); |
392 | if (e->k == VJMP) | 470 | if (e->k == VJMP) |
393 | luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ | 471 | luaK_concat(fs, &e->t, e->u.info); /* put this jump in `t' list */ |
394 | if (hasjumps(e)) { | 472 | if (hasjumps(e)) { |
395 | int final; /* position after whole expression */ | 473 | int final; /* position after whole expression */ |
396 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ | 474 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ |
@@ -406,7 +484,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { | |||
406 | patchlistaux(fs, e->t, final, reg, p_t); | 484 | patchlistaux(fs, e->t, final, reg, p_t); |
407 | } | 485 | } |
408 | e->f = e->t = NO_JUMP; | 486 | e->f = e->t = NO_JUMP; |
409 | e->u.s.info = reg; | 487 | e->u.info = reg; |
410 | e->k = VNONRELOC; | 488 | e->k = VNONRELOC; |
411 | } | 489 | } |
412 | 490 | ||
@@ -422,14 +500,20 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) { | |||
422 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | 500 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { |
423 | luaK_dischargevars(fs, e); | 501 | luaK_dischargevars(fs, e); |
424 | if (e->k == VNONRELOC) { | 502 | if (e->k == VNONRELOC) { |
425 | if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ | 503 | if (!hasjumps(e)) return e->u.info; /* exp is already in a register */ |
426 | if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ | 504 | if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ |
427 | exp2reg(fs, e, e->u.s.info); /* put value on it */ | 505 | exp2reg(fs, e, e->u.info); /* put value on it */ |
428 | return e->u.s.info; | 506 | return e->u.info; |
429 | } | 507 | } |
430 | } | 508 | } |
431 | luaK_exp2nextreg(fs, e); /* default */ | 509 | luaK_exp2nextreg(fs, e); /* default */ |
432 | return e->u.s.info; | 510 | return e->u.info; |
511 | } | ||
512 | |||
513 | |||
514 | void luaK_exp2anyregup (FuncState *fs, expdesc *e) { | ||
515 | if (e->k != VUPVAL || hasjumps(e)) | ||
516 | luaK_exp2anyreg(fs, e); | ||
433 | } | 517 | } |
434 | 518 | ||
435 | 519 | ||
@@ -444,22 +528,24 @@ void luaK_exp2val (FuncState *fs, expdesc *e) { | |||
444 | int luaK_exp2RK (FuncState *fs, expdesc *e) { | 528 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
445 | luaK_exp2val(fs, e); | 529 | luaK_exp2val(fs, e); |
446 | switch (e->k) { | 530 | switch (e->k) { |
447 | case VKNUM: | ||
448 | case VTRUE: | 531 | case VTRUE: |
449 | case VFALSE: | 532 | case VFALSE: |
450 | case VNIL: { | 533 | case VNIL: { |
451 | if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ | 534 | if (fs->nk <= MAXINDEXRK) { /* constant fits in RK operand? */ |
452 | e->u.s.info = (e->k == VNIL) ? nilK(fs) : | 535 | e->u.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE)); |
453 | (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : | ||
454 | boolK(fs, (e->k == VTRUE)); | ||
455 | e->k = VK; | 536 | e->k = VK; |
456 | return RKASK(e->u.s.info); | 537 | return RKASK(e->u.info); |
457 | } | 538 | } |
458 | else break; | 539 | else break; |
459 | } | 540 | } |
541 | case VKNUM: { | ||
542 | e->u.info = luaK_numberK(fs, e->u.nval); | ||
543 | e->k = VK; | ||
544 | /* go through */ | ||
545 | } | ||
460 | case VK: { | 546 | case VK: { |
461 | if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ | 547 | if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */ |
462 | return RKASK(e->u.s.info); | 548 | return RKASK(e->u.info); |
463 | else break; | 549 | else break; |
464 | } | 550 | } |
465 | default: break; | 551 | default: break; |
@@ -473,22 +559,18 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { | |||
473 | switch (var->k) { | 559 | switch (var->k) { |
474 | case VLOCAL: { | 560 | case VLOCAL: { |
475 | freeexp(fs, ex); | 561 | freeexp(fs, ex); |
476 | exp2reg(fs, ex, var->u.s.info); | 562 | exp2reg(fs, ex, var->u.info); |
477 | return; | 563 | return; |
478 | } | 564 | } |
479 | case VUPVAL: { | 565 | case VUPVAL: { |
480 | int e = luaK_exp2anyreg(fs, ex); | 566 | int e = luaK_exp2anyreg(fs, ex); |
481 | luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); | 567 | luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); |
482 | break; | ||
483 | } | ||
484 | case VGLOBAL: { | ||
485 | int e = luaK_exp2anyreg(fs, ex); | ||
486 | luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); | ||
487 | break; | 568 | break; |
488 | } | 569 | } |
489 | case VINDEXED: { | 570 | case VINDEXED: { |
571 | OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; | ||
490 | int e = luaK_exp2RK(fs, ex); | 572 | int e = luaK_exp2RK(fs, ex); |
491 | luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); | 573 | luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); |
492 | break; | 574 | break; |
493 | } | 575 | } |
494 | default: { | 576 | default: { |
@@ -501,20 +583,20 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { | |||
501 | 583 | ||
502 | 584 | ||
503 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { | 585 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { |
504 | int func; | 586 | int ereg; |
505 | luaK_exp2anyreg(fs, e); | 587 | luaK_exp2anyreg(fs, e); |
588 | ereg = e->u.info; /* register where 'e' was placed */ | ||
506 | freeexp(fs, e); | 589 | freeexp(fs, e); |
507 | func = fs->freereg; | 590 | e->u.info = fs->freereg; /* base register for op_self */ |
508 | luaK_reserveregs(fs, 2); | ||
509 | luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); | ||
510 | freeexp(fs, key); | ||
511 | e->u.s.info = func; | ||
512 | e->k = VNONRELOC; | 591 | e->k = VNONRELOC; |
592 | luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ | ||
593 | luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key)); | ||
594 | freeexp(fs, key); | ||
513 | } | 595 | } |
514 | 596 | ||
515 | 597 | ||
516 | static void invertjump (FuncState *fs, expdesc *e) { | 598 | static void invertjump (FuncState *fs, expdesc *e) { |
517 | Instruction *pc = getjumpcontrol(fs, e->u.s.info); | 599 | Instruction *pc = getjumpcontrol(fs, e->u.info); |
518 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && | 600 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && |
519 | GET_OPCODE(*pc) != OP_TEST); | 601 | GET_OPCODE(*pc) != OP_TEST); |
520 | SETARG_A(*pc, !(GETARG_A(*pc))); | 602 | SETARG_A(*pc, !(GETARG_A(*pc))); |
@@ -532,7 +614,7 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { | |||
532 | } | 614 | } |
533 | discharge2anyreg(fs, e); | 615 | discharge2anyreg(fs, e); |
534 | freeexp(fs, e); | 616 | freeexp(fs, e); |
535 | return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); | 617 | return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); |
536 | } | 618 | } |
537 | 619 | ||
538 | 620 | ||
@@ -540,17 +622,13 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { | |||
540 | int pc; /* pc of last jump */ | 622 | int pc; /* pc of last jump */ |
541 | luaK_dischargevars(fs, e); | 623 | luaK_dischargevars(fs, e); |
542 | switch (e->k) { | 624 | switch (e->k) { |
543 | case VK: case VKNUM: case VTRUE: { | ||
544 | pc = NO_JUMP; /* always true; do nothing */ | ||
545 | break; | ||
546 | } | ||
547 | case VFALSE: { | ||
548 | pc = luaK_jump(fs); /* always jump */ | ||
549 | break; | ||
550 | } | ||
551 | case VJMP: { | 625 | case VJMP: { |
552 | invertjump(fs, e); | 626 | invertjump(fs, e); |
553 | pc = e->u.s.info; | 627 | pc = e->u.info; |
628 | break; | ||
629 | } | ||
630 | case VK: case VKNUM: case VTRUE: { | ||
631 | pc = NO_JUMP; /* always true; do nothing */ | ||
554 | break; | 632 | break; |
555 | } | 633 | } |
556 | default: { | 634 | default: { |
@@ -564,20 +642,16 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { | |||
564 | } | 642 | } |
565 | 643 | ||
566 | 644 | ||
567 | static void luaK_goiffalse (FuncState *fs, expdesc *e) { | 645 | void luaK_goiffalse (FuncState *fs, expdesc *e) { |
568 | int pc; /* pc of last jump */ | 646 | int pc; /* pc of last jump */ |
569 | luaK_dischargevars(fs, e); | 647 | luaK_dischargevars(fs, e); |
570 | switch (e->k) { | 648 | switch (e->k) { |
571 | case VNIL: case VFALSE: { | 649 | case VJMP: { |
572 | pc = NO_JUMP; /* always false; do nothing */ | 650 | pc = e->u.info; |
573 | break; | ||
574 | } | ||
575 | case VTRUE: { | ||
576 | pc = luaK_jump(fs); /* always jump */ | ||
577 | break; | 651 | break; |
578 | } | 652 | } |
579 | case VJMP: { | 653 | case VNIL: case VFALSE: { |
580 | pc = e->u.s.info; | 654 | pc = NO_JUMP; /* always false; do nothing */ |
581 | break; | 655 | break; |
582 | } | 656 | } |
583 | default: { | 657 | default: { |
@@ -610,7 +684,7 @@ static void codenot (FuncState *fs, expdesc *e) { | |||
610 | case VNONRELOC: { | 684 | case VNONRELOC: { |
611 | discharge2anyreg(fs, e); | 685 | discharge2anyreg(fs, e); |
612 | freeexp(fs, e); | 686 | freeexp(fs, e); |
613 | e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); | 687 | e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); |
614 | e->k = VRELOCABLE; | 688 | e->k = VRELOCABLE; |
615 | break; | 689 | break; |
616 | } | 690 | } |
@@ -627,38 +701,28 @@ static void codenot (FuncState *fs, expdesc *e) { | |||
627 | 701 | ||
628 | 702 | ||
629 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | 703 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { |
630 | t->u.s.aux = luaK_exp2RK(fs, k); | 704 | lua_assert(!hasjumps(t)); |
705 | t->u.ind.t = t->u.info; | ||
706 | t->u.ind.idx = luaK_exp2RK(fs, k); | ||
707 | t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL | ||
708 | : check_exp(vkisinreg(t->k), VLOCAL); | ||
631 | t->k = VINDEXED; | 709 | t->k = VINDEXED; |
632 | } | 710 | } |
633 | 711 | ||
634 | 712 | ||
635 | static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { | 713 | static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { |
636 | lua_Number v1, v2, r; | 714 | lua_Number r; |
637 | if (!isnumeral(e1) || !isnumeral(e2)) return 0; | 715 | if (!isnumeral(e1) || !isnumeral(e2)) return 0; |
638 | v1 = e1->u.nval; | 716 | if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) |
639 | v2 = e2->u.nval; | 717 | return 0; /* do not attempt to divide by 0 */ |
640 | switch (op) { | 718 | r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); |
641 | case OP_ADD: r = luai_numadd(v1, v2); break; | ||
642 | case OP_SUB: r = luai_numsub(v1, v2); break; | ||
643 | case OP_MUL: r = luai_nummul(v1, v2); break; | ||
644 | case OP_DIV: | ||
645 | if (v2 == 0) return 0; /* do not attempt to divide by 0 */ | ||
646 | r = luai_numdiv(v1, v2); break; | ||
647 | case OP_MOD: | ||
648 | if (v2 == 0) return 0; /* do not attempt to divide by 0 */ | ||
649 | r = luai_nummod(v1, v2); break; | ||
650 | case OP_POW: r = luai_numpow(v1, v2); break; | ||
651 | case OP_UNM: r = luai_numunm(v1); break; | ||
652 | case OP_LEN: return 0; /* no constant folding for 'len' */ | ||
653 | default: lua_assert(0); r = 0; break; | ||
654 | } | ||
655 | if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ | ||
656 | e1->u.nval = r; | 719 | e1->u.nval = r; |
657 | return 1; | 720 | return 1; |
658 | } | 721 | } |
659 | 722 | ||
660 | 723 | ||
661 | static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { | 724 | static void codearith (FuncState *fs, OpCode op, |
725 | expdesc *e1, expdesc *e2, int line) { | ||
662 | if (constfolding(op, e1, e2)) | 726 | if (constfolding(op, e1, e2)) |
663 | return; | 727 | return; |
664 | else { | 728 | else { |
@@ -672,8 +736,9 @@ static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { | |||
672 | freeexp(fs, e2); | 736 | freeexp(fs, e2); |
673 | freeexp(fs, e1); | 737 | freeexp(fs, e1); |
674 | } | 738 | } |
675 | e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); | 739 | e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); |
676 | e1->k = VRELOCABLE; | 740 | e1->k = VRELOCABLE; |
741 | luaK_fixline(fs, line); | ||
677 | } | 742 | } |
678 | } | 743 | } |
679 | 744 | ||
@@ -689,25 +754,28 @@ static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, | |||
689 | temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ | 754 | temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ |
690 | cond = 1; | 755 | cond = 1; |
691 | } | 756 | } |
692 | e1->u.s.info = condjump(fs, op, cond, o1, o2); | 757 | e1->u.info = condjump(fs, op, cond, o1, o2); |
693 | e1->k = VJMP; | 758 | e1->k = VJMP; |
694 | } | 759 | } |
695 | 760 | ||
696 | 761 | ||
697 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { | 762 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { |
698 | expdesc e2; | 763 | expdesc e2; |
699 | e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; | 764 | e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; |
700 | switch (op) { | 765 | switch (op) { |
701 | case OPR_MINUS: { | 766 | case OPR_MINUS: { |
702 | if (!isnumeral(e)) | 767 | if (isnumeral(e)) /* minus constant? */ |
703 | luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ | 768 | e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ |
704 | codearith(fs, OP_UNM, e, &e2); | 769 | else { |
770 | luaK_exp2anyreg(fs, e); | ||
771 | codearith(fs, OP_UNM, e, &e2, line); | ||
772 | } | ||
705 | break; | 773 | break; |
706 | } | 774 | } |
707 | case OPR_NOT: codenot(fs, e); break; | 775 | case OPR_NOT: codenot(fs, e); break; |
708 | case OPR_LEN: { | 776 | case OPR_LEN: { |
709 | luaK_exp2anyreg(fs, e); /* cannot operate on constants */ | 777 | luaK_exp2anyreg(fs, e); /* cannot operate on constants */ |
710 | codearith(fs, OP_LEN, e, &e2); | 778 | codearith(fs, OP_LEN, e, &e2, line); |
711 | break; | 779 | break; |
712 | } | 780 | } |
713 | default: lua_assert(0); | 781 | default: lua_assert(0); |
@@ -742,7 +810,8 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | |||
742 | } | 810 | } |
743 | 811 | ||
744 | 812 | ||
745 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | 813 | void luaK_posfix (FuncState *fs, BinOpr op, |
814 | expdesc *e1, expdesc *e2, int line) { | ||
746 | switch (op) { | 815 | switch (op) { |
747 | case OPR_AND: { | 816 | case OPR_AND: { |
748 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ | 817 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ |
@@ -761,29 +830,30 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | |||
761 | case OPR_CONCAT: { | 830 | case OPR_CONCAT: { |
762 | luaK_exp2val(fs, e2); | 831 | luaK_exp2val(fs, e2); |
763 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { | 832 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { |
764 | lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); | 833 | lua_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1); |
765 | freeexp(fs, e1); | 834 | freeexp(fs, e1); |
766 | SETARG_B(getcode(fs, e2), e1->u.s.info); | 835 | SETARG_B(getcode(fs, e2), e1->u.info); |
767 | e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; | 836 | e1->k = VRELOCABLE; e1->u.info = e2->u.info; |
768 | } | 837 | } |
769 | else { | 838 | else { |
770 | luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ | 839 | luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ |
771 | codearith(fs, OP_CONCAT, e1, e2); | 840 | codearith(fs, OP_CONCAT, e1, e2, line); |
772 | } | 841 | } |
773 | break; | 842 | break; |
774 | } | 843 | } |
775 | case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; | 844 | case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: |
776 | case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; | 845 | case OPR_MOD: case OPR_POW: { |
777 | case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; | 846 | codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line); |
778 | case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; | 847 | break; |
779 | case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; | 848 | } |
780 | case OPR_POW: codearith(fs, OP_POW, e1, e2); break; | 849 | case OPR_EQ: case OPR_LT: case OPR_LE: { |
781 | case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; | 850 | codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2); |
782 | case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; | 851 | break; |
783 | case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; | 852 | } |
784 | case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; | 853 | case OPR_NE: case OPR_GT: case OPR_GE: { |
785 | case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; | 854 | codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2); |
786 | case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; | 855 | break; |
856 | } | ||
787 | default: lua_assert(0); | 857 | default: lua_assert(0); |
788 | } | 858 | } |
789 | } | 859 | } |
@@ -794,46 +864,18 @@ void luaK_fixline (FuncState *fs, int line) { | |||
794 | } | 864 | } |
795 | 865 | ||
796 | 866 | ||
797 | static int luaK_code (FuncState *fs, Instruction i, int line) { | ||
798 | Proto *f = fs->f; | ||
799 | dischargejpc(fs); /* `pc' will change */ | ||
800 | /* put new instruction in code array */ | ||
801 | luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, | ||
802 | MAX_INT, "code size overflow"); | ||
803 | f->code[fs->pc] = i; | ||
804 | /* save corresponding line information */ | ||
805 | luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, | ||
806 | MAX_INT, "code size overflow"); | ||
807 | f->lineinfo[fs->pc] = line; | ||
808 | return fs->pc++; | ||
809 | } | ||
810 | |||
811 | |||
812 | int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { | ||
813 | lua_assert(getOpMode(o) == iABC); | ||
814 | lua_assert(getBMode(o) != OpArgN || b == 0); | ||
815 | lua_assert(getCMode(o) != OpArgN || c == 0); | ||
816 | return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); | ||
817 | } | ||
818 | |||
819 | |||
820 | int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { | ||
821 | lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); | ||
822 | lua_assert(getCMode(o) == OpArgN); | ||
823 | return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); | ||
824 | } | ||
825 | |||
826 | |||
827 | void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { | 867 | void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { |
828 | int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; | 868 | int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; |
829 | int b = (tostore == LUA_MULTRET) ? 0 : tostore; | 869 | int b = (tostore == LUA_MULTRET) ? 0 : tostore; |
830 | lua_assert(tostore != 0); | 870 | lua_assert(tostore != 0); |
831 | if (c <= MAXARG_C) | 871 | if (c <= MAXARG_C) |
832 | luaK_codeABC(fs, OP_SETLIST, base, b, c); | 872 | luaK_codeABC(fs, OP_SETLIST, base, b, c); |
833 | else { | 873 | else if (c <= MAXARG_Ax) { |
834 | luaK_codeABC(fs, OP_SETLIST, base, b, 0); | 874 | luaK_codeABC(fs, OP_SETLIST, base, b, 0); |
835 | luaK_code(fs, cast(Instruction, c), fs->ls->lastline); | 875 | codeextraarg(fs, c); |
836 | } | 876 | } |
877 | else | ||
878 | luaX_syntaxerror(fs->ls, "constructor too long"); | ||
837 | fs->freereg = base + 1; /* free registers with list values */ | 879 | fs->freereg = base + 1; /* free registers with list values */ |
838 | } | 880 | } |
839 | 881 | ||
diff --git a/apps/plugins/lua/lcode.h b/apps/plugins/lua/lcode.h index 751b2b5695..6a1424cf5a 100644 --- a/apps/plugins/lua/lcode.h +++ b/apps/plugins/lua/lcode.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lcode.h,v 1.58.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -21,13 +21,13 @@ | |||
21 | 21 | ||
22 | 22 | ||
23 | /* | 23 | /* |
24 | ** grep "ORDER OPR" if you change these enums | 24 | ** grep "ORDER OPR" if you change these enums (ORDER OP) |
25 | */ | 25 | */ |
26 | typedef enum BinOpr { | 26 | typedef enum BinOpr { |
27 | OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, | 27 | OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, |
28 | OPR_CONCAT, | 28 | OPR_CONCAT, |
29 | OPR_NE, OPR_EQ, | 29 | OPR_EQ, OPR_LT, OPR_LE, |
30 | OPR_LT, OPR_LE, OPR_GT, OPR_GE, | 30 | OPR_NE, OPR_GT, OPR_GE, |
31 | OPR_AND, OPR_OR, | 31 | OPR_AND, OPR_OR, |
32 | OPR_NOBINOPR | 32 | OPR_NOBINOPR |
33 | } BinOpr; | 33 | } BinOpr; |
@@ -36,14 +36,17 @@ typedef enum BinOpr { | |||
36 | typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; | 36 | typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; |
37 | 37 | ||
38 | 38 | ||
39 | #define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) | 39 | #define getcode(fs,e) ((fs)->f->code[(e)->u.info]) |
40 | 40 | ||
41 | #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) | 41 | #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) |
42 | 42 | ||
43 | #define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) | 43 | #define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) |
44 | 44 | ||
45 | #define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) | ||
46 | |||
45 | LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); | 47 | LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); |
46 | LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); | 48 | LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); |
49 | LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k); | ||
47 | LUAI_FUNC void luaK_fixline (FuncState *fs, int line); | 50 | LUAI_FUNC void luaK_fixline (FuncState *fs, int line); |
48 | LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); | 51 | LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); |
49 | LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); | 52 | LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); |
@@ -52,12 +55,14 @@ LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); | |||
52 | LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); | 55 | LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); |
53 | LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); | 56 | LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); |
54 | LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); | 57 | LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); |
58 | LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); | ||
55 | LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); | 59 | LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); |
56 | LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); | 60 | LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); |
57 | LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); | 61 | LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); |
58 | LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); | 62 | LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); |
59 | LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); | 63 | LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); |
60 | LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); | 64 | LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); |
65 | LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); | ||
61 | LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); | 66 | LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); |
62 | LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); | 67 | LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); |
63 | LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); | 68 | LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); |
@@ -65,11 +70,13 @@ LUAI_FUNC int luaK_jump (FuncState *fs); | |||
65 | LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); | 70 | LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); |
66 | LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); | 71 | LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); |
67 | LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); | 72 | LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); |
73 | LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level); | ||
68 | LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); | 74 | LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); |
69 | LUAI_FUNC int luaK_getlabel (FuncState *fs); | 75 | LUAI_FUNC int luaK_getlabel (FuncState *fs); |
70 | LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); | 76 | LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); |
71 | LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); | 77 | LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); |
72 | LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); | 78 | LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, |
79 | expdesc *v2, int line); | ||
73 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); | 80 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); |
74 | 81 | ||
75 | 82 | ||
diff --git a/apps/plugins/lua/lctype.h b/apps/plugins/lua/lctype.h new file mode 100644 index 0000000000..b09b21a337 --- /dev/null +++ b/apps/plugins/lua/lctype.h | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | ** $Id: lctype.h,v 1.12.1.1 2013/04/12 18:48:47 roberto Exp $ | ||
3 | ** 'ctype' functions for Lua | ||
4 | ** See Copyright Notice in lua.h | ||
5 | */ | ||
6 | |||
7 | #ifndef lctype_h | ||
8 | #define lctype_h | ||
9 | |||
10 | #include "lua.h" | ||
11 | |||
12 | |||
13 | /* | ||
14 | ** WARNING: the functions defined here do not necessarily correspond | ||
15 | ** to the similar functions in the standard C ctype.h. They are | ||
16 | ** optimized for the specific needs of Lua | ||
17 | */ | ||
18 | |||
19 | #if !defined(LUA_USE_CTYPE) | ||
20 | |||
21 | #if 'A' == 65 && '0' == 48 | ||
22 | /* ASCII case: can use its own tables; faster and fixed */ | ||
23 | #define LUA_USE_CTYPE 0 | ||
24 | #else | ||
25 | /* must use standard C ctype */ | ||
26 | #define LUA_USE_CTYPE 1 | ||
27 | #endif | ||
28 | |||
29 | #endif | ||
30 | |||
31 | |||
32 | #if !LUA_USE_CTYPE /* { */ | ||
33 | |||
34 | #include <limits.h> | ||
35 | |||
36 | #include "llimits.h" | ||
37 | |||
38 | |||
39 | #define ALPHABIT 0 | ||
40 | #define DIGITBIT 1 | ||
41 | #define PRINTBIT 2 | ||
42 | #define SPACEBIT 3 | ||
43 | #define XDIGITBIT 4 | ||
44 | |||
45 | |||
46 | #define MASK(B) (1 << (B)) | ||
47 | |||
48 | |||
49 | /* | ||
50 | ** add 1 to char to allow index -1 (EOZ) | ||
51 | */ | ||
52 | #define testprop(c,p) (luai_ctype_[(c)+1] & (p)) | ||
53 | |||
54 | /* | ||
55 | ** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' | ||
56 | */ | ||
57 | #define lislalpha(c) testprop(c, MASK(ALPHABIT)) | ||
58 | #define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) | ||
59 | #define lisdigit(c) testprop(c, MASK(DIGITBIT)) | ||
60 | #define lisspace(c) testprop(c, MASK(SPACEBIT)) | ||
61 | #define lisprint(c) testprop(c, MASK(PRINTBIT)) | ||
62 | #define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) | ||
63 | |||
64 | /* | ||
65 | ** this 'ltolower' only works for alphabetic characters | ||
66 | */ | ||
67 | #define ltolower(c) ((c) | ('A' ^ 'a')) | ||
68 | |||
69 | |||
70 | /* two more entries for 0 and -1 (EOZ) */ | ||
71 | LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; | ||
72 | |||
73 | |||
74 | #else /* }{ */ | ||
75 | |||
76 | /* | ||
77 | ** use standard C ctypes | ||
78 | */ | ||
79 | |||
80 | #include <ctype.h> | ||
81 | |||
82 | |||
83 | #define lislalpha(c) (isalpha(c) || (c) == '_') | ||
84 | #define lislalnum(c) (isalnum(c) || (c) == '_') | ||
85 | #define lisdigit(c) (isdigit(c)) | ||
86 | #define lisspace(c) (isspace(c)) | ||
87 | #define lisprint(c) (isprint(c)) | ||
88 | #define lisxdigit(c) (isxdigit(c)) | ||
89 | |||
90 | #define ltolower(c) (tolower(c)) | ||
91 | |||
92 | #endif /* } */ | ||
93 | |||
94 | #endif | ||
95 | |||
diff --git a/apps/plugins/lua/ldebug.c b/apps/plugins/lua/ldebug.c index 50ad3d3803..20d663efff 100644 --- a/apps/plugins/lua/ldebug.c +++ b/apps/plugins/lua/ldebug.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ | 2 | ** $Id: ldebug.c,v 2.90.1.3 2013/05/16 16:04:15 roberto Exp $ |
3 | ** Debug Interface | 3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -30,23 +30,20 @@ | |||
30 | 30 | ||
31 | 31 | ||
32 | 32 | ||
33 | #define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) | ||
34 | |||
35 | |||
33 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); | 36 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); |
34 | 37 | ||
35 | 38 | ||
36 | static int currentpc (lua_State *L, CallInfo *ci) { | 39 | static int currentpc (CallInfo *ci) { |
37 | if (!isLua(ci)) return -1; /* function is not a Lua function? */ | 40 | lua_assert(isLua(ci)); |
38 | if (ci == L->ci) | 41 | return pcRel(ci->u.l.savedpc, ci_func(ci)->p); |
39 | ci->savedpc = L->savedpc; | ||
40 | return pcRel(ci->savedpc, ci_func(ci)->l.p); | ||
41 | } | 42 | } |
42 | 43 | ||
43 | 44 | ||
44 | static int currentline (lua_State *L, CallInfo *ci) { | 45 | static int currentline (CallInfo *ci) { |
45 | int pc = currentpc(L, ci); | 46 | return getfuncline(ci_func(ci)->p, currentpc(ci)); |
46 | if (pc < 0) | ||
47 | return -1; /* only active lua functions have current-line information */ | ||
48 | else | ||
49 | return getline(ci_func(ci)->l.p, pc); | ||
50 | } | 47 | } |
51 | 48 | ||
52 | 49 | ||
@@ -58,6 +55,8 @@ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { | |||
58 | mask = 0; | 55 | mask = 0; |
59 | func = NULL; | 56 | func = NULL; |
60 | } | 57 | } |
58 | if (isLua(L->ci)) | ||
59 | L->oldpc = L->ci->u.l.savedpc; | ||
61 | L->hook = func; | 60 | L->hook = func; |
62 | L->basehookcount = count; | 61 | L->basehookcount = count; |
63 | resethookcount(L); | 62 | resethookcount(L); |
@@ -84,19 +83,13 @@ LUA_API int lua_gethookcount (lua_State *L) { | |||
84 | LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { | 83 | LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { |
85 | int status; | 84 | int status; |
86 | CallInfo *ci; | 85 | CallInfo *ci; |
86 | if (level < 0) return 0; /* invalid (negative) level */ | ||
87 | lua_lock(L); | 87 | lua_lock(L); |
88 | for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { | 88 | for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) |
89 | level--; | 89 | level--; |
90 | if (f_isLua(ci)) /* Lua function? */ | 90 | if (level == 0 && ci != &L->base_ci) { /* level found? */ |
91 | level -= ci->tailcalls; /* skip lost tail calls */ | ||
92 | } | ||
93 | if (level == 0 && ci > L->base_ci) { /* level found? */ | ||
94 | status = 1; | 91 | status = 1; |
95 | ar->i_ci = cast_int(ci - L->base_ci); | 92 | ar->i_ci = ci; |
96 | } | ||
97 | else if (level < 0) { /* level is of a lost tail call? */ | ||
98 | status = 1; | ||
99 | ar->i_ci = 0; | ||
100 | } | 93 | } |
101 | else status = 0; /* no such level */ | 94 | else status = 0; /* no such level */ |
102 | lua_unlock(L); | 95 | lua_unlock(L); |
@@ -104,43 +97,78 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { | |||
104 | } | 97 | } |
105 | 98 | ||
106 | 99 | ||
107 | static Proto *getluaproto (CallInfo *ci) { | 100 | static const char *upvalname (Proto *p, int uv) { |
108 | return (isLua(ci) ? ci_func(ci)->l.p : NULL); | 101 | TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); |
102 | if (s == NULL) return "?"; | ||
103 | else return getstr(s); | ||
109 | } | 104 | } |
110 | 105 | ||
111 | 106 | ||
112 | static const char *findlocal (lua_State *L, CallInfo *ci, int n) { | 107 | static const char *findvararg (CallInfo *ci, int n, StkId *pos) { |
113 | const char *name; | 108 | int nparams = clLvalue(ci->func)->p->numparams; |
114 | Proto *fp = getluaproto(ci); | 109 | if (n >= ci->u.l.base - ci->func - nparams) |
115 | if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) | 110 | return NULL; /* no such vararg */ |
116 | return name; /* is a local variable in a Lua function */ | ||
117 | else { | 111 | else { |
118 | StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; | 112 | *pos = ci->func + nparams + n; |
119 | if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ | 113 | return "(*vararg)"; /* generic name for any vararg */ |
120 | return "(*temporary)"; | 114 | } |
115 | } | ||
116 | |||
117 | |||
118 | static const char *findlocal (lua_State *L, CallInfo *ci, int n, | ||
119 | StkId *pos) { | ||
120 | const char *name = NULL; | ||
121 | StkId base; | ||
122 | if (isLua(ci)) { | ||
123 | if (n < 0) /* access to vararg values? */ | ||
124 | return findvararg(ci, -n, pos); | ||
125 | else { | ||
126 | base = ci->u.l.base; | ||
127 | name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); | ||
128 | } | ||
129 | } | ||
130 | else | ||
131 | base = ci->func + 1; | ||
132 | if (name == NULL) { /* no 'standard' name? */ | ||
133 | StkId limit = (ci == L->ci) ? L->top : ci->next->func; | ||
134 | if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ | ||
135 | name = "(*temporary)"; /* generic name for any valid slot */ | ||
121 | else | 136 | else |
122 | return NULL; | 137 | return NULL; /* no name */ |
123 | } | 138 | } |
139 | *pos = base + (n - 1); | ||
140 | return name; | ||
124 | } | 141 | } |
125 | 142 | ||
126 | 143 | ||
127 | LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { | 144 | LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { |
128 | CallInfo *ci = L->base_ci + ar->i_ci; | 145 | const char *name; |
129 | const char *name = findlocal(L, ci, n); | ||
130 | lua_lock(L); | 146 | lua_lock(L); |
131 | if (name) | 147 | if (ar == NULL) { /* information about non-active function? */ |
132 | luaA_pushobject(L, ci->base + (n - 1)); | 148 | if (!isLfunction(L->top - 1)) /* not a Lua function? */ |
149 | name = NULL; | ||
150 | else /* consider live variables at function start (parameters) */ | ||
151 | name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); | ||
152 | } | ||
153 | else { /* active function; get information through 'ar' */ | ||
154 | StkId pos = 0; /* to avoid warnings */ | ||
155 | name = findlocal(L, ar->i_ci, n, &pos); | ||
156 | if (name) { | ||
157 | setobj2s(L, L->top, pos); | ||
158 | api_incr_top(L); | ||
159 | } | ||
160 | } | ||
133 | lua_unlock(L); | 161 | lua_unlock(L); |
134 | return name; | 162 | return name; |
135 | } | 163 | } |
136 | 164 | ||
137 | 165 | ||
138 | LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { | 166 | LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { |
139 | CallInfo *ci = L->base_ci + ar->i_ci; | 167 | StkId pos = 0; /* to avoid warnings */ |
140 | const char *name = findlocal(L, ci, n); | 168 | const char *name = findlocal(L, ar->i_ci, n, &pos); |
141 | lua_lock(L); | 169 | lua_lock(L); |
142 | if (name) | 170 | if (name) |
143 | setobjs2s(L, ci->base + (n - 1), L->top - 1); | 171 | setobjs2s(L, pos, L->top - 1); |
144 | L->top--; /* pop value */ | 172 | L->top--; /* pop value */ |
145 | lua_unlock(L); | 173 | lua_unlock(L); |
146 | return name; | 174 | return name; |
@@ -148,55 +176,45 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { | |||
148 | 176 | ||
149 | 177 | ||
150 | static void funcinfo (lua_Debug *ar, Closure *cl) { | 178 | static void funcinfo (lua_Debug *ar, Closure *cl) { |
151 | if (cl->c.isC) { | 179 | if (noLuaClosure(cl)) { |
152 | ar->source = "=[C]"; | 180 | ar->source = "=[C]"; |
153 | ar->linedefined = -1; | 181 | ar->linedefined = -1; |
154 | ar->lastlinedefined = -1; | 182 | ar->lastlinedefined = -1; |
155 | ar->what = "C"; | 183 | ar->what = "C"; |
156 | } | 184 | } |
157 | else { | 185 | else { |
158 | ar->source = getstr(cl->l.p->source); | 186 | Proto *p = cl->l.p; |
159 | ar->linedefined = cl->l.p->linedefined; | 187 | ar->source = p->source ? getstr(p->source) : "=?"; |
160 | ar->lastlinedefined = cl->l.p->lastlinedefined; | 188 | ar->linedefined = p->linedefined; |
189 | ar->lastlinedefined = p->lastlinedefined; | ||
161 | ar->what = (ar->linedefined == 0) ? "main" : "Lua"; | 190 | ar->what = (ar->linedefined == 0) ? "main" : "Lua"; |
162 | } | 191 | } |
163 | luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); | 192 | luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); |
164 | } | 193 | } |
165 | 194 | ||
166 | 195 | ||
167 | static void info_tailcall (lua_Debug *ar) { | ||
168 | ar->name = ar->namewhat = ""; | ||
169 | ar->what = "tail"; | ||
170 | ar->lastlinedefined = ar->linedefined = ar->currentline = -1; | ||
171 | ar->source = "=(tail call)"; | ||
172 | luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); | ||
173 | ar->nups = 0; | ||
174 | } | ||
175 | |||
176 | |||
177 | static void collectvalidlines (lua_State *L, Closure *f) { | 196 | static void collectvalidlines (lua_State *L, Closure *f) { |
178 | if (f == NULL || f->c.isC) { | 197 | if (noLuaClosure(f)) { |
179 | setnilvalue(L->top); | 198 | setnilvalue(L->top); |
199 | api_incr_top(L); | ||
180 | } | 200 | } |
181 | else { | 201 | else { |
182 | Table *t = luaH_new(L, 0, 0); | ||
183 | int *lineinfo = f->l.p->lineinfo; | ||
184 | int i; | 202 | int i; |
185 | for (i=0; i<f->l.p->sizelineinfo; i++) | 203 | TValue v; |
186 | setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); | 204 | int *lineinfo = f->l.p->lineinfo; |
187 | sethvalue(L, L->top, t); | 205 | Table *t = luaH_new(L); /* new table to store active lines */ |
206 | sethvalue(L, L->top, t); /* push it on stack */ | ||
207 | api_incr_top(L); | ||
208 | setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ | ||
209 | for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ | ||
210 | luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ | ||
188 | } | 211 | } |
189 | incr_top(L); | ||
190 | } | 212 | } |
191 | 213 | ||
192 | 214 | ||
193 | static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | 215 | static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, |
194 | Closure *f, CallInfo *ci) { | 216 | Closure *f, CallInfo *ci) { |
195 | int status = 1; | 217 | int status = 1; |
196 | if (f == NULL) { | ||
197 | info_tailcall(ar); | ||
198 | return status; | ||
199 | } | ||
200 | for (; *what; what++) { | 218 | for (; *what; what++) { |
201 | switch (*what) { | 219 | switch (*what) { |
202 | case 'S': { | 220 | case 'S': { |
@@ -204,15 +222,31 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | |||
204 | break; | 222 | break; |
205 | } | 223 | } |
206 | case 'l': { | 224 | case 'l': { |
207 | ar->currentline = (ci) ? currentline(L, ci) : -1; | 225 | ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; |
208 | break; | 226 | break; |
209 | } | 227 | } |
210 | case 'u': { | 228 | case 'u': { |
211 | ar->nups = f->c.nupvalues; | 229 | ar->nups = (f == NULL) ? 0 : f->c.nupvalues; |
230 | if (noLuaClosure(f)) { | ||
231 | ar->isvararg = 1; | ||
232 | ar->nparams = 0; | ||
233 | } | ||
234 | else { | ||
235 | ar->isvararg = f->l.p->is_vararg; | ||
236 | ar->nparams = f->l.p->numparams; | ||
237 | } | ||
238 | break; | ||
239 | } | ||
240 | case 't': { | ||
241 | ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; | ||
212 | break; | 242 | break; |
213 | } | 243 | } |
214 | case 'n': { | 244 | case 'n': { |
215 | ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; | 245 | /* calling function is a known Lua function? */ |
246 | if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) | ||
247 | ar->namewhat = getfuncname(L, ci->previous, &ar->name); | ||
248 | else | ||
249 | ar->namewhat = NULL; | ||
216 | if (ar->namewhat == NULL) { | 250 | if (ar->namewhat == NULL) { |
217 | ar->namewhat = ""; /* not found */ | 251 | ar->namewhat = ""; /* not found */ |
218 | ar->name = NULL; | 252 | ar->name = NULL; |
@@ -231,29 +265,30 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | |||
231 | 265 | ||
232 | LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | 266 | LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { |
233 | int status; | 267 | int status; |
234 | Closure *f = NULL; | 268 | Closure *cl; |
235 | CallInfo *ci = NULL; | 269 | CallInfo *ci; |
270 | StkId func; | ||
236 | lua_lock(L); | 271 | lua_lock(L); |
237 | if (*what == '>') { | 272 | if (*what == '>') { |
238 | StkId func = L->top - 1; | 273 | ci = NULL; |
239 | luai_apicheck(L, ttisfunction(func)); | 274 | func = L->top - 1; |
275 | api_check(L, ttisfunction(func), "function expected"); | ||
240 | what++; /* skip the '>' */ | 276 | what++; /* skip the '>' */ |
241 | f = clvalue(func); | ||
242 | L->top--; /* pop function */ | 277 | L->top--; /* pop function */ |
243 | } | 278 | } |
244 | else if (ar->i_ci != 0) { /* no tail call? */ | 279 | else { |
245 | ci = L->base_ci + ar->i_ci; | 280 | ci = ar->i_ci; |
281 | func = ci->func; | ||
246 | lua_assert(ttisfunction(ci->func)); | 282 | lua_assert(ttisfunction(ci->func)); |
247 | f = clvalue(ci->func); | ||
248 | } | 283 | } |
249 | status = auxgetinfo(L, what, ar, f, ci); | 284 | cl = ttisclosure(func) ? clvalue(func) : NULL; |
285 | status = auxgetinfo(L, what, ar, cl, ci); | ||
250 | if (strchr(what, 'f')) { | 286 | if (strchr(what, 'f')) { |
251 | if (f == NULL) setnilvalue(L->top); | 287 | setobjs2s(L, L->top, func); |
252 | else setclvalue(L, L->top, f); | 288 | api_incr_top(L); |
253 | incr_top(L); | ||
254 | } | 289 | } |
255 | if (strchr(what, 'L')) | 290 | if (strchr(what, 'L')) |
256 | collectvalidlines(L, f); | 291 | collectvalidlines(L, cl); |
257 | lua_unlock(L); | 292 | lua_unlock(L); |
258 | return status; | 293 | return status; |
259 | } | 294 | } |
@@ -261,315 +296,231 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | |||
261 | 296 | ||
262 | /* | 297 | /* |
263 | ** {====================================================== | 298 | ** {====================================================== |
264 | ** Symbolic Execution and code checker | 299 | ** Symbolic Execution |
265 | ** ======================================================= | 300 | ** ======================================================= |
266 | */ | 301 | */ |
267 | 302 | ||
268 | #define check(x) if (!(x)) return 0; | 303 | static const char *getobjname (Proto *p, int lastpc, int reg, |
304 | const char **name); | ||
269 | 305 | ||
270 | #define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) | ||
271 | 306 | ||
272 | #define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) | 307 | /* |
273 | 308 | ** find a "name" for the RK value 'c' | |
274 | 309 | */ | |
275 | 310 | static void kname (Proto *p, int pc, int c, const char **name) { | |
276 | static int precheck (const Proto *pt) { | 311 | if (ISK(c)) { /* is 'c' a constant? */ |
277 | check(pt->maxstacksize <= MAXSTACK); | 312 | TValue *kvalue = &p->k[INDEXK(c)]; |
278 | check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); | 313 | if (ttisstring(kvalue)) { /* literal constant? */ |
279 | check(!(pt->is_vararg & VARARG_NEEDSARG) || | 314 | *name = svalue(kvalue); /* it is its own name */ |
280 | (pt->is_vararg & VARARG_HASARG)); | 315 | return; |
281 | check(pt->sizeupvalues <= pt->nups); | 316 | } |
282 | check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); | 317 | /* else no reasonable name found */ |
283 | check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); | 318 | } |
284 | return 1; | 319 | else { /* 'c' is a register */ |
285 | } | 320 | const char *what = getobjname(p, pc, c, name); /* search for 'c' */ |
286 | 321 | if (what && *what == 'c') { /* found a constant name? */ | |
287 | 322 | return; /* 'name' already filled */ | |
288 | #define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) | ||
289 | |||
290 | int luaG_checkopenop (Instruction i) { | ||
291 | switch (GET_OPCODE(i)) { | ||
292 | case OP_CALL: | ||
293 | case OP_TAILCALL: | ||
294 | case OP_RETURN: | ||
295 | case OP_SETLIST: { | ||
296 | check(GETARG_B(i) == 0); | ||
297 | return 1; | ||
298 | } | 323 | } |
299 | default: return 0; /* invalid instruction after an open call */ | 324 | /* else no reasonable name found */ |
300 | } | 325 | } |
326 | *name = "?"; /* no reasonable name found */ | ||
301 | } | 327 | } |
302 | 328 | ||
303 | 329 | ||
304 | static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { | 330 | static int filterpc (int pc, int jmptarget) { |
305 | switch (mode) { | 331 | if (pc < jmptarget) /* is code conditional (inside a jump)? */ |
306 | case OpArgN: check(r == 0); break; | 332 | return -1; /* cannot know who sets that register */ |
307 | case OpArgU: break; | 333 | else return pc; /* current position sets that register */ |
308 | case OpArgR: checkreg(pt, r); break; | ||
309 | case OpArgK: | ||
310 | check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); | ||
311 | break; | ||
312 | } | ||
313 | return 1; | ||
314 | } | 334 | } |
315 | 335 | ||
316 | 336 | ||
317 | static Instruction symbexec (const Proto *pt, int lastpc, int reg) { | 337 | /* |
338 | ** try to find last instruction before 'lastpc' that modified register 'reg' | ||
339 | */ | ||
340 | static int findsetreg (Proto *p, int lastpc, int reg) { | ||
318 | int pc; | 341 | int pc; |
319 | int last; /* stores position of last instruction that changed `reg' */ | 342 | int setreg = -1; /* keep last instruction that changed 'reg' */ |
320 | last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ | 343 | int jmptarget = 0; /* any code before this address is conditional */ |
321 | check(precheck(pt)); | ||
322 | for (pc = 0; pc < lastpc; pc++) { | 344 | for (pc = 0; pc < lastpc; pc++) { |
323 | Instruction i = pt->code[pc]; | 345 | Instruction i = p->code[pc]; |
324 | OpCode op = GET_OPCODE(i); | 346 | OpCode op = GET_OPCODE(i); |
325 | int a = GETARG_A(i); | 347 | int a = GETARG_A(i); |
326 | int b = 0; | ||
327 | int c = 0; | ||
328 | check(op < NUM_OPCODES); | ||
329 | checkreg(pt, a); | ||
330 | switch (getOpMode(op)) { | ||
331 | case iABC: { | ||
332 | b = GETARG_B(i); | ||
333 | c = GETARG_C(i); | ||
334 | check(checkArgMode(pt, b, getBMode(op))); | ||
335 | check(checkArgMode(pt, c, getCMode(op))); | ||
336 | break; | ||
337 | } | ||
338 | case iABx: { | ||
339 | b = GETARG_Bx(i); | ||
340 | if (getBMode(op) == OpArgK) check(b < pt->sizek); | ||
341 | break; | ||
342 | } | ||
343 | case iAsBx: { | ||
344 | b = GETARG_sBx(i); | ||
345 | if (getBMode(op) == OpArgR) { | ||
346 | int dest = pc+1+b; | ||
347 | check(0 <= dest && dest < pt->sizecode); | ||
348 | if (dest > 0) { | ||
349 | int j; | ||
350 | /* check that it does not jump to a setlist count; this | ||
351 | is tricky, because the count from a previous setlist may | ||
352 | have the same value of an invalid setlist; so, we must | ||
353 | go all the way back to the first of them (if any) */ | ||
354 | for (j = 0; j < dest; j++) { | ||
355 | Instruction d = pt->code[dest-1-j]; | ||
356 | if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; | ||
357 | } | ||
358 | /* if 'j' is even, previous value is not a setlist (even if | ||
359 | it looks like one) */ | ||
360 | check((j&1) == 0); | ||
361 | } | ||
362 | } | ||
363 | break; | ||
364 | } | ||
365 | } | ||
366 | if (testAMode(op)) { | ||
367 | if (a == reg) last = pc; /* change register `a' */ | ||
368 | } | ||
369 | if (testTMode(op)) { | ||
370 | check(pc+2 < pt->sizecode); /* check skip */ | ||
371 | check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); | ||
372 | } | ||
373 | switch (op) { | 348 | switch (op) { |
374 | case OP_LOADBOOL: { | ||
375 | if (c == 1) { /* does it jump? */ | ||
376 | check(pc+2 < pt->sizecode); /* check its jump */ | ||
377 | check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || | ||
378 | GETARG_C(pt->code[pc+1]) != 0); | ||
379 | } | ||
380 | break; | ||
381 | } | ||
382 | case OP_LOADNIL: { | 349 | case OP_LOADNIL: { |
383 | if (a <= reg && reg <= b) | 350 | int b = GETARG_B(i); |
384 | last = pc; /* set registers from `a' to `b' */ | 351 | if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ |
385 | break; | 352 | setreg = filterpc(pc, jmptarget); |
386 | } | ||
387 | case OP_GETUPVAL: | ||
388 | case OP_SETUPVAL: { | ||
389 | check(b < pt->nups); | ||
390 | break; | ||
391 | } | ||
392 | case OP_GETGLOBAL: | ||
393 | case OP_SETGLOBAL: { | ||
394 | check(ttisstring(&pt->k[b])); | ||
395 | break; | ||
396 | } | ||
397 | case OP_SELF: { | ||
398 | checkreg(pt, a+1); | ||
399 | if (reg == a+1) last = pc; | ||
400 | break; | ||
401 | } | ||
402 | case OP_CONCAT: { | ||
403 | check(b < c); /* at least two operands */ | ||
404 | break; | ||
405 | } | ||
406 | case OP_TFORLOOP: { | ||
407 | check(c >= 1); /* at least one result (control variable) */ | ||
408 | checkreg(pt, a+2+c); /* space for results */ | ||
409 | if (reg >= a+2) last = pc; /* affect all regs above its base */ | ||
410 | break; | 353 | break; |
411 | } | 354 | } |
412 | case OP_FORLOOP: | 355 | case OP_TFORCALL: { |
413 | case OP_FORPREP: | 356 | if (reg >= a + 2) /* affect all regs above its base */ |
414 | checkreg(pt, a+3); | 357 | setreg = filterpc(pc, jmptarget); |
415 | /* go through */ | ||
416 | case OP_JMP: { | ||
417 | int dest = pc+1+b; | ||
418 | /* not full check and jump is forward and do not skip `lastpc'? */ | ||
419 | if (reg != NO_REG && pc < dest && dest <= lastpc) | ||
420 | pc += b; /* do the jump */ | ||
421 | break; | 358 | break; |
422 | } | 359 | } |
423 | case OP_CALL: | 360 | case OP_CALL: |
424 | case OP_TAILCALL: { | 361 | case OP_TAILCALL: { |
425 | if (b != 0) { | 362 | if (reg >= a) /* affect all registers above base */ |
426 | checkreg(pt, a+b-1); | 363 | setreg = filterpc(pc, jmptarget); |
427 | } | ||
428 | c--; /* c = num. returns */ | ||
429 | if (c == LUA_MULTRET) { | ||
430 | check(checkopenop(pt, pc)); | ||
431 | } | ||
432 | else if (c != 0) | ||
433 | checkreg(pt, a+c-1); | ||
434 | if (reg >= a) last = pc; /* affect all registers above base */ | ||
435 | break; | 364 | break; |
436 | } | 365 | } |
437 | case OP_RETURN: { | 366 | case OP_JMP: { |
438 | b--; /* b = num. returns */ | 367 | int b = GETARG_sBx(i); |
439 | if (b > 0) checkreg(pt, a+b-1); | 368 | int dest = pc + 1 + b; |
440 | break; | 369 | /* jump is forward and do not skip `lastpc'? */ |
441 | } | 370 | if (pc < dest && dest <= lastpc) { |
442 | case OP_SETLIST: { | 371 | if (dest > jmptarget) |
443 | if (b > 0) checkreg(pt, a + b); | 372 | jmptarget = dest; /* update 'jmptarget' */ |
444 | if (c == 0) { | ||
445 | pc++; | ||
446 | check(pc < pt->sizecode - 1); | ||
447 | } | 373 | } |
448 | break; | 374 | break; |
449 | } | 375 | } |
450 | case OP_CLOSURE: { | 376 | case OP_TEST: { |
451 | int nup, j; | 377 | if (reg == a) /* jumped code can change 'a' */ |
452 | check(b < pt->sizep); | 378 | setreg = filterpc(pc, jmptarget); |
453 | nup = pt->p[b]->nups; | ||
454 | check(pc + nup < pt->sizecode); | ||
455 | for (j = 1; j <= nup; j++) { | ||
456 | OpCode op1 = GET_OPCODE(pt->code[pc + j]); | ||
457 | check(op1 == OP_GETUPVAL || op1 == OP_MOVE); | ||
458 | } | ||
459 | if (reg != NO_REG) /* tracing? */ | ||
460 | pc += nup; /* do not 'execute' these pseudo-instructions */ | ||
461 | break; | 379 | break; |
462 | } | 380 | } |
463 | case OP_VARARG: { | 381 | default: |
464 | check((pt->is_vararg & VARARG_ISVARARG) && | 382 | if (testAMode(op) && reg == a) /* any instruction that set A */ |
465 | !(pt->is_vararg & VARARG_NEEDSARG)); | 383 | setreg = filterpc(pc, jmptarget); |
466 | b--; | ||
467 | if (b == LUA_MULTRET) check(checkopenop(pt, pc)); | ||
468 | checkreg(pt, a+b-1); | ||
469 | break; | 384 | break; |
470 | } | ||
471 | default: break; | ||
472 | } | 385 | } |
473 | } | 386 | } |
474 | return pt->code[last]; | 387 | return setreg; |
475 | } | ||
476 | |||
477 | #undef check | ||
478 | #undef checkjump | ||
479 | #undef checkreg | ||
480 | |||
481 | /* }====================================================== */ | ||
482 | |||
483 | |||
484 | int luaG_checkcode (const Proto *pt) { | ||
485 | return (symbexec(pt, pt->sizecode, NO_REG) != 0); | ||
486 | } | 388 | } |
487 | 389 | ||
488 | 390 | ||
489 | static const char *kname (Proto *p, int c) { | 391 | static const char *getobjname (Proto *p, int lastpc, int reg, |
490 | if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) | ||
491 | return svalue(&p->k[INDEXK(c)]); | ||
492 | else | ||
493 | return "?"; | ||
494 | } | ||
495 | |||
496 | |||
497 | static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, | ||
498 | const char **name) { | 392 | const char **name) { |
499 | if (isLua(ci)) { /* a Lua function? */ | 393 | int pc; |
500 | Proto *p = ci_func(ci)->l.p; | 394 | *name = luaF_getlocalname(p, reg + 1, lastpc); |
501 | int pc = currentpc(L, ci); | 395 | if (*name) /* is a local? */ |
502 | Instruction i; | 396 | return "local"; |
503 | *name = luaF_getlocalname(p, stackpos+1, pc); | 397 | /* else try symbolic execution */ |
504 | if (*name) /* is a local? */ | 398 | pc = findsetreg(p, lastpc, reg); |
505 | return "local"; | 399 | if (pc != -1) { /* could find instruction? */ |
506 | i = symbexec(p, pc, stackpos); /* try symbolic execution */ | 400 | Instruction i = p->code[pc]; |
507 | lua_assert(pc != -1); | 401 | OpCode op = GET_OPCODE(i); |
508 | switch (GET_OPCODE(i)) { | 402 | switch (op) { |
509 | case OP_GETGLOBAL: { | ||
510 | int g = GETARG_Bx(i); /* global index */ | ||
511 | lua_assert(ttisstring(&p->k[g])); | ||
512 | *name = svalue(&p->k[g]); | ||
513 | return "global"; | ||
514 | } | ||
515 | case OP_MOVE: { | 403 | case OP_MOVE: { |
516 | int a = GETARG_A(i); | 404 | int b = GETARG_B(i); /* move from 'b' to 'a' */ |
517 | int b = GETARG_B(i); /* move from `b' to `a' */ | 405 | if (b < GETARG_A(i)) |
518 | if (b < a) | 406 | return getobjname(p, pc, b, name); /* get name for 'b' */ |
519 | return getobjname(L, ci, b, name); /* get name for `b' */ | ||
520 | break; | 407 | break; |
521 | } | 408 | } |
409 | case OP_GETTABUP: | ||
522 | case OP_GETTABLE: { | 410 | case OP_GETTABLE: { |
523 | int k = GETARG_C(i); /* key index */ | 411 | int k = GETARG_C(i); /* key index */ |
524 | *name = kname(p, k); | 412 | int t = GETARG_B(i); /* table index */ |
525 | return "field"; | 413 | const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ |
414 | ? luaF_getlocalname(p, t + 1, pc) | ||
415 | : upvalname(p, t); | ||
416 | kname(p, pc, k, name); | ||
417 | return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; | ||
526 | } | 418 | } |
527 | case OP_GETUPVAL: { | 419 | case OP_GETUPVAL: { |
528 | int u = GETARG_B(i); /* upvalue index */ | 420 | *name = upvalname(p, GETARG_B(i)); |
529 | *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; | ||
530 | return "upvalue"; | 421 | return "upvalue"; |
531 | } | 422 | } |
423 | case OP_LOADK: | ||
424 | case OP_LOADKX: { | ||
425 | int b = (op == OP_LOADK) ? GETARG_Bx(i) | ||
426 | : GETARG_Ax(p->code[pc + 1]); | ||
427 | if (ttisstring(&p->k[b])) { | ||
428 | *name = svalue(&p->k[b]); | ||
429 | return "constant"; | ||
430 | } | ||
431 | break; | ||
432 | } | ||
532 | case OP_SELF: { | 433 | case OP_SELF: { |
533 | int k = GETARG_C(i); /* key index */ | 434 | int k = GETARG_C(i); /* key index */ |
534 | *name = kname(p, k); | 435 | kname(p, pc, k, name); |
535 | return "method"; | 436 | return "method"; |
536 | } | 437 | } |
537 | default: break; | 438 | default: break; /* go through to return NULL */ |
538 | } | 439 | } |
539 | } | 440 | } |
540 | return NULL; /* no useful name found */ | 441 | return NULL; /* could not find reasonable name */ |
541 | } | 442 | } |
542 | 443 | ||
543 | 444 | ||
544 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { | 445 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { |
545 | Instruction i; | 446 | TMS tm; |
546 | if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) | 447 | Proto *p = ci_func(ci)->p; /* calling function */ |
547 | return NULL; /* calling function is not Lua (or is unknown) */ | 448 | int pc = currentpc(ci); /* calling instruction index */ |
548 | ci--; /* calling function */ | 449 | Instruction i = p->code[pc]; /* calling instruction */ |
549 | i = ci_func(ci)->l.p->code[currentpc(L, ci)]; | 450 | switch (GET_OPCODE(i)) { |
550 | if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || | 451 | case OP_CALL: |
551 | GET_OPCODE(i) == OP_TFORLOOP) | 452 | case OP_TAILCALL: /* get function name */ |
552 | return getobjname(L, ci, GETARG_A(i), name); | 453 | return getobjname(p, pc, GETARG_A(i), name); |
553 | else | 454 | case OP_TFORCALL: { /* for iterator */ |
554 | return NULL; /* no useful name can be found */ | 455 | *name = "for iterator"; |
456 | return "for iterator"; | ||
457 | } | ||
458 | /* all other instructions can call only through metamethods */ | ||
459 | case OP_SELF: | ||
460 | case OP_GETTABUP: | ||
461 | case OP_GETTABLE: tm = TM_INDEX; break; | ||
462 | case OP_SETTABUP: | ||
463 | case OP_SETTABLE: tm = TM_NEWINDEX; break; | ||
464 | case OP_EQ: tm = TM_EQ; break; | ||
465 | case OP_ADD: tm = TM_ADD; break; | ||
466 | case OP_SUB: tm = TM_SUB; break; | ||
467 | case OP_MUL: tm = TM_MUL; break; | ||
468 | case OP_DIV: tm = TM_DIV; break; | ||
469 | case OP_MOD: tm = TM_MOD; break; | ||
470 | case OP_POW: tm = TM_POW; break; | ||
471 | case OP_UNM: tm = TM_UNM; break; | ||
472 | case OP_LEN: tm = TM_LEN; break; | ||
473 | case OP_LT: tm = TM_LT; break; | ||
474 | case OP_LE: tm = TM_LE; break; | ||
475 | case OP_CONCAT: tm = TM_CONCAT; break; | ||
476 | default: | ||
477 | return NULL; /* else no useful name can be found */ | ||
478 | } | ||
479 | *name = getstr(G(L)->tmname[tm]); | ||
480 | return "metamethod"; | ||
555 | } | 481 | } |
556 | 482 | ||
483 | /* }====================================================== */ | ||
484 | |||
485 | |||
557 | 486 | ||
558 | /* only ANSI way to check whether a pointer points to an array */ | 487 | /* |
488 | ** only ANSI way to check whether a pointer points to an array | ||
489 | ** (used only for error messages, so efficiency is not a big concern) | ||
490 | */ | ||
559 | static int isinstack (CallInfo *ci, const TValue *o) { | 491 | static int isinstack (CallInfo *ci, const TValue *o) { |
560 | StkId p; | 492 | StkId p; |
561 | for (p = ci->base; p < ci->top; p++) | 493 | for (p = ci->u.l.base; p < ci->top; p++) |
562 | if (o == p) return 1; | 494 | if (o == p) return 1; |
563 | return 0; | 495 | return 0; |
564 | } | 496 | } |
565 | 497 | ||
566 | 498 | ||
567 | void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { | 499 | static const char *getupvalname (CallInfo *ci, const TValue *o, |
500 | const char **name) { | ||
501 | LClosure *c = ci_func(ci); | ||
502 | int i; | ||
503 | for (i = 0; i < c->nupvalues; i++) { | ||
504 | if (c->upvals[i]->v == o) { | ||
505 | *name = upvalname(c->p, i); | ||
506 | return "upvalue"; | ||
507 | } | ||
508 | } | ||
509 | return NULL; | ||
510 | } | ||
511 | |||
512 | |||
513 | l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { | ||
514 | CallInfo *ci = L->ci; | ||
568 | const char *name = NULL; | 515 | const char *name = NULL; |
569 | const char *t = luaT_typenames[ttype(o)]; | 516 | const char *t = objtypename(o); |
570 | const char *kind = (isinstack(L->ci, o)) ? | 517 | const char *kind = NULL; |
571 | getobjname(L, L->ci, cast_int(o - L->base), &name) : | 518 | if (isLua(ci)) { |
572 | NULL; | 519 | kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ |
520 | if (!kind && isinstack(ci, o)) /* no? try a register */ | ||
521 | kind = getobjname(ci_func(ci)->p, currentpc(ci), | ||
522 | cast_int(o - ci->u.l.base), &name); | ||
523 | } | ||
573 | if (kind) | 524 | if (kind) |
574 | luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", | 525 | luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", |
575 | op, kind, name, t); | 526 | op, kind, name, t); |
@@ -578,14 +529,14 @@ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { | |||
578 | } | 529 | } |
579 | 530 | ||
580 | 531 | ||
581 | void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { | 532 | l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) { |
582 | if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; | 533 | if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; |
583 | lua_assert(!ttisstring(p1) && !ttisnumber(p1)); | 534 | lua_assert(!ttisstring(p1) && !ttisnumber(p1)); |
584 | luaG_typeerror(L, p1, "concatenate"); | 535 | luaG_typeerror(L, p1, "concatenate"); |
585 | } | 536 | } |
586 | 537 | ||
587 | 538 | ||
588 | void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { | 539 | l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { |
589 | TValue temp; | 540 | TValue temp; |
590 | if (luaV_tonumber(p1, &temp) == NULL) | 541 | if (luaV_tonumber(p1, &temp) == NULL) |
591 | p2 = p1; /* first operand is wrong */ | 542 | p2 = p1; /* first operand is wrong */ |
@@ -593,14 +544,13 @@ void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { | |||
593 | } | 544 | } |
594 | 545 | ||
595 | 546 | ||
596 | int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { | 547 | l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { |
597 | const char *t1 = luaT_typenames[ttype(p1)]; | 548 | const char *t1 = objtypename(p1); |
598 | const char *t2 = luaT_typenames[ttype(p2)]; | 549 | const char *t2 = objtypename(p2); |
599 | if (t1[2] == t2[2]) | 550 | if (t1 == t2) |
600 | luaG_runerror(L, "attempt to compare two %s values", t1); | 551 | luaG_runerror(L, "attempt to compare two %s values", t1); |
601 | else | 552 | else |
602 | luaG_runerror(L, "attempt to compare %s with %s", t1, t2); | 553 | luaG_runerror(L, "attempt to compare %s with %s", t1, t2); |
603 | return 0; | ||
604 | } | 554 | } |
605 | 555 | ||
606 | 556 | ||
@@ -608,27 +558,32 @@ static void addinfo (lua_State *L, const char *msg) { | |||
608 | CallInfo *ci = L->ci; | 558 | CallInfo *ci = L->ci; |
609 | if (isLua(ci)) { /* is Lua code? */ | 559 | if (isLua(ci)) { /* is Lua code? */ |
610 | char buff[LUA_IDSIZE]; /* add file:line information */ | 560 | char buff[LUA_IDSIZE]; /* add file:line information */ |
611 | int line = currentline(L, ci); | 561 | int line = currentline(ci); |
612 | luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); | 562 | TString *src = ci_func(ci)->p->source; |
563 | if (src) | ||
564 | luaO_chunkid(buff, getstr(src), LUA_IDSIZE); | ||
565 | else { /* no source available; use "?" instead */ | ||
566 | buff[0] = '?'; buff[1] = '\0'; | ||
567 | } | ||
613 | luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); | 568 | luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); |
614 | } | 569 | } |
615 | } | 570 | } |
616 | 571 | ||
617 | 572 | ||
618 | void luaG_errormsg (lua_State *L) { | 573 | l_noret luaG_errormsg (lua_State *L) { |
619 | if (L->errfunc != 0) { /* is there an error handling function? */ | 574 | if (L->errfunc != 0) { /* is there an error handling function? */ |
620 | StkId errfunc = restorestack(L, L->errfunc); | 575 | StkId errfunc = restorestack(L, L->errfunc); |
621 | if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); | 576 | if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); |
622 | setobjs2s(L, L->top, L->top - 1); /* move argument */ | 577 | setobjs2s(L, L->top, L->top - 1); /* move argument */ |
623 | setobjs2s(L, L->top - 1, errfunc); /* push function */ | 578 | setobjs2s(L, L->top - 1, errfunc); /* push function */ |
624 | incr_top(L); | 579 | L->top++; |
625 | luaD_call(L, L->top - 2, 1); /* call it */ | 580 | luaD_call(L, L->top - 2, 1, 0); /* call it */ |
626 | } | 581 | } |
627 | luaD_throw(L, LUA_ERRRUN); | 582 | luaD_throw(L, LUA_ERRRUN); |
628 | } | 583 | } |
629 | 584 | ||
630 | 585 | ||
631 | void luaG_runerror (lua_State *L, const char *fmt, ...) { | 586 | l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { |
632 | va_list argp; | 587 | va_list argp; |
633 | va_start(argp, fmt); | 588 | va_start(argp, fmt); |
634 | addinfo(L, luaO_pushvfstring(L, fmt, argp)); | 589 | addinfo(L, luaO_pushvfstring(L, fmt, argp)); |
diff --git a/apps/plugins/lua/ldebug.h b/apps/plugins/lua/ldebug.h index 22226b4096..6445c763ea 100644 --- a/apps/plugins/lua/ldebug.h +++ b/apps/plugins/lua/ldebug.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: ldebug.h,v 2.7.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Auxiliary functions from Debug Interface module | 3 | ** Auxiliary functions from Debug Interface module |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -13,21 +13,22 @@ | |||
13 | 13 | ||
14 | #define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) | 14 | #define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) |
15 | 15 | ||
16 | #define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) | 16 | #define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) |
17 | 17 | ||
18 | #define resethookcount(L) (L->hookcount = L->basehookcount) | 18 | #define resethookcount(L) (L->hookcount = L->basehookcount) |
19 | 19 | ||
20 | /* Active Lua function (given call info) */ | ||
21 | #define ci_func(ci) (clLvalue((ci)->func)) | ||
20 | 22 | ||
21 | LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, | 23 | |
22 | const char *opname); | 24 | LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, |
23 | LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); | 25 | const char *opname); |
24 | LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, | 26 | LUAI_FUNC l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2); |
25 | const TValue *p2); | 27 | LUAI_FUNC l_noret luaG_aritherror (lua_State *L, const TValue *p1, |
26 | LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, | 28 | const TValue *p2); |
27 | const TValue *p2); | 29 | LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, |
28 | LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); | 30 | const TValue *p2); |
29 | LUAI_FUNC void luaG_errormsg (lua_State *L); | 31 | LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); |
30 | LUAI_FUNC int luaG_checkcode (const Proto *pt); | 32 | LUAI_FUNC l_noret luaG_errormsg (lua_State *L); |
31 | LUAI_FUNC int luaG_checkopenop (Instruction i); | ||
32 | 33 | ||
33 | #endif | 34 | #endif |
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 | ||
diff --git a/apps/plugins/lua/ldo.h b/apps/plugins/lua/ldo.h index 4c97134805..d3d3082c9b 100644 --- a/apps/plugins/lua/ldo.h +++ b/apps/plugins/lua/ldo.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: ldo.h,v 2.20.1.1 2013/04/12 18:48:47 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 | */ |
@@ -13,45 +13,34 @@ | |||
13 | #include "lzio.h" | 13 | #include "lzio.h" |
14 | 14 | ||
15 | 15 | ||
16 | #define luaD_checkstack(L,n) \ | 16 | #define luaD_checkstack(L,n) if (L->stack_last - L->top <= (n)) \ |
17 | if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ | 17 | luaD_growstack(L, n); else condmovestack(L); |
18 | luaD_growstack(L, n); \ | ||
19 | else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); | ||
20 | 18 | ||
21 | 19 | ||
22 | #define incr_top(L) {luaD_checkstack(L,1); L->top++;} | 20 | #define incr_top(L) {L->top++; luaD_checkstack(L,0);} |
23 | 21 | ||
24 | #define savestack(L,p) ((char *)(p) - (char *)L->stack) | 22 | #define savestack(L,p) ((char *)(p) - (char *)L->stack) |
25 | #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) | 23 | #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) |
26 | 24 | ||
27 | #define saveci(L,p) ((char *)(p) - (char *)L->base_ci) | ||
28 | #define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) | ||
29 | |||
30 | |||
31 | /* results from luaD_precall */ | ||
32 | #define PCRLUA 0 /* initiated a call to a Lua function */ | ||
33 | #define PCRC 1 /* did a call to a C function */ | ||
34 | #define PCRYIELD 2 /* C funtion yielded */ | ||
35 | |||
36 | 25 | ||
37 | /* type of protected functions, to be ran by `runprotected' */ | 26 | /* type of protected functions, to be ran by `runprotected' */ |
38 | typedef void (*Pfunc) (lua_State *L, void *ud); | 27 | typedef void (*Pfunc) (lua_State *L, void *ud); |
39 | 28 | ||
40 | LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); | 29 | LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, |
41 | LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); | 30 | const char *mode); |
31 | LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); | ||
42 | LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); | 32 | LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); |
43 | LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); | 33 | LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults, |
34 | int allowyield); | ||
44 | LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, | 35 | LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, |
45 | ptrdiff_t oldtop, ptrdiff_t ef); | 36 | ptrdiff_t oldtop, ptrdiff_t ef); |
46 | LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); | 37 | LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); |
47 | LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); | ||
48 | LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); | 38 | LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); |
49 | LUAI_FUNC void luaD_growstack (lua_State *L, int n); | 39 | LUAI_FUNC void luaD_growstack (lua_State *L, int n); |
40 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); | ||
50 | 41 | ||
51 | LUAI_FUNC void luaD_throw (lua_State *L, int errcode); | 42 | LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); |
52 | LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); | 43 | LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); |
53 | 44 | ||
54 | LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); | ||
55 | |||
56 | #endif | 45 | #endif |
57 | 46 | ||
diff --git a/apps/plugins/lua/ldump.c b/apps/plugins/lua/ldump.c index c9d3d4870f..61fa2cd892 100644 --- a/apps/plugins/lua/ldump.c +++ b/apps/plugins/lua/ldump.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ | 2 | ** $Id: ldump.c,v 2.17.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** save precompiled Lua chunks | 3 | ** save precompiled Lua chunks |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -24,7 +24,7 @@ typedef struct { | |||
24 | } DumpState; | 24 | } DumpState; |
25 | 25 | ||
26 | #define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) | 26 | #define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) |
27 | #define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) | 27 | #define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) |
28 | 28 | ||
29 | static void DumpBlock(const void* b, size_t size, DumpState* D) | 29 | static void DumpBlock(const void* b, size_t size, DumpState* D) |
30 | { | 30 | { |
@@ -60,7 +60,7 @@ static void DumpVector(const void* b, int n, size_t size, DumpState* D) | |||
60 | 60 | ||
61 | static void DumpString(const TString* s, DumpState* D) | 61 | static void DumpString(const TString* s, DumpState* D) |
62 | { | 62 | { |
63 | if (s==NULL || getstr(s)==NULL) | 63 | if (s==NULL) |
64 | { | 64 | { |
65 | size_t size=0; | 65 | size_t size=0; |
66 | DumpVar(size,D); | 66 | DumpVar(size,D); |
@@ -69,13 +69,13 @@ static void DumpString(const TString* s, DumpState* D) | |||
69 | { | 69 | { |
70 | size_t size=s->tsv.len+1; /* include trailing '\0' */ | 70 | size_t size=s->tsv.len+1; /* include trailing '\0' */ |
71 | DumpVar(size,D); | 71 | DumpVar(size,D); |
72 | DumpBlock(getstr(s),size,D); | 72 | DumpBlock(getstr(s),size*sizeof(char),D); |
73 | } | 73 | } |
74 | } | 74 | } |
75 | 75 | ||
76 | #define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) | 76 | #define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) |
77 | 77 | ||
78 | static void DumpFunction(const Proto* f, const TString* p, DumpState* D); | 78 | static void DumpFunction(const Proto* f, DumpState* D); |
79 | 79 | ||
80 | static void DumpConstants(const Proto* f, DumpState* D) | 80 | static void DumpConstants(const Proto* f, DumpState* D) |
81 | { | 81 | { |
@@ -84,8 +84,8 @@ static void DumpConstants(const Proto* f, DumpState* D) | |||
84 | for (i=0; i<n; i++) | 84 | for (i=0; i<n; i++) |
85 | { | 85 | { |
86 | const TValue* o=&f->k[i]; | 86 | const TValue* o=&f->k[i]; |
87 | DumpChar(ttype(o),D); | 87 | DumpChar(ttypenv(o),D); |
88 | switch (ttype(o)) | 88 | switch (ttypenv(o)) |
89 | { | 89 | { |
90 | case LUA_TNIL: | 90 | case LUA_TNIL: |
91 | break; | 91 | break; |
@@ -98,19 +98,29 @@ static void DumpConstants(const Proto* f, DumpState* D) | |||
98 | case LUA_TSTRING: | 98 | case LUA_TSTRING: |
99 | DumpString(rawtsvalue(o),D); | 99 | DumpString(rawtsvalue(o),D); |
100 | break; | 100 | break; |
101 | default: | 101 | default: lua_assert(0); |
102 | lua_assert(0); /* cannot happen */ | ||
103 | break; | ||
104 | } | 102 | } |
105 | } | 103 | } |
106 | n=f->sizep; | 104 | n=f->sizep; |
107 | DumpInt(n,D); | 105 | DumpInt(n,D); |
108 | for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D); | 106 | for (i=0; i<n; i++) DumpFunction(f->p[i],D); |
107 | } | ||
108 | |||
109 | static void DumpUpvalues(const Proto* f, DumpState* D) | ||
110 | { | ||
111 | int i,n=f->sizeupvalues; | ||
112 | DumpInt(n,D); | ||
113 | for (i=0; i<n; i++) | ||
114 | { | ||
115 | DumpChar(f->upvalues[i].instack,D); | ||
116 | DumpChar(f->upvalues[i].idx,D); | ||
117 | } | ||
109 | } | 118 | } |
110 | 119 | ||
111 | static void DumpDebug(const Proto* f, DumpState* D) | 120 | static void DumpDebug(const Proto* f, DumpState* D) |
112 | { | 121 | { |
113 | int i,n; | 122 | int i,n; |
123 | DumpString((D->strip) ? NULL : f->source,D); | ||
114 | n= (D->strip) ? 0 : f->sizelineinfo; | 124 | n= (D->strip) ? 0 : f->sizelineinfo; |
115 | DumpVector(f->lineinfo,n,sizeof(int),D); | 125 | DumpVector(f->lineinfo,n,sizeof(int),D); |
116 | n= (D->strip) ? 0 : f->sizelocvars; | 126 | n= (D->strip) ? 0 : f->sizelocvars; |
@@ -123,26 +133,25 @@ static void DumpDebug(const Proto* f, DumpState* D) | |||
123 | } | 133 | } |
124 | n= (D->strip) ? 0 : f->sizeupvalues; | 134 | n= (D->strip) ? 0 : f->sizeupvalues; |
125 | DumpInt(n,D); | 135 | DumpInt(n,D); |
126 | for (i=0; i<n; i++) DumpString(f->upvalues[i],D); | 136 | for (i=0; i<n; i++) DumpString(f->upvalues[i].name,D); |
127 | } | 137 | } |
128 | 138 | ||
129 | static void DumpFunction(const Proto* f, const TString* p, DumpState* D) | 139 | static void DumpFunction(const Proto* f, DumpState* D) |
130 | { | 140 | { |
131 | DumpString((f->source==p || D->strip) ? NULL : f->source,D); | ||
132 | DumpInt(f->linedefined,D); | 141 | DumpInt(f->linedefined,D); |
133 | DumpInt(f->lastlinedefined,D); | 142 | DumpInt(f->lastlinedefined,D); |
134 | DumpChar(f->nups,D); | ||
135 | DumpChar(f->numparams,D); | 143 | DumpChar(f->numparams,D); |
136 | DumpChar(f->is_vararg,D); | 144 | DumpChar(f->is_vararg,D); |
137 | DumpChar(f->maxstacksize,D); | 145 | DumpChar(f->maxstacksize,D); |
138 | DumpCode(f,D); | 146 | DumpCode(f,D); |
139 | DumpConstants(f,D); | 147 | DumpConstants(f,D); |
148 | DumpUpvalues(f,D); | ||
140 | DumpDebug(f,D); | 149 | DumpDebug(f,D); |
141 | } | 150 | } |
142 | 151 | ||
143 | static void DumpHeader(DumpState* D) | 152 | static void DumpHeader(DumpState* D) |
144 | { | 153 | { |
145 | char h[LUAC_HEADERSIZE]; | 154 | lu_byte h[LUAC_HEADERSIZE]; |
146 | luaU_header(h); | 155 | luaU_header(h); |
147 | DumpBlock(h,LUAC_HEADERSIZE,D); | 156 | DumpBlock(h,LUAC_HEADERSIZE,D); |
148 | } | 157 | } |
@@ -159,6 +168,6 @@ int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip | |||
159 | D.strip=strip; | 168 | D.strip=strip; |
160 | D.status=0; | 169 | D.status=0; |
161 | DumpHeader(&D); | 170 | DumpHeader(&D); |
162 | DumpFunction(f,NULL,&D); | 171 | DumpFunction(f,&D); |
163 | return D.status; | 172 | return D.status; |
164 | } | 173 | } |
diff --git a/apps/plugins/lua/lfunc.c b/apps/plugins/lua/lfunc.c index 813e88f583..e90e1520ce 100644 --- a/apps/plugins/lua/lfunc.c +++ b/apps/plugins/lua/lfunc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ | 2 | ** $Id: lfunc.c,v 2.30.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -20,30 +20,24 @@ | |||
20 | 20 | ||
21 | 21 | ||
22 | 22 | ||
23 | Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { | 23 | Closure *luaF_newCclosure (lua_State *L, int n) { |
24 | Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); | 24 | Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n), NULL, 0)->cl; |
25 | luaC_link(L, obj2gco(c), LUA_TFUNCTION); | 25 | c->c.nupvalues = cast_byte(n); |
26 | c->c.isC = 1; | ||
27 | c->c.env = e; | ||
28 | c->c.nupvalues = cast_byte(nelems); | ||
29 | return c; | 26 | return c; |
30 | } | 27 | } |
31 | 28 | ||
32 | 29 | ||
33 | Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { | 30 | Closure *luaF_newLclosure (lua_State *L, int n) { |
34 | Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); | 31 | Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n), NULL, 0)->cl; |
35 | luaC_link(L, obj2gco(c), LUA_TFUNCTION); | 32 | c->l.p = NULL; |
36 | c->l.isC = 0; | 33 | c->l.nupvalues = cast_byte(n); |
37 | c->l.env = e; | 34 | while (n--) c->l.upvals[n] = NULL; |
38 | c->l.nupvalues = cast_byte(nelems); | ||
39 | while (nelems--) c->l.upvals[nelems] = NULL; | ||
40 | return c; | 35 | return c; |
41 | } | 36 | } |
42 | 37 | ||
43 | 38 | ||
44 | UpVal *luaF_newupval (lua_State *L) { | 39 | UpVal *luaF_newupval (lua_State *L) { |
45 | UpVal *uv = luaM_new(L, UpVal); | 40 | UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv; |
46 | luaC_link(L, obj2gco(uv), LUA_TUPVAL); | ||
47 | uv->v = &uv->u.value; | 41 | uv->v = &uv->u.value; |
48 | setnilvalue(uv->v); | 42 | setnilvalue(uv->v); |
49 | return uv; | 43 | return uv; |
@@ -55,21 +49,20 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { | |||
55 | GCObject **pp = &L->openupval; | 49 | GCObject **pp = &L->openupval; |
56 | UpVal *p; | 50 | UpVal *p; |
57 | UpVal *uv; | 51 | UpVal *uv; |
58 | while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { | 52 | while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { |
53 | GCObject *o = obj2gco(p); | ||
59 | lua_assert(p->v != &p->u.value); | 54 | lua_assert(p->v != &p->u.value); |
55 | lua_assert(!isold(o) || isold(obj2gco(L))); | ||
60 | if (p->v == level) { /* found a corresponding upvalue? */ | 56 | if (p->v == level) { /* found a corresponding upvalue? */ |
61 | if (isdead(g, obj2gco(p))) /* is it dead? */ | 57 | if (isdead(g, o)) /* is it dead? */ |
62 | changewhite(obj2gco(p)); /* ressurect it */ | 58 | changewhite(o); /* resurrect it */ |
63 | return p; | 59 | return p; |
64 | } | 60 | } |
65 | pp = &p->next; | 61 | pp = &p->next; |
66 | } | 62 | } |
67 | uv = luaM_new(L, UpVal); /* not found: create a new one */ | 63 | /* not found: create a new one */ |
68 | uv->tt = LUA_TUPVAL; | 64 | uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv; |
69 | uv->marked = luaC_white(g); | ||
70 | uv->v = level; /* current value lives in the stack */ | 65 | uv->v = level; /* current value lives in the stack */ |
71 | uv->next = *pp; /* chain it in the proper position */ | ||
72 | *pp = obj2gco(uv); | ||
73 | uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ | 66 | uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ |
74 | uv->u.l.next = g->uvhead.u.l.next; | 67 | uv->u.l.next = g->uvhead.u.l.next; |
75 | uv->u.l.next->u.l.prev = uv; | 68 | uv->u.l.next->u.l.prev = uv; |
@@ -96,41 +89,42 @@ void luaF_freeupval (lua_State *L, UpVal *uv) { | |||
96 | void luaF_close (lua_State *L, StkId level) { | 89 | void luaF_close (lua_State *L, StkId level) { |
97 | UpVal *uv; | 90 | UpVal *uv; |
98 | global_State *g = G(L); | 91 | global_State *g = G(L); |
99 | while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { | 92 | while (L->openupval != NULL && (uv = gco2uv(L->openupval))->v >= level) { |
100 | GCObject *o = obj2gco(uv); | 93 | GCObject *o = obj2gco(uv); |
101 | lua_assert(!isblack(o) && uv->v != &uv->u.value); | 94 | lua_assert(!isblack(o) && uv->v != &uv->u.value); |
102 | L->openupval = uv->next; /* remove from `open' list */ | 95 | L->openupval = uv->next; /* remove from `open' list */ |
103 | if (isdead(g, o)) | 96 | if (isdead(g, o)) |
104 | luaF_freeupval(L, uv); /* free upvalue */ | 97 | luaF_freeupval(L, uv); /* free upvalue */ |
105 | else { | 98 | else { |
106 | unlinkupval(uv); | 99 | unlinkupval(uv); /* remove upvalue from 'uvhead' list */ |
107 | setobj(L, &uv->u.value, uv->v); | 100 | setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ |
108 | uv->v = &uv->u.value; /* now current value lives here */ | 101 | uv->v = &uv->u.value; /* now current value lives here */ |
109 | luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ | 102 | gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */ |
103 | g->allgc = o; | ||
104 | luaC_checkupvalcolor(g, uv); | ||
110 | } | 105 | } |
111 | } | 106 | } |
112 | } | 107 | } |
113 | 108 | ||
114 | 109 | ||
115 | Proto *luaF_newproto (lua_State *L) { | 110 | Proto *luaF_newproto (lua_State *L) { |
116 | Proto *f = luaM_new(L, Proto); | 111 | Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p; |
117 | luaC_link(L, obj2gco(f), LUA_TPROTO); | ||
118 | f->k = NULL; | 112 | f->k = NULL; |
119 | f->sizek = 0; | 113 | f->sizek = 0; |
120 | f->p = NULL; | 114 | f->p = NULL; |
121 | f->sizep = 0; | 115 | f->sizep = 0; |
122 | f->code = NULL; | 116 | f->code = NULL; |
117 | f->cache = NULL; | ||
123 | f->sizecode = 0; | 118 | f->sizecode = 0; |
119 | f->lineinfo = NULL; | ||
124 | f->sizelineinfo = 0; | 120 | f->sizelineinfo = 0; |
125 | f->sizeupvalues = 0; | ||
126 | f->nups = 0; | ||
127 | f->upvalues = NULL; | 121 | f->upvalues = NULL; |
122 | f->sizeupvalues = 0; | ||
128 | f->numparams = 0; | 123 | f->numparams = 0; |
129 | f->is_vararg = 0; | 124 | f->is_vararg = 0; |
130 | f->maxstacksize = 0; | 125 | f->maxstacksize = 0; |
131 | f->lineinfo = NULL; | ||
132 | f->sizelocvars = 0; | ||
133 | f->locvars = NULL; | 126 | f->locvars = NULL; |
127 | f->sizelocvars = 0; | ||
134 | f->linedefined = 0; | 128 | f->linedefined = 0; |
135 | f->lastlinedefined = 0; | 129 | f->lastlinedefined = 0; |
136 | f->source = NULL; | 130 | f->source = NULL; |
@@ -139,23 +133,16 @@ Proto *luaF_newproto (lua_State *L) { | |||
139 | 133 | ||
140 | 134 | ||
141 | void luaF_freeproto (lua_State *L, Proto *f) { | 135 | void luaF_freeproto (lua_State *L, Proto *f) { |
142 | luaM_freearray(L, f->code, f->sizecode, Instruction); | 136 | luaM_freearray(L, f->code, f->sizecode); |
143 | luaM_freearray(L, f->p, f->sizep, Proto *); | 137 | luaM_freearray(L, f->p, f->sizep); |
144 | luaM_freearray(L, f->k, f->sizek, TValue); | 138 | luaM_freearray(L, f->k, f->sizek); |
145 | luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); | 139 | luaM_freearray(L, f->lineinfo, f->sizelineinfo); |
146 | luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); | 140 | luaM_freearray(L, f->locvars, f->sizelocvars); |
147 | luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); | 141 | luaM_freearray(L, f->upvalues, f->sizeupvalues); |
148 | luaM_free(L, f); | 142 | luaM_free(L, f); |
149 | } | 143 | } |
150 | 144 | ||
151 | 145 | ||
152 | void luaF_freeclosure (lua_State *L, Closure *c) { | ||
153 | int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : | ||
154 | sizeLclosure(c->l.nupvalues); | ||
155 | luaM_freemem(L, c, size); | ||
156 | } | ||
157 | |||
158 | |||
159 | /* | 146 | /* |
160 | ** Look for n-th local variable at line `line' in function `func'. | 147 | ** Look for n-th local variable at line `line' in function `func'. |
161 | ** Returns NULL if not found. | 148 | ** Returns NULL if not found. |
diff --git a/apps/plugins/lua/lfunc.h b/apps/plugins/lua/lfunc.h index 4c2b7fd138..ca0d3a3e0b 100644 --- a/apps/plugins/lua/lfunc.h +++ b/apps/plugins/lua/lfunc.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lfunc.h,v 2.8.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -19,13 +19,12 @@ | |||
19 | 19 | ||
20 | 20 | ||
21 | LUAI_FUNC Proto *luaF_newproto (lua_State *L); | 21 | LUAI_FUNC Proto *luaF_newproto (lua_State *L); |
22 | LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); | 22 | LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems); |
23 | LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); | 23 | LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems); |
24 | LUAI_FUNC UpVal *luaF_newupval (lua_State *L); | 24 | LUAI_FUNC UpVal *luaF_newupval (lua_State *L); |
25 | LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); | 25 | LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); |
26 | LUAI_FUNC void luaF_close (lua_State *L, StkId level); | 26 | LUAI_FUNC void luaF_close (lua_State *L, StkId level); |
27 | LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); | 27 | LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); |
28 | LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); | ||
29 | LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); | 28 | LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); |
30 | LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, | 29 | LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, |
31 | int pc); | 30 | int pc); |
diff --git a/apps/plugins/lua/lgc.c b/apps/plugins/lua/lgc.c index d9e0b78294..52460dcdd5 100644 --- a/apps/plugins/lua/lgc.c +++ b/apps/plugins/lua/lgc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $ | 2 | ** $Id: lgc.c,v 2.140.1.2 2013/04/26 18:22:05 roberto Exp $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -23,376 +23,663 @@ | |||
23 | #include "ltm.h" | 23 | #include "ltm.h" |
24 | 24 | ||
25 | 25 | ||
26 | #define GCSTEPSIZE 1024u | ||
27 | #define GCSWEEPMAX 40 | ||
28 | #define GCSWEEPCOST 10 | ||
29 | #define GCFINALIZECOST 100 | ||
30 | 26 | ||
27 | /* | ||
28 | ** cost of sweeping one element (the size of a small object divided | ||
29 | ** by some adjust for the sweep speed) | ||
30 | */ | ||
31 | #define GCSWEEPCOST ((sizeof(TString) + 4) / 4) | ||
31 | 32 | ||
32 | #define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) | 33 | /* maximum number of elements to sweep in each single step */ |
34 | #define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) | ||
33 | 35 | ||
34 | #define makewhite(g,x) \ | 36 | /* maximum number of finalizers to call in each GC step */ |
35 | ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) | 37 | #define GCFINALIZENUM 4 |
38 | |||
39 | |||
40 | /* | ||
41 | ** macro to adjust 'stepmul': 'stepmul' is actually used like | ||
42 | ** 'stepmul / STEPMULADJ' (value chosen by tests) | ||
43 | */ | ||
44 | #define STEPMULADJ 200 | ||
45 | |||
46 | |||
47 | /* | ||
48 | ** macro to adjust 'pause': 'pause' is actually used like | ||
49 | ** 'pause / PAUSEADJ' (value chosen by tests) | ||
50 | */ | ||
51 | #define PAUSEADJ 100 | ||
36 | 52 | ||
37 | #define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) | ||
38 | #define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) | ||
39 | 53 | ||
40 | #define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) | 54 | /* |
55 | ** 'makewhite' erases all color bits plus the old bit and then | ||
56 | ** sets only the current white bit | ||
57 | */ | ||
58 | #define maskcolors (~(bit2mask(BLACKBIT, OLDBIT) | WHITEBITS)) | ||
59 | #define makewhite(g,x) \ | ||
60 | (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) | ||
41 | 61 | ||
62 | #define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) | ||
63 | #define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) | ||
42 | 64 | ||
43 | #define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) | ||
44 | #define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) | ||
45 | 65 | ||
66 | #define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) | ||
46 | 67 | ||
47 | #define KEYWEAK bitmask(KEYWEAKBIT) | 68 | #define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) |
48 | #define VALUEWEAK bitmask(VALUEWEAKBIT) | ||
49 | 69 | ||
50 | 70 | ||
71 | #define checkconsistency(obj) \ | ||
72 | lua_longassert(!iscollectable(obj) || righttt(obj)) | ||
73 | |||
51 | 74 | ||
52 | #define markvalue(g,o) { checkconsistency(o); \ | 75 | #define markvalue(g,o) { checkconsistency(o); \ |
53 | if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } | 76 | if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } |
54 | 77 | ||
55 | #define markobject(g,t) { if (iswhite(obj2gco(t))) \ | 78 | #define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \ |
56 | reallymarkobject(g, obj2gco(t)); } | 79 | reallymarkobject(g, obj2gco(t)); } |
57 | 80 | ||
81 | static void reallymarkobject (global_State *g, GCObject *o); | ||
82 | |||
83 | |||
84 | /* | ||
85 | ** {====================================================== | ||
86 | ** Generic functions | ||
87 | ** ======================================================= | ||
88 | */ | ||
89 | |||
90 | |||
91 | /* | ||
92 | ** one after last element in a hash array | ||
93 | */ | ||
94 | #define gnodelast(h) gnode(h, cast(size_t, sizenode(h))) | ||
95 | |||
58 | 96 | ||
59 | #define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) | 97 | /* |
98 | ** link table 'h' into list pointed by 'p' | ||
99 | */ | ||
100 | #define linktable(h,p) ((h)->gclist = *(p), *(p) = obj2gco(h)) | ||
60 | 101 | ||
61 | 102 | ||
103 | /* | ||
104 | ** if key is not marked, mark its entry as dead (therefore removing it | ||
105 | ** from the table) | ||
106 | */ | ||
62 | static void removeentry (Node *n) { | 107 | static void removeentry (Node *n) { |
63 | lua_assert(ttisnil(gval(n))); | 108 | lua_assert(ttisnil(gval(n))); |
64 | if (iscollectable(gkey(n))) | 109 | if (valiswhite(gkey(n))) |
65 | setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ | 110 | setdeadvalue(gkey(n)); /* unused and unmarked key; remove it */ |
111 | } | ||
112 | |||
113 | |||
114 | /* | ||
115 | ** tells whether a key or value can be cleared from a weak | ||
116 | ** table. Non-collectable objects are never removed from weak | ||
117 | ** tables. Strings behave as `values', so are never removed too. for | ||
118 | ** other objects: if really collected, cannot keep them; for objects | ||
119 | ** being finalized, keep them in keys, but not in values | ||
120 | */ | ||
121 | static int iscleared (global_State *g, const TValue *o) { | ||
122 | if (!iscollectable(o)) return 0; | ||
123 | else if (ttisstring(o)) { | ||
124 | markobject(g, rawtsvalue(o)); /* strings are `values', so are never weak */ | ||
125 | return 0; | ||
126 | } | ||
127 | else return iswhite(gcvalue(o)); | ||
66 | } | 128 | } |
67 | 129 | ||
68 | 130 | ||
131 | /* | ||
132 | ** barrier that moves collector forward, that is, mark the white object | ||
133 | ** being pointed by a black object. | ||
134 | */ | ||
135 | void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { | ||
136 | global_State *g = G(L); | ||
137 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); | ||
138 | lua_assert(g->gcstate != GCSpause); | ||
139 | lua_assert(gch(o)->tt != LUA_TTABLE); | ||
140 | if (keepinvariantout(g)) /* must keep invariant? */ | ||
141 | reallymarkobject(g, v); /* restore invariant */ | ||
142 | else { /* sweep phase */ | ||
143 | lua_assert(issweepphase(g)); | ||
144 | makewhite(g, o); /* mark main obj. as white to avoid other barriers */ | ||
145 | } | ||
146 | } | ||
147 | |||
148 | |||
149 | /* | ||
150 | ** barrier that moves collector backward, that is, mark the black object | ||
151 | ** pointing to a white object as gray again. (Current implementation | ||
152 | ** only works for tables; access to 'gclist' is not uniform across | ||
153 | ** different types.) | ||
154 | */ | ||
155 | void luaC_barrierback_ (lua_State *L, GCObject *o) { | ||
156 | global_State *g = G(L); | ||
157 | lua_assert(isblack(o) && !isdead(g, o) && gch(o)->tt == LUA_TTABLE); | ||
158 | black2gray(o); /* make object gray (again) */ | ||
159 | gco2t(o)->gclist = g->grayagain; | ||
160 | g->grayagain = o; | ||
161 | } | ||
162 | |||
163 | |||
164 | /* | ||
165 | ** barrier for prototypes. When creating first closure (cache is | ||
166 | ** NULL), use a forward barrier; this may be the only closure of the | ||
167 | ** prototype (if it is a "regular" function, with a single instance) | ||
168 | ** and the prototype may be big, so it is better to avoid traversing | ||
169 | ** it again. Otherwise, use a backward barrier, to avoid marking all | ||
170 | ** possible instances. | ||
171 | */ | ||
172 | LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c) { | ||
173 | global_State *g = G(L); | ||
174 | lua_assert(isblack(obj2gco(p))); | ||
175 | if (p->cache == NULL) { /* first time? */ | ||
176 | luaC_objbarrier(L, p, c); | ||
177 | } | ||
178 | else { /* use a backward barrier */ | ||
179 | black2gray(obj2gco(p)); /* make prototype gray (again) */ | ||
180 | p->gclist = g->grayagain; | ||
181 | g->grayagain = obj2gco(p); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | |||
186 | /* | ||
187 | ** check color (and invariants) for an upvalue that was closed, | ||
188 | ** i.e., moved into the 'allgc' list | ||
189 | */ | ||
190 | void luaC_checkupvalcolor (global_State *g, UpVal *uv) { | ||
191 | GCObject *o = obj2gco(uv); | ||
192 | lua_assert(!isblack(o)); /* open upvalues are never black */ | ||
193 | if (isgray(o)) { | ||
194 | if (keepinvariant(g)) { | ||
195 | resetoldbit(o); /* see MOVE OLD rule */ | ||
196 | gray2black(o); /* it is being visited now */ | ||
197 | markvalue(g, uv->v); | ||
198 | } | ||
199 | else { | ||
200 | lua_assert(issweepphase(g)); | ||
201 | makewhite(g, o); | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | |||
206 | |||
207 | /* | ||
208 | ** create a new collectable object (with given type and size) and link | ||
209 | ** it to '*list'. 'offset' tells how many bytes to allocate before the | ||
210 | ** object itself (used only by states). | ||
211 | */ | ||
212 | GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, | ||
213 | int offset) { | ||
214 | global_State *g = G(L); | ||
215 | char *raw = cast(char *, luaM_newobject(L, novariant(tt), sz)); | ||
216 | GCObject *o = obj2gco(raw + offset); | ||
217 | if (list == NULL) | ||
218 | list = &g->allgc; /* standard list for collectable objects */ | ||
219 | gch(o)->marked = luaC_white(g); | ||
220 | gch(o)->tt = tt; | ||
221 | gch(o)->next = *list; | ||
222 | *list = o; | ||
223 | return o; | ||
224 | } | ||
225 | |||
226 | /* }====================================================== */ | ||
227 | |||
228 | |||
229 | |||
230 | /* | ||
231 | ** {====================================================== | ||
232 | ** Mark functions | ||
233 | ** ======================================================= | ||
234 | */ | ||
235 | |||
236 | |||
237 | /* | ||
238 | ** mark an object. Userdata, strings, and closed upvalues are visited | ||
239 | ** and turned black here. Other objects are marked gray and added | ||
240 | ** to appropriate list to be visited (and turned black) later. (Open | ||
241 | ** upvalues are already linked in 'headuv' list.) | ||
242 | */ | ||
69 | static void reallymarkobject (global_State *g, GCObject *o) { | 243 | static void reallymarkobject (global_State *g, GCObject *o) { |
70 | lua_assert(iswhite(o) && !isdead(g, o)); | 244 | lu_mem size; |
71 | white2gray(o); | 245 | white2gray(o); |
72 | switch (o->gch.tt) { | 246 | switch (gch(o)->tt) { |
73 | case LUA_TSTRING: { | 247 | case LUA_TSHRSTR: |
74 | return; | 248 | case LUA_TLNGSTR: { |
249 | size = sizestring(gco2ts(o)); | ||
250 | break; /* nothing else to mark; make it black */ | ||
75 | } | 251 | } |
76 | case LUA_TUSERDATA: { | 252 | case LUA_TUSERDATA: { |
77 | Table *mt = gco2u(o)->metatable; | 253 | Table *mt = gco2u(o)->metatable; |
78 | gray2black(o); /* udata are never gray */ | 254 | markobject(g, mt); |
79 | if (mt) markobject(g, mt); | ||
80 | markobject(g, gco2u(o)->env); | 255 | markobject(g, gco2u(o)->env); |
81 | return; | 256 | size = sizeudata(gco2u(o)); |
257 | break; | ||
82 | } | 258 | } |
83 | case LUA_TUPVAL: { | 259 | case LUA_TUPVAL: { |
84 | UpVal *uv = gco2uv(o); | 260 | UpVal *uv = gco2uv(o); |
85 | markvalue(g, uv->v); | 261 | markvalue(g, uv->v); |
86 | if (uv->v == &uv->u.value) /* closed? */ | 262 | if (uv->v != &uv->u.value) /* open? */ |
87 | gray2black(o); /* open upvalues are never black */ | 263 | return; /* open upvalues remain gray */ |
264 | size = sizeof(UpVal); | ||
265 | break; | ||
266 | } | ||
267 | case LUA_TLCL: { | ||
268 | gco2lcl(o)->gclist = g->gray; | ||
269 | g->gray = o; | ||
88 | return; | 270 | return; |
89 | } | 271 | } |
90 | case LUA_TFUNCTION: { | 272 | case LUA_TCCL: { |
91 | gco2cl(o)->c.gclist = g->gray; | 273 | gco2ccl(o)->gclist = g->gray; |
92 | g->gray = o; | 274 | g->gray = o; |
93 | break; | 275 | return; |
94 | } | 276 | } |
95 | case LUA_TTABLE: { | 277 | case LUA_TTABLE: { |
96 | gco2h(o)->gclist = g->gray; | 278 | linktable(gco2t(o), &g->gray); |
97 | g->gray = o; | 279 | return; |
98 | break; | ||
99 | } | 280 | } |
100 | case LUA_TTHREAD: { | 281 | case LUA_TTHREAD: { |
101 | gco2th(o)->gclist = g->gray; | 282 | gco2th(o)->gclist = g->gray; |
102 | g->gray = o; | 283 | g->gray = o; |
103 | break; | 284 | return; |
104 | } | 285 | } |
105 | case LUA_TPROTO: { | 286 | case LUA_TPROTO: { |
106 | gco2p(o)->gclist = g->gray; | 287 | gco2p(o)->gclist = g->gray; |
107 | g->gray = o; | 288 | g->gray = o; |
108 | break; | 289 | return; |
109 | } | 290 | } |
110 | default: lua_assert(0); | 291 | default: lua_assert(0); return; |
111 | } | 292 | } |
293 | gray2black(o); | ||
294 | g->GCmemtrav += size; | ||
295 | } | ||
296 | |||
297 | |||
298 | /* | ||
299 | ** mark metamethods for basic types | ||
300 | */ | ||
301 | static void markmt (global_State *g) { | ||
302 | int i; | ||
303 | for (i=0; i < LUA_NUMTAGS; i++) | ||
304 | markobject(g, g->mt[i]); | ||
112 | } | 305 | } |
113 | 306 | ||
114 | 307 | ||
115 | static void marktmu (global_State *g) { | 308 | /* |
116 | GCObject *u = g->tmudata; | 309 | ** mark all objects in list of being-finalized |
117 | if (u) { | 310 | */ |
118 | do { | 311 | static void markbeingfnz (global_State *g) { |
119 | u = u->gch.next; | 312 | GCObject *o; |
120 | makewhite(g, u); /* may be marked, if left from previous GC */ | 313 | for (o = g->tobefnz; o != NULL; o = gch(o)->next) { |
121 | reallymarkobject(g, u); | 314 | makewhite(g, o); |
122 | } while (u != g->tmudata); | 315 | reallymarkobject(g, o); |
123 | } | 316 | } |
124 | } | 317 | } |
125 | 318 | ||
126 | 319 | ||
127 | /* move `dead' udata that need finalization to list `tmudata' */ | 320 | /* |
128 | size_t luaC_separateudata (lua_State *L, int all) { | 321 | ** mark all values stored in marked open upvalues. (See comment in |
129 | global_State *g = G(L); | 322 | ** 'lstate.h'.) |
130 | size_t deadmem = 0; | 323 | */ |
131 | GCObject **p = &g->mainthread->next; | 324 | static void remarkupvals (global_State *g) { |
132 | GCObject *curr; | 325 | UpVal *uv; |
133 | while ((curr = *p) != NULL) { | 326 | for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { |
134 | if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) | 327 | if (isgray(obj2gco(uv))) |
135 | p = &curr->gch.next; /* don't bother with them */ | 328 | markvalue(g, uv->v); |
136 | else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { | ||
137 | markfinalized(gco2u(curr)); /* don't need finalization */ | ||
138 | p = &curr->gch.next; | ||
139 | } | ||
140 | else { /* must call its gc method */ | ||
141 | deadmem += sizeudata(gco2u(curr)); | ||
142 | markfinalized(gco2u(curr)); | ||
143 | *p = curr->gch.next; | ||
144 | /* link `curr' at the end of `tmudata' list */ | ||
145 | if (g->tmudata == NULL) /* list is empty? */ | ||
146 | g->tmudata = curr->gch.next = curr; /* creates a circular list */ | ||
147 | else { | ||
148 | curr->gch.next = g->tmudata->gch.next; | ||
149 | g->tmudata->gch.next = curr; | ||
150 | g->tmudata = curr; | ||
151 | } | ||
152 | } | ||
153 | } | 329 | } |
154 | return deadmem; | ||
155 | } | 330 | } |
156 | 331 | ||
157 | 332 | ||
158 | static int traversetable (global_State *g, Table *h) { | 333 | /* |
159 | int i; | 334 | ** mark root set and reset all gray lists, to start a new |
160 | int weakkey = 0; | 335 | ** incremental (or full) collection |
161 | int weakvalue = 0; | 336 | */ |
162 | const TValue *mode; | 337 | static void restartcollection (global_State *g) { |
163 | if (h->metatable) | 338 | g->gray = g->grayagain = NULL; |
164 | markobject(g, h->metatable); | 339 | g->weak = g->allweak = g->ephemeron = NULL; |
165 | mode = gfasttm(g, h->metatable, TM_MODE); | 340 | markobject(g, g->mainthread); |
166 | if (mode && ttisstring(mode)) { /* is there a weak mode? */ | 341 | markvalue(g, &g->l_registry); |
167 | weakkey = (strchr(svalue(mode), 'k') != NULL); | 342 | markmt(g); |
168 | weakvalue = (strchr(svalue(mode), 'v') != NULL); | 343 | markbeingfnz(g); /* mark any finalizing object left from previous cycle */ |
169 | if (weakkey || weakvalue) { /* is really weak? */ | 344 | } |
170 | h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ | 345 | |
171 | h->marked |= cast_byte((weakkey << KEYWEAKBIT) | | 346 | /* }====================================================== */ |
172 | (weakvalue << VALUEWEAKBIT)); | 347 | |
173 | h->gclist = g->weak; /* must be cleared after GC, ... */ | 348 | |
174 | g->weak = obj2gco(h); /* ... so put in the appropriate list */ | 349 | /* |
175 | } | 350 | ** {====================================================== |
176 | } | 351 | ** Traverse functions |
177 | if (weakkey && weakvalue) return 1; | 352 | ** ======================================================= |
178 | if (!weakvalue) { | 353 | */ |
179 | i = h->sizearray; | 354 | |
180 | while (i--) | 355 | static void traverseweakvalue (global_State *g, Table *h) { |
181 | markvalue(g, &h->array[i]); | 356 | Node *n, *limit = gnodelast(h); |
182 | } | 357 | /* if there is array part, assume it may have white values (do not |
183 | i = sizenode(h); | 358 | traverse it just to check) */ |
184 | while (i--) { | 359 | int hasclears = (h->sizearray > 0); |
185 | Node *n = gnode(h, i); | 360 | for (n = gnode(h, 0); n < limit; n++) { |
186 | lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); | 361 | checkdeadkey(n); |
187 | if (ttisnil(gval(n))) | 362 | if (ttisnil(gval(n))) /* entry is empty? */ |
188 | removeentry(n); /* remove empty entries */ | 363 | removeentry(n); /* remove it */ |
189 | else { | 364 | else { |
190 | lua_assert(!ttisnil(gkey(n))); | 365 | lua_assert(!ttisnil(gkey(n))); |
191 | if (!weakkey) markvalue(g, gkey(n)); | 366 | markvalue(g, gkey(n)); /* mark key */ |
192 | if (!weakvalue) markvalue(g, gval(n)); | 367 | if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ |
368 | hasclears = 1; /* table will have to be cleared */ | ||
193 | } | 369 | } |
194 | } | 370 | } |
195 | return weakkey || weakvalue; | 371 | if (hasclears) |
372 | linktable(h, &g->weak); /* has to be cleared later */ | ||
373 | else /* no white values */ | ||
374 | linktable(h, &g->grayagain); /* no need to clean */ | ||
196 | } | 375 | } |
197 | 376 | ||
198 | 377 | ||
199 | /* | 378 | static int traverseephemeron (global_State *g, Table *h) { |
200 | ** All marks are conditional because a GC may happen while the | 379 | int marked = 0; /* true if an object is marked in this traversal */ |
201 | ** prototype is still being created | 380 | int hasclears = 0; /* true if table has white keys */ |
202 | */ | 381 | int prop = 0; /* true if table has entry "white-key -> white-value" */ |
203 | static void traverseproto (global_State *g, Proto *f) { | 382 | Node *n, *limit = gnodelast(h); |
204 | int i; | 383 | int i; |
205 | if (f->source) stringmark(f->source); | 384 | /* traverse array part (numeric keys are 'strong') */ |
206 | for (i=0; i<f->sizek; i++) /* mark literals */ | 385 | for (i = 0; i < h->sizearray; i++) { |
207 | markvalue(g, &f->k[i]); | 386 | if (valiswhite(&h->array[i])) { |
208 | for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */ | 387 | marked = 1; |
209 | if (f->upvalues[i]) | 388 | reallymarkobject(g, gcvalue(&h->array[i])); |
210 | stringmark(f->upvalues[i]); | 389 | } |
211 | } | ||
212 | for (i=0; i<f->sizep; i++) { /* mark nested protos */ | ||
213 | if (f->p[i]) | ||
214 | markobject(g, f->p[i]); | ||
215 | } | 390 | } |
216 | for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */ | 391 | /* traverse hash part */ |
217 | if (f->locvars[i].varname) | 392 | for (n = gnode(h, 0); n < limit; n++) { |
218 | stringmark(f->locvars[i].varname); | 393 | checkdeadkey(n); |
394 | if (ttisnil(gval(n))) /* entry is empty? */ | ||
395 | removeentry(n); /* remove it */ | ||
396 | else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */ | ||
397 | hasclears = 1; /* table must be cleared */ | ||
398 | if (valiswhite(gval(n))) /* value not marked yet? */ | ||
399 | prop = 1; /* must propagate again */ | ||
400 | } | ||
401 | else if (valiswhite(gval(n))) { /* value not marked yet? */ | ||
402 | marked = 1; | ||
403 | reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ | ||
404 | } | ||
219 | } | 405 | } |
406 | if (prop) | ||
407 | linktable(h, &g->ephemeron); /* have to propagate again */ | ||
408 | else if (hasclears) /* does table have white keys? */ | ||
409 | linktable(h, &g->allweak); /* may have to clean white keys */ | ||
410 | else /* no white keys */ | ||
411 | linktable(h, &g->grayagain); /* no need to clean */ | ||
412 | return marked; | ||
220 | } | 413 | } |
221 | 414 | ||
222 | 415 | ||
223 | 416 | static void traversestrongtable (global_State *g, Table *h) { | |
224 | static void traverseclosure (global_State *g, Closure *cl) { | 417 | Node *n, *limit = gnodelast(h); |
225 | markobject(g, cl->c.env); | 418 | int i; |
226 | if (cl->c.isC) { | 419 | for (i = 0; i < h->sizearray; i++) /* traverse array part */ |
227 | int i; | 420 | markvalue(g, &h->array[i]); |
228 | for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */ | 421 | for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ |
229 | markvalue(g, &cl->c.upvalue[i]); | 422 | checkdeadkey(n); |
423 | if (ttisnil(gval(n))) /* entry is empty? */ | ||
424 | removeentry(n); /* remove it */ | ||
425 | else { | ||
426 | lua_assert(!ttisnil(gkey(n))); | ||
427 | markvalue(g, gkey(n)); /* mark key */ | ||
428 | markvalue(g, gval(n)); /* mark value */ | ||
429 | } | ||
230 | } | 430 | } |
231 | else { | 431 | } |
232 | int i; | 432 | |
233 | lua_assert(cl->l.nupvalues == cl->l.p->nups); | 433 | |
234 | markobject(g, cl->l.p); | 434 | static lu_mem traversetable (global_State *g, Table *h) { |
235 | for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */ | 435 | const char *weakkey, *weakvalue; |
236 | markobject(g, cl->l.upvals[i]); | 436 | const TValue *mode = gfasttm(g, h->metatable, TM_MODE); |
437 | markobject(g, h->metatable); | ||
438 | if (mode && ttisstring(mode) && /* is there a weak mode? */ | ||
439 | ((weakkey = strchr(svalue(mode), 'k')), | ||
440 | (weakvalue = strchr(svalue(mode), 'v')), | ||
441 | (weakkey || weakvalue))) { /* is really weak? */ | ||
442 | black2gray(obj2gco(h)); /* keep table gray */ | ||
443 | if (!weakkey) /* strong keys? */ | ||
444 | traverseweakvalue(g, h); | ||
445 | else if (!weakvalue) /* strong values? */ | ||
446 | traverseephemeron(g, h); | ||
447 | else /* all weak */ | ||
448 | linktable(h, &g->allweak); /* nothing to traverse now */ | ||
237 | } | 449 | } |
450 | else /* not weak */ | ||
451 | traversestrongtable(g, h); | ||
452 | return sizeof(Table) + sizeof(TValue) * h->sizearray + | ||
453 | sizeof(Node) * cast(size_t, sizenode(h)); | ||
238 | } | 454 | } |
239 | 455 | ||
240 | 456 | ||
241 | static void checkstacksizes (lua_State *L, StkId max) { | 457 | static int traverseproto (global_State *g, Proto *f) { |
242 | int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ | 458 | int i; |
243 | int s_used = cast_int(max - L->stack); /* part of stack in use */ | 459 | if (f->cache && iswhite(obj2gco(f->cache))) |
244 | if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ | 460 | f->cache = NULL; /* allow cache to be collected */ |
245 | return; /* do not touch the stacks */ | 461 | markobject(g, f->source); |
246 | if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) | 462 | for (i = 0; i < f->sizek; i++) /* mark literals */ |
247 | luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ | 463 | markvalue(g, &f->k[i]); |
248 | condhardstacktests(luaD_reallocCI(L, ci_used + 1)); | 464 | for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ |
249 | if (4*s_used < L->stacksize && | 465 | markobject(g, f->upvalues[i].name); |
250 | 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) | 466 | for (i = 0; i < f->sizep; i++) /* mark nested protos */ |
251 | luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ | 467 | markobject(g, f->p[i]); |
252 | condhardstacktests(luaD_reallocstack(L, s_used)); | 468 | for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ |
469 | markobject(g, f->locvars[i].varname); | ||
470 | return sizeof(Proto) + sizeof(Instruction) * f->sizecode + | ||
471 | sizeof(Proto *) * f->sizep + | ||
472 | sizeof(TValue) * f->sizek + | ||
473 | sizeof(int) * f->sizelineinfo + | ||
474 | sizeof(LocVar) * f->sizelocvars + | ||
475 | sizeof(Upvaldesc) * f->sizeupvalues; | ||
253 | } | 476 | } |
254 | 477 | ||
255 | 478 | ||
256 | static void traversestack (global_State *g, lua_State *l) { | 479 | static lu_mem traverseCclosure (global_State *g, CClosure *cl) { |
257 | StkId o, lim; | 480 | int i; |
258 | CallInfo *ci; | 481 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ |
259 | markvalue(g, gt(l)); | 482 | markvalue(g, &cl->upvalue[i]); |
260 | lim = l->top; | 483 | return sizeCclosure(cl->nupvalues); |
261 | for (ci = l->base_ci; ci <= l->ci; ci++) { | 484 | } |
262 | lua_assert(ci->top <= l->stack_last); | 485 | |
263 | if (lim < ci->top) lim = ci->top; | 486 | static lu_mem traverseLclosure (global_State *g, LClosure *cl) { |
264 | } | 487 | int i; |
265 | for (o = l->stack; o < l->top; o++) | 488 | markobject(g, cl->p); /* mark its prototype */ |
489 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ | ||
490 | markobject(g, cl->upvals[i]); | ||
491 | return sizeLclosure(cl->nupvalues); | ||
492 | } | ||
493 | |||
494 | |||
495 | static lu_mem traversestack (global_State *g, lua_State *th) { | ||
496 | int n = 0; | ||
497 | StkId o = th->stack; | ||
498 | if (o == NULL) | ||
499 | return 1; /* stack not completely built yet */ | ||
500 | for (; o < th->top; o++) /* mark live elements in the stack */ | ||
266 | markvalue(g, o); | 501 | markvalue(g, o); |
267 | for (; o <= lim; o++) | 502 | if (g->gcstate == GCSatomic) { /* final traversal? */ |
268 | setnilvalue(o); | 503 | StkId lim = th->stack + th->stacksize; /* real end of stack */ |
269 | checkstacksizes(l, lim); | 504 | for (; o < lim; o++) /* clear not-marked stack slice */ |
505 | setnilvalue(o); | ||
506 | } | ||
507 | else { /* count call infos to compute size */ | ||
508 | CallInfo *ci; | ||
509 | for (ci = &th->base_ci; ci != th->ci; ci = ci->next) | ||
510 | n++; | ||
511 | } | ||
512 | return sizeof(lua_State) + sizeof(TValue) * th->stacksize + | ||
513 | sizeof(CallInfo) * n; | ||
270 | } | 514 | } |
271 | 515 | ||
272 | 516 | ||
273 | /* | 517 | /* |
274 | ** traverse one gray object, turning it to black. | 518 | ** traverse one gray object, turning it to black (except for threads, |
275 | ** Returns `quantity' traversed. | 519 | ** which are always gray). |
276 | */ | 520 | */ |
277 | static l_mem propagatemark (global_State *g) { | 521 | static void propagatemark (global_State *g) { |
522 | lu_mem size; | ||
278 | GCObject *o = g->gray; | 523 | GCObject *o = g->gray; |
279 | lua_assert(isgray(o)); | 524 | lua_assert(isgray(o)); |
280 | gray2black(o); | 525 | gray2black(o); |
281 | switch (o->gch.tt) { | 526 | switch (gch(o)->tt) { |
282 | case LUA_TTABLE: { | 527 | case LUA_TTABLE: { |
283 | Table *h = gco2h(o); | 528 | Table *h = gco2t(o); |
284 | g->gray = h->gclist; | 529 | g->gray = h->gclist; /* remove from 'gray' list */ |
285 | if (traversetable(g, h)) /* table is weak? */ | 530 | size = traversetable(g, h); |
286 | black2gray(o); /* keep it gray */ | 531 | break; |
287 | return sizeof(Table) + sizeof(TValue) * h->sizearray + | 532 | } |
288 | sizeof(Node) * sizenode(h); | 533 | case LUA_TLCL: { |
289 | } | 534 | LClosure *cl = gco2lcl(o); |
290 | case LUA_TFUNCTION: { | 535 | g->gray = cl->gclist; /* remove from 'gray' list */ |
291 | Closure *cl = gco2cl(o); | 536 | size = traverseLclosure(g, cl); |
292 | g->gray = cl->c.gclist; | 537 | break; |
293 | traverseclosure(g, cl); | 538 | } |
294 | return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : | 539 | case LUA_TCCL: { |
295 | sizeLclosure(cl->l.nupvalues); | 540 | CClosure *cl = gco2ccl(o); |
541 | g->gray = cl->gclist; /* remove from 'gray' list */ | ||
542 | size = traverseCclosure(g, cl); | ||
543 | break; | ||
296 | } | 544 | } |
297 | case LUA_TTHREAD: { | 545 | case LUA_TTHREAD: { |
298 | lua_State *th = gco2th(o); | 546 | lua_State *th = gco2th(o); |
299 | g->gray = th->gclist; | 547 | g->gray = th->gclist; /* remove from 'gray' list */ |
300 | th->gclist = g->grayagain; | 548 | th->gclist = g->grayagain; |
301 | g->grayagain = o; | 549 | g->grayagain = o; /* insert into 'grayagain' list */ |
302 | black2gray(o); | 550 | black2gray(o); |
303 | traversestack(g, th); | 551 | size = traversestack(g, th); |
304 | return sizeof(lua_State) + sizeof(TValue) * th->stacksize + | 552 | break; |
305 | sizeof(CallInfo) * th->size_ci; | ||
306 | } | 553 | } |
307 | case LUA_TPROTO: { | 554 | case LUA_TPROTO: { |
308 | Proto *p = gco2p(o); | 555 | Proto *p = gco2p(o); |
309 | g->gray = p->gclist; | 556 | g->gray = p->gclist; /* remove from 'gray' list */ |
310 | traverseproto(g, p); | 557 | size = traverseproto(g, p); |
311 | return sizeof(Proto) + sizeof(Instruction) * p->sizecode + | 558 | break; |
312 | sizeof(Proto *) * p->sizep + | ||
313 | sizeof(TValue) * p->sizek + | ||
314 | sizeof(int) * p->sizelineinfo + | ||
315 | sizeof(LocVar) * p->sizelocvars + | ||
316 | sizeof(TString *) * p->sizeupvalues; | ||
317 | } | 559 | } |
318 | default: lua_assert(0); return 0; | 560 | default: lua_assert(0); return; |
319 | } | 561 | } |
562 | g->GCmemtrav += size; | ||
320 | } | 563 | } |
321 | 564 | ||
322 | 565 | ||
323 | static size_t propagateall (global_State *g) { | 566 | static void propagateall (global_State *g) { |
324 | size_t m = 0; | 567 | while (g->gray) propagatemark(g); |
325 | while (g->gray) m += propagatemark(g); | ||
326 | return m; | ||
327 | } | 568 | } |
328 | 569 | ||
329 | 570 | ||
571 | static void propagatelist (global_State *g, GCObject *l) { | ||
572 | lua_assert(g->gray == NULL); /* no grays left */ | ||
573 | g->gray = l; | ||
574 | propagateall(g); /* traverse all elements from 'l' */ | ||
575 | } | ||
576 | |||
330 | /* | 577 | /* |
331 | ** The next function tells whether a key or value can be cleared from | 578 | ** retraverse all gray lists. Because tables may be reinserted in other |
332 | ** a weak table. Non-collectable objects are never removed from weak | 579 | ** lists when traversed, traverse the original lists to avoid traversing |
333 | ** tables. Strings behave as `values', so are never removed too. for | 580 | ** twice the same table (which is not wrong, but inefficient) |
334 | ** other objects: if really collected, cannot keep them; for userdata | ||
335 | ** being finalized, keep them in keys, but not in values | ||
336 | */ | 581 | */ |
337 | static int iscleared (const TValue *o, int iskey) { | 582 | static void retraversegrays (global_State *g) { |
338 | if (!iscollectable(o)) return 0; | 583 | GCObject *weak = g->weak; /* save original lists */ |
339 | if (ttisstring(o)) { | 584 | GCObject *grayagain = g->grayagain; |
340 | stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ | 585 | GCObject *ephemeron = g->ephemeron; |
341 | return 0; | 586 | g->weak = g->grayagain = g->ephemeron = NULL; |
342 | } | 587 | propagateall(g); /* traverse main gray list */ |
343 | return iswhite(gcvalue(o)) || | 588 | propagatelist(g, grayagain); |
344 | (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); | 589 | propagatelist(g, weak); |
590 | propagatelist(g, ephemeron); | ||
591 | } | ||
592 | |||
593 | |||
594 | static void convergeephemerons (global_State *g) { | ||
595 | int changed; | ||
596 | do { | ||
597 | GCObject *w; | ||
598 | GCObject *next = g->ephemeron; /* get ephemeron list */ | ||
599 | g->ephemeron = NULL; /* tables will return to this list when traversed */ | ||
600 | changed = 0; | ||
601 | while ((w = next) != NULL) { | ||
602 | next = gco2t(w)->gclist; | ||
603 | if (traverseephemeron(g, gco2t(w))) { /* traverse marked some value? */ | ||
604 | propagateall(g); /* propagate changes */ | ||
605 | changed = 1; /* will have to revisit all ephemeron tables */ | ||
606 | } | ||
607 | } | ||
608 | } while (changed); | ||
345 | } | 609 | } |
346 | 610 | ||
611 | /* }====================================================== */ | ||
612 | |||
347 | 613 | ||
348 | /* | 614 | /* |
349 | ** clear collected entries from weaktables | 615 | ** {====================================================== |
616 | ** Sweep Functions | ||
617 | ** ======================================================= | ||
350 | */ | 618 | */ |
351 | static void cleartable (GCObject *l) { | 619 | |
352 | while (l) { | 620 | |
353 | Table *h = gco2h(l); | 621 | /* |
354 | int i = h->sizearray; | 622 | ** clear entries with unmarked keys from all weaktables in list 'l' up |
355 | lua_assert(testbit(h->marked, VALUEWEAKBIT) || | 623 | ** to element 'f' |
356 | testbit(h->marked, KEYWEAKBIT)); | 624 | */ |
357 | if (testbit(h->marked, VALUEWEAKBIT)) { | 625 | static void clearkeys (global_State *g, GCObject *l, GCObject *f) { |
358 | while (i--) { | 626 | for (; l != f; l = gco2t(l)->gclist) { |
359 | TValue *o = &h->array[i]; | 627 | Table *h = gco2t(l); |
360 | if (iscleared(o, 0)) /* value was collected? */ | 628 | Node *n, *limit = gnodelast(h); |
361 | setnilvalue(o); /* remove value */ | 629 | for (n = gnode(h, 0); n < limit; n++) { |
630 | if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { | ||
631 | setnilvalue(gval(n)); /* remove value ... */ | ||
632 | removeentry(n); /* and remove entry from table */ | ||
362 | } | 633 | } |
363 | } | 634 | } |
364 | i = sizenode(h); | 635 | } |
365 | while (i--) { | 636 | } |
366 | Node *n = gnode(h, i); | 637 | |
367 | if (!ttisnil(gval(n)) && /* non-empty entry? */ | 638 | |
368 | (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { | 639 | /* |
640 | ** clear entries with unmarked values from all weaktables in list 'l' up | ||
641 | ** to element 'f' | ||
642 | */ | ||
643 | static void clearvalues (global_State *g, GCObject *l, GCObject *f) { | ||
644 | for (; l != f; l = gco2t(l)->gclist) { | ||
645 | Table *h = gco2t(l); | ||
646 | Node *n, *limit = gnodelast(h); | ||
647 | int i; | ||
648 | for (i = 0; i < h->sizearray; i++) { | ||
649 | TValue *o = &h->array[i]; | ||
650 | if (iscleared(g, o)) /* value was collected? */ | ||
651 | setnilvalue(o); /* remove value */ | ||
652 | } | ||
653 | for (n = gnode(h, 0); n < limit; n++) { | ||
654 | if (!ttisnil(gval(n)) && iscleared(g, gval(n))) { | ||
369 | setnilvalue(gval(n)); /* remove value ... */ | 655 | setnilvalue(gval(n)); /* remove value ... */ |
370 | removeentry(n); /* remove entry from table */ | 656 | removeentry(n); /* and remove entry from table */ |
371 | } | 657 | } |
372 | } | 658 | } |
373 | l = h->gclist; | ||
374 | } | 659 | } |
375 | } | 660 | } |
376 | 661 | ||
377 | 662 | ||
378 | static void freeobj (lua_State *L, GCObject *o) { | 663 | static void freeobj (lua_State *L, GCObject *o) { |
379 | switch (o->gch.tt) { | 664 | switch (gch(o)->tt) { |
380 | case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; | 665 | case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; |
381 | case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; | 666 | case LUA_TLCL: { |
382 | case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; | 667 | luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); |
383 | case LUA_TTABLE: luaH_free(L, gco2h(o)); break; | ||
384 | case LUA_TTHREAD: { | ||
385 | lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); | ||
386 | luaE_freethread(L, gco2th(o)); | ||
387 | break; | 668 | break; |
388 | } | 669 | } |
389 | case LUA_TSTRING: { | 670 | case LUA_TCCL: { |
390 | G(L)->strt.nuse--; | 671 | luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); |
391 | luaM_freemem(L, o, sizestring(gco2ts(o))); | ||
392 | break; | 672 | break; |
393 | } | 673 | } |
394 | case LUA_TUSERDATA: { | 674 | case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; |
395 | luaM_freemem(L, o, sizeudata(gco2u(o))); | 675 | case LUA_TTABLE: luaH_free(L, gco2t(o)); break; |
676 | case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; | ||
677 | case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; | ||
678 | case LUA_TSHRSTR: | ||
679 | G(L)->strt.nuse--; | ||
680 | /* go through */ | ||
681 | case LUA_TLNGSTR: { | ||
682 | luaM_freemem(L, o, sizestring(gco2ts(o))); | ||
396 | break; | 683 | break; |
397 | } | 684 | } |
398 | default: lua_assert(0); | 685 | default: lua_assert(0); |
@@ -400,312 +687,534 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
400 | } | 687 | } |
401 | 688 | ||
402 | 689 | ||
403 | |||
404 | #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) | 690 | #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) |
691 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); | ||
405 | 692 | ||
406 | 693 | ||
694 | /* | ||
695 | ** sweep the (open) upvalues of a thread and resize its stack and | ||
696 | ** list of call-info structures. | ||
697 | */ | ||
698 | static void sweepthread (lua_State *L, lua_State *L1) { | ||
699 | if (L1->stack == NULL) return; /* stack not completely built yet */ | ||
700 | sweepwholelist(L, &L1->openupval); /* sweep open upvalues */ | ||
701 | luaE_freeCI(L1); /* free extra CallInfo slots */ | ||
702 | /* should not change the stack during an emergency gc cycle */ | ||
703 | if (G(L)->gckind != KGC_EMERGENCY) | ||
704 | luaD_shrinkstack(L1); | ||
705 | } | ||
706 | |||
707 | |||
708 | /* | ||
709 | ** sweep at most 'count' elements from a list of GCObjects erasing dead | ||
710 | ** objects, where a dead (not alive) object is one marked with the "old" | ||
711 | ** (non current) white and not fixed. | ||
712 | ** In non-generational mode, change all non-dead objects back to white, | ||
713 | ** preparing for next collection cycle. | ||
714 | ** In generational mode, keep black objects black, and also mark them as | ||
715 | ** old; stop when hitting an old object, as all objects after that | ||
716 | ** one will be old too. | ||
717 | ** When object is a thread, sweep its list of open upvalues too. | ||
718 | */ | ||
407 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | 719 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { |
408 | GCObject *curr; | ||
409 | global_State *g = G(L); | 720 | global_State *g = G(L); |
410 | int deadmask = otherwhite(g); | 721 | int ow = otherwhite(g); |
411 | while ((curr = *p) != NULL && count-- > 0) { | 722 | int toclear, toset; /* bits to clear and to set in all live objects */ |
412 | if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ | 723 | int tostop; /* stop sweep when this is true */ |
413 | sweepwholelist(L, &gco2th(curr)->openupval); | 724 | if (isgenerational(g)) { /* generational mode? */ |
414 | if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ | 725 | toclear = ~0; /* clear nothing */ |
415 | lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); | 726 | toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */ |
416 | makewhite(g, curr); /* make it white (for next cycle) */ | 727 | tostop = bitmask(OLDBIT); /* do not sweep old generation */ |
417 | p = &curr->gch.next; | 728 | } |
418 | } | 729 | else { /* normal mode */ |
419 | else { /* must erase `curr' */ | 730 | toclear = maskcolors; /* clear all color bits + old bit */ |
420 | lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); | 731 | toset = luaC_white(g); /* make object white */ |
421 | *p = curr->gch.next; | 732 | tostop = 0; /* do not stop */ |
422 | if (curr == g->rootgc) /* is the first element of the list? */ | 733 | } |
423 | g->rootgc = curr->gch.next; /* adjust first */ | 734 | while (*p != NULL && count-- > 0) { |
424 | freeobj(L, curr); | 735 | GCObject *curr = *p; |
736 | int marked = gch(curr)->marked; | ||
737 | if (isdeadm(ow, marked)) { /* is 'curr' dead? */ | ||
738 | *p = gch(curr)->next; /* remove 'curr' from list */ | ||
739 | freeobj(L, curr); /* erase 'curr' */ | ||
740 | } | ||
741 | else { | ||
742 | if (testbits(marked, tostop)) | ||
743 | return NULL; /* stop sweeping this list */ | ||
744 | if (gch(curr)->tt == LUA_TTHREAD) | ||
745 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ | ||
746 | /* update marks */ | ||
747 | gch(curr)->marked = cast_byte((marked & toclear) | toset); | ||
748 | p = &gch(curr)->next; /* go to next element */ | ||
425 | } | 749 | } |
426 | } | 750 | } |
751 | return (*p == NULL) ? NULL : p; | ||
752 | } | ||
753 | |||
754 | |||
755 | /* | ||
756 | ** sweep a list until a live object (or end of list) | ||
757 | */ | ||
758 | static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) { | ||
759 | GCObject ** old = p; | ||
760 | int i = 0; | ||
761 | do { | ||
762 | i++; | ||
763 | p = sweeplist(L, p, 1); | ||
764 | } while (p == old); | ||
765 | if (n) *n += i; | ||
427 | return p; | 766 | return p; |
428 | } | 767 | } |
429 | 768 | ||
769 | /* }====================================================== */ | ||
770 | |||
771 | |||
772 | /* | ||
773 | ** {====================================================== | ||
774 | ** Finalization | ||
775 | ** ======================================================= | ||
776 | */ | ||
430 | 777 | ||
431 | static void checkSizes (lua_State *L) { | 778 | static void checkSizes (lua_State *L) { |
432 | global_State *g = G(L); | 779 | global_State *g = G(L); |
433 | /* check size of string hash */ | 780 | if (g->gckind != KGC_EMERGENCY) { /* do not change sizes in emergency */ |
434 | if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && | 781 | int hs = g->strt.size / 2; /* half the size of the string table */ |
435 | g->strt.size > MINSTRTABSIZE*2) | 782 | if (g->strt.nuse < cast(lu_int32, hs)) /* using less than that half? */ |
436 | luaS_resize(L, g->strt.size/2); /* table is too big */ | 783 | luaS_resize(L, hs); /* halve its size */ |
437 | /* check size of buffer */ | 784 | luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ |
438 | if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ | ||
439 | size_t newsize = luaZ_sizebuffer(&g->buff) / 2; | ||
440 | luaZ_resizebuffer(L, &g->buff, newsize); | ||
441 | } | 785 | } |
442 | } | 786 | } |
443 | 787 | ||
444 | 788 | ||
445 | static void GCTM (lua_State *L) { | 789 | static GCObject *udata2finalize (global_State *g) { |
790 | GCObject *o = g->tobefnz; /* get first element */ | ||
791 | lua_assert(isfinalized(o)); | ||
792 | g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ | ||
793 | gch(o)->next = g->allgc; /* return it to 'allgc' list */ | ||
794 | g->allgc = o; | ||
795 | resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */ | ||
796 | lua_assert(!isold(o)); /* see MOVE OLD rule */ | ||
797 | if (!keepinvariantout(g)) /* not keeping invariant? */ | ||
798 | makewhite(g, o); /* "sweep" object */ | ||
799 | return o; | ||
800 | } | ||
801 | |||
802 | |||
803 | static void dothecall (lua_State *L, void *ud) { | ||
804 | UNUSED(ud); | ||
805 | luaD_call(L, L->top - 2, 0, 0); | ||
806 | } | ||
807 | |||
808 | |||
809 | static void GCTM (lua_State *L, int propagateerrors) { | ||
446 | global_State *g = G(L); | 810 | global_State *g = G(L); |
447 | GCObject *o = g->tmudata->gch.next; /* get first element */ | ||
448 | Udata *udata = rawgco2u(o); | ||
449 | const TValue *tm; | 811 | const TValue *tm; |
450 | /* remove udata from `tmudata' */ | 812 | TValue v; |
451 | if (o == g->tmudata) /* last element? */ | 813 | setgcovalue(L, &v, udata2finalize(g)); |
452 | g->tmudata = NULL; | 814 | tm = luaT_gettmbyobj(L, &v, TM_GC); |
453 | else | 815 | if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ |
454 | g->tmudata->gch.next = udata->uv.next; | 816 | int status; |
455 | udata->uv.next = g->mainthread->next; /* return it to `root' list */ | ||
456 | g->mainthread->next = o; | ||
457 | makewhite(g, o); | ||
458 | tm = fasttm(L, udata->uv.metatable, TM_GC); | ||
459 | if (tm != NULL) { | ||
460 | lu_byte oldah = L->allowhook; | 817 | lu_byte oldah = L->allowhook; |
461 | lu_mem oldt = g->GCthreshold; | 818 | int running = g->gcrunning; |
462 | L->allowhook = 0; /* stop debug hooks during GC tag method */ | 819 | L->allowhook = 0; /* stop debug hooks during GC metamethod */ |
463 | g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ | 820 | g->gcrunning = 0; /* avoid GC steps */ |
464 | setobj2s(L, L->top, tm); | 821 | setobj2s(L, L->top, tm); /* push finalizer... */ |
465 | setuvalue(L, L->top+1, udata); | 822 | setobj2s(L, L->top + 1, &v); /* ... and its argument */ |
466 | L->top += 2; | 823 | L->top += 2; /* and (next line) call the finalizer */ |
467 | luaD_call(L, L->top - 2, 0); | 824 | status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); |
468 | L->allowhook = oldah; /* restore hooks */ | 825 | L->allowhook = oldah; /* restore hooks */ |
469 | g->GCthreshold = oldt; /* restore threshold */ | 826 | g->gcrunning = running; /* restore state */ |
827 | if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ | ||
828 | if (status == LUA_ERRRUN) { /* is there an error object? */ | ||
829 | const char *msg = (ttisstring(L->top - 1)) | ||
830 | ? svalue(L->top - 1) | ||
831 | : "no message"; | ||
832 | luaO_pushfstring(L, "error in __gc metamethod (%s)", msg); | ||
833 | status = LUA_ERRGCMM; /* error in __gc metamethod */ | ||
834 | } | ||
835 | luaD_throw(L, status); /* re-throw error */ | ||
836 | } | ||
470 | } | 837 | } |
471 | } | 838 | } |
472 | 839 | ||
473 | 840 | ||
474 | /* | 841 | /* |
475 | ** Call all GC tag methods | 842 | ** move all unreachable objects (or 'all' objects) that need |
843 | ** finalization from list 'finobj' to list 'tobefnz' (to be finalized) | ||
476 | */ | 844 | */ |
477 | void luaC_callGCTM (lua_State *L) { | 845 | static void separatetobefnz (lua_State *L, int all) { |
478 | while (G(L)->tmudata) | 846 | global_State *g = G(L); |
479 | GCTM(L); | 847 | GCObject **p = &g->finobj; |
848 | GCObject *curr; | ||
849 | GCObject **lastnext = &g->tobefnz; | ||
850 | /* find last 'next' field in 'tobefnz' list (to add elements in its end) */ | ||
851 | while (*lastnext != NULL) | ||
852 | lastnext = &gch(*lastnext)->next; | ||
853 | while ((curr = *p) != NULL) { /* traverse all finalizable objects */ | ||
854 | lua_assert(!isfinalized(curr)); | ||
855 | lua_assert(testbit(gch(curr)->marked, SEPARATED)); | ||
856 | if (!(iswhite(curr) || all)) /* not being collected? */ | ||
857 | p = &gch(curr)->next; /* don't bother with it */ | ||
858 | else { | ||
859 | l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ | ||
860 | *p = gch(curr)->next; /* remove 'curr' from 'finobj' list */ | ||
861 | gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ | ||
862 | *lastnext = curr; | ||
863 | lastnext = &gch(curr)->next; | ||
864 | } | ||
865 | } | ||
480 | } | 866 | } |
481 | 867 | ||
482 | 868 | ||
483 | void luaC_freeall (lua_State *L) { | 869 | /* |
870 | ** if object 'o' has a finalizer, remove it from 'allgc' list (must | ||
871 | ** search the list to find it) and link it in 'finobj' list. | ||
872 | */ | ||
873 | void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | ||
484 | global_State *g = G(L); | 874 | global_State *g = G(L); |
485 | int i; | 875 | if (testbit(gch(o)->marked, SEPARATED) || /* obj. is already separated... */ |
486 | g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ | 876 | isfinalized(o) || /* ... or is finalized... */ |
487 | sweepwholelist(L, &g->rootgc); | 877 | gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ |
488 | for (i = 0; i < g->strt.size; i++) /* free all string lists */ | 878 | return; /* nothing to be done */ |
489 | sweepwholelist(L, &g->strt.hash[i]); | 879 | else { /* move 'o' to 'finobj' list */ |
880 | GCObject **p; | ||
881 | GCheader *ho = gch(o); | ||
882 | if (g->sweepgc == &ho->next) { /* avoid removing current sweep object */ | ||
883 | lua_assert(issweepphase(g)); | ||
884 | g->sweepgc = sweeptolive(L, g->sweepgc, NULL); | ||
885 | } | ||
886 | /* search for pointer pointing to 'o' */ | ||
887 | for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ } | ||
888 | *p = ho->next; /* remove 'o' from root list */ | ||
889 | ho->next = g->finobj; /* link it in list 'finobj' */ | ||
890 | g->finobj = o; | ||
891 | l_setbit(ho->marked, SEPARATED); /* mark it as such */ | ||
892 | if (!keepinvariantout(g)) /* not keeping invariant? */ | ||
893 | makewhite(g, o); /* "sweep" object */ | ||
894 | else | ||
895 | resetoldbit(o); /* see MOVE OLD rule */ | ||
896 | } | ||
490 | } | 897 | } |
491 | 898 | ||
899 | /* }====================================================== */ | ||
492 | 900 | ||
493 | static void markmt (global_State *g) { | 901 | |
494 | int i; | 902 | /* |
495 | for (i=0; i<NUM_TAGS; i++) | 903 | ** {====================================================== |
496 | if (g->mt[i]) markobject(g, g->mt[i]); | 904 | ** GC control |
905 | ** ======================================================= | ||
906 | */ | ||
907 | |||
908 | |||
909 | /* | ||
910 | ** set a reasonable "time" to wait before starting a new GC cycle; | ||
911 | ** cycle will start when memory use hits threshold | ||
912 | */ | ||
913 | static void setpause (global_State *g, l_mem estimate) { | ||
914 | l_mem debt, threshold; | ||
915 | estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ | ||
916 | threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ | ||
917 | ? estimate * g->gcpause /* no overflow */ | ||
918 | : MAX_LMEM; /* overflow; truncate to maximum */ | ||
919 | debt = -cast(l_mem, threshold - gettotalbytes(g)); | ||
920 | luaE_setdebt(g, debt); | ||
497 | } | 921 | } |
498 | 922 | ||
499 | 923 | ||
500 | /* mark root set */ | 924 | #define sweepphases \ |
501 | static void markroot (lua_State *L) { | 925 | (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) |
926 | |||
927 | |||
928 | /* | ||
929 | ** enter first sweep phase (strings) and prepare pointers for other | ||
930 | ** sweep phases. The calls to 'sweeptolive' make pointers point to an | ||
931 | ** object inside the list (instead of to the header), so that the real | ||
932 | ** sweep do not need to skip objects created between "now" and the start | ||
933 | ** of the real sweep. | ||
934 | ** Returns how many objects it swept. | ||
935 | */ | ||
936 | static int entersweep (lua_State *L) { | ||
502 | global_State *g = G(L); | 937 | global_State *g = G(L); |
503 | g->gray = NULL; | 938 | int n = 0; |
504 | g->grayagain = NULL; | 939 | g->gcstate = GCSsweepstring; |
505 | g->weak = NULL; | 940 | lua_assert(g->sweepgc == NULL && g->sweepfin == NULL); |
506 | markobject(g, g->mainthread); | 941 | /* prepare to sweep strings, finalizable objects, and regular objects */ |
507 | /* make global table be traversed before main stack */ | 942 | g->sweepstrgc = 0; |
508 | markvalue(g, gt(g->mainthread)); | 943 | g->sweepfin = sweeptolive(L, &g->finobj, &n); |
509 | markvalue(g, registry(L)); | 944 | g->sweepgc = sweeptolive(L, &g->allgc, &n); |
510 | markmt(g); | 945 | return n; |
511 | g->gcstate = GCSpropagate; | ||
512 | } | 946 | } |
513 | 947 | ||
514 | 948 | ||
515 | static void remarkupvals (global_State *g) { | 949 | /* |
516 | UpVal *uv; | 950 | ** change GC mode |
517 | for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { | 951 | */ |
518 | lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); | 952 | void luaC_changemode (lua_State *L, int mode) { |
519 | if (isgray(obj2gco(uv))) | 953 | global_State *g = G(L); |
520 | markvalue(g, uv->v); | 954 | if (mode == g->gckind) return; /* nothing to change */ |
955 | if (mode == KGC_GEN) { /* change to generational mode */ | ||
956 | /* make sure gray lists are consistent */ | ||
957 | luaC_runtilstate(L, bitmask(GCSpropagate)); | ||
958 | g->GCestimate = gettotalbytes(g); | ||
959 | g->gckind = KGC_GEN; | ||
960 | } | ||
961 | else { /* change to incremental mode */ | ||
962 | /* sweep all objects to turn them back to white | ||
963 | (as white has not changed, nothing extra will be collected) */ | ||
964 | g->gckind = KGC_NORMAL; | ||
965 | entersweep(L); | ||
966 | luaC_runtilstate(L, ~sweepphases); | ||
521 | } | 967 | } |
522 | } | 968 | } |
523 | 969 | ||
524 | 970 | ||
525 | static void atomic (lua_State *L) { | 971 | /* |
972 | ** call all pending finalizers | ||
973 | */ | ||
974 | static void callallpendingfinalizers (lua_State *L, int propagateerrors) { | ||
526 | global_State *g = G(L); | 975 | global_State *g = G(L); |
527 | size_t udsize; /* total size of userdata to be finalized */ | 976 | while (g->tobefnz) { |
528 | /* remark occasional upvalues of (maybe) dead threads */ | 977 | resetoldbit(g->tobefnz); |
529 | remarkupvals(g); | 978 | GCTM(L, propagateerrors); |
530 | /* traverse objects cautch by write barrier and by 'remarkupvals' */ | 979 | } |
531 | propagateall(g); | 980 | } |
532 | /* remark weak tables */ | 981 | |
533 | g->gray = g->weak; | 982 | |
534 | g->weak = NULL; | 983 | void luaC_freeallobjects (lua_State *L) { |
984 | global_State *g = G(L); | ||
985 | int i; | ||
986 | separatetobefnz(L, 1); /* separate all objects with finalizers */ | ||
987 | lua_assert(g->finobj == NULL); | ||
988 | callallpendingfinalizers(L, 0); | ||
989 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ | ||
990 | g->gckind = KGC_NORMAL; | ||
991 | sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ | ||
992 | sweepwholelist(L, &g->allgc); | ||
993 | for (i = 0; i < g->strt.size; i++) /* free all string lists */ | ||
994 | sweepwholelist(L, &g->strt.hash[i]); | ||
995 | lua_assert(g->strt.nuse == 0); | ||
996 | } | ||
997 | |||
998 | |||
999 | static l_mem atomic (lua_State *L) { | ||
1000 | global_State *g = G(L); | ||
1001 | l_mem work = -cast(l_mem, g->GCmemtrav); /* start counting work */ | ||
1002 | GCObject *origweak, *origall; | ||
535 | lua_assert(!iswhite(obj2gco(g->mainthread))); | 1003 | lua_assert(!iswhite(obj2gco(g->mainthread))); |
536 | markobject(g, L); /* mark running thread */ | 1004 | markobject(g, L); /* mark running thread */ |
537 | markmt(g); /* mark basic metatables (again) */ | 1005 | /* registry and global metatables may be changed by API */ |
538 | propagateall(g); | 1006 | markvalue(g, &g->l_registry); |
539 | /* remark gray again */ | 1007 | markmt(g); /* mark basic metatables */ |
540 | g->gray = g->grayagain; | 1008 | /* remark occasional upvalues of (maybe) dead threads */ |
541 | g->grayagain = NULL; | 1009 | remarkupvals(g); |
542 | propagateall(g); | 1010 | propagateall(g); /* propagate changes */ |
543 | udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ | 1011 | work += g->GCmemtrav; /* stop counting (do not (re)count grays) */ |
544 | marktmu(g); /* mark `preserved' userdata */ | 1012 | /* traverse objects caught by write barrier and by 'remarkupvals' */ |
545 | udsize += propagateall(g); /* remark, to propagate `preserveness' */ | 1013 | retraversegrays(g); |
546 | cleartable(g->weak); /* remove collected objects from weak tables */ | 1014 | work -= g->GCmemtrav; /* restart counting */ |
547 | /* flip current white */ | 1015 | convergeephemerons(g); |
548 | g->currentwhite = cast_byte(otherwhite(g)); | 1016 | /* at this point, all strongly accessible objects are marked. */ |
549 | g->sweepstrgc = 0; | 1017 | /* clear values from weak tables, before checking finalizers */ |
550 | g->sweepgc = &g->rootgc; | 1018 | clearvalues(g, g->weak, NULL); |
551 | g->gcstate = GCSsweepstring; | 1019 | clearvalues(g, g->allweak, NULL); |
552 | g->estimate = g->totalbytes - udsize; /* first estimate */ | 1020 | origweak = g->weak; origall = g->allweak; |
1021 | work += g->GCmemtrav; /* stop counting (objects being finalized) */ | ||
1022 | separatetobefnz(L, 0); /* separate objects to be finalized */ | ||
1023 | markbeingfnz(g); /* mark objects that will be finalized */ | ||
1024 | propagateall(g); /* remark, to propagate `preserveness' */ | ||
1025 | work -= g->GCmemtrav; /* restart counting */ | ||
1026 | convergeephemerons(g); | ||
1027 | /* at this point, all resurrected objects are marked. */ | ||
1028 | /* remove dead objects from weak tables */ | ||
1029 | clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */ | ||
1030 | clearkeys(g, g->allweak, NULL); /* clear keys from all allweak tables */ | ||
1031 | /* clear values from resurrected weak tables */ | ||
1032 | clearvalues(g, g->weak, origweak); | ||
1033 | clearvalues(g, g->allweak, origall); | ||
1034 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ | ||
1035 | work += g->GCmemtrav; /* complete counting */ | ||
1036 | return work; /* estimate of memory marked by 'atomic' */ | ||
553 | } | 1037 | } |
554 | 1038 | ||
555 | 1039 | ||
556 | static l_mem singlestep (lua_State *L) { | 1040 | static lu_mem singlestep (lua_State *L) { |
557 | global_State *g = G(L); | 1041 | global_State *g = G(L); |
558 | /*lua_checkmemory(L);*/ | ||
559 | switch (g->gcstate) { | 1042 | switch (g->gcstate) { |
560 | case GCSpause: { | 1043 | case GCSpause: { |
561 | markroot(L); /* start a new collection */ | 1044 | /* start to count memory traversed */ |
562 | return 0; | 1045 | g->GCmemtrav = g->strt.size * sizeof(GCObject*); |
1046 | lua_assert(!isgenerational(g)); | ||
1047 | restartcollection(g); | ||
1048 | g->gcstate = GCSpropagate; | ||
1049 | return g->GCmemtrav; | ||
563 | } | 1050 | } |
564 | case GCSpropagate: { | 1051 | case GCSpropagate: { |
565 | if (g->gray) | 1052 | if (g->gray) { |
566 | return propagatemark(g); | 1053 | lu_mem oldtrav = g->GCmemtrav; |
1054 | propagatemark(g); | ||
1055 | return g->GCmemtrav - oldtrav; /* memory traversed in this step */ | ||
1056 | } | ||
567 | else { /* no more `gray' objects */ | 1057 | else { /* no more `gray' objects */ |
568 | atomic(L); /* finish mark phase */ | 1058 | lu_mem work; |
569 | return 0; | 1059 | int sw; |
1060 | g->gcstate = GCSatomic; /* finish mark phase */ | ||
1061 | g->GCestimate = g->GCmemtrav; /* save what was counted */; | ||
1062 | work = atomic(L); /* add what was traversed by 'atomic' */ | ||
1063 | g->GCestimate += work; /* estimate of total memory traversed */ | ||
1064 | sw = entersweep(L); | ||
1065 | return work + sw * GCSWEEPCOST; | ||
570 | } | 1066 | } |
571 | } | 1067 | } |
572 | case GCSsweepstring: { | 1068 | case GCSsweepstring: { |
573 | lu_mem old = g->totalbytes; | 1069 | int i; |
574 | sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); | 1070 | for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++) |
575 | if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ | 1071 | sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]); |
576 | g->gcstate = GCSsweep; /* end sweep-string phase */ | 1072 | g->sweepstrgc += i; |
577 | lua_assert(old >= g->totalbytes); | 1073 | if (g->sweepstrgc >= g->strt.size) /* no more strings to sweep? */ |
578 | g->estimate -= old - g->totalbytes; | 1074 | g->gcstate = GCSsweepudata; |
579 | return GCSWEEPCOST; | 1075 | return i * GCSWEEPCOST; |
580 | } | 1076 | } |
581 | case GCSsweep: { | 1077 | case GCSsweepudata: { |
582 | lu_mem old = g->totalbytes; | 1078 | if (g->sweepfin) { |
583 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); | 1079 | g->sweepfin = sweeplist(L, g->sweepfin, GCSWEEPMAX); |
584 | if (*g->sweepgc == NULL) { /* nothing more to sweep? */ | 1080 | return GCSWEEPMAX*GCSWEEPCOST; |
585 | checkSizes(L); | ||
586 | g->gcstate = GCSfinalize; /* end sweep phase */ | ||
587 | } | ||
588 | lua_assert(old >= g->totalbytes); | ||
589 | g->estimate -= old - g->totalbytes; | ||
590 | return GCSWEEPMAX*GCSWEEPCOST; | ||
591 | } | ||
592 | case GCSfinalize: { | ||
593 | if (g->tmudata) { | ||
594 | GCTM(L); | ||
595 | if (g->estimate > GCFINALIZECOST) | ||
596 | g->estimate -= GCFINALIZECOST; | ||
597 | return GCFINALIZECOST; | ||
598 | } | 1081 | } |
599 | else { | 1082 | else { |
600 | g->gcstate = GCSpause; /* end collection */ | 1083 | g->gcstate = GCSsweep; |
601 | g->gcdept = 0; | ||
602 | return 0; | 1084 | return 0; |
603 | } | 1085 | } |
604 | } | 1086 | } |
1087 | case GCSsweep: { | ||
1088 | if (g->sweepgc) { | ||
1089 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); | ||
1090 | return GCSWEEPMAX*GCSWEEPCOST; | ||
1091 | } | ||
1092 | else { | ||
1093 | /* sweep main thread */ | ||
1094 | GCObject *mt = obj2gco(g->mainthread); | ||
1095 | sweeplist(L, &mt, 1); | ||
1096 | checkSizes(L); | ||
1097 | g->gcstate = GCSpause; /* finish collection */ | ||
1098 | return GCSWEEPCOST; | ||
1099 | } | ||
1100 | } | ||
605 | default: lua_assert(0); return 0; | 1101 | default: lua_assert(0); return 0; |
606 | } | 1102 | } |
607 | } | 1103 | } |
608 | 1104 | ||
609 | 1105 | ||
610 | void luaC_step (lua_State *L) { | 1106 | /* |
1107 | ** advances the garbage collector until it reaches a state allowed | ||
1108 | ** by 'statemask' | ||
1109 | */ | ||
1110 | void luaC_runtilstate (lua_State *L, int statesmask) { | ||
611 | global_State *g = G(L); | 1111 | global_State *g = G(L); |
612 | l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; | 1112 | while (!testbit(statesmask, g->gcstate)) |
613 | if (lim == 0) | 1113 | singlestep(L); |
614 | lim = (MAX_LUMEM-1)/2; /* no limit */ | ||
615 | g->gcdept += g->totalbytes - g->GCthreshold; | ||
616 | do { | ||
617 | lim -= singlestep(L); | ||
618 | if (g->gcstate == GCSpause) | ||
619 | break; | ||
620 | } while (lim > 0); | ||
621 | if (g->gcstate != GCSpause) { | ||
622 | if (g->gcdept < GCSTEPSIZE) | ||
623 | g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ | ||
624 | else { | ||
625 | g->gcdept -= GCSTEPSIZE; | ||
626 | g->GCthreshold = g->totalbytes; | ||
627 | } | ||
628 | } | ||
629 | else { | ||
630 | lua_assert(g->totalbytes >= g->estimate); | ||
631 | setthreshold(g); | ||
632 | } | ||
633 | } | 1114 | } |
634 | 1115 | ||
635 | 1116 | ||
636 | void luaC_fullgc (lua_State *L) { | 1117 | static void generationalcollection (lua_State *L) { |
637 | global_State *g = G(L); | 1118 | global_State *g = G(L); |
638 | if (g->gcstate <= GCSpropagate) { | 1119 | lua_assert(g->gcstate == GCSpropagate); |
639 | /* reset sweep marks to sweep all elements (returning them to white) */ | 1120 | if (g->GCestimate == 0) { /* signal for another major collection? */ |
640 | g->sweepstrgc = 0; | 1121 | luaC_fullgc(L, 0); /* perform a full regular collection */ |
641 | g->sweepgc = &g->rootgc; | 1122 | g->GCestimate = gettotalbytes(g); /* update control */ |
642 | /* reset other collector lists */ | ||
643 | g->gray = NULL; | ||
644 | g->grayagain = NULL; | ||
645 | g->weak = NULL; | ||
646 | g->gcstate = GCSsweepstring; | ||
647 | } | ||
648 | lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); | ||
649 | /* finish any pending sweep phase */ | ||
650 | while (g->gcstate != GCSfinalize) { | ||
651 | lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); | ||
652 | singlestep(L); | ||
653 | } | 1123 | } |
654 | markroot(L); | 1124 | else { |
655 | while (g->gcstate != GCSpause) { | 1125 | lu_mem estimate = g->GCestimate; |
656 | singlestep(L); | 1126 | luaC_runtilstate(L, bitmask(GCSpause)); /* run complete (minor) cycle */ |
1127 | g->gcstate = GCSpropagate; /* skip restart */ | ||
1128 | if (gettotalbytes(g) > (estimate / 100) * g->gcmajorinc) | ||
1129 | g->GCestimate = 0; /* signal for a major collection */ | ||
1130 | else | ||
1131 | g->GCestimate = estimate; /* keep estimate from last major coll. */ | ||
1132 | |||
657 | } | 1133 | } |
658 | setthreshold(g); | 1134 | setpause(g, gettotalbytes(g)); |
1135 | lua_assert(g->gcstate == GCSpropagate); | ||
659 | } | 1136 | } |
660 | 1137 | ||
661 | 1138 | ||
662 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { | 1139 | static void incstep (lua_State *L) { |
663 | global_State *g = G(L); | 1140 | global_State *g = G(L); |
664 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); | 1141 | l_mem debt = g->GCdebt; |
665 | lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); | 1142 | int stepmul = g->gcstepmul; |
666 | lua_assert(ttype(&o->gch) != LUA_TTABLE); | 1143 | if (stepmul < 40) stepmul = 40; /* avoid ridiculous low values (and 0) */ |
667 | /* must keep invariant? */ | 1144 | /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */ |
668 | if (g->gcstate == GCSpropagate) | 1145 | debt = (debt / STEPMULADJ) + 1; |
669 | reallymarkobject(g, v); /* restore invariant */ | 1146 | debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; |
670 | else /* don't mind */ | 1147 | do { /* always perform at least one single step */ |
671 | makewhite(g, o); /* mark as white just to avoid other barriers */ | 1148 | lu_mem work = singlestep(L); /* do some work */ |
1149 | debt -= work; | ||
1150 | } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); | ||
1151 | if (g->gcstate == GCSpause) | ||
1152 | setpause(g, g->GCestimate); /* pause until next cycle */ | ||
1153 | else { | ||
1154 | debt = (debt / stepmul) * STEPMULADJ; /* convert 'work units' to Kb */ | ||
1155 | luaE_setdebt(g, debt); | ||
1156 | } | ||
672 | } | 1157 | } |
673 | 1158 | ||
674 | 1159 | ||
675 | void luaC_barrierback (lua_State *L, Table *t) { | 1160 | /* |
1161 | ** performs a basic GC step | ||
1162 | */ | ||
1163 | void luaC_forcestep (lua_State *L) { | ||
676 | global_State *g = G(L); | 1164 | global_State *g = G(L); |
677 | GCObject *o = obj2gco(t); | 1165 | int i; |
678 | lua_assert(isblack(o) && !isdead(g, o)); | 1166 | if (isgenerational(g)) generationalcollection(L); |
679 | lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); | 1167 | else incstep(L); |
680 | black2gray(o); /* make table gray (again) */ | 1168 | /* run a few finalizers (or all of them at the end of a collect cycle) */ |
681 | t->gclist = g->grayagain; | 1169 | for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++) |
682 | g->grayagain = o; | 1170 | GCTM(L, 1); /* call one finalizer */ |
683 | } | 1171 | } |
684 | 1172 | ||
685 | 1173 | ||
686 | void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { | 1174 | /* |
1175 | ** performs a basic GC step only if collector is running | ||
1176 | */ | ||
1177 | void luaC_step (lua_State *L) { | ||
687 | global_State *g = G(L); | 1178 | global_State *g = G(L); |
688 | o->gch.next = g->rootgc; | 1179 | if (g->gcrunning) luaC_forcestep(L); |
689 | g->rootgc = o; | 1180 | else luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ |
690 | o->gch.marked = luaC_white(g); | ||
691 | o->gch.tt = tt; | ||
692 | } | 1181 | } |
693 | 1182 | ||
694 | 1183 | ||
695 | void luaC_linkupval (lua_State *L, UpVal *uv) { | 1184 | |
1185 | /* | ||
1186 | ** performs a full GC cycle; if "isemergency", does not call | ||
1187 | ** finalizers (which could change stack positions) | ||
1188 | */ | ||
1189 | void luaC_fullgc (lua_State *L, int isemergency) { | ||
696 | global_State *g = G(L); | 1190 | global_State *g = G(L); |
697 | GCObject *o = obj2gco(uv); | 1191 | int origkind = g->gckind; |
698 | o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ | 1192 | lua_assert(origkind != KGC_EMERGENCY); |
699 | g->rootgc = o; | 1193 | if (isemergency) /* do not run finalizers during emergency GC */ |
700 | if (isgray(o)) { | 1194 | g->gckind = KGC_EMERGENCY; |
701 | if (g->gcstate == GCSpropagate) { | 1195 | else { |
702 | gray2black(o); /* closed upvalues need barrier */ | 1196 | g->gckind = KGC_NORMAL; |
703 | luaC_barrier(L, uv, uv->v); | 1197 | callallpendingfinalizers(L, 1); |
704 | } | 1198 | } |
705 | else { /* sweep phase: sweep it (turning it into white) */ | 1199 | if (keepinvariant(g)) { /* may there be some black objects? */ |
706 | makewhite(g, o); | 1200 | /* must sweep all objects to turn them back to white |
707 | lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); | 1201 | (as white has not changed, nothing will be collected) */ |
708 | } | 1202 | entersweep(L); |
1203 | } | ||
1204 | /* finish any pending sweep phase to start a new cycle */ | ||
1205 | luaC_runtilstate(L, bitmask(GCSpause)); | ||
1206 | luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ | ||
1207 | luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */ | ||
1208 | if (origkind == KGC_GEN) { /* generational mode? */ | ||
1209 | /* generational mode must be kept in propagate phase */ | ||
1210 | luaC_runtilstate(L, bitmask(GCSpropagate)); | ||
709 | } | 1211 | } |
1212 | g->gckind = origkind; | ||
1213 | setpause(g, gettotalbytes(g)); | ||
1214 | if (!isemergency) /* do not run finalizers during emergency GC */ | ||
1215 | callallpendingfinalizers(L, 1); | ||
710 | } | 1216 | } |
711 | 1217 | ||
1218 | /* }====================================================== */ | ||
1219 | |||
1220 | |||
diff --git a/apps/plugins/lua/lgc.h b/apps/plugins/lua/lgc.h index 5123ccb479..84bb1cdf99 100644 --- a/apps/plugins/lua/lgc.h +++ b/apps/plugins/lua/lgc.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lgc.h,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -9,65 +9,107 @@ | |||
9 | 9 | ||
10 | 10 | ||
11 | #include "lobject.h" | 11 | #include "lobject.h" |
12 | #include "lstate.h" | ||
13 | |||
14 | /* | ||
15 | ** Collectable objects may have one of three colors: white, which | ||
16 | ** means the object is not marked; gray, which means the | ||
17 | ** object is marked, but its references may be not marked; and | ||
18 | ** black, which means that the object and all its references are marked. | ||
19 | ** The main invariant of the garbage collector, while marking objects, | ||
20 | ** is that a black object can never point to a white one. Moreover, | ||
21 | ** any gray object must be in a "gray list" (gray, grayagain, weak, | ||
22 | ** allweak, ephemeron) so that it can be visited again before finishing | ||
23 | ** the collection cycle. These lists have no meaning when the invariant | ||
24 | ** is not being enforced (e.g., sweep phase). | ||
25 | */ | ||
26 | |||
27 | |||
28 | |||
29 | /* how much to allocate before next GC step */ | ||
30 | #if !defined(GCSTEPSIZE) | ||
31 | /* ~100 small strings */ | ||
32 | #define GCSTEPSIZE (cast_int(100 * sizeof(TString))) | ||
33 | #endif | ||
12 | 34 | ||
13 | 35 | ||
14 | /* | 36 | /* |
15 | ** Possible states of the Garbage Collector | 37 | ** Possible states of the Garbage Collector |
16 | */ | 38 | */ |
17 | #define GCSpause 0 | 39 | #define GCSpropagate 0 |
18 | #define GCSpropagate 1 | 40 | #define GCSatomic 1 |
19 | #define GCSsweepstring 2 | 41 | #define GCSsweepstring 2 |
20 | #define GCSsweep 3 | 42 | #define GCSsweepudata 3 |
21 | #define GCSfinalize 4 | 43 | #define GCSsweep 4 |
44 | #define GCSpause 5 | ||
45 | |||
22 | 46 | ||
47 | #define issweepphase(g) \ | ||
48 | (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) | ||
49 | |||
50 | #define isgenerational(g) ((g)->gckind == KGC_GEN) | ||
23 | 51 | ||
24 | /* | 52 | /* |
25 | ** some userful bit tricks | 53 | ** macros to tell when main invariant (white objects cannot point to black |
54 | ** ones) must be kept. During a non-generational collection, the sweep | ||
55 | ** phase may break the invariant, as objects turned white may point to | ||
56 | ** still-black objects. The invariant is restored when sweep ends and | ||
57 | ** all objects are white again. During a generational collection, the | ||
58 | ** invariant must be kept all times. | ||
26 | */ | 59 | */ |
27 | #define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) | ||
28 | #define setbits(x,m) ((x) |= (m)) | ||
29 | #define testbits(x,m) ((x) & (m)) | ||
30 | #define bitmask(b) (1<<(b)) | ||
31 | #define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) | ||
32 | #define l_setbit(x,b) setbits(x, bitmask(b)) | ||
33 | #define resetbit(x,b) resetbits(x, bitmask(b)) | ||
34 | #define testbit(x,b) testbits(x, bitmask(b)) | ||
35 | #define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) | ||
36 | #define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) | ||
37 | #define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) | ||
38 | 60 | ||
61 | #define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic) | ||
39 | 62 | ||
40 | 63 | ||
41 | /* | 64 | /* |
42 | ** Layout for bit use in `marked' field: | 65 | ** Outside the collector, the state in generational mode is kept in |
43 | ** bit 0 - object is white (type 0) | 66 | ** 'propagate', so 'keepinvariant' is always true. |
44 | ** bit 1 - object is white (type 1) | ||
45 | ** bit 2 - object is black | ||
46 | ** bit 3 - for userdata: has been finalized | ||
47 | ** bit 3 - for tables: has weak keys | ||
48 | ** bit 4 - for tables: has weak values | ||
49 | ** bit 5 - object is fixed (should not be collected) | ||
50 | ** bit 6 - object is "super" fixed (only the main thread) | ||
51 | */ | 67 | */ |
68 | #define keepinvariantout(g) \ | ||
69 | check_exp(g->gcstate == GCSpropagate || !isgenerational(g), \ | ||
70 | g->gcstate <= GCSatomic) | ||
71 | |||
52 | 72 | ||
73 | /* | ||
74 | ** some useful bit tricks | ||
75 | */ | ||
76 | #define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) | ||
77 | #define setbits(x,m) ((x) |= (m)) | ||
78 | #define testbits(x,m) ((x) & (m)) | ||
79 | #define bitmask(b) (1<<(b)) | ||
80 | #define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) | ||
81 | #define l_setbit(x,b) setbits(x, bitmask(b)) | ||
82 | #define resetbit(x,b) resetbits(x, bitmask(b)) | ||
83 | #define testbit(x,b) testbits(x, bitmask(b)) | ||
84 | |||
85 | |||
86 | /* Layout for bit use in `marked' field: */ | ||
87 | #define WHITE0BIT 0 /* object is white (type 0) */ | ||
88 | #define WHITE1BIT 1 /* object is white (type 1) */ | ||
89 | #define BLACKBIT 2 /* object is black */ | ||
90 | #define FINALIZEDBIT 3 /* object has been separated for finalization */ | ||
91 | #define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */ | ||
92 | #define FIXEDBIT 5 /* object is fixed (should not be collected) */ | ||
93 | #define OLDBIT 6 /* object is old (only in generational mode) */ | ||
94 | /* bit 7 is currently used by tests (luaL_checkmemory) */ | ||
53 | 95 | ||
54 | #define WHITE0BIT 0 | ||
55 | #define WHITE1BIT 1 | ||
56 | #define BLACKBIT 2 | ||
57 | #define FINALIZEDBIT 3 | ||
58 | #define KEYWEAKBIT 3 | ||
59 | #define VALUEWEAKBIT 4 | ||
60 | #define FIXEDBIT 5 | ||
61 | #define SFIXEDBIT 6 | ||
62 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) | 96 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) |
63 | 97 | ||
64 | 98 | ||
65 | #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) | 99 | #define iswhite(x) testbits((x)->gch.marked, WHITEBITS) |
66 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) | 100 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) |
67 | #define isgray(x) (!isblack(x) && !iswhite(x)) | 101 | #define isgray(x) /* neither white nor black */ \ |
102 | (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) | ||
103 | |||
104 | #define isold(x) testbit((x)->gch.marked, OLDBIT) | ||
105 | |||
106 | /* MOVE OLD rule: whenever an object is moved to the beginning of | ||
107 | a GC list, its old bit must be cleared */ | ||
108 | #define resetoldbit(o) resetbit((o)->gch.marked, OLDBIT) | ||
68 | 109 | ||
69 | #define otherwhite(g) (g->currentwhite ^ WHITEBITS) | 110 | #define otherwhite(g) (g->currentwhite ^ WHITEBITS) |
70 | #define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) | 111 | #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) |
112 | #define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked) | ||
71 | 113 | ||
72 | #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) | 114 | #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) |
73 | #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) | 115 | #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) |
@@ -77,34 +119,39 @@ | |||
77 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) | 119 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) |
78 | 120 | ||
79 | 121 | ||
80 | #define luaC_checkGC(L) { \ | 122 | #define luaC_condGC(L,c) \ |
81 | condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ | 123 | {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);} |
82 | if (G(L)->totalbytes >= G(L)->GCthreshold) \ | 124 | #define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);) |
83 | luaC_step(L); } | ||
84 | 125 | ||
85 | 126 | ||
86 | #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ | 127 | #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ |
87 | luaC_barrierf(L,obj2gco(p),gcvalue(v)); } | 128 | luaC_barrier_(L,obj2gco(p),gcvalue(v)); } |
88 | 129 | ||
89 | #define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ | 130 | #define luaC_barrierback(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ |
90 | luaC_barrierback(L,t); } | 131 | luaC_barrierback_(L,p); } |
91 | 132 | ||
92 | #define luaC_objbarrier(L,p,o) \ | 133 | #define luaC_objbarrier(L,p,o) \ |
93 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ | 134 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ |
94 | luaC_barrierf(L,obj2gco(p),obj2gco(o)); } | 135 | luaC_barrier_(L,obj2gco(p),obj2gco(o)); } |
95 | 136 | ||
96 | #define luaC_objbarriert(L,t,o) \ | 137 | #define luaC_objbarrierback(L,p,o) \ |
97 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } | 138 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) luaC_barrierback_(L,p); } |
98 | 139 | ||
99 | LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); | 140 | #define luaC_barrierproto(L,p,c) \ |
100 | LUAI_FUNC void luaC_callGCTM (lua_State *L); | 141 | { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); } |
101 | LUAI_FUNC void luaC_freeall (lua_State *L); | ||
102 | LUAI_FUNC void luaC_step (lua_State *L); | ||
103 | LUAI_FUNC void luaC_fullgc (lua_State *L); | ||
104 | LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); | ||
105 | LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); | ||
106 | LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); | ||
107 | LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); | ||
108 | 142 | ||
143 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); | ||
144 | LUAI_FUNC void luaC_step (lua_State *L); | ||
145 | LUAI_FUNC void luaC_forcestep (lua_State *L); | ||
146 | LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); | ||
147 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); | ||
148 | LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, | ||
149 | GCObject **list, int offset); | ||
150 | LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); | ||
151 | LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); | ||
152 | LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); | ||
153 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); | ||
154 | LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); | ||
155 | LUAI_FUNC void luaC_changemode (lua_State *L, int mode); | ||
109 | 156 | ||
110 | #endif | 157 | #endif |
diff --git a/apps/plugins/lua/liolib.c b/apps/plugins/lua/liolib.c index 7a43915f20..a282dd1ac0 100644 --- a/apps/plugins/lua/liolib.c +++ b/apps/plugins/lua/liolib.c | |||
@@ -1,10 +1,21 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $ | 2 | ** $Id: liolib.c,v 2.112.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Standard I/O (and system) library | 3 | ** Standard I/O (and system) library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
6 | 6 | ||
7 | 7 | ||
8 | /* | ||
9 | ** This definition must come before the inclusion of 'stdio.h'; it | ||
10 | ** should not affect non-POSIX systems | ||
11 | */ | ||
12 | #if !defined(_FILE_OFFSET_BITS) | ||
13 | #define _LARGEFILE_SOURCE 1 | ||
14 | #define _FILE_OFFSET_BITS 64 | ||
15 | #endif | ||
16 | |||
17 | |||
18 | #include <errno.h> | ||
8 | #include <stdio.h> | 19 | #include <stdio.h> |
9 | #include <stdlib.h> | 20 | #include <stdlib.h> |
10 | #include <string.h> | 21 | #include <string.h> |
@@ -19,46 +30,111 @@ | |||
19 | #include "rocklibc.h" | 30 | #include "rocklibc.h" |
20 | 31 | ||
21 | 32 | ||
33 | #if !defined(lua_checkmode) | ||
22 | 34 | ||
23 | #define IO_INPUT 1 | 35 | /* |
24 | #define IO_OUTPUT 2 | 36 | ** Check whether 'mode' matches '[rwa]%+?b?'. |
37 | ** Change this macro to accept other modes for 'fopen' besides | ||
38 | ** the standard ones. | ||
39 | */ | ||
40 | #define lua_checkmode(mode) \ | ||
41 | (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \ | ||
42 | (*mode != '+' || ++mode) && /* skip if char is '+' */ \ | ||
43 | (*mode != 'b' || ++mode) && /* skip if char is 'b' */ \ | ||
44 | (*mode == '\0')) | ||
25 | 45 | ||
46 | #endif | ||
26 | 47 | ||
27 | static const char *const fnames[] = {"input", "output"}; | 48 | /* |
49 | ** {====================================================== | ||
50 | ** lua_popen spawns a new process connected to the current | ||
51 | ** one through the file streams. | ||
52 | ** ======================================================= | ||
53 | */ | ||
28 | 54 | ||
55 | #if !defined(lua_popen) /* { */ | ||
29 | 56 | ||
30 | static int pushresult (lua_State *L, int i, const char *filename) { | 57 | #if defined(LUA_USE_POPEN) /* { */ |
31 | int en = errno; | ||
32 | if (i) { | ||
33 | lua_pushboolean(L, 1); | ||
34 | return 1; | ||
35 | } | ||
36 | else { | ||
37 | lua_pushnil(L); | ||
38 | if (filename) | ||
39 | lua_pushfstring(L, "%s: %s", filename, strerror(en)); | ||
40 | else | ||
41 | lua_pushfstring(L, "%s", strerror(en)); | ||
42 | lua_pushinteger(L, 0); | ||
43 | return 3; | ||
44 | } | ||
45 | } | ||
46 | 58 | ||
59 | #define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) | ||
60 | #define lua_pclose(L,file) ((void)L, pclose(file)) | ||
47 | 61 | ||
48 | static void fileerror (lua_State *L, int arg, const char *filename) { | 62 | #elif defined(LUA_WIN) /* }{ */ |
49 | lua_pushfstring(L, "%s: %s", filename, strerror(errno)); | 63 | |
50 | luaL_argerror(L, arg, lua_tostring(L, -1)); | 64 | #define lua_popen(L,c,m) ((void)L, _popen(c,m)) |
51 | } | 65 | #define lua_pclose(L,file) ((void)L, _pclose(file)) |
66 | |||
67 | |||
68 | #else /* }{ */ | ||
69 | |||
70 | #define lua_popen(L,c,m) ((void)((void)c, m), \ | ||
71 | luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) | ||
72 | #define lua_pclose(L,file) ((void)((void)L, file), -1) | ||
73 | |||
74 | |||
75 | #endif /* } */ | ||
76 | |||
77 | #endif /* } */ | ||
78 | |||
79 | /* }====================================================== */ | ||
80 | |||
81 | |||
82 | /* | ||
83 | ** {====================================================== | ||
84 | ** lua_fseek: configuration for longer offsets | ||
85 | ** ======================================================= | ||
86 | */ | ||
87 | |||
88 | #if !defined(lua_fseek) && !defined(LUA_ANSI) /* { */ | ||
89 | |||
90 | #if defined(LUA_USE_POSIX) /* { */ | ||
91 | |||
92 | #define l_fseek(f,o,w) fseeko(f,o,w) | ||
93 | #define l_ftell(f) ftello(f) | ||
94 | #define l_seeknum off_t | ||
95 | |||
96 | #elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \ | ||
97 | && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */ | ||
98 | /* Windows (but not DDK) and Visual C++ 2005 or higher */ | ||
99 | |||
100 | #define l_fseek(f,o,w) _fseeki64(f,o,w) | ||
101 | #define l_ftell(f) _ftelli64(f) | ||
102 | #define l_seeknum __int64 | ||
103 | |||
104 | #endif /* } */ | ||
105 | |||
106 | #endif /* } */ | ||
107 | |||
108 | |||
109 | #if !defined(l_fseek) /* default definitions */ | ||
110 | #define l_fseek(f,o,w) fseek(f,o,w) | ||
111 | #define l_ftell(f) ftell(f) | ||
112 | #define l_seeknum long | ||
113 | #endif | ||
114 | |||
115 | /* }====================================================== */ | ||
116 | |||
117 | |||
118 | #define IO_PREFIX "_IO_" | ||
119 | #define IO_INPUT (IO_PREFIX "input") | ||
120 | #define IO_OUTPUT (IO_PREFIX "output") | ||
121 | |||
122 | |||
123 | typedef luaL_Stream LStream; | ||
124 | |||
125 | |||
126 | #define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) | ||
127 | |||
128 | #define isclosed(p) ((p)->closef == NULL) | ||
52 | 129 | ||
53 | 130 | ||
54 | static int io_type (lua_State *L) { | 131 | static int io_type (lua_State *L) { |
55 | void *ud; | 132 | LStream *p; |
56 | luaL_checkany(L, 1); | 133 | luaL_checkany(L, 1); |
57 | ud = lua_touserdata(L, 1); | 134 | p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); |
58 | lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); | 135 | if (p == NULL) |
59 | if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) | ||
60 | lua_pushnil(L); /* not a file */ | 136 | lua_pushnil(L); /* not a file */ |
61 | else if (*((int *)ud) < 0) | 137 | else if (isclosed(p)) |
62 | lua_pushliteral(L, "closed file"); | 138 | lua_pushliteral(L, "closed file"); |
63 | else | 139 | else |
64 | lua_pushliteral(L, "file"); | 140 | lua_pushliteral(L, "file"); |
@@ -66,76 +142,97 @@ static int io_type (lua_State *L) { | |||
66 | } | 142 | } |
67 | 143 | ||
68 | 144 | ||
69 | static int* tofile (lua_State *L) { | 145 | static int f_tostring (lua_State *L) { |
70 | int *f = (int*) luaL_checkudata(L, 1, LUA_FILEHANDLE); | 146 | LStream *p = tolstream(L); |
71 | if (*f < 0) | 147 | if (isclosed(p)) |
72 | luaL_error(L, "attempt to use a closed file"); | 148 | lua_pushliteral(L, "file (closed)"); |
73 | return f; | 149 | else |
150 | lua_pushfstring(L, "file (%p)", p->f); | ||
151 | return 1; | ||
74 | } | 152 | } |
75 | 153 | ||
76 | 154 | ||
155 | static FILE *tofile (lua_State *L) { | ||
156 | LStream *p = tolstream(L); | ||
157 | if (isclosed(p)) | ||
158 | luaL_error(L, "attempt to use a closed file"); | ||
159 | lua_assert(p->f); | ||
160 | return p->f; | ||
161 | } | ||
162 | |||
77 | 163 | ||
78 | /* | 164 | /* |
79 | ** When creating file handles, always creates a `closed' file handle | 165 | ** When creating file handles, always creates a `closed' file handle |
80 | ** before opening the actual file; so, if there is a memory error, the | 166 | ** before opening the actual file; so, if there is a memory error, the |
81 | ** file is not left opened. | 167 | ** file is not left opened. |
82 | */ | 168 | */ |
83 | static int* newfile (lua_State *L) { | 169 | static LStream *newprefile (lua_State *L) { |
84 | int *pf = (int *)lua_newuserdata(L, sizeof(int)); | 170 | LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); |
85 | *pf = -1; /* file handle is currently `closed' */ | 171 | p->closef = NULL; /* mark file handle as 'closed' */ |
86 | luaL_getmetatable(L, LUA_FILEHANDLE); | 172 | luaL_setmetatable(L, LUA_FILEHANDLE); |
87 | lua_setmetatable(L, -2); | 173 | return p; |
88 | return pf; | ||
89 | } | ||
90 | |||
91 | |||
92 | /* | ||
93 | ** function to close regular files | ||
94 | */ | ||
95 | static int io_fclose (lua_State *L) { | ||
96 | int *p = tofile(L); | ||
97 | int ok = (rb->close(*p) == 0); | ||
98 | *p = -1; | ||
99 | return pushresult(L, ok, NULL); | ||
100 | } | 174 | } |
101 | 175 | ||
102 | 176 | ||
103 | static inline int aux_close (lua_State *L) { | 177 | static int aux_close (lua_State *L) { |
104 | return io_fclose(L); | 178 | LStream *p = tolstream(L); |
179 | lua_CFunction cf = p->closef; | ||
180 | p->closef = NULL; /* mark stream as closed */ | ||
181 | return (*cf)(L); /* close it */ | ||
105 | } | 182 | } |
106 | 183 | ||
107 | 184 | ||
108 | static int io_close (lua_State *L) { | 185 | static int io_close (lua_State *L) { |
109 | if (lua_isnone(L, 1)) | 186 | if (lua_isnone(L, 1)) /* no argument? */ |
110 | lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); | 187 | lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ |
111 | tofile(L); /* make sure argument is a file */ | 188 | tofile(L); /* make sure argument is an open stream */ |
112 | return aux_close(L); | 189 | return aux_close(L); |
113 | } | 190 | } |
114 | 191 | ||
115 | 192 | ||
116 | static int io_gc (lua_State *L) { | 193 | static int f_gc (lua_State *L) { |
117 | int f = *(int*) luaL_checkudata(L, 1, LUA_FILEHANDLE); | 194 | LStream *p = tolstream(L); |
118 | /* ignore closed files */ | 195 | if (!isclosed(p) && p->f != NULL) |
119 | if (f >= 0) | 196 | aux_close(L); /* ignore closed and incompletely open files */ |
120 | aux_close(L); | ||
121 | return 0; | 197 | return 0; |
122 | } | 198 | } |
123 | 199 | ||
124 | 200 | ||
125 | static int io_tostring (lua_State *L) { | 201 | /* |
126 | int f = *(int*) luaL_checkudata(L, 1, LUA_FILEHANDLE); | 202 | ** function to close regular files |
127 | if (f < 0) | 203 | */ |
128 | lua_pushliteral(L, "file (closed)"); | 204 | static int io_fclose (lua_State *L) { |
129 | else | 205 | LStream *p = tolstream(L); |
130 | lua_pushfstring(L, "file (%d)", f); | 206 | int res = rb->close((int)p->f); |
131 | return 1; | 207 | return luaL_fileresult(L, (res == 0), NULL); |
208 | } | ||
209 | |||
210 | |||
211 | static LStream *newfile (lua_State *L) { | ||
212 | LStream *p = newprefile(L); | ||
213 | p->f = NULL; | ||
214 | p->closef = &io_fclose; | ||
215 | return p; | ||
216 | } | ||
217 | |||
218 | |||
219 | static void opencheck (lua_State *L, const char *fname, const char *mode) { | ||
220 | LStream *p = newfile(L); | ||
221 | int flags = O_RDONLY; | ||
222 | if (strcmp(mode, "w") == 0) | ||
223 | flags = O_WRONLY; | ||
224 | p->f = (FILE*)rb->open(fname, flags); | ||
225 | if (p->f == NULL) | ||
226 | luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno)); | ||
132 | } | 227 | } |
133 | 228 | ||
134 | 229 | ||
135 | static int io_open (lua_State *L) { | 230 | static int io_open (lua_State *L) { |
136 | const char *filename = luaL_checkstring(L, 1); | 231 | const char *filename = luaL_checkstring(L, 1); |
137 | const char *mode = luaL_optstring(L, 2, "r"); | 232 | const char *mode = luaL_optstring(L, 2, "r"); |
138 | int *pf = newfile(L); | 233 | LStream *p = newfile(L); |
234 | const char *md = mode; /* to traverse/check mode */ | ||
235 | luaL_argcheck(L, lua_checkmode(md), 2, "invalid mode"); | ||
139 | int flags = 0; | 236 | int flags = 0; |
140 | if(*(mode+1) == '+') { | 237 | if(*(mode+1) == '+') { |
141 | flags = O_RDWR; | 238 | flags = O_RDWR; |
@@ -158,84 +255,117 @@ static int io_open (lua_State *L) { | |||
158 | } | 255 | } |
159 | if((*mode == 'w' || *mode == 'a') && !rb->file_exists(filename)) | 256 | if((*mode == 'w' || *mode == 'a') && !rb->file_exists(filename)) |
160 | flags |= O_CREAT; | 257 | flags |= O_CREAT; |
161 | *pf = rb->open(filename, flags, 0666); | 258 | int pf = rb->open(filename, flags, 0666); |
162 | return (*pf < 0) ? pushresult(L, 0, filename) : 1; | 259 | p->f = (FILE*)pf; |
260 | return (pf < 0) ? luaL_fileresult(L, 0, filename) : 1; | ||
163 | } | 261 | } |
164 | 262 | ||
165 | 263 | ||
166 | static int* getiofile (lua_State *L, int findex) { | 264 | #if 0 |
167 | int *f; | 265 | /* |
168 | lua_rawgeti(L, LUA_ENVIRONINDEX, findex); | 266 | ** function to close 'popen' files |
169 | f = (int *)lua_touserdata(L, -1); | 267 | */ |
170 | if (f == NULL || *f < 0) | 268 | static int io_pclose (lua_State *L) { |
171 | luaL_error(L, "standard %s file is closed", fnames[findex - 1]); | 269 | LStream *p = tolstream(L); |
172 | return f; | 270 | return luaL_execresult(L, lua_pclose(L, p->f)); |
173 | } | 271 | } |
174 | 272 | ||
175 | 273 | ||
176 | static int g_iofile (lua_State *L, int f, int flags) { | 274 | static int io_popen (lua_State *L) { |
275 | const char *filename = luaL_checkstring(L, 1); | ||
276 | const char *mode = luaL_optstring(L, 2, "r"); | ||
277 | LStream *p = newprefile(L); | ||
278 | p->f = lua_popen(L, filename, mode); | ||
279 | p->closef = &io_pclose; | ||
280 | return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; | ||
281 | } | ||
282 | |||
283 | |||
284 | static int io_tmpfile (lua_State *L) { | ||
285 | LStream *p = newfile(L); | ||
286 | p->f = tmpfile(); | ||
287 | return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; | ||
288 | } | ||
289 | #endif | ||
290 | |||
291 | |||
292 | static FILE *getiofile (lua_State *L, const char *findex) { | ||
293 | LStream *p; | ||
294 | lua_getfield(L, LUA_REGISTRYINDEX, findex); | ||
295 | p = (LStream *)lua_touserdata(L, -1); | ||
296 | if (isclosed(p)) | ||
297 | luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX)); | ||
298 | return p->f; | ||
299 | } | ||
300 | |||
301 | |||
302 | static int g_iofile (lua_State *L, const char *f, const char *mode) { | ||
177 | if (!lua_isnoneornil(L, 1)) { | 303 | if (!lua_isnoneornil(L, 1)) { |
178 | const char *filename = lua_tostring(L, 1); | 304 | const char *filename = lua_tostring(L, 1); |
179 | if (filename) { | 305 | if (filename) |
180 | int *pf = newfile(L); | 306 | opencheck(L, filename, mode); |
181 | *pf = rb->open(filename, flags); | ||
182 | if (*pf < 0) | ||
183 | fileerror(L, 1, filename); | ||
184 | } | ||
185 | else { | 307 | else { |
186 | tofile(L); /* check that it's a valid file handle */ | 308 | tofile(L); /* check that it's a valid file handle */ |
187 | lua_pushvalue(L, 1); | 309 | lua_pushvalue(L, 1); |
188 | } | 310 | } |
189 | lua_rawseti(L, LUA_ENVIRONINDEX, f); | 311 | lua_setfield(L, LUA_REGISTRYINDEX, f); |
190 | } | 312 | } |
191 | /* return current value */ | 313 | /* return current value */ |
192 | lua_rawgeti(L, LUA_ENVIRONINDEX, f); | 314 | lua_getfield(L, LUA_REGISTRYINDEX, f); |
193 | return 1; | 315 | return 1; |
194 | } | 316 | } |
195 | 317 | ||
196 | 318 | ||
197 | static int io_input (lua_State *L) { | 319 | static int io_input (lua_State *L) { |
198 | return g_iofile(L, IO_INPUT, O_RDONLY); | 320 | return g_iofile(L, IO_INPUT, "r"); |
199 | } | 321 | } |
200 | 322 | ||
201 | 323 | ||
202 | static int io_output (lua_State *L) { | 324 | static int io_output (lua_State *L) { |
203 | return g_iofile(L, IO_OUTPUT, O_WRONLY); | 325 | return g_iofile(L, IO_OUTPUT, "w"); |
204 | } | 326 | } |
205 | 327 | ||
206 | 328 | ||
207 | static int io_readline (lua_State *L); | 329 | static int io_readline (lua_State *L); |
208 | 330 | ||
209 | 331 | ||
210 | static void aux_lines (lua_State *L, int idx, int toclose) { | 332 | static void aux_lines (lua_State *L, int toclose) { |
211 | lua_pushvalue(L, idx); | 333 | int i; |
334 | int n = lua_gettop(L) - 1; /* number of arguments to read */ | ||
335 | /* ensure that arguments will fit here and into 'io_readline' stack */ | ||
336 | luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options"); | ||
337 | lua_pushvalue(L, 1); /* file handle */ | ||
338 | lua_pushinteger(L, n); /* number of arguments to read */ | ||
212 | lua_pushboolean(L, toclose); /* close/not close file when finished */ | 339 | lua_pushboolean(L, toclose); /* close/not close file when finished */ |
213 | lua_pushcclosure(L, io_readline, 2); | 340 | for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1); /* copy arguments */ |
341 | lua_pushcclosure(L, io_readline, 3 + n); | ||
214 | } | 342 | } |
215 | 343 | ||
216 | 344 | ||
217 | static int f_lines (lua_State *L) { | 345 | static int f_lines (lua_State *L) { |
218 | tofile(L); /* check that it's a valid file handle */ | 346 | tofile(L); /* check that it's a valid file handle */ |
219 | aux_lines(L, 1, 0); | 347 | aux_lines(L, 0); |
220 | return 1; | 348 | return 1; |
221 | } | 349 | } |
222 | 350 | ||
223 | 351 | ||
224 | static int io_lines (lua_State *L) { | 352 | static int io_lines (lua_State *L) { |
225 | if (lua_isnoneornil(L, 1)) { /* no arguments? */ | 353 | int toclose; |
226 | /* will iterate over default input */ | 354 | if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ |
227 | lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); | 355 | if (lua_isnil(L, 1)) { /* no file name? */ |
228 | return f_lines(L); | 356 | lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ |
357 | lua_replace(L, 1); /* put it at index 1 */ | ||
358 | tofile(L); /* check that it's a valid file handle */ | ||
359 | toclose = 0; /* do not close it after iteration */ | ||
229 | } | 360 | } |
230 | else { | 361 | else { /* open a new file */ |
231 | const char *filename = luaL_checkstring(L, 1); | 362 | const char *filename = luaL_checkstring(L, 1); |
232 | int *pf = newfile(L); | 363 | opencheck(L, filename, "r"); |
233 | *pf = rb->open(filename, O_RDONLY); | 364 | lua_replace(L, 1); /* put file at index 1 */ |
234 | if (*pf < 0) | 365 | toclose = 1; /* close it after iteration */ |
235 | fileerror(L, 1, filename); | ||
236 | aux_lines(L, lua_gettop(L), 1); | ||
237 | return 1; | ||
238 | } | 366 | } |
367 | aux_lines(L, toclose); | ||
368 | return 1; | ||
239 | } | 369 | } |
240 | 370 | ||
241 | 371 | ||
@@ -245,72 +375,89 @@ static int io_lines (lua_State *L) { | |||
245 | ** ======================================================= | 375 | ** ======================================================= |
246 | */ | 376 | */ |
247 | 377 | ||
248 | static int read_number (lua_State *L, int *f) { | 378 | |
379 | static int read_number (lua_State *L, FILE *f) { | ||
249 | lua_Number d; | 380 | lua_Number d; |
250 | if (PREFIX(fscanf)(*f, LUA_NUMBER_SCAN, &d) == 1) { | 381 | if (PREFIX(fscanf)(f, LUA_NUMBER_SCAN, &d) == 1) { |
251 | lua_pushnumber(L, d); | 382 | lua_pushnumber(L, d); |
252 | return 1; | 383 | return 1; |
253 | } | 384 | } |
254 | else return 0; /* read fails */ | 385 | else { |
386 | lua_pushnil(L); /* "result" to be removed */ | ||
387 | return 0; /* read fails */ | ||
388 | } | ||
255 | } | 389 | } |
256 | 390 | ||
257 | 391 | ||
258 | static int test_eof (lua_State *L, int *f) { | 392 | static int test_eof (lua_State *L, FILE *f) { |
259 | ssize_t s = rb->lseek(*f, 0, SEEK_CUR); | 393 | ssize_t s = rb->lseek((int)f, 0, SEEK_CUR); |
260 | lua_pushlstring(L, NULL, 0); | 394 | lua_pushlstring(L, NULL, 0); |
261 | return s != rb->filesize(*f); | 395 | return s != rb->filesize((int)f); |
262 | } | 396 | } |
263 | 397 | ||
264 | 398 | ||
265 | /* Rockbox already defines read_line() */ | 399 | /* Rockbox already defines read_line() */ |
266 | static int _read_line (lua_State *L, int *f) { | 400 | static int _read_line (lua_State *L, FILE *f, int chop) { |
267 | luaL_Buffer b; | 401 | luaL_Buffer b; |
268 | luaL_buffinit(L, &b); | 402 | luaL_buffinit(L, &b); |
269 | for (;;) { | 403 | for (;;) { |
270 | size_t l; | 404 | size_t l; |
271 | size_t r; | 405 | size_t r; |
272 | char *p = luaL_prepbuffer(&b); | 406 | char *p = luaL_prepbuffer(&b); |
273 | r = rb->read_line(*f, p, LUAL_BUFFERSIZE); | 407 | r = rb->read_line((int)f, p, LUAL_BUFFERSIZE); |
274 | l = strlen(p); | 408 | l = strlen(p); |
275 | if (l == 0 || p[l-1] != '\n') | 409 | if (l == 0 || p[l-1] != '\n') |
276 | luaL_addsize(&b, l); | 410 | luaL_addsize(&b, l); |
277 | else { | 411 | else { |
278 | luaL_addsize(&b, l - 1); /* do not include `eol' */ | 412 | luaL_addsize(&b, l - chop); /* chop 'eol' if needed */ |
279 | luaL_pushresult(&b); /* close buffer */ | 413 | luaL_pushresult(&b); /* close buffer */ |
280 | return 1; /* read at least an `eol' */ | 414 | return 1; /* read at least an `eol' */ |
281 | } | 415 | } |
282 | if (r < LUAL_BUFFERSIZE) { /* eof? */ | 416 | if (r < LUAL_BUFFERSIZE) { /* eof? */ |
283 | luaL_pushresult(&b); /* close buffer */ | 417 | luaL_pushresult(&b); /* close buffer */ |
284 | return (lua_objlen(L, -1) > 0); /* check whether read something */ | 418 | return (lua_rawlen(L, -1) > 0); /* check whether read something */ |
285 | } | 419 | } |
286 | } | 420 | } |
287 | } | 421 | } |
288 | 422 | ||
289 | 423 | ||
290 | static int read_chars (lua_State *L, int *f, size_t n) { | 424 | #define MAX_SIZE_T (~(size_t)0) |
291 | size_t rlen; /* how much to read */ | 425 | |
292 | size_t nr; /* number of chars actually read */ | 426 | static void read_all (lua_State *L, FILE *f) { |
427 | size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ | ||
293 | luaL_Buffer b; | 428 | luaL_Buffer b; |
294 | luaL_buffinit(L, &b); | 429 | luaL_buffinit(L, &b); |
295 | rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ | 430 | for (;;) { |
296 | do { | 431 | char *p = luaL_prepbuffsize(&b, rlen); |
297 | char *p = luaL_prepbuffer(&b); | 432 | size_t nr = rb->read((int)f, p, rlen); |
298 | if (rlen > n) rlen = n; /* cannot read more than asked */ | ||
299 | nr = rb->read(*f, p, rlen); | ||
300 | luaL_addsize(&b, nr); | 433 | luaL_addsize(&b, nr); |
301 | n -= nr; /* still have to read `n' chars */ | 434 | if (nr < rlen) break; /* eof? */ |
302 | } while (n > 0 && nr == rlen); /* until end of count or eof */ | 435 | else if (rlen <= (MAX_SIZE_T / 4)) /* avoid buffers too large */ |
436 | rlen *= 2; /* double buffer size at each iteration */ | ||
437 | } | ||
438 | luaL_pushresult(&b); /* close buffer */ | ||
439 | } | ||
440 | |||
441 | |||
442 | static int read_chars (lua_State *L, FILE *f, size_t n) { | ||
443 | size_t nr; /* number of chars actually read */ | ||
444 | char *p; | ||
445 | luaL_Buffer b; | ||
446 | luaL_buffinit(L, &b); | ||
447 | p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ | ||
448 | nr = rb->read((int)f, p, n); /* try to read 'n' chars */ | ||
449 | luaL_addsize(&b, nr); | ||
303 | luaL_pushresult(&b); /* close buffer */ | 450 | luaL_pushresult(&b); /* close buffer */ |
304 | return (n == 0 || lua_objlen(L, -1) > 0); | 451 | return (nr > 0); /* true iff read something */ |
305 | } | 452 | } |
306 | 453 | ||
307 | 454 | ||
308 | static int g_read (lua_State *L, int *f, int first) { | 455 | static int g_read (lua_State *L, FILE *f, int first) { |
309 | int nargs = lua_gettop(L) - 1; | 456 | int nargs = lua_gettop(L) - 1; |
310 | int success; | 457 | int success; |
311 | int n; | 458 | int n; |
312 | if (nargs == 0) { /* no arguments? */ | 459 | if (nargs == 0) { /* no arguments? */ |
313 | success = _read_line(L, f); | 460 | success = _read_line(L, f, 1); |
314 | n = first+1; /* to return 1 result */ | 461 | n = first+1; /* to return 1 result */ |
315 | } | 462 | } |
316 | else { /* ensure stack space for all results and for auxlib's buffer */ | 463 | else { /* ensure stack space for all results and for auxlib's buffer */ |
@@ -329,10 +476,13 @@ static int g_read (lua_State *L, int *f, int first) { | |||
329 | success = read_number(L, f); | 476 | success = read_number(L, f); |
330 | break; | 477 | break; |
331 | case 'l': /* line */ | 478 | case 'l': /* line */ |
332 | success = _read_line(L, f); | 479 | success = _read_line(L, f, 1); |
480 | break; | ||
481 | case 'L': /* line with end-of-line */ | ||
482 | success = _read_line(L, f, 0); | ||
333 | break; | 483 | break; |
334 | case 'a': /* file */ | 484 | case 'a': /* file */ |
335 | read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ | 485 | read_all(L, f); /* read entire file */ |
336 | success = 1; /* always success */ | 486 | success = 1; /* always success */ |
337 | break; | 487 | break; |
338 | default: | 488 | default: |
@@ -360,14 +510,24 @@ static int f_read (lua_State *L) { | |||
360 | 510 | ||
361 | 511 | ||
362 | static int io_readline (lua_State *L) { | 512 | static int io_readline (lua_State *L) { |
363 | int *f = (int *) lua_touserdata(L, lua_upvalueindex(1)); | 513 | LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); |
364 | int sucess; | 514 | int i; |
365 | if (*f < 0) /* file is already closed? */ | 515 | int n = (int)lua_tointeger(L, lua_upvalueindex(2)); |
366 | luaL_error(L, "file is already closed"); | 516 | if (isclosed(p)) /* file is already closed? */ |
367 | sucess = _read_line(L, f); | 517 | return luaL_error(L, "file is already closed"); |
368 | if (sucess) return 1; | 518 | lua_settop(L , 1); |
369 | else { /* EOF */ | 519 | for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ |
370 | if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ | 520 | lua_pushvalue(L, lua_upvalueindex(3 + i)); |
521 | n = g_read(L, p->f, 2); /* 'n' is number of results */ | ||
522 | lua_assert(n > 0); /* should return at least a nil */ | ||
523 | if (!lua_isnil(L, -n)) /* read at least one value? */ | ||
524 | return n; /* return them */ | ||
525 | else { /* first result is nil: EOF or error */ | ||
526 | if (n > 1) { /* is there error information? */ | ||
527 | /* 2nd result is error message */ | ||
528 | return luaL_error(L, "%s", lua_tostring(L, -n + 1)); | ||
529 | } | ||
530 | if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ | ||
371 | lua_settop(L, 0); | 531 | lua_settop(L, 0); |
372 | lua_pushvalue(L, lua_upvalueindex(1)); | 532 | lua_pushvalue(L, lua_upvalueindex(1)); |
373 | aux_close(L); /* close it */ | 533 | aux_close(L); /* close it */ |
@@ -379,22 +539,23 @@ static int io_readline (lua_State *L) { | |||
379 | /* }====================================================== */ | 539 | /* }====================================================== */ |
380 | 540 | ||
381 | 541 | ||
382 | static int g_write (lua_State *L, int *f, int arg) { | 542 | static int g_write (lua_State *L, FILE *f, int arg) { |
383 | int nargs = lua_gettop(L) - 1; | 543 | int nargs = lua_gettop(L) - arg; |
384 | int status = 1; | 544 | int status = 1; |
385 | for (; nargs--; arg++) { | 545 | for (; nargs--; arg++) { |
386 | if (lua_type(L, arg) == LUA_TNUMBER) { | 546 | if (lua_type(L, arg) == LUA_TNUMBER) { |
387 | /* optimization: could be done exactly as for strings */ | 547 | /* optimization: could be done exactly as for strings */ |
388 | status = status && | 548 | status = status && |
389 | rb->fdprintf(*f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; | 549 | rb->fdprintf((int)f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; |
390 | } | 550 | } |
391 | else { | 551 | else { |
392 | size_t l; | 552 | size_t l; |
393 | const char *s = luaL_checklstring(L, arg, &l); | 553 | const char *s = luaL_checklstring(L, arg, &l); |
394 | status = status && (rb->write(*f, s, l) == (ssize_t)l); | 554 | status = status && (rb->write((int)f, s, l) == (ssize_t)l); |
395 | } | 555 | } |
396 | } | 556 | } |
397 | return pushresult(L, status, NULL); | 557 | if (status) return 1; /* file handle already on stack top */ |
558 | else return luaL_fileresult(L, status, NULL); | ||
398 | } | 559 | } |
399 | 560 | ||
400 | 561 | ||
@@ -404,47 +565,86 @@ static int io_write (lua_State *L) { | |||
404 | 565 | ||
405 | 566 | ||
406 | static int f_write (lua_State *L) { | 567 | static int f_write (lua_State *L) { |
407 | return g_write(L, tofile(L), 2); | 568 | FILE *f = tofile(L); |
569 | lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ | ||
570 | return g_write(L, f, 2); | ||
408 | } | 571 | } |
409 | 572 | ||
410 | 573 | ||
411 | static int f_seek (lua_State *L) { | 574 | static int f_seek (lua_State *L) { |
412 | static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; | 575 | static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; |
413 | static const char *const modenames[] = {"set", "cur", "end", NULL}; | 576 | static const char *const modenames[] = {"set", "cur", "end", NULL}; |
414 | int f = *tofile(L); | 577 | FILE *f = tofile(L); |
415 | int op = luaL_checkoption(L, 2, "cur", modenames); | 578 | int op = luaL_checkoption(L, 2, "cur", modenames); |
416 | long offset = luaL_optlong(L, 3, 0); | 579 | lua_Number p3 = luaL_optnumber(L, 3, 0); |
417 | op = rb->lseek(f, offset, mode[op]); | 580 | l_seeknum offset = (l_seeknum)p3; |
581 | luaL_argcheck(L, (lua_Number)offset == p3, 3, | ||
582 | "not an integer in proper range"); | ||
583 | op = rb->lseek((int)f, offset, mode[op]); | ||
418 | if (op) | 584 | if (op) |
419 | return pushresult(L, 0, NULL); /* error */ | 585 | return luaL_fileresult(L, 0, NULL); /* error */ |
420 | else { | 586 | else { |
421 | lua_pushinteger(L, rb->lseek(f, 0, SEEK_CUR)); | 587 | lua_pushnumber(L, (lua_Number)rb->lseek((int)f, 0, SEEK_CUR)); |
422 | return 1; | 588 | return 1; |
423 | } | 589 | } |
424 | } | 590 | } |
425 | 591 | ||
592 | #if 0 | ||
593 | static int f_setvbuf (lua_State *L) { | ||
594 | static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; | ||
595 | static const char *const modenames[] = {"no", "full", "line", NULL}; | ||
596 | FILE *f = tofile(L); | ||
597 | int op = luaL_checkoption(L, 2, NULL, modenames); | ||
598 | lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); | ||
599 | int res = setvbuf(f, NULL, mode[op], sz); | ||
600 | return luaL_fileresult(L, res == 0, NULL); | ||
601 | } | ||
602 | |||
426 | 603 | ||
604 | |||
605 | static int io_flush (lua_State *L) { | ||
606 | return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); | ||
607 | } | ||
608 | |||
609 | |||
610 | static int f_flush (lua_State *L) { | ||
611 | return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); | ||
612 | } | ||
613 | #endif | ||
614 | |||
615 | |||
616 | /* | ||
617 | ** functions for 'io' library | ||
618 | */ | ||
427 | static const luaL_Reg iolib[] = { | 619 | static const luaL_Reg iolib[] = { |
428 | {"close", io_close}, | 620 | {"close", io_close}, |
621 | /*{"flush", io_flush},*/ | ||
429 | {"input", io_input}, | 622 | {"input", io_input}, |
430 | {"lines", io_lines}, | 623 | {"lines", io_lines}, |
431 | {"open", io_open}, | 624 | {"open", io_open}, |
432 | {"output", io_output}, | 625 | {"output", io_output}, |
626 | /*{"popen", io_popen},*/ | ||
433 | {"read", io_read}, | 627 | {"read", io_read}, |
628 | /*{"tmpfile", io_tmpfile},*/ | ||
434 | {"type", io_type}, | 629 | {"type", io_type}, |
435 | {"write", io_write}, | 630 | {"write", io_write}, |
436 | {NULL, NULL} | 631 | {NULL, NULL} |
437 | }; | 632 | }; |
438 | 633 | ||
439 | 634 | ||
635 | /* | ||
636 | ** methods for file handles | ||
637 | */ | ||
440 | static const luaL_Reg flib[] = { | 638 | static const luaL_Reg flib[] = { |
441 | {"close", io_close}, | 639 | {"close", io_close}, |
640 | /*{"flush", f_flush},*/ | ||
442 | {"lines", f_lines}, | 641 | {"lines", f_lines}, |
443 | {"read", f_read}, | 642 | {"read", f_read}, |
444 | {"seek", f_seek}, | 643 | {"seek", f_seek}, |
644 | /*{"setvbuf", f_setvbuf},*/ | ||
445 | {"write", f_write}, | 645 | {"write", f_write}, |
446 | {"__gc", io_gc}, | 646 | {"__gc", f_gc}, |
447 | {"__tostring", io_tostring}, | 647 | {"__tostring", f_tostring}, |
448 | {NULL, NULL} | 648 | {NULL, NULL} |
449 | }; | 649 | }; |
450 | 650 | ||
@@ -453,16 +653,40 @@ static void createmeta (lua_State *L) { | |||
453 | luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ | 653 | luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ |
454 | lua_pushvalue(L, -1); /* push metatable */ | 654 | lua_pushvalue(L, -1); /* push metatable */ |
455 | lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ | 655 | lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ |
456 | luaL_register(L, NULL, flib); /* file methods */ | 656 | luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ |
657 | lua_pop(L, 1); /* pop new metatable */ | ||
457 | } | 658 | } |
458 | 659 | ||
459 | 660 | ||
460 | LUALIB_API int luaopen_io (lua_State *L) { | 661 | /* |
662 | ** function to (not) close the standard files stdin, stdout, and stderr | ||
663 | */ | ||
664 | #if 0 | ||
665 | static int io_noclose (lua_State *L) { | ||
666 | LStream *p = tolstream(L); | ||
667 | p->closef = &io_noclose; /* keep file opened */ | ||
668 | lua_pushnil(L); | ||
669 | lua_pushliteral(L, "cannot close standard file"); | ||
670 | return 2; | ||
671 | } | ||
672 | |||
673 | |||
674 | static void createstdfile (lua_State *L, FILE *f, const char *k, | ||
675 | const char *fname) { | ||
676 | LStream *p = newprefile(L); | ||
677 | p->f = f; | ||
678 | p->closef = &io_noclose; | ||
679 | if (k != NULL) { | ||
680 | lua_pushvalue(L, -1); | ||
681 | lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ | ||
682 | } | ||
683 | lua_setfield(L, -2, fname); /* add file to module */ | ||
684 | } | ||
685 | #endif | ||
686 | |||
687 | LUAMOD_API int luaopen_io (lua_State *L) { | ||
688 | luaL_newlib(L, iolib); /* new module */ | ||
461 | createmeta(L); | 689 | createmeta(L); |
462 | lua_replace(L, LUA_ENVIRONINDEX); | ||
463 | /* open library */ | ||
464 | luaL_register(L, LUA_IOLIBNAME, iolib); | ||
465 | /* create (and set) default files */ | 690 | /* create (and set) default files */ |
466 | lua_pop(L, 1); /* pop environment for default files */ | ||
467 | return 1; | 691 | return 1; |
468 | } | 692 | } |
diff --git a/apps/plugins/lua/llex.c b/apps/plugins/lua/llex.c index 85ac516be3..8d410f620d 100644 --- a/apps/plugins/lua/llex.c +++ b/apps/plugins/lua/llex.c | |||
@@ -1,12 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ | 2 | ** $Id: llex.c,v 2.63.1.2 2013/08/30 15:49:41 roberto Exp $ |
3 | ** Lexical Analyzer | 3 | ** Lexical Analyzer |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
6 | 6 | ||
7 | 7 | ||
8 | #include <ctype.h> | ||
9 | /* #include <locale.h> */ | ||
10 | #include <string.h> | 8 | #include <string.h> |
11 | 9 | ||
12 | #define llex_c | 10 | #define llex_c |
@@ -14,6 +12,7 @@ | |||
14 | 12 | ||
15 | #include "lua.h" | 13 | #include "lua.h" |
16 | 14 | ||
15 | #include "lctype.h" | ||
17 | #include "ldo.h" | 16 | #include "ldo.h" |
18 | #include "llex.h" | 17 | #include "llex.h" |
19 | #include "lobject.h" | 18 | #include "lobject.h" |
@@ -29,35 +28,36 @@ | |||
29 | 28 | ||
30 | 29 | ||
31 | 30 | ||
32 | |||
33 | #define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') | 31 | #define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') |
34 | 32 | ||
35 | 33 | ||
36 | /* ORDER RESERVED */ | 34 | /* ORDER RESERVED */ |
37 | const char *const luaX_tokens [] = { | 35 | static const char *const luaX_tokens [] = { |
38 | "and", "break", "do", "else", "elseif", | 36 | "and", "break", "do", "else", "elseif", |
39 | "end", "false", "for", "function", "if", | 37 | "end", "false", "for", "function", "goto", "if", |
40 | "in", "local", "nil", "not", "or", "repeat", | 38 | "in", "local", "nil", "not", "or", "repeat", |
41 | "return", "then", "true", "until", "while", | 39 | "return", "then", "true", "until", "while", |
42 | "..", "...", "==", ">=", "<=", "~=", | 40 | "..", "...", "==", ">=", "<=", "~=", "::", "<eof>", |
43 | "<number>", "<name>", "<string>", "<eof>", | 41 | "<number>", "<name>", "<string>" |
44 | NULL | ||
45 | }; | 42 | }; |
46 | 43 | ||
47 | 44 | ||
48 | #define save_and_next(ls) (save(ls, ls->current), next(ls)) | 45 | #define save_and_next(ls) (save(ls, ls->current), next(ls)) |
49 | 46 | ||
50 | 47 | ||
48 | static l_noret lexerror (LexState *ls, const char *msg, int token); | ||
49 | |||
50 | |||
51 | static void save (LexState *ls, int c) { | 51 | static void save (LexState *ls, int c) { |
52 | Mbuffer *b = ls->buff; | 52 | Mbuffer *b = ls->buff; |
53 | if (b->n + 1 > b->buffsize) { | 53 | if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { |
54 | size_t newsize; | 54 | size_t newsize; |
55 | if (b->buffsize >= MAX_SIZET/2) | 55 | if (luaZ_sizebuffer(b) >= MAX_SIZET/2) |
56 | luaX_lexerror(ls, "lexical element too long", 0); | 56 | lexerror(ls, "lexical element too long", 0); |
57 | newsize = b->buffsize * 2; | 57 | newsize = luaZ_sizebuffer(b) * 2; |
58 | luaZ_resizebuffer(ls->L, b, newsize); | 58 | luaZ_resizebuffer(ls->L, b, newsize); |
59 | } | 59 | } |
60 | b->buffer[b->n++] = cast(char, c); | 60 | b->buffer[luaZ_bufflen(b)++] = cast(char, c); |
61 | } | 61 | } |
62 | 62 | ||
63 | 63 | ||
@@ -66,23 +66,24 @@ void luaX_init (lua_State *L) { | |||
66 | for (i=0; i<NUM_RESERVED; i++) { | 66 | for (i=0; i<NUM_RESERVED; i++) { |
67 | TString *ts = luaS_new(L, luaX_tokens[i]); | 67 | TString *ts = luaS_new(L, luaX_tokens[i]); |
68 | luaS_fix(ts); /* reserved words are never collected */ | 68 | luaS_fix(ts); /* reserved words are never collected */ |
69 | lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN); | 69 | ts->tsv.extra = cast_byte(i+1); /* reserved word */ |
70 | ts->tsv.reserved = cast_byte(i+1); /* reserved word */ | ||
71 | } | 70 | } |
72 | } | 71 | } |
73 | 72 | ||
74 | 73 | ||
75 | #define MAXSRC 80 | ||
76 | |||
77 | |||
78 | const char *luaX_token2str (LexState *ls, int token) { | 74 | const char *luaX_token2str (LexState *ls, int token) { |
79 | if (token < FIRST_RESERVED) { | 75 | if (token < FIRST_RESERVED) { /* single-byte symbols? */ |
80 | lua_assert(token == cast(unsigned char, token)); | 76 | lua_assert(token == cast(unsigned char, token)); |
81 | return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : | 77 | return (lisprint(token)) ? luaO_pushfstring(ls->L, LUA_QL("%c"), token) : |
82 | luaO_pushfstring(ls->L, "%c", token); | 78 | luaO_pushfstring(ls->L, "char(%d)", token); |
79 | } | ||
80 | else { | ||
81 | const char *s = luaX_tokens[token - FIRST_RESERVED]; | ||
82 | if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ | ||
83 | return luaO_pushfstring(ls->L, LUA_QS, s); | ||
84 | else /* names, strings, and numerals */ | ||
85 | return s; | ||
83 | } | 86 | } |
84 | else | ||
85 | return luaX_tokens[token-FIRST_RESERVED]; | ||
86 | } | 87 | } |
87 | 88 | ||
88 | 89 | ||
@@ -92,38 +93,57 @@ static const char *txtToken (LexState *ls, int token) { | |||
92 | case TK_STRING: | 93 | case TK_STRING: |
93 | case TK_NUMBER: | 94 | case TK_NUMBER: |
94 | save(ls, '\0'); | 95 | save(ls, '\0'); |
95 | return luaZ_buffer(ls->buff); | 96 | return luaO_pushfstring(ls->L, LUA_QS, luaZ_buffer(ls->buff)); |
96 | default: | 97 | default: |
97 | return luaX_token2str(ls, token); | 98 | return luaX_token2str(ls, token); |
98 | } | 99 | } |
99 | } | 100 | } |
100 | 101 | ||
101 | 102 | ||
102 | void luaX_lexerror (LexState *ls, const char *msg, int token) { | 103 | static l_noret lexerror (LexState *ls, const char *msg, int token) { |
103 | char buff[MAXSRC]; | 104 | char buff[LUA_IDSIZE]; |
104 | luaO_chunkid(buff, getstr(ls->source), MAXSRC); | 105 | luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE); |
105 | msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); | 106 | msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); |
106 | if (token) | 107 | if (token) |
107 | luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); | 108 | luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); |
108 | luaD_throw(ls->L, LUA_ERRSYNTAX); | 109 | luaD_throw(ls->L, LUA_ERRSYNTAX); |
109 | } | 110 | } |
110 | 111 | ||
111 | 112 | ||
112 | void luaX_syntaxerror (LexState *ls, const char *msg) { | 113 | l_noret luaX_syntaxerror (LexState *ls, const char *msg) { |
113 | luaX_lexerror(ls, msg, ls->t.token); | 114 | lexerror(ls, msg, ls->t.token); |
114 | } | 115 | } |
115 | 116 | ||
116 | 117 | ||
118 | /* | ||
119 | ** creates a new string and anchors it in function's table so that | ||
120 | ** it will not be collected until the end of the function's compilation | ||
121 | ** (by that time it should be anchored in function's prototype) | ||
122 | */ | ||
117 | TString *luaX_newstring (LexState *ls, const char *str, size_t l) { | 123 | TString *luaX_newstring (LexState *ls, const char *str, size_t l) { |
118 | lua_State *L = ls->L; | 124 | lua_State *L = ls->L; |
119 | TString *ts = luaS_newlstr(L, str, l); | 125 | TValue *o; /* entry for `str' */ |
120 | TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ | 126 | TString *ts = luaS_newlstr(L, str, l); /* create new string */ |
121 | if (ttisnil(o)) | 127 | setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ |
122 | setbvalue(o, 1); /* make sure `str' will not be collected */ | 128 | o = luaH_set(L, ls->fs->h, L->top - 1); |
129 | if (ttisnil(o)) { /* not in use yet? (see 'addK') */ | ||
130 | /* boolean value does not need GC barrier; | ||
131 | table has no metatable, so it does not need to invalidate cache */ | ||
132 | setbvalue(o, 1); /* t[string] = true */ | ||
133 | luaC_checkGC(L); | ||
134 | } | ||
135 | else { /* string already present */ | ||
136 | ts = rawtsvalue(keyfromval(o)); /* re-use value previously stored */ | ||
137 | } | ||
138 | L->top--; /* remove string from stack */ | ||
123 | return ts; | 139 | return ts; |
124 | } | 140 | } |
125 | 141 | ||
126 | 142 | ||
143 | /* | ||
144 | ** increment line number and skips newline sequence (any of | ||
145 | ** \n, \r, \n\r, or \r\n) | ||
146 | */ | ||
127 | static void inclinenumber (LexState *ls) { | 147 | static void inclinenumber (LexState *ls) { |
128 | int old = ls->current; | 148 | int old = ls->current; |
129 | lua_assert(currIsNewline(ls)); | 149 | lua_assert(currIsNewline(ls)); |
@@ -135,17 +155,20 @@ static void inclinenumber (LexState *ls) { | |||
135 | } | 155 | } |
136 | 156 | ||
137 | 157 | ||
138 | void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { | 158 | void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, |
159 | int firstchar) { | ||
139 | ls->decpoint = '.'; | 160 | ls->decpoint = '.'; |
140 | ls->L = L; | 161 | ls->L = L; |
162 | ls->current = firstchar; | ||
141 | ls->lookahead.token = TK_EOS; /* no look-ahead token */ | 163 | ls->lookahead.token = TK_EOS; /* no look-ahead token */ |
142 | ls->z = z; | 164 | ls->z = z; |
143 | ls->fs = NULL; | 165 | ls->fs = NULL; |
144 | ls->linenumber = 1; | 166 | ls->linenumber = 1; |
145 | ls->lastline = 1; | 167 | ls->lastline = 1; |
146 | ls->source = source; | 168 | ls->source = source; |
169 | ls->envn = luaS_new(L, LUA_ENV); /* create env name */ | ||
170 | luaS_fix(ls->envn); /* never collect this name */ | ||
147 | luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ | 171 | luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ |
148 | next(ls); /* read first char */ | ||
149 | } | 172 | } |
150 | 173 | ||
151 | 174 | ||
@@ -159,13 +182,16 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { | |||
159 | 182 | ||
160 | 183 | ||
161 | static int check_next (LexState *ls, const char *set) { | 184 | static int check_next (LexState *ls, const char *set) { |
162 | if (!strchr(set, ls->current)) | 185 | if (ls->current == '\0' || !strchr(set, ls->current)) |
163 | return 0; | 186 | return 0; |
164 | save_and_next(ls); | 187 | save_and_next(ls); |
165 | return 1; | 188 | return 1; |
166 | } | 189 | } |
167 | 190 | ||
168 | 191 | ||
192 | /* | ||
193 | ** change all characters 'from' in buffer to 'to' | ||
194 | */ | ||
169 | static void buffreplace (LexState *ls, char from, char to) { | 195 | static void buffreplace (LexState *ls, char from, char to) { |
170 | size_t n = luaZ_bufflen(ls->buff); | 196 | size_t n = luaZ_bufflen(ls->buff); |
171 | char *p = luaZ_buffer(ls->buff); | 197 | char *p = luaZ_buffer(ls->buff); |
@@ -174,37 +200,59 @@ static void buffreplace (LexState *ls, char from, char to) { | |||
174 | } | 200 | } |
175 | 201 | ||
176 | 202 | ||
203 | #if !defined(getlocaledecpoint) | ||
204 | #define getlocaledecpoint() (localeconv()->decimal_point[0]) | ||
205 | #endif | ||
206 | |||
207 | |||
208 | #define buff2d(b,e) luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e) | ||
209 | |||
210 | /* | ||
211 | ** in case of format error, try to change decimal point separator to | ||
212 | ** the one defined in the current locale and check again | ||
213 | */ | ||
177 | static void trydecpoint (LexState *ls, SemInfo *seminfo) { | 214 | static void trydecpoint (LexState *ls, SemInfo *seminfo) { |
178 | /* format error: try to update decimal point separator */ | ||
179 | /* struct lconv *cv = localeconv(); */ | ||
180 | char old = ls->decpoint; | 215 | char old = ls->decpoint; |
181 | ls->decpoint = '.'; /* (cv ? cv->decimal_point[0] : '.'); */ | 216 | ls->decpoint = getlocaledecpoint(); |
182 | buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ | 217 | buffreplace(ls, old, ls->decpoint); /* try new decimal separator */ |
183 | if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { | 218 | if (!buff2d(ls->buff, &seminfo->r)) { |
184 | /* format error with correct decimal point: no more options */ | 219 | /* format error with correct decimal point: no more options */ |
185 | buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ | 220 | buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ |
186 | luaX_lexerror(ls, "malformed number", TK_NUMBER); | 221 | lexerror(ls, "malformed number", TK_NUMBER); |
187 | } | 222 | } |
188 | } | 223 | } |
189 | 224 | ||
190 | 225 | ||
191 | /* LUA_NUMBER */ | 226 | /* LUA_NUMBER */ |
227 | /* | ||
228 | ** this function is quite liberal in what it accepts, as 'luaO_str2d' | ||
229 | ** will reject ill-formed numerals. | ||
230 | */ | ||
192 | static void read_numeral (LexState *ls, SemInfo *seminfo) { | 231 | static void read_numeral (LexState *ls, SemInfo *seminfo) { |
193 | lua_assert(isdigit(ls->current)); | 232 | const char *expo = "Ee"; |
194 | do { | 233 | int first = ls->current; |
195 | save_and_next(ls); | 234 | lua_assert(lisdigit(ls->current)); |
196 | } while (isdigit(ls->current) || ls->current == '.'); | 235 | save_and_next(ls); |
197 | if (check_next(ls, "Ee")) /* `E'? */ | 236 | if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */ |
198 | check_next(ls, "+-"); /* optional exponent sign */ | 237 | expo = "Pp"; |
199 | while (isalnum(ls->current) || ls->current == '_') | 238 | for (;;) { |
200 | save_and_next(ls); | 239 | if (check_next(ls, expo)) /* exponent part? */ |
240 | check_next(ls, "+-"); /* optional exponent sign */ | ||
241 | if (lisxdigit(ls->current) || ls->current == '.') | ||
242 | save_and_next(ls); | ||
243 | else break; | ||
244 | } | ||
201 | save(ls, '\0'); | 245 | save(ls, '\0'); |
202 | buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ | 246 | buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ |
203 | if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ | 247 | if (!buff2d(ls->buff, &seminfo->r)) /* format error? */ |
204 | trydecpoint(ls, seminfo); /* try to update decimal point separator */ | 248 | trydecpoint(ls, seminfo); /* try to update decimal point separator */ |
205 | } | 249 | } |
206 | 250 | ||
207 | 251 | ||
252 | /* | ||
253 | ** skip a sequence '[=*[' or ']=*]' and return its number of '='s or | ||
254 | ** -1 if sequence is malformed | ||
255 | */ | ||
208 | static int skip_sep (LexState *ls) { | 256 | static int skip_sep (LexState *ls) { |
209 | int count = 0; | 257 | int count = 0; |
210 | int s = ls->current; | 258 | int s = ls->current; |
@@ -219,43 +267,23 @@ static int skip_sep (LexState *ls) { | |||
219 | 267 | ||
220 | 268 | ||
221 | static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { | 269 | static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { |
222 | int cont = 0; | ||
223 | (void)(cont); /* avoid warnings when `cont' is not used */ | ||
224 | save_and_next(ls); /* skip 2nd `[' */ | 270 | save_and_next(ls); /* skip 2nd `[' */ |
225 | if (currIsNewline(ls)) /* string starts with a newline? */ | 271 | if (currIsNewline(ls)) /* string starts with a newline? */ |
226 | inclinenumber(ls); /* skip it */ | 272 | inclinenumber(ls); /* skip it */ |
227 | for (;;) { | 273 | for (;;) { |
228 | switch (ls->current) { | 274 | switch (ls->current) { |
229 | case EOZ: | 275 | case EOZ: |
230 | luaX_lexerror(ls, (seminfo) ? "unfinished long string" : | 276 | lexerror(ls, (seminfo) ? "unfinished long string" : |
231 | "unfinished long comment", TK_EOS); | 277 | "unfinished long comment", TK_EOS); |
232 | break; /* to avoid warnings */ | 278 | break; /* to avoid warnings */ |
233 | #if defined(LUA_COMPAT_LSTR) | ||
234 | case '[': { | ||
235 | if (skip_sep(ls) == sep) { | ||
236 | save_and_next(ls); /* skip 2nd `[' */ | ||
237 | cont++; | ||
238 | #if LUA_COMPAT_LSTR == 1 | ||
239 | if (sep == 0) | ||
240 | luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); | ||
241 | #endif | ||
242 | } | ||
243 | break; | ||
244 | } | ||
245 | #endif | ||
246 | case ']': { | 279 | case ']': { |
247 | if (skip_sep(ls) == sep) { | 280 | if (skip_sep(ls) == sep) { |
248 | save_and_next(ls); /* skip 2nd `]' */ | 281 | save_and_next(ls); /* skip 2nd `]' */ |
249 | #if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 | ||
250 | cont--; | ||
251 | if (sep == 0 && cont >= 0) break; | ||
252 | #endif | ||
253 | goto endloop; | 282 | goto endloop; |
254 | } | 283 | } |
255 | break; | 284 | break; |
256 | } | 285 | } |
257 | case '\n': | 286 | case '\n': case '\r': { |
258 | case '\r': { | ||
259 | save(ls, '\n'); | 287 | save(ls, '\n'); |
260 | inclinenumber(ls); | 288 | inclinenumber(ls); |
261 | if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ | 289 | if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ |
@@ -273,51 +301,91 @@ static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { | |||
273 | } | 301 | } |
274 | 302 | ||
275 | 303 | ||
304 | static void escerror (LexState *ls, int *c, int n, const char *msg) { | ||
305 | int i; | ||
306 | luaZ_resetbuffer(ls->buff); /* prepare error message */ | ||
307 | save(ls, '\\'); | ||
308 | for (i = 0; i < n && c[i] != EOZ; i++) | ||
309 | save(ls, c[i]); | ||
310 | lexerror(ls, msg, TK_STRING); | ||
311 | } | ||
312 | |||
313 | |||
314 | static int readhexaesc (LexState *ls) { | ||
315 | int c[3], i; /* keep input for error message */ | ||
316 | int r = 0; /* result accumulator */ | ||
317 | c[0] = 'x'; /* for error message */ | ||
318 | for (i = 1; i < 3; i++) { /* read two hexadecimal digits */ | ||
319 | c[i] = next(ls); | ||
320 | if (!lisxdigit(c[i])) | ||
321 | escerror(ls, c, i + 1, "hexadecimal digit expected"); | ||
322 | r = (r << 4) + luaO_hexavalue(c[i]); | ||
323 | } | ||
324 | return r; | ||
325 | } | ||
326 | |||
327 | |||
328 | static int readdecesc (LexState *ls) { | ||
329 | int c[3], i; | ||
330 | int r = 0; /* result accumulator */ | ||
331 | for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ | ||
332 | c[i] = ls->current; | ||
333 | r = 10*r + c[i] - '0'; | ||
334 | next(ls); | ||
335 | } | ||
336 | if (r > UCHAR_MAX) | ||
337 | escerror(ls, c, i, "decimal escape too large"); | ||
338 | return r; | ||
339 | } | ||
340 | |||
341 | |||
276 | static void read_string (LexState *ls, int del, SemInfo *seminfo) { | 342 | static void read_string (LexState *ls, int del, SemInfo *seminfo) { |
277 | save_and_next(ls); | 343 | save_and_next(ls); /* keep delimiter (for error messages) */ |
278 | while (ls->current != del) { | 344 | while (ls->current != del) { |
279 | switch (ls->current) { | 345 | switch (ls->current) { |
280 | case EOZ: | 346 | case EOZ: |
281 | luaX_lexerror(ls, "unfinished string", TK_EOS); | 347 | lexerror(ls, "unfinished string", TK_EOS); |
282 | continue; /* to avoid warnings */ | 348 | break; /* to avoid warnings */ |
283 | case '\n': | 349 | case '\n': |
284 | case '\r': | 350 | case '\r': |
285 | luaX_lexerror(ls, "unfinished string", TK_STRING); | 351 | lexerror(ls, "unfinished string", TK_STRING); |
286 | continue; /* to avoid warnings */ | 352 | break; /* to avoid warnings */ |
287 | case '\\': { | 353 | case '\\': { /* escape sequences */ |
288 | int c; | 354 | int c; /* final character to be saved */ |
289 | next(ls); /* do not save the `\' */ | 355 | next(ls); /* do not save the `\' */ |
290 | switch (ls->current) { | 356 | switch (ls->current) { |
291 | case 'a': c = '\a'; break; | 357 | case 'a': c = '\a'; goto read_save; |
292 | case 'b': c = '\b'; break; | 358 | case 'b': c = '\b'; goto read_save; |
293 | case 'f': c = '\f'; break; | 359 | case 'f': c = '\f'; goto read_save; |
294 | case 'n': c = '\n'; break; | 360 | case 'n': c = '\n'; goto read_save; |
295 | case 'r': c = '\r'; break; | 361 | case 'r': c = '\r'; goto read_save; |
296 | case 't': c = '\t'; break; | 362 | case 't': c = '\t'; goto read_save; |
297 | case 'v': c = '\v'; break; | 363 | case 'v': c = '\v'; goto read_save; |
298 | case '\n': /* go through */ | 364 | case 'x': c = readhexaesc(ls); goto read_save; |
299 | case '\r': save(ls, '\n'); inclinenumber(ls); continue; | 365 | case '\n': case '\r': |
300 | case EOZ: continue; /* will raise an error next loop */ | 366 | inclinenumber(ls); c = '\n'; goto only_save; |
301 | default: { | 367 | case '\\': case '\"': case '\'': |
302 | if (!isdigit(ls->current)) | 368 | c = ls->current; goto read_save; |
303 | save_and_next(ls); /* handles \\, \", \', and \? */ | 369 | case EOZ: goto no_save; /* will raise an error next loop */ |
304 | else { /* \xxx */ | 370 | case 'z': { /* zap following span of spaces */ |
305 | int i = 0; | 371 | next(ls); /* skip the 'z' */ |
306 | c = 0; | 372 | while (lisspace(ls->current)) { |
307 | do { | 373 | if (currIsNewline(ls)) inclinenumber(ls); |
308 | c = 10*c + (ls->current-'0'); | 374 | else next(ls); |
309 | next(ls); | ||
310 | } while (++i<3 && isdigit(ls->current)); | ||
311 | if (c > UCHAR_MAX) | ||
312 | luaX_lexerror(ls, "escape sequence too large", TK_STRING); | ||
313 | save(ls, c); | ||
314 | } | 375 | } |
315 | continue; | 376 | goto no_save; |
377 | } | ||
378 | default: { | ||
379 | if (!lisdigit(ls->current)) | ||
380 | escerror(ls, &ls->current, 1, "invalid escape sequence"); | ||
381 | /* digital escape \ddd */ | ||
382 | c = readdecesc(ls); | ||
383 | goto only_save; | ||
316 | } | 384 | } |
317 | } | 385 | } |
318 | save(ls, c); | 386 | read_save: next(ls); /* read next character */ |
319 | next(ls); | 387 | only_save: save(ls, c); /* save 'c' */ |
320 | continue; | 388 | no_save: break; |
321 | } | 389 | } |
322 | default: | 390 | default: |
323 | save_and_next(ls); | 391 | save_and_next(ls); |
@@ -333,38 +401,41 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
333 | luaZ_resetbuffer(ls->buff); | 401 | luaZ_resetbuffer(ls->buff); |
334 | for (;;) { | 402 | for (;;) { |
335 | switch (ls->current) { | 403 | switch (ls->current) { |
336 | case '\n': | 404 | case '\n': case '\r': { /* line breaks */ |
337 | case '\r': { | ||
338 | inclinenumber(ls); | 405 | inclinenumber(ls); |
339 | continue; | 406 | break; |
340 | } | 407 | } |
341 | case '-': { | 408 | case ' ': case '\f': case '\t': case '\v': { /* spaces */ |
409 | next(ls); | ||
410 | break; | ||
411 | } | ||
412 | case '-': { /* '-' or '--' (comment) */ | ||
342 | next(ls); | 413 | next(ls); |
343 | if (ls->current != '-') return '-'; | 414 | if (ls->current != '-') return '-'; |
344 | /* else is a comment */ | 415 | /* else is a comment */ |
345 | next(ls); | 416 | next(ls); |
346 | if (ls->current == '[') { | 417 | if (ls->current == '[') { /* long comment? */ |
347 | int sep = skip_sep(ls); | 418 | int sep = skip_sep(ls); |
348 | luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ | 419 | luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ |
349 | if (sep >= 0) { | 420 | if (sep >= 0) { |
350 | read_long_string(ls, NULL, sep); /* long comment */ | 421 | read_long_string(ls, NULL, sep); /* skip long comment */ |
351 | luaZ_resetbuffer(ls->buff); | 422 | luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ |
352 | continue; | 423 | break; |
353 | } | 424 | } |
354 | } | 425 | } |
355 | /* else short comment */ | 426 | /* else short comment */ |
356 | while (!currIsNewline(ls) && ls->current != EOZ) | 427 | while (!currIsNewline(ls) && ls->current != EOZ) |
357 | next(ls); | 428 | next(ls); /* skip until end of line (or end of file) */ |
358 | continue; | 429 | break; |
359 | } | 430 | } |
360 | case '[': { | 431 | case '[': { /* long string or simply '[' */ |
361 | int sep = skip_sep(ls); | 432 | int sep = skip_sep(ls); |
362 | if (sep >= 0) { | 433 | if (sep >= 0) { |
363 | read_long_string(ls, seminfo, sep); | 434 | read_long_string(ls, seminfo, sep); |
364 | return TK_STRING; | 435 | return TK_STRING; |
365 | } | 436 | } |
366 | else if (sep == -1) return '['; | 437 | else if (sep == -1) return '['; |
367 | else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); | 438 | else lexerror(ls, "invalid long string delimiter", TK_STRING); |
368 | } | 439 | } |
369 | case '=': { | 440 | case '=': { |
370 | next(ls); | 441 | next(ls); |
@@ -386,56 +457,52 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
386 | if (ls->current != '=') return '~'; | 457 | if (ls->current != '=') return '~'; |
387 | else { next(ls); return TK_NE; } | 458 | else { next(ls); return TK_NE; } |
388 | } | 459 | } |
389 | case '"': | 460 | case ':': { |
390 | case '\'': { | 461 | next(ls); |
462 | if (ls->current != ':') return ':'; | ||
463 | else { next(ls); return TK_DBCOLON; } | ||
464 | } | ||
465 | case '"': case '\'': { /* short literal strings */ | ||
391 | read_string(ls, ls->current, seminfo); | 466 | read_string(ls, ls->current, seminfo); |
392 | return TK_STRING; | 467 | return TK_STRING; |
393 | } | 468 | } |
394 | case '.': { | 469 | case '.': { /* '.', '..', '...', or number */ |
395 | save_and_next(ls); | 470 | save_and_next(ls); |
396 | if (check_next(ls, ".")) { | 471 | if (check_next(ls, ".")) { |
397 | if (check_next(ls, ".")) | 472 | if (check_next(ls, ".")) |
398 | return TK_DOTS; /* ... */ | 473 | return TK_DOTS; /* '...' */ |
399 | else return TK_CONCAT; /* .. */ | 474 | else return TK_CONCAT; /* '..' */ |
400 | } | ||
401 | else if (!isdigit(ls->current)) return '.'; | ||
402 | else { | ||
403 | read_numeral(ls, seminfo); | ||
404 | return TK_NUMBER; | ||
405 | } | 475 | } |
476 | else if (!lisdigit(ls->current)) return '.'; | ||
477 | /* else go through */ | ||
478 | } | ||
479 | case '0': case '1': case '2': case '3': case '4': | ||
480 | case '5': case '6': case '7': case '8': case '9': { | ||
481 | read_numeral(ls, seminfo); | ||
482 | return TK_NUMBER; | ||
406 | } | 483 | } |
407 | case EOZ: { | 484 | case EOZ: { |
408 | return TK_EOS; | 485 | return TK_EOS; |
409 | } | 486 | } |
410 | default: { | 487 | default: { |
411 | if (isspace(ls->current)) { | 488 | if (lislalpha(ls->current)) { /* identifier or reserved word? */ |
412 | lua_assert(!currIsNewline(ls)); | ||
413 | next(ls); | ||
414 | continue; | ||
415 | } | ||
416 | else if (isdigit(ls->current)) { | ||
417 | read_numeral(ls, seminfo); | ||
418 | return TK_NUMBER; | ||
419 | } | ||
420 | else if (isalpha(ls->current) || ls->current == '_') { | ||
421 | /* identifier or reserved word */ | ||
422 | TString *ts; | 489 | TString *ts; |
423 | do { | 490 | do { |
424 | save_and_next(ls); | 491 | save_and_next(ls); |
425 | } while (isalnum(ls->current) || ls->current == '_'); | 492 | } while (lislalnum(ls->current)); |
426 | ts = luaX_newstring(ls, luaZ_buffer(ls->buff), | 493 | ts = luaX_newstring(ls, luaZ_buffer(ls->buff), |
427 | luaZ_bufflen(ls->buff)); | 494 | luaZ_bufflen(ls->buff)); |
428 | if (ts->tsv.reserved > 0) /* reserved word? */ | 495 | seminfo->ts = ts; |
429 | return ts->tsv.reserved - 1 + FIRST_RESERVED; | 496 | if (isreserved(ts)) /* reserved word? */ |
497 | return ts->tsv.extra - 1 + FIRST_RESERVED; | ||
430 | else { | 498 | else { |
431 | seminfo->ts = ts; | ||
432 | return TK_NAME; | 499 | return TK_NAME; |
433 | } | 500 | } |
434 | } | 501 | } |
435 | else { | 502 | else { /* single-char tokens (+ - / ...) */ |
436 | int c = ls->current; | 503 | int c = ls->current; |
437 | next(ls); | 504 | next(ls); |
438 | return c; /* single-char tokens (+ - / ...) */ | 505 | return c; |
439 | } | 506 | } |
440 | } | 507 | } |
441 | } | 508 | } |
@@ -454,8 +521,9 @@ void luaX_next (LexState *ls) { | |||
454 | } | 521 | } |
455 | 522 | ||
456 | 523 | ||
457 | void luaX_lookahead (LexState *ls) { | 524 | int luaX_lookahead (LexState *ls) { |
458 | lua_assert(ls->lookahead.token == TK_EOS); | 525 | lua_assert(ls->lookahead.token == TK_EOS); |
459 | ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); | 526 | ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); |
527 | return ls->lookahead.token; | ||
460 | } | 528 | } |
461 | 529 | ||
diff --git a/apps/plugins/lua/llex.h b/apps/plugins/lua/llex.h index fa8b7a2a28..a4acdd3021 100644 --- a/apps/plugins/lua/llex.h +++ b/apps/plugins/lua/llex.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: llex.h,v 1.72.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Lexical Analyzer | 3 | ** Lexical Analyzer |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -13,8 +13,6 @@ | |||
13 | 13 | ||
14 | #define FIRST_RESERVED 257 | 14 | #define FIRST_RESERVED 257 |
15 | 15 | ||
16 | /* maximum length of a reserved word */ | ||
17 | #define TOKEN_LEN (sizeof("function")/sizeof(char)) | ||
18 | 16 | ||
19 | 17 | ||
20 | /* | 18 | /* |
@@ -25,21 +23,17 @@ enum RESERVED { | |||
25 | /* terminal symbols denoted by reserved words */ | 23 | /* terminal symbols denoted by reserved words */ |
26 | TK_AND = FIRST_RESERVED, TK_BREAK, | 24 | TK_AND = FIRST_RESERVED, TK_BREAK, |
27 | TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, | 25 | TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, |
28 | TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, | 26 | TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, |
29 | TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, | 27 | TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, |
30 | /* other terminal symbols */ | 28 | /* other terminal symbols */ |
31 | TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, | 29 | TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_DBCOLON, TK_EOS, |
32 | TK_NAME, TK_STRING, TK_EOS | 30 | TK_NUMBER, TK_NAME, TK_STRING |
33 | }; | 31 | }; |
34 | 32 | ||
35 | /* number of reserved words */ | 33 | /* number of reserved words */ |
36 | #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) | 34 | #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) |
37 | 35 | ||
38 | 36 | ||
39 | /* array with token `names' */ | ||
40 | LUAI_DATA const char *const luaX_tokens []; | ||
41 | |||
42 | |||
43 | typedef union { | 37 | typedef union { |
44 | lua_Number r; | 38 | lua_Number r; |
45 | TString *ts; | 39 | TString *ts; |
@@ -52,29 +46,32 @@ typedef struct Token { | |||
52 | } Token; | 46 | } Token; |
53 | 47 | ||
54 | 48 | ||
49 | /* state of the lexer plus state of the parser when shared by all | ||
50 | functions */ | ||
55 | typedef struct LexState { | 51 | typedef struct LexState { |
56 | int current; /* current character (charint) */ | 52 | int current; /* current character (charint) */ |
57 | int linenumber; /* input line counter */ | 53 | int linenumber; /* input line counter */ |
58 | int lastline; /* line of last token `consumed' */ | 54 | int lastline; /* line of last token `consumed' */ |
59 | Token t; /* current token */ | 55 | Token t; /* current token */ |
60 | Token lookahead; /* look ahead token */ | 56 | Token lookahead; /* look ahead token */ |
61 | struct FuncState *fs; /* `FuncState' is private to the parser */ | 57 | struct FuncState *fs; /* current function (parser) */ |
62 | struct lua_State *L; | 58 | struct lua_State *L; |
63 | ZIO *z; /* input stream */ | 59 | ZIO *z; /* input stream */ |
64 | Mbuffer *buff; /* buffer for tokens */ | 60 | Mbuffer *buff; /* buffer for tokens */ |
61 | struct Dyndata *dyd; /* dynamic structures used by the parser */ | ||
65 | TString *source; /* current source name */ | 62 | TString *source; /* current source name */ |
63 | TString *envn; /* environment variable name */ | ||
66 | char decpoint; /* locale decimal point */ | 64 | char decpoint; /* locale decimal point */ |
67 | } LexState; | 65 | } LexState; |
68 | 66 | ||
69 | 67 | ||
70 | LUAI_FUNC void luaX_init (lua_State *L); | 68 | LUAI_FUNC void luaX_init (lua_State *L); |
71 | LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, | 69 | LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, |
72 | TString *source); | 70 | TString *source, int firstchar); |
73 | LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); | 71 | LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); |
74 | LUAI_FUNC void luaX_next (LexState *ls); | 72 | LUAI_FUNC void luaX_next (LexState *ls); |
75 | LUAI_FUNC void luaX_lookahead (LexState *ls); | 73 | LUAI_FUNC int luaX_lookahead (LexState *ls); |
76 | LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); | 74 | LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); |
77 | LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); | ||
78 | LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); | 75 | LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); |
79 | 76 | ||
80 | 77 | ||
diff --git a/apps/plugins/lua/llimits.h b/apps/plugins/lua/llimits.h index a31ad160ad..152dd05515 100644 --- a/apps/plugins/lua/llimits.h +++ b/apps/plugins/lua/llimits.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: llimits.h,v 1.103.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Limits, basic types, and some other `installation-dependent' definitions | 3 | ** Limits, basic types, and some other `installation-dependent' definitions |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -15,7 +15,7 @@ | |||
15 | #include "lua.h" | 15 | #include "lua.h" |
16 | 16 | ||
17 | 17 | ||
18 | typedef LUAI_UINT32 lu_int32; | 18 | typedef unsigned LUA_INT32 lu_int32; |
19 | 19 | ||
20 | typedef LUAI_UMEM lu_mem; | 20 | typedef LUAI_UMEM lu_mem; |
21 | 21 | ||
@@ -31,6 +31,8 @@ typedef unsigned char lu_byte; | |||
31 | 31 | ||
32 | #define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) | 32 | #define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) |
33 | 33 | ||
34 | #define MAX_LMEM ((l_mem) ((MAX_LUMEM >> 1) - 2)) | ||
35 | |||
34 | 36 | ||
35 | #define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ | 37 | #define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ |
36 | 38 | ||
@@ -44,6 +46,10 @@ typedef unsigned char lu_byte; | |||
44 | 46 | ||
45 | 47 | ||
46 | /* type to ensure maximum alignment */ | 48 | /* type to ensure maximum alignment */ |
49 | #if !defined(LUAI_USER_ALIGNMENT_T) | ||
50 | #define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } | ||
51 | #endif | ||
52 | |||
47 | typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; | 53 | typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; |
48 | 54 | ||
49 | 55 | ||
@@ -52,36 +58,75 @@ typedef LUAI_UACNUMBER l_uacNumber; | |||
52 | 58 | ||
53 | 59 | ||
54 | /* internal assertions for in-house debugging */ | 60 | /* internal assertions for in-house debugging */ |
55 | #ifdef lua_assert | 61 | #if defined(lua_assert) |
56 | |||
57 | #define check_exp(c,e) (lua_assert(c), (e)) | 62 | #define check_exp(c,e) (lua_assert(c), (e)) |
58 | #define api_check(l,e) lua_assert(e) | 63 | /* to avoid problems with conditions too long */ |
59 | 64 | #define lua_longassert(c) { if (!(c)) lua_assert(0); } | |
60 | #else | 65 | #else |
61 | |||
62 | #define lua_assert(c) ((void)0) | 66 | #define lua_assert(c) ((void)0) |
63 | #define check_exp(c,e) (e) | 67 | #define check_exp(c,e) (e) |
64 | #define api_check luai_apicheck | 68 | #define lua_longassert(c) ((void)0) |
69 | #endif | ||
65 | 70 | ||
71 | /* | ||
72 | ** assertion for checking API calls | ||
73 | */ | ||
74 | #if !defined(luai_apicheck) | ||
75 | |||
76 | #if defined(LUA_USE_APICHECK) | ||
77 | #include <assert.h> | ||
78 | #define luai_apicheck(L,e) assert(e) | ||
79 | #else | ||
80 | #define luai_apicheck(L,e) lua_assert(e) | ||
66 | #endif | 81 | #endif |
67 | 82 | ||
83 | #endif | ||
84 | |||
85 | #define api_check(l,e,msg) luai_apicheck(l,(e) && msg) | ||
86 | |||
68 | 87 | ||
69 | #ifndef UNUSED | 88 | #if !defined(UNUSED) |
70 | #define UNUSED(x) ((void)(x)) /* to avoid warnings */ | 89 | #define UNUSED(x) ((void)(x)) /* to avoid warnings */ |
71 | #endif | 90 | #endif |
72 | 91 | ||
73 | 92 | ||
74 | #ifndef cast | ||
75 | #define cast(t, exp) ((t)(exp)) | 93 | #define cast(t, exp) ((t)(exp)) |
76 | #endif | ||
77 | 94 | ||
78 | #define cast_byte(i) cast(lu_byte, (i)) | 95 | #define cast_byte(i) cast(lu_byte, (i)) |
79 | #define cast_num(i) cast(lua_Number, (i)) | 96 | #define cast_num(i) cast(lua_Number, (i)) |
80 | #define cast_int(i) cast(int, (i)) | 97 | #define cast_int(i) cast(int, (i)) |
98 | #define cast_uchar(i) cast(unsigned char, (i)) | ||
99 | |||
100 | |||
101 | /* | ||
102 | ** non-return type | ||
103 | */ | ||
104 | #if defined(__GNUC__) | ||
105 | #define l_noret void __attribute__((noreturn)) | ||
106 | #elif defined(_MSC_VER) | ||
107 | #define l_noret void __declspec(noreturn) | ||
108 | #else | ||
109 | #define l_noret void | ||
110 | #endif | ||
81 | 111 | ||
82 | 112 | ||
83 | 113 | ||
84 | /* | 114 | /* |
115 | ** maximum depth for nested C calls and syntactical nested non-terminals | ||
116 | ** in a program. (Value must fit in an unsigned short int.) | ||
117 | */ | ||
118 | #if !defined(LUAI_MAXCCALLS) | ||
119 | #define LUAI_MAXCCALLS 200 | ||
120 | #endif | ||
121 | |||
122 | /* | ||
123 | ** maximum number of upvalues in a closure (both C and Lua). (Value | ||
124 | ** must fit in an unsigned char.) | ||
125 | */ | ||
126 | #define MAXUPVAL UCHAR_MAX | ||
127 | |||
128 | |||
129 | /* | ||
85 | ** type for virtual-machine instructions | 130 | ** type for virtual-machine instructions |
86 | ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) | 131 | ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) |
87 | */ | 132 | */ |
@@ -95,34 +140,170 @@ typedef lu_int32 Instruction; | |||
95 | 140 | ||
96 | 141 | ||
97 | /* minimum size for the string table (must be power of 2) */ | 142 | /* minimum size for the string table (must be power of 2) */ |
98 | #ifndef MINSTRTABSIZE | 143 | #if !defined(MINSTRTABSIZE) |
99 | #define MINSTRTABSIZE 32 | 144 | #define MINSTRTABSIZE 32 |
100 | #endif | 145 | #endif |
101 | 146 | ||
102 | 147 | ||
103 | /* minimum size for string buffer */ | 148 | /* minimum size for string buffer */ |
104 | #ifndef LUA_MINBUFFER | 149 | #if !defined(LUA_MINBUFFER) |
105 | #define LUA_MINBUFFER 32 | 150 | #define LUA_MINBUFFER 32 |
106 | #endif | 151 | #endif |
107 | 152 | ||
108 | 153 | ||
109 | #ifndef lua_lock | 154 | #if !defined(lua_lock) |
110 | #define lua_lock(L) ((void) 0) | 155 | #define lua_lock(L) ((void) 0) |
111 | #define lua_unlock(L) ((void) 0) | 156 | #define lua_unlock(L) ((void) 0) |
112 | #endif | 157 | #endif |
113 | 158 | ||
114 | #ifndef luai_threadyield | 159 | #if !defined(luai_threadyield) |
115 | #define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} | 160 | #define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} |
116 | #endif | 161 | #endif |
117 | 162 | ||
118 | 163 | ||
119 | /* | 164 | /* |
165 | ** these macros allow user-specific actions on threads when you defined | ||
166 | ** LUAI_EXTRASPACE and need to do something extra when a thread is | ||
167 | ** created/deleted/resumed/yielded. | ||
168 | */ | ||
169 | #if !defined(luai_userstateopen) | ||
170 | #define luai_userstateopen(L) ((void)L) | ||
171 | #endif | ||
172 | |||
173 | #if !defined(luai_userstateclose) | ||
174 | #define luai_userstateclose(L) ((void)L) | ||
175 | #endif | ||
176 | |||
177 | #if !defined(luai_userstatethread) | ||
178 | #define luai_userstatethread(L,L1) ((void)L) | ||
179 | #endif | ||
180 | |||
181 | #if !defined(luai_userstatefree) | ||
182 | #define luai_userstatefree(L,L1) ((void)L) | ||
183 | #endif | ||
184 | |||
185 | #if !defined(luai_userstateresume) | ||
186 | #define luai_userstateresume(L,n) ((void)L) | ||
187 | #endif | ||
188 | |||
189 | #if !defined(luai_userstateyield) | ||
190 | #define luai_userstateyield(L,n) ((void)L) | ||
191 | #endif | ||
192 | |||
193 | /* | ||
194 | ** lua_number2int is a macro to convert lua_Number to int. | ||
195 | ** lua_number2integer is a macro to convert lua_Number to lua_Integer. | ||
196 | ** lua_number2unsigned is a macro to convert a lua_Number to a lua_Unsigned. | ||
197 | ** lua_unsigned2number is a macro to convert a lua_Unsigned to a lua_Number. | ||
198 | ** luai_hashnum is a macro to hash a lua_Number value into an integer. | ||
199 | ** The hash must be deterministic and give reasonable values for | ||
200 | ** both small and large values (outside the range of integers). | ||
201 | */ | ||
202 | |||
203 | #if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ | ||
204 | /* trick with Microsoft assembler for X86 */ | ||
205 | |||
206 | #define lua_number2int(i,n) __asm {__asm fld n __asm fistp i} | ||
207 | #define lua_number2integer(i,n) lua_number2int(i, n) | ||
208 | #define lua_number2unsigned(i,n) \ | ||
209 | {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} | ||
210 | |||
211 | |||
212 | #elif defined(LUA_IEEE754TRICK) /* }{ */ | ||
213 | /* the next trick should work on any machine using IEEE754 with | ||
214 | a 32-bit int type */ | ||
215 | |||
216 | union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; | ||
217 | |||
218 | #if !defined(LUA_IEEEENDIAN) /* { */ | ||
219 | #define LUAI_EXTRAIEEE \ | ||
220 | static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; | ||
221 | #define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) | ||
222 | #else | ||
223 | #define LUA_IEEEENDIANLOC LUA_IEEEENDIAN | ||
224 | #define LUAI_EXTRAIEEE /* empty */ | ||
225 | #endif /* } */ | ||
226 | |||
227 | #define lua_number2int32(i,n,t) \ | ||
228 | { LUAI_EXTRAIEEE \ | ||
229 | volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ | ||
230 | (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; } | ||
231 | |||
232 | #define luai_hashnum(i,n) \ | ||
233 | { volatile union luai_Cast u; u.l_d = (n) + 1.0; /* avoid -0 */ \ | ||
234 | (i) = u.l_p[0]; (i) += u.l_p[1]; } /* add double bits for his hash */ | ||
235 | |||
236 | #define lua_number2int(i,n) lua_number2int32(i, n, int) | ||
237 | #define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) | ||
238 | |||
239 | /* the trick can be expanded to lua_Integer when it is a 32-bit value */ | ||
240 | #if defined(LUA_IEEELL) | ||
241 | #define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer) | ||
242 | #endif | ||
243 | |||
244 | #endif /* } */ | ||
245 | |||
246 | |||
247 | /* the following definitions always work, but may be slow */ | ||
248 | |||
249 | #if !defined(lua_number2int) | ||
250 | #define lua_number2int(i,n) ((i)=(int)(n)) | ||
251 | #endif | ||
252 | |||
253 | #if !defined(lua_number2integer) | ||
254 | #define lua_number2integer(i,n) ((i)=(lua_Integer)(n)) | ||
255 | #endif | ||
256 | |||
257 | #if !defined(lua_number2unsigned) /* { */ | ||
258 | /* the following definition assures proper modulo behavior */ | ||
259 | #if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT) | ||
260 | #include <math.h> | ||
261 | #define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) | ||
262 | #define lua_number2unsigned(i,n) \ | ||
263 | ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) | ||
264 | #else | ||
265 | #define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) | ||
266 | #endif | ||
267 | #endif /* } */ | ||
268 | |||
269 | |||
270 | #if !defined(lua_unsigned2number) | ||
271 | /* on several machines, coercion from unsigned to double is slow, | ||
272 | so it may be worth to avoid */ | ||
273 | #define lua_unsigned2number(u) \ | ||
274 | (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u)) | ||
275 | #endif | ||
276 | |||
277 | |||
278 | |||
279 | #if defined(ltable_c) && !defined(luai_hashnum) | ||
280 | |||
281 | #include <float.h> | ||
282 | #include <math.h> | ||
283 | |||
284 | #define luai_hashnum(i,n) { int e; \ | ||
285 | n = l_mathop(frexp)(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \ | ||
286 | lua_number2int(i, n); i += e; } | ||
287 | |||
288 | #endif | ||
289 | |||
290 | |||
291 | |||
292 | /* | ||
120 | ** macro to control inclusion of some hard tests on stack reallocation | 293 | ** macro to control inclusion of some hard tests on stack reallocation |
121 | */ | 294 | */ |
122 | #ifndef HARDSTACKTESTS | 295 | #if !defined(HARDSTACKTESTS) |
123 | #define condhardstacktests(x) ((void)0) | 296 | #define condmovestack(L) ((void)0) |
297 | #else | ||
298 | /* realloc stack keeping its size */ | ||
299 | #define condmovestack(L) luaD_reallocstack((L), (L)->stacksize) | ||
300 | #endif | ||
301 | |||
302 | #if !defined(HARDMEMTESTS) | ||
303 | #define condchangemem(L) condmovestack(L) | ||
124 | #else | 304 | #else |
125 | #define condhardstacktests(x) x | 305 | #define condchangemem(L) \ |
306 | ((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1))) | ||
126 | #endif | 307 | #endif |
127 | 308 | ||
128 | #endif | 309 | #endif |
diff --git a/apps/plugins/lua/lmathlib.c b/apps/plugins/lua/lmathlib.c index 99a104050c..0b288e6a12 100644 --- a/apps/plugins/lua/lmathlib.c +++ b/apps/plugins/lua/lmathlib.c | |||
@@ -1,14 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $ | 2 | ** $Id: lmathlib.c,v 1.83.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Standard mathematical library | 3 | ** Standard mathematical library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
6 | 6 | ||
7 | 7 | ||
8 | #if 0 | ||
9 | #include <stdlib.h> | 8 | #include <stdlib.h> |
10 | #include <math.h> | 9 | #include <math.h> |
11 | #endif | ||
12 | 10 | ||
13 | #define lmathlib_c | 11 | #define lmathlib_c |
14 | #define LUA_LIB | 12 | #define LUA_LIB |
@@ -20,9 +18,9 @@ | |||
20 | 18 | ||
21 | 19 | ||
22 | #undef PI | 20 | #undef PI |
23 | #define PI (3.14159265358979323846) | 21 | #define PI ((lua_Number)(3.1415926535897932384626433832795)) |
24 | #define RADIANS_PER_DEGREE (PI/180.0) | 22 | #define RADIANS_PER_DEGREE ((lua_Number)(PI/180.0)) |
25 | #define DEGREES_PER_RADIAN (180.0/PI) | 23 | #define DEGREES_PER_RADIAN ((lua_Number)180.0/PI) |
26 | 24 | ||
27 | 25 | ||
28 | static int math_abs (lua_State *L) { | 26 | static int math_abs (lua_State *L) { |
@@ -34,52 +32,53 @@ static int math_abs (lua_State *L) { | |||
34 | 32 | ||
35 | #if 0 | 33 | #if 0 |
36 | static int math_sin (lua_State *L) { | 34 | static int math_sin (lua_State *L) { |
37 | lua_pushnumber(L, sin(luaL_checknumber(L, 1))); | 35 | lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); |
38 | return 1; | 36 | return 1; |
39 | } | 37 | } |
40 | 38 | ||
41 | static int math_sinh (lua_State *L) { | 39 | static int math_sinh (lua_State *L) { |
42 | lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); | 40 | lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); |
43 | return 1; | 41 | return 1; |
44 | } | 42 | } |
45 | 43 | ||
46 | static int math_cos (lua_State *L) { | 44 | static int math_cos (lua_State *L) { |
47 | lua_pushnumber(L, cos(luaL_checknumber(L, 1))); | 45 | lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); |
48 | return 1; | 46 | return 1; |
49 | } | 47 | } |
50 | 48 | ||
51 | static int math_cosh (lua_State *L) { | 49 | static int math_cosh (lua_State *L) { |
52 | lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); | 50 | lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); |
53 | return 1; | 51 | return 1; |
54 | } | 52 | } |
55 | 53 | ||
56 | static int math_tan (lua_State *L) { | 54 | static int math_tan (lua_State *L) { |
57 | lua_pushnumber(L, tan(luaL_checknumber(L, 1))); | 55 | lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); |
58 | return 1; | 56 | return 1; |
59 | } | 57 | } |
60 | 58 | ||
61 | static int math_tanh (lua_State *L) { | 59 | static int math_tanh (lua_State *L) { |
62 | lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); | 60 | lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); |
63 | return 1; | 61 | return 1; |
64 | } | 62 | } |
65 | 63 | ||
66 | static int math_asin (lua_State *L) { | 64 | static int math_asin (lua_State *L) { |
67 | lua_pushnumber(L, asin(luaL_checknumber(L, 1))); | 65 | lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); |
68 | return 1; | 66 | return 1; |
69 | } | 67 | } |
70 | 68 | ||
71 | static int math_acos (lua_State *L) { | 69 | static int math_acos (lua_State *L) { |
72 | lua_pushnumber(L, acos(luaL_checknumber(L, 1))); | 70 | lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); |
73 | return 1; | 71 | return 1; |
74 | } | 72 | } |
75 | 73 | ||
76 | static int math_atan (lua_State *L) { | 74 | static int math_atan (lua_State *L) { |
77 | lua_pushnumber(L, atan(luaL_checknumber(L, 1))); | 75 | lua_pushnumber(L, l_mathop(atan)(luaL_checknumber(L, 1))); |
78 | return 1; | 76 | return 1; |
79 | } | 77 | } |
80 | 78 | ||
81 | static int math_atan2 (lua_State *L) { | 79 | static int math_atan2 (lua_State *L) { |
82 | lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); | 80 | lua_pushnumber(L, l_mathop(atan2)(luaL_checknumber(L, 1), |
81 | luaL_checknumber(L, 2))); | ||
83 | return 1; | 82 | return 1; |
84 | } | 83 | } |
85 | #endif | 84 | #endif |
@@ -104,35 +103,48 @@ static int math_fmod (lua_State *L) { | |||
104 | 103 | ||
105 | #if 0 | 104 | #if 0 |
106 | static int math_modf (lua_State *L) { | 105 | static int math_modf (lua_State *L) { |
107 | double ip; | 106 | lua_Number ip; |
108 | double fp = modf(luaL_checknumber(L, 1), &ip); | 107 | lua_Number fp = l_mathop(modf)(luaL_checknumber(L, 1), &ip); |
109 | lua_pushnumber(L, ip); | 108 | lua_pushnumber(L, ip); |
110 | lua_pushnumber(L, fp); | 109 | lua_pushnumber(L, fp); |
111 | return 2; | 110 | return 2; |
112 | } | 111 | } |
113 | 112 | ||
114 | static int math_sqrt (lua_State *L) { | 113 | static int math_sqrt (lua_State *L) { |
115 | lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); | 114 | lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); |
116 | return 1; | 115 | return 1; |
117 | } | 116 | } |
118 | 117 | ||
119 | static int math_pow (lua_State *L) { | 118 | static int math_pow (lua_State *L) { |
120 | lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); | 119 | lua_Number x = luaL_checknumber(L, 1); |
120 | lua_Number y = luaL_checknumber(L, 2); | ||
121 | lua_pushnumber(L, l_mathop(pow)(x, y)); | ||
121 | return 1; | 122 | return 1; |
122 | } | 123 | } |
123 | 124 | ||
124 | static int math_log (lua_State *L) { | 125 | static int math_log (lua_State *L) { |
125 | lua_pushnumber(L, log(luaL_checknumber(L, 1))); | 126 | lua_Number x = luaL_checknumber(L, 1); |
127 | lua_Number res; | ||
128 | if (lua_isnoneornil(L, 2)) | ||
129 | res = l_mathop(log)(x); | ||
130 | else { | ||
131 | lua_Number base = luaL_checknumber(L, 2); | ||
132 | if (base == (lua_Number)10.0) res = l_mathop(log10)(x); | ||
133 | else res = l_mathop(log)(x)/l_mathop(log)(base); | ||
134 | } | ||
135 | lua_pushnumber(L, res); | ||
126 | return 1; | 136 | return 1; |
127 | } | 137 | } |
128 | 138 | ||
139 | #if defined(LUA_COMPAT_LOG10) | ||
129 | static int math_log10 (lua_State *L) { | 140 | static int math_log10 (lua_State *L) { |
130 | lua_pushnumber(L, log10(luaL_checknumber(L, 1))); | 141 | lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); |
131 | return 1; | 142 | return 1; |
132 | } | 143 | } |
144 | #endif | ||
133 | 145 | ||
134 | static int math_exp (lua_State *L) { | 146 | static int math_exp (lua_State *L) { |
135 | lua_pushnumber(L, exp(luaL_checknumber(L, 1))); | 147 | lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); |
136 | return 1; | 148 | return 1; |
137 | } | 149 | } |
138 | #endif | 150 | #endif |
@@ -140,6 +152,7 @@ static int math_deg (lua_State *L) { | |||
140 | lua_pushnumber(L, luaL_checknumber(L, 1)*DEGREES_PER_RADIAN); | 152 | lua_pushnumber(L, luaL_checknumber(L, 1)*DEGREES_PER_RADIAN); |
141 | return 1; | 153 | return 1; |
142 | } | 154 | } |
155 | |||
143 | static int math_rad (lua_State *L) { | 156 | static int math_rad (lua_State *L) { |
144 | lua_pushnumber(L, (luaL_checknumber(L, 1)*100)/(DEGREES_PER_RADIAN*100)); | 157 | lua_pushnumber(L, (luaL_checknumber(L, 1)*100)/(DEGREES_PER_RADIAN*100)); |
145 | return 1; | 158 | return 1; |
@@ -148,13 +161,15 @@ static int math_rad (lua_State *L) { | |||
148 | #if 0 | 161 | #if 0 |
149 | static int math_frexp (lua_State *L) { | 162 | static int math_frexp (lua_State *L) { |
150 | int e; | 163 | int e; |
151 | lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); | 164 | lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); |
152 | lua_pushinteger(L, e); | 165 | lua_pushinteger(L, e); |
153 | return 2; | 166 | return 2; |
154 | } | 167 | } |
155 | 168 | ||
156 | static int math_ldexp (lua_State *L) { | 169 | static int math_ldexp (lua_State *L) { |
157 | lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); | 170 | lua_Number x = luaL_checknumber(L, 1); |
171 | int ep = luaL_checkint(L, 2); | ||
172 | lua_pushnumber(L, l_mathop(ldexp)(x, ep)); | ||
158 | return 1; | 173 | return 1; |
159 | } | 174 | } |
160 | #endif | 175 | #endif |
@@ -197,16 +212,16 @@ static int math_random (lua_State *L) { | |||
197 | break; | 212 | break; |
198 | } | 213 | } |
199 | case 1: { /* only upper limit */ | 214 | case 1: { /* only upper limit */ |
200 | int u = luaL_checkint(L, 1); | 215 | lua_Number u = luaL_checknumber(L, 1); |
201 | luaL_argcheck(L, 1<=u, 1, "interval is empty"); | 216 | luaL_argcheck(L, 1 <= u, 1, "interval is empty"); |
202 | lua_pushnumber(L, r%u+1); /* int between 1 and `u' */ | 217 | lua_pushnumber(L, r%u+1); /* int between 1 and `u' */ |
203 | break; | 218 | break; |
204 | } | 219 | } |
205 | case 2: { /* lower and upper limits */ | 220 | case 2: { /* lower and upper limits */ |
206 | int l = luaL_checkint(L, 1); | 221 | lua_Number l = luaL_checknumber(L, 1); |
207 | int u = luaL_checkint(L, 2); | 222 | lua_Number u = luaL_checknumber(L, 2); |
208 | luaL_argcheck(L, l<=u, 2, "interval is empty"); | 223 | luaL_argcheck(L, l <= u, 2, "interval is empty"); |
209 | lua_pushnumber(L, r%(u-l+1)+l); /* int between `l' and `u' */ | 224 | lua_pushnumber(L, r%(u-l+1)+l); /* [l, u] */ |
210 | break; | 225 | break; |
211 | } | 226 | } |
212 | default: return luaL_error(L, "wrong number of arguments"); | 227 | default: return luaL_error(L, "wrong number of arguments"); |
@@ -216,7 +231,7 @@ static int math_random (lua_State *L) { | |||
216 | 231 | ||
217 | 232 | ||
218 | static int math_randomseed (lua_State *L) { | 233 | static int math_randomseed (lua_State *L) { |
219 | rb->srand(luaL_checkint(L, 1)); | 234 | rb->srand(luaL_checkunsigned(L, 1)); |
220 | return 0; | 235 | return 0; |
221 | } | 236 | } |
222 | 237 | ||
@@ -243,7 +258,9 @@ static const luaL_Reg mathlib[] = { | |||
243 | #if 0 | 258 | #if 0 |
244 | {"frexp", math_frexp}, | 259 | {"frexp", math_frexp}, |
245 | {"ldexp", math_ldexp}, | 260 | {"ldexp", math_ldexp}, |
261 | #if defined(LUA_COMPAT_LOG10) | ||
246 | {"log10", math_log10}, | 262 | {"log10", math_log10}, |
263 | #endif | ||
247 | {"log", math_log}, | 264 | {"log", math_log}, |
248 | #endif | 265 | #endif |
249 | {"max", math_max}, | 266 | {"max", math_max}, |
@@ -259,7 +276,7 @@ static const luaL_Reg mathlib[] = { | |||
259 | {"sinh", math_sinh}, | 276 | {"sinh", math_sinh}, |
260 | {"sin", math_sin}, | 277 | {"sin", math_sin}, |
261 | {"sqrt", math_sqrt}, | 278 | {"sqrt", math_sqrt}, |
262 | {"tanh", math_tanh}, | 279 | {"tanh", math_tanh}, |
263 | {"tan", math_tan}, | 280 | {"tan", math_tan}, |
264 | #endif | 281 | #endif |
265 | {NULL, NULL} | 282 | {NULL, NULL} |
@@ -269,17 +286,14 @@ static const luaL_Reg mathlib[] = { | |||
269 | /* | 286 | /* |
270 | ** Open math library | 287 | ** Open math library |
271 | */ | 288 | */ |
272 | LUALIB_API int luaopen_math (lua_State *L) { | 289 | LUAMOD_API int luaopen_math (lua_State *L) { |
273 | luaL_register(L, LUA_MATHLIBNAME, mathlib); | 290 | luaL_newlib(L, mathlib); |
274 | #if 0 /* No use in adding floating point constants when there's no FP */ | 291 | #if 0 /* No use in adding floating point constants when there's no FP */ |
275 | lua_pushnumber(L, PI); | 292 | lua_pushnumber(L, PI); |
276 | lua_setfield(L, -2, "pi"); | 293 | lua_setfield(L, -2, "pi"); |
277 | lua_pushnumber(L, HUGE_VAL); | 294 | lua_pushnumber(L, HUGE_VAL); |
278 | lua_setfield(L, -2, "huge"); | 295 | lua_setfield(L, -2, "huge"); |
279 | #if defined(LUA_COMPAT_MOD) | ||
280 | lua_getfield(L, -1, "fmod"); | ||
281 | lua_setfield(L, -2, "mod"); | ||
282 | #endif | ||
283 | #endif | 296 | #endif |
284 | return 1; | 297 | return 1; |
285 | } | 298 | } |
299 | |||
diff --git a/apps/plugins/lua/lmem.c b/apps/plugins/lua/lmem.c index ae7d8c965f..ee343e3e03 100644 --- a/apps/plugins/lua/lmem.c +++ b/apps/plugins/lua/lmem.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ | 2 | ** $Id: lmem.c,v 1.84.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Interface to Memory Manager | 3 | ** Interface to Memory Manager |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include "ldebug.h" | 15 | #include "ldebug.h" |
16 | #include "ldo.h" | 16 | #include "ldo.h" |
17 | #include "lgc.h" | ||
17 | #include "lmem.h" | 18 | #include "lmem.h" |
18 | #include "lobject.h" | 19 | #include "lobject.h" |
19 | #include "lstate.h" | 20 | #include "lstate.h" |
@@ -25,12 +26,11 @@ | |||
25 | ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); | 26 | ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); |
26 | ** (`osize' is the old size, `nsize' is the new size) | 27 | ** (`osize' is the old size, `nsize' is the new size) |
27 | ** | 28 | ** |
28 | ** Lua ensures that (ptr == NULL) iff (osize == 0). | 29 | ** * frealloc(ud, NULL, x, s) creates a new block of size `s' (no |
29 | ** | 30 | ** matter 'x'). |
30 | ** * frealloc(ud, NULL, 0, x) creates a new block of size `x' | ||
31 | ** | 31 | ** |
32 | ** * frealloc(ud, p, x, 0) frees the block `p' | 32 | ** * frealloc(ud, p, x, 0) frees the block `p' |
33 | ** (in this specific case, frealloc must return NULL). | 33 | ** (in this specific case, frealloc must return NULL); |
34 | ** particularly, frealloc(ud, NULL, 0, 0) does nothing | 34 | ** particularly, frealloc(ud, NULL, 0, 0) does nothing |
35 | ** (which is equivalent to free(NULL) in ANSI C) | 35 | ** (which is equivalent to free(NULL) in ANSI C) |
36 | ** | 36 | ** |
@@ -44,12 +44,12 @@ | |||
44 | 44 | ||
45 | 45 | ||
46 | void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, | 46 | void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, |
47 | int limit, const char *errormsg) { | 47 | int limit, const char *what) { |
48 | void *newblock; | 48 | void *newblock; |
49 | int newsize; | 49 | int newsize; |
50 | if (*size >= limit/2) { /* cannot double it? */ | 50 | if (*size >= limit/2) { /* cannot double it? */ |
51 | if (*size >= limit) /* cannot grow even a little? */ | 51 | if (*size >= limit) /* cannot grow even a little? */ |
52 | luaG_runerror(L, errormsg); | 52 | luaG_runerror(L, "too many %s (limit is %d)", what, limit); |
53 | newsize = limit; /* still have at least one free place */ | 53 | newsize = limit; /* still have at least one free place */ |
54 | } | 54 | } |
55 | else { | 55 | else { |
@@ -63,9 +63,8 @@ void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, | |||
63 | } | 63 | } |
64 | 64 | ||
65 | 65 | ||
66 | void *luaM_toobig (lua_State *L) { | 66 | l_noret luaM_toobig (lua_State *L) { |
67 | luaG_runerror(L, "memory allocation error: block too big"); | 67 | luaG_runerror(L, "memory allocation error: block too big"); |
68 | return NULL; /* to avoid warnings */ | ||
69 | } | 68 | } |
70 | 69 | ||
71 | 70 | ||
@@ -74,13 +73,27 @@ void *luaM_toobig (lua_State *L) { | |||
74 | ** generic allocation routine. | 73 | ** generic allocation routine. |
75 | */ | 74 | */ |
76 | void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { | 75 | void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { |
76 | void *newblock; | ||
77 | global_State *g = G(L); | 77 | global_State *g = G(L); |
78 | lua_assert((osize == 0) == (block == NULL)); | 78 | size_t realosize = (block) ? osize : 0; |
79 | block = (*g->frealloc)(g->ud, block, osize, nsize); | 79 | lua_assert((realosize == 0) == (block == NULL)); |
80 | if (block == NULL && nsize > 0) | 80 | #if defined(HARDMEMTESTS) |
81 | luaD_throw(L, LUA_ERRMEM); | 81 | if (nsize > realosize && g->gcrunning) |
82 | lua_assert((nsize == 0) == (block == NULL)); | 82 | luaC_fullgc(L, 1); /* force a GC whenever possible */ |
83 | g->totalbytes = (g->totalbytes - osize) + nsize; | 83 | #endif |
84 | return block; | 84 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); |
85 | if (newblock == NULL && nsize > 0) { | ||
86 | api_check(L, nsize > realosize, | ||
87 | "realloc cannot fail when shrinking a block"); | ||
88 | if (g->gcrunning) { | ||
89 | luaC_fullgc(L, 1); /* try to free some memory... */ | ||
90 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ | ||
91 | } | ||
92 | if (newblock == NULL) | ||
93 | luaD_throw(L, LUA_ERRMEM); | ||
94 | } | ||
95 | lua_assert((nsize == 0) == (newblock == NULL)); | ||
96 | g->GCdebt = (g->GCdebt + nsize) - realosize; | ||
97 | return newblock; | ||
85 | } | 98 | } |
86 | 99 | ||
diff --git a/apps/plugins/lua/lmem.h b/apps/plugins/lua/lmem.h index 97a888c7f8..bd4f4e0726 100644 --- a/apps/plugins/lua/lmem.h +++ b/apps/plugins/lua/lmem.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lmem.h,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Interface to Memory Manager | 3 | ** Interface to Memory Manager |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -13,23 +13,30 @@ | |||
13 | #include "llimits.h" | 13 | #include "llimits.h" |
14 | #include "lua.h" | 14 | #include "lua.h" |
15 | 15 | ||
16 | #define MEMERRMSG "not enough memory" | ||
17 | |||
18 | 16 | ||
17 | /* | ||
18 | ** This macro avoids the runtime division MAX_SIZET/(e), as 'e' is | ||
19 | ** always constant. | ||
20 | ** The macro is somewhat complex to avoid warnings: | ||
21 | ** +1 avoids warnings of "comparison has constant result"; | ||
22 | ** cast to 'void' avoids warnings of "value unused". | ||
23 | */ | ||
19 | #define luaM_reallocv(L,b,on,n,e) \ | 24 | #define luaM_reallocv(L,b,on,n,e) \ |
20 | ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ | 25 | (cast(void, \ |
21 | luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ | 26 | (cast(size_t, (n)+1) > MAX_SIZET/(e)) ? (luaM_toobig(L), 0) : 0), \ |
22 | luaM_toobig(L)) | 27 | luaM_realloc_(L, (b), (on)*(e), (n)*(e))) |
23 | 28 | ||
24 | #define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) | 29 | #define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) |
25 | #define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) | 30 | #define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) |
26 | #define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) | 31 | #define luaM_freearray(L, b, n) luaM_reallocv(L, (b), n, 0, sizeof((b)[0])) |
27 | 32 | ||
28 | #define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) | 33 | #define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) |
29 | #define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) | 34 | #define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) |
30 | #define luaM_newvector(L,n,t) \ | 35 | #define luaM_newvector(L,n,t) \ |
31 | cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) | 36 | cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) |
32 | 37 | ||
38 | #define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) | ||
39 | |||
33 | #define luaM_growvector(L,v,nelems,size,t,limit,e) \ | 40 | #define luaM_growvector(L,v,nelems,size,t,limit,e) \ |
34 | if ((nelems)+1 > (size)) \ | 41 | if ((nelems)+1 > (size)) \ |
35 | ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) | 42 | ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) |
@@ -37,13 +44,14 @@ | |||
37 | #define luaM_reallocvector(L, v,oldn,n,t) \ | 44 | #define luaM_reallocvector(L, v,oldn,n,t) \ |
38 | ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) | 45 | ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) |
39 | 46 | ||
47 | LUAI_FUNC l_noret luaM_toobig (lua_State *L); | ||
40 | 48 | ||
49 | /* not to be called directly */ | ||
41 | LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, | 50 | LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, |
42 | size_t size); | 51 | size_t size); |
43 | LUAI_FUNC void *luaM_toobig (lua_State *L); | ||
44 | LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, | 52 | LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, |
45 | size_t size_elem, int limit, | 53 | size_t size_elem, int limit, |
46 | const char *errormsg); | 54 | const char *what); |
47 | 55 | ||
48 | #endif | 56 | #endif |
49 | 57 | ||
diff --git a/apps/plugins/lua/loadlib.c b/apps/plugins/lua/loadlib.c index 1cc7ebd7db..f5a63386b5 100644 --- a/apps/plugins/lua/loadlib.c +++ b/apps/plugins/lua/loadlib.c | |||
@@ -1,14 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: loadlib.c,v 1.52.1.3 2008/08/06 13:29:28 roberto Exp $ | 2 | ** $Id: loadlib.c,v 1.111.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Dynamic library loader for Lua | 3 | ** Dynamic library loader for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | ** | 5 | ** |
6 | ** This module contains an implementation of loadlib for Unix systems | 6 | ** This module contains an implementation of loadlib for Unix systems |
7 | ** that have dlfcn, an implementation for Darwin (Mac OS X), an | 7 | ** that have dlfcn, an implementation for Windows, and a stub for other |
8 | ** implementation for Windows, and a stub for other systems. | 8 | ** systems. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | 11 | ||
12 | /* | ||
13 | ** if needed, includes windows header before everything else | ||
14 | */ | ||
15 | #if defined(_WIN32) | ||
16 | #include <windows.h> | ||
17 | #endif | ||
18 | |||
19 | |||
12 | #include <stdlib.h> | 20 | #include <stdlib.h> |
13 | #include <string.h> | 21 | #include <string.h> |
14 | 22 | ||
@@ -20,10 +28,296 @@ | |||
20 | 28 | ||
21 | #include "lauxlib.h" | 29 | #include "lauxlib.h" |
22 | #include "lualib.h" | 30 | #include "lualib.h" |
23 | #include "rocklib.h" | ||
24 | 31 | ||
25 | 32 | ||
26 | #define setprogdir(L) ((void)0) | 33 | /* |
34 | ** LUA_PATH and LUA_CPATH are the names of the environment | ||
35 | ** variables that Lua check to set its paths. | ||
36 | */ | ||
37 | #if !defined(LUA_PATH) | ||
38 | #define LUA_PATH "LUA_PATH" | ||
39 | #endif | ||
40 | |||
41 | #if !defined(LUA_CPATH) | ||
42 | #define LUA_CPATH "LUA_CPATH" | ||
43 | #endif | ||
44 | |||
45 | #define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR | ||
46 | |||
47 | #define LUA_PATHVERSION LUA_PATH LUA_PATHSUFFIX | ||
48 | #define LUA_CPATHVERSION LUA_CPATH LUA_PATHSUFFIX | ||
49 | |||
50 | /* | ||
51 | ** LUA_PATH_SEP is the character that separates templates in a path. | ||
52 | ** LUA_PATH_MARK is the string that marks the substitution points in a | ||
53 | ** template. | ||
54 | ** LUA_EXEC_DIR in a Windows path is replaced by the executable's | ||
55 | ** directory. | ||
56 | ** LUA_IGMARK is a mark to ignore all before it when building the | ||
57 | ** luaopen_ function name. | ||
58 | */ | ||
59 | #if !defined (LUA_PATH_SEP) | ||
60 | #define LUA_PATH_SEP ";" | ||
61 | #endif | ||
62 | #if !defined (LUA_PATH_MARK) | ||
63 | #define LUA_PATH_MARK "?" | ||
64 | #endif | ||
65 | #if !defined (LUA_EXEC_DIR) | ||
66 | #define LUA_EXEC_DIR "!" | ||
67 | #endif | ||
68 | #if !defined (LUA_IGMARK) | ||
69 | #define LUA_IGMARK "-" | ||
70 | #endif | ||
71 | |||
72 | |||
73 | /* | ||
74 | ** LUA_CSUBSEP is the character that replaces dots in submodule names | ||
75 | ** when searching for a C loader. | ||
76 | ** LUA_LSUBSEP is the character that replaces dots in submodule names | ||
77 | ** when searching for a Lua loader. | ||
78 | */ | ||
79 | #if !defined(LUA_CSUBSEP) | ||
80 | #define LUA_CSUBSEP LUA_DIRSEP | ||
81 | #endif | ||
82 | |||
83 | #if !defined(LUA_LSUBSEP) | ||
84 | #define LUA_LSUBSEP LUA_DIRSEP | ||
85 | #endif | ||
86 | |||
87 | |||
88 | /* prefix for open functions in C libraries */ | ||
89 | #define LUA_POF "luaopen_" | ||
90 | |||
91 | /* separator for open functions in C libraries */ | ||
92 | #define LUA_OFSEP "_" | ||
93 | |||
94 | |||
95 | /* table (in the registry) that keeps handles for all loaded C libraries */ | ||
96 | #define CLIBS "_CLIBS" | ||
97 | |||
98 | #define LIB_FAIL "open" | ||
99 | |||
100 | |||
101 | /* error codes for ll_loadfunc */ | ||
102 | #define ERRLIB 1 | ||
103 | #define ERRFUNC 2 | ||
104 | |||
105 | #define setprogdir(L) ((void)0) | ||
106 | |||
107 | |||
108 | /* | ||
109 | ** system-dependent functions | ||
110 | */ | ||
111 | static void ll_unloadlib (void *lib); | ||
112 | static void *ll_load (lua_State *L, const char *path, int seeglb); | ||
113 | static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); | ||
114 | |||
115 | |||
116 | |||
117 | #if defined(LUA_USE_DLOPEN) | ||
118 | /* | ||
119 | ** {======================================================================== | ||
120 | ** This is an implementation of loadlib based on the dlfcn interface. | ||
121 | ** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, | ||
122 | ** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least | ||
123 | ** as an emulation layer on top of native functions. | ||
124 | ** ========================================================================= | ||
125 | */ | ||
126 | |||
127 | #include <dlfcn.h> | ||
128 | |||
129 | static void ll_unloadlib (void *lib) { | ||
130 | dlclose(lib); | ||
131 | } | ||
132 | |||
133 | |||
134 | static void *ll_load (lua_State *L, const char *path, int seeglb) { | ||
135 | void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); | ||
136 | if (lib == NULL) lua_pushstring(L, dlerror()); | ||
137 | return lib; | ||
138 | } | ||
139 | |||
140 | |||
141 | static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { | ||
142 | lua_CFunction f = (lua_CFunction)dlsym(lib, sym); | ||
143 | if (f == NULL) lua_pushstring(L, dlerror()); | ||
144 | return f; | ||
145 | } | ||
146 | |||
147 | /* }====================================================== */ | ||
148 | |||
149 | |||
150 | |||
151 | #elif defined(LUA_DL_DLL) | ||
152 | /* | ||
153 | ** {====================================================================== | ||
154 | ** This is an implementation of loadlib for Windows using native functions. | ||
155 | ** ======================================================================= | ||
156 | */ | ||
157 | |||
158 | #undef setprogdir | ||
159 | |||
160 | /* | ||
161 | ** optional flags for LoadLibraryEx | ||
162 | */ | ||
163 | #if !defined(LUA_LLE_FLAGS) | ||
164 | #define LUA_LLE_FLAGS 0 | ||
165 | #endif | ||
166 | |||
167 | |||
168 | static void setprogdir (lua_State *L) { | ||
169 | char buff[MAX_PATH + 1]; | ||
170 | char *lb; | ||
171 | DWORD nsize = sizeof(buff)/sizeof(char); | ||
172 | DWORD n = GetModuleFileNameA(NULL, buff, nsize); | ||
173 | if (n == 0 || n == nsize || (lb = rb->strrchr(buff, '\\')) == NULL) | ||
174 | luaL_error(L, "unable to get ModuleFileName"); | ||
175 | else { | ||
176 | *lb = '\0'; | ||
177 | luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); | ||
178 | lua_remove(L, -2); /* remove original string */ | ||
179 | } | ||
180 | } | ||
181 | |||
182 | |||
183 | static void pusherror (lua_State *L) { | ||
184 | int error = GetLastError(); | ||
185 | char buffer[128]; | ||
186 | if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, | ||
187 | NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL)) | ||
188 | lua_pushstring(L, buffer); | ||
189 | else | ||
190 | lua_pushfstring(L, "system error %d\n", error); | ||
191 | } | ||
192 | |||
193 | static void ll_unloadlib (void *lib) { | ||
194 | FreeLibrary((HMODULE)lib); | ||
195 | } | ||
196 | |||
197 | |||
198 | static void *ll_load (lua_State *L, const char *path, int seeglb) { | ||
199 | HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); | ||
200 | (void)(seeglb); /* not used: symbols are 'global' by default */ | ||
201 | if (lib == NULL) pusherror(L); | ||
202 | return lib; | ||
203 | } | ||
204 | |||
205 | |||
206 | static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { | ||
207 | lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); | ||
208 | if (f == NULL) pusherror(L); | ||
209 | return f; | ||
210 | } | ||
211 | |||
212 | /* }====================================================== */ | ||
213 | |||
214 | |||
215 | #else | ||
216 | /* | ||
217 | ** {====================================================== | ||
218 | ** Fallback for other systems | ||
219 | ** ======================================================= | ||
220 | */ | ||
221 | |||
222 | #undef LIB_FAIL | ||
223 | #define LIB_FAIL "absent" | ||
224 | |||
225 | |||
226 | #define DLMSG "dynamic libraries not enabled; check your Lua installation" | ||
227 | |||
228 | |||
229 | static void ll_unloadlib (void *lib) { | ||
230 | (void)(lib); /* not used */ | ||
231 | } | ||
232 | |||
233 | |||
234 | static void *ll_load (lua_State *L, const char *path, int seeglb) { | ||
235 | (void)(path); (void)(seeglb); /* not used */ | ||
236 | lua_pushliteral(L, DLMSG); | ||
237 | return NULL; | ||
238 | } | ||
239 | |||
240 | |||
241 | static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { | ||
242 | (void)(lib); (void)(sym); /* not used */ | ||
243 | lua_pushliteral(L, DLMSG); | ||
244 | return NULL; | ||
245 | } | ||
246 | |||
247 | /* }====================================================== */ | ||
248 | #endif | ||
249 | |||
250 | |||
251 | static void *ll_checkclib (lua_State *L, const char *path) { | ||
252 | void *plib; | ||
253 | lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); | ||
254 | lua_getfield(L, -1, path); | ||
255 | plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ | ||
256 | lua_pop(L, 2); /* pop CLIBS table and 'plib' */ | ||
257 | return plib; | ||
258 | } | ||
259 | |||
260 | |||
261 | static void ll_addtoclib (lua_State *L, const char *path, void *plib) { | ||
262 | lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); | ||
263 | lua_pushlightuserdata(L, plib); | ||
264 | lua_pushvalue(L, -1); | ||
265 | lua_setfield(L, -3, path); /* CLIBS[path] = plib */ | ||
266 | lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ | ||
267 | lua_pop(L, 1); /* pop CLIBS table */ | ||
268 | } | ||
269 | |||
270 | |||
271 | /* | ||
272 | ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib | ||
273 | ** handles in list CLIBS | ||
274 | */ | ||
275 | static int gctm (lua_State *L) { | ||
276 | int n = luaL_len(L, 1); | ||
277 | for (; n >= 1; n--) { /* for each handle, in reverse order */ | ||
278 | lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ | ||
279 | ll_unloadlib(lua_touserdata(L, -1)); | ||
280 | lua_pop(L, 1); /* pop handle */ | ||
281 | } | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | |||
286 | static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { | ||
287 | void *reg = ll_checkclib(L, path); /* check loaded C libraries */ | ||
288 | if (reg == NULL) { /* must load library? */ | ||
289 | reg = ll_load(L, path, *sym == '*'); | ||
290 | if (reg == NULL) return ERRLIB; /* unable to load library */ | ||
291 | ll_addtoclib(L, path, reg); | ||
292 | } | ||
293 | if (*sym == '*') { /* loading only library (no function)? */ | ||
294 | lua_pushboolean(L, 1); /* return 'true' */ | ||
295 | return 0; /* no errors */ | ||
296 | } | ||
297 | else { | ||
298 | lua_CFunction f = ll_sym(L, reg, sym); | ||
299 | if (f == NULL) | ||
300 | return ERRFUNC; /* unable to find function */ | ||
301 | lua_pushcfunction(L, f); /* else create new function */ | ||
302 | return 0; /* no errors */ | ||
303 | } | ||
304 | } | ||
305 | |||
306 | |||
307 | static int ll_loadlib (lua_State *L) { | ||
308 | const char *path = luaL_checkstring(L, 1); | ||
309 | const char *init = luaL_checkstring(L, 2); | ||
310 | int stat = ll_loadfunc(L, path, init); | ||
311 | if (stat == 0) /* no errors? */ | ||
312 | return 1; /* return the loaded function */ | ||
313 | else { /* error; error message is on stack top */ | ||
314 | lua_pushnil(L); | ||
315 | lua_insert(L, -2); | ||
316 | lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); | ||
317 | return 3; /* return nil, error message, and where */ | ||
318 | } | ||
319 | } | ||
320 | |||
27 | 321 | ||
28 | 322 | ||
29 | /* | 323 | /* |
@@ -34,70 +328,143 @@ | |||
34 | 328 | ||
35 | 329 | ||
36 | static int readable (const char *filename) { | 330 | static int readable (const char *filename) { |
37 | int f = rb->open(filename, O_RDONLY); /* try to open file */ | 331 | return rb->file_exists(filename); |
38 | if (f < 0) return 0; /* open failed */ | ||
39 | rb->close(f); | ||
40 | return 1; | ||
41 | } | 332 | } |
42 | 333 | ||
43 | 334 | ||
44 | static const char *pushnexttemplate (lua_State *L, const char *path) { | 335 | static const char *pushnexttemplate (lua_State *L, const char *path) { |
45 | const char *l; | 336 | const char *l; |
46 | while (*path == *LUA_PATHSEP) path++; /* skip separators */ | 337 | while (*path == *LUA_PATH_SEP) path++; /* skip separators */ |
47 | if (*path == '\0') return NULL; /* no more templates */ | 338 | if (*path == '\0') return NULL; /* no more templates */ |
48 | l = strchr(path, *LUA_PATHSEP); /* find next separator */ | 339 | l = strchr(path, *LUA_PATH_SEP); /* find next separator */ |
49 | if (l == NULL) l = path + strlen(path); | 340 | if (l == NULL) l = path + strlen(path); |
50 | lua_pushlstring(L, path, l - path); /* template */ | 341 | lua_pushlstring(L, path, l - path); /* template */ |
51 | return l; | 342 | return l; |
52 | } | 343 | } |
53 | 344 | ||
54 | 345 | ||
55 | static const char *findfile (lua_State *L, const char *name, | 346 | static const char *searchpath (lua_State *L, const char *name, |
56 | const char *pname) { | 347 | const char *path, |
57 | const char *path, *current_path = get_current_path(L, 2); | 348 | const char *sep, |
58 | name = luaL_gsub(L, name, ".", LUA_DIRSEP); | 349 | const char *dirsep) { |
59 | lua_getfield(L, LUA_ENVIRONINDEX, pname); | 350 | luaL_Buffer msg; /* to build error message */ |
60 | path = lua_tostring(L, -1); | 351 | luaL_buffinit(L, &msg); |
61 | if (path == NULL) | 352 | if (*sep != '\0') /* non-empty separator? */ |
62 | luaL_error(L, LUA_QL("package.%s") " must be a string", pname); | 353 | name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ |
63 | lua_pushliteral(L, ""); /* error accumulator */ | ||
64 | while ((path = pushnexttemplate(L, path)) != NULL) { | 354 | while ((path = pushnexttemplate(L, path)) != NULL) { |
65 | const char *filename; | 355 | const char *filename = luaL_gsub(L, lua_tostring(L, -1), |
66 | filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); | 356 | LUA_PATH_MARK, name); |
67 | if(current_path != NULL) filename = luaL_gsub(L, filename, "$", current_path); | ||
68 | lua_remove(L, -2); /* remove path template */ | 357 | lua_remove(L, -2); /* remove path template */ |
69 | if (readable(filename)) /* does file exist and is readable? */ | 358 | if (readable(filename)) /* does file exist and is readable? */ |
70 | return filename; /* return that file name */ | 359 | return filename; /* return that file name */ |
71 | lua_pushfstring(L, "\n\tno file " LUA_QS, filename); | 360 | lua_pushfstring(L, "\n\tno file " LUA_QS, filename); |
72 | lua_remove(L, -2); /* remove file name */ | 361 | lua_remove(L, -2); /* remove file name */ |
73 | lua_concat(L, 2); /* add entry to possible error message */ | 362 | luaL_addvalue(&msg); /* concatenate error msg. entry */ |
74 | } | 363 | } |
364 | luaL_pushresult(&msg); /* create error message */ | ||
75 | return NULL; /* not found */ | 365 | return NULL; /* not found */ |
76 | } | 366 | } |
77 | 367 | ||
78 | 368 | ||
79 | static void loaderror (lua_State *L, const char *filename) { | 369 | static int ll_searchpath (lua_State *L) { |
80 | luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", | 370 | const char *f = searchpath(L, luaL_checkstring(L, 1), |
81 | lua_tostring(L, 1), filename, lua_tostring(L, -1)); | 371 | luaL_checkstring(L, 2), |
372 | luaL_optstring(L, 3, "."), | ||
373 | luaL_optstring(L, 4, LUA_DIRSEP)); | ||
374 | if (f != NULL) return 1; | ||
375 | else { /* error message is on top of the stack */ | ||
376 | lua_pushnil(L); | ||
377 | lua_insert(L, -2); | ||
378 | return 2; /* return nil + error message */ | ||
379 | } | ||
82 | } | 380 | } |
83 | 381 | ||
84 | 382 | ||
85 | static int loader_Lua (lua_State *L) { | 383 | static const char *findfile (lua_State *L, const char *name, |
384 | const char *pname, | ||
385 | const char *dirsep) { | ||
386 | const char *path; | ||
387 | lua_getfield(L, lua_upvalueindex(1), pname); | ||
388 | path = lua_tostring(L, -1); | ||
389 | if (path == NULL) | ||
390 | luaL_error(L, LUA_QL("package.%s") " must be a string", pname); | ||
391 | return searchpath(L, name, path, ".", dirsep); | ||
392 | } | ||
393 | |||
394 | |||
395 | static int checkload (lua_State *L, int stat, const char *filename) { | ||
396 | if (stat) { /* module loaded successfully? */ | ||
397 | lua_pushstring(L, filename); /* will be 2nd argument to module */ | ||
398 | return 2; /* return open function and file name */ | ||
399 | } | ||
400 | else | ||
401 | return luaL_error(L, "error loading module " LUA_QS | ||
402 | " from file " LUA_QS ":\n\t%s", | ||
403 | lua_tostring(L, 1), filename, lua_tostring(L, -1)); | ||
404 | } | ||
405 | |||
406 | |||
407 | static int searcher_Lua (lua_State *L) { | ||
86 | const char *filename; | 408 | const char *filename; |
87 | const char *name = luaL_checkstring(L, 1); | 409 | const char *name = luaL_checkstring(L, 1); |
88 | filename = findfile(L, name, "path"); | 410 | filename = findfile(L, name, "path", LUA_LSUBSEP); |
89 | if (filename == NULL) return 1; /* library not found in this path */ | 411 | if (filename == NULL) return 1; /* module not found in this path */ |
90 | if (luaL_loadfile(L, filename) != 0) | 412 | return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); |
91 | loaderror(L, filename); | 413 | } |
92 | return 1; /* library loaded successfully */ | 414 | |
415 | |||
416 | static int loadfunc (lua_State *L, const char *filename, const char *modname) { | ||
417 | const char *funcname; | ||
418 | const char *mark; | ||
419 | modname = luaL_gsub(L, modname, ".", LUA_OFSEP); | ||
420 | mark = strchr(modname, *LUA_IGMARK); | ||
421 | if (mark) { | ||
422 | int stat; | ||
423 | funcname = lua_pushlstring(L, modname, mark - modname); | ||
424 | funcname = lua_pushfstring(L, LUA_POF"%s", funcname); | ||
425 | stat = ll_loadfunc(L, filename, funcname); | ||
426 | if (stat != ERRFUNC) return stat; | ||
427 | modname = mark + 1; /* else go ahead and try old-style name */ | ||
428 | } | ||
429 | funcname = lua_pushfstring(L, LUA_POF"%s", modname); | ||
430 | return ll_loadfunc(L, filename, funcname); | ||
93 | } | 431 | } |
94 | 432 | ||
95 | 433 | ||
96 | static int loader_preload (lua_State *L) { | 434 | static int searcher_C (lua_State *L) { |
97 | const char *name = luaL_checkstring(L, 1); | 435 | const char *name = luaL_checkstring(L, 1); |
98 | lua_getfield(L, LUA_ENVIRONINDEX, "preload"); | 436 | const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); |
99 | if (!lua_istable(L, -1)) | 437 | if (filename == NULL) return 1; /* module not found in this path */ |
100 | luaL_error(L, LUA_QL("package.preload") " must be a table"); | 438 | return checkload(L, (loadfunc(L, filename, name) == 0), filename); |
439 | } | ||
440 | |||
441 | |||
442 | static int searcher_Croot (lua_State *L) { | ||
443 | const char *filename; | ||
444 | const char *name = luaL_checkstring(L, 1); | ||
445 | const char *p = strchr(name, '.'); | ||
446 | int stat; | ||
447 | if (p == NULL) return 0; /* is root */ | ||
448 | lua_pushlstring(L, name, p - name); | ||
449 | filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); | ||
450 | if (filename == NULL) return 1; /* root not found */ | ||
451 | if ((stat = loadfunc(L, filename, name)) != 0) { | ||
452 | if (stat != ERRFUNC) | ||
453 | return checkload(L, 0, filename); /* real error */ | ||
454 | else { /* open function not found */ | ||
455 | lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, | ||
456 | name, filename); | ||
457 | return 1; | ||
458 | } | ||
459 | } | ||
460 | lua_pushstring(L, filename); /* will be 2nd argument to module */ | ||
461 | return 2; | ||
462 | } | ||
463 | |||
464 | |||
465 | static int searcher_preload (lua_State *L) { | ||
466 | const char *name = luaL_checkstring(L, 1); | ||
467 | lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); | ||
101 | lua_getfield(L, -1, name); | 468 | lua_getfield(L, -1, name); |
102 | if (lua_isnil(L, -1)) /* not found? */ | 469 | if (lua_isnil(L, -1)) /* not found? */ |
103 | lua_pushfstring(L, "\n\tno field package.preload['%s']", name); | 470 | lua_pushfstring(L, "\n\tno field package.preload['%s']", name); |
@@ -105,48 +472,53 @@ static int loader_preload (lua_State *L) { | |||
105 | } | 472 | } |
106 | 473 | ||
107 | 474 | ||
108 | static const int sentinel_ = 0; | 475 | static void findloader (lua_State *L, const char *name) { |
109 | #define sentinel ((void *)&sentinel_) | 476 | int i; |
477 | luaL_Buffer msg; /* to build error message */ | ||
478 | luaL_buffinit(L, &msg); | ||
479 | lua_getfield(L, lua_upvalueindex(1), "searchers"); /* will be at index 3 */ | ||
480 | if (!lua_istable(L, 3)) | ||
481 | luaL_error(L, LUA_QL("package.searchers") " must be a table"); | ||
482 | /* iterate over available searchers to find a loader */ | ||
483 | for (i = 1; ; i++) { | ||
484 | lua_rawgeti(L, 3, i); /* get a searcher */ | ||
485 | if (lua_isnil(L, -1)) { /* no more searchers? */ | ||
486 | lua_pop(L, 1); /* remove nil */ | ||
487 | luaL_pushresult(&msg); /* create error message */ | ||
488 | luaL_error(L, "module " LUA_QS " not found:%s", | ||
489 | name, lua_tostring(L, -1)); | ||
490 | } | ||
491 | lua_pushstring(L, name); | ||
492 | lua_call(L, 1, 2); /* call it */ | ||
493 | if (lua_isfunction(L, -2)) /* did it find a loader? */ | ||
494 | return; /* module loader found */ | ||
495 | else if (lua_isstring(L, -2)) { /* searcher returned error message? */ | ||
496 | lua_pop(L, 1); /* remove extra return */ | ||
497 | luaL_addvalue(&msg); /* concatenate error message */ | ||
498 | } | ||
499 | else | ||
500 | lua_pop(L, 2); /* remove both returns */ | ||
501 | } | ||
502 | } | ||
110 | 503 | ||
111 | 504 | ||
112 | static int ll_require (lua_State *L) { | 505 | static int ll_require (lua_State *L) { |
113 | const char *name = luaL_checkstring(L, 1); | 506 | const char *name = luaL_checkstring(L, 1); |
114 | int i; | ||
115 | lua_settop(L, 1); /* _LOADED table will be at index 2 */ | 507 | lua_settop(L, 1); /* _LOADED table will be at index 2 */ |
116 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); | 508 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); |
117 | lua_getfield(L, 2, name); | 509 | lua_getfield(L, 2, name); /* _LOADED[name] */ |
118 | if (lua_toboolean(L, -1)) { /* is it there? */ | 510 | if (lua_toboolean(L, -1)) /* is it there? */ |
119 | if (lua_touserdata(L, -1) == sentinel) /* check loops */ | ||
120 | luaL_error(L, "loop or previous error loading module " LUA_QS, name); | ||
121 | return 1; /* package is already loaded */ | 511 | return 1; /* package is already loaded */ |
122 | } | 512 | /* else must load package */ |
123 | /* else must load it; iterate over available loaders */ | 513 | lua_pop(L, 1); /* remove 'getfield' result */ |
124 | lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); | 514 | findloader(L, name); |
125 | if (!lua_istable(L, -1)) | 515 | lua_pushstring(L, name); /* pass name as argument to module loader */ |
126 | luaL_error(L, LUA_QL("package.loaders") " must be a table"); | 516 | lua_insert(L, -2); /* name is 1st argument (before search data) */ |
127 | lua_pushliteral(L, ""); /* error message accumulator */ | 517 | lua_call(L, 2, 1); /* run loader to load module */ |
128 | for (i=1; ; i++) { | ||
129 | lua_rawgeti(L, -2, i); /* get a loader */ | ||
130 | if (lua_isnil(L, -1)) | ||
131 | luaL_error(L, "module " LUA_QS " not found:%s", | ||
132 | name, lua_tostring(L, -2)); | ||
133 | lua_pushstring(L, name); | ||
134 | lua_call(L, 1, 1); /* call it */ | ||
135 | if (lua_isfunction(L, -1)) /* did it find module? */ | ||
136 | break; /* module loaded successfully */ | ||
137 | else if (lua_isstring(L, -1)) /* loader returned error message? */ | ||
138 | lua_concat(L, 2); /* accumulate it */ | ||
139 | else | ||
140 | lua_pop(L, 1); | ||
141 | } | ||
142 | lua_pushlightuserdata(L, sentinel); | ||
143 | lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ | ||
144 | lua_pushstring(L, name); /* pass name as argument to module */ | ||
145 | lua_call(L, 1, 1); /* run loaded module */ | ||
146 | if (!lua_isnil(L, -1)) /* non-nil return? */ | 518 | if (!lua_isnil(L, -1)) /* non-nil return? */ |
147 | lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ | 519 | lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ |
148 | lua_getfield(L, 2, name); | 520 | lua_getfield(L, 2, name); |
149 | if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ | 521 | if (lua_isnil(L, -1)) { /* module did not set a value? */ |
150 | lua_pushboolean(L, 1); /* use true as result */ | 522 | lua_pushboolean(L, 1); /* use true as result */ |
151 | lua_pushvalue(L, -1); /* extra copy to be returned */ | 523 | lua_pushvalue(L, -1); /* extra copy to be returned */ |
152 | lua_setfield(L, 2, name); /* _LOADED[name] = true */ | 524 | lua_setfield(L, 2, name); /* _LOADED[name] = true */ |
@@ -163,26 +535,31 @@ static int ll_require (lua_State *L) { | |||
163 | ** 'module' function | 535 | ** 'module' function |
164 | ** ======================================================= | 536 | ** ======================================================= |
165 | */ | 537 | */ |
166 | 538 | #if defined(LUA_COMPAT_MODULE) | |
167 | 539 | ||
168 | static void setfenv (lua_State *L) { | 540 | /* |
541 | ** changes the environment variable of calling function | ||
542 | */ | ||
543 | static void set_env (lua_State *L) { | ||
169 | lua_Debug ar; | 544 | lua_Debug ar; |
170 | if (lua_getstack(L, 1, &ar) == 0 || | 545 | if (lua_getstack(L, 1, &ar) == 0 || |
171 | lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ | 546 | lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ |
172 | lua_iscfunction(L, -1)) | 547 | lua_iscfunction(L, -1)) |
173 | luaL_error(L, LUA_QL("module") " not called from a Lua function"); | 548 | luaL_error(L, LUA_QL("module") " not called from a Lua function"); |
174 | lua_pushvalue(L, -2); | 549 | lua_pushvalue(L, -2); /* copy new environment table to top */ |
175 | lua_setfenv(L, -2); | 550 | lua_setupvalue(L, -2, 1); |
176 | lua_pop(L, 1); | 551 | lua_pop(L, 1); /* remove function */ |
177 | } | 552 | } |
178 | 553 | ||
179 | 554 | ||
180 | static void dooptions (lua_State *L, int n) { | 555 | static void dooptions (lua_State *L, int n) { |
181 | int i; | 556 | int i; |
182 | for (i = 2; i <= n; i++) { | 557 | for (i = 2; i <= n; i++) { |
183 | lua_pushvalue(L, i); /* get option (a function) */ | 558 | if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ |
184 | lua_pushvalue(L, -2); /* module */ | 559 | lua_pushvalue(L, i); /* get option (a function) */ |
185 | lua_call(L, 1, 0); | 560 | lua_pushvalue(L, -2); /* module */ |
561 | lua_call(L, 1, 0); | ||
562 | } | ||
186 | } | 563 | } |
187 | } | 564 | } |
188 | 565 | ||
@@ -204,17 +581,8 @@ static void modinit (lua_State *L, const char *modname) { | |||
204 | 581 | ||
205 | static int ll_module (lua_State *L) { | 582 | static int ll_module (lua_State *L) { |
206 | const char *modname = luaL_checkstring(L, 1); | 583 | const char *modname = luaL_checkstring(L, 1); |
207 | int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ | 584 | int lastarg = lua_gettop(L); /* last parameter */ |
208 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); | 585 | luaL_pushmodule(L, modname, 1); /* get/create module table */ |
209 | lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ | ||
210 | if (!lua_istable(L, -1)) { /* not found? */ | ||
211 | lua_pop(L, 1); /* remove previous result */ | ||
212 | /* try global variable (and create one if it does not exist) */ | ||
213 | if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL) | ||
214 | return luaL_error(L, "name conflict for module " LUA_QS, modname); | ||
215 | lua_pushvalue(L, -1); | ||
216 | lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ | ||
217 | } | ||
218 | /* check whether table already has a _NAME field */ | 586 | /* check whether table already has a _NAME field */ |
219 | lua_getfield(L, -1, "_NAME"); | 587 | lua_getfield(L, -1, "_NAME"); |
220 | if (!lua_isnil(L, -1)) /* is table an initialized module? */ | 588 | if (!lua_isnil(L, -1)) /* is table an initialized module? */ |
@@ -224,9 +592,9 @@ static int ll_module (lua_State *L) { | |||
224 | modinit(L, modname); | 592 | modinit(L, modname); |
225 | } | 593 | } |
226 | lua_pushvalue(L, -1); | 594 | lua_pushvalue(L, -1); |
227 | setfenv(L); | 595 | set_env(L); |
228 | dooptions(L, loaded - 1); | 596 | dooptions(L, lastarg); |
229 | return 0; | 597 | return 1; |
230 | } | 598 | } |
231 | 599 | ||
232 | 600 | ||
@@ -237,22 +605,38 @@ static int ll_seeall (lua_State *L) { | |||
237 | lua_pushvalue(L, -1); | 605 | lua_pushvalue(L, -1); |
238 | lua_setmetatable(L, 1); | 606 | lua_setmetatable(L, 1); |
239 | } | 607 | } |
240 | lua_pushvalue(L, LUA_GLOBALSINDEX); | 608 | lua_pushglobaltable(L); |
241 | lua_setfield(L, -2, "__index"); /* mt.__index = _G */ | 609 | lua_setfield(L, -2, "__index"); /* mt.__index = _G */ |
242 | return 0; | 610 | return 0; |
243 | } | 611 | } |
244 | 612 | ||
245 | 613 | #endif | |
246 | /* }====================================================== */ | 614 | /* }====================================================== */ |
247 | 615 | ||
248 | 616 | ||
249 | 617 | ||
250 | /* auxiliary mark (for internal use) */ | 618 | /* auxiliary mark (for internal use) */ |
251 | #define AUXMARK "\1" | 619 | #define AUXMARK "\1" |
620 | |||
621 | |||
622 | /* | ||
623 | ** return registry.LUA_NOENV as a boolean | ||
624 | */ | ||
625 | #if 0 | ||
626 | static int noenv (lua_State *L) { | ||
627 | int b; | ||
628 | lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); | ||
629 | b = lua_toboolean(L, -1); | ||
630 | lua_pop(L, 1); /* remove value */ | ||
631 | return b; | ||
632 | } | ||
633 | #endif | ||
634 | |||
252 | 635 | ||
253 | static void setpath (lua_State *L, const char *fieldname, const char *envname, | 636 | static void setpath (lua_State *L, const char *fieldname, const char *envname1, |
254 | const char *def) { | 637 | const char *envname2, const char *def) { |
255 | (void)envname; | 638 | (void)envname1; |
639 | (void)envname2; | ||
256 | lua_pushstring(L, def); /* use default */ | 640 | lua_pushstring(L, def); /* use default */ |
257 | setprogdir(L); | 641 | setprogdir(L); |
258 | lua_setfield(L, -2, fieldname); | 642 | lua_setfield(L, -2, fieldname); |
@@ -260,56 +644,72 @@ static void setpath (lua_State *L, const char *fieldname, const char *envname, | |||
260 | 644 | ||
261 | 645 | ||
262 | static const luaL_Reg pk_funcs[] = { | 646 | static const luaL_Reg pk_funcs[] = { |
647 | {"loadlib", ll_loadlib}, | ||
648 | {"searchpath", ll_searchpath}, | ||
649 | #if defined(LUA_COMPAT_MODULE) | ||
263 | {"seeall", ll_seeall}, | 650 | {"seeall", ll_seeall}, |
651 | #endif | ||
264 | {NULL, NULL} | 652 | {NULL, NULL} |
265 | }; | 653 | }; |
266 | 654 | ||
267 | 655 | ||
268 | static const luaL_Reg ll_funcs[] = { | 656 | static const luaL_Reg ll_funcs[] = { |
657 | #if defined(LUA_COMPAT_MODULE) | ||
269 | {"module", ll_module}, | 658 | {"module", ll_module}, |
659 | #endif | ||
270 | {"require", ll_require}, | 660 | {"require", ll_require}, |
271 | {NULL, NULL} | 661 | {NULL, NULL} |
272 | }; | 662 | }; |
273 | 663 | ||
274 | 664 | ||
275 | static const lua_CFunction loaders[] = | 665 | static void createsearcherstable (lua_State *L) { |
276 | {loader_preload, loader_Lua, NULL}; | 666 | static const lua_CFunction searchers[] = |
667 | {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; | ||
668 | int i; | ||
669 | /* create 'searchers' table */ | ||
670 | lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); | ||
671 | /* fill it with pre-defined searchers */ | ||
672 | for (i=0; searchers[i] != NULL; i++) { | ||
673 | lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ | ||
674 | lua_pushcclosure(L, searchers[i], 1); | ||
675 | lua_rawseti(L, -2, i+1); | ||
676 | } | ||
677 | } | ||
277 | 678 | ||
278 | 679 | ||
279 | LUALIB_API int luaopen_package (lua_State *L) { | 680 | LUAMOD_API int luaopen_package (lua_State *L) { |
280 | int i; | 681 | /* create table CLIBS to keep track of loaded C libraries */ |
281 | /* create new type _LOADLIB */ | 682 | luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); |
282 | luaL_newmetatable(L, "_LOADLIB"); | 683 | lua_createtable(L, 0, 1); /* metatable for CLIBS */ |
684 | lua_pushcfunction(L, gctm); | ||
685 | lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ | ||
686 | lua_setmetatable(L, -2); | ||
283 | /* create `package' table */ | 687 | /* create `package' table */ |
284 | luaL_register(L, LUA_LOADLIBNAME, pk_funcs); | 688 | luaL_newlib(L, pk_funcs); |
285 | #if defined(LUA_COMPAT_LOADLIB) | 689 | createsearcherstable(L); |
286 | lua_getfield(L, -1, "loadlib"); | 690 | #if defined(LUA_COMPAT_LOADERS) |
287 | lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); | 691 | lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ |
692 | lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */ | ||
288 | #endif | 693 | #endif |
289 | lua_pushvalue(L, -1); | 694 | lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ |
290 | lua_replace(L, LUA_ENVIRONINDEX); | 695 | /* set field 'path' */ |
291 | /* create `loaders' table */ | 696 | setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT); |
292 | lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1); | 697 | /* set field 'cpath' */ |
293 | /* fill it with pre-defined loaders */ | 698 | setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT); |
294 | for (i=0; loaders[i] != NULL; i++) { | ||
295 | lua_pushcfunction(L, loaders[i]); | ||
296 | lua_rawseti(L, -2, i+1); | ||
297 | } | ||
298 | lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ | ||
299 | setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ | ||
300 | /* store config information */ | 699 | /* store config information */ |
301 | lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" | 700 | lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" |
302 | LUA_EXECDIR "\n" LUA_IGMARK); | 701 | LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); |
303 | lua_setfield(L, -2, "config"); | 702 | lua_setfield(L, -2, "config"); |
304 | /* set field `loaded' */ | 703 | /* set field `loaded' */ |
305 | luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); | 704 | luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); |
306 | lua_setfield(L, -2, "loaded"); | 705 | lua_setfield(L, -2, "loaded"); |
307 | /* set field `preload' */ | 706 | /* set field `preload' */ |
308 | lua_newtable(L); | 707 | luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); |
309 | lua_setfield(L, -2, "preload"); | 708 | lua_setfield(L, -2, "preload"); |
310 | lua_pushvalue(L, LUA_GLOBALSINDEX); | 709 | lua_pushglobaltable(L); |
311 | luaL_register(L, NULL, ll_funcs); /* open lib into global table */ | 710 | lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ |
312 | lua_pop(L, 1); | 711 | luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ |
712 | lua_pop(L, 1); /* pop global table */ | ||
313 | return 1; /* return 'package' table */ | 713 | return 1; /* return 'package' table */ |
314 | } | 714 | } |
315 | 715 | ||
diff --git a/apps/plugins/lua/lobject.c b/apps/plugins/lua/lobject.c index 62ad8e9359..34bbb25c9a 100644 --- a/apps/plugins/lua/lobject.c +++ b/apps/plugins/lua/lobject.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ | 2 | ** $Id: lobject.c,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Some generic functions over Lua objects | 3 | ** Some generic functions over Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -15,6 +15,8 @@ | |||
15 | 15 | ||
16 | #include "lua.h" | 16 | #include "lua.h" |
17 | 17 | ||
18 | #include "lctype.h" | ||
19 | #include "ldebug.h" | ||
18 | #include "ldo.h" | 20 | #include "ldo.h" |
19 | #include "lmem.h" | 21 | #include "lmem.h" |
20 | #include "lobject.h" | 22 | #include "lobject.h" |
@@ -24,7 +26,7 @@ | |||
24 | 26 | ||
25 | 27 | ||
26 | 28 | ||
27 | const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; | 29 | LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; |
28 | 30 | ||
29 | 31 | ||
30 | /* | 32 | /* |
@@ -33,25 +35,25 @@ const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; | |||
33 | ** eeeee != 0 and (xxx) otherwise. | 35 | ** eeeee != 0 and (xxx) otherwise. |
34 | */ | 36 | */ |
35 | int luaO_int2fb (unsigned int x) { | 37 | int luaO_int2fb (unsigned int x) { |
36 | int e = 0; /* expoent */ | 38 | int e = 0; /* exponent */ |
37 | while (x >= 16) { | 39 | if (x < 8) return x; |
40 | while (x >= 0x10) { | ||
38 | x = (x+1) >> 1; | 41 | x = (x+1) >> 1; |
39 | e++; | 42 | e++; |
40 | } | 43 | } |
41 | if (x < 8) return x; | 44 | return ((e+1) << 3) | (cast_int(x) - 8); |
42 | else return ((e+1) << 3) | (cast_int(x) - 8); | ||
43 | } | 45 | } |
44 | 46 | ||
45 | 47 | ||
46 | /* converts back */ | 48 | /* converts back */ |
47 | int luaO_fb2int (int x) { | 49 | int luaO_fb2int (int x) { |
48 | int e = (x >> 3) & 31; | 50 | int e = (x >> 3) & 0x1f; |
49 | if (e == 0) return x; | 51 | if (e == 0) return x; |
50 | else return ((x & 7)+8) << (e - 1); | 52 | else return ((x & 7) + 8) << (e - 1); |
51 | } | 53 | } |
52 | 54 | ||
53 | 55 | ||
54 | int luaO_log2 (unsigned int x) { | 56 | int luaO_ceillog2 (unsigned int x) { |
55 | static const lu_byte log_2[256] = { | 57 | static const lu_byte log_2[256] = { |
56 | 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, | 58 | 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, |
57 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, | 59 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, |
@@ -62,109 +64,169 @@ int luaO_log2 (unsigned int x) { | |||
62 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | 64 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, |
63 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 | 65 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 |
64 | }; | 66 | }; |
65 | int l = -1; | 67 | int l = 0; |
68 | x--; | ||
66 | while (x >= 256) { l += 8; x >>= 8; } | 69 | while (x >= 256) { l += 8; x >>= 8; } |
67 | return l + log_2[x]; | 70 | return l + log_2[x]; |
71 | } | ||
72 | |||
73 | |||
74 | lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) { | ||
75 | switch (op) { | ||
76 | case LUA_OPADD: return luai_numadd(NULL, v1, v2); | ||
77 | case LUA_OPSUB: return luai_numsub(NULL, v1, v2); | ||
78 | case LUA_OPMUL: return luai_nummul(NULL, v1, v2); | ||
79 | case LUA_OPDIV: return luai_numdiv(NULL, v1, v2); | ||
80 | case LUA_OPMOD: return luai_nummod(NULL, v1, v2); | ||
81 | case LUA_OPPOW: return luai_numpow(NULL, v1, v2); | ||
82 | case LUA_OPUNM: return luai_numunm(NULL, v1); | ||
83 | default: lua_assert(0); return 0; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | |||
88 | int luaO_hexavalue (int c) { | ||
89 | if (lisdigit(c)) return c - '0'; | ||
90 | else return ltolower(c) - 'a' + 10; | ||
91 | } | ||
92 | |||
93 | |||
94 | #if !defined(lua_strx2number) | ||
95 | |||
96 | #include <math.h> | ||
97 | |||
98 | |||
99 | static int isneg (const char **s) { | ||
100 | if (**s == '-') { (*s)++; return 1; } | ||
101 | else if (**s == '+') (*s)++; | ||
102 | return 0; | ||
103 | } | ||
68 | 104 | ||
105 | |||
106 | static lua_Number readhexa (const char **s, lua_Number r, int *count) { | ||
107 | for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */ | ||
108 | r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s))); | ||
109 | (*count)++; | ||
110 | } | ||
111 | return r; | ||
69 | } | 112 | } |
70 | 113 | ||
71 | 114 | ||
72 | int luaO_rawequalObj (const TValue *t1, const TValue *t2) { | 115 | /* |
73 | if (ttype(t1) != ttype(t2)) return 0; | 116 | ** convert an hexadecimal numeric string to a number, following |
74 | else switch (ttype(t1)) { | 117 | ** C99 specification for 'strtod' |
75 | case LUA_TNIL: | 118 | */ |
76 | return 1; | 119 | static lua_Number lua_strx2number (const char *s, char **endptr) { |
77 | case LUA_TNUMBER: | 120 | lua_Number r = 0.0; |
78 | return luai_numeq(nvalue(t1), nvalue(t2)); | 121 | int e = 0, i = 0; |
79 | case LUA_TBOOLEAN: | 122 | int neg = 0; /* 1 if number is negative */ |
80 | return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ | 123 | *endptr = cast(char *, s); /* nothing is valid yet */ |
81 | case LUA_TLIGHTUSERDATA: | 124 | while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ |
82 | return pvalue(t1) == pvalue(t2); | 125 | neg = isneg(&s); /* check signal */ |
83 | default: | 126 | if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ |
84 | lua_assert(iscollectable(t1)); | 127 | return 0.0; /* invalid format (no '0x') */ |
85 | return gcvalue(t1) == gcvalue(t2); | 128 | s += 2; /* skip '0x' */ |
129 | r = readhexa(&s, r, &i); /* read integer part */ | ||
130 | if (*s == '.') { | ||
131 | s++; /* skip dot */ | ||
132 | r = readhexa(&s, r, &e); /* read fractional part */ | ||
86 | } | 133 | } |
134 | if (i == 0 && e == 0) | ||
135 | return 0.0; /* invalid format (no digit) */ | ||
136 | e *= -4; /* each fractional digit divides value by 2^-4 */ | ||
137 | *endptr = cast(char *, s); /* valid up to here */ | ||
138 | if (*s == 'p' || *s == 'P') { /* exponent part? */ | ||
139 | int exp1 = 0; | ||
140 | int neg1; | ||
141 | s++; /* skip 'p' */ | ||
142 | neg1 = isneg(&s); /* signal */ | ||
143 | if (!lisdigit(cast_uchar(*s))) | ||
144 | goto ret; /* must have at least one digit */ | ||
145 | while (lisdigit(cast_uchar(*s))) /* read exponent */ | ||
146 | exp1 = exp1 * 10 + *(s++) - '0'; | ||
147 | if (neg1) exp1 = -exp1; | ||
148 | e += exp1; | ||
149 | } | ||
150 | *endptr = cast(char *, s); /* valid up to here */ | ||
151 | ret: | ||
152 | if (neg) r = -r; | ||
153 | return l_mathop(ldexp)(r, e); | ||
87 | } | 154 | } |
88 | 155 | ||
156 | #endif | ||
157 | |||
89 | 158 | ||
90 | int luaO_str2d (const char *s, lua_Number *result) { | 159 | int luaO_str2d (const char *s, size_t len, lua_Number *result) { |
91 | char *endptr; | 160 | char *endptr; |
92 | *result = lua_str2number(s, &endptr); | 161 | if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ |
93 | if (endptr == s) return 0; /* conversion failed */ | 162 | return 0; |
94 | if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ | 163 | else if (strpbrk(s, "xX")) /* hexa? */ |
95 | *result = cast_num(strtoul(s, &endptr, 16)); | 164 | *result = lua_strx2number(s, &endptr); |
96 | if (*endptr == '\0') return 1; /* most common case */ | 165 | else |
97 | while (isspace(cast(unsigned char, *endptr))) endptr++; | 166 | *result = lua_str2number(s, &endptr); |
98 | if (*endptr != '\0') return 0; /* invalid trailing characters? */ | 167 | if (endptr == s) return 0; /* nothing recognized */ |
99 | return 1; | 168 | while (lisspace(cast_uchar(*endptr))) endptr++; |
169 | return (endptr == s + len); /* OK if no trailing characters */ | ||
100 | } | 170 | } |
101 | 171 | ||
102 | 172 | ||
103 | 173 | ||
104 | static void pushstr (lua_State *L, const char *str) { | 174 | static void pushstr (lua_State *L, const char *str, size_t l) { |
105 | setsvalue2s(L, L->top, luaS_new(L, str)); | 175 | setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); |
106 | incr_top(L); | ||
107 | } | 176 | } |
108 | 177 | ||
109 | 178 | ||
110 | /* this function handles only `%d', `%c', %f, %p, and `%s' formats */ | 179 | /* this function handles only `%d', `%c', %f, %p, and `%s' formats */ |
111 | const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { | 180 | const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { |
112 | int n = 1; | 181 | int n = 0; |
113 | pushstr(L, ""); | ||
114 | for (;;) { | 182 | for (;;) { |
115 | const char *e = strchr(fmt, '%'); | 183 | const char *e = strchr(fmt, '%'); |
116 | if (e == NULL) break; | 184 | if (e == NULL) break; |
117 | setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); | 185 | luaD_checkstack(L, 2); /* fmt + item */ |
118 | incr_top(L); | 186 | pushstr(L, fmt, e - fmt); |
119 | switch (*(e+1)) { | 187 | switch (*(e+1)) { |
120 | case 's': { | 188 | case 's': { |
121 | const char *s = va_arg(argp, char *); | 189 | const char *s = va_arg(argp, char *); |
122 | if (s == NULL) s = "(null)"; | 190 | if (s == NULL) s = "(null)"; |
123 | pushstr(L, s); | 191 | pushstr(L, s, strlen(s)); |
124 | break; | 192 | break; |
125 | } | 193 | } |
126 | case 'c': { | 194 | case 'c': { |
127 | char buff[2]; | 195 | char buff; |
128 | buff[0] = cast(char, va_arg(argp, int)); | 196 | buff = cast(char, va_arg(argp, int)); |
129 | buff[1] = '\0'; | 197 | pushstr(L, &buff, 1); |
130 | pushstr(L, buff); | ||
131 | break; | 198 | break; |
132 | } | 199 | } |
133 | case 'd': { | 200 | case 'd': { |
134 | setnvalue(L->top, cast_num(va_arg(argp, int))); | 201 | setnvalue(L->top++, cast_num(va_arg(argp, int))); |
135 | incr_top(L); | ||
136 | break; | 202 | break; |
137 | } | 203 | } |
138 | case 'f': { | 204 | case 'f': { |
139 | setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); | 205 | setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber))); |
140 | incr_top(L); | ||
141 | break; | 206 | break; |
142 | } | 207 | } |
143 | case 'p': { | 208 | case 'p': { |
144 | char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ | 209 | char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ |
145 | snprintf(buff, 4*sizeof(void *) + 8, "%p", va_arg(argp, void *)); | 210 | int l = snprintf(buff, sizeof(buff), "%p", va_arg(argp, void *)); |
146 | pushstr(L, buff); | 211 | pushstr(L, buff, l); |
147 | break; | 212 | break; |
148 | } | 213 | } |
149 | case '%': { | 214 | case '%': { |
150 | pushstr(L, "%"); | 215 | pushstr(L, "%", 1); |
151 | break; | 216 | break; |
152 | } | 217 | } |
153 | default: { | 218 | default: { |
154 | char buff[3]; | 219 | luaG_runerror(L, |
155 | buff[0] = '%'; | 220 | "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"), |
156 | buff[1] = *(e+1); | 221 | *(e + 1)); |
157 | buff[2] = '\0'; | ||
158 | pushstr(L, buff); | ||
159 | break; | ||
160 | } | 222 | } |
161 | } | 223 | } |
162 | n += 2; | 224 | n += 2; |
163 | fmt = e+2; | 225 | fmt = e+2; |
164 | } | 226 | } |
165 | pushstr(L, fmt); | 227 | luaD_checkstack(L, 1); |
166 | luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); | 228 | pushstr(L, fmt, strlen(fmt)); |
167 | L->top -= n; | 229 | if (n > 0) luaV_concat(L, n + 1); |
168 | return svalue(L->top - 1); | 230 | return svalue(L->top - 1); |
169 | } | 231 | } |
170 | 232 | ||
@@ -179,36 +241,48 @@ const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { | |||
179 | } | 241 | } |
180 | 242 | ||
181 | 243 | ||
244 | /* number of chars of a literal string without the ending \0 */ | ||
245 | #define LL(x) (sizeof(x)/sizeof(char) - 1) | ||
246 | |||
247 | #define RETS "..." | ||
248 | #define PRE "[string \"" | ||
249 | #define POS "\"]" | ||
250 | |||
251 | #define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) | ||
252 | |||
182 | void luaO_chunkid (char *out, const char *source, size_t bufflen) { | 253 | void luaO_chunkid (char *out, const char *source, size_t bufflen) { |
183 | if (*source == '=') { | 254 | size_t l = strlen(source); |
184 | strncpy(out, source+1, bufflen); /* remove first char */ | 255 | if (*source == '=') { /* 'literal' source */ |
185 | out[bufflen-1] = '\0'; /* ensures null termination */ | 256 | if (l <= bufflen) /* small enough? */ |
257 | memcpy(out, source + 1, l * sizeof(char)); | ||
258 | else { /* truncate it */ | ||
259 | addstr(out, source + 1, bufflen - 1); | ||
260 | *out = '\0'; | ||
261 | } | ||
186 | } | 262 | } |
187 | else { /* out = "source", or "...source" */ | 263 | else if (*source == '@') { /* file name */ |
188 | if (*source == '@') { | 264 | if (l <= bufflen) /* small enough? */ |
189 | size_t l; | 265 | memcpy(out, source + 1, l * sizeof(char)); |
190 | source++; /* skip the `@' */ | 266 | else { /* add '...' before rest of name */ |
191 | bufflen -= sizeof(" '...' "); | 267 | addstr(out, RETS, LL(RETS)); |
192 | l = strlen(source); | 268 | bufflen -= LL(RETS); |
193 | strcpy(out, ""); | 269 | memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); |
194 | if (l > bufflen) { | ||
195 | source += (l-bufflen); /* get last part of file name */ | ||
196 | strcat(out, "..."); | ||
197 | } | ||
198 | strcat(out, source); | ||
199 | } | 270 | } |
200 | else { /* out = [string "string"] */ | 271 | } |
201 | size_t len = strcspn(source, "\n\r"); /* stop at first newline */ | 272 | else { /* string; format as [string "source"] */ |
202 | bufflen -= sizeof(" [string \"...\"] "); | 273 | const char *nl = strchr(source, '\n'); /* find first new line (if any) */ |
203 | if (len > bufflen) len = bufflen; | 274 | addstr(out, PRE, LL(PRE)); /* add prefix */ |
204 | strcpy(out, "[string \""); | 275 | bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ |
205 | if (source[len] != '\0') { /* must truncate? */ | 276 | if (l < bufflen && nl == NULL) { /* small one-line source? */ |
206 | strncat(out, source, len); | 277 | addstr(out, source, l); /* keep it */ |
207 | strcat(out, "..."); | ||
208 | } | ||
209 | else | ||
210 | strcat(out, source); | ||
211 | strcat(out, "\"]"); | ||
212 | } | 278 | } |
279 | else { | ||
280 | if (nl != NULL) l = nl - source; /* stop at first newline */ | ||
281 | if (l > bufflen) l = bufflen; | ||
282 | addstr(out, source, l); | ||
283 | addstr(out, RETS, LL(RETS)); | ||
284 | } | ||
285 | memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); | ||
213 | } | 286 | } |
214 | } | 287 | } |
288 | |||
diff --git a/apps/plugins/lua/lobject.h b/apps/plugins/lua/lobject.h index 93288fe0fb..3a630b944c 100644 --- a/apps/plugins/lua/lobject.h +++ b/apps/plugins/lua/lobject.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lobject.h,v 2.71.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -16,18 +16,52 @@ | |||
16 | #include "lua.h" | 16 | #include "lua.h" |
17 | 17 | ||
18 | 18 | ||
19 | /* tags for values visible from Lua */ | 19 | /* |
20 | #define LAST_TAG LUA_TTHREAD | 20 | ** Extra tags for non-values |
21 | */ | ||
22 | #define LUA_TPROTO LUA_NUMTAGS | ||
23 | #define LUA_TUPVAL (LUA_NUMTAGS+1) | ||
24 | #define LUA_TDEADKEY (LUA_NUMTAGS+2) | ||
21 | 25 | ||
22 | #define NUM_TAGS (LAST_TAG+1) | 26 | /* |
27 | ** number of all possible tags (including LUA_TNONE but excluding DEADKEY) | ||
28 | */ | ||
29 | #define LUA_TOTALTAGS (LUA_TUPVAL+2) | ||
23 | 30 | ||
24 | 31 | ||
25 | /* | 32 | /* |
26 | ** Extra tags for non-values | 33 | ** tags for Tagged Values have the following use of bits: |
34 | ** bits 0-3: actual tag (a LUA_T* value) | ||
35 | ** bits 4-5: variant bits | ||
36 | ** bit 6: whether value is collectable | ||
27 | */ | 37 | */ |
28 | #define LUA_TPROTO (LAST_TAG+1) | 38 | |
29 | #define LUA_TUPVAL (LAST_TAG+2) | 39 | #define VARBITS (3 << 4) |
30 | #define LUA_TDEADKEY (LAST_TAG+3) | 40 | |
41 | |||
42 | /* | ||
43 | ** LUA_TFUNCTION variants: | ||
44 | ** 0 - Lua function | ||
45 | ** 1 - light C function | ||
46 | ** 2 - regular C function (closure) | ||
47 | */ | ||
48 | |||
49 | /* Variant tags for functions */ | ||
50 | #define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */ | ||
51 | #define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */ | ||
52 | #define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ | ||
53 | |||
54 | |||
55 | /* Variant tags for strings */ | ||
56 | #define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */ | ||
57 | #define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ | ||
58 | |||
59 | |||
60 | /* Bit mark for collectable types */ | ||
61 | #define BIT_ISCOLLECTABLE (1 << 6) | ||
62 | |||
63 | /* mark a tag as collectable */ | ||
64 | #define ctb(t) ((t) | BIT_ISCOLLECTABLE) | ||
31 | 65 | ||
32 | 66 | ||
33 | /* | 67 | /* |
@@ -52,120 +86,165 @@ typedef struct GCheader { | |||
52 | 86 | ||
53 | 87 | ||
54 | 88 | ||
55 | |||
56 | /* | 89 | /* |
57 | ** Union of all Lua values | 90 | ** Union of all Lua values |
58 | */ | 91 | */ |
59 | typedef union { | 92 | typedef union Value Value; |
60 | GCObject *gc; | 93 | |
61 | void *p; | 94 | |
62 | lua_Number n; | 95 | #define numfield lua_Number n; /* numbers */ |
63 | int b; | 96 | |
64 | } Value; | ||
65 | 97 | ||
66 | 98 | ||
67 | /* | 99 | /* |
68 | ** Tagged Values | 100 | ** Tagged Values. This is the basic representation of values in Lua, |
101 | ** an actual value plus a tag with its type. | ||
69 | */ | 102 | */ |
70 | 103 | ||
71 | #define TValuefields Value value; int tt | 104 | #define TValuefields Value value_; int tt_ |
72 | 105 | ||
73 | typedef struct lua_TValue { | 106 | typedef struct lua_TValue TValue; |
74 | TValuefields; | 107 | |
75 | } TValue; | 108 | |
109 | /* macro defining a nil value */ | ||
110 | #define NILCONSTANT {NULL}, LUA_TNIL | ||
111 | |||
112 | |||
113 | #define val_(o) ((o)->value_) | ||
114 | #define num_(o) (val_(o).n) | ||
115 | |||
116 | |||
117 | /* raw type tag of a TValue */ | ||
118 | #define rttype(o) ((o)->tt_) | ||
119 | |||
120 | /* tag with no variants (bits 0-3) */ | ||
121 | #define novariant(x) ((x) & 0x0F) | ||
122 | |||
123 | /* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ | ||
124 | #define ttype(o) (rttype(o) & 0x3F) | ||
125 | |||
126 | /* type tag of a TValue with no variants (bits 0-3) */ | ||
127 | #define ttypenv(o) (novariant(rttype(o))) | ||
76 | 128 | ||
77 | 129 | ||
78 | /* Macros to test type */ | 130 | /* Macros to test type */ |
79 | #define ttisnil(o) (ttype(o) == LUA_TNIL) | 131 | #define checktag(o,t) (rttype(o) == (t)) |
80 | #define ttisnumber(o) (ttype(o) == LUA_TNUMBER) | 132 | #define checktype(o,t) (ttypenv(o) == (t)) |
81 | #define ttisstring(o) (ttype(o) == LUA_TSTRING) | 133 | #define ttisnumber(o) checktag((o), LUA_TNUMBER) |
82 | #define ttistable(o) (ttype(o) == LUA_TTABLE) | 134 | #define ttisnil(o) checktag((o), LUA_TNIL) |
83 | #define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) | 135 | #define ttisboolean(o) checktag((o), LUA_TBOOLEAN) |
84 | #define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) | 136 | #define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) |
85 | #define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) | 137 | #define ttisstring(o) checktype((o), LUA_TSTRING) |
86 | #define ttisthread(o) (ttype(o) == LUA_TTHREAD) | 138 | #define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) |
87 | #define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) | 139 | #define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) |
140 | #define ttistable(o) checktag((o), ctb(LUA_TTABLE)) | ||
141 | #define ttisfunction(o) checktype(o, LUA_TFUNCTION) | ||
142 | #define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) | ||
143 | #define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) | ||
144 | #define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) | ||
145 | #define ttislcf(o) checktag((o), LUA_TLCF) | ||
146 | #define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA)) | ||
147 | #define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) | ||
148 | #define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) | ||
149 | |||
150 | #define ttisequal(o1,o2) (rttype(o1) == rttype(o2)) | ||
88 | 151 | ||
89 | /* Macros to access values */ | 152 | /* Macros to access values */ |
90 | #define ttype(o) ((o)->tt) | 153 | #define nvalue(o) check_exp(ttisnumber(o), num_(o)) |
91 | #define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) | 154 | #define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) |
92 | #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) | 155 | #define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) |
93 | #define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) | 156 | #define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts) |
94 | #define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) | ||
95 | #define tsvalue(o) (&rawtsvalue(o)->tsv) | 157 | #define tsvalue(o) (&rawtsvalue(o)->tsv) |
96 | #define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) | 158 | #define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).gc->u) |
97 | #define uvalue(o) (&rawuvalue(o)->uv) | 159 | #define uvalue(o) (&rawuvalue(o)->uv) |
98 | #define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) | 160 | #define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl) |
99 | #define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) | 161 | #define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l) |
100 | #define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) | 162 | #define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c) |
101 | #define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) | 163 | #define fvalue(o) check_exp(ttislcf(o), val_(o).f) |
164 | #define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h) | ||
165 | #define bvalue(o) check_exp(ttisboolean(o), val_(o).b) | ||
166 | #define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th) | ||
167 | /* a dead value may get the 'gc' field, but cannot access its contents */ | ||
168 | #define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc)) | ||
102 | 169 | ||
103 | #define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) | 170 | #define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) |
104 | 171 | ||
105 | /* | 172 | |
106 | ** for internal debug only | 173 | #define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) |
107 | */ | 174 | |
108 | #define checkconsistency(obj) \ | 175 | |
109 | lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) | 176 | /* Macros for internal tests */ |
177 | #define righttt(obj) (ttype(obj) == gcvalue(obj)->gch.tt) | ||
110 | 178 | ||
111 | #define checkliveness(g,obj) \ | 179 | #define checkliveness(g,obj) \ |
112 | lua_assert(!iscollectable(obj) || \ | 180 | lua_longassert(!iscollectable(obj) || \ |
113 | ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) | 181 | (righttt(obj) && !isdead(g,gcvalue(obj)))) |
114 | 182 | ||
115 | 183 | ||
116 | /* Macros to set values */ | 184 | /* Macros to set values */ |
117 | #define setnilvalue(obj) ((obj)->tt=LUA_TNIL) | 185 | #define settt_(o,t) ((o)->tt_=(t)) |
118 | 186 | ||
119 | #define setnvalue(obj,x) \ | 187 | #define setnvalue(obj,x) \ |
120 | { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } | 188 | { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); } |
189 | |||
190 | #define setnilvalue(obj) settt_(obj, LUA_TNIL) | ||
191 | |||
192 | #define setfvalue(obj,x) \ | ||
193 | { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); } | ||
121 | 194 | ||
122 | #define setpvalue(obj,x) \ | 195 | #define setpvalue(obj,x) \ |
123 | { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } | 196 | { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); } |
124 | 197 | ||
125 | #define setbvalue(obj,x) \ | 198 | #define setbvalue(obj,x) \ |
126 | { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } | 199 | { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } |
200 | |||
201 | #define setgcovalue(L,obj,x) \ | ||
202 | { TValue *io=(obj); GCObject *i_g=(x); \ | ||
203 | val_(io).gc=i_g; settt_(io, ctb(gch(i_g)->tt)); } | ||
127 | 204 | ||
128 | #define setsvalue(L,obj,x) \ | 205 | #define setsvalue(L,obj,x) \ |
129 | { TValue *i_o=(obj); \ | 206 | { TValue *io=(obj); \ |
130 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ | 207 | TString *x_ = (x); \ |
131 | checkliveness(G(L),i_o); } | 208 | val_(io).gc=cast(GCObject *, x_); settt_(io, ctb(x_->tsv.tt)); \ |
209 | checkliveness(G(L),io); } | ||
132 | 210 | ||
133 | #define setuvalue(L,obj,x) \ | 211 | #define setuvalue(L,obj,x) \ |
134 | { TValue *i_o=(obj); \ | 212 | { TValue *io=(obj); \ |
135 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ | 213 | val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TUSERDATA)); \ |
136 | checkliveness(G(L),i_o); } | 214 | checkliveness(G(L),io); } |
137 | 215 | ||
138 | #define setthvalue(L,obj,x) \ | 216 | #define setthvalue(L,obj,x) \ |
139 | { TValue *i_o=(obj); \ | 217 | { TValue *io=(obj); \ |
140 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ | 218 | val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTHREAD)); \ |
141 | checkliveness(G(L),i_o); } | 219 | checkliveness(G(L),io); } |
142 | 220 | ||
143 | #define setclvalue(L,obj,x) \ | 221 | #define setclLvalue(L,obj,x) \ |
144 | { TValue *i_o=(obj); \ | 222 | { TValue *io=(obj); \ |
145 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ | 223 | val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TLCL)); \ |
146 | checkliveness(G(L),i_o); } | 224 | checkliveness(G(L),io); } |
147 | 225 | ||
148 | #define sethvalue(L,obj,x) \ | 226 | #define setclCvalue(L,obj,x) \ |
149 | { TValue *i_o=(obj); \ | 227 | { TValue *io=(obj); \ |
150 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ | 228 | val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TCCL)); \ |
151 | checkliveness(G(L),i_o); } | 229 | checkliveness(G(L),io); } |
152 | 230 | ||
153 | #define setptvalue(L,obj,x) \ | 231 | #define sethvalue(L,obj,x) \ |
154 | { TValue *i_o=(obj); \ | 232 | { TValue *io=(obj); \ |
155 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ | 233 | val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \ |
156 | checkliveness(G(L),i_o); } | 234 | checkliveness(G(L),io); } |
157 | 235 | ||
236 | #define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) | ||
158 | 237 | ||
159 | 238 | ||
160 | 239 | ||
161 | #define setobj(L,obj1,obj2) \ | 240 | #define setobj(L,obj1,obj2) \ |
162 | { const TValue *o2=(obj2); TValue *o1=(obj1); \ | 241 | { const TValue *io2=(obj2); TValue *io1=(obj1); \ |
163 | o1->value = o2->value; o1->tt=o2->tt; \ | 242 | io1->value_ = io2->value_; io1->tt_ = io2->tt_; \ |
164 | checkliveness(G(L),o1); } | 243 | checkliveness(G(L),io1); } |
165 | 244 | ||
166 | 245 | ||
167 | /* | 246 | /* |
168 | ** different types of sets, according to destination | 247 | ** different types of assignments, according to destination |
169 | */ | 248 | */ |
170 | 249 | ||
171 | /* from stack to (same) stack */ | 250 | /* from stack to (same) stack */ |
@@ -183,47 +262,204 @@ typedef struct lua_TValue { | |||
183 | #define setobj2n setobj | 262 | #define setobj2n setobj |
184 | #define setsvalue2n setsvalue | 263 | #define setsvalue2n setsvalue |
185 | 264 | ||
186 | #define setttype(obj, tt) (ttype(obj) = (tt)) | 265 | |
266 | /* check whether a number is valid (useful only for NaN trick) */ | ||
267 | #define luai_checknum(L,o,c) { /* empty */ } | ||
268 | |||
269 | |||
270 | /* | ||
271 | ** {====================================================== | ||
272 | ** NaN Trick | ||
273 | ** ======================================================= | ||
274 | */ | ||
275 | #if defined(LUA_NANTRICK) | ||
276 | |||
277 | /* | ||
278 | ** numbers are represented in the 'd_' field. All other values have the | ||
279 | ** value (NNMARK | tag) in 'tt__'. A number with such pattern would be | ||
280 | ** a "signaled NaN", which is never generated by regular operations by | ||
281 | ** the CPU (nor by 'strtod') | ||
282 | */ | ||
283 | |||
284 | /* allows for external implementation for part of the trick */ | ||
285 | #if !defined(NNMARK) /* { */ | ||
286 | |||
287 | |||
288 | #if !defined(LUA_IEEEENDIAN) | ||
289 | #error option 'LUA_NANTRICK' needs 'LUA_IEEEENDIAN' | ||
290 | #endif | ||
291 | |||
292 | |||
293 | #define NNMARK 0x7FF7A500 | ||
294 | #define NNMASK 0x7FFFFF00 | ||
295 | |||
296 | #undef TValuefields | ||
297 | #undef NILCONSTANT | ||
298 | |||
299 | #if (LUA_IEEEENDIAN == 0) /* { */ | ||
300 | |||
301 | /* little endian */ | ||
302 | #define TValuefields \ | ||
303 | union { struct { Value v__; int tt__; } i; double d__; } u | ||
304 | #define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}} | ||
305 | /* field-access macros */ | ||
306 | #define v_(o) ((o)->u.i.v__) | ||
307 | #define d_(o) ((o)->u.d__) | ||
308 | #define tt_(o) ((o)->u.i.tt__) | ||
309 | |||
310 | #else /* }{ */ | ||
311 | |||
312 | /* big endian */ | ||
313 | #define TValuefields \ | ||
314 | union { struct { int tt__; Value v__; } i; double d__; } u | ||
315 | #define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}} | ||
316 | /* field-access macros */ | ||
317 | #define v_(o) ((o)->u.i.v__) | ||
318 | #define d_(o) ((o)->u.d__) | ||
319 | #define tt_(o) ((o)->u.i.tt__) | ||
320 | |||
321 | #endif /* } */ | ||
322 | |||
323 | #endif /* } */ | ||
187 | 324 | ||
188 | 325 | ||
189 | #define iscollectable(o) (ttype(o) >= LUA_TSTRING) | 326 | /* correspondence with standard representation */ |
327 | #undef val_ | ||
328 | #define val_(o) v_(o) | ||
329 | #undef num_ | ||
330 | #define num_(o) d_(o) | ||
190 | 331 | ||
191 | 332 | ||
333 | #undef numfield | ||
334 | #define numfield /* no such field; numbers are the entire struct */ | ||
335 | |||
336 | /* basic check to distinguish numbers from non-numbers */ | ||
337 | #undef ttisnumber | ||
338 | #define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK) | ||
339 | |||
340 | #define tag2tt(t) (NNMARK | (t)) | ||
341 | |||
342 | #undef rttype | ||
343 | #define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff) | ||
344 | |||
345 | #undef settt_ | ||
346 | #define settt_(o,t) (tt_(o) = tag2tt(t)) | ||
347 | |||
348 | #undef setnvalue | ||
349 | #define setnvalue(obj,x) \ | ||
350 | { TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); } | ||
351 | |||
352 | #undef setobj | ||
353 | #define setobj(L,obj1,obj2) \ | ||
354 | { const TValue *o2_=(obj2); TValue *o1_=(obj1); \ | ||
355 | o1_->u = o2_->u; \ | ||
356 | checkliveness(G(L),o1_); } | ||
357 | |||
358 | |||
359 | /* | ||
360 | ** these redefinitions are not mandatory, but these forms are more efficient | ||
361 | */ | ||
362 | |||
363 | #undef checktag | ||
364 | #undef checktype | ||
365 | #define checktag(o,t) (tt_(o) == tag2tt(t)) | ||
366 | #define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS)) | ||
367 | |||
368 | #undef ttisequal | ||
369 | #define ttisequal(o1,o2) \ | ||
370 | (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2))) | ||
371 | |||
372 | |||
373 | #undef luai_checknum | ||
374 | #define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; } | ||
375 | |||
376 | #endif | ||
377 | /* }====================================================== */ | ||
378 | |||
379 | |||
380 | |||
381 | /* | ||
382 | ** {====================================================== | ||
383 | ** types and prototypes | ||
384 | ** ======================================================= | ||
385 | */ | ||
386 | |||
387 | |||
388 | union Value { | ||
389 | GCObject *gc; /* collectable objects */ | ||
390 | void *p; /* light userdata */ | ||
391 | int b; /* booleans */ | ||
392 | lua_CFunction f; /* light C functions */ | ||
393 | numfield /* numbers */ | ||
394 | }; | ||
395 | |||
396 | |||
397 | struct lua_TValue { | ||
398 | TValuefields; | ||
399 | }; | ||
400 | |||
192 | 401 | ||
193 | typedef TValue *StkId; /* index to stack elements */ | 402 | typedef TValue *StkId; /* index to stack elements */ |
194 | 403 | ||
195 | 404 | ||
405 | |||
406 | |||
196 | /* | 407 | /* |
197 | ** String headers for string table | 408 | ** Header for string value; string bytes follow the end of this structure |
198 | */ | 409 | */ |
199 | typedef union TString { | 410 | typedef union TString { |
200 | L_Umaxalign dummy; /* ensures maximum alignment for strings */ | 411 | L_Umaxalign dummy; /* ensures maximum alignment for strings */ |
201 | struct { | 412 | struct { |
202 | CommonHeader; | 413 | CommonHeader; |
203 | lu_byte reserved; | 414 | lu_byte extra; /* reserved words for short strings; "has hash" for longs */ |
204 | unsigned int hash; | 415 | unsigned int hash; |
205 | size_t len; | 416 | size_t len; /* number of characters in string */ |
206 | } tsv; | 417 | } tsv; |
207 | } TString; | 418 | } TString; |
208 | 419 | ||
209 | 420 | ||
421 | /* get the actual string (array of bytes) from a TString */ | ||
210 | #define getstr(ts) cast(const char *, (ts) + 1) | 422 | #define getstr(ts) cast(const char *, (ts) + 1) |
211 | #define svalue(o) getstr(rawtsvalue(o)) | ||
212 | 423 | ||
424 | /* get the actual string (array of bytes) from a Lua value */ | ||
425 | #define svalue(o) getstr(rawtsvalue(o)) | ||
213 | 426 | ||
214 | 427 | ||
428 | /* | ||
429 | ** Header for userdata; memory area follows the end of this structure | ||
430 | */ | ||
215 | typedef union Udata { | 431 | typedef union Udata { |
216 | L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ | 432 | L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ |
217 | struct { | 433 | struct { |
218 | CommonHeader; | 434 | CommonHeader; |
219 | struct Table *metatable; | 435 | struct Table *metatable; |
220 | struct Table *env; | 436 | struct Table *env; |
221 | size_t len; | 437 | size_t len; /* number of bytes */ |
222 | } uv; | 438 | } uv; |
223 | } Udata; | 439 | } Udata; |
224 | 440 | ||
225 | 441 | ||
226 | 442 | ||
443 | /* | ||
444 | ** Description of an upvalue for function prototypes | ||
445 | */ | ||
446 | typedef struct Upvaldesc { | ||
447 | TString *name; /* upvalue name (for debug information) */ | ||
448 | lu_byte instack; /* whether it is in stack */ | ||
449 | lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ | ||
450 | } Upvaldesc; | ||
451 | |||
452 | |||
453 | /* | ||
454 | ** Description of a local variable for function prototypes | ||
455 | ** (used for debug information) | ||
456 | */ | ||
457 | typedef struct LocVar { | ||
458 | TString *varname; | ||
459 | int startpc; /* first point where variable is active */ | ||
460 | int endpc; /* first point where variable is dead */ | ||
461 | } LocVar; | ||
462 | |||
227 | 463 | ||
228 | /* | 464 | /* |
229 | ** Function Prototypes | 465 | ** Function Prototypes |
@@ -233,11 +469,12 @@ typedef struct Proto { | |||
233 | TValue *k; /* constants used by the function */ | 469 | TValue *k; /* constants used by the function */ |
234 | Instruction *code; | 470 | Instruction *code; |
235 | struct Proto **p; /* functions defined inside the function */ | 471 | struct Proto **p; /* functions defined inside the function */ |
236 | int *lineinfo; /* map from opcodes to source lines */ | 472 | int *lineinfo; /* map from opcodes to source lines (debug information) */ |
237 | struct LocVar *locvars; /* information about local variables */ | 473 | LocVar *locvars; /* information about local variables (debug information) */ |
238 | TString **upvalues; /* upvalue names */ | 474 | Upvaldesc *upvalues; /* upvalue information */ |
239 | TString *source; | 475 | union Closure *cache; /* last created closure with this prototype */ |
240 | int sizeupvalues; | 476 | TString *source; /* used for debug information */ |
477 | int sizeupvalues; /* size of 'upvalues' */ | ||
241 | int sizek; /* size of `k' */ | 478 | int sizek; /* size of `k' */ |
242 | int sizecode; | 479 | int sizecode; |
243 | int sizelineinfo; | 480 | int sizelineinfo; |
@@ -246,31 +483,16 @@ typedef struct Proto { | |||
246 | int linedefined; | 483 | int linedefined; |
247 | int lastlinedefined; | 484 | int lastlinedefined; |
248 | GCObject *gclist; | 485 | GCObject *gclist; |
249 | lu_byte nups; /* number of upvalues */ | 486 | lu_byte numparams; /* number of fixed parameters */ |
250 | lu_byte numparams; | ||
251 | lu_byte is_vararg; | 487 | lu_byte is_vararg; |
252 | lu_byte maxstacksize; | 488 | lu_byte maxstacksize; /* maximum stack used by this function */ |
253 | } Proto; | 489 | } Proto; |
254 | 490 | ||
255 | 491 | ||
256 | /* masks for new-style vararg */ | ||
257 | #define VARARG_HASARG 1 | ||
258 | #define VARARG_ISVARARG 2 | ||
259 | #define VARARG_NEEDSARG 4 | ||
260 | |||
261 | |||
262 | typedef struct LocVar { | ||
263 | TString *varname; | ||
264 | int startpc; /* first point where variable is active */ | ||
265 | int endpc; /* first point where variable is dead */ | ||
266 | } LocVar; | ||
267 | |||
268 | |||
269 | 492 | ||
270 | /* | 493 | /* |
271 | ** Upvalues | 494 | ** Lua Upvalues |
272 | */ | 495 | */ |
273 | |||
274 | typedef struct UpVal { | 496 | typedef struct UpVal { |
275 | CommonHeader; | 497 | CommonHeader; |
276 | TValue *v; /* points to stack or to its own value */ | 498 | TValue *v; /* points to stack or to its own value */ |
@@ -289,20 +511,19 @@ typedef struct UpVal { | |||
289 | */ | 511 | */ |
290 | 512 | ||
291 | #define ClosureHeader \ | 513 | #define ClosureHeader \ |
292 | CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ | 514 | CommonHeader; lu_byte nupvalues; GCObject *gclist |
293 | struct Table *env | ||
294 | 515 | ||
295 | typedef struct CClosure { | 516 | typedef struct CClosure { |
296 | ClosureHeader; | 517 | ClosureHeader; |
297 | lua_CFunction f; | 518 | lua_CFunction f; |
298 | TValue upvalue[1]; | 519 | TValue upvalue[1]; /* list of upvalues */ |
299 | } CClosure; | 520 | } CClosure; |
300 | 521 | ||
301 | 522 | ||
302 | typedef struct LClosure { | 523 | typedef struct LClosure { |
303 | ClosureHeader; | 524 | ClosureHeader; |
304 | struct Proto *p; | 525 | struct Proto *p; |
305 | UpVal *upvals[1]; | 526 | UpVal *upvals[1]; /* list of upvalues */ |
306 | } LClosure; | 527 | } LClosure; |
307 | 528 | ||
308 | 529 | ||
@@ -312,8 +533,9 @@ typedef union Closure { | |||
312 | } Closure; | 533 | } Closure; |
313 | 534 | ||
314 | 535 | ||
315 | #define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) | 536 | #define isLfunction(o) ttisLclosure(o) |
316 | #define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) | 537 | |
538 | #define getproto(o) (clLvalue(o)->p) | ||
317 | 539 | ||
318 | 540 | ||
319 | /* | 541 | /* |
@@ -337,7 +559,7 @@ typedef struct Node { | |||
337 | 559 | ||
338 | typedef struct Table { | 560 | typedef struct Table { |
339 | CommonHeader; | 561 | CommonHeader; |
340 | lu_byte flags; /* 1<<p means tagmethod(p) is not present */ | 562 | lu_byte flags; /* 1<<p means tagmethod(p) is not present */ |
341 | lu_byte lsizenode; /* log2 of size of `node' array */ | 563 | lu_byte lsizenode; /* log2 of size of `node' array */ |
342 | struct Table *metatable; | 564 | struct Table *metatable; |
343 | TValue *array; /* array part */ | 565 | TValue *array; /* array part */ |
@@ -360,17 +582,21 @@ typedef struct Table { | |||
360 | #define sizenode(t) (twoto((t)->lsizenode)) | 582 | #define sizenode(t) (twoto((t)->lsizenode)) |
361 | 583 | ||
362 | 584 | ||
585 | /* | ||
586 | ** (address of) a fixed nil value | ||
587 | */ | ||
363 | #define luaO_nilobject (&luaO_nilobject_) | 588 | #define luaO_nilobject (&luaO_nilobject_) |
364 | 589 | ||
365 | LUAI_DATA const TValue luaO_nilobject_; | ||
366 | 590 | ||
367 | #define ceillog2(x) (luaO_log2((x)-1) + 1) | 591 | LUAI_DDEC const TValue luaO_nilobject_; |
592 | |||
368 | 593 | ||
369 | LUAI_FUNC int luaO_log2 (unsigned int x); | ||
370 | LUAI_FUNC int luaO_int2fb (unsigned int x); | 594 | LUAI_FUNC int luaO_int2fb (unsigned int x); |
371 | LUAI_FUNC int luaO_fb2int (int x); | 595 | LUAI_FUNC int luaO_fb2int (int x); |
372 | LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); | 596 | LUAI_FUNC int luaO_ceillog2 (unsigned int x); |
373 | LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); | 597 | LUAI_FUNC lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2); |
598 | LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result); | ||
599 | LUAI_FUNC int luaO_hexavalue (int c); | ||
374 | LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, | 600 | LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, |
375 | va_list argp); | 601 | va_list argp); |
376 | LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); | 602 | LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); |
diff --git a/apps/plugins/lua/lopcodes.c b/apps/plugins/lua/lopcodes.c index 4cc745230b..4190dc7624 100644 --- a/apps/plugins/lua/lopcodes.c +++ b/apps/plugins/lua/lopcodes.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ | 2 | ** $Id: lopcodes.c,v 1.49.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Opcodes for Lua virtual machine | ||
3 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
4 | */ | 5 | */ |
5 | 6 | ||
@@ -13,15 +14,16 @@ | |||
13 | 14 | ||
14 | /* ORDER OP */ | 15 | /* ORDER OP */ |
15 | 16 | ||
16 | const char *const luaP_opnames[NUM_OPCODES+1] = { | 17 | LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { |
17 | "MOVE", | 18 | "MOVE", |
18 | "LOADK", | 19 | "LOADK", |
20 | "LOADKX", | ||
19 | "LOADBOOL", | 21 | "LOADBOOL", |
20 | "LOADNIL", | 22 | "LOADNIL", |
21 | "GETUPVAL", | 23 | "GETUPVAL", |
22 | "GETGLOBAL", | 24 | "GETTABUP", |
23 | "GETTABLE", | 25 | "GETTABLE", |
24 | "SETGLOBAL", | 26 | "SETTABUP", |
25 | "SETUPVAL", | 27 | "SETUPVAL", |
26 | "SETTABLE", | 28 | "SETTABLE", |
27 | "NEWTABLE", | 29 | "NEWTABLE", |
@@ -47,27 +49,29 @@ const char *const luaP_opnames[NUM_OPCODES+1] = { | |||
47 | "RETURN", | 49 | "RETURN", |
48 | "FORLOOP", | 50 | "FORLOOP", |
49 | "FORPREP", | 51 | "FORPREP", |
52 | "TFORCALL", | ||
50 | "TFORLOOP", | 53 | "TFORLOOP", |
51 | "SETLIST", | 54 | "SETLIST", |
52 | "CLOSE", | ||
53 | "CLOSURE", | 55 | "CLOSURE", |
54 | "VARARG", | 56 | "VARARG", |
57 | "EXTRAARG", | ||
55 | NULL | 58 | NULL |
56 | }; | 59 | }; |
57 | 60 | ||
58 | 61 | ||
59 | #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) | 62 | #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) |
60 | 63 | ||
61 | const lu_byte luaP_opmodes[NUM_OPCODES] = { | 64 | LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { |
62 | /* T A B C mode opcode */ | 65 | /* T A B C mode opcode */ |
63 | opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ | 66 | opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ |
64 | ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ | 67 | ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ |
68 | ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ | ||
65 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ | 69 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ |
66 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ | 70 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ |
67 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ | 71 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ |
68 | ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ | 72 | ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ |
69 | ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ | 73 | ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ |
70 | ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ | 74 | ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ |
71 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ | 75 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ |
72 | ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ | 76 | ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ |
73 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ | 77 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ |
@@ -86,17 +90,18 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
86 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ | 90 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ |
87 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ | 91 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ |
88 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ | 92 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ |
89 | ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ | 93 | ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */ |
90 | ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ | 94 | ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ |
91 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ | 95 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ |
92 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ | 96 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ |
93 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ | 97 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ |
94 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ | 98 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ |
95 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ | 99 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ |
96 | ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ | 100 | ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ |
101 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ | ||
97 | ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ | 102 | ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ |
98 | ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ | ||
99 | ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ | 103 | ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ |
100 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ | 104 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ |
105 | ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ | ||
101 | }; | 106 | }; |
102 | 107 | ||
diff --git a/apps/plugins/lua/lopcodes.h b/apps/plugins/lua/lopcodes.h index e1aed0f637..51f5791545 100644 --- a/apps/plugins/lua/lopcodes.h +++ b/apps/plugins/lua/lopcodes.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lopcodes.h,v 1.142.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -17,6 +17,7 @@ | |||
17 | `A' : 8 bits | 17 | `A' : 8 bits |
18 | `B' : 9 bits | 18 | `B' : 9 bits |
19 | `C' : 9 bits | 19 | `C' : 9 bits |
20 | 'Ax' : 26 bits ('A', 'B', and 'C' together) | ||
20 | `Bx' : 18 bits (`B' and `C' together) | 21 | `Bx' : 18 bits (`B' and `C' together) |
21 | `sBx' : signed Bx | 22 | `sBx' : signed Bx |
22 | 23 | ||
@@ -28,7 +29,7 @@ | |||
28 | ===========================================================================*/ | 29 | ===========================================================================*/ |
29 | 30 | ||
30 | 31 | ||
31 | enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ | 32 | enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ |
32 | 33 | ||
33 | 34 | ||
34 | /* | 35 | /* |
@@ -38,6 +39,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ | |||
38 | #define SIZE_B 9 | 39 | #define SIZE_B 9 |
39 | #define SIZE_Bx (SIZE_C + SIZE_B) | 40 | #define SIZE_Bx (SIZE_C + SIZE_B) |
40 | #define SIZE_A 8 | 41 | #define SIZE_A 8 |
42 | #define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A) | ||
41 | 43 | ||
42 | #define SIZE_OP 6 | 44 | #define SIZE_OP 6 |
43 | 45 | ||
@@ -46,6 +48,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ | |||
46 | #define POS_C (POS_A + SIZE_A) | 48 | #define POS_C (POS_A + SIZE_A) |
47 | #define POS_B (POS_C + SIZE_C) | 49 | #define POS_B (POS_C + SIZE_C) |
48 | #define POS_Bx POS_C | 50 | #define POS_Bx POS_C |
51 | #define POS_Ax POS_A | ||
49 | 52 | ||
50 | 53 | ||
51 | /* | 54 | /* |
@@ -61,6 +64,12 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ | |||
61 | #define MAXARG_sBx MAX_INT | 64 | #define MAXARG_sBx MAX_INT |
62 | #endif | 65 | #endif |
63 | 66 | ||
67 | #if SIZE_Ax < LUAI_BITSINT-1 | ||
68 | #define MAXARG_Ax ((1<<SIZE_Ax)-1) | ||
69 | #else | ||
70 | #define MAXARG_Ax MAX_INT | ||
71 | #endif | ||
72 | |||
64 | 73 | ||
65 | #define MAXARG_A ((1<<SIZE_A)-1) | 74 | #define MAXARG_A ((1<<SIZE_A)-1) |
66 | #define MAXARG_B ((1<<SIZE_B)-1) | 75 | #define MAXARG_B ((1<<SIZE_B)-1) |
@@ -68,7 +77,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ | |||
68 | 77 | ||
69 | 78 | ||
70 | /* creates a mask with `n' 1 bits at position `p' */ | 79 | /* creates a mask with `n' 1 bits at position `p' */ |
71 | #define MASK1(n,p) ((~((~(Instruction)0)<<n))<<p) | 80 | #define MASK1(n,p) ((~((~(Instruction)0)<<(n)))<<(p)) |
72 | 81 | ||
73 | /* creates a mask with `n' 0 bits at position `p' */ | 82 | /* creates a mask with `n' 0 bits at position `p' */ |
74 | #define MASK0(n,p) (~MASK1(n,p)) | 83 | #define MASK0(n,p) (~MASK1(n,p)) |
@@ -81,21 +90,24 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ | |||
81 | #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ | 90 | #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ |
82 | ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP)))) | 91 | ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP)))) |
83 | 92 | ||
84 | #define GETARG_A(i) (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0))) | 93 | #define getarg(i,pos,size) (cast(int, ((i)>>pos) & MASK1(size,0))) |
85 | #define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ | 94 | #define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ |
86 | ((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A)))) | 95 | ((cast(Instruction, v)<<pos)&MASK1(size,pos)))) |
87 | 96 | ||
88 | #define GETARG_B(i) (cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0))) | 97 | #define GETARG_A(i) getarg(i, POS_A, SIZE_A) |
89 | #define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ | 98 | #define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A) |
90 | ((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B)))) | ||
91 | 99 | ||
92 | #define GETARG_C(i) (cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0))) | 100 | #define GETARG_B(i) getarg(i, POS_B, SIZE_B) |
93 | #define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ | 101 | #define SETARG_B(i,v) setarg(i, v, POS_B, SIZE_B) |
94 | ((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C)))) | ||
95 | 102 | ||
96 | #define GETARG_Bx(i) (cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0))) | 103 | #define GETARG_C(i) getarg(i, POS_C, SIZE_C) |
97 | #define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ | 104 | #define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C) |
98 | ((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx)))) | 105 | |
106 | #define GETARG_Bx(i) getarg(i, POS_Bx, SIZE_Bx) | ||
107 | #define SETARG_Bx(i,v) setarg(i, v, POS_Bx, SIZE_Bx) | ||
108 | |||
109 | #define GETARG_Ax(i) getarg(i, POS_Ax, SIZE_Ax) | ||
110 | #define SETARG_Ax(i,v) setarg(i, v, POS_Ax, SIZE_Ax) | ||
99 | 111 | ||
100 | #define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx) | 112 | #define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx) |
101 | #define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx)) | 113 | #define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx)) |
@@ -110,6 +122,9 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ | |||
110 | | (cast(Instruction, a)<<POS_A) \ | 122 | | (cast(Instruction, a)<<POS_A) \ |
111 | | (cast(Instruction, bc)<<POS_Bx)) | 123 | | (cast(Instruction, bc)<<POS_Bx)) |
112 | 124 | ||
125 | #define CREATE_Ax(o,a) ((cast(Instruction, o)<<POS_OP) \ | ||
126 | | (cast(Instruction, a)<<POS_Ax)) | ||
127 | |||
113 | 128 | ||
114 | /* | 129 | /* |
115 | ** Macros to operate RK indices | 130 | ** Macros to operate RK indices |
@@ -153,14 +168,15 @@ name args description | |||
153 | ------------------------------------------------------------------------*/ | 168 | ------------------------------------------------------------------------*/ |
154 | OP_MOVE,/* A B R(A) := R(B) */ | 169 | OP_MOVE,/* A B R(A) := R(B) */ |
155 | OP_LOADK,/* A Bx R(A) := Kst(Bx) */ | 170 | OP_LOADK,/* A Bx R(A) := Kst(Bx) */ |
171 | OP_LOADKX,/* A R(A) := Kst(extra arg) */ | ||
156 | OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ | 172 | OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ |
157 | OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */ | 173 | OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */ |
158 | OP_GETUPVAL,/* A B R(A) := UpValue[B] */ | 174 | OP_GETUPVAL,/* A B R(A) := UpValue[B] */ |
159 | 175 | ||
160 | OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */ | 176 | OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */ |
161 | OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ | 177 | OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ |
162 | 178 | ||
163 | OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */ | 179 | OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */ |
164 | OP_SETUPVAL,/* A B UpValue[B] := R(A) */ | 180 | OP_SETUPVAL,/* A B UpValue[B] := R(A) */ |
165 | OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ | 181 | OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ |
166 | 182 | ||
@@ -180,14 +196,13 @@ OP_LEN,/* A B R(A) := length of R(B) */ | |||
180 | 196 | ||
181 | OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ | 197 | OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ |
182 | 198 | ||
183 | OP_JMP,/* sBx pc+=sBx */ | 199 | OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A) + 1 */ |
184 | |||
185 | OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ | 200 | OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ |
186 | OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ | 201 | OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ |
187 | OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ | 202 | OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ |
188 | 203 | ||
189 | OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ | 204 | OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ |
190 | OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ | 205 | OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ |
191 | 206 | ||
192 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ | 207 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ |
193 | OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ | 208 | OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ |
@@ -197,39 +212,44 @@ OP_FORLOOP,/* A sBx R(A)+=R(A+2); | |||
197 | if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/ | 212 | if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/ |
198 | OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */ | 213 | OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */ |
199 | 214 | ||
200 | OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); | 215 | OP_TFORCALL,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */ |
201 | if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */ | 216 | OP_TFORLOOP,/* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/ |
217 | |||
202 | OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ | 218 | OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ |
203 | 219 | ||
204 | OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/ | 220 | OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ |
205 | OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ | 221 | |
222 | OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */ | ||
206 | 223 | ||
207 | OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ | 224 | OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ |
208 | } OpCode; | 225 | } OpCode; |
209 | 226 | ||
210 | 227 | ||
211 | #define NUM_OPCODES (cast(int, OP_VARARG) + 1) | 228 | #define NUM_OPCODES (cast(int, OP_EXTRAARG) + 1) |
212 | 229 | ||
213 | 230 | ||
214 | 231 | ||
215 | /*=========================================================================== | 232 | /*=========================================================================== |
216 | Notes: | 233 | Notes: |
217 | (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, | 234 | (*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then `top' is |
218 | and can be 0: OP_CALL then sets `top' to last_result+1, so | 235 | set to last_result+1, so next open instruction (OP_CALL, OP_RETURN, |
219 | next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. | 236 | OP_SETLIST) may use `top'. |
220 | 237 | ||
221 | (*) In OP_VARARG, if (B == 0) then use actual number of varargs and | 238 | (*) In OP_VARARG, if (B == 0) then use actual number of varargs and |
222 | set top (like in OP_CALL with C == 0). | 239 | set top (like in OP_CALL with C == 0). |
223 | 240 | ||
224 | (*) In OP_RETURN, if (B == 0) then return up to `top' | 241 | (*) In OP_RETURN, if (B == 0) then return up to `top'. |
225 | 242 | ||
226 | (*) In OP_SETLIST, if (B == 0) then B = `top'; | 243 | (*) In OP_SETLIST, if (B == 0) then B = `top'; if (C == 0) then next |
227 | if (C == 0) then next `instruction' is real C | 244 | 'instruction' is EXTRAARG(real C). |
245 | |||
246 | (*) In OP_LOADKX, the next 'instruction' is always EXTRAARG. | ||
228 | 247 | ||
229 | (*) For comparisons, A specifies what condition the test should accept | 248 | (*) For comparisons, A specifies what condition the test should accept |
230 | (true or false). | 249 | (true or false). |
250 | |||
251 | (*) All `skips' (pc++) assume that next instruction is a jump. | ||
231 | 252 | ||
232 | (*) All `skips' (pc++) assume that next instruction is a jump | ||
233 | ===========================================================================*/ | 253 | ===========================================================================*/ |
234 | 254 | ||
235 | 255 | ||
@@ -239,8 +259,8 @@ OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ | |||
239 | ** bits 2-3: C arg mode | 259 | ** bits 2-3: C arg mode |
240 | ** bits 4-5: B arg mode | 260 | ** bits 4-5: B arg mode |
241 | ** bit 6: instruction set register A | 261 | ** bit 6: instruction set register A |
242 | ** bit 7: operator is a test | 262 | ** bit 7: operator is a test (next instruction must be a jump) |
243 | */ | 263 | */ |
244 | 264 | ||
245 | enum OpArgMask { | 265 | enum OpArgMask { |
246 | OpArgN, /* argument is not used */ | 266 | OpArgN, /* argument is not used */ |
@@ -249,7 +269,7 @@ enum OpArgMask { | |||
249 | OpArgK /* argument is a constant or register/constant */ | 269 | OpArgK /* argument is a constant or register/constant */ |
250 | }; | 270 | }; |
251 | 271 | ||
252 | LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; | 272 | LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES]; |
253 | 273 | ||
254 | #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) | 274 | #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) |
255 | #define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) | 275 | #define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) |
@@ -258,7 +278,7 @@ LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; | |||
258 | #define testTMode(m) (luaP_opmodes[m] & (1 << 7)) | 278 | #define testTMode(m) (luaP_opmodes[m] & (1 << 7)) |
259 | 279 | ||
260 | 280 | ||
261 | LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ | 281 | LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ |
262 | 282 | ||
263 | 283 | ||
264 | /* number of list items to accumulate before a SETLIST instruction */ | 284 | /* number of list items to accumulate before a SETLIST instruction */ |
diff --git a/apps/plugins/lua/loslib.c b/apps/plugins/lua/loslib.c index 6cb8c0541b..350e848d38 100644 --- a/apps/plugins/lua/loslib.c +++ b/apps/plugins/lua/loslib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $ | 2 | ** $Id: loslib.c,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Standard Operating System library | 3 | ** Standard Operating System library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -19,31 +19,109 @@ | |||
19 | #include "lualib.h" | 19 | #include "lualib.h" |
20 | 20 | ||
21 | 21 | ||
22 | static int os_pushresult (lua_State *L, int i, const char *filename) { | 22 | /* |
23 | int en = errno; /* calls to Lua API may change this value */ | 23 | ** list of valid conversion specifiers for the 'strftime' function |
24 | if (i) { | 24 | */ |
25 | lua_pushboolean(L, 1); | 25 | #if !defined(LUA_STRFTIMEOPTIONS) |
26 | return 1; | 26 | |
27 | } | 27 | #if !defined(LUA_USE_POSIX) |
28 | #define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } | ||
29 | #else | ||
30 | #define LUA_STRFTIMEOPTIONS \ | ||
31 | { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \ | ||
32 | "", "E", "cCxXyY", \ | ||
33 | "O", "deHImMSuUVwWy" } | ||
34 | #endif | ||
35 | |||
36 | #endif | ||
37 | |||
38 | |||
39 | |||
40 | /* | ||
41 | ** By default, Lua uses tmpnam except when POSIX is available, where it | ||
42 | ** uses mkstemp. | ||
43 | */ | ||
44 | #if defined(LUA_USE_MKSTEMP) | ||
45 | #include <unistd.h> | ||
46 | #define LUA_TMPNAMBUFSIZE 32 | ||
47 | #define lua_tmpnam(b,e) { \ | ||
48 | strcpy(b, "/tmp/lua_XXXXXX"); \ | ||
49 | e = mkstemp(b); \ | ||
50 | if (e != -1) close(e); \ | ||
51 | e = (e == -1); } | ||
52 | |||
53 | #elif !defined(lua_tmpnam) | ||
54 | |||
55 | #define LUA_TMPNAMBUFSIZE L_tmpnam | ||
56 | #define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } | ||
57 | |||
58 | #endif | ||
59 | |||
60 | |||
61 | /* | ||
62 | ** By default, Lua uses gmtime/localtime, except when POSIX is available, | ||
63 | ** where it uses gmtime_r/localtime_r | ||
64 | */ | ||
65 | #if defined(LUA_USE_GMTIME_R) | ||
66 | |||
67 | #define l_gmtime(t,r) gmtime_r(t,r) | ||
68 | #define l_localtime(t,r) localtime_r(t,r) | ||
69 | |||
70 | #elif !defined(l_gmtime) | ||
71 | |||
72 | #define l_gmtime(t,r) ((void)r, gmtime(t)) | ||
73 | #define l_localtime(t,r) ((void)r, localtime(t)) | ||
74 | |||
75 | #endif | ||
76 | |||
77 | |||
78 | |||
79 | static int os_execute (lua_State *L) { | ||
80 | const char *cmd = luaL_optstring(L, 1, NULL); | ||
81 | int stat = -1; | ||
82 | if (cmd != NULL) | ||
83 | return luaL_execresult(L, stat); | ||
28 | else { | 84 | else { |
29 | lua_pushnil(L); | 85 | lua_pushboolean(L, stat); /* true if there is a shell */ |
30 | lua_pushfstring(L, "%s: %s", filename, strerror(en)); | 86 | return 1; |
31 | lua_pushinteger(L, en); | ||
32 | return 3; | ||
33 | } | 87 | } |
34 | } | 88 | } |
35 | 89 | ||
36 | 90 | ||
37 | static int os_remove (lua_State *L) { | 91 | static int os_remove (lua_State *L) { |
38 | const char *filename = luaL_checkstring(L, 1); | 92 | const char *filename = luaL_checkstring(L, 1); |
39 | return os_pushresult(L, rb->remove(filename) == 0, filename); | 93 | return luaL_fileresult(L, rb->remove(filename) == 0, filename); |
40 | } | 94 | } |
41 | 95 | ||
42 | 96 | ||
43 | static int os_rename (lua_State *L) { | 97 | static int os_rename (lua_State *L) { |
44 | const char *fromname = luaL_checkstring(L, 1); | 98 | const char *fromname = luaL_checkstring(L, 1); |
45 | const char *toname = luaL_checkstring(L, 2); | 99 | const char *toname = luaL_checkstring(L, 2); |
46 | return os_pushresult(L, rb->rename(fromname, toname) == 0, fromname); | 100 | return luaL_fileresult(L, rb->rename(fromname, toname) == 0, NULL); |
101 | } | ||
102 | |||
103 | #if 0 | ||
104 | static int os_tmpname (lua_State *L) { | ||
105 | char buff[LUA_TMPNAMBUFSIZE]; | ||
106 | int err; | ||
107 | lua_tmpnam(buff, err); | ||
108 | if (err) | ||
109 | return luaL_error(L, "unable to generate a unique filename"); | ||
110 | lua_pushstring(L, buff); | ||
111 | return 1; | ||
112 | } | ||
113 | #endif | ||
114 | |||
115 | |||
116 | static int os_getenv (lua_State *L) { | ||
117 | lua_pushnil(L); | ||
118 | return 1; | ||
119 | } | ||
120 | |||
121 | |||
122 | static int os_clock (lua_State *L) { | ||
123 | lua_pushnumber(L, 0); | ||
124 | return 1; | ||
47 | } | 125 | } |
48 | 126 | ||
49 | 127 | ||
@@ -67,7 +145,6 @@ static void setboolfield (lua_State *L, const char *key, int value) { | |||
67 | lua_setfield(L, -2, key); | 145 | lua_setfield(L, -2, key); |
68 | } | 146 | } |
69 | 147 | ||
70 | #if CONFIG_RTC | ||
71 | static int getboolfield (lua_State *L, const char *key) { | 148 | static int getboolfield (lua_State *L, const char *key) { |
72 | int res; | 149 | int res; |
73 | lua_getfield(L, -1, key); | 150 | lua_getfield(L, -1, key); |
@@ -78,11 +155,10 @@ static int getboolfield (lua_State *L, const char *key) { | |||
78 | 155 | ||
79 | 156 | ||
80 | static int getfield (lua_State *L, const char *key, int d) { | 157 | static int getfield (lua_State *L, const char *key, int d) { |
81 | int res; | 158 | int res, isnum; |
82 | lua_getfield(L, -1, key); | 159 | lua_getfield(L, -1, key); |
83 | if (lua_isnumber(L, -1)) | 160 | res = (int)lua_tointegerx(L, -1, &isnum); |
84 | res = (int)lua_tointeger(L, -1); | 161 | if (!isnum) { |
85 | else { | ||
86 | if (d < 0) | 162 | if (d < 0) |
87 | return luaL_error(L, "field " LUA_QS " missing in date table", key); | 163 | return luaL_error(L, "field " LUA_QS " missing in date table", key); |
88 | res = d; | 164 | res = d; |
@@ -90,22 +166,42 @@ static int getfield (lua_State *L, const char *key, int d) { | |||
90 | lua_pop(L, 1); | 166 | lua_pop(L, 1); |
91 | return res; | 167 | return res; |
92 | } | 168 | } |
93 | #endif | 169 | |
170 | |||
171 | static const char *checkoption (lua_State *L, const char *conv, char *buff) { | ||
172 | static const char *const options[] = LUA_STRFTIMEOPTIONS; | ||
173 | unsigned int i; | ||
174 | for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) { | ||
175 | if (*conv != '\0' && strchr(options[i], *conv) != NULL) { | ||
176 | buff[1] = *conv; | ||
177 | if (*options[i + 1] == '\0') { /* one-char conversion specifier? */ | ||
178 | buff[2] = '\0'; /* end buffer */ | ||
179 | return conv + 1; | ||
180 | } | ||
181 | else if (*(conv + 1) != '\0' && | ||
182 | strchr(options[i + 1], *(conv + 1)) != NULL) { | ||
183 | buff[2] = *(conv + 1); /* valid two-char conversion specifier */ | ||
184 | buff[3] = '\0'; /* end buffer */ | ||
185 | return conv + 2; | ||
186 | } | ||
187 | } | ||
188 | } | ||
189 | luaL_argerror(L, 1, | ||
190 | lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); | ||
191 | return conv; /* to avoid warnings */ | ||
192 | } | ||
94 | 193 | ||
95 | 194 | ||
96 | static int os_date (lua_State *L) { | 195 | static int os_date (lua_State *L) { |
97 | const char *s = luaL_optstring(L, 1, "%c"); | 196 | const char *s = luaL_optstring(L, 1, "%c"); |
98 | time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, | 197 | time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); |
99 | #if CONFIG_RTC | 198 | struct tm tmr, *stm; |
100 | rb->mktime(rb->get_time()) | 199 | if (*s == '!') { /* UTC? */ |
101 | #else | 200 | stm = l_gmtime(&t, &tmr); |
102 | 0 | ||
103 | #endif | ||
104 | ); | ||
105 | struct tm *stm; | ||
106 | if (*s == '!') /* UTC? */ /* Rockbox doesn't support timezones */ | ||
107 | s++; /* skip `!' */ | 201 | s++; /* skip `!' */ |
108 | stm = gmtime(&t); | 202 | } |
203 | else | ||
204 | stm = l_localtime(&t, &tmr); | ||
109 | if (stm == NULL) /* invalid date? */ | 205 | if (stm == NULL) /* invalid date? */ |
110 | lua_pushnil(L); | 206 | lua_pushnil(L); |
111 | else if (strcmp(s, "*t") == 0) { | 207 | else if (strcmp(s, "*t") == 0) { |
@@ -121,17 +217,17 @@ static int os_date (lua_State *L) { | |||
121 | setboolfield(L, "isdst", stm->tm_isdst); | 217 | setboolfield(L, "isdst", stm->tm_isdst); |
122 | } | 218 | } |
123 | else { | 219 | else { |
124 | char cc[3]; | 220 | char cc[4]; |
125 | luaL_Buffer b; | 221 | luaL_Buffer b; |
126 | cc[0] = '%'; cc[2] = '\0'; | 222 | cc[0] = '%'; |
127 | luaL_buffinit(L, &b); | 223 | luaL_buffinit(L, &b); |
128 | for (; *s; s++) { | 224 | while (*s) { |
129 | if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ | 225 | if (*s != '%') /* no conversion specifier? */ |
130 | luaL_addchar(&b, *s); | 226 | luaL_addchar(&b, *s++); |
131 | else { | 227 | else { |
132 | size_t reslen; | 228 | size_t reslen; |
133 | char buff[200]; /* should be big enough for any conversion result */ | 229 | char buff[200]; /* should be big enough for any conversion result */ |
134 | cc[1] = *(++s); | 230 | s = checkoption(L, s + 1, cc); |
135 | reslen = strftime(buff, sizeof(buff), cc, stm); | 231 | reslen = strftime(buff, sizeof(buff), cc, stm); |
136 | luaL_addlstring(&b, buff, reslen); | 232 | luaL_addlstring(&b, buff, reslen); |
137 | } | 233 | } |
@@ -141,11 +237,11 @@ static int os_date (lua_State *L) { | |||
141 | return 1; | 237 | return 1; |
142 | } | 238 | } |
143 | 239 | ||
240 | |||
144 | static int os_time (lua_State *L) { | 241 | static int os_time (lua_State *L) { |
145 | time_t t = -1; | 242 | time_t t; |
146 | #if CONFIG_RTC | ||
147 | if (lua_isnoneornil(L, 1)) /* called without args? */ | 243 | if (lua_isnoneornil(L, 1)) /* called without args? */ |
148 | t = rb->mktime(rb->get_time()); /* get current time */ | 244 | t = time(NULL); /* get current time */ |
149 | else { | 245 | else { |
150 | struct tm ts; | 246 | struct tm ts; |
151 | luaL_checktype(L, 1, LUA_TTABLE); | 247 | luaL_checktype(L, 1, LUA_TTABLE); |
@@ -157,9 +253,8 @@ static int os_time (lua_State *L) { | |||
157 | ts.tm_mon = getfield(L, "month", -1) - 1; | 253 | ts.tm_mon = getfield(L, "month", -1) - 1; |
158 | ts.tm_year = getfield(L, "year", -1) - 1900; | 254 | ts.tm_year = getfield(L, "year", -1) - 1900; |
159 | ts.tm_isdst = getboolfield(L, "isdst"); | 255 | ts.tm_isdst = getboolfield(L, "isdst"); |
160 | t = rb->mktime(&ts); | 256 | t = mktime(&ts); |
161 | } | 257 | } |
162 | #endif | ||
163 | if (t == (time_t)(-1)) | 258 | if (t == (time_t)(-1)) |
164 | lua_pushnil(L); | 259 | lua_pushnil(L); |
165 | else | 260 | else |
@@ -168,26 +263,54 @@ static int os_time (lua_State *L) { | |||
168 | } | 263 | } |
169 | 264 | ||
170 | 265 | ||
266 | static int os_difftime (lua_State *L) { | ||
267 | lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), | ||
268 | (time_t)(luaL_optnumber(L, 2, 0)))); | ||
269 | return 1; | ||
270 | } | ||
271 | |||
171 | /* }====================================================== */ | 272 | /* }====================================================== */ |
172 | 273 | ||
173 | 274 | ||
275 | #if 0 | ||
276 | static int os_setlocale (lua_State *L) { | ||
277 | static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, | ||
278 | LC_NUMERIC, LC_TIME}; | ||
279 | static const char *const catnames[] = {"all", "collate", "ctype", "monetary", | ||
280 | "numeric", "time", NULL}; | ||
281 | const char *l = luaL_optstring(L, 1, NULL); | ||
282 | int op = luaL_checkoption(L, 2, "all", catnames); | ||
283 | lua_pushstring(L, setlocale(cat[op], l)); | ||
284 | return 1; | ||
285 | } | ||
286 | #endif | ||
287 | |||
288 | |||
174 | static int os_exit (lua_State *L) { | 289 | static int os_exit (lua_State *L) { |
175 | exit(luaL_optint(L, 1, EXIT_SUCCESS)); | 290 | int status; |
176 | return EXIT_SUCCESS; /* never reached, surpress warning */ | 291 | if (lua_isboolean(L, 1)) |
292 | status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); | ||
293 | else | ||
294 | status = luaL_optint(L, 1, EXIT_SUCCESS); | ||
295 | if (lua_toboolean(L, 2)) | ||
296 | lua_close(L); | ||
297 | if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ | ||
298 | return 0; | ||
177 | } | 299 | } |
178 | 300 | ||
301 | |||
179 | static const luaL_Reg syslib[] = { | 302 | static const luaL_Reg syslib[] = { |
180 | //{"clock", os_clock}, | 303 | {"clock", os_clock}, |
181 | {"date", os_date}, | 304 | {"date", os_date}, |
182 | //{"difftime", os_difftime}, | 305 | {"difftime", os_difftime}, |
183 | //{"execute", os_execute}, | 306 | {"execute", os_execute}, |
184 | {"exit", os_exit}, | 307 | {"exit", os_exit}, |
185 | //{"getenv", os_getenv}, | 308 | {"getenv", os_getenv}, |
186 | {"remove", os_remove}, | 309 | {"remove", os_remove}, |
187 | {"rename", os_rename}, | 310 | {"rename", os_rename}, |
188 | //{"setlocale", os_setlocale}, | 311 | /*{"setlocale", os_setlocale},*/ |
189 | {"time", os_time}, | 312 | {"time", os_time}, |
190 | //{"tmpname", os_tmpname}, | 313 | /*{"tmpname", os_tmpname},*/ |
191 | {NULL, NULL} | 314 | {NULL, NULL} |
192 | }; | 315 | }; |
193 | 316 | ||
@@ -195,8 +318,8 @@ static const luaL_Reg syslib[] = { | |||
195 | 318 | ||
196 | 319 | ||
197 | 320 | ||
198 | LUALIB_API int luaopen_os (lua_State *L) { | 321 | LUAMOD_API int luaopen_os (lua_State *L) { |
199 | luaL_register(L, LUA_OSLIBNAME, syslib); | 322 | luaL_newlib(L, syslib); |
200 | return 1; | 323 | return 1; |
201 | } | 324 | } |
202 | 325 | ||
diff --git a/apps/plugins/lua/lparser.c b/apps/plugins/lua/lparser.c index 800cdb1a3b..9e1a9ca2cf 100644 --- a/apps/plugins/lua/lparser.c +++ b/apps/plugins/lua/lparser.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $ | 2 | ** $Id: lparser.c,v 2.130.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -27,11 +27,13 @@ | |||
27 | 27 | ||
28 | 28 | ||
29 | 29 | ||
30 | #define hasmultret(k) ((k) == VCALL || (k) == VVARARG) | 30 | /* maximum number of local variables per function (must be smaller |
31 | than 250, due to the bytecode format) */ | ||
32 | #define MAXVARS 200 | ||
33 | |||
31 | 34 | ||
32 | #define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) | 35 | #define hasmultret(k) ((k) == VCALL || (k) == VVARARG) |
33 | 36 | ||
34 | #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) | ||
35 | 37 | ||
36 | 38 | ||
37 | /* | 39 | /* |
@@ -39,10 +41,11 @@ | |||
39 | */ | 41 | */ |
40 | typedef struct BlockCnt { | 42 | typedef struct BlockCnt { |
41 | struct BlockCnt *previous; /* chain */ | 43 | struct BlockCnt *previous; /* chain */ |
42 | int breaklist; /* list of jumps out of this loop */ | 44 | short firstlabel; /* index of first label in this block */ |
43 | lu_byte nactvar; /* # active locals outside the breakable structure */ | 45 | short firstgoto; /* index of first pending goto in this block */ |
46 | lu_byte nactvar; /* # active locals outside the block */ | ||
44 | lu_byte upval; /* true if some variable in the block is an upvalue */ | 47 | lu_byte upval; /* true if some variable in the block is an upvalue */ |
45 | lu_byte isbreakable; /* true if `block' is a loop */ | 48 | lu_byte isloop; /* true if `block' is a loop */ |
46 | } BlockCnt; | 49 | } BlockCnt; |
47 | 50 | ||
48 | 51 | ||
@@ -50,11 +53,13 @@ typedef struct BlockCnt { | |||
50 | /* | 53 | /* |
51 | ** prototypes for recursive non-terminal functions | 54 | ** prototypes for recursive non-terminal functions |
52 | */ | 55 | */ |
53 | static void chunk (LexState *ls); | 56 | static void statement (LexState *ls); |
54 | static void expr (LexState *ls, expdesc *v); | 57 | static void expr (LexState *ls, expdesc *v); |
55 | 58 | ||
56 | 59 | ||
57 | static void anchor_token (LexState *ls) { | 60 | static void anchor_token (LexState *ls) { |
61 | /* last token from outer function must be EOS */ | ||
62 | lua_assert(ls->fs != NULL || ls->t.token == TK_EOS); | ||
58 | if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { | 63 | if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { |
59 | TString *ts = ls->t.seminfo.ts; | 64 | TString *ts = ls->t.seminfo.ts; |
60 | luaX_newstring(ls, getstr(ts), ts->tsv.len); | 65 | luaX_newstring(ls, getstr(ts), ts->tsv.len); |
@@ -62,18 +67,34 @@ static void anchor_token (LexState *ls) { | |||
62 | } | 67 | } |
63 | 68 | ||
64 | 69 | ||
65 | static void error_expected (LexState *ls, int token) { | 70 | /* semantic error */ |
71 | static l_noret semerror (LexState *ls, const char *msg) { | ||
72 | ls->t.token = 0; /* remove 'near to' from final message */ | ||
73 | luaX_syntaxerror(ls, msg); | ||
74 | } | ||
75 | |||
76 | |||
77 | static l_noret error_expected (LexState *ls, int token) { | ||
66 | luaX_syntaxerror(ls, | 78 | luaX_syntaxerror(ls, |
67 | luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); | 79 | luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); |
80 | } | ||
81 | |||
82 | |||
83 | static l_noret errorlimit (FuncState *fs, int limit, const char *what) { | ||
84 | lua_State *L = fs->ls->L; | ||
85 | const char *msg; | ||
86 | int line = fs->f->linedefined; | ||
87 | const char *where = (line == 0) | ||
88 | ? "main function" | ||
89 | : luaO_pushfstring(L, "function at line %d", line); | ||
90 | msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", | ||
91 | what, limit, where); | ||
92 | luaX_syntaxerror(fs->ls, msg); | ||
68 | } | 93 | } |
69 | 94 | ||
70 | 95 | ||
71 | static void errorlimit (FuncState *fs, int limit, const char *what) { | 96 | static void checklimit (FuncState *fs, int v, int l, const char *what) { |
72 | const char *msg = (fs->f->linedefined == 0) ? | 97 | if (v > l) errorlimit(fs, l, what); |
73 | luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : | ||
74 | luaO_pushfstring(fs->L, "function at line %d has more than %d %s", | ||
75 | fs->f->linedefined, limit, what); | ||
76 | luaX_lexerror(fs->ls, msg, 0); | ||
77 | } | 98 | } |
78 | 99 | ||
79 | 100 | ||
@@ -91,6 +112,7 @@ static void check (LexState *ls, int c) { | |||
91 | error_expected(ls, c); | 112 | error_expected(ls, c); |
92 | } | 113 | } |
93 | 114 | ||
115 | |||
94 | static void checknext (LexState *ls, int c) { | 116 | static void checknext (LexState *ls, int c) { |
95 | check(ls, c); | 117 | check(ls, c); |
96 | luaX_next(ls); | 118 | luaX_next(ls); |
@@ -107,7 +129,7 @@ static void check_match (LexState *ls, int what, int who, int where) { | |||
107 | error_expected(ls, what); | 129 | error_expected(ls, what); |
108 | else { | 130 | else { |
109 | luaX_syntaxerror(ls, luaO_pushfstring(ls->L, | 131 | luaX_syntaxerror(ls, luaO_pushfstring(ls->L, |
110 | LUA_QS " expected (to close " LUA_QS " at line %d)", | 132 | "%s expected (to close %s at line %d)", |
111 | luaX_token2str(ls, what), luaX_token2str(ls, who), where)); | 133 | luaX_token2str(ls, what), luaX_token2str(ls, who), where)); |
112 | } | 134 | } |
113 | } | 135 | } |
@@ -126,7 +148,7 @@ static TString *str_checkname (LexState *ls) { | |||
126 | static void init_exp (expdesc *e, expkind k, int i) { | 148 | static void init_exp (expdesc *e, expkind k, int i) { |
127 | e->f = e->t = NO_JUMP; | 149 | e->f = e->t = NO_JUMP; |
128 | e->k = k; | 150 | e->k = k; |
129 | e->u.s.info = i; | 151 | e->u.info = i; |
130 | } | 152 | } |
131 | 153 | ||
132 | 154 | ||
@@ -135,7 +157,7 @@ static void codestring (LexState *ls, expdesc *e, TString *s) { | |||
135 | } | 157 | } |
136 | 158 | ||
137 | 159 | ||
138 | static void checkname(LexState *ls, expdesc *e) { | 160 | static void checkname (LexState *ls, expdesc *e) { |
139 | codestring(ls, e, str_checkname(ls)); | 161 | codestring(ls, e, str_checkname(ls)); |
140 | } | 162 | } |
141 | 163 | ||
@@ -145,7 +167,7 @@ static int registerlocalvar (LexState *ls, TString *varname) { | |||
145 | Proto *f = fs->f; | 167 | Proto *f = fs->f; |
146 | int oldsize = f->sizelocvars; | 168 | int oldsize = f->sizelocvars; |
147 | luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, | 169 | luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, |
148 | LocVar, SHRT_MAX, "too many local variables"); | 170 | LocVar, SHRT_MAX, "local variables"); |
149 | while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; | 171 | while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; |
150 | f->locvars[fs->nlocvars].varname = varname; | 172 | f->locvars[fs->nlocvars].varname = varname; |
151 | luaC_objbarrier(ls->L, f, varname); | 173 | luaC_objbarrier(ls->L, f, varname); |
@@ -153,14 +175,30 @@ static int registerlocalvar (LexState *ls, TString *varname) { | |||
153 | } | 175 | } |
154 | 176 | ||
155 | 177 | ||
156 | #define new_localvarliteral(ls,v,n) \ | 178 | static void new_localvar (LexState *ls, TString *name) { |
157 | new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) | 179 | FuncState *fs = ls->fs; |
180 | Dyndata *dyd = ls->dyd; | ||
181 | int reg = registerlocalvar(ls, name); | ||
182 | checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, | ||
183 | MAXVARS, "local variables"); | ||
184 | luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, | ||
185 | dyd->actvar.size, Vardesc, MAX_INT, "local variables"); | ||
186 | dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); | ||
187 | } | ||
158 | 188 | ||
159 | 189 | ||
160 | static void new_localvar (LexState *ls, TString *name, int n) { | 190 | static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { |
161 | FuncState *fs = ls->fs; | 191 | new_localvar(ls, luaX_newstring(ls, name, sz)); |
162 | luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); | 192 | } |
163 | fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); | 193 | |
194 | #define new_localvarliteral(ls,v) \ | ||
195 | new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) | ||
196 | |||
197 | |||
198 | static LocVar *getlocvar (FuncState *fs, int i) { | ||
199 | int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; | ||
200 | lua_assert(idx < fs->nlocvars); | ||
201 | return &fs->f->locvars[idx]; | ||
164 | } | 202 | } |
165 | 203 | ||
166 | 204 | ||
@@ -168,77 +206,88 @@ static void adjustlocalvars (LexState *ls, int nvars) { | |||
168 | FuncState *fs = ls->fs; | 206 | FuncState *fs = ls->fs; |
169 | fs->nactvar = cast_byte(fs->nactvar + nvars); | 207 | fs->nactvar = cast_byte(fs->nactvar + nvars); |
170 | for (; nvars; nvars--) { | 208 | for (; nvars; nvars--) { |
171 | getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; | 209 | getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; |
172 | } | 210 | } |
173 | } | 211 | } |
174 | 212 | ||
175 | 213 | ||
176 | static void removevars (LexState *ls, int tolevel) { | 214 | static void removevars (FuncState *fs, int tolevel) { |
177 | FuncState *fs = ls->fs; | 215 | fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); |
178 | while (fs->nactvar > tolevel) | 216 | while (fs->nactvar > tolevel) |
179 | getlocvar(fs, --fs->nactvar).endpc = fs->pc; | 217 | getlocvar(fs, --fs->nactvar)->endpc = fs->pc; |
180 | } | 218 | } |
181 | 219 | ||
182 | 220 | ||
183 | static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { | 221 | static int searchupvalue (FuncState *fs, TString *name) { |
184 | int i; | 222 | int i; |
223 | Upvaldesc *up = fs->f->upvalues; | ||
224 | for (i = 0; i < fs->nups; i++) { | ||
225 | if (luaS_eqstr(up[i].name, name)) return i; | ||
226 | } | ||
227 | return -1; /* not found */ | ||
228 | } | ||
229 | |||
230 | |||
231 | static int newupvalue (FuncState *fs, TString *name, expdesc *v) { | ||
185 | Proto *f = fs->f; | 232 | Proto *f = fs->f; |
186 | int oldsize = f->sizeupvalues; | 233 | int oldsize = f->sizeupvalues; |
187 | for (i=0; i<f->nups; i++) { | 234 | checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); |
188 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { | 235 | luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, |
189 | lua_assert(f->upvalues[i] == name); | 236 | Upvaldesc, MAXUPVAL, "upvalues"); |
190 | return i; | 237 | while (oldsize < f->sizeupvalues) f->upvalues[oldsize++].name = NULL; |
191 | } | 238 | f->upvalues[fs->nups].instack = (v->k == VLOCAL); |
192 | } | 239 | f->upvalues[fs->nups].idx = cast_byte(v->u.info); |
193 | /* new one */ | 240 | f->upvalues[fs->nups].name = name; |
194 | luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); | 241 | luaC_objbarrier(fs->ls->L, f, name); |
195 | luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, | 242 | return fs->nups++; |
196 | TString *, MAX_INT, ""); | ||
197 | while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; | ||
198 | f->upvalues[f->nups] = name; | ||
199 | luaC_objbarrier(fs->L, f, name); | ||
200 | lua_assert(v->k == VLOCAL || v->k == VUPVAL); | ||
201 | fs->upvalues[f->nups].k = cast_byte(v->k); | ||
202 | fs->upvalues[f->nups].info = cast_byte(v->u.s.info); | ||
203 | return f->nups++; | ||
204 | } | 243 | } |
205 | 244 | ||
206 | 245 | ||
207 | static int searchvar (FuncState *fs, TString *n) { | 246 | static int searchvar (FuncState *fs, TString *n) { |
208 | int i; | 247 | int i; |
209 | for (i=fs->nactvar-1; i >= 0; i--) { | 248 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { |
210 | if (n == getlocvar(fs, i).varname) | 249 | if (luaS_eqstr(n, getlocvar(fs, i)->varname)) |
211 | return i; | 250 | return i; |
212 | } | 251 | } |
213 | return -1; /* not found */ | 252 | return -1; /* not found */ |
214 | } | 253 | } |
215 | 254 | ||
216 | 255 | ||
256 | /* | ||
257 | Mark block where variable at given level was defined | ||
258 | (to emit close instructions later). | ||
259 | */ | ||
217 | static void markupval (FuncState *fs, int level) { | 260 | static void markupval (FuncState *fs, int level) { |
218 | BlockCnt *bl = fs->bl; | 261 | BlockCnt *bl = fs->bl; |
219 | while (bl && bl->nactvar > level) bl = bl->previous; | 262 | while (bl->nactvar > level) bl = bl->previous; |
220 | if (bl) bl->upval = 1; | 263 | bl->upval = 1; |
221 | } | 264 | } |
222 | 265 | ||
223 | 266 | ||
267 | /* | ||
268 | Find variable with given name 'n'. If it is an upvalue, add this | ||
269 | upvalue into all intermediate functions. | ||
270 | */ | ||
224 | static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | 271 | static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { |
225 | if (fs == NULL) { /* no more levels? */ | 272 | if (fs == NULL) /* no more levels? */ |
226 | init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ | 273 | return VVOID; /* default is global */ |
227 | return VGLOBAL; | ||
228 | } | ||
229 | else { | 274 | else { |
230 | int v = searchvar(fs, n); /* look up at current level */ | 275 | int v = searchvar(fs, n); /* look up locals at current level */ |
231 | if (v >= 0) { | 276 | if (v >= 0) { /* found? */ |
232 | init_exp(var, VLOCAL, v); | 277 | init_exp(var, VLOCAL, v); /* variable is local */ |
233 | if (!base) | 278 | if (!base) |
234 | markupval(fs, v); /* local will be used as an upval */ | 279 | markupval(fs, v); /* local will be used as an upval */ |
235 | return VLOCAL; | 280 | return VLOCAL; |
236 | } | 281 | } |
237 | else { /* not found at current level; try upper one */ | 282 | else { /* not found as local at current level; try upvalues */ |
238 | if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) | 283 | int idx = searchupvalue(fs, n); /* try existing upvalues */ |
239 | return VGLOBAL; | 284 | if (idx < 0) { /* not found? */ |
240 | var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ | 285 | if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */ |
241 | var->k = VUPVAL; /* upvalue in this level */ | 286 | return VVOID; /* not found; is a global */ |
287 | /* else was LOCAL or UPVAL */ | ||
288 | idx = newupvalue(fs, n, var); /* will be a new upvalue */ | ||
289 | } | ||
290 | init_exp(var, VUPVAL, idx); | ||
242 | return VUPVAL; | 291 | return VUPVAL; |
243 | } | 292 | } |
244 | } | 293 | } |
@@ -248,8 +297,13 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | |||
248 | static void singlevar (LexState *ls, expdesc *var) { | 297 | static void singlevar (LexState *ls, expdesc *var) { |
249 | TString *varname = str_checkname(ls); | 298 | TString *varname = str_checkname(ls); |
250 | FuncState *fs = ls->fs; | 299 | FuncState *fs = ls->fs; |
251 | if (singlevaraux(fs, varname, var, 1) == VGLOBAL) | 300 | if (singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */ |
252 | var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ | 301 | expdesc key; |
302 | singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ | ||
303 | lua_assert(var->k == VLOCAL || var->k == VUPVAL); | ||
304 | codestring(ls, &key, varname); /* key is variable name */ | ||
305 | luaK_indexed(fs, var, &key); /* env[varname] */ | ||
306 | } | ||
253 | } | 307 | } |
254 | 308 | ||
255 | 309 | ||
@@ -274,18 +328,118 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | |||
274 | 328 | ||
275 | 329 | ||
276 | static void enterlevel (LexState *ls) { | 330 | static void enterlevel (LexState *ls) { |
277 | if (++ls->L->nCcalls > LUAI_MAXCCALLS) | 331 | lua_State *L = ls->L; |
278 | luaX_lexerror(ls, "chunk has too many syntax levels", 0); | 332 | ++L->nCcalls; |
333 | checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); | ||
279 | } | 334 | } |
280 | 335 | ||
281 | 336 | ||
282 | #define leavelevel(ls) ((ls)->L->nCcalls--) | 337 | #define leavelevel(ls) ((ls)->L->nCcalls--) |
283 | 338 | ||
284 | 339 | ||
285 | static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { | 340 | static void closegoto (LexState *ls, int g, Labeldesc *label) { |
286 | bl->breaklist = NO_JUMP; | 341 | int i; |
287 | bl->isbreakable = isbreakable; | 342 | FuncState *fs = ls->fs; |
343 | Labellist *gl = &ls->dyd->gt; | ||
344 | Labeldesc *gt = &gl->arr[g]; | ||
345 | lua_assert(luaS_eqstr(gt->name, label->name)); | ||
346 | if (gt->nactvar < label->nactvar) { | ||
347 | TString *vname = getlocvar(fs, gt->nactvar)->varname; | ||
348 | const char *msg = luaO_pushfstring(ls->L, | ||
349 | "<goto %s> at line %d jumps into the scope of local " LUA_QS, | ||
350 | getstr(gt->name), gt->line, getstr(vname)); | ||
351 | semerror(ls, msg); | ||
352 | } | ||
353 | luaK_patchlist(fs, gt->pc, label->pc); | ||
354 | /* remove goto from pending list */ | ||
355 | for (i = g; i < gl->n - 1; i++) | ||
356 | gl->arr[i] = gl->arr[i + 1]; | ||
357 | gl->n--; | ||
358 | } | ||
359 | |||
360 | |||
361 | /* | ||
362 | ** try to close a goto with existing labels; this solves backward jumps | ||
363 | */ | ||
364 | static int findlabel (LexState *ls, int g) { | ||
365 | int i; | ||
366 | BlockCnt *bl = ls->fs->bl; | ||
367 | Dyndata *dyd = ls->dyd; | ||
368 | Labeldesc *gt = &dyd->gt.arr[g]; | ||
369 | /* check labels in current block for a match */ | ||
370 | for (i = bl->firstlabel; i < dyd->label.n; i++) { | ||
371 | Labeldesc *lb = &dyd->label.arr[i]; | ||
372 | if (luaS_eqstr(lb->name, gt->name)) { /* correct label? */ | ||
373 | if (gt->nactvar > lb->nactvar && | ||
374 | (bl->upval || dyd->label.n > bl->firstlabel)) | ||
375 | luaK_patchclose(ls->fs, gt->pc, lb->nactvar); | ||
376 | closegoto(ls, g, lb); /* close it */ | ||
377 | return 1; | ||
378 | } | ||
379 | } | ||
380 | return 0; /* label not found; cannot close goto */ | ||
381 | } | ||
382 | |||
383 | |||
384 | static int newlabelentry (LexState *ls, Labellist *l, TString *name, | ||
385 | int line, int pc) { | ||
386 | int n = l->n; | ||
387 | luaM_growvector(ls->L, l->arr, n, l->size, | ||
388 | Labeldesc, SHRT_MAX, "labels/gotos"); | ||
389 | l->arr[n].name = name; | ||
390 | l->arr[n].line = line; | ||
391 | l->arr[n].nactvar = ls->fs->nactvar; | ||
392 | l->arr[n].pc = pc; | ||
393 | l->n++; | ||
394 | return n; | ||
395 | } | ||
396 | |||
397 | |||
398 | /* | ||
399 | ** check whether new label 'lb' matches any pending gotos in current | ||
400 | ** block; solves forward jumps | ||
401 | */ | ||
402 | static void findgotos (LexState *ls, Labeldesc *lb) { | ||
403 | Labellist *gl = &ls->dyd->gt; | ||
404 | int i = ls->fs->bl->firstgoto; | ||
405 | while (i < gl->n) { | ||
406 | if (luaS_eqstr(gl->arr[i].name, lb->name)) | ||
407 | closegoto(ls, i, lb); | ||
408 | else | ||
409 | i++; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | |||
414 | /* | ||
415 | ** "export" pending gotos to outer level, to check them against | ||
416 | ** outer labels; if the block being exited has upvalues, and | ||
417 | ** the goto exits the scope of any variable (which can be the | ||
418 | ** upvalue), close those variables being exited. | ||
419 | */ | ||
420 | static void movegotosout (FuncState *fs, BlockCnt *bl) { | ||
421 | int i = bl->firstgoto; | ||
422 | Labellist *gl = &fs->ls->dyd->gt; | ||
423 | /* correct pending gotos to current block and try to close it | ||
424 | with visible labels */ | ||
425 | while (i < gl->n) { | ||
426 | Labeldesc *gt = &gl->arr[i]; | ||
427 | if (gt->nactvar > bl->nactvar) { | ||
428 | if (bl->upval) | ||
429 | luaK_patchclose(fs, gt->pc, bl->nactvar); | ||
430 | gt->nactvar = bl->nactvar; | ||
431 | } | ||
432 | if (!findlabel(fs->ls, i)) | ||
433 | i++; /* move to next one */ | ||
434 | } | ||
435 | } | ||
436 | |||
437 | |||
438 | static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { | ||
439 | bl->isloop = isloop; | ||
288 | bl->nactvar = fs->nactvar; | 440 | bl->nactvar = fs->nactvar; |
441 | bl->firstlabel = fs->ls->dyd->label.n; | ||
442 | bl->firstgoto = fs->ls->dyd->gt.n; | ||
289 | bl->upval = 0; | 443 | bl->upval = 0; |
290 | bl->previous = fs->bl; | 444 | bl->previous = fs->bl; |
291 | fs->bl = bl; | 445 | fs->bl = bl; |
@@ -293,63 +447,108 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { | |||
293 | } | 447 | } |
294 | 448 | ||
295 | 449 | ||
450 | /* | ||
451 | ** create a label named "break" to resolve break statements | ||
452 | */ | ||
453 | static void breaklabel (LexState *ls) { | ||
454 | TString *n = luaS_new(ls->L, "break"); | ||
455 | int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc); | ||
456 | findgotos(ls, &ls->dyd->label.arr[l]); | ||
457 | } | ||
458 | |||
459 | /* | ||
460 | ** generates an error for an undefined 'goto'; choose appropriate | ||
461 | ** message when label name is a reserved word (which can only be 'break') | ||
462 | */ | ||
463 | static l_noret undefgoto (LexState *ls, Labeldesc *gt) { | ||
464 | const char *msg = isreserved(gt->name) | ||
465 | ? "<%s> at line %d not inside a loop" | ||
466 | : "no visible label " LUA_QS " for <goto> at line %d"; | ||
467 | msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); | ||
468 | semerror(ls, msg); | ||
469 | } | ||
470 | |||
471 | |||
296 | static void leaveblock (FuncState *fs) { | 472 | static void leaveblock (FuncState *fs) { |
297 | BlockCnt *bl = fs->bl; | 473 | BlockCnt *bl = fs->bl; |
474 | LexState *ls = fs->ls; | ||
475 | if (bl->previous && bl->upval) { | ||
476 | /* create a 'jump to here' to close upvalues */ | ||
477 | int j = luaK_jump(fs); | ||
478 | luaK_patchclose(fs, j, bl->nactvar); | ||
479 | luaK_patchtohere(fs, j); | ||
480 | } | ||
481 | if (bl->isloop) | ||
482 | breaklabel(ls); /* close pending breaks */ | ||
298 | fs->bl = bl->previous; | 483 | fs->bl = bl->previous; |
299 | removevars(fs->ls, bl->nactvar); | 484 | removevars(fs, bl->nactvar); |
300 | if (bl->upval) | ||
301 | luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); | ||
302 | /* a block either controls scope or breaks (never both) */ | ||
303 | lua_assert(!bl->isbreakable || !bl->upval); | ||
304 | lua_assert(bl->nactvar == fs->nactvar); | 485 | lua_assert(bl->nactvar == fs->nactvar); |
305 | fs->freereg = fs->nactvar; /* free registers */ | 486 | fs->freereg = fs->nactvar; /* free registers */ |
306 | luaK_patchtohere(fs, bl->breaklist); | 487 | ls->dyd->label.n = bl->firstlabel; /* remove local labels */ |
488 | if (bl->previous) /* inner block? */ | ||
489 | movegotosout(fs, bl); /* update pending gotos to outer block */ | ||
490 | else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ | ||
491 | undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ | ||
307 | } | 492 | } |
308 | 493 | ||
309 | 494 | ||
310 | static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { | 495 | /* |
496 | ** adds a new prototype into list of prototypes | ||
497 | */ | ||
498 | static Proto *addprototype (LexState *ls) { | ||
499 | Proto *clp; | ||
500 | lua_State *L = ls->L; | ||
311 | FuncState *fs = ls->fs; | 501 | FuncState *fs = ls->fs; |
312 | Proto *f = fs->f; | 502 | Proto *f = fs->f; /* prototype of current function */ |
313 | int oldsize = f->sizep; | 503 | if (fs->np >= f->sizep) { |
314 | int i; | 504 | int oldsize = f->sizep; |
315 | luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, | 505 | luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); |
316 | MAXARG_Bx, "constant table overflow"); | 506 | while (oldsize < f->sizep) f->p[oldsize++] = NULL; |
317 | while (oldsize < f->sizep) f->p[oldsize++] = NULL; | ||
318 | f->p[fs->np++] = func->f; | ||
319 | luaC_objbarrier(ls->L, f, func->f); | ||
320 | init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); | ||
321 | for (i=0; i<func->f->nups; i++) { | ||
322 | OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; | ||
323 | luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); | ||
324 | } | 507 | } |
508 | f->p[fs->np++] = clp = luaF_newproto(L); | ||
509 | luaC_objbarrier(L, f, clp); | ||
510 | return clp; | ||
325 | } | 511 | } |
326 | 512 | ||
327 | 513 | ||
328 | static void lparser_open_func (LexState *ls, FuncState *fs) { | 514 | /* |
515 | ** codes instruction to create new closure in parent function. | ||
516 | ** The OP_CLOSURE instruction must use the last available register, | ||
517 | ** so that, if it invokes the GC, the GC knows which registers | ||
518 | ** are in use at that time. | ||
519 | */ | ||
520 | static void codeclosure (LexState *ls, expdesc *v) { | ||
521 | FuncState *fs = ls->fs->prev; | ||
522 | init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); | ||
523 | luaK_exp2nextreg(fs, v); /* fix it at the last register */ | ||
524 | } | ||
525 | |||
526 | |||
527 | static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { | ||
329 | lua_State *L = ls->L; | 528 | lua_State *L = ls->L; |
330 | Proto *f = luaF_newproto(L); | 529 | Proto *f; |
331 | fs->f = f; | ||
332 | fs->prev = ls->fs; /* linked list of funcstates */ | 530 | fs->prev = ls->fs; /* linked list of funcstates */ |
333 | fs->ls = ls; | 531 | fs->ls = ls; |
334 | fs->L = L; | ||
335 | ls->fs = fs; | 532 | ls->fs = fs; |
336 | fs->pc = 0; | 533 | fs->pc = 0; |
337 | fs->lasttarget = -1; | 534 | fs->lasttarget = 0; |
338 | fs->jpc = NO_JUMP; | 535 | fs->jpc = NO_JUMP; |
339 | fs->freereg = 0; | 536 | fs->freereg = 0; |
340 | fs->nk = 0; | 537 | fs->nk = 0; |
341 | fs->np = 0; | 538 | fs->np = 0; |
539 | fs->nups = 0; | ||
342 | fs->nlocvars = 0; | 540 | fs->nlocvars = 0; |
343 | fs->nactvar = 0; | 541 | fs->nactvar = 0; |
542 | fs->firstlocal = ls->dyd->actvar.n; | ||
344 | fs->bl = NULL; | 543 | fs->bl = NULL; |
544 | f = fs->f; | ||
345 | f->source = ls->source; | 545 | f->source = ls->source; |
346 | f->maxstacksize = 2; /* registers 0/1 are always valid */ | 546 | f->maxstacksize = 2; /* registers 0/1 are always valid */ |
347 | fs->h = luaH_new(L, 0, 0); | 547 | fs->h = luaH_new(L); |
348 | /* anchor table of constants and prototype (to avoid being collected) */ | 548 | /* anchor table of constants (to avoid being collected) */ |
349 | sethvalue2s(L, L->top, fs->h); | 549 | sethvalue2s(L, L->top, fs->h); |
350 | incr_top(L); | 550 | incr_top(L); |
351 | setptvalue2s(L, L->top, f); | 551 | enterblock(fs, bl, 0); |
352 | incr_top(L); | ||
353 | } | 552 | } |
354 | 553 | ||
355 | 554 | ||
@@ -357,8 +556,8 @@ static void close_func (LexState *ls) { | |||
357 | lua_State *L = ls->L; | 556 | lua_State *L = ls->L; |
358 | FuncState *fs = ls->fs; | 557 | FuncState *fs = ls->fs; |
359 | Proto *f = fs->f; | 558 | Proto *f = fs->f; |
360 | removevars(ls, 0); | ||
361 | luaK_ret(fs, 0, 0); /* final return */ | 559 | luaK_ret(fs, 0, 0); /* final return */ |
560 | leaveblock(fs); | ||
362 | luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); | 561 | luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); |
363 | f->sizecode = fs->pc; | 562 | f->sizecode = fs->pc; |
364 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); | 563 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); |
@@ -369,32 +568,14 @@ static void close_func (LexState *ls) { | |||
369 | f->sizep = fs->np; | 568 | f->sizep = fs->np; |
370 | luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); | 569 | luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); |
371 | f->sizelocvars = fs->nlocvars; | 570 | f->sizelocvars = fs->nlocvars; |
372 | luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); | 571 | luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); |
373 | f->sizeupvalues = f->nups; | 572 | f->sizeupvalues = fs->nups; |
374 | lua_assert(luaG_checkcode(f)); | ||
375 | lua_assert(fs->bl == NULL); | 573 | lua_assert(fs->bl == NULL); |
376 | ls->fs = fs->prev; | 574 | ls->fs = fs->prev; |
377 | L->top -= 2; /* remove table and prototype from the stack */ | 575 | /* last token read was anchored in defunct function; must re-anchor it */ |
378 | /* last token read was anchored in defunct function; must reanchor it */ | 576 | anchor_token(ls); |
379 | if (fs) anchor_token(ls); | 577 | L->top--; /* pop table of constants */ |
380 | } | 578 | luaC_checkGC(L); |
381 | |||
382 | |||
383 | Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { | ||
384 | struct LexState lexstate; | ||
385 | struct FuncState funcstate; | ||
386 | lexstate.buff = buff; | ||
387 | luaX_setinput(L, &lexstate, z, luaS_new(L, name)); | ||
388 | lparser_open_func(&lexstate, &funcstate); | ||
389 | funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ | ||
390 | luaX_next(&lexstate); /* read first token */ | ||
391 | chunk(&lexstate); | ||
392 | check(&lexstate, TK_EOS); | ||
393 | close_func(&lexstate); | ||
394 | lua_assert(funcstate.prev == NULL); | ||
395 | lua_assert(funcstate.f->nups == 0); | ||
396 | lua_assert(lexstate.fs == NULL); | ||
397 | return funcstate.f; | ||
398 | } | 579 | } |
399 | 580 | ||
400 | 581 | ||
@@ -404,11 +585,39 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { | |||
404 | /*============================================================*/ | 585 | /*============================================================*/ |
405 | 586 | ||
406 | 587 | ||
407 | static void field (LexState *ls, expdesc *v) { | 588 | /* |
408 | /* field -> ['.' | ':'] NAME */ | 589 | ** check whether current token is in the follow set of a block. |
590 | ** 'until' closes syntactical blocks, but do not close scope, | ||
591 | ** so it handled in separate. | ||
592 | */ | ||
593 | static int block_follow (LexState *ls, int withuntil) { | ||
594 | switch (ls->t.token) { | ||
595 | case TK_ELSE: case TK_ELSEIF: | ||
596 | case TK_END: case TK_EOS: | ||
597 | return 1; | ||
598 | case TK_UNTIL: return withuntil; | ||
599 | default: return 0; | ||
600 | } | ||
601 | } | ||
602 | |||
603 | |||
604 | static void statlist (LexState *ls) { | ||
605 | /* statlist -> { stat [`;'] } */ | ||
606 | while (!block_follow(ls, 1)) { | ||
607 | if (ls->t.token == TK_RETURN) { | ||
608 | statement(ls); | ||
609 | return; /* 'return' must be last statement */ | ||
610 | } | ||
611 | statement(ls); | ||
612 | } | ||
613 | } | ||
614 | |||
615 | |||
616 | static void fieldsel (LexState *ls, expdesc *v) { | ||
617 | /* fieldsel -> ['.' | ':'] NAME */ | ||
409 | FuncState *fs = ls->fs; | 618 | FuncState *fs = ls->fs; |
410 | expdesc key; | 619 | expdesc key; |
411 | luaK_exp2anyreg(fs, v); | 620 | luaK_exp2anyregup(fs, v); |
412 | luaX_next(ls); /* skip the dot or colon */ | 621 | luaX_next(ls); /* skip the dot or colon */ |
413 | checkname(ls, &key); | 622 | checkname(ls, &key); |
414 | luaK_indexed(fs, v, &key); | 623 | luaK_indexed(fs, v, &key); |
@@ -447,7 +656,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) { | |||
447 | expdesc key, val; | 656 | expdesc key, val; |
448 | int rkkey; | 657 | int rkkey; |
449 | if (ls->t.token == TK_NAME) { | 658 | if (ls->t.token == TK_NAME) { |
450 | luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); | 659 | checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); |
451 | checkname(ls, &key); | 660 | checkname(ls, &key); |
452 | } | 661 | } |
453 | else /* ls->t.token == '[' */ | 662 | else /* ls->t.token == '[' */ |
@@ -456,7 +665,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) { | |||
456 | checknext(ls, '='); | 665 | checknext(ls, '='); |
457 | rkkey = luaK_exp2RK(fs, &key); | 666 | rkkey = luaK_exp2RK(fs, &key); |
458 | expr(ls, &val); | 667 | expr(ls, &val); |
459 | luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); | 668 | luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); |
460 | fs->freereg = reg; /* free registers */ | 669 | fs->freereg = reg; /* free registers */ |
461 | } | 670 | } |
462 | 671 | ||
@@ -466,7 +675,7 @@ static void closelistfield (FuncState *fs, struct ConsControl *cc) { | |||
466 | luaK_exp2nextreg(fs, &cc->v); | 675 | luaK_exp2nextreg(fs, &cc->v); |
467 | cc->v.k = VVOID; | 676 | cc->v.k = VVOID; |
468 | if (cc->tostore == LFIELDS_PER_FLUSH) { | 677 | if (cc->tostore == LFIELDS_PER_FLUSH) { |
469 | luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ | 678 | luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ |
470 | cc->tostore = 0; /* no more items pending */ | 679 | cc->tostore = 0; /* no more items pending */ |
471 | } | 680 | } |
472 | } | 681 | } |
@@ -476,27 +685,51 @@ static void lastlistfield (FuncState *fs, struct ConsControl *cc) { | |||
476 | if (cc->tostore == 0) return; | 685 | if (cc->tostore == 0) return; |
477 | if (hasmultret(cc->v.k)) { | 686 | if (hasmultret(cc->v.k)) { |
478 | luaK_setmultret(fs, &cc->v); | 687 | luaK_setmultret(fs, &cc->v); |
479 | luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); | 688 | luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET); |
480 | cc->na--; /* do not count last expression (unknown number of elements) */ | 689 | cc->na--; /* do not count last expression (unknown number of elements) */ |
481 | } | 690 | } |
482 | else { | 691 | else { |
483 | if (cc->v.k != VVOID) | 692 | if (cc->v.k != VVOID) |
484 | luaK_exp2nextreg(fs, &cc->v); | 693 | luaK_exp2nextreg(fs, &cc->v); |
485 | luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); | 694 | luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); |
486 | } | 695 | } |
487 | } | 696 | } |
488 | 697 | ||
489 | 698 | ||
490 | static void listfield (LexState *ls, struct ConsControl *cc) { | 699 | static void listfield (LexState *ls, struct ConsControl *cc) { |
700 | /* listfield -> exp */ | ||
491 | expr(ls, &cc->v); | 701 | expr(ls, &cc->v); |
492 | luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); | 702 | checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); |
493 | cc->na++; | 703 | cc->na++; |
494 | cc->tostore++; | 704 | cc->tostore++; |
495 | } | 705 | } |
496 | 706 | ||
497 | 707 | ||
708 | static void field (LexState *ls, struct ConsControl *cc) { | ||
709 | /* field -> listfield | recfield */ | ||
710 | switch(ls->t.token) { | ||
711 | case TK_NAME: { /* may be 'listfield' or 'recfield' */ | ||
712 | if (luaX_lookahead(ls) != '=') /* expression? */ | ||
713 | listfield(ls, cc); | ||
714 | else | ||
715 | recfield(ls, cc); | ||
716 | break; | ||
717 | } | ||
718 | case '[': { | ||
719 | recfield(ls, cc); | ||
720 | break; | ||
721 | } | ||
722 | default: { | ||
723 | listfield(ls, cc); | ||
724 | break; | ||
725 | } | ||
726 | } | ||
727 | } | ||
728 | |||
729 | |||
498 | static void constructor (LexState *ls, expdesc *t) { | 730 | static void constructor (LexState *ls, expdesc *t) { |
499 | /* constructor -> ?? */ | 731 | /* constructor -> '{' [ field { sep field } [sep] ] '}' |
732 | sep -> ',' | ';' */ | ||
500 | FuncState *fs = ls->fs; | 733 | FuncState *fs = ls->fs; |
501 | int line = ls->linenumber; | 734 | int line = ls->linenumber; |
502 | int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); | 735 | int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); |
@@ -505,30 +738,13 @@ static void constructor (LexState *ls, expdesc *t) { | |||
505 | cc.t = t; | 738 | cc.t = t; |
506 | init_exp(t, VRELOCABLE, pc); | 739 | init_exp(t, VRELOCABLE, pc); |
507 | init_exp(&cc.v, VVOID, 0); /* no value (yet) */ | 740 | init_exp(&cc.v, VVOID, 0); /* no value (yet) */ |
508 | luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ | 741 | luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ |
509 | checknext(ls, '{'); | 742 | checknext(ls, '{'); |
510 | do { | 743 | do { |
511 | lua_assert(cc.v.k == VVOID || cc.tostore > 0); | 744 | lua_assert(cc.v.k == VVOID || cc.tostore > 0); |
512 | if (ls->t.token == '}') break; | 745 | if (ls->t.token == '}') break; |
513 | closelistfield(fs, &cc); | 746 | closelistfield(fs, &cc); |
514 | switch(ls->t.token) { | 747 | field(ls, &cc); |
515 | case TK_NAME: { /* may be listfields or recfields */ | ||
516 | luaX_lookahead(ls); | ||
517 | if (ls->lookahead.token != '=') /* expression? */ | ||
518 | listfield(ls, &cc); | ||
519 | else | ||
520 | recfield(ls, &cc); | ||
521 | break; | ||
522 | } | ||
523 | case '[': { /* constructor_item -> recfield */ | ||
524 | recfield(ls, &cc); | ||
525 | break; | ||
526 | } | ||
527 | default: { /* constructor_part -> listfield */ | ||
528 | listfield(ls, &cc); | ||
529 | break; | ||
530 | } | ||
531 | } | ||
532 | } while (testnext(ls, ',') || testnext(ls, ';')); | 748 | } while (testnext(ls, ',') || testnext(ls, ';')); |
533 | check_match(ls, '}', '{', line); | 749 | check_match(ls, '}', '{', line); |
534 | lastlistfield(fs, &cc); | 750 | lastlistfield(fs, &cc); |
@@ -550,17 +766,13 @@ static void parlist (LexState *ls) { | |||
550 | do { | 766 | do { |
551 | switch (ls->t.token) { | 767 | switch (ls->t.token) { |
552 | case TK_NAME: { /* param -> NAME */ | 768 | case TK_NAME: { /* param -> NAME */ |
553 | new_localvar(ls, str_checkname(ls), nparams++); | 769 | new_localvar(ls, str_checkname(ls)); |
770 | nparams++; | ||
554 | break; | 771 | break; |
555 | } | 772 | } |
556 | case TK_DOTS: { /* param -> `...' */ | 773 | case TK_DOTS: { /* param -> `...' */ |
557 | luaX_next(ls); | 774 | luaX_next(ls); |
558 | #if defined(LUA_COMPAT_VARARG) | 775 | f->is_vararg = 1; |
559 | /* use `arg' as default name */ | ||
560 | new_localvarliteral(ls, "arg", nparams++); | ||
561 | f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; | ||
562 | #endif | ||
563 | f->is_vararg |= VARARG_ISVARARG; | ||
564 | break; | 776 | break; |
565 | } | 777 | } |
566 | default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected"); | 778 | default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected"); |
@@ -568,33 +780,35 @@ static void parlist (LexState *ls) { | |||
568 | } while (!f->is_vararg && testnext(ls, ',')); | 780 | } while (!f->is_vararg && testnext(ls, ',')); |
569 | } | 781 | } |
570 | adjustlocalvars(ls, nparams); | 782 | adjustlocalvars(ls, nparams); |
571 | f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); | 783 | f->numparams = cast_byte(fs->nactvar); |
572 | luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ | 784 | luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ |
573 | } | 785 | } |
574 | 786 | ||
575 | 787 | ||
576 | static void body (LexState *ls, expdesc *e, int needself, int line) { | 788 | static void body (LexState *ls, expdesc *e, int ismethod, int line) { |
577 | /* body -> `(' parlist `)' chunk END */ | 789 | /* body -> `(' parlist `)' block END */ |
578 | FuncState new_fs; | 790 | FuncState new_fs; |
579 | lparser_open_func(ls, &new_fs); | 791 | BlockCnt bl; |
792 | new_fs.f = addprototype(ls); | ||
580 | new_fs.f->linedefined = line; | 793 | new_fs.f->linedefined = line; |
794 | open_func(ls, &new_fs, &bl); | ||
581 | checknext(ls, '('); | 795 | checknext(ls, '('); |
582 | if (needself) { | 796 | if (ismethod) { |
583 | new_localvarliteral(ls, "self", 0); | 797 | new_localvarliteral(ls, "self"); /* create 'self' parameter */ |
584 | adjustlocalvars(ls, 1); | 798 | adjustlocalvars(ls, 1); |
585 | } | 799 | } |
586 | parlist(ls); | 800 | parlist(ls); |
587 | checknext(ls, ')'); | 801 | checknext(ls, ')'); |
588 | chunk(ls); | 802 | statlist(ls); |
589 | new_fs.f->lastlinedefined = ls->linenumber; | 803 | new_fs.f->lastlinedefined = ls->linenumber; |
590 | check_match(ls, TK_END, TK_FUNCTION, line); | 804 | check_match(ls, TK_END, TK_FUNCTION, line); |
805 | codeclosure(ls, e); | ||
591 | close_func(ls); | 806 | close_func(ls); |
592 | pushclosure(ls, &new_fs, e); | ||
593 | } | 807 | } |
594 | 808 | ||
595 | 809 | ||
596 | static int explist1 (LexState *ls, expdesc *v) { | 810 | static int explist (LexState *ls, expdesc *v) { |
597 | /* explist1 -> expr { `,' expr } */ | 811 | /* explist -> expr { `,' expr } */ |
598 | int n = 1; /* at least one expression */ | 812 | int n = 1; /* at least one expression */ |
599 | expr(ls, v); | 813 | expr(ls, v); |
600 | while (testnext(ls, ',')) { | 814 | while (testnext(ls, ',')) { |
@@ -606,20 +820,17 @@ static int explist1 (LexState *ls, expdesc *v) { | |||
606 | } | 820 | } |
607 | 821 | ||
608 | 822 | ||
609 | static void funcargs (LexState *ls, expdesc *f) { | 823 | static void funcargs (LexState *ls, expdesc *f, int line) { |
610 | FuncState *fs = ls->fs; | 824 | FuncState *fs = ls->fs; |
611 | expdesc args; | 825 | expdesc args; |
612 | int base, nparams; | 826 | int base, nparams; |
613 | int line = ls->linenumber; | ||
614 | switch (ls->t.token) { | 827 | switch (ls->t.token) { |
615 | case '(': { /* funcargs -> `(' [ explist1 ] `)' */ | 828 | case '(': { /* funcargs -> `(' [ explist ] `)' */ |
616 | if (line != ls->lastline) | ||
617 | luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); | ||
618 | luaX_next(ls); | 829 | luaX_next(ls); |
619 | if (ls->t.token == ')') /* arg list is empty? */ | 830 | if (ls->t.token == ')') /* arg list is empty? */ |
620 | args.k = VVOID; | 831 | args.k = VVOID; |
621 | else { | 832 | else { |
622 | explist1(ls, &args); | 833 | explist(ls, &args); |
623 | luaK_setmultret(fs, &args); | 834 | luaK_setmultret(fs, &args); |
624 | } | 835 | } |
625 | check_match(ls, ')', '(', line); | 836 | check_match(ls, ')', '(', line); |
@@ -636,11 +847,10 @@ static void funcargs (LexState *ls, expdesc *f) { | |||
636 | } | 847 | } |
637 | default: { | 848 | default: { |
638 | luaX_syntaxerror(ls, "function arguments expected"); | 849 | luaX_syntaxerror(ls, "function arguments expected"); |
639 | return; | ||
640 | } | 850 | } |
641 | } | 851 | } |
642 | lua_assert(f->k == VNONRELOC); | 852 | lua_assert(f->k == VNONRELOC); |
643 | base = f->u.s.info; /* base register for call */ | 853 | base = f->u.info; /* base register for call */ |
644 | if (hasmultret(args.k)) | 854 | if (hasmultret(args.k)) |
645 | nparams = LUA_MULTRET; /* open call */ | 855 | nparams = LUA_MULTRET; /* open call */ |
646 | else { | 856 | else { |
@@ -664,8 +874,8 @@ static void funcargs (LexState *ls, expdesc *f) { | |||
664 | */ | 874 | */ |
665 | 875 | ||
666 | 876 | ||
667 | static void prefixexp (LexState *ls, expdesc *v) { | 877 | static void primaryexp (LexState *ls, expdesc *v) { |
668 | /* prefixexp -> NAME | '(' expr ')' */ | 878 | /* primaryexp -> NAME | '(' expr ')' */ |
669 | switch (ls->t.token) { | 879 | switch (ls->t.token) { |
670 | case '(': { | 880 | case '(': { |
671 | int line = ls->linenumber; | 881 | int line = ls->linenumber; |
@@ -681,26 +891,26 @@ static void prefixexp (LexState *ls, expdesc *v) { | |||
681 | } | 891 | } |
682 | default: { | 892 | default: { |
683 | luaX_syntaxerror(ls, "unexpected symbol"); | 893 | luaX_syntaxerror(ls, "unexpected symbol"); |
684 | return; | ||
685 | } | 894 | } |
686 | } | 895 | } |
687 | } | 896 | } |
688 | 897 | ||
689 | 898 | ||
690 | static void primaryexp (LexState *ls, expdesc *v) { | 899 | static void suffixedexp (LexState *ls, expdesc *v) { |
691 | /* primaryexp -> | 900 | /* suffixedexp -> |
692 | prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ | 901 | primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ |
693 | FuncState *fs = ls->fs; | 902 | FuncState *fs = ls->fs; |
694 | prefixexp(ls, v); | 903 | int line = ls->linenumber; |
904 | primaryexp(ls, v); | ||
695 | for (;;) { | 905 | for (;;) { |
696 | switch (ls->t.token) { | 906 | switch (ls->t.token) { |
697 | case '.': { /* field */ | 907 | case '.': { /* fieldsel */ |
698 | field(ls, v); | 908 | fieldsel(ls, v); |
699 | break; | 909 | break; |
700 | } | 910 | } |
701 | case '[': { /* `[' exp1 `]' */ | 911 | case '[': { /* `[' exp1 `]' */ |
702 | expdesc key; | 912 | expdesc key; |
703 | luaK_exp2anyreg(fs, v); | 913 | luaK_exp2anyregup(fs, v); |
704 | yindex(ls, &key); | 914 | yindex(ls, &key); |
705 | luaK_indexed(fs, v, &key); | 915 | luaK_indexed(fs, v, &key); |
706 | break; | 916 | break; |
@@ -710,12 +920,12 @@ static void primaryexp (LexState *ls, expdesc *v) { | |||
710 | luaX_next(ls); | 920 | luaX_next(ls); |
711 | checkname(ls, &key); | 921 | checkname(ls, &key); |
712 | luaK_self(fs, v, &key); | 922 | luaK_self(fs, v, &key); |
713 | funcargs(ls, v); | 923 | funcargs(ls, v, line); |
714 | break; | 924 | break; |
715 | } | 925 | } |
716 | case '(': case TK_STRING: case '{': { /* funcargs */ | 926 | case '(': case TK_STRING: case '{': { /* funcargs */ |
717 | luaK_exp2nextreg(fs, v); | 927 | luaK_exp2nextreg(fs, v); |
718 | funcargs(ls, v); | 928 | funcargs(ls, v, line); |
719 | break; | 929 | break; |
720 | } | 930 | } |
721 | default: return; | 931 | default: return; |
@@ -725,8 +935,8 @@ static void primaryexp (LexState *ls, expdesc *v) { | |||
725 | 935 | ||
726 | 936 | ||
727 | static void simpleexp (LexState *ls, expdesc *v) { | 937 | static void simpleexp (LexState *ls, expdesc *v) { |
728 | /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | | 938 | /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | |
729 | constructor | FUNCTION body | primaryexp */ | 939 | constructor | FUNCTION body | suffixedexp */ |
730 | switch (ls->t.token) { | 940 | switch (ls->t.token) { |
731 | case TK_NUMBER: { | 941 | case TK_NUMBER: { |
732 | init_exp(v, VKNUM, 0); | 942 | init_exp(v, VKNUM, 0); |
@@ -753,7 +963,6 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
753 | FuncState *fs = ls->fs; | 963 | FuncState *fs = ls->fs; |
754 | check_condition(ls, fs->f->is_vararg, | 964 | check_condition(ls, fs->f->is_vararg, |
755 | "cannot use " LUA_QL("...") " outside a vararg function"); | 965 | "cannot use " LUA_QL("...") " outside a vararg function"); |
756 | fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ | ||
757 | init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); | 966 | init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); |
758 | break; | 967 | break; |
759 | } | 968 | } |
@@ -767,7 +976,7 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
767 | return; | 976 | return; |
768 | } | 977 | } |
769 | default: { | 978 | default: { |
770 | primaryexp(ls, v); | 979 | suffixedexp(ls, v); |
771 | return; | 980 | return; |
772 | } | 981 | } |
773 | } | 982 | } |
@@ -811,11 +1020,11 @@ static const struct { | |||
811 | lu_byte left; /* left priority for each binary operator */ | 1020 | lu_byte left; /* left priority for each binary operator */ |
812 | lu_byte right; /* right priority */ | 1021 | lu_byte right; /* right priority */ |
813 | } priority[] = { /* ORDER OPR */ | 1022 | } priority[] = { /* ORDER OPR */ |
814 | {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ | 1023 | {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `*' `/' `%' */ |
815 | {10, 9}, {5, 4}, /* power and concat (right associative) */ | 1024 | {10, 9}, {5, 4}, /* ^, .. (right associative) */ |
816 | {3, 3}, {3, 3}, /* equality and inequality */ | 1025 | {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ |
817 | {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ | 1026 | {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ |
818 | {2, 2}, {1, 1} /* logical (and/or) */ | 1027 | {2, 2}, {1, 1} /* and, or */ |
819 | }; | 1028 | }; |
820 | 1029 | ||
821 | #define UNARY_PRIORITY 8 /* priority for unary operators */ | 1030 | #define UNARY_PRIORITY 8 /* priority for unary operators */ |
@@ -825,15 +1034,16 @@ static const struct { | |||
825 | ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } | 1034 | ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } |
826 | ** where `binop' is any binary operator with a priority higher than `limit' | 1035 | ** where `binop' is any binary operator with a priority higher than `limit' |
827 | */ | 1036 | */ |
828 | static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { | 1037 | static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { |
829 | BinOpr op; | 1038 | BinOpr op; |
830 | UnOpr uop; | 1039 | UnOpr uop; |
831 | enterlevel(ls); | 1040 | enterlevel(ls); |
832 | uop = getunopr(ls->t.token); | 1041 | uop = getunopr(ls->t.token); |
833 | if (uop != OPR_NOUNOPR) { | 1042 | if (uop != OPR_NOUNOPR) { |
1043 | int line = ls->linenumber; | ||
834 | luaX_next(ls); | 1044 | luaX_next(ls); |
835 | subexpr(ls, v, UNARY_PRIORITY); | 1045 | subexpr(ls, v, UNARY_PRIORITY); |
836 | luaK_prefix(ls->fs, uop, v); | 1046 | luaK_prefix(ls->fs, uop, v, line); |
837 | } | 1047 | } |
838 | else simpleexp(ls, v); | 1048 | else simpleexp(ls, v); |
839 | /* expand while operators have priorities higher than `limit' */ | 1049 | /* expand while operators have priorities higher than `limit' */ |
@@ -841,11 +1051,12 @@ static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { | |||
841 | while (op != OPR_NOBINOPR && priority[op].left > limit) { | 1051 | while (op != OPR_NOBINOPR && priority[op].left > limit) { |
842 | expdesc v2; | 1052 | expdesc v2; |
843 | BinOpr nextop; | 1053 | BinOpr nextop; |
1054 | int line = ls->linenumber; | ||
844 | luaX_next(ls); | 1055 | luaX_next(ls); |
845 | luaK_infix(ls->fs, op, v); | 1056 | luaK_infix(ls->fs, op, v); |
846 | /* read sub-expression with higher priority */ | 1057 | /* read sub-expression with higher priority */ |
847 | nextop = subexpr(ls, &v2, priority[op].right); | 1058 | nextop = subexpr(ls, &v2, priority[op].right); |
848 | luaK_posfix(ls->fs, op, v, &v2); | 1059 | luaK_posfix(ls->fs, op, v, &v2, line); |
849 | op = nextop; | 1060 | op = nextop; |
850 | } | 1061 | } |
851 | leavelevel(ls); | 1062 | leavelevel(ls); |
@@ -868,23 +1079,12 @@ static void expr (LexState *ls, expdesc *v) { | |||
868 | */ | 1079 | */ |
869 | 1080 | ||
870 | 1081 | ||
871 | static int block_follow (int token) { | ||
872 | switch (token) { | ||
873 | case TK_ELSE: case TK_ELSEIF: case TK_END: | ||
874 | case TK_UNTIL: case TK_EOS: | ||
875 | return 1; | ||
876 | default: return 0; | ||
877 | } | ||
878 | } | ||
879 | |||
880 | |||
881 | static void block (LexState *ls) { | 1082 | static void block (LexState *ls) { |
882 | /* block -> chunk */ | 1083 | /* block -> statlist */ |
883 | FuncState *fs = ls->fs; | 1084 | FuncState *fs = ls->fs; |
884 | BlockCnt bl; | 1085 | BlockCnt bl; |
885 | enterblock(fs, &bl, 0); | 1086 | enterblock(fs, &bl, 0); |
886 | chunk(ls); | 1087 | statlist(ls); |
887 | lua_assert(bl.breaklist == NO_JUMP); | ||
888 | leaveblock(fs); | 1088 | leaveblock(fs); |
889 | } | 1089 | } |
890 | 1090 | ||
@@ -900,29 +1100,34 @@ struct LHS_assign { | |||
900 | 1100 | ||
901 | 1101 | ||
902 | /* | 1102 | /* |
903 | ** check whether, in an assignment to a local variable, the local variable | 1103 | ** check whether, in an assignment to an upvalue/local variable, the |
904 | ** is needed in a previous assignment (to a table). If so, save original | 1104 | ** upvalue/local variable is begin used in a previous assignment to a |
905 | ** local value in a safe place and use this safe copy in the previous | 1105 | ** table. If so, save original upvalue/local value in a safe place and |
906 | ** assignment. | 1106 | ** use this safe copy in the previous assignment. |
907 | */ | 1107 | */ |
908 | static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | 1108 | static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { |
909 | FuncState *fs = ls->fs; | 1109 | FuncState *fs = ls->fs; |
910 | int extra = fs->freereg; /* eventual position to save local variable */ | 1110 | int extra = fs->freereg; /* eventual position to save local variable */ |
911 | int conflict = 0; | 1111 | int conflict = 0; |
912 | for (; lh; lh = lh->prev) { | 1112 | for (; lh; lh = lh->prev) { /* check all previous assignments */ |
913 | if (lh->v.k == VINDEXED) { | 1113 | if (lh->v.k == VINDEXED) { /* assigning to a table? */ |
914 | if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ | 1114 | /* table is the upvalue/local being assigned now? */ |
1115 | if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { | ||
915 | conflict = 1; | 1116 | conflict = 1; |
916 | lh->v.u.s.info = extra; /* previous assignment will use safe copy */ | 1117 | lh->v.u.ind.vt = VLOCAL; |
1118 | lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ | ||
917 | } | 1119 | } |
918 | if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ | 1120 | /* index is the local being assigned? (index cannot be upvalue) */ |
1121 | if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { | ||
919 | conflict = 1; | 1122 | conflict = 1; |
920 | lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ | 1123 | lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ |
921 | } | 1124 | } |
922 | } | 1125 | } |
923 | } | 1126 | } |
924 | if (conflict) { | 1127 | if (conflict) { |
925 | luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ | 1128 | /* copy upvalue/local value to a temporary (in position 'extra') */ |
1129 | OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; | ||
1130 | luaK_codeABC(fs, op, extra, v->u.info, 0); | ||
926 | luaK_reserveregs(fs, 1); | 1131 | luaK_reserveregs(fs, 1); |
927 | } | 1132 | } |
928 | } | 1133 | } |
@@ -930,22 +1135,21 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | |||
930 | 1135 | ||
931 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | 1136 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { |
932 | expdesc e; | 1137 | expdesc e; |
933 | check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, | 1138 | check_condition(ls, vkisvar(lh->v.k), "syntax error"); |
934 | "syntax error"); | 1139 | if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ |
935 | if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ | ||
936 | struct LHS_assign nv; | 1140 | struct LHS_assign nv; |
937 | nv.prev = lh; | 1141 | nv.prev = lh; |
938 | primaryexp(ls, &nv.v); | 1142 | suffixedexp(ls, &nv.v); |
939 | if (nv.v.k == VLOCAL) | 1143 | if (nv.v.k != VINDEXED) |
940 | check_conflict(ls, lh, &nv.v); | 1144 | check_conflict(ls, lh, &nv.v); |
941 | luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, | 1145 | checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, |
942 | "variables in assignment"); | 1146 | "C levels"); |
943 | assignment(ls, &nv, nvars+1); | 1147 | assignment(ls, &nv, nvars+1); |
944 | } | 1148 | } |
945 | else { /* assignment -> `=' explist1 */ | 1149 | else { /* assignment -> `=' explist */ |
946 | int nexps; | 1150 | int nexps; |
947 | checknext(ls, '='); | 1151 | checknext(ls, '='); |
948 | nexps = explist1(ls, &e); | 1152 | nexps = explist(ls, &e); |
949 | if (nexps != nvars) { | 1153 | if (nexps != nvars) { |
950 | adjust_assign(ls, nvars, nexps, &e); | 1154 | adjust_assign(ls, nvars, nexps, &e); |
951 | if (nexps > nvars) | 1155 | if (nexps > nvars) |
@@ -972,19 +1176,57 @@ static int cond (LexState *ls) { | |||
972 | } | 1176 | } |
973 | 1177 | ||
974 | 1178 | ||
975 | static void breakstat (LexState *ls) { | 1179 | static void gotostat (LexState *ls, int pc) { |
1180 | int line = ls->linenumber; | ||
1181 | TString *label; | ||
1182 | int g; | ||
1183 | if (testnext(ls, TK_GOTO)) | ||
1184 | label = str_checkname(ls); | ||
1185 | else { | ||
1186 | luaX_next(ls); /* skip break */ | ||
1187 | label = luaS_new(ls->L, "break"); | ||
1188 | } | ||
1189 | g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); | ||
1190 | findlabel(ls, g); /* close it if label already defined */ | ||
1191 | } | ||
1192 | |||
1193 | |||
1194 | /* check for repeated labels on the same block */ | ||
1195 | static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { | ||
1196 | int i; | ||
1197 | for (i = fs->bl->firstlabel; i < ll->n; i++) { | ||
1198 | if (luaS_eqstr(label, ll->arr[i].name)) { | ||
1199 | const char *msg = luaO_pushfstring(fs->ls->L, | ||
1200 | "label " LUA_QS " already defined on line %d", | ||
1201 | getstr(label), ll->arr[i].line); | ||
1202 | semerror(fs->ls, msg); | ||
1203 | } | ||
1204 | } | ||
1205 | } | ||
1206 | |||
1207 | |||
1208 | /* skip no-op statements */ | ||
1209 | static void skipnoopstat (LexState *ls) { | ||
1210 | while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) | ||
1211 | statement(ls); | ||
1212 | } | ||
1213 | |||
1214 | |||
1215 | static void labelstat (LexState *ls, TString *label, int line) { | ||
1216 | /* label -> '::' NAME '::' */ | ||
976 | FuncState *fs = ls->fs; | 1217 | FuncState *fs = ls->fs; |
977 | BlockCnt *bl = fs->bl; | 1218 | Labellist *ll = &ls->dyd->label; |
978 | int upval = 0; | 1219 | int l; /* index of new label being created */ |
979 | while (bl && !bl->isbreakable) { | 1220 | checkrepeated(fs, ll, label); /* check for repeated labels */ |
980 | upval |= bl->upval; | 1221 | checknext(ls, TK_DBCOLON); /* skip double colon */ |
981 | bl = bl->previous; | 1222 | /* create new entry for this label */ |
1223 | l = newlabelentry(ls, ll, label, line, fs->pc); | ||
1224 | skipnoopstat(ls); /* skip other no-op statements */ | ||
1225 | if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ | ||
1226 | /* assume that locals are already out of scope */ | ||
1227 | ll->arr[l].nactvar = fs->bl->nactvar; | ||
982 | } | 1228 | } |
983 | if (!bl) | 1229 | findgotos(ls, &ll->arr[l]); |
984 | luaX_syntaxerror(ls, "no loop to break"); | ||
985 | if (upval) | ||
986 | luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); | ||
987 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); | ||
988 | } | 1230 | } |
989 | 1231 | ||
990 | 1232 | ||
@@ -1000,7 +1242,7 @@ static void whilestat (LexState *ls, int line) { | |||
1000 | enterblock(fs, &bl, 1); | 1242 | enterblock(fs, &bl, 1); |
1001 | checknext(ls, TK_DO); | 1243 | checknext(ls, TK_DO); |
1002 | block(ls); | 1244 | block(ls); |
1003 | luaK_patchlist(fs, luaK_jump(fs), whileinit); | 1245 | luaK_jumpto(fs, whileinit); |
1004 | check_match(ls, TK_END, TK_WHILE, line); | 1246 | check_match(ls, TK_END, TK_WHILE, line); |
1005 | leaveblock(fs); | 1247 | leaveblock(fs); |
1006 | luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ | 1248 | luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ |
@@ -1016,30 +1258,25 @@ static void repeatstat (LexState *ls, int line) { | |||
1016 | enterblock(fs, &bl1, 1); /* loop block */ | 1258 | enterblock(fs, &bl1, 1); /* loop block */ |
1017 | enterblock(fs, &bl2, 0); /* scope block */ | 1259 | enterblock(fs, &bl2, 0); /* scope block */ |
1018 | luaX_next(ls); /* skip REPEAT */ | 1260 | luaX_next(ls); /* skip REPEAT */ |
1019 | chunk(ls); | 1261 | statlist(ls); |
1020 | check_match(ls, TK_UNTIL, TK_REPEAT, line); | 1262 | check_match(ls, TK_UNTIL, TK_REPEAT, line); |
1021 | condexit = cond(ls); /* read condition (inside scope block) */ | 1263 | condexit = cond(ls); /* read condition (inside scope block) */ |
1022 | if (!bl2.upval) { /* no upvalues? */ | 1264 | if (bl2.upval) /* upvalues? */ |
1023 | leaveblock(fs); /* finish scope */ | 1265 | luaK_patchclose(fs, condexit, bl2.nactvar); |
1024 | luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ | 1266 | leaveblock(fs); /* finish scope */ |
1025 | } | 1267 | luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ |
1026 | else { /* complete semantics when there are upvalues */ | ||
1027 | breakstat(ls); /* if condition then break */ | ||
1028 | luaK_patchtohere(ls->fs, condexit); /* else... */ | ||
1029 | leaveblock(fs); /* finish scope... */ | ||
1030 | luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ | ||
1031 | } | ||
1032 | leaveblock(fs); /* finish loop */ | 1268 | leaveblock(fs); /* finish loop */ |
1033 | } | 1269 | } |
1034 | 1270 | ||
1035 | 1271 | ||
1036 | static int exp1 (LexState *ls) { | 1272 | static int exp1 (LexState *ls) { |
1037 | expdesc e; | 1273 | expdesc e; |
1038 | int k; | 1274 | int reg; |
1039 | expr(ls, &e); | 1275 | expr(ls, &e); |
1040 | k = e.k; | ||
1041 | luaK_exp2nextreg(ls->fs, &e); | 1276 | luaK_exp2nextreg(ls->fs, &e); |
1042 | return k; | 1277 | lua_assert(e.k == VNONRELOC); |
1278 | reg = e.u.info; | ||
1279 | return reg; | ||
1043 | } | 1280 | } |
1044 | 1281 | ||
1045 | 1282 | ||
@@ -1057,10 +1294,15 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { | |||
1057 | block(ls); | 1294 | block(ls); |
1058 | leaveblock(fs); /* end of scope for declared variables */ | 1295 | leaveblock(fs); /* end of scope for declared variables */ |
1059 | luaK_patchtohere(fs, prep); | 1296 | luaK_patchtohere(fs, prep); |
1060 | endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : | 1297 | if (isnum) /* numeric for? */ |
1061 | luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); | 1298 | endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); |
1062 | luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ | 1299 | else { /* generic for */ |
1063 | luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); | 1300 | luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); |
1301 | luaK_fixline(fs, line); | ||
1302 | endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP); | ||
1303 | } | ||
1304 | luaK_patchlist(fs, endfor, prep + 1); | ||
1305 | luaK_fixline(fs, line); | ||
1064 | } | 1306 | } |
1065 | 1307 | ||
1066 | 1308 | ||
@@ -1068,10 +1310,10 @@ static void fornum (LexState *ls, TString *varname, int line) { | |||
1068 | /* fornum -> NAME = exp1,exp1[,exp1] forbody */ | 1310 | /* fornum -> NAME = exp1,exp1[,exp1] forbody */ |
1069 | FuncState *fs = ls->fs; | 1311 | FuncState *fs = ls->fs; |
1070 | int base = fs->freereg; | 1312 | int base = fs->freereg; |
1071 | new_localvarliteral(ls, "(for index)", 0); | 1313 | new_localvarliteral(ls, "(for index)"); |
1072 | new_localvarliteral(ls, "(for limit)", 1); | 1314 | new_localvarliteral(ls, "(for limit)"); |
1073 | new_localvarliteral(ls, "(for step)", 2); | 1315 | new_localvarliteral(ls, "(for step)"); |
1074 | new_localvar(ls, varname, 3); | 1316 | new_localvar(ls, varname); |
1075 | checknext(ls, '='); | 1317 | checknext(ls, '='); |
1076 | exp1(ls); /* initial value */ | 1318 | exp1(ls); /* initial value */ |
1077 | checknext(ls, ','); | 1319 | checknext(ls, ','); |
@@ -1079,7 +1321,7 @@ static void fornum (LexState *ls, TString *varname, int line) { | |||
1079 | if (testnext(ls, ',')) | 1321 | if (testnext(ls, ',')) |
1080 | exp1(ls); /* optional step */ | 1322 | exp1(ls); /* optional step */ |
1081 | else { /* default step = 1 */ | 1323 | else { /* default step = 1 */ |
1082 | luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); | 1324 | luaK_codek(fs, fs->freereg, luaK_numberK(fs, 1)); |
1083 | luaK_reserveregs(fs, 1); | 1325 | luaK_reserveregs(fs, 1); |
1084 | } | 1326 | } |
1085 | forbody(ls, base, line, 1, 1); | 1327 | forbody(ls, base, line, 1, 1); |
@@ -1087,23 +1329,25 @@ static void fornum (LexState *ls, TString *varname, int line) { | |||
1087 | 1329 | ||
1088 | 1330 | ||
1089 | static void forlist (LexState *ls, TString *indexname) { | 1331 | static void forlist (LexState *ls, TString *indexname) { |
1090 | /* forlist -> NAME {,NAME} IN explist1 forbody */ | 1332 | /* forlist -> NAME {,NAME} IN explist forbody */ |
1091 | FuncState *fs = ls->fs; | 1333 | FuncState *fs = ls->fs; |
1092 | expdesc e; | 1334 | expdesc e; |
1093 | int nvars = 0; | 1335 | int nvars = 4; /* gen, state, control, plus at least one declared var */ |
1094 | int line; | 1336 | int line; |
1095 | int base = fs->freereg; | 1337 | int base = fs->freereg; |
1096 | /* create control variables */ | 1338 | /* create control variables */ |
1097 | new_localvarliteral(ls, "(for generator)", nvars++); | 1339 | new_localvarliteral(ls, "(for generator)"); |
1098 | new_localvarliteral(ls, "(for state)", nvars++); | 1340 | new_localvarliteral(ls, "(for state)"); |
1099 | new_localvarliteral(ls, "(for control)", nvars++); | 1341 | new_localvarliteral(ls, "(for control)"); |
1100 | /* create declared variables */ | 1342 | /* create declared variables */ |
1101 | new_localvar(ls, indexname, nvars++); | 1343 | new_localvar(ls, indexname); |
1102 | while (testnext(ls, ',')) | 1344 | while (testnext(ls, ',')) { |
1103 | new_localvar(ls, str_checkname(ls), nvars++); | 1345 | new_localvar(ls, str_checkname(ls)); |
1346 | nvars++; | ||
1347 | } | ||
1104 | checknext(ls, TK_IN); | 1348 | checknext(ls, TK_IN); |
1105 | line = ls->linenumber; | 1349 | line = ls->linenumber; |
1106 | adjust_assign(ls, 3, explist1(ls, &e), &e); | 1350 | adjust_assign(ls, 3, explist(ls, &e), &e); |
1107 | luaK_checkstack(fs, 3); /* extra space to call generator */ | 1351 | luaK_checkstack(fs, 3); /* extra space to call generator */ |
1108 | forbody(ls, base, line, nvars - 3, 0); | 1352 | forbody(ls, base, line, nvars - 3, 0); |
1109 | } | 1353 | } |
@@ -1127,65 +1371,77 @@ static void forstat (LexState *ls, int line) { | |||
1127 | } | 1371 | } |
1128 | 1372 | ||
1129 | 1373 | ||
1130 | static int test_then_block (LexState *ls) { | 1374 | static void test_then_block (LexState *ls, int *escapelist) { |
1131 | /* test_then_block -> [IF | ELSEIF] cond THEN block */ | 1375 | /* test_then_block -> [IF | ELSEIF] cond THEN block */ |
1132 | int condexit; | 1376 | BlockCnt bl; |
1377 | FuncState *fs = ls->fs; | ||
1378 | expdesc v; | ||
1379 | int jf; /* instruction to skip 'then' code (if condition is false) */ | ||
1133 | luaX_next(ls); /* skip IF or ELSEIF */ | 1380 | luaX_next(ls); /* skip IF or ELSEIF */ |
1134 | condexit = cond(ls); | 1381 | expr(ls, &v); /* read condition */ |
1135 | checknext(ls, TK_THEN); | 1382 | checknext(ls, TK_THEN); |
1136 | block(ls); /* `then' part */ | 1383 | if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { |
1137 | return condexit; | 1384 | luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ |
1385 | enterblock(fs, &bl, 0); /* must enter block before 'goto' */ | ||
1386 | gotostat(ls, v.t); /* handle goto/break */ | ||
1387 | skipnoopstat(ls); /* skip other no-op statements */ | ||
1388 | if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ | ||
1389 | leaveblock(fs); | ||
1390 | return; /* and that is it */ | ||
1391 | } | ||
1392 | else /* must skip over 'then' part if condition is false */ | ||
1393 | jf = luaK_jump(fs); | ||
1394 | } | ||
1395 | else { /* regular case (not goto/break) */ | ||
1396 | luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ | ||
1397 | enterblock(fs, &bl, 0); | ||
1398 | jf = v.f; | ||
1399 | } | ||
1400 | statlist(ls); /* `then' part */ | ||
1401 | leaveblock(fs); | ||
1402 | if (ls->t.token == TK_ELSE || | ||
1403 | ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ | ||
1404 | luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ | ||
1405 | luaK_patchtohere(fs, jf); | ||
1138 | } | 1406 | } |
1139 | 1407 | ||
1140 | 1408 | ||
1141 | static void ifstat (LexState *ls, int line) { | 1409 | static void ifstat (LexState *ls, int line) { |
1142 | /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ | 1410 | /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ |
1143 | FuncState *fs = ls->fs; | 1411 | FuncState *fs = ls->fs; |
1144 | int flist; | 1412 | int escapelist = NO_JUMP; /* exit list for finished parts */ |
1145 | int escapelist = NO_JUMP; | 1413 | test_then_block(ls, &escapelist); /* IF cond THEN block */ |
1146 | flist = test_then_block(ls); /* IF cond THEN block */ | 1414 | while (ls->t.token == TK_ELSEIF) |
1147 | while (ls->t.token == TK_ELSEIF) { | 1415 | test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ |
1148 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | 1416 | if (testnext(ls, TK_ELSE)) |
1149 | luaK_patchtohere(fs, flist); | ||
1150 | flist = test_then_block(ls); /* ELSEIF cond THEN block */ | ||
1151 | } | ||
1152 | if (ls->t.token == TK_ELSE) { | ||
1153 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | ||
1154 | luaK_patchtohere(fs, flist); | ||
1155 | luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ | ||
1156 | block(ls); /* `else' part */ | 1417 | block(ls); /* `else' part */ |
1157 | } | ||
1158 | else | ||
1159 | luaK_concat(fs, &escapelist, flist); | ||
1160 | luaK_patchtohere(fs, escapelist); | ||
1161 | check_match(ls, TK_END, TK_IF, line); | 1418 | check_match(ls, TK_END, TK_IF, line); |
1419 | luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ | ||
1162 | } | 1420 | } |
1163 | 1421 | ||
1164 | 1422 | ||
1165 | static void localfunc (LexState *ls) { | 1423 | static void localfunc (LexState *ls) { |
1166 | expdesc v, b; | 1424 | expdesc b; |
1167 | FuncState *fs = ls->fs; | 1425 | FuncState *fs = ls->fs; |
1168 | new_localvar(ls, str_checkname(ls), 0); | 1426 | new_localvar(ls, str_checkname(ls)); /* new local variable */ |
1169 | init_exp(&v, VLOCAL, fs->freereg); | 1427 | adjustlocalvars(ls, 1); /* enter its scope */ |
1170 | luaK_reserveregs(fs, 1); | 1428 | body(ls, &b, 0, ls->linenumber); /* function created in next register */ |
1171 | adjustlocalvars(ls, 1); | ||
1172 | body(ls, &b, 0, ls->linenumber); | ||
1173 | luaK_storevar(fs, &v, &b); | ||
1174 | /* debug information will only see the variable after this point! */ | 1429 | /* debug information will only see the variable after this point! */ |
1175 | getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; | 1430 | getlocvar(fs, b.u.info)->startpc = fs->pc; |
1176 | } | 1431 | } |
1177 | 1432 | ||
1178 | 1433 | ||
1179 | static void localstat (LexState *ls) { | 1434 | static void localstat (LexState *ls) { |
1180 | /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ | 1435 | /* stat -> LOCAL NAME {`,' NAME} [`=' explist] */ |
1181 | int nvars = 0; | 1436 | int nvars = 0; |
1182 | int nexps; | 1437 | int nexps; |
1183 | expdesc e; | 1438 | expdesc e; |
1184 | do { | 1439 | do { |
1185 | new_localvar(ls, str_checkname(ls), nvars++); | 1440 | new_localvar(ls, str_checkname(ls)); |
1441 | nvars++; | ||
1186 | } while (testnext(ls, ',')); | 1442 | } while (testnext(ls, ',')); |
1187 | if (testnext(ls, '=')) | 1443 | if (testnext(ls, '=')) |
1188 | nexps = explist1(ls, &e); | 1444 | nexps = explist(ls, &e); |
1189 | else { | 1445 | else { |
1190 | e.k = VVOID; | 1446 | e.k = VVOID; |
1191 | nexps = 0; | 1447 | nexps = 0; |
@@ -1196,26 +1452,26 @@ static void localstat (LexState *ls) { | |||
1196 | 1452 | ||
1197 | 1453 | ||
1198 | static int funcname (LexState *ls, expdesc *v) { | 1454 | static int funcname (LexState *ls, expdesc *v) { |
1199 | /* funcname -> NAME {field} [`:' NAME] */ | 1455 | /* funcname -> NAME {fieldsel} [`:' NAME] */ |
1200 | int needself = 0; | 1456 | int ismethod = 0; |
1201 | singlevar(ls, v); | 1457 | singlevar(ls, v); |
1202 | while (ls->t.token == '.') | 1458 | while (ls->t.token == '.') |
1203 | field(ls, v); | 1459 | fieldsel(ls, v); |
1204 | if (ls->t.token == ':') { | 1460 | if (ls->t.token == ':') { |
1205 | needself = 1; | 1461 | ismethod = 1; |
1206 | field(ls, v); | 1462 | fieldsel(ls, v); |
1207 | } | 1463 | } |
1208 | return needself; | 1464 | return ismethod; |
1209 | } | 1465 | } |
1210 | 1466 | ||
1211 | 1467 | ||
1212 | static void funcstat (LexState *ls, int line) { | 1468 | static void funcstat (LexState *ls, int line) { |
1213 | /* funcstat -> FUNCTION funcname body */ | 1469 | /* funcstat -> FUNCTION funcname body */ |
1214 | int needself; | 1470 | int ismethod; |
1215 | expdesc v, b; | 1471 | expdesc v, b; |
1216 | luaX_next(ls); /* skip FUNCTION */ | 1472 | luaX_next(ls); /* skip FUNCTION */ |
1217 | needself = funcname(ls, &v); | 1473 | ismethod = funcname(ls, &v); |
1218 | body(ls, &b, needself, line); | 1474 | body(ls, &b, ismethod, line); |
1219 | luaK_storevar(ls->fs, &v, &b); | 1475 | luaK_storevar(ls->fs, &v, &b); |
1220 | luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ | 1476 | luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ |
1221 | } | 1477 | } |
@@ -1225,26 +1481,27 @@ static void exprstat (LexState *ls) { | |||
1225 | /* stat -> func | assignment */ | 1481 | /* stat -> func | assignment */ |
1226 | FuncState *fs = ls->fs; | 1482 | FuncState *fs = ls->fs; |
1227 | struct LHS_assign v; | 1483 | struct LHS_assign v; |
1228 | primaryexp(ls, &v.v); | 1484 | suffixedexp(ls, &v.v); |
1229 | if (v.v.k == VCALL) /* stat -> func */ | 1485 | if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ |
1230 | SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ | ||
1231 | else { /* stat -> assignment */ | ||
1232 | v.prev = NULL; | 1486 | v.prev = NULL; |
1233 | assignment(ls, &v, 1); | 1487 | assignment(ls, &v, 1); |
1234 | } | 1488 | } |
1489 | else { /* stat -> func */ | ||
1490 | check_condition(ls, v.v.k == VCALL, "syntax error"); | ||
1491 | SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ | ||
1492 | } | ||
1235 | } | 1493 | } |
1236 | 1494 | ||
1237 | 1495 | ||
1238 | static void retstat (LexState *ls) { | 1496 | static void retstat (LexState *ls) { |
1239 | /* stat -> RETURN explist */ | 1497 | /* stat -> RETURN [explist] [';'] */ |
1240 | FuncState *fs = ls->fs; | 1498 | FuncState *fs = ls->fs; |
1241 | expdesc e; | 1499 | expdesc e; |
1242 | int first, nret; /* registers with returned values */ | 1500 | int first, nret; /* registers with returned values */ |
1243 | luaX_next(ls); /* skip RETURN */ | 1501 | if (block_follow(ls, 1) || ls->t.token == ';') |
1244 | if (block_follow(ls->t.token) || ls->t.token == ';') | ||
1245 | first = nret = 0; /* return no values */ | 1502 | first = nret = 0; /* return no values */ |
1246 | else { | 1503 | else { |
1247 | nret = explist1(ls, &e); /* optional return values */ | 1504 | nret = explist(ls, &e); /* optional return values */ |
1248 | if (hasmultret(e.k)) { | 1505 | if (hasmultret(e.k)) { |
1249 | luaK_setmultret(fs, &e); | 1506 | luaK_setmultret(fs, &e); |
1250 | if (e.k == VCALL && nret == 1) { /* tail call? */ | 1507 | if (e.k == VCALL && nret == 1) { /* tail call? */ |
@@ -1265,37 +1522,43 @@ static void retstat (LexState *ls) { | |||
1265 | } | 1522 | } |
1266 | } | 1523 | } |
1267 | luaK_ret(fs, first, nret); | 1524 | luaK_ret(fs, first, nret); |
1525 | testnext(ls, ';'); /* skip optional semicolon */ | ||
1268 | } | 1526 | } |
1269 | 1527 | ||
1270 | 1528 | ||
1271 | static int statement (LexState *ls) { | 1529 | static void statement (LexState *ls) { |
1272 | int line = ls->linenumber; /* may be needed for error messages */ | 1530 | int line = ls->linenumber; /* may be needed for error messages */ |
1531 | enterlevel(ls); | ||
1273 | switch (ls->t.token) { | 1532 | switch (ls->t.token) { |
1533 | case ';': { /* stat -> ';' (empty statement) */ | ||
1534 | luaX_next(ls); /* skip ';' */ | ||
1535 | break; | ||
1536 | } | ||
1274 | case TK_IF: { /* stat -> ifstat */ | 1537 | case TK_IF: { /* stat -> ifstat */ |
1275 | ifstat(ls, line); | 1538 | ifstat(ls, line); |
1276 | return 0; | 1539 | break; |
1277 | } | 1540 | } |
1278 | case TK_WHILE: { /* stat -> whilestat */ | 1541 | case TK_WHILE: { /* stat -> whilestat */ |
1279 | whilestat(ls, line); | 1542 | whilestat(ls, line); |
1280 | return 0; | 1543 | break; |
1281 | } | 1544 | } |
1282 | case TK_DO: { /* stat -> DO block END */ | 1545 | case TK_DO: { /* stat -> DO block END */ |
1283 | luaX_next(ls); /* skip DO */ | 1546 | luaX_next(ls); /* skip DO */ |
1284 | block(ls); | 1547 | block(ls); |
1285 | check_match(ls, TK_END, TK_DO, line); | 1548 | check_match(ls, TK_END, TK_DO, line); |
1286 | return 0; | 1549 | break; |
1287 | } | 1550 | } |
1288 | case TK_FOR: { /* stat -> forstat */ | 1551 | case TK_FOR: { /* stat -> forstat */ |
1289 | forstat(ls, line); | 1552 | forstat(ls, line); |
1290 | return 0; | 1553 | break; |
1291 | } | 1554 | } |
1292 | case TK_REPEAT: { /* stat -> repeatstat */ | 1555 | case TK_REPEAT: { /* stat -> repeatstat */ |
1293 | repeatstat(ls, line); | 1556 | repeatstat(ls, line); |
1294 | return 0; | 1557 | break; |
1295 | } | 1558 | } |
1296 | case TK_FUNCTION: { | 1559 | case TK_FUNCTION: { /* stat -> funcstat */ |
1297 | funcstat(ls, line); /* stat -> funcstat */ | 1560 | funcstat(ls, line); |
1298 | return 0; | 1561 | break; |
1299 | } | 1562 | } |
1300 | case TK_LOCAL: { /* stat -> localstat */ | 1563 | case TK_LOCAL: { /* stat -> localstat */ |
1301 | luaX_next(ls); /* skip LOCAL */ | 1564 | luaX_next(ls); /* skip LOCAL */ |
@@ -1303,37 +1566,73 @@ static int statement (LexState *ls) { | |||
1303 | localfunc(ls); | 1566 | localfunc(ls); |
1304 | else | 1567 | else |
1305 | localstat(ls); | 1568 | localstat(ls); |
1306 | return 0; | 1569 | break; |
1570 | } | ||
1571 | case TK_DBCOLON: { /* stat -> label */ | ||
1572 | luaX_next(ls); /* skip double colon */ | ||
1573 | labelstat(ls, str_checkname(ls), line); | ||
1574 | break; | ||
1307 | } | 1575 | } |
1308 | case TK_RETURN: { /* stat -> retstat */ | 1576 | case TK_RETURN: { /* stat -> retstat */ |
1577 | luaX_next(ls); /* skip RETURN */ | ||
1309 | retstat(ls); | 1578 | retstat(ls); |
1310 | return 1; /* must be last statement */ | 1579 | break; |
1311 | } | 1580 | } |
1312 | case TK_BREAK: { /* stat -> breakstat */ | 1581 | case TK_BREAK: /* stat -> breakstat */ |
1313 | luaX_next(ls); /* skip BREAK */ | 1582 | case TK_GOTO: { /* stat -> 'goto' NAME */ |
1314 | breakstat(ls); | 1583 | gotostat(ls, luaK_jump(ls->fs)); |
1315 | return 1; /* must be last statement */ | 1584 | break; |
1316 | } | 1585 | } |
1317 | default: { | 1586 | default: { /* stat -> func | assignment */ |
1318 | exprstat(ls); | 1587 | exprstat(ls); |
1319 | return 0; /* to avoid warnings */ | 1588 | break; |
1320 | } | 1589 | } |
1321 | } | 1590 | } |
1591 | lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && | ||
1592 | ls->fs->freereg >= ls->fs->nactvar); | ||
1593 | ls->fs->freereg = ls->fs->nactvar; /* free registers */ | ||
1594 | leavelevel(ls); | ||
1322 | } | 1595 | } |
1323 | 1596 | ||
1597 | /* }====================================================================== */ | ||
1324 | 1598 | ||
1325 | static void chunk (LexState *ls) { | 1599 | |
1326 | /* chunk -> { stat [`;'] } */ | 1600 | /* |
1327 | int islast = 0; | 1601 | ** compiles the main function, which is a regular vararg function with an |
1328 | enterlevel(ls); | 1602 | ** upvalue named LUA_ENV |
1329 | while (!islast && !block_follow(ls->t.token)) { | 1603 | */ |
1330 | islast = statement(ls); | 1604 | static void mainfunc (LexState *ls, FuncState *fs) { |
1331 | testnext(ls, ';'); | 1605 | BlockCnt bl; |
1332 | lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && | 1606 | expdesc v; |
1333 | ls->fs->freereg >= ls->fs->nactvar); | 1607 | open_func(ls, fs, &bl); |
1334 | ls->fs->freereg = ls->fs->nactvar; /* free registers */ | 1608 | fs->f->is_vararg = 1; /* main function is always vararg */ |
1335 | } | 1609 | init_exp(&v, VLOCAL, 0); /* create and... */ |
1336 | leavelevel(ls); | 1610 | newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ |
1611 | luaX_next(ls); /* read first token */ | ||
1612 | statlist(ls); /* parse main body */ | ||
1613 | check(ls, TK_EOS); | ||
1614 | close_func(ls); | ||
1615 | } | ||
1616 | |||
1617 | |||
1618 | Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | ||
1619 | Dyndata *dyd, const char *name, int firstchar) { | ||
1620 | LexState lexstate; | ||
1621 | FuncState funcstate; | ||
1622 | Closure *cl = luaF_newLclosure(L, 1); /* create main closure */ | ||
1623 | /* anchor closure (to avoid being collected) */ | ||
1624 | setclLvalue(L, L->top, cl); | ||
1625 | incr_top(L); | ||
1626 | funcstate.f = cl->l.p = luaF_newproto(L); | ||
1627 | funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ | ||
1628 | lexstate.buff = buff; | ||
1629 | lexstate.dyd = dyd; | ||
1630 | dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; | ||
1631 | luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); | ||
1632 | mainfunc(&lexstate, &funcstate); | ||
1633 | lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); | ||
1634 | /* all scopes should be correctly finished */ | ||
1635 | lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); | ||
1636 | return cl; /* it's on the stack too */ | ||
1337 | } | 1637 | } |
1338 | 1638 | ||
1339 | /* }====================================================================== */ | ||
diff --git a/apps/plugins/lua/lparser.h b/apps/plugins/lua/lparser.h index f9b8e24913..0346e3c41a 100644 --- a/apps/plugins/lua/lparser.h +++ b/apps/plugins/lua/lparser.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lparser.h,v 1.70.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -23,34 +23,72 @@ typedef enum { | |||
23 | VFALSE, | 23 | VFALSE, |
24 | VK, /* info = index of constant in `k' */ | 24 | VK, /* info = index of constant in `k' */ |
25 | VKNUM, /* nval = numerical value */ | 25 | VKNUM, /* nval = numerical value */ |
26 | VNONRELOC, /* info = result register */ | ||
26 | VLOCAL, /* info = local register */ | 27 | VLOCAL, /* info = local register */ |
27 | VUPVAL, /* info = index of upvalue in `upvalues' */ | 28 | VUPVAL, /* info = index of upvalue in 'upvalues' */ |
28 | VGLOBAL, /* info = index of table; aux = index of global name in `k' */ | 29 | VINDEXED, /* t = table register/upvalue; idx = index R/K */ |
29 | VINDEXED, /* info = table register; aux = index register (or `k') */ | ||
30 | VJMP, /* info = instruction pc */ | 30 | VJMP, /* info = instruction pc */ |
31 | VRELOCABLE, /* info = instruction pc */ | 31 | VRELOCABLE, /* info = instruction pc */ |
32 | VNONRELOC, /* info = result register */ | ||
33 | VCALL, /* info = instruction pc */ | 32 | VCALL, /* info = instruction pc */ |
34 | VVARARG /* info = instruction pc */ | 33 | VVARARG /* info = instruction pc */ |
35 | } expkind; | 34 | } expkind; |
36 | 35 | ||
36 | |||
37 | #define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) | ||
38 | #define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) | ||
39 | |||
37 | typedef struct expdesc { | 40 | typedef struct expdesc { |
38 | expkind k; | 41 | expkind k; |
39 | union { | 42 | union { |
40 | struct { int info, aux; } s; | 43 | struct { /* for indexed variables (VINDEXED) */ |
41 | lua_Number nval; | 44 | short idx; /* index (R/K) */ |
45 | lu_byte t; /* table (register or upvalue) */ | ||
46 | lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ | ||
47 | } ind; | ||
48 | int info; /* for generic use */ | ||
49 | lua_Number nval; /* for VKNUM */ | ||
42 | } u; | 50 | } u; |
43 | int t; /* patch list of `exit when true' */ | 51 | int t; /* patch list of `exit when true' */ |
44 | int f; /* patch list of `exit when false' */ | 52 | int f; /* patch list of `exit when false' */ |
45 | } expdesc; | 53 | } expdesc; |
46 | 54 | ||
47 | 55 | ||
48 | typedef struct upvaldesc { | 56 | /* description of active local variable */ |
49 | lu_byte k; | 57 | typedef struct Vardesc { |
50 | lu_byte info; | 58 | short idx; /* variable index in stack */ |
51 | } upvaldesc; | 59 | } Vardesc; |
60 | |||
61 | |||
62 | /* description of pending goto statements and label statements */ | ||
63 | typedef struct Labeldesc { | ||
64 | TString *name; /* label identifier */ | ||
65 | int pc; /* position in code */ | ||
66 | int line; /* line where it appeared */ | ||
67 | lu_byte nactvar; /* local level where it appears in current block */ | ||
68 | } Labeldesc; | ||
69 | |||
70 | |||
71 | /* list of labels or gotos */ | ||
72 | typedef struct Labellist { | ||
73 | Labeldesc *arr; /* array */ | ||
74 | int n; /* number of entries in use */ | ||
75 | int size; /* array size */ | ||
76 | } Labellist; | ||
77 | |||
78 | |||
79 | /* dynamic structures used by the parser */ | ||
80 | typedef struct Dyndata { | ||
81 | struct { /* list of active local variables */ | ||
82 | Vardesc *arr; | ||
83 | int n; | ||
84 | int size; | ||
85 | } actvar; | ||
86 | Labellist gt; /* list of pending gotos */ | ||
87 | Labellist label; /* list of active labels */ | ||
88 | } Dyndata; | ||
52 | 89 | ||
53 | 90 | ||
91 | /* control of blocks */ | ||
54 | struct BlockCnt; /* defined in lparser.c */ | 92 | struct BlockCnt; /* defined in lparser.c */ |
55 | 93 | ||
56 | 94 | ||
@@ -60,23 +98,22 @@ typedef struct FuncState { | |||
60 | Table *h; /* table to find (and reuse) elements in `k' */ | 98 | Table *h; /* table to find (and reuse) elements in `k' */ |
61 | struct FuncState *prev; /* enclosing function */ | 99 | struct FuncState *prev; /* enclosing function */ |
62 | struct LexState *ls; /* lexical state */ | 100 | struct LexState *ls; /* lexical state */ |
63 | struct lua_State *L; /* copy of the Lua state */ | ||
64 | struct BlockCnt *bl; /* chain of current blocks */ | 101 | struct BlockCnt *bl; /* chain of current blocks */ |
65 | int pc; /* next position to code (equivalent to `ncode') */ | 102 | int pc; /* next position to code (equivalent to `ncode') */ |
66 | int lasttarget; /* `pc' of last `jump target' */ | 103 | int lasttarget; /* 'label' of last 'jump label' */ |
67 | int jpc; /* list of pending jumps to `pc' */ | 104 | int jpc; /* list of pending jumps to `pc' */ |
68 | int freereg; /* first free register */ | ||
69 | int nk; /* number of elements in `k' */ | 105 | int nk; /* number of elements in `k' */ |
70 | int np; /* number of elements in `p' */ | 106 | int np; /* number of elements in `p' */ |
71 | short nlocvars; /* number of elements in `locvars' */ | 107 | int firstlocal; /* index of first local var (in Dyndata array) */ |
108 | short nlocvars; /* number of elements in 'f->locvars' */ | ||
72 | lu_byte nactvar; /* number of active local variables */ | 109 | lu_byte nactvar; /* number of active local variables */ |
73 | upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ | 110 | lu_byte nups; /* number of upvalues */ |
74 | unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ | 111 | lu_byte freereg; /* first free register */ |
75 | } FuncState; | 112 | } FuncState; |
76 | 113 | ||
77 | 114 | ||
78 | LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | 115 | LUAI_FUNC Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, |
79 | const char *name); | 116 | Dyndata *dyd, const char *name, int firstchar); |
80 | 117 | ||
81 | 118 | ||
82 | #endif | 119 | #endif |
diff --git a/apps/plugins/lua/lstate.c b/apps/plugins/lua/lstate.c index 4313b83a0c..c7f2672be7 100644 --- a/apps/plugins/lua/lstate.c +++ b/apps/plugins/lua/lstate.c | |||
@@ -1,17 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ | 2 | ** $Id: lstate.c,v 2.99.1.2 2013/11/08 17:45:31 roberto Exp $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
6 | 6 | ||
7 | 7 | ||
8 | #include <stddef.h> | 8 | #include <stddef.h> |
9 | #include <string.h> | ||
9 | 10 | ||
10 | #define lstate_c | 11 | #define lstate_c |
11 | #define LUA_CORE | 12 | #define LUA_CORE |
12 | 13 | ||
13 | #include "lua.h" | 14 | #include "lua.h" |
14 | 15 | ||
16 | #include "lapi.h" | ||
15 | #include "ldebug.h" | 17 | #include "ldebug.h" |
16 | #include "ldo.h" | 18 | #include "ldo.h" |
17 | #include "lfunc.h" | 19 | #include "lfunc.h" |
@@ -24,119 +26,240 @@ | |||
24 | #include "ltm.h" | 26 | #include "ltm.h" |
25 | 27 | ||
26 | 28 | ||
27 | #define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) | 29 | #if !defined(LUAI_GCPAUSE) |
28 | #define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) | 30 | #define LUAI_GCPAUSE 200 /* 200% */ |
29 | #define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) | 31 | #endif |
32 | |||
33 | #if !defined(LUAI_GCMAJOR) | ||
34 | #define LUAI_GCMAJOR 200 /* 200% */ | ||
35 | #endif | ||
36 | |||
37 | #if !defined(LUAI_GCMUL) | ||
38 | #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ | ||
39 | #endif | ||
40 | |||
41 | |||
42 | #define MEMERRMSG "not enough memory" | ||
43 | |||
44 | |||
45 | /* | ||
46 | ** a macro to help the creation of a unique random seed when a state is | ||
47 | ** created; the seed is used to randomize hashes. | ||
48 | */ | ||
49 | #if !defined(luai_makeseed) | ||
50 | #include <time.h> | ||
51 | #define luai_makeseed() cast(unsigned int, time(NULL)) | ||
52 | #endif | ||
53 | |||
54 | |||
55 | |||
56 | /* | ||
57 | ** thread state + extra space | ||
58 | */ | ||
59 | typedef struct LX { | ||
60 | #if defined(LUAI_EXTRASPACE) | ||
61 | char buff[LUAI_EXTRASPACE]; | ||
62 | #endif | ||
63 | lua_State l; | ||
64 | } LX; | ||
30 | 65 | ||
31 | 66 | ||
32 | /* | 67 | /* |
33 | ** Main thread combines a thread state and the global state | 68 | ** Main thread combines a thread state and the global state |
34 | */ | 69 | */ |
35 | typedef struct LG { | 70 | typedef struct LG { |
36 | lua_State l; | 71 | LX l; |
37 | global_State g; | 72 | global_State g; |
38 | } LG; | 73 | } LG; |
39 | 74 | ||
75 | |||
76 | |||
77 | #define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) | ||
78 | |||
79 | |||
80 | /* | ||
81 | ** Compute an initial seed as random as possible. In ANSI, rely on | ||
82 | ** Address Space Layout Randomization (if present) to increase | ||
83 | ** randomness.. | ||
84 | */ | ||
85 | #define addbuff(b,p,e) \ | ||
86 | { size_t t = cast(size_t, e); \ | ||
87 | memcpy(buff + p, &t, sizeof(t)); p += sizeof(t); } | ||
88 | |||
89 | static unsigned int makeseed (lua_State *L) { | ||
90 | char buff[4 * sizeof(size_t)]; | ||
91 | unsigned int h = luai_makeseed(); | ||
92 | int p = 0; | ||
93 | addbuff(buff, p, L); /* heap variable */ | ||
94 | addbuff(buff, p, &h); /* local variable */ | ||
95 | addbuff(buff, p, luaO_nilobject); /* global variable */ | ||
96 | addbuff(buff, p, &lua_newstate); /* public function */ | ||
97 | lua_assert(p == sizeof(buff)); | ||
98 | return luaS_hash(buff, p, h); | ||
99 | } | ||
100 | |||
101 | |||
102 | /* | ||
103 | ** set GCdebt to a new value keeping the value (totalbytes + GCdebt) | ||
104 | ** invariant | ||
105 | */ | ||
106 | void luaE_setdebt (global_State *g, l_mem debt) { | ||
107 | g->totalbytes -= (debt - g->GCdebt); | ||
108 | g->GCdebt = debt; | ||
109 | } | ||
110 | |||
111 | |||
112 | CallInfo *luaE_extendCI (lua_State *L) { | ||
113 | CallInfo *ci = luaM_new(L, CallInfo); | ||
114 | lua_assert(L->ci->next == NULL); | ||
115 | L->ci->next = ci; | ||
116 | ci->previous = L->ci; | ||
117 | ci->next = NULL; | ||
118 | return ci; | ||
119 | } | ||
120 | |||
121 | |||
122 | void luaE_freeCI (lua_State *L) { | ||
123 | CallInfo *ci = L->ci; | ||
124 | CallInfo *next = ci->next; | ||
125 | ci->next = NULL; | ||
126 | while ((ci = next) != NULL) { | ||
127 | next = ci->next; | ||
128 | luaM_free(L, ci); | ||
129 | } | ||
130 | } | ||
40 | 131 | ||
41 | 132 | ||
42 | static void stack_init (lua_State *L1, lua_State *L) { | 133 | static void stack_init (lua_State *L1, lua_State *L) { |
43 | /* initialize CallInfo array */ | 134 | int i; CallInfo *ci; |
44 | L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); | ||
45 | L1->ci = L1->base_ci; | ||
46 | L1->size_ci = BASIC_CI_SIZE; | ||
47 | L1->end_ci = L1->base_ci + L1->size_ci - 1; | ||
48 | /* initialize stack array */ | 135 | /* initialize stack array */ |
49 | L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); | 136 | L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue); |
50 | L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; | 137 | L1->stacksize = BASIC_STACK_SIZE; |
138 | for (i = 0; i < BASIC_STACK_SIZE; i++) | ||
139 | setnilvalue(L1->stack + i); /* erase new stack */ | ||
51 | L1->top = L1->stack; | 140 | L1->top = L1->stack; |
52 | L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; | 141 | L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; |
53 | /* initialize first ci */ | 142 | /* initialize first ci */ |
54 | L1->ci->func = L1->top; | 143 | ci = &L1->base_ci; |
55 | setnilvalue(L1->top++); /* `function' entry for this `ci' */ | 144 | ci->next = ci->previous = NULL; |
56 | L1->base = L1->ci->base = L1->top; | 145 | ci->callstatus = 0; |
57 | L1->ci->top = L1->top + LUA_MINSTACK; | 146 | ci->func = L1->top; |
147 | setnilvalue(L1->top++); /* 'function' entry for this 'ci' */ | ||
148 | ci->top = L1->top + LUA_MINSTACK; | ||
149 | L1->ci = ci; | ||
150 | } | ||
151 | |||
152 | |||
153 | static void freestack (lua_State *L) { | ||
154 | if (L->stack == NULL) | ||
155 | return; /* stack not completely built yet */ | ||
156 | L->ci = &L->base_ci; /* free the entire 'ci' list */ | ||
157 | luaE_freeCI(L); | ||
158 | luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ | ||
58 | } | 159 | } |
59 | 160 | ||
60 | 161 | ||
61 | static void freestack (lua_State *L, lua_State *L1) { | 162 | /* |
62 | luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); | 163 | ** Create registry table and its predefined values |
63 | luaM_freearray(L, L1->stack, L1->stacksize, TValue); | 164 | */ |
165 | static void init_registry (lua_State *L, global_State *g) { | ||
166 | TValue mt; | ||
167 | /* create registry */ | ||
168 | Table *registry = luaH_new(L); | ||
169 | sethvalue(L, &g->l_registry, registry); | ||
170 | luaH_resize(L, registry, LUA_RIDX_LAST, 0); | ||
171 | /* registry[LUA_RIDX_MAINTHREAD] = L */ | ||
172 | setthvalue(L, &mt, L); | ||
173 | luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt); | ||
174 | /* registry[LUA_RIDX_GLOBALS] = table of globals */ | ||
175 | sethvalue(L, &mt, luaH_new(L)); | ||
176 | luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt); | ||
64 | } | 177 | } |
65 | 178 | ||
66 | 179 | ||
67 | /* | 180 | /* |
68 | ** open parts that may cause memory-allocation errors | 181 | ** open parts of the state that may cause memory-allocation errors |
69 | */ | 182 | */ |
70 | static void f_luaopen (lua_State *L, void *ud) { | 183 | static void f_luaopen (lua_State *L, void *ud) { |
71 | global_State *g = G(L); | 184 | global_State *g = G(L); |
72 | UNUSED(ud); | 185 | UNUSED(ud); |
73 | stack_init(L, L); /* init stack */ | 186 | stack_init(L, L); /* init stack */ |
74 | sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ | 187 | init_registry(L, g); |
75 | sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ | ||
76 | luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ | 188 | luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ |
77 | luaT_init(L); | 189 | luaT_init(L); |
78 | luaX_init(L); | 190 | luaX_init(L); |
79 | luaS_fix(luaS_newliteral(L, MEMERRMSG)); | 191 | /* pre-create memory-error message */ |
80 | g->GCthreshold = 4*g->totalbytes; | 192 | g->memerrmsg = luaS_newliteral(L, MEMERRMSG); |
193 | luaS_fix(g->memerrmsg); /* it should never be collected */ | ||
194 | g->gcrunning = 1; /* allow gc */ | ||
195 | g->version = lua_version(NULL); | ||
196 | luai_userstateopen(L); | ||
81 | } | 197 | } |
82 | 198 | ||
83 | 199 | ||
200 | /* | ||
201 | ** preinitialize a state with consistent values without allocating | ||
202 | ** any memory (to avoid errors) | ||
203 | */ | ||
84 | static void preinit_state (lua_State *L, global_State *g) { | 204 | static void preinit_state (lua_State *L, global_State *g) { |
85 | G(L) = g; | 205 | G(L) = g; |
86 | L->stack = NULL; | 206 | L->stack = NULL; |
207 | L->ci = NULL; | ||
87 | L->stacksize = 0; | 208 | L->stacksize = 0; |
88 | L->errorJmp = NULL; | 209 | L->errorJmp = NULL; |
210 | L->nCcalls = 0; | ||
89 | L->hook = NULL; | 211 | L->hook = NULL; |
90 | L->hookmask = 0; | 212 | L->hookmask = 0; |
91 | L->basehookcount = 0; | 213 | L->basehookcount = 0; |
92 | L->allowhook = 1; | 214 | L->allowhook = 1; |
93 | resethookcount(L); | 215 | resethookcount(L); |
94 | L->openupval = NULL; | 216 | L->openupval = NULL; |
95 | L->size_ci = 0; | 217 | L->nny = 1; |
96 | L->nCcalls = L->baseCcalls = 0; | 218 | L->status = LUA_OK; |
97 | L->status = 0; | ||
98 | L->base_ci = L->ci = NULL; | ||
99 | L->savedpc = NULL; | ||
100 | L->errfunc = 0; | 219 | L->errfunc = 0; |
101 | setnilvalue(gt(L)); | ||
102 | } | 220 | } |
103 | 221 | ||
104 | 222 | ||
105 | static void close_state (lua_State *L) { | 223 | static void close_state (lua_State *L) { |
106 | global_State *g = G(L); | 224 | global_State *g = G(L); |
107 | luaF_close(L, L->stack); /* close all upvalues for this thread */ | 225 | luaF_close(L, L->stack); /* close all upvalues for this thread */ |
108 | luaC_freeall(L); /* collect all objects */ | 226 | luaC_freeallobjects(L); /* collect all objects */ |
109 | lua_assert(g->rootgc == obj2gco(L)); | 227 | if (g->version) /* closing a fully built state? */ |
110 | lua_assert(g->strt.nuse == 0); | 228 | luai_userstateclose(L); |
111 | luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); | 229 | luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); |
112 | luaZ_freebuffer(L, &g->buff); | 230 | luaZ_freebuffer(L, &g->buff); |
113 | freestack(L, L); | 231 | freestack(L); |
114 | lua_assert(g->totalbytes == sizeof(LG)); | 232 | lua_assert(gettotalbytes(g) == sizeof(LG)); |
115 | (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); | 233 | (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ |
116 | } | 234 | } |
117 | 235 | ||
118 | 236 | ||
119 | lua_State *luaE_newthread (lua_State *L) { | 237 | LUA_API lua_State *lua_newthread (lua_State *L) { |
120 | lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); | 238 | lua_State *L1; |
121 | luaC_link(L, obj2gco(L1), LUA_TTHREAD); | 239 | lua_lock(L); |
240 | luaC_checkGC(L); | ||
241 | L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th; | ||
242 | setthvalue(L, L->top, L1); | ||
243 | api_incr_top(L); | ||
122 | preinit_state(L1, G(L)); | 244 | preinit_state(L1, G(L)); |
123 | stack_init(L1, L); /* init stack */ | ||
124 | setobj2n(L, gt(L1), gt(L)); /* share table of globals */ | ||
125 | L1->hookmask = L->hookmask; | 245 | L1->hookmask = L->hookmask; |
126 | L1->basehookcount = L->basehookcount; | 246 | L1->basehookcount = L->basehookcount; |
127 | L1->hook = L->hook; | 247 | L1->hook = L->hook; |
128 | resethookcount(L1); | 248 | resethookcount(L1); |
129 | lua_assert(iswhite(obj2gco(L1))); | 249 | luai_userstatethread(L, L1); |
250 | stack_init(L1, L); /* init stack */ | ||
251 | lua_unlock(L); | ||
130 | return L1; | 252 | return L1; |
131 | } | 253 | } |
132 | 254 | ||
133 | 255 | ||
134 | void luaE_freethread (lua_State *L, lua_State *L1) { | 256 | void luaE_freethread (lua_State *L, lua_State *L1) { |
257 | LX *l = fromstate(L1); | ||
135 | luaF_close(L1, L1->stack); /* close all upvalues for this thread */ | 258 | luaF_close(L1, L1->stack); /* close all upvalues for this thread */ |
136 | lua_assert(L1->openupval == NULL); | 259 | lua_assert(L1->openupval == NULL); |
137 | luai_userstatefree(L1); | 260 | luai_userstatefree(L, L1); |
138 | freestack(L, L1); | 261 | freestack(L1); |
139 | luaM_freemem(L, fromstate(L1), state_size(lua_State)); | 262 | luaM_free(L, l); |
140 | } | 263 | } |
141 | 264 | ||
142 | 265 | ||
@@ -144,71 +267,57 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
144 | int i; | 267 | int i; |
145 | lua_State *L; | 268 | lua_State *L; |
146 | global_State *g; | 269 | global_State *g; |
147 | void *l = (*f)(ud, NULL, 0, state_size(LG)); | 270 | LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); |
148 | if (l == NULL) return NULL; | 271 | if (l == NULL) return NULL; |
149 | L = tostate(l); | 272 | L = &l->l.l; |
150 | g = &((LG *)L)->g; | 273 | g = &l->g; |
151 | L->next = NULL; | 274 | L->next = NULL; |
152 | L->tt = LUA_TTHREAD; | 275 | L->tt = LUA_TTHREAD; |
153 | g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); | 276 | g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); |
154 | L->marked = luaC_white(g); | 277 | L->marked = luaC_white(g); |
155 | set2bits(L->marked, FIXEDBIT, SFIXEDBIT); | 278 | g->gckind = KGC_NORMAL; |
156 | preinit_state(L, g); | 279 | preinit_state(L, g); |
157 | g->frealloc = f; | 280 | g->frealloc = f; |
158 | g->ud = ud; | 281 | g->ud = ud; |
159 | g->mainthread = L; | 282 | g->mainthread = L; |
283 | g->seed = makeseed(L); | ||
160 | g->uvhead.u.l.prev = &g->uvhead; | 284 | g->uvhead.u.l.prev = &g->uvhead; |
161 | g->uvhead.u.l.next = &g->uvhead; | 285 | g->uvhead.u.l.next = &g->uvhead; |
162 | g->GCthreshold = 0; /* mark it as unfinished state */ | 286 | g->gcrunning = 0; /* no GC while building state */ |
287 | g->GCestimate = 0; | ||
163 | g->strt.size = 0; | 288 | g->strt.size = 0; |
164 | g->strt.nuse = 0; | 289 | g->strt.nuse = 0; |
165 | g->strt.hash = NULL; | 290 | g->strt.hash = NULL; |
166 | setnilvalue(registry(L)); | 291 | setnilvalue(&g->l_registry); |
167 | luaZ_initbuffer(L, &g->buff); | 292 | luaZ_initbuffer(L, &g->buff); |
168 | g->panic = NULL; | 293 | g->panic = NULL; |
294 | g->version = NULL; | ||
169 | g->gcstate = GCSpause; | 295 | g->gcstate = GCSpause; |
170 | g->rootgc = obj2gco(L); | 296 | g->allgc = NULL; |
171 | g->sweepstrgc = 0; | 297 | g->finobj = NULL; |
172 | g->sweepgc = &g->rootgc; | 298 | g->tobefnz = NULL; |
173 | g->gray = NULL; | 299 | g->sweepgc = g->sweepfin = NULL; |
174 | g->grayagain = NULL; | 300 | g->gray = g->grayagain = NULL; |
175 | g->weak = NULL; | 301 | g->weak = g->ephemeron = g->allweak = NULL; |
176 | g->tmudata = NULL; | ||
177 | g->totalbytes = sizeof(LG); | 302 | g->totalbytes = sizeof(LG); |
303 | g->GCdebt = 0; | ||
178 | g->gcpause = LUAI_GCPAUSE; | 304 | g->gcpause = LUAI_GCPAUSE; |
305 | g->gcmajorinc = LUAI_GCMAJOR; | ||
179 | g->gcstepmul = LUAI_GCMUL; | 306 | g->gcstepmul = LUAI_GCMUL; |
180 | g->gcdept = 0; | 307 | for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; |
181 | for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL; | 308 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { |
182 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { | ||
183 | /* memory allocation error: free partial state */ | 309 | /* memory allocation error: free partial state */ |
184 | close_state(L); | 310 | close_state(L); |
185 | L = NULL; | 311 | L = NULL; |
186 | } | 312 | } |
187 | else | ||
188 | luai_userstateopen(L); | ||
189 | return L; | 313 | return L; |
190 | } | 314 | } |
191 | 315 | ||
192 | 316 | ||
193 | static void callallgcTM (lua_State *L, void *ud) { | ||
194 | UNUSED(ud); | ||
195 | luaC_callGCTM(L); /* call GC metamethods for all udata */ | ||
196 | } | ||
197 | |||
198 | |||
199 | LUA_API void lua_close (lua_State *L) { | 317 | LUA_API void lua_close (lua_State *L) { |
200 | L = G(L)->mainthread; /* only the main thread can be closed */ | 318 | L = G(L)->mainthread; /* only the main thread can be closed */ |
201 | lua_lock(L); | 319 | lua_lock(L); |
202 | luaF_close(L, L->stack); /* close all upvalues for this thread */ | ||
203 | luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ | ||
204 | L->errfunc = 0; /* no error function during GC metamethods */ | ||
205 | do { /* repeat until no more errors */ | ||
206 | L->ci = L->base_ci; | ||
207 | L->base = L->top = L->ci->base; | ||
208 | L->nCcalls = L->baseCcalls = 0; | ||
209 | } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); | ||
210 | lua_assert(G(L)->tmudata == NULL); | ||
211 | luai_userstateclose(L); | ||
212 | close_state(L); | 320 | close_state(L); |
213 | } | 321 | } |
214 | 322 | ||
323 | |||
diff --git a/apps/plugins/lua/lstate.h b/apps/plugins/lua/lstate.h index 94a6249461..daffd9aacf 100644 --- a/apps/plugins/lua/lstate.h +++ b/apps/plugins/lua/lstate.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lstate.h,v 2.82.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -14,26 +14,47 @@ | |||
14 | #include "lzio.h" | 14 | #include "lzio.h" |
15 | 15 | ||
16 | 16 | ||
17 | /* | ||
17 | 18 | ||
18 | struct lua_longjmp; /* defined in ldo.c */ | 19 | ** Some notes about garbage-collected objects: All objects in Lua must |
20 | ** be kept somehow accessible until being freed. | ||
21 | ** | ||
22 | ** Lua keeps most objects linked in list g->allgc. The link uses field | ||
23 | ** 'next' of the CommonHeader. | ||
24 | ** | ||
25 | ** Strings are kept in several lists headed by the array g->strt.hash. | ||
26 | ** | ||
27 | ** Open upvalues are not subject to independent garbage collection. They | ||
28 | ** are collected together with their respective threads. Lua keeps a | ||
29 | ** double-linked list with all open upvalues (g->uvhead) so that it can | ||
30 | ** mark objects referred by them. (They are always gray, so they must | ||
31 | ** be remarked in the atomic step. Usually their contents would be marked | ||
32 | ** when traversing the respective threads, but the thread may already be | ||
33 | ** dead, while the upvalue is still accessible through closures.) | ||
34 | ** | ||
35 | ** Objects with finalizers are kept in the list g->finobj. | ||
36 | ** | ||
37 | ** The list g->tobefnz links all objects being finalized. | ||
19 | 38 | ||
39 | */ | ||
20 | 40 | ||
21 | /* table of globals */ | ||
22 | #define gt(L) (&L->l_gt) | ||
23 | 41 | ||
24 | /* registry */ | 42 | struct lua_longjmp; /* defined in ldo.c */ |
25 | #define registry(L) (&G(L)->l_registry) | 43 | |
26 | 44 | ||
27 | 45 | ||
28 | /* extra stack space to handle TM calls and some other extras */ | 46 | /* extra stack space to handle TM calls and some other extras */ |
29 | #define EXTRA_STACK 5 | 47 | #define EXTRA_STACK 5 |
30 | 48 | ||
31 | 49 | ||
32 | #define BASIC_CI_SIZE 8 | ||
33 | |||
34 | #define BASIC_STACK_SIZE (2*LUA_MINSTACK) | 50 | #define BASIC_STACK_SIZE (2*LUA_MINSTACK) |
35 | 51 | ||
36 | 52 | ||
53 | /* kinds of Garbage Collection */ | ||
54 | #define KGC_NORMAL 0 | ||
55 | #define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ | ||
56 | #define KGC_GEN 2 /* generational collection */ | ||
57 | |||
37 | 58 | ||
38 | typedef struct stringtable { | 59 | typedef struct stringtable { |
39 | GCObject **hash; | 60 | GCObject **hash; |
@@ -43,54 +64,87 @@ typedef struct stringtable { | |||
43 | 64 | ||
44 | 65 | ||
45 | /* | 66 | /* |
46 | ** informations about a call | 67 | ** information about a call |
47 | */ | 68 | */ |
48 | typedef struct CallInfo { | 69 | typedef struct CallInfo { |
49 | StkId base; /* base for this function */ | ||
50 | StkId func; /* function index in the stack */ | 70 | StkId func; /* function index in the stack */ |
51 | StkId top; /* top for this function */ | 71 | StkId top; /* top for this function */ |
52 | const Instruction *savedpc; | 72 | struct CallInfo *previous, *next; /* dynamic call link */ |
53 | int nresults; /* expected number of results from this function */ | 73 | short nresults; /* expected number of results from this function */ |
54 | int tailcalls; /* number of tail calls lost under this entry */ | 74 | lu_byte callstatus; |
75 | ptrdiff_t extra; | ||
76 | union { | ||
77 | struct { /* only for Lua functions */ | ||
78 | StkId base; /* base for this function */ | ||
79 | const Instruction *savedpc; | ||
80 | } l; | ||
81 | struct { /* only for C functions */ | ||
82 | int ctx; /* context info. in case of yields */ | ||
83 | lua_CFunction k; /* continuation in case of yields */ | ||
84 | ptrdiff_t old_errfunc; | ||
85 | lu_byte old_allowhook; | ||
86 | lu_byte status; | ||
87 | } c; | ||
88 | } u; | ||
55 | } CallInfo; | 89 | } CallInfo; |
56 | 90 | ||
57 | 91 | ||
92 | /* | ||
93 | ** Bits in CallInfo status | ||
94 | */ | ||
95 | #define CIST_LUA (1<<0) /* call is running a Lua function */ | ||
96 | #define CIST_HOOKED (1<<1) /* call is running a debug hook */ | ||
97 | #define CIST_REENTRY (1<<2) /* call is running on same invocation of | ||
98 | luaV_execute of previous call */ | ||
99 | #define CIST_YIELDED (1<<3) /* call reentered after suspension */ | ||
100 | #define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ | ||
101 | #define CIST_STAT (1<<5) /* call has an error status (pcall) */ | ||
102 | #define CIST_TAIL (1<<6) /* call was tail called */ | ||
103 | #define CIST_HOOKYIELD (1<<7) /* last hook called yielded */ | ||
104 | |||
58 | 105 | ||
59 | #define curr_func(L) (clvalue(L->ci->func)) | 106 | #define isLua(ci) ((ci)->callstatus & CIST_LUA) |
60 | #define ci_func(ci) (clvalue((ci)->func)) | ||
61 | #define f_isLua(ci) (!ci_func(ci)->c.isC) | ||
62 | #define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) | ||
63 | 107 | ||
64 | 108 | ||
65 | /* | 109 | /* |
66 | ** `global state', shared by all threads of this state | 110 | ** `global state', shared by all threads of this state |
67 | */ | 111 | */ |
68 | typedef struct global_State { | 112 | typedef struct global_State { |
69 | stringtable strt; /* hash table for strings */ | ||
70 | lua_Alloc frealloc; /* function to reallocate memory */ | 113 | lua_Alloc frealloc; /* function to reallocate memory */ |
71 | void *ud; /* auxiliary data to `frealloc' */ | 114 | void *ud; /* auxiliary data to `frealloc' */ |
115 | lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */ | ||
116 | l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ | ||
117 | lu_mem GCmemtrav; /* memory traversed by the GC */ | ||
118 | lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ | ||
119 | stringtable strt; /* hash table for strings */ | ||
120 | TValue l_registry; | ||
121 | unsigned int seed; /* randomized seed for hashes */ | ||
72 | lu_byte currentwhite; | 122 | lu_byte currentwhite; |
73 | lu_byte gcstate; /* state of garbage collector */ | 123 | lu_byte gcstate; /* state of garbage collector */ |
124 | lu_byte gckind; /* kind of GC running */ | ||
125 | lu_byte gcrunning; /* true if GC is running */ | ||
74 | int sweepstrgc; /* position of sweep in `strt' */ | 126 | int sweepstrgc; /* position of sweep in `strt' */ |
75 | GCObject *rootgc; /* list of all collectable objects */ | 127 | GCObject *allgc; /* list of all collectable objects */ |
76 | GCObject **sweepgc; /* position of sweep in `rootgc' */ | 128 | GCObject *finobj; /* list of collectable objects with finalizers */ |
129 | GCObject **sweepgc; /* current position of sweep in list 'allgc' */ | ||
130 | GCObject **sweepfin; /* current position of sweep in list 'finobj' */ | ||
77 | GCObject *gray; /* list of gray objects */ | 131 | GCObject *gray; /* list of gray objects */ |
78 | GCObject *grayagain; /* list of objects to be traversed atomically */ | 132 | GCObject *grayagain; /* list of objects to be traversed atomically */ |
79 | GCObject *weak; /* list of weak tables (to be cleared) */ | 133 | GCObject *weak; /* list of tables with weak values */ |
80 | GCObject *tmudata; /* last element of list of userdata to be GC */ | 134 | GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ |
81 | Mbuffer buff; /* temporary buffer for string concatentation */ | 135 | GCObject *allweak; /* list of all-weak tables */ |
82 | lu_mem GCthreshold; | 136 | GCObject *tobefnz; /* list of userdata to be GC */ |
83 | lu_mem totalbytes; /* number of bytes currently allocated */ | 137 | UpVal uvhead; /* head of double-linked list of all open upvalues */ |
84 | lu_mem estimate; /* an estimate of number of bytes actually in use */ | 138 | Mbuffer buff; /* temporary buffer for string concatenation */ |
85 | lu_mem gcdept; /* how much GC is `behind schedule' */ | ||
86 | int gcpause; /* size of pause between successive GCs */ | 139 | int gcpause; /* size of pause between successive GCs */ |
140 | int gcmajorinc; /* pause between major collections (only in gen. mode) */ | ||
87 | int gcstepmul; /* GC `granularity' */ | 141 | int gcstepmul; /* GC `granularity' */ |
88 | lua_CFunction panic; /* to be called in unprotected errors */ | 142 | lua_CFunction panic; /* to be called in unprotected errors */ |
89 | TValue l_registry; | ||
90 | struct lua_State *mainthread; | 143 | struct lua_State *mainthread; |
91 | UpVal uvhead; /* head of double-linked list of all open upvalues */ | 144 | const lua_Number *version; /* pointer to version number */ |
92 | struct Table *mt[NUM_TAGS]; /* metatables for basic types */ | 145 | TString *memerrmsg; /* memory-error message */ |
93 | TString *tmname[TM_N]; /* array with tag-method names */ | 146 | TString *tmname[TM_N]; /* array with tag-method names */ |
147 | struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ | ||
94 | } global_State; | 148 | } global_State; |
95 | 149 | ||
96 | 150 | ||
@@ -101,29 +155,24 @@ struct lua_State { | |||
101 | CommonHeader; | 155 | CommonHeader; |
102 | lu_byte status; | 156 | lu_byte status; |
103 | StkId top; /* first free slot in the stack */ | 157 | StkId top; /* first free slot in the stack */ |
104 | StkId base; /* base of current function */ | ||
105 | global_State *l_G; | 158 | global_State *l_G; |
106 | CallInfo *ci; /* call info for current function */ | 159 | CallInfo *ci; /* call info for current function */ |
107 | const Instruction *savedpc; /* `savedpc' of current function */ | 160 | const Instruction *oldpc; /* last pc traced */ |
108 | StkId stack_last; /* last free slot in the stack */ | 161 | StkId stack_last; /* last free slot in the stack */ |
109 | StkId stack; /* stack base */ | 162 | StkId stack; /* stack base */ |
110 | CallInfo *end_ci; /* points after end of ci array*/ | ||
111 | CallInfo *base_ci; /* array of CallInfo's */ | ||
112 | int stacksize; | 163 | int stacksize; |
113 | int size_ci; /* size of array `base_ci' */ | 164 | unsigned short nny; /* number of non-yieldable calls in stack */ |
114 | unsigned short nCcalls; /* number of nested C calls */ | 165 | unsigned short nCcalls; /* number of nested C calls */ |
115 | unsigned short baseCcalls; /* nested C calls when resuming coroutine */ | ||
116 | lu_byte hookmask; | 166 | lu_byte hookmask; |
117 | lu_byte allowhook; | 167 | lu_byte allowhook; |
118 | int basehookcount; | 168 | int basehookcount; |
119 | int hookcount; | 169 | int hookcount; |
120 | lua_Hook hook; | 170 | lua_Hook hook; |
121 | TValue l_gt; /* table of globals */ | ||
122 | TValue env; /* temporary place for environments */ | ||
123 | GCObject *openupval; /* list of open upvalues in this stack */ | 171 | GCObject *openupval; /* list of open upvalues in this stack */ |
124 | GCObject *gclist; | 172 | GCObject *gclist; |
125 | struct lua_longjmp *errorJmp; /* current error recover point */ | 173 | struct lua_longjmp *errorJmp; /* current error recover point */ |
126 | ptrdiff_t errfunc; /* current error handling function (stack index) */ | 174 | ptrdiff_t errfunc; /* current error handling function (stack index) */ |
175 | CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ | ||
127 | }; | 176 | }; |
128 | 177 | ||
129 | 178 | ||
@@ -134,7 +183,7 @@ struct lua_State { | |||
134 | ** Union of all collectable objects | 183 | ** Union of all collectable objects |
135 | */ | 184 | */ |
136 | union GCObject { | 185 | union GCObject { |
137 | GCheader gch; | 186 | GCheader gch; /* common header */ |
138 | union TString ts; | 187 | union TString ts; |
139 | union Udata u; | 188 | union Udata u; |
140 | union Closure cl; | 189 | union Closure cl; |
@@ -145,25 +194,35 @@ union GCObject { | |||
145 | }; | 194 | }; |
146 | 195 | ||
147 | 196 | ||
197 | #define gch(o) (&(o)->gch) | ||
198 | |||
148 | /* macros to convert a GCObject into a specific value */ | 199 | /* macros to convert a GCObject into a specific value */ |
149 | #define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) | 200 | #define rawgco2ts(o) \ |
201 | check_exp(novariant((o)->gch.tt) == LUA_TSTRING, &((o)->ts)) | ||
150 | #define gco2ts(o) (&rawgco2ts(o)->tsv) | 202 | #define gco2ts(o) (&rawgco2ts(o)->tsv) |
151 | #define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) | 203 | #define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) |
152 | #define gco2u(o) (&rawgco2u(o)->uv) | 204 | #define gco2u(o) (&rawgco2u(o)->uv) |
153 | #define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) | 205 | #define gco2lcl(o) check_exp((o)->gch.tt == LUA_TLCL, &((o)->cl.l)) |
154 | #define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) | 206 | #define gco2ccl(o) check_exp((o)->gch.tt == LUA_TCCL, &((o)->cl.c)) |
207 | #define gco2cl(o) \ | ||
208 | check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl)) | ||
209 | #define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) | ||
155 | #define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) | 210 | #define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) |
156 | #define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) | 211 | #define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) |
157 | #define ngcotouv(o) \ | ||
158 | check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) | ||
159 | #define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) | 212 | #define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) |
160 | 213 | ||
161 | /* macro to convert any Lua object into a GCObject */ | 214 | /* macro to convert any Lua object into a GCObject */ |
162 | #define obj2gco(v) (cast(GCObject *, (v))) | 215 | #define obj2gco(v) (cast(GCObject *, (v))) |
163 | 216 | ||
164 | 217 | ||
165 | LUAI_FUNC lua_State *luaE_newthread (lua_State *L); | 218 | /* actual number of total bytes allocated */ |
219 | #define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt) | ||
220 | |||
221 | LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); | ||
166 | LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); | 222 | LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); |
223 | LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); | ||
224 | LUAI_FUNC void luaE_freeCI (lua_State *L); | ||
225 | |||
167 | 226 | ||
168 | #endif | 227 | #endif |
169 | 228 | ||
diff --git a/apps/plugins/lua/lstring.c b/apps/plugins/lua/lstring.c index 49113151cc..af96c89c18 100644 --- a/apps/plugins/lua/lstring.c +++ b/apps/plugins/lua/lstring.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ | 2 | ** $Id: lstring.c,v 2.26.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** String table (keeps all strings handled by Lua) | 3 | ** String table (keeps all strings handled by Lua) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -18,78 +18,157 @@ | |||
18 | #include "lstring.h" | 18 | #include "lstring.h" |
19 | 19 | ||
20 | 20 | ||
21 | /* | ||
22 | ** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to | ||
23 | ** compute its hash | ||
24 | */ | ||
25 | #if !defined(LUAI_HASHLIMIT) | ||
26 | #define LUAI_HASHLIMIT 5 | ||
27 | #endif | ||
28 | |||
29 | |||
30 | /* | ||
31 | ** equality for long strings | ||
32 | */ | ||
33 | int luaS_eqlngstr (TString *a, TString *b) { | ||
34 | size_t len = a->tsv.len; | ||
35 | lua_assert(a->tsv.tt == LUA_TLNGSTR && b->tsv.tt == LUA_TLNGSTR); | ||
36 | return (a == b) || /* same instance or... */ | ||
37 | ((len == b->tsv.len) && /* equal length and ... */ | ||
38 | (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ | ||
39 | } | ||
40 | |||
41 | |||
42 | /* | ||
43 | ** equality for strings | ||
44 | */ | ||
45 | int luaS_eqstr (TString *a, TString *b) { | ||
46 | return (a->tsv.tt == b->tsv.tt) && | ||
47 | (a->tsv.tt == LUA_TSHRSTR ? eqshrstr(a, b) : luaS_eqlngstr(a, b)); | ||
48 | } | ||
49 | |||
21 | 50 | ||
51 | unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { | ||
52 | unsigned int h = seed ^ cast(unsigned int, l); | ||
53 | size_t l1; | ||
54 | size_t step = (l >> LUAI_HASHLIMIT) + 1; | ||
55 | for (l1 = l; l1 >= step; l1 -= step) | ||
56 | h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1])); | ||
57 | return h; | ||
58 | } | ||
59 | |||
60 | |||
61 | /* | ||
62 | ** resizes the string table | ||
63 | */ | ||
22 | void luaS_resize (lua_State *L, int newsize) { | 64 | void luaS_resize (lua_State *L, int newsize) { |
23 | GCObject **newhash; | ||
24 | stringtable *tb; | ||
25 | int i; | 65 | int i; |
26 | if (G(L)->gcstate == GCSsweepstring) | 66 | stringtable *tb = &G(L)->strt; |
27 | return; /* cannot resize during GC traverse */ | 67 | /* cannot resize while GC is traversing strings */ |
28 | newhash = luaM_newvector(L, newsize, GCObject *); | 68 | luaC_runtilstate(L, ~bitmask(GCSsweepstring)); |
29 | tb = &G(L)->strt; | 69 | if (newsize > tb->size) { |
30 | for (i=0; i<newsize; i++) newhash[i] = NULL; | 70 | luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); |
71 | for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL; | ||
72 | } | ||
31 | /* rehash */ | 73 | /* rehash */ |
32 | for (i=0; i<tb->size; i++) { | 74 | for (i=0; i<tb->size; i++) { |
33 | GCObject *p = tb->hash[i]; | 75 | GCObject *p = tb->hash[i]; |
76 | tb->hash[i] = NULL; | ||
34 | while (p) { /* for each node in the list */ | 77 | while (p) { /* for each node in the list */ |
35 | GCObject *next = p->gch.next; /* save next */ | 78 | GCObject *next = gch(p)->next; /* save next */ |
36 | unsigned int h = gco2ts(p)->hash; | 79 | unsigned int h = lmod(gco2ts(p)->hash, newsize); /* new position */ |
37 | int h1 = lmod(h, newsize); /* new position */ | 80 | gch(p)->next = tb->hash[h]; /* chain it */ |
38 | lua_assert(cast_int(h%newsize) == lmod(h, newsize)); | 81 | tb->hash[h] = p; |
39 | p->gch.next = newhash[h1]; /* chain it */ | 82 | resetoldbit(p); /* see MOVE OLD rule */ |
40 | newhash[h1] = p; | ||
41 | p = next; | 83 | p = next; |
42 | } | 84 | } |
43 | } | 85 | } |
44 | luaM_freearray(L, tb->hash, tb->size, TString *); | 86 | if (newsize < tb->size) { |
87 | /* shrinking slice must be empty */ | ||
88 | lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); | ||
89 | luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); | ||
90 | } | ||
45 | tb->size = newsize; | 91 | tb->size = newsize; |
46 | tb->hash = newhash; | ||
47 | } | 92 | } |
48 | 93 | ||
49 | 94 | ||
50 | static TString *newlstr (lua_State *L, const char *str, size_t l, | 95 | /* |
51 | unsigned int h) { | 96 | ** creates a new string object |
97 | */ | ||
98 | static TString *createstrobj (lua_State *L, const char *str, size_t l, | ||
99 | int tag, unsigned int h, GCObject **list) { | ||
52 | TString *ts; | 100 | TString *ts; |
53 | stringtable *tb; | 101 | size_t totalsize; /* total size of TString object */ |
54 | if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) | 102 | totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); |
55 | luaM_toobig(L); | 103 | ts = &luaC_newobj(L, tag, totalsize, list, 0)->ts; |
56 | ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); | ||
57 | ts->tsv.len = l; | 104 | ts->tsv.len = l; |
58 | ts->tsv.hash = h; | 105 | ts->tsv.hash = h; |
59 | ts->tsv.marked = luaC_white(G(L)); | 106 | ts->tsv.extra = 0; |
60 | ts->tsv.tt = LUA_TSTRING; | ||
61 | ts->tsv.reserved = 0; | ||
62 | memcpy(ts+1, str, l*sizeof(char)); | 107 | memcpy(ts+1, str, l*sizeof(char)); |
63 | ((char *)(ts+1))[l] = '\0'; /* ending 0 */ | 108 | ((char *)(ts+1))[l] = '\0'; /* ending 0 */ |
64 | tb = &G(L)->strt; | ||
65 | h = lmod(h, tb->size); | ||
66 | ts->tsv.next = tb->hash[h]; /* chain new entry */ | ||
67 | tb->hash[h] = obj2gco(ts); | ||
68 | tb->nuse++; | ||
69 | if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) | ||
70 | luaS_resize(L, tb->size*2); /* too crowded */ | ||
71 | return ts; | 109 | return ts; |
72 | } | 110 | } |
73 | 111 | ||
74 | 112 | ||
75 | TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { | 113 | /* |
114 | ** creates a new short string, inserting it into string table | ||
115 | */ | ||
116 | static TString *newshrstr (lua_State *L, const char *str, size_t l, | ||
117 | unsigned int h) { | ||
118 | GCObject **list; /* (pointer to) list where it will be inserted */ | ||
119 | stringtable *tb = &G(L)->strt; | ||
120 | TString *s; | ||
121 | if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) | ||
122 | luaS_resize(L, tb->size*2); /* too crowded */ | ||
123 | list = &tb->hash[lmod(h, tb->size)]; | ||
124 | s = createstrobj(L, str, l, LUA_TSHRSTR, h, list); | ||
125 | tb->nuse++; | ||
126 | return s; | ||
127 | } | ||
128 | |||
129 | |||
130 | /* | ||
131 | ** checks whether short string exists and reuses it or creates a new one | ||
132 | */ | ||
133 | static TString *internshrstr (lua_State *L, const char *str, size_t l) { | ||
76 | GCObject *o; | 134 | GCObject *o; |
77 | unsigned int h = cast(unsigned int, l); /* seed */ | 135 | global_State *g = G(L); |
78 | size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ | 136 | unsigned int h = luaS_hash(str, l, g->seed); |
79 | size_t l1; | 137 | for (o = g->strt.hash[lmod(h, g->strt.size)]; |
80 | for (l1=l; l1>=step; l1-=step) /* compute hash */ | ||
81 | h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); | ||
82 | for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; | ||
83 | o != NULL; | 138 | o != NULL; |
84 | o = o->gch.next) { | 139 | o = gch(o)->next) { |
85 | TString *ts = rawgco2ts(o); | 140 | TString *ts = rawgco2ts(o); |
86 | if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { | 141 | if (h == ts->tsv.hash && |
87 | /* string may be dead */ | 142 | l == ts->tsv.len && |
88 | if (isdead(G(L), o)) changewhite(o); | 143 | (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { |
144 | if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */ | ||
145 | changewhite(o); /* resurrect it */ | ||
89 | return ts; | 146 | return ts; |
90 | } | 147 | } |
91 | } | 148 | } |
92 | return newlstr(L, str, l, h); /* not found */ | 149 | return newshrstr(L, str, l, h); /* not found; create a new string */ |
150 | } | ||
151 | |||
152 | |||
153 | /* | ||
154 | ** new string (with explicit length) | ||
155 | */ | ||
156 | TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { | ||
157 | if (l <= LUAI_MAXSHORTLEN) /* short string? */ | ||
158 | return internshrstr(L, str, l); | ||
159 | else { | ||
160 | if (l + 1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) | ||
161 | luaM_toobig(L); | ||
162 | return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed, NULL); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | |||
167 | /* | ||
168 | ** new zero-terminated string | ||
169 | */ | ||
170 | TString *luaS_new (lua_State *L, const char *str) { | ||
171 | return luaS_newlstr(L, str, strlen(str)); | ||
93 | } | 172 | } |
94 | 173 | ||
95 | 174 | ||
@@ -97,15 +176,10 @@ Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { | |||
97 | Udata *u; | 176 | Udata *u; |
98 | if (s > MAX_SIZET - sizeof(Udata)) | 177 | if (s > MAX_SIZET - sizeof(Udata)) |
99 | luaM_toobig(L); | 178 | luaM_toobig(L); |
100 | u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); | 179 | u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u; |
101 | u->uv.marked = luaC_white(G(L)); /* is not finalized */ | ||
102 | u->uv.tt = LUA_TUSERDATA; | ||
103 | u->uv.len = s; | 180 | u->uv.len = s; |
104 | u->uv.metatable = NULL; | 181 | u->uv.metatable = NULL; |
105 | u->uv.env = e; | 182 | u->uv.env = e; |
106 | /* chain it on udata list (after main thread) */ | ||
107 | u->uv.next = G(L)->mainthread->next; | ||
108 | G(L)->mainthread->next = obj2gco(u); | ||
109 | return u; | 183 | return u; |
110 | } | 184 | } |
111 | 185 | ||
diff --git a/apps/plugins/lua/lstring.h b/apps/plugins/lua/lstring.h index c88e4c12a9..260e7f169b 100644 --- a/apps/plugins/lua/lstring.h +++ b/apps/plugins/lua/lstring.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lstring.h,v 1.49.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** String table (keep all strings handled by Lua) | 3 | ** String table (keep all strings handled by Lua) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -7,7 +7,6 @@ | |||
7 | #ifndef lstring_h | 7 | #ifndef lstring_h |
8 | #define lstring_h | 8 | #define lstring_h |
9 | 9 | ||
10 | |||
11 | #include "lgc.h" | 10 | #include "lgc.h" |
12 | #include "lobject.h" | 11 | #include "lobject.h" |
13 | #include "lstate.h" | 12 | #include "lstate.h" |
@@ -17,15 +16,31 @@ | |||
17 | 16 | ||
18 | #define sizeudata(u) (sizeof(union Udata)+(u)->len) | 17 | #define sizeudata(u) (sizeof(union Udata)+(u)->len) |
19 | 18 | ||
20 | #define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) | ||
21 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ | 19 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ |
22 | (sizeof(s)/sizeof(char))-1)) | 20 | (sizeof(s)/sizeof(char))-1)) |
23 | 21 | ||
24 | #define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) | 22 | #define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) |
25 | 23 | ||
24 | |||
25 | /* | ||
26 | ** test whether a string is a reserved word | ||
27 | */ | ||
28 | #define isreserved(s) ((s)->tsv.tt == LUA_TSHRSTR && (s)->tsv.extra > 0) | ||
29 | |||
30 | |||
31 | /* | ||
32 | ** equality for short strings, which are always internalized | ||
33 | */ | ||
34 | #define eqshrstr(a,b) check_exp((a)->tsv.tt == LUA_TSHRSTR, (a) == (b)) | ||
35 | |||
36 | |||
37 | LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); | ||
38 | LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); | ||
39 | LUAI_FUNC int luaS_eqstr (TString *a, TString *b); | ||
26 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize); | 40 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize); |
27 | LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); | 41 | LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); |
28 | LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); | 42 | LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); |
43 | LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); | ||
29 | 44 | ||
30 | 45 | ||
31 | #endif | 46 | #endif |
diff --git a/apps/plugins/lua/lstrlib.c b/apps/plugins/lua/lstrlib.c index 3d6103692f..04cc2f60d6 100644 --- a/apps/plugins/lua/lstrlib.c +++ b/apps/plugins/lua/lstrlib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ | 2 | ** $Id: lstrlib.c,v 1.178.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Standard library for string operations and pattern-matching | 3 | ** Standard library for string operations and pattern-matching |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -20,47 +20,58 @@ | |||
20 | #include "lualib.h" | 20 | #include "lualib.h" |
21 | 21 | ||
22 | 22 | ||
23 | /* | ||
24 | ** maximum number of captures that a pattern can do during | ||
25 | ** pattern-matching. This limit is arbitrary. | ||
26 | */ | ||
27 | #if !defined(LUA_MAXCAPTURES) | ||
28 | #define LUA_MAXCAPTURES 32 | ||
29 | #endif | ||
30 | |||
31 | |||
23 | /* macro to `unsign' a character */ | 32 | /* macro to `unsign' a character */ |
24 | #define uchar(c) ((unsigned char)(c)) | 33 | #define uchar(c) ((unsigned char)(c)) |
25 | 34 | ||
26 | 35 | ||
27 | 36 | ||
28 | static int str_len (lua_State *L) { | 37 | static int str_len (lua_State *L) { |
29 | size_t l; | 38 | size_t l; |
30 | luaL_checklstring(L, 1, &l); | 39 | luaL_checklstring(L, 1, &l); |
31 | lua_pushinteger(L, l); | 40 | lua_pushinteger(L, (lua_Integer)l); |
32 | return 1; | 41 | return 1; |
33 | } | 42 | } |
34 | 43 | ||
35 | 44 | ||
36 | static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { | 45 | /* translate a relative string position: negative means back from end */ |
37 | /* relative string position: negative means back from end */ | 46 | static size_t posrelat (ptrdiff_t pos, size_t len) { |
38 | if (pos < 0) pos += (ptrdiff_t)len + 1; | 47 | if (pos >= 0) return (size_t)pos; |
39 | return (pos >= 0) ? pos : 0; | 48 | else if (0u - (size_t)pos > len) return 0; |
49 | else return len - ((size_t)-pos) + 1; | ||
40 | } | 50 | } |
41 | 51 | ||
42 | 52 | ||
43 | static int str_sub (lua_State *L) { | 53 | static int str_sub (lua_State *L) { |
44 | size_t l; | 54 | size_t l; |
45 | const char *s = luaL_checklstring(L, 1, &l); | 55 | const char *s = luaL_checklstring(L, 1, &l); |
46 | ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); | 56 | size_t start = posrelat(luaL_checkinteger(L, 2), l); |
47 | ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); | 57 | size_t end = posrelat(luaL_optinteger(L, 3, -1), l); |
48 | if (start < 1) start = 1; | 58 | if (start < 1) start = 1; |
49 | if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; | 59 | if (end > l) end = l; |
50 | if (start <= end) | 60 | if (start <= end) |
51 | lua_pushlstring(L, s+start-1, end-start+1); | 61 | lua_pushlstring(L, s + start - 1, end - start + 1); |
52 | else lua_pushliteral(L, ""); | 62 | else lua_pushliteral(L, ""); |
53 | return 1; | 63 | return 1; |
54 | } | 64 | } |
55 | 65 | ||
56 | 66 | ||
57 | static int str_reverse (lua_State *L) { | 67 | static int str_reverse (lua_State *L) { |
58 | size_t l; | 68 | size_t l, i; |
59 | luaL_Buffer b; | 69 | luaL_Buffer b; |
60 | const char *s = luaL_checklstring(L, 1, &l); | 70 | const char *s = luaL_checklstring(L, 1, &l); |
61 | luaL_buffinit(L, &b); | 71 | char *p = luaL_buffinitsize(L, &b, l); |
62 | while (l--) luaL_addchar(&b, s[l]); | 72 | for (i = 0; i < l; i++) |
63 | luaL_pushresult(&b); | 73 | p[i] = s[l - i - 1]; |
74 | luaL_pushresultsize(&b, l); | ||
64 | return 1; | 75 | return 1; |
65 | } | 76 | } |
66 | 77 | ||
@@ -70,10 +81,10 @@ static int str_lower (lua_State *L) { | |||
70 | size_t i; | 81 | size_t i; |
71 | luaL_Buffer b; | 82 | luaL_Buffer b; |
72 | const char *s = luaL_checklstring(L, 1, &l); | 83 | const char *s = luaL_checklstring(L, 1, &l); |
73 | luaL_buffinit(L, &b); | 84 | char *p = luaL_buffinitsize(L, &b, l); |
74 | for (i=0; i<l; i++) | 85 | for (i=0; i<l; i++) |
75 | luaL_addchar(&b, tolower(uchar(s[i]))); | 86 | p[i] = tolower(uchar(s[i])); |
76 | luaL_pushresult(&b); | 87 | luaL_pushresultsize(&b, l); |
77 | return 1; | 88 | return 1; |
78 | } | 89 | } |
79 | 90 | ||
@@ -83,22 +94,38 @@ static int str_upper (lua_State *L) { | |||
83 | size_t i; | 94 | size_t i; |
84 | luaL_Buffer b; | 95 | luaL_Buffer b; |
85 | const char *s = luaL_checklstring(L, 1, &l); | 96 | const char *s = luaL_checklstring(L, 1, &l); |
86 | luaL_buffinit(L, &b); | 97 | char *p = luaL_buffinitsize(L, &b, l); |
87 | for (i=0; i<l; i++) | 98 | for (i=0; i<l; i++) |
88 | luaL_addchar(&b, toupper(uchar(s[i]))); | 99 | p[i] = toupper(uchar(s[i])); |
89 | luaL_pushresult(&b); | 100 | luaL_pushresultsize(&b, l); |
90 | return 1; | 101 | return 1; |
91 | } | 102 | } |
92 | 103 | ||
104 | |||
105 | /* reasonable limit to avoid arithmetic overflow */ | ||
106 | #define MAXSIZE ((~(size_t)0) >> 1) | ||
107 | |||
93 | static int str_rep (lua_State *L) { | 108 | static int str_rep (lua_State *L) { |
94 | size_t l; | 109 | size_t l, lsep; |
95 | luaL_Buffer b; | ||
96 | const char *s = luaL_checklstring(L, 1, &l); | 110 | const char *s = luaL_checklstring(L, 1, &l); |
97 | int n = luaL_checkint(L, 2); | 111 | int n = luaL_checkint(L, 2); |
98 | luaL_buffinit(L, &b); | 112 | const char *sep = luaL_optlstring(L, 3, "", &lsep); |
99 | while (n-- > 0) | 113 | if (n <= 0) lua_pushliteral(L, ""); |
100 | luaL_addlstring(&b, s, l); | 114 | else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */ |
101 | luaL_pushresult(&b); | 115 | return luaL_error(L, "resulting string too large"); |
116 | else { | ||
117 | size_t totallen = n * l + (n - 1) * lsep; | ||
118 | luaL_Buffer b; | ||
119 | char *p = luaL_buffinitsize(L, &b, totallen); | ||
120 | while (n-- > 1) { /* first n-1 copies (followed by separator) */ | ||
121 | memcpy(p, s, l * sizeof(char)); p += l; | ||
122 | if (lsep > 0) { /* avoid empty 'memcpy' (may be expensive) */ | ||
123 | memcpy(p, sep, lsep * sizeof(char)); p += lsep; | ||
124 | } | ||
125 | } | ||
126 | memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ | ||
127 | luaL_pushresultsize(&b, totallen); | ||
128 | } | ||
102 | return 1; | 129 | return 1; |
103 | } | 130 | } |
104 | 131 | ||
@@ -106,15 +133,15 @@ static int str_rep (lua_State *L) { | |||
106 | static int str_byte (lua_State *L) { | 133 | static int str_byte (lua_State *L) { |
107 | size_t l; | 134 | size_t l; |
108 | const char *s = luaL_checklstring(L, 1, &l); | 135 | const char *s = luaL_checklstring(L, 1, &l); |
109 | ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); | 136 | size_t posi = posrelat(luaL_optinteger(L, 2, 1), l); |
110 | ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); | 137 | size_t pose = posrelat(luaL_optinteger(L, 3, posi), l); |
111 | int n, i; | 138 | int n, i; |
112 | if (posi <= 0) posi = 1; | 139 | if (posi < 1) posi = 1; |
113 | if ((size_t)pose > l) pose = l; | 140 | if (pose > l) pose = l; |
114 | if (posi > pose) return 0; /* empty interval; return no values */ | 141 | if (posi > pose) return 0; /* empty interval; return no values */ |
115 | n = (int)(pose - posi + 1); | 142 | n = (int)(pose - posi + 1); |
116 | if (posi + n <= pose) /* overflow? */ | 143 | if (posi + n <= pose) /* (size_t -> int) overflow? */ |
117 | luaL_error(L, "string slice too long"); | 144 | return luaL_error(L, "string slice too long"); |
118 | luaL_checkstack(L, n, "string slice too long"); | 145 | luaL_checkstack(L, n, "string slice too long"); |
119 | for (i=0; i<n; i++) | 146 | for (i=0; i<n; i++) |
120 | lua_pushinteger(L, uchar(s[posi+i-1])); | 147 | lua_pushinteger(L, uchar(s[posi+i-1])); |
@@ -126,13 +153,13 @@ static int str_char (lua_State *L) { | |||
126 | int n = lua_gettop(L); /* number of arguments */ | 153 | int n = lua_gettop(L); /* number of arguments */ |
127 | int i; | 154 | int i; |
128 | luaL_Buffer b; | 155 | luaL_Buffer b; |
129 | luaL_buffinit(L, &b); | 156 | char *p = luaL_buffinitsize(L, &b, n); |
130 | for (i=1; i<=n; i++) { | 157 | for (i=1; i<=n; i++) { |
131 | int c = luaL_checkint(L, i); | 158 | int c = luaL_checkint(L, i); |
132 | luaL_argcheck(L, uchar(c) == c, i, "invalid value"); | 159 | luaL_argcheck(L, uchar(c) == c, i, "value out of range"); |
133 | luaL_addchar(&b, uchar(c)); | 160 | p[i - 1] = uchar(c); |
134 | } | 161 | } |
135 | luaL_pushresult(&b); | 162 | luaL_pushresultsize(&b, n); |
136 | return 1; | 163 | return 1; |
137 | } | 164 | } |
138 | 165 | ||
@@ -150,7 +177,7 @@ static int str_dump (lua_State *L) { | |||
150 | lua_settop(L, 1); | 177 | lua_settop(L, 1); |
151 | luaL_buffinit(L,&b); | 178 | luaL_buffinit(L,&b); |
152 | if (lua_dump(L, writer, &b) != 0) | 179 | if (lua_dump(L, writer, &b) != 0) |
153 | luaL_error(L, "unable to dump given function"); | 180 | return luaL_error(L, "unable to dump given function"); |
154 | luaL_pushresult(&b); | 181 | luaL_pushresult(&b); |
155 | return 1; | 182 | return 1; |
156 | } | 183 | } |
@@ -167,9 +194,12 @@ static int str_dump (lua_State *L) { | |||
167 | #define CAP_UNFINISHED (-1) | 194 | #define CAP_UNFINISHED (-1) |
168 | #define CAP_POSITION (-2) | 195 | #define CAP_POSITION (-2) |
169 | 196 | ||
197 | |||
170 | typedef struct MatchState { | 198 | typedef struct MatchState { |
199 | int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ | ||
171 | const char *src_init; /* init of source string */ | 200 | const char *src_init; /* init of source string */ |
172 | const char *src_end; /* end (`\0') of source string */ | 201 | const char *src_end; /* end ('\0') of source string */ |
202 | const char *p_end; /* end ('\0') of pattern */ | ||
173 | lua_State *L; | 203 | lua_State *L; |
174 | int level; /* total number of captures (finished or unfinished) */ | 204 | int level; /* total number of captures (finished or unfinished) */ |
175 | struct { | 205 | struct { |
@@ -179,6 +209,16 @@ typedef struct MatchState { | |||
179 | } MatchState; | 209 | } MatchState; |
180 | 210 | ||
181 | 211 | ||
212 | /* recursive function */ | ||
213 | static const char *match (MatchState *ms, const char *s, const char *p); | ||
214 | |||
215 | |||
216 | /* maximum recursion depth for 'match' */ | ||
217 | #if !defined(MAXCCALLS) | ||
218 | #define MAXCCALLS 200 | ||
219 | #endif | ||
220 | |||
221 | |||
182 | #define L_ESC '%' | 222 | #define L_ESC '%' |
183 | #define SPECIALS "^$*+?.([%-" | 223 | #define SPECIALS "^$*+?.([%-" |
184 | 224 | ||
@@ -186,7 +226,7 @@ typedef struct MatchState { | |||
186 | static int check_capture (MatchState *ms, int l) { | 226 | static int check_capture (MatchState *ms, int l) { |
187 | l -= '1'; | 227 | l -= '1'; |
188 | if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) | 228 | if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) |
189 | return luaL_error(ms->L, "invalid capture index"); | 229 | return luaL_error(ms->L, "invalid capture index %%%d", l + 1); |
190 | return l; | 230 | return l; |
191 | } | 231 | } |
192 | 232 | ||
@@ -202,16 +242,16 @@ static int capture_to_close (MatchState *ms) { | |||
202 | static const char *classend (MatchState *ms, const char *p) { | 242 | static const char *classend (MatchState *ms, const char *p) { |
203 | switch (*p++) { | 243 | switch (*p++) { |
204 | case L_ESC: { | 244 | case L_ESC: { |
205 | if (*p == '\0') | 245 | if (p == ms->p_end) |
206 | luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); | 246 | luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); |
207 | return p+1; | 247 | return p+1; |
208 | } | 248 | } |
209 | case '[': { | 249 | case '[': { |
210 | if (*p == '^') p++; | 250 | if (*p == '^') p++; |
211 | do { /* look for a `]' */ | 251 | do { /* look for a `]' */ |
212 | if (*p == '\0') | 252 | if (p == ms->p_end) |
213 | luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); | 253 | luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); |
214 | if (*(p++) == L_ESC && *p != '\0') | 254 | if (*(p++) == L_ESC && p < ms->p_end) |
215 | p++; /* skip escapes (e.g. `%]') */ | 255 | p++; /* skip escapes (e.g. `%]') */ |
216 | } while (*p != ']'); | 256 | } while (*p != ']'); |
217 | return p+1; | 257 | return p+1; |
@@ -229,13 +269,14 @@ static int match_class (int c, int cl) { | |||
229 | case 'a' : res = isalpha(c); break; | 269 | case 'a' : res = isalpha(c); break; |
230 | case 'c' : res = iscntrl(c); break; | 270 | case 'c' : res = iscntrl(c); break; |
231 | case 'd' : res = isdigit(c); break; | 271 | case 'd' : res = isdigit(c); break; |
272 | case 'g' : res = isgraph(c); break; | ||
232 | case 'l' : res = islower(c); break; | 273 | case 'l' : res = islower(c); break; |
233 | case 'p' : res = ispunct(c); break; | 274 | case 'p' : res = ispunct(c); break; |
234 | case 's' : res = isspace(c); break; | 275 | case 's' : res = isspace(c); break; |
235 | case 'u' : res = isupper(c); break; | 276 | case 'u' : res = isupper(c); break; |
236 | case 'w' : res = isalnum(c); break; | 277 | case 'w' : res = isalnum(c); break; |
237 | case 'x' : res = isxdigit(c); break; | 278 | case 'x' : res = isxdigit(c); break; |
238 | case 'z' : res = (c == 0); break; | 279 | case 'z' : res = (c == 0); break; /* deprecated option */ |
239 | default: return (cl == c); | 280 | default: return (cl == c); |
240 | } | 281 | } |
241 | return (islower(cl) ? res : !res); | 282 | return (islower(cl) ? res : !res); |
@@ -265,23 +306,27 @@ static int matchbracketclass (int c, const char *p, const char *ec) { | |||
265 | } | 306 | } |
266 | 307 | ||
267 | 308 | ||
268 | static int singlematch (int c, const char *p, const char *ep) { | 309 | static int singlematch (MatchState *ms, const char *s, const char *p, |
269 | switch (*p) { | 310 | const char *ep) { |
270 | case '.': return 1; /* matches any char */ | 311 | if (s >= ms->src_end) |
271 | case L_ESC: return match_class(c, uchar(*(p+1))); | 312 | return 0; |
272 | case '[': return matchbracketclass(c, p, ep-1); | 313 | else { |
273 | default: return (uchar(*p) == c); | 314 | int c = uchar(*s); |
315 | switch (*p) { | ||
316 | case '.': return 1; /* matches any char */ | ||
317 | case L_ESC: return match_class(c, uchar(*(p+1))); | ||
318 | case '[': return matchbracketclass(c, p, ep-1); | ||
319 | default: return (uchar(*p) == c); | ||
320 | } | ||
274 | } | 321 | } |
275 | } | 322 | } |
276 | 323 | ||
277 | 324 | ||
278 | static const char *match (MatchState *ms, const char *s, const char *p); | ||
279 | |||
280 | |||
281 | static const char *matchbalance (MatchState *ms, const char *s, | 325 | static const char *matchbalance (MatchState *ms, const char *s, |
282 | const char *p) { | 326 | const char *p) { |
283 | if (*p == 0 || *(p+1) == 0) | 327 | if (p >= ms->p_end - 1) |
284 | luaL_error(ms->L, "unbalanced pattern"); | 328 | luaL_error(ms->L, "malformed pattern " |
329 | "(missing arguments to " LUA_QL("%%b") ")"); | ||
285 | if (*s != *p) return NULL; | 330 | if (*s != *p) return NULL; |
286 | else { | 331 | else { |
287 | int b = *p; | 332 | int b = *p; |
@@ -301,7 +346,7 @@ static const char *matchbalance (MatchState *ms, const char *s, | |||
301 | static const char *max_expand (MatchState *ms, const char *s, | 346 | static const char *max_expand (MatchState *ms, const char *s, |
302 | const char *p, const char *ep) { | 347 | const char *p, const char *ep) { |
303 | ptrdiff_t i = 0; /* counts maximum expand for item */ | 348 | ptrdiff_t i = 0; /* counts maximum expand for item */ |
304 | while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep)) | 349 | while (singlematch(ms, s + i, p, ep)) |
305 | i++; | 350 | i++; |
306 | /* keeps trying to match with the maximum repetitions */ | 351 | /* keeps trying to match with the maximum repetitions */ |
307 | while (i>=0) { | 352 | while (i>=0) { |
@@ -319,7 +364,7 @@ static const char *min_expand (MatchState *ms, const char *s, | |||
319 | const char *res = match(ms, s, ep+1); | 364 | const char *res = match(ms, s, ep+1); |
320 | if (res != NULL) | 365 | if (res != NULL) |
321 | return res; | 366 | return res; |
322 | else if (s<ms->src_end && singlematch(uchar(*s), p, ep)) | 367 | else if (singlematch(ms, s, p, ep)) |
323 | s++; /* try with one more repetition */ | 368 | s++; /* try with one more repetition */ |
324 | else return NULL; | 369 | else return NULL; |
325 | } | 370 | } |
@@ -363,80 +408,105 @@ static const char *match_capture (MatchState *ms, const char *s, int l) { | |||
363 | 408 | ||
364 | 409 | ||
365 | static const char *match (MatchState *ms, const char *s, const char *p) { | 410 | static const char *match (MatchState *ms, const char *s, const char *p) { |
411 | if (ms->matchdepth-- == 0) | ||
412 | luaL_error(ms->L, "pattern too complex"); | ||
366 | init: /* using goto's to optimize tail recursion */ | 413 | init: /* using goto's to optimize tail recursion */ |
367 | switch (*p) { | 414 | if (p != ms->p_end) { /* end of pattern? */ |
368 | case '(': { /* start capture */ | 415 | switch (*p) { |
369 | if (*(p+1) == ')') /* position capture? */ | 416 | case '(': { /* start capture */ |
370 | return start_capture(ms, s, p+2, CAP_POSITION); | 417 | if (*(p + 1) == ')') /* position capture? */ |
371 | else | 418 | s = start_capture(ms, s, p + 2, CAP_POSITION); |
372 | return start_capture(ms, s, p+1, CAP_UNFINISHED); | 419 | else |
373 | } | 420 | s = start_capture(ms, s, p + 1, CAP_UNFINISHED); |
374 | case ')': { /* end capture */ | 421 | break; |
375 | return end_capture(ms, s, p+1); | 422 | } |
376 | } | 423 | case ')': { /* end capture */ |
377 | case L_ESC: { | 424 | s = end_capture(ms, s, p + 1); |
378 | switch (*(p+1)) { | 425 | break; |
379 | case 'b': { /* balanced string? */ | 426 | } |
380 | s = matchbalance(ms, s, p+2); | 427 | case '$': { |
381 | if (s == NULL) return NULL; | 428 | if ((p + 1) != ms->p_end) /* is the `$' the last char in pattern? */ |
382 | p+=4; goto init; /* else return match(ms, s, p+4); */ | 429 | goto dflt; /* no; go to default */ |
383 | } | 430 | s = (s == ms->src_end) ? s : NULL; /* check end of string */ |
384 | case 'f': { /* frontier? */ | 431 | break; |
385 | const char *ep; char previous; | 432 | } |
386 | p += 2; | 433 | case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ |
387 | if (*p != '[') | 434 | switch (*(p + 1)) { |
388 | luaL_error(ms->L, "missing " LUA_QL("[") " after " | 435 | case 'b': { /* balanced string? */ |
389 | LUA_QL("%%f") " in pattern"); | 436 | s = matchbalance(ms, s, p + 2); |
390 | ep = classend(ms, p); /* points to what is next */ | 437 | if (s != NULL) { |
391 | previous = (s == ms->src_init) ? '\0' : *(s-1); | 438 | p += 4; goto init; /* return match(ms, s, p + 4); */ |
392 | if (matchbracketclass(uchar(previous), p, ep-1) || | 439 | } /* else fail (s == NULL) */ |
393 | !matchbracketclass(uchar(*s), p, ep-1)) return NULL; | 440 | break; |
394 | p=ep; goto init; /* else return match(ms, s, ep); */ | 441 | } |
395 | } | 442 | case 'f': { /* frontier? */ |
396 | default: { | 443 | const char *ep; char previous; |
397 | if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ | 444 | p += 2; |
398 | s = match_capture(ms, s, uchar(*(p+1))); | 445 | if (*p != '[') |
399 | if (s == NULL) return NULL; | 446 | luaL_error(ms->L, "missing " LUA_QL("[") " after " |
400 | p+=2; goto init; /* else return match(ms, s, p+2) */ | 447 | LUA_QL("%%f") " in pattern"); |
448 | ep = classend(ms, p); /* points to what is next */ | ||
449 | previous = (s == ms->src_init) ? '\0' : *(s - 1); | ||
450 | if (!matchbracketclass(uchar(previous), p, ep - 1) && | ||
451 | matchbracketclass(uchar(*s), p, ep - 1)) { | ||
452 | p = ep; goto init; /* return match(ms, s, ep); */ | ||
453 | } | ||
454 | s = NULL; /* match failed */ | ||
455 | break; | ||
401 | } | 456 | } |
402 | goto dflt; /* case default */ | 457 | case '0': case '1': case '2': case '3': |
458 | case '4': case '5': case '6': case '7': | ||
459 | case '8': case '9': { /* capture results (%0-%9)? */ | ||
460 | s = match_capture(ms, s, uchar(*(p + 1))); | ||
461 | if (s != NULL) { | ||
462 | p += 2; goto init; /* return match(ms, s, p + 2) */ | ||
463 | } | ||
464 | break; | ||
465 | } | ||
466 | default: goto dflt; | ||
403 | } | 467 | } |
468 | break; | ||
404 | } | 469 | } |
405 | } | 470 | default: dflt: { /* pattern class plus optional suffix */ |
406 | case '\0': { /* end of pattern */ | 471 | const char *ep = classend(ms, p); /* points to optional suffix */ |
407 | return s; /* match succeeded */ | 472 | /* does not match at least once? */ |
408 | } | 473 | if (!singlematch(ms, s, p, ep)) { |
409 | case '$': { | 474 | if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ |
410 | if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ | 475 | p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ |
411 | return (s == ms->src_end) ? s : NULL; /* check end of string */ | 476 | } |
412 | else goto dflt; | 477 | else /* '+' or no suffix */ |
413 | } | 478 | s = NULL; /* fail */ |
414 | default: dflt: { /* it is a pattern item */ | ||
415 | const char *ep = classend(ms, p); /* points to what is next */ | ||
416 | int m = s<ms->src_end && singlematch(uchar(*s), p, ep); | ||
417 | switch (*ep) { | ||
418 | case '?': { /* optional */ | ||
419 | const char *res; | ||
420 | if (m && ((res=match(ms, s+1, ep+1)) != NULL)) | ||
421 | return res; | ||
422 | p=ep+1; goto init; /* else return match(ms, s, ep+1); */ | ||
423 | } | ||
424 | case '*': { /* 0 or more repetitions */ | ||
425 | return max_expand(ms, s, p, ep); | ||
426 | } | ||
427 | case '+': { /* 1 or more repetitions */ | ||
428 | return (m ? max_expand(ms, s+1, p, ep) : NULL); | ||
429 | } | ||
430 | case '-': { /* 0 or more repetitions (minimum) */ | ||
431 | return min_expand(ms, s, p, ep); | ||
432 | } | 479 | } |
433 | default: { | 480 | else { /* matched once */ |
434 | if (!m) return NULL; | 481 | switch (*ep) { /* handle optional suffix */ |
435 | s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ | 482 | case '?': { /* optional */ |
483 | const char *res; | ||
484 | if ((res = match(ms, s + 1, ep + 1)) != NULL) | ||
485 | s = res; | ||
486 | else { | ||
487 | p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ | ||
488 | } | ||
489 | break; | ||
490 | } | ||
491 | case '+': /* 1 or more repetitions */ | ||
492 | s++; /* 1 match already done */ | ||
493 | /* go through */ | ||
494 | case '*': /* 0 or more repetitions */ | ||
495 | s = max_expand(ms, s, p, ep); | ||
496 | break; | ||
497 | case '-': /* 0 or more repetitions (minimum) */ | ||
498 | s = min_expand(ms, s, p, ep); | ||
499 | break; | ||
500 | default: /* no suffix */ | ||
501 | s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ | ||
502 | } | ||
436 | } | 503 | } |
504 | break; | ||
437 | } | 505 | } |
438 | } | 506 | } |
439 | } | 507 | } |
508 | ms->matchdepth++; | ||
509 | return s; | ||
440 | } | 510 | } |
441 | 511 | ||
442 | 512 | ||
@@ -492,37 +562,58 @@ static int push_captures (MatchState *ms, const char *s, const char *e) { | |||
492 | } | 562 | } |
493 | 563 | ||
494 | 564 | ||
565 | /* check whether pattern has no special characters */ | ||
566 | static int nospecials (const char *p, size_t l) { | ||
567 | size_t upto = 0; | ||
568 | do { | ||
569 | if (strpbrk(p + upto, SPECIALS)) | ||
570 | return 0; /* pattern has a special character */ | ||
571 | upto += strlen(p + upto) + 1; /* may have more after \0 */ | ||
572 | } while (upto <= l); | ||
573 | return 1; /* no special chars found */ | ||
574 | } | ||
575 | |||
576 | |||
495 | static int str_find_aux (lua_State *L, int find) { | 577 | static int str_find_aux (lua_State *L, int find) { |
496 | size_t l1, l2; | 578 | size_t ls, lp; |
497 | const char *s = luaL_checklstring(L, 1, &l1); | 579 | const char *s = luaL_checklstring(L, 1, &ls); |
498 | const char *p = luaL_checklstring(L, 2, &l2); | 580 | const char *p = luaL_checklstring(L, 2, &lp); |
499 | ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; | 581 | size_t init = posrelat(luaL_optinteger(L, 3, 1), ls); |
500 | if (init < 0) init = 0; | 582 | if (init < 1) init = 1; |
501 | else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; | 583 | else if (init > ls + 1) { /* start after string's end? */ |
502 | if (find && (lua_toboolean(L, 4) || /* explicit request? */ | 584 | lua_pushnil(L); /* cannot find anything */ |
503 | strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ | 585 | return 1; |
586 | } | ||
587 | /* explicit request or no special characters? */ | ||
588 | if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { | ||
504 | /* do a plain search */ | 589 | /* do a plain search */ |
505 | const char *s2 = lmemfind(s+init, l1-init, p, l2); | 590 | const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp); |
506 | if (s2) { | 591 | if (s2) { |
507 | lua_pushinteger(L, s2-s+1); | 592 | lua_pushinteger(L, s2 - s + 1); |
508 | lua_pushinteger(L, s2-s+l2); | 593 | lua_pushinteger(L, s2 - s + lp); |
509 | return 2; | 594 | return 2; |
510 | } | 595 | } |
511 | } | 596 | } |
512 | else { | 597 | else { |
513 | MatchState ms; | 598 | MatchState ms; |
514 | int anchor = (*p == '^') ? (p++, 1) : 0; | 599 | const char *s1 = s + init - 1; |
515 | const char *s1=s+init; | 600 | int anchor = (*p == '^'); |
601 | if (anchor) { | ||
602 | p++; lp--; /* skip anchor character */ | ||
603 | } | ||
516 | ms.L = L; | 604 | ms.L = L; |
605 | ms.matchdepth = MAXCCALLS; | ||
517 | ms.src_init = s; | 606 | ms.src_init = s; |
518 | ms.src_end = s+l1; | 607 | ms.src_end = s + ls; |
608 | ms.p_end = p + lp; | ||
519 | do { | 609 | do { |
520 | const char *res; | 610 | const char *res; |
521 | ms.level = 0; | 611 | ms.level = 0; |
612 | lua_assert(ms.matchdepth == MAXCCALLS); | ||
522 | if ((res=match(&ms, s1, p)) != NULL) { | 613 | if ((res=match(&ms, s1, p)) != NULL) { |
523 | if (find) { | 614 | if (find) { |
524 | lua_pushinteger(L, s1-s+1); /* start */ | 615 | lua_pushinteger(L, s1 - s + 1); /* start */ |
525 | lua_pushinteger(L, res-s); /* end */ | 616 | lua_pushinteger(L, res - s); /* end */ |
526 | return push_captures(&ms, NULL, 0) + 2; | 617 | return push_captures(&ms, NULL, 0) + 2; |
527 | } | 618 | } |
528 | else | 619 | else |
@@ -547,18 +638,21 @@ static int str_match (lua_State *L) { | |||
547 | 638 | ||
548 | static int gmatch_aux (lua_State *L) { | 639 | static int gmatch_aux (lua_State *L) { |
549 | MatchState ms; | 640 | MatchState ms; |
550 | size_t ls; | 641 | size_t ls, lp; |
551 | const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); | 642 | const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); |
552 | const char *p = lua_tostring(L, lua_upvalueindex(2)); | 643 | const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp); |
553 | const char *src; | 644 | const char *src; |
554 | ms.L = L; | 645 | ms.L = L; |
646 | ms.matchdepth = MAXCCALLS; | ||
555 | ms.src_init = s; | 647 | ms.src_init = s; |
556 | ms.src_end = s+ls; | 648 | ms.src_end = s+ls; |
649 | ms.p_end = p + lp; | ||
557 | for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); | 650 | for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); |
558 | src <= ms.src_end; | 651 | src <= ms.src_end; |
559 | src++) { | 652 | src++) { |
560 | const char *e; | 653 | const char *e; |
561 | ms.level = 0; | 654 | ms.level = 0; |
655 | lua_assert(ms.matchdepth == MAXCCALLS); | ||
562 | if ((e = match(&ms, src, p)) != NULL) { | 656 | if ((e = match(&ms, src, p)) != NULL) { |
563 | lua_Integer newstart = e-s; | 657 | lua_Integer newstart = e-s; |
564 | if (e == src) newstart++; /* empty match? go at least one position */ | 658 | if (e == src) newstart++; /* empty match? go at least one position */ |
@@ -581,12 +675,6 @@ static int gmatch (lua_State *L) { | |||
581 | } | 675 | } |
582 | 676 | ||
583 | 677 | ||
584 | static int gfind_nodef (lua_State *L) { | ||
585 | return luaL_error(L, LUA_QL("string.gfind") " was renamed to " | ||
586 | LUA_QL("string.gmatch")); | ||
587 | } | ||
588 | |||
589 | |||
590 | static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, | 678 | static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, |
591 | const char *e) { | 679 | const char *e) { |
592 | size_t l, i; | 680 | size_t l, i; |
@@ -596,8 +684,12 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, | |||
596 | luaL_addchar(b, news[i]); | 684 | luaL_addchar(b, news[i]); |
597 | else { | 685 | else { |
598 | i++; /* skip ESC */ | 686 | i++; /* skip ESC */ |
599 | if (!isdigit(uchar(news[i]))) | 687 | if (!isdigit(uchar(news[i]))) { |
688 | if (news[i] != L_ESC) | ||
689 | luaL_error(ms->L, "invalid use of " LUA_QL("%c") | ||
690 | " in replacement string", L_ESC); | ||
600 | luaL_addchar(b, news[i]); | 691 | luaL_addchar(b, news[i]); |
692 | } | ||
601 | else if (news[i] == '0') | 693 | else if (news[i] == '0') |
602 | luaL_addlstring(b, s, e - s); | 694 | luaL_addlstring(b, s, e - s); |
603 | else { | 695 | else { |
@@ -610,14 +702,9 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, | |||
610 | 702 | ||
611 | 703 | ||
612 | static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, | 704 | static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, |
613 | const char *e) { | 705 | const char *e, int tr) { |
614 | lua_State *L = ms->L; | 706 | lua_State *L = ms->L; |
615 | switch (lua_type(L, 3)) { | 707 | switch (tr) { |
616 | case LUA_TNUMBER: | ||
617 | case LUA_TSTRING: { | ||
618 | add_s(ms, b, s, e); | ||
619 | return; | ||
620 | } | ||
621 | case LUA_TFUNCTION: { | 708 | case LUA_TFUNCTION: { |
622 | int n; | 709 | int n; |
623 | lua_pushvalue(L, 3); | 710 | lua_pushvalue(L, 3); |
@@ -630,41 +717,51 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, | |||
630 | lua_gettable(L, 3); | 717 | lua_gettable(L, 3); |
631 | break; | 718 | break; |
632 | } | 719 | } |
720 | default: { /* LUA_TNUMBER or LUA_TSTRING */ | ||
721 | add_s(ms, b, s, e); | ||
722 | return; | ||
723 | } | ||
633 | } | 724 | } |
634 | if (!lua_toboolean(L, -1)) { /* nil or false? */ | 725 | if (!lua_toboolean(L, -1)) { /* nil or false? */ |
635 | lua_pop(L, 1); | 726 | lua_pop(L, 1); |
636 | lua_pushlstring(L, s, e - s); /* keep original text */ | 727 | lua_pushlstring(L, s, e - s); /* keep original text */ |
637 | } | 728 | } |
638 | else if (!lua_isstring(L, -1)) | 729 | else if (!lua_isstring(L, -1)) |
639 | luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); | 730 | luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); |
640 | luaL_addvalue(b); /* add result to accumulator */ | 731 | luaL_addvalue(b); /* add result to accumulator */ |
641 | } | 732 | } |
642 | 733 | ||
643 | 734 | ||
644 | static int str_gsub (lua_State *L) { | 735 | static int str_gsub (lua_State *L) { |
645 | size_t srcl; | 736 | size_t srcl, lp; |
646 | const char *src = luaL_checklstring(L, 1, &srcl); | 737 | const char *src = luaL_checklstring(L, 1, &srcl); |
647 | const char *p = luaL_checkstring(L, 2); | 738 | const char *p = luaL_checklstring(L, 2, &lp); |
648 | int tr = lua_type(L, 3); | 739 | int tr = lua_type(L, 3); |
649 | int max_s = luaL_optint(L, 4, srcl+1); | 740 | size_t max_s = luaL_optinteger(L, 4, srcl+1); |
650 | int anchor = (*p == '^') ? (p++, 1) : 0; | 741 | int anchor = (*p == '^'); |
651 | int n = 0; | 742 | size_t n = 0; |
652 | MatchState ms; | 743 | MatchState ms; |
653 | luaL_Buffer b; | 744 | luaL_Buffer b; |
654 | luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || | 745 | luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || |
655 | tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, | 746 | tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, |
656 | "string/function/table expected"); | 747 | "string/function/table expected"); |
657 | luaL_buffinit(L, &b); | 748 | luaL_buffinit(L, &b); |
749 | if (anchor) { | ||
750 | p++; lp--; /* skip anchor character */ | ||
751 | } | ||
658 | ms.L = L; | 752 | ms.L = L; |
753 | ms.matchdepth = MAXCCALLS; | ||
659 | ms.src_init = src; | 754 | ms.src_init = src; |
660 | ms.src_end = src+srcl; | 755 | ms.src_end = src+srcl; |
756 | ms.p_end = p + lp; | ||
661 | while (n < max_s) { | 757 | while (n < max_s) { |
662 | const char *e; | 758 | const char *e; |
663 | ms.level = 0; | 759 | ms.level = 0; |
760 | lua_assert(ms.matchdepth == MAXCCALLS); | ||
664 | e = match(&ms, src, p); | 761 | e = match(&ms, src, p); |
665 | if (e) { | 762 | if (e) { |
666 | n++; | 763 | n++; |
667 | add_value(&ms, &b, src, e); | 764 | add_value(&ms, &b, src, e, tr); |
668 | } | 765 | } |
669 | if (e && e>src) /* non empty match? */ | 766 | if (e && e>src) /* non empty match? */ |
670 | src = e; /* skip it */ | 767 | src = e; /* skip it */ |
@@ -682,6 +779,46 @@ static int str_gsub (lua_State *L) { | |||
682 | /* }====================================================== */ | 779 | /* }====================================================== */ |
683 | 780 | ||
684 | 781 | ||
782 | |||
783 | /* | ||
784 | ** {====================================================== | ||
785 | ** STRING FORMAT | ||
786 | ** ======================================================= | ||
787 | */ | ||
788 | |||
789 | /* | ||
790 | ** LUA_INTFRMLEN is the length modifier for integer conversions in | ||
791 | ** 'string.format'; LUA_INTFRM_T is the integer type corresponding to | ||
792 | ** the previous length | ||
793 | */ | ||
794 | #if !defined(LUA_INTFRMLEN) /* { */ | ||
795 | #if defined(LUA_USE_LONGLONG) | ||
796 | |||
797 | #define LUA_INTFRMLEN "ll" | ||
798 | #define LUA_INTFRM_T long long | ||
799 | |||
800 | #else | ||
801 | |||
802 | #define LUA_INTFRMLEN "l" | ||
803 | #define LUA_INTFRM_T long | ||
804 | |||
805 | #endif | ||
806 | #endif /* } */ | ||
807 | |||
808 | |||
809 | /* | ||
810 | ** LUA_FLTFRMLEN is the length modifier for float conversions in | ||
811 | ** 'string.format'; LUA_FLTFRM_T is the float type corresponding to | ||
812 | ** the previous length | ||
813 | */ | ||
814 | #if !defined(LUA_FLTFRMLEN) | ||
815 | |||
816 | #define LUA_FLTFRMLEN "" | ||
817 | #define LUA_FLTFRM_T double | ||
818 | |||
819 | #endif | ||
820 | |||
821 | |||
685 | /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ | 822 | /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ |
686 | #define MAX_ITEM 512 | 823 | #define MAX_ITEM 512 |
687 | /* valid flags in a format specification */ | 824 | /* valid flags in a format specification */ |
@@ -698,25 +835,20 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { | |||
698 | const char *s = luaL_checklstring(L, arg, &l); | 835 | const char *s = luaL_checklstring(L, arg, &l); |
699 | luaL_addchar(b, '"'); | 836 | luaL_addchar(b, '"'); |
700 | while (l--) { | 837 | while (l--) { |
701 | switch (*s) { | 838 | if (*s == '"' || *s == '\\' || *s == '\n') { |
702 | case '"': case '\\': case '\n': { | 839 | luaL_addchar(b, '\\'); |
703 | luaL_addchar(b, '\\'); | 840 | luaL_addchar(b, *s); |
704 | luaL_addchar(b, *s); | ||
705 | break; | ||
706 | } | ||
707 | case '\r': { | ||
708 | luaL_addlstring(b, "\\r", 2); | ||
709 | break; | ||
710 | } | ||
711 | case '\0': { | ||
712 | luaL_addlstring(b, "\\000", 4); | ||
713 | break; | ||
714 | } | ||
715 | default: { | ||
716 | luaL_addchar(b, *s); | ||
717 | break; | ||
718 | } | ||
719 | } | 841 | } |
842 | else if (*s == '\0' || iscntrl(uchar(*s))) { | ||
843 | char buff[10]; | ||
844 | if (!isdigit(uchar(*(s+1)))) | ||
845 | snprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); | ||
846 | else | ||
847 | snprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s)); | ||
848 | luaL_addstring(b, buff); | ||
849 | } | ||
850 | else | ||
851 | luaL_addchar(b, *s); | ||
720 | s++; | 852 | s++; |
721 | } | 853 | } |
722 | luaL_addchar(b, '"'); | 854 | luaL_addchar(b, '"'); |
@@ -725,7 +857,7 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { | |||
725 | static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { | 857 | static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { |
726 | const char *p = strfrmt; | 858 | const char *p = strfrmt; |
727 | while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ | 859 | while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ |
728 | if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) | 860 | if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) |
729 | luaL_error(L, "invalid format (repeated flags)"); | 861 | luaL_error(L, "invalid format (repeated flags)"); |
730 | if (isdigit(uchar(*p))) p++; /* skip width */ | 862 | if (isdigit(uchar(*p))) p++; /* skip width */ |
731 | if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ | 863 | if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ |
@@ -737,23 +869,28 @@ static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { | |||
737 | if (isdigit(uchar(*p))) | 869 | if (isdigit(uchar(*p))) |
738 | luaL_error(L, "invalid format (width or precision too long)"); | 870 | luaL_error(L, "invalid format (width or precision too long)"); |
739 | *(form++) = '%'; | 871 | *(form++) = '%'; |
740 | strncpy(form, strfrmt, p - strfrmt + 1); | 872 | memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char)); |
741 | form += p - strfrmt + 1; | 873 | form += p - strfrmt + 1; |
742 | *form = '\0'; | 874 | *form = '\0'; |
743 | return p; | 875 | return p; |
744 | } | 876 | } |
745 | 877 | ||
746 | 878 | ||
747 | static void addintlen (char *form) { | 879 | /* |
880 | ** add length modifier into formats | ||
881 | */ | ||
882 | static void addlenmod (char *form, const char *lenmod) { | ||
748 | size_t l = strlen(form); | 883 | size_t l = strlen(form); |
884 | size_t lm = strlen(lenmod); | ||
749 | char spec = form[l - 1]; | 885 | char spec = form[l - 1]; |
750 | strcpy(form + l - 1, LUA_INTFRMLEN); | 886 | strcpy(form + l - 1, lenmod); |
751 | form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; | 887 | form[l + lm - 1] = spec; |
752 | form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; | 888 | form[l + lm] = '\0'; |
753 | } | 889 | } |
754 | 890 | ||
755 | 891 | ||
756 | static int str_format (lua_State *L) { | 892 | static int str_format (lua_State *L) { |
893 | int top = lua_gettop(L); | ||
757 | int arg = 1; | 894 | int arg = 1; |
758 | size_t sfl; | 895 | size_t sfl; |
759 | const char *strfrmt = luaL_checklstring(L, arg, &sfl); | 896 | const char *strfrmt = luaL_checklstring(L, arg, &sfl); |
@@ -767,45 +904,61 @@ static int str_format (lua_State *L) { | |||
767 | luaL_addchar(&b, *strfrmt++); /* %% */ | 904 | luaL_addchar(&b, *strfrmt++); /* %% */ |
768 | else { /* format item */ | 905 | else { /* format item */ |
769 | char form[MAX_FORMAT]; /* to store the format (`%...') */ | 906 | char form[MAX_FORMAT]; /* to store the format (`%...') */ |
770 | char buff[MAX_ITEM]; /* to store the formatted item */ | 907 | char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ |
771 | arg++; | 908 | int nb = 0; /* number of bytes in added item */ |
909 | if (++arg > top) | ||
910 | luaL_argerror(L, arg, "no value"); | ||
772 | strfrmt = scanformat(L, strfrmt, form); | 911 | strfrmt = scanformat(L, strfrmt, form); |
773 | switch (*strfrmt++) { | 912 | switch (*strfrmt++) { |
774 | case 'c': { | 913 | case 'c': { |
775 | snprintf(buff, MAX_ITEM, form, (int)luaL_checknumber(L, arg)); | 914 | nb = snprintf(buff, MAX_ITEM, form, luaL_checkint(L, arg)); |
776 | break; | 915 | break; |
777 | } | 916 | } |
778 | case 'd': case 'i': { | 917 | case 'd': case 'i': { |
779 | addintlen(form); | 918 | lua_Number n = luaL_checknumber(L, arg); |
780 | snprintf(buff, MAX_ITEM, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); | 919 | LUA_INTFRM_T ni = (LUA_INTFRM_T)n; |
920 | lua_Number diff = n - (lua_Number)ni; | ||
921 | luaL_argcheck(L, -1 < diff && diff < 1, arg, | ||
922 | "not a number in proper range"); | ||
923 | addlenmod(form, LUA_INTFRMLEN); | ||
924 | nb = snprintf(buff, MAX_ITEM, form, ni); | ||
781 | break; | 925 | break; |
782 | } | 926 | } |
783 | case 'o': case 'u': case 'x': case 'X': { | 927 | case 'o': case 'u': case 'x': case 'X': { |
784 | addintlen(form); | 928 | lua_Number n = luaL_checknumber(L, arg); |
785 | snprintf(buff, MAX_ITEM, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); | 929 | unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n; |
930 | lua_Number diff = n - (lua_Number)ni; | ||
931 | luaL_argcheck(L, -1 < diff && diff < 1, arg, | ||
932 | "not a non-negative number in proper range"); | ||
933 | addlenmod(form, LUA_INTFRMLEN); | ||
934 | nb = snprintf(buff, MAX_ITEM, form, ni); | ||
786 | break; | 935 | break; |
787 | } | 936 | } |
788 | case 'e': case 'E': case 'f': | 937 | case 'e': case 'E': case 'f': |
938 | #if defined(LUA_USE_AFORMAT) | ||
939 | case 'a': case 'A': | ||
940 | #endif | ||
789 | case 'g': case 'G': { | 941 | case 'g': case 'G': { |
790 | snprintf(buff, MAX_ITEM, form, (double)luaL_checknumber(L, arg)); | 942 | addlenmod(form, LUA_FLTFRMLEN); |
943 | nb = snprintf(buff, MAX_ITEM, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg)); | ||
791 | break; | 944 | break; |
792 | } | 945 | } |
793 | case 'q': { | 946 | case 'q': { |
794 | addquoted(L, &b, arg); | 947 | addquoted(L, &b, arg); |
795 | continue; /* skip the 'addsize' at the end */ | 948 | break; |
796 | } | 949 | } |
797 | case 's': { | 950 | case 's': { |
798 | size_t l; | 951 | size_t l; |
799 | const char *s = luaL_checklstring(L, arg, &l); | 952 | const char *s = luaL_tolstring(L, arg, &l); |
800 | if (!strchr(form, '.') && l >= 100) { | 953 | if (!strchr(form, '.') && l >= 100) { |
801 | /* no precision and string is too long to be formatted; | 954 | /* no precision and string is too long to be formatted; |
802 | keep original string */ | 955 | keep original string */ |
803 | lua_pushvalue(L, arg); | ||
804 | luaL_addvalue(&b); | 956 | luaL_addvalue(&b); |
805 | continue; /* skip the `addsize' at the end */ | 957 | break; |
806 | } | 958 | } |
807 | else { | 959 | else { |
808 | snprintf(buff, MAX_ITEM, form, s); | 960 | nb = snprintf(buff, MAX_ITEM, form, s); |
961 | lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ | ||
809 | break; | 962 | break; |
810 | } | 963 | } |
811 | } | 964 | } |
@@ -814,13 +967,15 @@ static int str_format (lua_State *L) { | |||
814 | LUA_QL("format"), *(strfrmt - 1)); | 967 | LUA_QL("format"), *(strfrmt - 1)); |
815 | } | 968 | } |
816 | } | 969 | } |
817 | luaL_addlstring(&b, buff, strlen(buff)); | 970 | luaL_addsize(&b, nb); |
818 | } | 971 | } |
819 | } | 972 | } |
820 | luaL_pushresult(&b); | 973 | luaL_pushresult(&b); |
821 | return 1; | 974 | return 1; |
822 | } | 975 | } |
823 | 976 | ||
977 | /* }====================================================== */ | ||
978 | |||
824 | 979 | ||
825 | static const luaL_Reg strlib[] = { | 980 | static const luaL_Reg strlib[] = { |
826 | {"byte", str_byte}, | 981 | {"byte", str_byte}, |
@@ -828,7 +983,6 @@ static const luaL_Reg strlib[] = { | |||
828 | {"dump", str_dump}, | 983 | {"dump", str_dump}, |
829 | {"find", str_find}, | 984 | {"find", str_find}, |
830 | {"format", str_format}, | 985 | {"format", str_format}, |
831 | {"gfind", gfind_nodef}, | ||
832 | {"gmatch", gmatch}, | 986 | {"gmatch", gmatch}, |
833 | {"gsub", str_gsub}, | 987 | {"gsub", str_gsub}, |
834 | {"len", str_len}, | 988 | {"len", str_len}, |
@@ -843,13 +997,13 @@ static const luaL_Reg strlib[] = { | |||
843 | 997 | ||
844 | 998 | ||
845 | static void createmetatable (lua_State *L) { | 999 | static void createmetatable (lua_State *L) { |
846 | lua_createtable(L, 0, 1); /* create metatable for strings */ | 1000 | lua_createtable(L, 0, 1); /* table to be metatable for strings */ |
847 | lua_pushliteral(L, ""); /* dummy string */ | 1001 | lua_pushliteral(L, ""); /* dummy string */ |
848 | lua_pushvalue(L, -2); | 1002 | lua_pushvalue(L, -2); /* copy table */ |
849 | lua_setmetatable(L, -2); /* set string metatable */ | 1003 | lua_setmetatable(L, -2); /* set table as metatable for strings */ |
850 | lua_pop(L, 1); /* pop dummy string */ | 1004 | lua_pop(L, 1); /* pop dummy string */ |
851 | lua_pushvalue(L, -2); /* string library... */ | 1005 | lua_pushvalue(L, -2); /* get string library */ |
852 | lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ | 1006 | lua_setfield(L, -2, "__index"); /* metatable.__index = string */ |
853 | lua_pop(L, 1); /* pop metatable */ | 1007 | lua_pop(L, 1); /* pop metatable */ |
854 | } | 1008 | } |
855 | 1009 | ||
@@ -857,12 +1011,8 @@ static void createmetatable (lua_State *L) { | |||
857 | /* | 1011 | /* |
858 | ** Open string library | 1012 | ** Open string library |
859 | */ | 1013 | */ |
860 | LUALIB_API int luaopen_string (lua_State *L) { | 1014 | LUAMOD_API int luaopen_string (lua_State *L) { |
861 | luaL_register(L, LUA_STRLIBNAME, strlib); | 1015 | luaL_newlib(L, strlib); |
862 | #if defined(LUA_COMPAT_GFIND) | ||
863 | lua_getfield(L, -1, "gmatch"); | ||
864 | lua_setfield(L, -2, "gfind"); | ||
865 | #endif | ||
866 | createmetatable(L); | 1016 | createmetatable(L); |
867 | return 1; | 1017 | return 1; |
868 | } | 1018 | } |
diff --git a/apps/plugins/lua/ltable.c b/apps/plugins/lua/ltable.c index ec84f4fabc..e0fe98ce3e 100644 --- a/apps/plugins/lua/ltable.c +++ b/apps/plugins/lua/ltable.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ | 2 | ** $Id: ltable.c,v 2.72.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -18,7 +18,6 @@ | |||
18 | ** Hence even when the load factor reaches 100%, performance remains good. | 18 | ** Hence even when the load factor reaches 100%, performance remains good. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <math.h> | ||
22 | #include <string.h> | 21 | #include <string.h> |
23 | 22 | ||
24 | #define ltable_c | 23 | #define ltable_c |
@@ -32,14 +31,16 @@ | |||
32 | #include "lmem.h" | 31 | #include "lmem.h" |
33 | #include "lobject.h" | 32 | #include "lobject.h" |
34 | #include "lstate.h" | 33 | #include "lstate.h" |
34 | #include "lstring.h" | ||
35 | #include "ltable.h" | 35 | #include "ltable.h" |
36 | #include "lvm.h" | ||
36 | 37 | ||
37 | 38 | ||
38 | /* | 39 | /* |
39 | ** max size of array part is 2^MAXBITS | 40 | ** max size of array part is 2^MAXBITS |
40 | */ | 41 | */ |
41 | #if LUAI_BITSINT > 26 | 42 | #if LUAI_BITSINT >= 32 |
42 | #define MAXBITS 26 | 43 | #define MAXBITS 30 |
43 | #else | 44 | #else |
44 | #define MAXBITS (LUAI_BITSINT-2) | 45 | #define MAXBITS (LUAI_BITSINT-2) |
45 | #endif | 46 | #endif |
@@ -47,10 +48,10 @@ | |||
47 | #define MAXASIZE (1 << MAXBITS) | 48 | #define MAXASIZE (1 << MAXBITS) |
48 | 49 | ||
49 | 50 | ||
50 | #define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) | 51 | #define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) |
51 | 52 | ||
52 | #define hashstr(t,str) hashpow2(t, (str)->tsv.hash) | 53 | #define hashstr(t,str) hashpow2(t, (str)->tsv.hash) |
53 | #define hashboolean(t,p) hashpow2(t, p) | 54 | #define hashboolean(t,p) hashpow2(t, p) |
54 | 55 | ||
55 | 56 | ||
56 | /* | 57 | /* |
@@ -72,9 +73,11 @@ | |||
72 | 73 | ||
73 | #define dummynode (&dummynode_) | 74 | #define dummynode (&dummynode_) |
74 | 75 | ||
76 | #define isdummy(n) ((n) == dummynode) | ||
77 | |||
75 | static const Node dummynode_ = { | 78 | static const Node dummynode_ = { |
76 | {{NULL}, LUA_TNIL}, /* value */ | 79 | {NILCONSTANT}, /* value */ |
77 | {{{NULL}, LUA_TNIL, NULL}} /* key */ | 80 | {{NILCONSTANT, NULL}} /* key */ |
78 | }; | 81 | }; |
79 | 82 | ||
80 | 83 | ||
@@ -101,12 +104,22 @@ static Node *mainposition (const Table *t, const TValue *key) { | |||
101 | switch (ttype(key)) { | 104 | switch (ttype(key)) { |
102 | case LUA_TNUMBER: | 105 | case LUA_TNUMBER: |
103 | return hashnum(t, nvalue(key)); | 106 | return hashnum(t, nvalue(key)); |
104 | case LUA_TSTRING: | 107 | case LUA_TLNGSTR: { |
108 | TString *s = rawtsvalue(key); | ||
109 | if (s->tsv.extra == 0) { /* no hash? */ | ||
110 | s->tsv.hash = luaS_hash(getstr(s), s->tsv.len, s->tsv.hash); | ||
111 | s->tsv.extra = 1; /* now it has its hash */ | ||
112 | } | ||
113 | return hashstr(t, rawtsvalue(key)); | ||
114 | } | ||
115 | case LUA_TSHRSTR: | ||
105 | return hashstr(t, rawtsvalue(key)); | 116 | return hashstr(t, rawtsvalue(key)); |
106 | case LUA_TBOOLEAN: | 117 | case LUA_TBOOLEAN: |
107 | return hashboolean(t, bvalue(key)); | 118 | return hashboolean(t, bvalue(key)); |
108 | case LUA_TLIGHTUSERDATA: | 119 | case LUA_TLIGHTUSERDATA: |
109 | return hashpointer(t, pvalue(key)); | 120 | return hashpointer(t, pvalue(key)); |
121 | case LUA_TLCF: | ||
122 | return hashpointer(t, fvalue(key)); | ||
110 | default: | 123 | default: |
111 | return hashpointer(t, gcvalue(key)); | 124 | return hashpointer(t, gcvalue(key)); |
112 | } | 125 | } |
@@ -132,7 +145,7 @@ static int arrayindex (const TValue *key) { | |||
132 | /* | 145 | /* |
133 | ** returns the index of a `key' for table traversals. First goes all | 146 | ** returns the index of a `key' for table traversals. First goes all |
134 | ** elements in the array part, then elements in the hash part. The | 147 | ** elements in the array part, then elements in the hash part. The |
135 | ** beginning of a traversal is signalled by -1. | 148 | ** beginning of a traversal is signaled by -1. |
136 | */ | 149 | */ |
137 | static int findindex (lua_State *L, Table *t, StkId key) { | 150 | static int findindex (lua_State *L, Table *t, StkId key) { |
138 | int i; | 151 | int i; |
@@ -142,19 +155,19 @@ static int findindex (lua_State *L, Table *t, StkId key) { | |||
142 | return i-1; /* yes; that's the index (corrected to C) */ | 155 | return i-1; /* yes; that's the index (corrected to C) */ |
143 | else { | 156 | else { |
144 | Node *n = mainposition(t, key); | 157 | Node *n = mainposition(t, key); |
145 | do { /* check whether `key' is somewhere in the chain */ | 158 | for (;;) { /* check whether `key' is somewhere in the chain */ |
146 | /* key may be dead already, but it is ok to use it in `next' */ | 159 | /* key may be dead already, but it is ok to use it in `next' */ |
147 | if (luaO_rawequalObj(key2tval(n), key) || | 160 | if (luaV_rawequalobj(gkey(n), key) || |
148 | (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && | 161 | (ttisdeadkey(gkey(n)) && iscollectable(key) && |
149 | gcvalue(gkey(n)) == gcvalue(key))) { | 162 | deadvalue(gkey(n)) == gcvalue(key))) { |
150 | i = cast_int(n - gnode(t, 0)); /* key index in hash table */ | 163 | i = cast_int(n - gnode(t, 0)); /* key index in hash table */ |
151 | /* hash elements are numbered after array ones */ | 164 | /* hash elements are numbered after array ones */ |
152 | return i + t->sizearray; | 165 | return i + t->sizearray; |
153 | } | 166 | } |
154 | else n = gnext(n); | 167 | else n = gnext(n); |
155 | } while (n); | 168 | if (n == NULL) |
156 | luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ | 169 | luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ |
157 | return 0; /* to avoid warnings */ | 170 | } |
158 | } | 171 | } |
159 | } | 172 | } |
160 | 173 | ||
@@ -170,7 +183,7 @@ int luaH_next (lua_State *L, Table *t, StkId key) { | |||
170 | } | 183 | } |
171 | for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ | 184 | for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ |
172 | if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ | 185 | if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ |
173 | setobj2s(L, key, key2tval(gnode(t, i))); | 186 | setobj2s(L, key, gkey(gnode(t, i))); |
174 | setobj2s(L, key+1, gval(gnode(t, i))); | 187 | setobj2s(L, key+1, gval(gnode(t, i))); |
175 | return 1; | 188 | return 1; |
176 | } | 189 | } |
@@ -211,7 +224,7 @@ static int computesizes (int nums[], int *narray) { | |||
211 | static int countint (const TValue *key, int *nums) { | 224 | static int countint (const TValue *key, int *nums) { |
212 | int k = arrayindex(key); | 225 | int k = arrayindex(key); |
213 | if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ | 226 | if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ |
214 | nums[ceillog2(k)]++; /* count as such */ | 227 | nums[luaO_ceillog2(k)]++; /* count as such */ |
215 | return 1; | 228 | return 1; |
216 | } | 229 | } |
217 | else | 230 | else |
@@ -251,7 +264,7 @@ static int numusehash (const Table *t, int *nums, int *pnasize) { | |||
251 | while (i--) { | 264 | while (i--) { |
252 | Node *n = &t->node[i]; | 265 | Node *n = &t->node[i]; |
253 | if (!ttisnil(gval(n))) { | 266 | if (!ttisnil(gval(n))) { |
254 | ause += countint(key2tval(n), nums); | 267 | ause += countint(gkey(n), nums); |
255 | totaluse++; | 268 | totaluse++; |
256 | } | 269 | } |
257 | } | 270 | } |
@@ -277,7 +290,7 @@ static void setnodevector (lua_State *L, Table *t, int size) { | |||
277 | } | 290 | } |
278 | else { | 291 | else { |
279 | int i; | 292 | int i; |
280 | lsize = ceillog2(size); | 293 | lsize = luaO_ceillog2(size); |
281 | if (lsize > MAXBITS) | 294 | if (lsize > MAXBITS) |
282 | luaG_runerror(L, "table overflow"); | 295 | luaG_runerror(L, "table overflow"); |
283 | size = twoto(lsize); | 296 | size = twoto(lsize); |
@@ -294,7 +307,7 @@ static void setnodevector (lua_State *L, Table *t, int size) { | |||
294 | } | 307 | } |
295 | 308 | ||
296 | 309 | ||
297 | static void resize (lua_State *L, Table *t, int nasize, int nhsize) { | 310 | void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) { |
298 | int i; | 311 | int i; |
299 | int oldasize = t->sizearray; | 312 | int oldasize = t->sizearray; |
300 | int oldhsize = t->lsizenode; | 313 | int oldhsize = t->lsizenode; |
@@ -302,13 +315,13 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) { | |||
302 | if (nasize > oldasize) /* array part must grow? */ | 315 | if (nasize > oldasize) /* array part must grow? */ |
303 | setarrayvector(L, t, nasize); | 316 | setarrayvector(L, t, nasize); |
304 | /* create new hash part with appropriate size */ | 317 | /* create new hash part with appropriate size */ |
305 | setnodevector(L, t, nhsize); | 318 | setnodevector(L, t, nhsize); |
306 | if (nasize < oldasize) { /* array part must shrink? */ | 319 | if (nasize < oldasize) { /* array part must shrink? */ |
307 | t->sizearray = nasize; | 320 | t->sizearray = nasize; |
308 | /* re-insert elements from vanishing slice */ | 321 | /* re-insert elements from vanishing slice */ |
309 | for (i=nasize; i<oldasize; i++) { | 322 | for (i=nasize; i<oldasize; i++) { |
310 | if (!ttisnil(&t->array[i])) | 323 | if (!ttisnil(&t->array[i])) |
311 | setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); | 324 | luaH_setint(L, t, i + 1, &t->array[i]); |
312 | } | 325 | } |
313 | /* shrink array */ | 326 | /* shrink array */ |
314 | luaM_reallocvector(L, t->array, oldasize, nasize, TValue); | 327 | luaM_reallocvector(L, t->array, oldasize, nasize, TValue); |
@@ -316,23 +329,26 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) { | |||
316 | /* re-insert elements from hash part */ | 329 | /* re-insert elements from hash part */ |
317 | for (i = twoto(oldhsize) - 1; i >= 0; i--) { | 330 | for (i = twoto(oldhsize) - 1; i >= 0; i--) { |
318 | Node *old = nold+i; | 331 | Node *old = nold+i; |
319 | if (!ttisnil(gval(old))) | 332 | if (!ttisnil(gval(old))) { |
320 | setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); | 333 | /* doesn't need barrier/invalidate cache, as entry was |
334 | already present in the table */ | ||
335 | setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); | ||
336 | } | ||
321 | } | 337 | } |
322 | if (nold != dummynode) | 338 | if (!isdummy(nold)) |
323 | luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ | 339 | luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old array */ |
324 | } | 340 | } |
325 | 341 | ||
326 | 342 | ||
327 | void luaH_resizearray (lua_State *L, Table *t, int nasize) { | 343 | void luaH_resizearray (lua_State *L, Table *t, int nasize) { |
328 | int nsize = (t->node == dummynode) ? 0 : sizenode(t); | 344 | int nsize = isdummy(t->node) ? 0 : sizenode(t); |
329 | resize(L, t, nasize, nsize); | 345 | luaH_resize(L, t, nasize, nsize); |
330 | } | 346 | } |
331 | 347 | ||
332 | 348 | ||
333 | static void rehash (lua_State *L, Table *t, const TValue *ek) { | 349 | static void rehash (lua_State *L, Table *t, const TValue *ek) { |
334 | int nasize, na; | 350 | int nasize, na; |
335 | int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ | 351 | int nums[MAXBITS+1]; /* nums[i] = number of keys with 2^(i-1) < k <= 2^i */ |
336 | int i; | 352 | int i; |
337 | int totaluse; | 353 | int totaluse; |
338 | for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ | 354 | for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ |
@@ -345,7 +361,7 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) { | |||
345 | /* compute new size for array part */ | 361 | /* compute new size for array part */ |
346 | na = computesizes(nums, &nasize); | 362 | na = computesizes(nums, &nasize); |
347 | /* resize the table to new computed sizes */ | 363 | /* resize the table to new computed sizes */ |
348 | resize(L, t, nasize, totaluse - na); | 364 | luaH_resize(L, t, nasize, totaluse - na); |
349 | } | 365 | } |
350 | 366 | ||
351 | 367 | ||
@@ -355,32 +371,28 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) { | |||
355 | */ | 371 | */ |
356 | 372 | ||
357 | 373 | ||
358 | Table *luaH_new (lua_State *L, int narray, int nhash) { | 374 | Table *luaH_new (lua_State *L) { |
359 | Table *t = luaM_new(L, Table); | 375 | Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table), NULL, 0)->h; |
360 | luaC_link(L, obj2gco(t), LUA_TTABLE); | ||
361 | t->metatable = NULL; | 376 | t->metatable = NULL; |
362 | t->flags = cast_byte(~0); | 377 | t->flags = cast_byte(~0); |
363 | /* temporary values (kept only if some malloc fails) */ | ||
364 | t->array = NULL; | 378 | t->array = NULL; |
365 | t->sizearray = 0; | 379 | t->sizearray = 0; |
366 | t->lsizenode = 0; | 380 | setnodevector(L, t, 0); |
367 | t->node = cast(Node *, dummynode); | ||
368 | setarrayvector(L, t, narray); | ||
369 | setnodevector(L, t, nhash); | ||
370 | return t; | 381 | return t; |
371 | } | 382 | } |
372 | 383 | ||
373 | 384 | ||
374 | void luaH_free (lua_State *L, Table *t) { | 385 | void luaH_free (lua_State *L, Table *t) { |
375 | if (t->node != dummynode) | 386 | if (!isdummy(t->node)) |
376 | luaM_freearray(L, t->node, sizenode(t), Node); | 387 | luaM_freearray(L, t->node, cast(size_t, sizenode(t))); |
377 | luaM_freearray(L, t->array, t->sizearray, TValue); | 388 | luaM_freearray(L, t->array, t->sizearray); |
378 | luaM_free(L, t); | 389 | luaM_free(L, t); |
379 | } | 390 | } |
380 | 391 | ||
381 | 392 | ||
382 | static Node *getfreepos (Table *t) { | 393 | static Node *getfreepos (Table *t) { |
383 | while (t->lastfree-- > t->node) { | 394 | while (t->lastfree > t->node) { |
395 | t->lastfree--; | ||
384 | if (ttisnil(gkey(t->lastfree))) | 396 | if (ttisnil(gkey(t->lastfree))) |
385 | return t->lastfree; | 397 | return t->lastfree; |
386 | } | 398 | } |
@@ -390,23 +402,28 @@ static Node *getfreepos (Table *t) { | |||
390 | 402 | ||
391 | 403 | ||
392 | /* | 404 | /* |
393 | ** inserts a new key into a hash table; first, check whether key's main | 405 | ** inserts a new key into a hash table; first, check whether key's main |
394 | ** position is free. If not, check whether colliding node is in its main | 406 | ** position is free. If not, check whether colliding node is in its main |
395 | ** position or not: if it is not, move colliding node to an empty place and | 407 | ** position or not: if it is not, move colliding node to an empty place and |
396 | ** put new key in its main position; otherwise (colliding node is in its main | 408 | ** put new key in its main position; otherwise (colliding node is in its main |
397 | ** position), new key goes to an empty position. | 409 | ** position), new key goes to an empty position. |
398 | */ | 410 | */ |
399 | static TValue *newkey (lua_State *L, Table *t, const TValue *key) { | 411 | TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { |
400 | Node *mp = mainposition(t, key); | 412 | Node *mp; |
401 | if (!ttisnil(gval(mp)) || mp == dummynode) { | 413 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); |
414 | else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) | ||
415 | luaG_runerror(L, "table index is NaN"); | ||
416 | mp = mainposition(t, key); | ||
417 | if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ | ||
402 | Node *othern; | 418 | Node *othern; |
403 | Node *n = getfreepos(t); /* get a free place */ | 419 | Node *n = getfreepos(t); /* get a free place */ |
404 | if (n == NULL) { /* cannot find a free place? */ | 420 | if (n == NULL) { /* cannot find a free place? */ |
405 | rehash(L, t, key); /* grow table */ | 421 | rehash(L, t, key); /* grow table */ |
406 | return luaH_set(L, t, key); /* re-insert key into grown table */ | 422 | /* whatever called 'newkey' take care of TM cache and GC barrier */ |
423 | return luaH_set(L, t, key); /* insert key into grown table */ | ||
407 | } | 424 | } |
408 | lua_assert(n != dummynode); | 425 | lua_assert(!isdummy(n)); |
409 | othern = mainposition(t, key2tval(mp)); | 426 | othern = mainposition(t, gkey(mp)); |
410 | if (othern != mp) { /* is colliding node out of its main position? */ | 427 | if (othern != mp) { /* is colliding node out of its main position? */ |
411 | /* yes; move colliding node into free position */ | 428 | /* yes; move colliding node into free position */ |
412 | while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ | 429 | while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ |
@@ -422,8 +439,8 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) { | |||
422 | mp = n; | 439 | mp = n; |
423 | } | 440 | } |
424 | } | 441 | } |
425 | gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; | 442 | setobj2t(L, gkey(mp), key); |
426 | luaC_barriert(L, t, key); | 443 | luaC_barrierback(L, obj2gco(t), key); |
427 | lua_assert(ttisnil(gval(mp))); | 444 | lua_assert(ttisnil(gval(mp))); |
428 | return gval(mp); | 445 | return gval(mp); |
429 | } | 446 | } |
@@ -432,7 +449,7 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) { | |||
432 | /* | 449 | /* |
433 | ** search function for integers | 450 | ** search function for integers |
434 | */ | 451 | */ |
435 | const TValue *luaH_getnum (Table *t, int key) { | 452 | const TValue *luaH_getint (Table *t, int key) { |
436 | /* (1 <= key && key <= t->sizearray) */ | 453 | /* (1 <= key && key <= t->sizearray) */ |
437 | if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) | 454 | if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) |
438 | return &t->array[key-1]; | 455 | return &t->array[key-1]; |
@@ -450,12 +467,13 @@ const TValue *luaH_getnum (Table *t, int key) { | |||
450 | 467 | ||
451 | 468 | ||
452 | /* | 469 | /* |
453 | ** search function for strings | 470 | ** search function for short strings |
454 | */ | 471 | */ |
455 | const TValue *luaH_getstr (Table *t, TString *key) { | 472 | const TValue *luaH_getstr (Table *t, TString *key) { |
456 | Node *n = hashstr(t, key); | 473 | Node *n = hashstr(t, key); |
474 | lua_assert(key->tsv.tt == LUA_TSHRSTR); | ||
457 | do { /* check whether `key' is somewhere in the chain */ | 475 | do { /* check whether `key' is somewhere in the chain */ |
458 | if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) | 476 | if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key)) |
459 | return gval(n); /* that's it */ | 477 | return gval(n); /* that's it */ |
460 | else n = gnext(n); | 478 | else n = gnext(n); |
461 | } while (n); | 479 | } while (n); |
@@ -468,20 +486,20 @@ const TValue *luaH_getstr (Table *t, TString *key) { | |||
468 | */ | 486 | */ |
469 | const TValue *luaH_get (Table *t, const TValue *key) { | 487 | const TValue *luaH_get (Table *t, const TValue *key) { |
470 | switch (ttype(key)) { | 488 | switch (ttype(key)) { |
489 | case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key)); | ||
471 | case LUA_TNIL: return luaO_nilobject; | 490 | case LUA_TNIL: return luaO_nilobject; |
472 | case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); | ||
473 | case LUA_TNUMBER: { | 491 | case LUA_TNUMBER: { |
474 | int k; | 492 | int k; |
475 | lua_Number n = nvalue(key); | 493 | lua_Number n = nvalue(key); |
476 | lua_number2int(k, n); | 494 | lua_number2int(k, n); |
477 | if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ | 495 | if (luai_numeq(cast_num(k), n)) /* index is int? */ |
478 | return luaH_getnum(t, k); /* use specialized version */ | 496 | return luaH_getint(t, k); /* use specialized version */ |
479 | /* else go through */ | 497 | /* else go through */ |
480 | } | 498 | } |
481 | default: { | 499 | default: { |
482 | Node *n = mainposition(t, key); | 500 | Node *n = mainposition(t, key); |
483 | do { /* check whether `key' is somewhere in the chain */ | 501 | do { /* check whether `key' is somewhere in the chain */ |
484 | if (luaO_rawequalObj(key2tval(n), key)) | 502 | if (luaV_rawequalobj(gkey(n), key)) |
485 | return gval(n); /* that's it */ | 503 | return gval(n); /* that's it */ |
486 | else n = gnext(n); | 504 | else n = gnext(n); |
487 | } while (n); | 505 | } while (n); |
@@ -491,41 +509,29 @@ const TValue *luaH_get (Table *t, const TValue *key) { | |||
491 | } | 509 | } |
492 | 510 | ||
493 | 511 | ||
512 | /* | ||
513 | ** beware: when using this function you probably need to check a GC | ||
514 | ** barrier and invalidate the TM cache. | ||
515 | */ | ||
494 | TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { | 516 | TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { |
495 | const TValue *p = luaH_get(t, key); | 517 | const TValue *p = luaH_get(t, key); |
496 | t->flags = 0; | ||
497 | if (p != luaO_nilobject) | 518 | if (p != luaO_nilobject) |
498 | return cast(TValue *, p); | 519 | return cast(TValue *, p); |
499 | else { | 520 | else return luaH_newkey(L, t, key); |
500 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); | ||
501 | else if (ttisnumber(key) && luai_numisnan(nvalue(key))) | ||
502 | luaG_runerror(L, "table index is NaN"); | ||
503 | return newkey(L, t, key); | ||
504 | } | ||
505 | } | 521 | } |
506 | 522 | ||
507 | 523 | ||
508 | TValue *luaH_setnum (lua_State *L, Table *t, int key) { | 524 | void luaH_setint (lua_State *L, Table *t, int key, TValue *value) { |
509 | const TValue *p = luaH_getnum(t, key); | 525 | const TValue *p = luaH_getint(t, key); |
526 | TValue *cell; | ||
510 | if (p != luaO_nilobject) | 527 | if (p != luaO_nilobject) |
511 | return cast(TValue *, p); | 528 | cell = cast(TValue *, p); |
512 | else { | 529 | else { |
513 | TValue k; | 530 | TValue k; |
514 | setnvalue(&k, cast_num(key)); | 531 | setnvalue(&k, cast_num(key)); |
515 | return newkey(L, t, &k); | 532 | cell = luaH_newkey(L, t, &k); |
516 | } | ||
517 | } | ||
518 | |||
519 | |||
520 | TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { | ||
521 | const TValue *p = luaH_getstr(t, key); | ||
522 | if (p != luaO_nilobject) | ||
523 | return cast(TValue *, p); | ||
524 | else { | ||
525 | TValue k; | ||
526 | setsvalue(L, &k, key); | ||
527 | return newkey(L, t, &k); | ||
528 | } | 533 | } |
534 | setobj2t(L, cell, value); | ||
529 | } | 535 | } |
530 | 536 | ||
531 | 537 | ||
@@ -533,20 +539,20 @@ static int unbound_search (Table *t, unsigned int j) { | |||
533 | unsigned int i = j; /* i is zero or a present index */ | 539 | unsigned int i = j; /* i is zero or a present index */ |
534 | j++; | 540 | j++; |
535 | /* find `i' and `j' such that i is present and j is not */ | 541 | /* find `i' and `j' such that i is present and j is not */ |
536 | while (!ttisnil(luaH_getnum(t, j))) { | 542 | while (!ttisnil(luaH_getint(t, j))) { |
537 | i = j; | 543 | i = j; |
538 | j *= 2; | 544 | j *= 2; |
539 | if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ | 545 | if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ |
540 | /* table was built with bad purposes: resort to linear search */ | 546 | /* table was built with bad purposes: resort to linear search */ |
541 | i = 1; | 547 | i = 1; |
542 | while (!ttisnil(luaH_getnum(t, i))) i++; | 548 | while (!ttisnil(luaH_getint(t, i))) i++; |
543 | return i - 1; | 549 | return i - 1; |
544 | } | 550 | } |
545 | } | 551 | } |
546 | /* now do a binary search between them */ | 552 | /* now do a binary search between them */ |
547 | while (j - i > 1) { | 553 | while (j - i > 1) { |
548 | unsigned int m = (i+j)/2; | 554 | unsigned int m = (i+j)/2; |
549 | if (ttisnil(luaH_getnum(t, m))) j = m; | 555 | if (ttisnil(luaH_getint(t, m))) j = m; |
550 | else i = m; | 556 | else i = m; |
551 | } | 557 | } |
552 | return i; | 558 | return i; |
@@ -570,7 +576,7 @@ int luaH_getn (Table *t) { | |||
570 | return i; | 576 | return i; |
571 | } | 577 | } |
572 | /* else must find a boundary in hash part */ | 578 | /* else must find a boundary in hash part */ |
573 | else if (t->node == dummynode) /* hash part is empty? */ | 579 | else if (isdummy(t->node)) /* hash part is empty? */ |
574 | return j; /* that is easy... */ | 580 | return j; /* that is easy... */ |
575 | else return unbound_search(t, j); | 581 | else return unbound_search(t, j); |
576 | } | 582 | } |
@@ -583,6 +589,6 @@ Node *luaH_mainposition (const Table *t, const TValue *key) { | |||
583 | return mainposition(t, key); | 589 | return mainposition(t, key); |
584 | } | 590 | } |
585 | 591 | ||
586 | int luaH_isdummy (Node *n) { return n == dummynode; } | 592 | int luaH_isdummy (Node *n) { return isdummy(n); } |
587 | 593 | ||
588 | #endif | 594 | #endif |
diff --git a/apps/plugins/lua/ltable.h b/apps/plugins/lua/ltable.h index aa28914871..d69449b2b8 100644 --- a/apps/plugins/lua/ltable.h +++ b/apps/plugins/lua/ltable.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: ltable.h,v 2.16.1.2 2013/08/30 15:49:41 roberto Exp $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -11,20 +11,25 @@ | |||
11 | 11 | ||
12 | 12 | ||
13 | #define gnode(t,i) (&(t)->node[i]) | 13 | #define gnode(t,i) (&(t)->node[i]) |
14 | #define gkey(n) (&(n)->i_key.nk) | 14 | #define gkey(n) (&(n)->i_key.tvk) |
15 | #define gval(n) (&(n)->i_val) | 15 | #define gval(n) (&(n)->i_val) |
16 | #define gnext(n) ((n)->i_key.nk.next) | 16 | #define gnext(n) ((n)->i_key.nk.next) |
17 | 17 | ||
18 | #define key2tval(n) (&(n)->i_key.tvk) | 18 | #define invalidateTMcache(t) ((t)->flags = 0) |
19 | 19 | ||
20 | /* returns the key, given the value of a table entry */ | ||
21 | #define keyfromval(v) \ | ||
22 | (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) | ||
20 | 23 | ||
21 | LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); | 24 | |
22 | LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); | 25 | LUAI_FUNC const TValue *luaH_getint (Table *t, int key); |
26 | LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value); | ||
23 | LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); | 27 | LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); |
24 | LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); | ||
25 | LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); | 28 | LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); |
29 | LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); | ||
26 | LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); | 30 | LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); |
27 | LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); | 31 | LUAI_FUNC Table *luaH_new (lua_State *L); |
32 | LUAI_FUNC void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize); | ||
28 | LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); | 33 | LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); |
29 | LUAI_FUNC void luaH_free (lua_State *L, Table *t); | 34 | LUAI_FUNC void luaH_free (lua_State *L, Table *t); |
30 | LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); | 35 | LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); |
diff --git a/apps/plugins/lua/ltablib.c b/apps/plugins/lua/ltablib.c index b6d9cb4ac7..6001224e39 100644 --- a/apps/plugins/lua/ltablib.c +++ b/apps/plugins/lua/ltablib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ | 2 | ** $Id: ltablib.c,v 1.65.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Library for Table Manipulation | 3 | ** Library for Table Manipulation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -16,43 +16,11 @@ | |||
16 | #include "lualib.h" | 16 | #include "lualib.h" |
17 | 17 | ||
18 | 18 | ||
19 | #define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) | 19 | #define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n)) |
20 | 20 | ||
21 | 21 | ||
22 | static int foreachi (lua_State *L) { | ||
23 | int i; | ||
24 | int n = aux_getn(L, 1); | ||
25 | luaL_checktype(L, 2, LUA_TFUNCTION); | ||
26 | for (i=1; i <= n; i++) { | ||
27 | lua_pushvalue(L, 2); /* function */ | ||
28 | lua_pushinteger(L, i); /* 1st argument */ | ||
29 | lua_rawgeti(L, 1, i); /* 2nd argument */ | ||
30 | lua_call(L, 2, 1); | ||
31 | if (!lua_isnil(L, -1)) | ||
32 | return 1; | ||
33 | lua_pop(L, 1); /* remove nil result */ | ||
34 | } | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | |||
39 | static int foreach (lua_State *L) { | ||
40 | luaL_checktype(L, 1, LUA_TTABLE); | ||
41 | luaL_checktype(L, 2, LUA_TFUNCTION); | ||
42 | lua_pushnil(L); /* first key */ | ||
43 | while (lua_next(L, 1)) { | ||
44 | lua_pushvalue(L, 2); /* function */ | ||
45 | lua_pushvalue(L, -3); /* key */ | ||
46 | lua_pushvalue(L, -3); /* value */ | ||
47 | lua_call(L, 2, 1); | ||
48 | if (!lua_isnil(L, -1)) | ||
49 | return 1; | ||
50 | lua_pop(L, 2); /* remove value and result */ | ||
51 | } | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | 22 | ||
23 | #if defined(LUA_COMPAT_MAXN) | ||
56 | static int maxn (lua_State *L) { | 24 | static int maxn (lua_State *L) { |
57 | lua_Number max = 0; | 25 | lua_Number max = 0; |
58 | luaL_checktype(L, 1, LUA_TTABLE); | 26 | luaL_checktype(L, 1, LUA_TTABLE); |
@@ -67,24 +35,7 @@ static int maxn (lua_State *L) { | |||
67 | lua_pushnumber(L, max); | 35 | lua_pushnumber(L, max); |
68 | return 1; | 36 | return 1; |
69 | } | 37 | } |
70 | |||
71 | |||
72 | static int getn (lua_State *L) { | ||
73 | lua_pushinteger(L, aux_getn(L, 1)); | ||
74 | return 1; | ||
75 | } | ||
76 | |||
77 | |||
78 | static int setn (lua_State *L) { | ||
79 | luaL_checktype(L, 1, LUA_TTABLE); | ||
80 | #ifndef luaL_setn | ||
81 | luaL_setn(L, 1, luaL_checkint(L, 2)); | ||
82 | #else | ||
83 | luaL_error(L, LUA_QL("setn") " is obsolete"); | ||
84 | #endif | 38 | #endif |
85 | lua_pushvalue(L, 1); | ||
86 | return 1; | ||
87 | } | ||
88 | 39 | ||
89 | 40 | ||
90 | static int tinsert (lua_State *L) { | 41 | static int tinsert (lua_State *L) { |
@@ -98,7 +49,7 @@ static int tinsert (lua_State *L) { | |||
98 | case 3: { | 49 | case 3: { |
99 | int i; | 50 | int i; |
100 | pos = luaL_checkint(L, 2); /* 2nd argument is the position */ | 51 | pos = luaL_checkint(L, 2); /* 2nd argument is the position */ |
101 | if (pos > e) e = pos; /* `grow' array if necessary */ | 52 | luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); |
102 | for (i = e; i > pos; i--) { /* move up elements */ | 53 | for (i = e; i > pos; i--) { /* move up elements */ |
103 | lua_rawgeti(L, 1, i-1); | 54 | lua_rawgeti(L, 1, i-1); |
104 | lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ | 55 | lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ |
@@ -109,25 +60,23 @@ static int tinsert (lua_State *L) { | |||
109 | return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); | 60 | return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); |
110 | } | 61 | } |
111 | } | 62 | } |
112 | luaL_setn(L, 1, e); /* new size */ | ||
113 | lua_rawseti(L, 1, pos); /* t[pos] = v */ | 63 | lua_rawseti(L, 1, pos); /* t[pos] = v */ |
114 | return 0; | 64 | return 0; |
115 | } | 65 | } |
116 | 66 | ||
117 | 67 | ||
118 | static int tremove (lua_State *L) { | 68 | static int tremove (lua_State *L) { |
119 | int e = aux_getn(L, 1); | 69 | int size = aux_getn(L, 1); |
120 | int pos = luaL_optint(L, 2, e); | 70 | int pos = luaL_optint(L, 2, size); |
121 | if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ | 71 | if (pos != size) /* validate 'pos' if given */ |
122 | return 0; /* nothing to remove */ | 72 | luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); |
123 | luaL_setn(L, 1, e - 1); /* t.n = n-1 */ | ||
124 | lua_rawgeti(L, 1, pos); /* result = t[pos] */ | 73 | lua_rawgeti(L, 1, pos); /* result = t[pos] */ |
125 | for ( ;pos<e; pos++) { | 74 | for ( ; pos < size; pos++) { |
126 | lua_rawgeti(L, 1, pos+1); | 75 | lua_rawgeti(L, 1, pos+1); |
127 | lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ | 76 | lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ |
128 | } | 77 | } |
129 | lua_pushnil(L); | 78 | lua_pushnil(L); |
130 | lua_rawseti(L, 1, e); /* t[e] = nil */ | 79 | lua_rawseti(L, 1, pos); /* t[pos] = nil */ |
131 | return 1; | 80 | return 1; |
132 | } | 81 | } |
133 | 82 | ||
@@ -137,7 +86,7 @@ static void addfield (lua_State *L, luaL_Buffer *b, int i) { | |||
137 | if (!lua_isstring(L, -1)) | 86 | if (!lua_isstring(L, -1)) |
138 | luaL_error(L, "invalid value (%s) at index %d in table for " | 87 | luaL_error(L, "invalid value (%s) at index %d in table for " |
139 | LUA_QL("concat"), luaL_typename(L, -1), i); | 88 | LUA_QL("concat"), luaL_typename(L, -1), i); |
140 | luaL_addvalue(b); | 89 | luaL_addvalue(b); |
141 | } | 90 | } |
142 | 91 | ||
143 | 92 | ||
@@ -148,7 +97,7 @@ static int tconcat (lua_State *L) { | |||
148 | const char *sep = luaL_optlstring(L, 2, "", &lsep); | 97 | const char *sep = luaL_optlstring(L, 2, "", &lsep); |
149 | luaL_checktype(L, 1, LUA_TTABLE); | 98 | luaL_checktype(L, 1, LUA_TTABLE); |
150 | i = luaL_optint(L, 3, 1); | 99 | i = luaL_optint(L, 3, 1); |
151 | last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1)); | 100 | last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1)); |
152 | luaL_buffinit(L, &b); | 101 | luaL_buffinit(L, &b); |
153 | for (; i < last; i++) { | 102 | for (; i < last; i++) { |
154 | addfield(L, &b, i); | 103 | addfield(L, &b, i); |
@@ -161,12 +110,54 @@ static int tconcat (lua_State *L) { | |||
161 | } | 110 | } |
162 | 111 | ||
163 | 112 | ||
113 | /* | ||
114 | ** {====================================================== | ||
115 | ** Pack/unpack | ||
116 | ** ======================================================= | ||
117 | */ | ||
118 | |||
119 | static int pack (lua_State *L) { | ||
120 | int n = lua_gettop(L); /* number of elements to pack */ | ||
121 | lua_createtable(L, n, 1); /* create result table */ | ||
122 | lua_pushinteger(L, n); | ||
123 | lua_setfield(L, -2, "n"); /* t.n = number of elements */ | ||
124 | if (n > 0) { /* at least one element? */ | ||
125 | int i; | ||
126 | lua_pushvalue(L, 1); | ||
127 | lua_rawseti(L, -2, 1); /* insert first element */ | ||
128 | lua_replace(L, 1); /* move table into index 1 */ | ||
129 | for (i = n; i >= 2; i--) /* assign other elements */ | ||
130 | lua_rawseti(L, 1, i); | ||
131 | } | ||
132 | return 1; /* return table */ | ||
133 | } | ||
134 | |||
135 | |||
136 | static int unpack (lua_State *L) { | ||
137 | int i, e, n; | ||
138 | luaL_checktype(L, 1, LUA_TTABLE); | ||
139 | i = luaL_optint(L, 2, 1); | ||
140 | e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1)); | ||
141 | if (i > e) return 0; /* empty range */ | ||
142 | n = e - i + 1; /* number of elements */ | ||
143 | if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ | ||
144 | return luaL_error(L, "too many results to unpack"); | ||
145 | lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ | ||
146 | while (i++ < e) /* push arg[i + 1...e] */ | ||
147 | lua_rawgeti(L, 1, i); | ||
148 | return n; | ||
149 | } | ||
150 | |||
151 | /* }====================================================== */ | ||
152 | |||
153 | |||
164 | 154 | ||
165 | /* | 155 | /* |
166 | ** {====================================================== | 156 | ** {====================================================== |
167 | ** Quicksort | 157 | ** Quicksort |
168 | ** (based on `Algorithms in MODULA-3', Robert Sedgewick; | 158 | ** (based on `Algorithms in MODULA-3', Robert Sedgewick; |
169 | ** Addison-Wesley, 1993.) | 159 | ** Addison-Wesley, 1993.) |
160 | ** ======================================================= | ||
170 | */ | 161 | */ |
171 | 162 | ||
172 | 163 | ||
@@ -187,7 +178,7 @@ static int sort_comp (lua_State *L, int a, int b) { | |||
187 | return res; | 178 | return res; |
188 | } | 179 | } |
189 | else /* a < b? */ | 180 | else /* a < b? */ |
190 | return lua_lessthan(L, a, b); | 181 | return lua_compare(L, a, b, LUA_OPLT); |
191 | } | 182 | } |
192 | 183 | ||
193 | static void auxsort (lua_State *L, int l, int u) { | 184 | static void auxsort (lua_State *L, int l, int u) { |
@@ -224,12 +215,12 @@ static void auxsort (lua_State *L, int l, int u) { | |||
224 | for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ | 215 | for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ |
225 | /* repeat ++i until a[i] >= P */ | 216 | /* repeat ++i until a[i] >= P */ |
226 | while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { | 217 | while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { |
227 | if (i>u) luaL_error(L, "invalid order function for sorting"); | 218 | if (i>=u) luaL_error(L, "invalid order function for sorting"); |
228 | lua_pop(L, 1); /* remove a[i] */ | 219 | lua_pop(L, 1); /* remove a[i] */ |
229 | } | 220 | } |
230 | /* repeat --j until a[j] <= P */ | 221 | /* repeat --j until a[j] <= P */ |
231 | while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { | 222 | while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { |
232 | if (j<l) luaL_error(L, "invalid order function for sorting"); | 223 | if (j<=l) luaL_error(L, "invalid order function for sorting"); |
233 | lua_pop(L, 1); /* remove a[j] */ | 224 | lua_pop(L, 1); /* remove a[j] */ |
234 | } | 225 | } |
235 | if (j<i) { | 226 | if (j<i) { |
@@ -268,20 +259,25 @@ static int sort (lua_State *L) { | |||
268 | 259 | ||
269 | static const luaL_Reg tab_funcs[] = { | 260 | static const luaL_Reg tab_funcs[] = { |
270 | {"concat", tconcat}, | 261 | {"concat", tconcat}, |
271 | {"foreach", foreach}, | 262 | #if defined(LUA_COMPAT_MAXN) |
272 | {"foreachi", foreachi}, | ||
273 | {"getn", getn}, | ||
274 | {"maxn", maxn}, | 263 | {"maxn", maxn}, |
264 | #endif | ||
275 | {"insert", tinsert}, | 265 | {"insert", tinsert}, |
266 | {"pack", pack}, | ||
267 | {"unpack", unpack}, | ||
276 | {"remove", tremove}, | 268 | {"remove", tremove}, |
277 | {"setn", setn}, | ||
278 | {"sort", sort}, | 269 | {"sort", sort}, |
279 | {NULL, NULL} | 270 | {NULL, NULL} |
280 | }; | 271 | }; |
281 | 272 | ||
282 | 273 | ||
283 | LUALIB_API int luaopen_table (lua_State *L) { | 274 | LUAMOD_API int luaopen_table (lua_State *L) { |
284 | luaL_register(L, LUA_TABLIBNAME, tab_funcs); | 275 | luaL_newlib(L, tab_funcs); |
276 | #if defined(LUA_COMPAT_UNPACK) | ||
277 | /* _G.unpack = table.unpack */ | ||
278 | lua_getfield(L, -1, "unpack"); | ||
279 | lua_setglobal(L, "unpack"); | ||
280 | #endif | ||
285 | return 1; | 281 | return 1; |
286 | } | 282 | } |
287 | 283 | ||
diff --git a/apps/plugins/lua/ltm.c b/apps/plugins/lua/ltm.c index c27f0f6fab..69b4ed7727 100644 --- a/apps/plugins/lua/ltm.c +++ b/apps/plugins/lua/ltm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ | 2 | ** $Id: ltm.c,v 2.14.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -19,20 +19,22 @@ | |||
19 | #include "ltm.h" | 19 | #include "ltm.h" |
20 | 20 | ||
21 | 21 | ||
22 | static const char udatatypename[] = "userdata"; | ||
22 | 23 | ||
23 | const char *const luaT_typenames[] = { | 24 | LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { |
24 | "nil", "boolean", "userdata", "number", | 25 | "no value", |
25 | "string", "table", "function", "userdata", "thread", | 26 | "nil", "boolean", udatatypename, "number", |
26 | "proto", "upval" | 27 | "string", "table", "function", udatatypename, "thread", |
28 | "proto", "upval" /* these last two cases are used for tests only */ | ||
27 | }; | 29 | }; |
28 | 30 | ||
29 | 31 | ||
30 | void luaT_init (lua_State *L) { | 32 | void luaT_init (lua_State *L) { |
31 | static const char *const luaT_eventname[] = { /* ORDER TM */ | 33 | static const char *const luaT_eventname[] = { /* ORDER TM */ |
32 | "__index", "__newindex", | 34 | "__index", "__newindex", |
33 | "__gc", "__mode", "__eq", | 35 | "__gc", "__mode", "__len", "__eq", |
34 | "__add", "__sub", "__mul", "__div", "__mod", | 36 | "__add", "__sub", "__mul", "__div", "__mod", |
35 | "__pow", "__unm", "__len", "__lt", "__le", | 37 | "__pow", "__unm", "__lt", "__le", |
36 | "__concat", "__call" | 38 | "__concat", "__call" |
37 | }; | 39 | }; |
38 | int i; | 40 | int i; |
@@ -60,7 +62,7 @@ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { | |||
60 | 62 | ||
61 | const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { | 63 | const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { |
62 | Table *mt; | 64 | Table *mt; |
63 | switch (ttype(o)) { | 65 | switch (ttypenv(o)) { |
64 | case LUA_TTABLE: | 66 | case LUA_TTABLE: |
65 | mt = hvalue(o)->metatable; | 67 | mt = hvalue(o)->metatable; |
66 | break; | 68 | break; |
@@ -68,7 +70,7 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { | |||
68 | mt = uvalue(o)->metatable; | 70 | mt = uvalue(o)->metatable; |
69 | break; | 71 | break; |
70 | default: | 72 | default: |
71 | mt = G(L)->mt[ttype(o)]; | 73 | mt = G(L)->mt[ttypenv(o)]; |
72 | } | 74 | } |
73 | return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); | 75 | return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); |
74 | } | 76 | } |
diff --git a/apps/plugins/lua/ltm.h b/apps/plugins/lua/ltm.h index 1b89683ef3..7f89c841f9 100644 --- a/apps/plugins/lua/ltm.h +++ b/apps/plugins/lua/ltm.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: ltm.h,v 2.11.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -20,6 +20,7 @@ typedef enum { | |||
20 | TM_NEWINDEX, | 20 | TM_NEWINDEX, |
21 | TM_GC, | 21 | TM_GC, |
22 | TM_MODE, | 22 | TM_MODE, |
23 | TM_LEN, | ||
23 | TM_EQ, /* last tag method with `fast' access */ | 24 | TM_EQ, /* last tag method with `fast' access */ |
24 | TM_ADD, | 25 | TM_ADD, |
25 | TM_SUB, | 26 | TM_SUB, |
@@ -28,7 +29,6 @@ typedef enum { | |||
28 | TM_MOD, | 29 | TM_MOD, |
29 | TM_POW, | 30 | TM_POW, |
30 | TM_UNM, | 31 | TM_UNM, |
31 | TM_LEN, | ||
32 | TM_LT, | 32 | TM_LT, |
33 | TM_LE, | 33 | TM_LE, |
34 | TM_CONCAT, | 34 | TM_CONCAT, |
@@ -43,7 +43,10 @@ typedef enum { | |||
43 | 43 | ||
44 | #define fasttm(l,et,e) gfasttm(G(l), et, e) | 44 | #define fasttm(l,et,e) gfasttm(G(l), et, e) |
45 | 45 | ||
46 | LUAI_DATA const char *const luaT_typenames[]; | 46 | #define ttypename(x) luaT_typenames_[(x) + 1] |
47 | #define objtypename(x) ttypename(ttypenv(x)) | ||
48 | |||
49 | LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; | ||
47 | 50 | ||
48 | 51 | ||
49 | LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); | 52 | LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); |
diff --git a/apps/plugins/lua/lua.h b/apps/plugins/lua/lua.h index a0c57dc60b..149a2c37bc 100644 --- a/apps/plugins/lua/lua.h +++ b/apps/plugins/lua/lua.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lua.h,v 1.285.1.2 2013/11/11 12:09:16 roberto Exp $ |
3 | ** Lua - An Extensible Extension Language | 3 | ** Lua - A Scripting Language |
4 | ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) | 4 | ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) |
5 | ** See Copyright Notice at the end of this file | 5 | ** See Copyright Notice at the end of this file |
6 | */ | 6 | */ |
@@ -16,35 +16,39 @@ | |||
16 | #include "luaconf.h" | 16 | #include "luaconf.h" |
17 | 17 | ||
18 | 18 | ||
19 | #define LUA_VERSION "Lua 5.1" | 19 | #define LUA_VERSION_MAJOR "5" |
20 | #define LUA_RELEASE "Lua 5.1.4" | 20 | #define LUA_VERSION_MINOR "2" |
21 | #define LUA_VERSION_NUM 501 | 21 | #define LUA_VERSION_NUM 502 |
22 | #define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" | 22 | #define LUA_VERSION_RELEASE "3" |
23 | #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" | ||
24 | 23 | ||
24 | #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR | ||
25 | #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE | ||
26 | #define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2013 Lua.org, PUC-Rio" | ||
27 | #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" | ||
25 | 28 | ||
26 | /* mark for precompiled code (`<esc>Lua') */ | ||
27 | #define LUA_SIGNATURE "\033Lua" | ||
28 | 29 | ||
29 | /* option for multiple returns in `lua_pcall' and `lua_call' */ | 30 | /* mark for precompiled code ('<esc>Lua') */ |
31 | #define LUA_SIGNATURE "\033Lua" | ||
32 | |||
33 | /* option for multiple returns in 'lua_pcall' and 'lua_call' */ | ||
30 | #define LUA_MULTRET (-1) | 34 | #define LUA_MULTRET (-1) |
31 | 35 | ||
32 | 36 | ||
33 | /* | 37 | /* |
34 | ** pseudo-indices | 38 | ** pseudo-indices |
35 | */ | 39 | */ |
36 | #define LUA_REGISTRYINDEX (-10000) | 40 | #define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX |
37 | #define LUA_ENVIRONINDEX (-10001) | 41 | #define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) |
38 | #define LUA_GLOBALSINDEX (-10002) | ||
39 | #define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) | ||
40 | 42 | ||
41 | 43 | ||
42 | /* thread status; 0 is OK */ | 44 | /* thread status */ |
45 | #define LUA_OK 0 | ||
43 | #define LUA_YIELD 1 | 46 | #define LUA_YIELD 1 |
44 | #define LUA_ERRRUN 2 | 47 | #define LUA_ERRRUN 2 |
45 | #define LUA_ERRSYNTAX 3 | 48 | #define LUA_ERRSYNTAX 3 |
46 | #define LUA_ERRMEM 4 | 49 | #define LUA_ERRMEM 4 |
47 | #define LUA_ERRERR 5 | 50 | #define LUA_ERRGCMM 5 |
51 | #define LUA_ERRERR 6 | ||
48 | 52 | ||
49 | 53 | ||
50 | typedef struct lua_State lua_State; | 54 | typedef struct lua_State lua_State; |
@@ -81,18 +85,18 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); | |||
81 | #define LUA_TUSERDATA 7 | 85 | #define LUA_TUSERDATA 7 |
82 | #define LUA_TTHREAD 8 | 86 | #define LUA_TTHREAD 8 |
83 | 87 | ||
88 | #define LUA_NUMTAGS 9 | ||
89 | |||
84 | 90 | ||
85 | 91 | ||
86 | /* minimum Lua stack available to a C function */ | 92 | /* minimum Lua stack available to a C function */ |
87 | #define LUA_MINSTACK 20 | 93 | #define LUA_MINSTACK 20 |
88 | 94 | ||
89 | 95 | ||
90 | /* | 96 | /* predefined values in the registry */ |
91 | ** generic extra include file | 97 | #define LUA_RIDX_MAINTHREAD 1 |
92 | */ | 98 | #define LUA_RIDX_GLOBALS 2 |
93 | #if defined(LUA_USER_H) | 99 | #define LUA_RIDX_LAST LUA_RIDX_GLOBALS |
94 | #include LUA_USER_H | ||
95 | #endif | ||
96 | 100 | ||
97 | 101 | ||
98 | /* type of numbers in Lua */ | 102 | /* type of numbers in Lua */ |
@@ -102,6 +106,23 @@ typedef LUA_NUMBER lua_Number; | |||
102 | /* type for integer functions */ | 106 | /* type for integer functions */ |
103 | typedef LUA_INTEGER lua_Integer; | 107 | typedef LUA_INTEGER lua_Integer; |
104 | 108 | ||
109 | /* unsigned integer type */ | ||
110 | typedef LUA_UNSIGNED lua_Unsigned; | ||
111 | |||
112 | |||
113 | |||
114 | /* | ||
115 | ** generic extra include file | ||
116 | */ | ||
117 | #if defined(LUA_USER_H) | ||
118 | #include LUA_USER_H | ||
119 | #endif | ||
120 | |||
121 | |||
122 | /* | ||
123 | ** RCS ident string | ||
124 | */ | ||
125 | extern const char lua_ident[]; | ||
105 | 126 | ||
106 | 127 | ||
107 | /* | 128 | /* |
@@ -114,15 +135,20 @@ LUA_API lua_State *(lua_newthread) (lua_State *L); | |||
114 | LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); | 135 | LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); |
115 | 136 | ||
116 | 137 | ||
138 | LUA_API const lua_Number *(lua_version) (lua_State *L); | ||
139 | |||
140 | |||
117 | /* | 141 | /* |
118 | ** basic stack manipulation | 142 | ** basic stack manipulation |
119 | */ | 143 | */ |
144 | LUA_API int (lua_absindex) (lua_State *L, int idx); | ||
120 | LUA_API int (lua_gettop) (lua_State *L); | 145 | LUA_API int (lua_gettop) (lua_State *L); |
121 | LUA_API void (lua_settop) (lua_State *L, int idx); | 146 | LUA_API void (lua_settop) (lua_State *L, int idx); |
122 | LUA_API void (lua_pushvalue) (lua_State *L, int idx); | 147 | LUA_API void (lua_pushvalue) (lua_State *L, int idx); |
123 | LUA_API void (lua_remove) (lua_State *L, int idx); | 148 | LUA_API void (lua_remove) (lua_State *L, int idx); |
124 | LUA_API void (lua_insert) (lua_State *L, int idx); | 149 | LUA_API void (lua_insert) (lua_State *L, int idx); |
125 | LUA_API void (lua_replace) (lua_State *L, int idx); | 150 | LUA_API void (lua_replace) (lua_State *L, int idx); |
151 | LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); | ||
126 | LUA_API int (lua_checkstack) (lua_State *L, int sz); | 152 | LUA_API int (lua_checkstack) (lua_State *L, int sz); |
127 | 153 | ||
128 | LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); | 154 | LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); |
@@ -139,15 +165,12 @@ LUA_API int (lua_isuserdata) (lua_State *L, int idx); | |||
139 | LUA_API int (lua_type) (lua_State *L, int idx); | 165 | LUA_API int (lua_type) (lua_State *L, int idx); |
140 | LUA_API const char *(lua_typename) (lua_State *L, int tp); | 166 | LUA_API const char *(lua_typename) (lua_State *L, int tp); |
141 | 167 | ||
142 | LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); | 168 | LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); |
143 | LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); | 169 | LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); |
144 | LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); | 170 | LUA_API lua_Unsigned (lua_tounsignedx) (lua_State *L, int idx, int *isnum); |
145 | |||
146 | LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); | ||
147 | LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); | ||
148 | LUA_API int (lua_toboolean) (lua_State *L, int idx); | 171 | LUA_API int (lua_toboolean) (lua_State *L, int idx); |
149 | LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); | 172 | LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); |
150 | LUA_API size_t (lua_objlen) (lua_State *L, int idx); | 173 | LUA_API size_t (lua_rawlen) (lua_State *L, int idx); |
151 | LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); | 174 | LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); |
152 | LUA_API void *(lua_touserdata) (lua_State *L, int idx); | 175 | LUA_API void *(lua_touserdata) (lua_State *L, int idx); |
153 | LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); | 176 | LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); |
@@ -155,13 +178,36 @@ LUA_API const void *(lua_topointer) (lua_State *L, int idx); | |||
155 | 178 | ||
156 | 179 | ||
157 | /* | 180 | /* |
181 | ** Comparison and arithmetic functions | ||
182 | */ | ||
183 | |||
184 | #define LUA_OPADD 0 /* ORDER TM */ | ||
185 | #define LUA_OPSUB 1 | ||
186 | #define LUA_OPMUL 2 | ||
187 | #define LUA_OPDIV 3 | ||
188 | #define LUA_OPMOD 4 | ||
189 | #define LUA_OPPOW 5 | ||
190 | #define LUA_OPUNM 6 | ||
191 | |||
192 | LUA_API void (lua_arith) (lua_State *L, int op); | ||
193 | |||
194 | #define LUA_OPEQ 0 | ||
195 | #define LUA_OPLT 1 | ||
196 | #define LUA_OPLE 2 | ||
197 | |||
198 | LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); | ||
199 | LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); | ||
200 | |||
201 | |||
202 | /* | ||
158 | ** push functions (C -> stack) | 203 | ** push functions (C -> stack) |
159 | */ | 204 | */ |
160 | LUA_API void (lua_pushnil) (lua_State *L); | 205 | LUA_API void (lua_pushnil) (lua_State *L); |
161 | LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); | 206 | LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); |
162 | LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); | 207 | LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); |
163 | LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); | 208 | LUA_API void (lua_pushunsigned) (lua_State *L, lua_Unsigned n); |
164 | LUA_API void (lua_pushstring) (lua_State *L, const char *s); | 209 | LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t l); |
210 | LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); | ||
165 | LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, | 211 | LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, |
166 | va_list argp); | 212 | va_list argp); |
167 | LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); | 213 | LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); |
@@ -174,35 +220,47 @@ LUA_API int (lua_pushthread) (lua_State *L); | |||
174 | /* | 220 | /* |
175 | ** get functions (Lua -> stack) | 221 | ** get functions (Lua -> stack) |
176 | */ | 222 | */ |
223 | LUA_API void (lua_getglobal) (lua_State *L, const char *var); | ||
177 | LUA_API void (lua_gettable) (lua_State *L, int idx); | 224 | LUA_API void (lua_gettable) (lua_State *L, int idx); |
178 | LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); | 225 | LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); |
179 | LUA_API void (lua_rawget) (lua_State *L, int idx); | 226 | LUA_API void (lua_rawget) (lua_State *L, int idx); |
180 | LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); | 227 | LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); |
228 | LUA_API void (lua_rawgetp) (lua_State *L, int idx, const void *p); | ||
181 | LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); | 229 | LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); |
182 | LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); | 230 | LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); |
183 | LUA_API int (lua_getmetatable) (lua_State *L, int objindex); | 231 | LUA_API int (lua_getmetatable) (lua_State *L, int objindex); |
184 | LUA_API void (lua_getfenv) (lua_State *L, int idx); | 232 | LUA_API void (lua_getuservalue) (lua_State *L, int idx); |
185 | 233 | ||
186 | 234 | ||
187 | /* | 235 | /* |
188 | ** set functions (stack -> Lua) | 236 | ** set functions (stack -> Lua) |
189 | */ | 237 | */ |
238 | LUA_API void (lua_setglobal) (lua_State *L, const char *var); | ||
190 | LUA_API void (lua_settable) (lua_State *L, int idx); | 239 | LUA_API void (lua_settable) (lua_State *L, int idx); |
191 | LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); | 240 | LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); |
192 | LUA_API void (lua_rawset) (lua_State *L, int idx); | 241 | LUA_API void (lua_rawset) (lua_State *L, int idx); |
193 | LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); | 242 | LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); |
243 | LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); | ||
194 | LUA_API int (lua_setmetatable) (lua_State *L, int objindex); | 244 | LUA_API int (lua_setmetatable) (lua_State *L, int objindex); |
195 | LUA_API int (lua_setfenv) (lua_State *L, int idx); | 245 | LUA_API void (lua_setuservalue) (lua_State *L, int idx); |
196 | 246 | ||
197 | 247 | ||
198 | /* | 248 | /* |
199 | ** `load' and `call' functions (load and run Lua code) | 249 | ** 'load' and 'call' functions (load and run Lua code) |
200 | */ | 250 | */ |
201 | LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); | 251 | LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx, |
202 | LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); | 252 | lua_CFunction k); |
203 | LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); | 253 | #define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) |
254 | |||
255 | LUA_API int (lua_getctx) (lua_State *L, int *ctx); | ||
256 | |||
257 | LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, | ||
258 | int ctx, lua_CFunction k); | ||
259 | #define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) | ||
260 | |||
204 | LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, | 261 | LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, |
205 | const char *chunkname); | 262 | const char *chunkname, |
263 | const char *mode); | ||
206 | 264 | ||
207 | LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); | 265 | LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); |
208 | 266 | ||
@@ -210,8 +268,10 @@ LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); | |||
210 | /* | 268 | /* |
211 | ** coroutine functions | 269 | ** coroutine functions |
212 | */ | 270 | */ |
213 | LUA_API int (lua_yield) (lua_State *L, int nresults); | 271 | LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx, |
214 | LUA_API int (lua_resume) (lua_State *L, int narg); | 272 | lua_CFunction k); |
273 | #define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) | ||
274 | LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); | ||
215 | LUA_API int (lua_status) (lua_State *L); | 275 | LUA_API int (lua_status) (lua_State *L); |
216 | 276 | ||
217 | /* | 277 | /* |
@@ -226,6 +286,10 @@ LUA_API int (lua_status) (lua_State *L); | |||
226 | #define LUA_GCSTEP 5 | 286 | #define LUA_GCSTEP 5 |
227 | #define LUA_GCSETPAUSE 6 | 287 | #define LUA_GCSETPAUSE 6 |
228 | #define LUA_GCSETSTEPMUL 7 | 288 | #define LUA_GCSETSTEPMUL 7 |
289 | #define LUA_GCSETMAJORINC 8 | ||
290 | #define LUA_GCISRUNNING 9 | ||
291 | #define LUA_GCGEN 10 | ||
292 | #define LUA_GCINC 11 | ||
229 | 293 | ||
230 | LUA_API int (lua_gc) (lua_State *L, int what, int data); | 294 | LUA_API int (lua_gc) (lua_State *L, int what, int data); |
231 | 295 | ||
@@ -239,18 +303,23 @@ LUA_API int (lua_error) (lua_State *L); | |||
239 | LUA_API int (lua_next) (lua_State *L, int idx); | 303 | LUA_API int (lua_next) (lua_State *L, int idx); |
240 | 304 | ||
241 | LUA_API void (lua_concat) (lua_State *L, int n); | 305 | LUA_API void (lua_concat) (lua_State *L, int n); |
306 | LUA_API void (lua_len) (lua_State *L, int idx); | ||
242 | 307 | ||
243 | LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); | 308 | LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); |
244 | LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); | 309 | LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); |
245 | 310 | ||
246 | 311 | ||
247 | 312 | ||
248 | /* | 313 | /* |
249 | ** =============================================================== | 314 | ** =============================================================== |
250 | ** some useful macros | 315 | ** some useful macros |
251 | ** =============================================================== | 316 | ** =============================================================== |
252 | */ | 317 | */ |
253 | 318 | ||
319 | #define lua_tonumber(L,i) lua_tonumberx(L,i,NULL) | ||
320 | #define lua_tointeger(L,i) lua_tointegerx(L,i,NULL) | ||
321 | #define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL) | ||
322 | |||
254 | #define lua_pop(L,n) lua_settop(L, -(n)-1) | 323 | #define lua_pop(L,n) lua_settop(L, -(n)-1) |
255 | 324 | ||
256 | #define lua_newtable(L) lua_createtable(L, 0, 0) | 325 | #define lua_newtable(L) lua_createtable(L, 0, 0) |
@@ -259,8 +328,6 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); | |||
259 | 328 | ||
260 | #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) | 329 | #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) |
261 | 330 | ||
262 | #define lua_strlen(L,i) lua_objlen(L, (i)) | ||
263 | |||
264 | #define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) | 331 | #define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) |
265 | #define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) | 332 | #define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) |
266 | #define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) | 333 | #define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) |
@@ -273,32 +340,14 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); | |||
273 | #define lua_pushliteral(L, s) \ | 340 | #define lua_pushliteral(L, s) \ |
274 | lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) | 341 | lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) |
275 | 342 | ||
276 | #define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) | 343 | #define lua_pushglobaltable(L) \ |
277 | #define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) | 344 | lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) |
278 | 345 | ||
279 | #define lua_tostring(L,i) lua_tolstring(L, (i), NULL) | 346 | #define lua_tostring(L,i) lua_tolstring(L, (i), NULL) |
280 | 347 | ||
281 | 348 | ||
282 | 349 | ||
283 | /* | 350 | /* |
284 | ** compatibility macros and functions | ||
285 | */ | ||
286 | |||
287 | #define lua_open() luaL_newstate() | ||
288 | |||
289 | #define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) | ||
290 | |||
291 | #define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) | ||
292 | |||
293 | #define lua_Chunkreader lua_Reader | ||
294 | #define lua_Chunkwriter lua_Writer | ||
295 | |||
296 | |||
297 | /* hack */ | ||
298 | LUA_API void lua_setlevel (lua_State *from, lua_State *to); | ||
299 | |||
300 | |||
301 | /* | ||
302 | ** {====================================================================== | 351 | ** {====================================================================== |
303 | ** Debug API | 352 | ** Debug API |
304 | ** ======================================================================= | 353 | ** ======================================================================= |
@@ -312,7 +361,7 @@ LUA_API void lua_setlevel (lua_State *from, lua_State *to); | |||
312 | #define LUA_HOOKRET 1 | 361 | #define LUA_HOOKRET 1 |
313 | #define LUA_HOOKLINE 2 | 362 | #define LUA_HOOKLINE 2 |
314 | #define LUA_HOOKCOUNT 3 | 363 | #define LUA_HOOKCOUNT 3 |
315 | #define LUA_HOOKTAILRET 4 | 364 | #define LUA_HOOKTAILCALL 4 |
316 | 365 | ||
317 | 366 | ||
318 | /* | 367 | /* |
@@ -326,43 +375,50 @@ LUA_API void lua_setlevel (lua_State *from, lua_State *to); | |||
326 | typedef struct lua_Debug lua_Debug; /* activation record */ | 375 | typedef struct lua_Debug lua_Debug; /* activation record */ |
327 | 376 | ||
328 | 377 | ||
329 | /* Functions to be called by the debuger in specific events */ | 378 | /* Functions to be called by the debugger in specific events */ |
330 | typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); | 379 | typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); |
331 | 380 | ||
332 | 381 | ||
333 | LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); | 382 | LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); |
334 | LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); | 383 | LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); |
335 | LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); | 384 | LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); |
336 | LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); | 385 | LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); |
337 | LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); | 386 | LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); |
338 | LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); | 387 | LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); |
388 | |||
389 | LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); | ||
390 | LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, | ||
391 | int fidx2, int n2); | ||
339 | 392 | ||
340 | LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); | 393 | LUA_API int (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); |
341 | LUA_API lua_Hook lua_gethook (lua_State *L); | 394 | LUA_API lua_Hook (lua_gethook) (lua_State *L); |
342 | LUA_API int lua_gethookmask (lua_State *L); | 395 | LUA_API int (lua_gethookmask) (lua_State *L); |
343 | LUA_API int lua_gethookcount (lua_State *L); | 396 | LUA_API int (lua_gethookcount) (lua_State *L); |
344 | 397 | ||
345 | 398 | ||
346 | struct lua_Debug { | 399 | struct lua_Debug { |
347 | int event; | 400 | int event; |
348 | const char *name; /* (n) */ | 401 | const char *name; /* (n) */ |
349 | const char *namewhat; /* (n) `global', `local', `field', `method' */ | 402 | const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ |
350 | const char *what; /* (S) `Lua', `C', `main', `tail' */ | 403 | const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ |
351 | const char *source; /* (S) */ | 404 | const char *source; /* (S) */ |
352 | int currentline; /* (l) */ | 405 | int currentline; /* (l) */ |
353 | int nups; /* (u) number of upvalues */ | ||
354 | int linedefined; /* (S) */ | 406 | int linedefined; /* (S) */ |
355 | int lastlinedefined; /* (S) */ | 407 | int lastlinedefined; /* (S) */ |
408 | unsigned char nups; /* (u) number of upvalues */ | ||
409 | unsigned char nparams;/* (u) number of parameters */ | ||
410 | char isvararg; /* (u) */ | ||
411 | char istailcall; /* (t) */ | ||
356 | char short_src[LUA_IDSIZE]; /* (S) */ | 412 | char short_src[LUA_IDSIZE]; /* (S) */ |
357 | /* private part */ | 413 | /* private part */ |
358 | int i_ci; /* active function */ | 414 | struct CallInfo *i_ci; /* active function */ |
359 | }; | 415 | }; |
360 | 416 | ||
361 | /* }====================================================================== */ | 417 | /* }====================================================================== */ |
362 | 418 | ||
363 | 419 | ||
364 | /****************************************************************************** | 420 | /****************************************************************************** |
365 | * Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. | 421 | * Copyright (C) 1994-2013 Lua.org, PUC-Rio. |
366 | * | 422 | * |
367 | * Permission is hereby granted, free of charge, to any person obtaining | 423 | * Permission is hereby granted, free of charge, to any person obtaining |
368 | * a copy of this software and associated documentation files (the | 424 | * a copy of this software and associated documentation files (the |
diff --git a/apps/plugins/lua/luaconf.h b/apps/plugins/lua/luaconf.h index 109e680a17..ed83e8f640 100644 --- a/apps/plugins/lua/luaconf.h +++ b/apps/plugins/lua/luaconf.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: luaconf.h,v 1.176.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Configuration file for Lua | 3 | ** Configuration file for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -24,30 +24,44 @@ | |||
24 | ** CHANGE it (define it) if you want Lua to avoid the use of any | 24 | ** CHANGE it (define it) if you want Lua to avoid the use of any |
25 | ** non-ansi feature or library. | 25 | ** non-ansi feature or library. |
26 | */ | 26 | */ |
27 | #if defined(__STRICT_ANSI__) | 27 | #if !defined(LUA_ANSI) && defined(__STRICT_ANSI__) |
28 | #define LUA_ANSI | 28 | #define LUA_ANSI |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | 31 | ||
32 | #if !defined(LUA_ANSI) && defined(_WIN32) | 32 | #if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) |
33 | #define LUA_WIN | 33 | #define LUA_WIN /* enable goodies for regular Windows platforms */ |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | #if defined(LUA_WIN) | ||
37 | #define LUA_DL_DLL | ||
38 | #define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ | ||
39 | #endif | ||
40 | |||
41 | |||
42 | |||
36 | #if defined(LUA_USE_LINUX) | 43 | #if defined(LUA_USE_LINUX) |
37 | #define LUA_USE_POSIX | 44 | #define LUA_USE_POSIX |
38 | #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ | 45 | #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ |
39 | #define LUA_USE_READLINE /* needs some extra libraries */ | 46 | #define LUA_USE_READLINE /* needs some extra libraries */ |
47 | #define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ | ||
48 | #define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ | ||
49 | #define LUA_USE_LONGLONG /* assume support for long long */ | ||
40 | #endif | 50 | #endif |
41 | 51 | ||
42 | #if defined(LUA_USE_MACOSX) | 52 | #if defined(LUA_USE_MACOSX) |
43 | #define LUA_USE_POSIX | 53 | #define LUA_USE_POSIX |
44 | #define LUA_DL_DYLD /* does not need extra library */ | 54 | #define LUA_USE_DLOPEN /* does not need -ldl */ |
55 | #define LUA_USE_READLINE /* needs an extra library: -lreadline */ | ||
56 | #define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ | ||
57 | #define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ | ||
58 | #define LUA_USE_LONGLONG /* assume support for long long */ | ||
45 | #endif | 59 | #endif |
46 | 60 | ||
47 | 61 | ||
48 | 62 | ||
49 | /* | 63 | /* |
50 | @@ LUA_USE_POSIX includes all functionallity listed as X/Open System | 64 | @@ LUA_USE_POSIX includes all functionality listed as X/Open System |
51 | @* Interfaces Extension (XSI). | 65 | @* Interfaces Extension (XSI). |
52 | ** CHANGE it (define it) if your system is XSI compatible. | 66 | ** CHANGE it (define it) if your system is XSI compatible. |
53 | */ | 67 | */ |
@@ -56,20 +70,10 @@ | |||
56 | #define LUA_USE_ISATTY | 70 | #define LUA_USE_ISATTY |
57 | #define LUA_USE_POPEN | 71 | #define LUA_USE_POPEN |
58 | #define LUA_USE_ULONGJMP | 72 | #define LUA_USE_ULONGJMP |
73 | #define LUA_USE_GMTIME_R | ||
59 | #endif | 74 | #endif |
60 | 75 | ||
61 | 76 | ||
62 | /* | ||
63 | @@ LUA_PATH and LUA_CPATH are the names of the environment variables that | ||
64 | @* Lua check to set its paths. | ||
65 | @@ LUA_INIT is the name of the environment variable that Lua | ||
66 | @* checks for initialization code. | ||
67 | ** CHANGE them if you want different names. | ||
68 | */ | ||
69 | #define LUA_PATH "LUA_PATH" | ||
70 | #define LUA_CPATH "LUA_CPATH" | ||
71 | #define LUA_INIT "LUA_INIT" | ||
72 | |||
73 | 77 | ||
74 | /* | 78 | /* |
75 | @@ LUA_PATH_DEFAULT is the default path that Lua uses to look for | 79 | @@ LUA_PATH_DEFAULT is the default path that Lua uses to look for |
@@ -80,7 +84,7 @@ | |||
80 | ** hierarchy or if you want to install your libraries in | 84 | ** hierarchy or if you want to install your libraries in |
81 | ** non-conventional directories. | 85 | ** non-conventional directories. |
82 | */ | 86 | */ |
83 | #if defined(_WIN32) | 87 | #if defined(_WIN32) /* { */ |
84 | /* | 88 | /* |
85 | ** In Windows, any exclamation mark ('!') in the path is replaced by the | 89 | ** In Windows, any exclamation mark ('!') in the path is replaced by the |
86 | ** path of the directory of the executable file of the current process. | 90 | ** path of the directory of the executable file of the current process. |
@@ -88,21 +92,23 @@ | |||
88 | #define LUA_LDIR "!\\lua\\" | 92 | #define LUA_LDIR "!\\lua\\" |
89 | #define LUA_CDIR "!\\" | 93 | #define LUA_CDIR "!\\" |
90 | #define LUA_PATH_DEFAULT \ | 94 | #define LUA_PATH_DEFAULT \ |
91 | ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ | 95 | LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ |
92 | LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" | 96 | LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" |
93 | #define LUA_CPATH_DEFAULT \ | 97 | #define LUA_CPATH_DEFAULT \ |
94 | ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" | 98 | LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" |
95 | 99 | ||
96 | #else | 100 | #else /* }{ */ |
101 | |||
102 | #define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" | ||
97 | #define LUA_ROOT "/usr/local/" | 103 | #define LUA_ROOT "/usr/local/" |
98 | #define LUA_LDIR LUA_ROOT "share/lua/5.1/" | 104 | #define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR |
99 | #define LUA_CDIR LUA_ROOT "lib/lua/5.1/" | 105 | #define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR |
100 | #define LUA_PATH_DEFAULT \ | 106 | #define LUA_PATH_DEFAULT \ |
101 | "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ | 107 | LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ |
102 | LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" | 108 | LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" |
103 | #define LUA_CPATH_DEFAULT \ | 109 | #define LUA_CPATH_DEFAULT \ |
104 | "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" | 110 | LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" |
105 | #endif | 111 | #endif /* } */ |
106 | 112 | ||
107 | 113 | ||
108 | /* | 114 | /* |
@@ -118,79 +124,67 @@ | |||
118 | 124 | ||
119 | 125 | ||
120 | /* | 126 | /* |
121 | @@ LUA_PATHSEP is the character that separates templates in a path. | 127 | @@ LUA_ENV is the name of the variable that holds the current |
122 | @@ LUA_PATH_MARK is the string that marks the substitution points in a | 128 | @@ environment, used to access global names. |
123 | @* template. | 129 | ** CHANGE it if you do not like this name. |
124 | @@ LUA_EXECDIR in a Windows path is replaced by the executable's | ||
125 | @* directory. | ||
126 | @@ LUA_IGMARK is a mark to ignore all before it when bulding the | ||
127 | @* luaopen_ function name. | ||
128 | ** CHANGE them if for some reason your system cannot use those | ||
129 | ** characters. (E.g., if one of those characters is a common character | ||
130 | ** in file/directory names.) Probably you do not need to change them. | ||
131 | */ | ||
132 | #define LUA_PATHSEP ";" | ||
133 | #define LUA_PATH_MARK "?" | ||
134 | #define LUA_EXECDIR "!" | ||
135 | #define LUA_IGMARK "-" | ||
136 | |||
137 | |||
138 | /* | ||
139 | @@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. | ||
140 | ** CHANGE that if ptrdiff_t is not adequate on your machine. (On most | ||
141 | ** machines, ptrdiff_t gives a good choice between int or long.) | ||
142 | */ | 130 | */ |
143 | #define LUA_INTEGER ptrdiff_t | 131 | #define LUA_ENV "_ENV" |
144 | 132 | ||
145 | 133 | ||
146 | /* | 134 | /* |
147 | @@ LUA_API is a mark for all core API functions. | 135 | @@ LUA_API is a mark for all core API functions. |
148 | @@ LUALIB_API is a mark for all standard library functions. | 136 | @@ LUALIB_API is a mark for all auxiliary library functions. |
137 | @@ LUAMOD_API is a mark for all standard library opening functions. | ||
149 | ** CHANGE them if you need to define those functions in some special way. | 138 | ** CHANGE them if you need to define those functions in some special way. |
150 | ** For instance, if you want to create one Windows DLL with the core and | 139 | ** For instance, if you want to create one Windows DLL with the core and |
151 | ** the libraries, you may want to use the following definition (define | 140 | ** the libraries, you may want to use the following definition (define |
152 | ** LUA_BUILD_AS_DLL to get it). | 141 | ** LUA_BUILD_AS_DLL to get it). |
153 | */ | 142 | */ |
154 | #if defined(LUA_BUILD_AS_DLL) | 143 | #if defined(LUA_BUILD_AS_DLL) /* { */ |
155 | 144 | ||
156 | #if defined(LUA_CORE) || defined(LUA_LIB) | 145 | #if defined(LUA_CORE) || defined(LUA_LIB) /* { */ |
157 | #define LUA_API __declspec(dllexport) | 146 | #define LUA_API __declspec(dllexport) |
158 | #else | 147 | #else /* }{ */ |
159 | #define LUA_API __declspec(dllimport) | 148 | #define LUA_API __declspec(dllimport) |
160 | #endif | 149 | #endif /* } */ |
161 | 150 | ||
162 | #else | 151 | #else /* }{ */ |
163 | 152 | ||
164 | #define LUA_API extern | 153 | #define LUA_API extern |
165 | 154 | ||
166 | #endif | 155 | #endif /* } */ |
156 | |||
167 | 157 | ||
168 | /* more often than not the libs go together with the core */ | 158 | /* more often than not the libs go together with the core */ |
169 | #define LUALIB_API LUA_API | 159 | #define LUALIB_API LUA_API |
160 | #define LUAMOD_API LUALIB_API | ||
170 | 161 | ||
171 | 162 | ||
172 | /* | 163 | /* |
173 | @@ LUAI_FUNC is a mark for all extern functions that are not to be | 164 | @@ LUAI_FUNC is a mark for all extern functions that are not to be |
174 | @* exported to outside modules. | 165 | @* exported to outside modules. |
175 | @@ LUAI_DATA is a mark for all extern (const) variables that are not to | 166 | @@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables |
176 | @* be exported to outside modules. | 167 | @* that are not to be exported to outside modules (LUAI_DDEF for |
168 | @* definitions and LUAI_DDEC for declarations). | ||
177 | ** CHANGE them if you need to mark them in some special way. Elf/gcc | 169 | ** CHANGE them if you need to mark them in some special way. Elf/gcc |
178 | ** (versions 3.2 and later) mark them as "hidden" to optimize access | 170 | ** (versions 3.2 and later) mark them as "hidden" to optimize access |
179 | ** when Lua is compiled as a shared library. | 171 | ** when Lua is compiled as a shared library. Not all elf targets support |
180 | */ | 172 | ** this attribute. Unfortunately, gcc does not offer a way to check |
181 | #if defined(luaall_c) | 173 | ** whether the target offers that support, and those without support |
182 | #define LUAI_FUNC static | 174 | ** give a warning about it. To avoid these warnings, change to the |
183 | #define LUAI_DATA /* empty */ | 175 | ** default definition. |
184 | 176 | */ | |
185 | #elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ | 177 | #if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ |
186 | defined(__ELF__) | 178 | defined(__ELF__) /* { */ |
187 | #define LUAI_FUNC __attribute__((visibility("hidden"))) extern | 179 | #define LUAI_FUNC __attribute__((visibility("hidden"))) extern |
188 | #define LUAI_DATA LUAI_FUNC | 180 | #define LUAI_DDEC LUAI_FUNC |
181 | #define LUAI_DDEF /* empty */ | ||
189 | 182 | ||
190 | #else | 183 | #else /* }{ */ |
191 | #define LUAI_FUNC extern | 184 | #define LUAI_FUNC extern |
192 | #define LUAI_DATA extern | 185 | #define LUAI_DDEC extern |
193 | #endif | 186 | #define LUAI_DDEF /* empty */ |
187 | #endif /* } */ | ||
194 | 188 | ||
195 | 189 | ||
196 | 190 | ||
@@ -211,175 +205,108 @@ | |||
211 | 205 | ||
212 | 206 | ||
213 | /* | 207 | /* |
214 | ** {================================================================== | 208 | @@ luai_writestring/luai_writeline define how 'print' prints its results. |
215 | ** Stand-alone configuration | 209 | ** They are only used in libraries and the stand-alone program. (The #if |
216 | ** =================================================================== | 210 | ** avoids including 'stdio.h' everywhere.) |
217 | */ | 211 | */ |
218 | 212 | #if defined(LUA_LIB) || defined(lua_c) | |
219 | #if defined(lua_c) || defined(luaall_c) | 213 | #define luai_writestring(s,l) DEBUGF("%s", (s)) |
214 | #define luai_writeline() luai_writestring("\n", 1) | ||
215 | #endif | ||
220 | 216 | ||
221 | /* | 217 | /* |
222 | @@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that | 218 | @@ luai_writestringerror defines how to print error messages. |
223 | @* is, whether we're running lua interactively). | 219 | ** (A format string with one argument is enough for Lua...) |
224 | ** CHANGE it if you have a better definition for non-POSIX/non-Windows | ||
225 | ** systems. | ||
226 | */ | 220 | */ |
227 | #if defined(LUA_USE_ISATTY) | 221 | #define luai_writestringerror(s,p) \ |
228 | #include <unistd.h> | 222 | (fprintf(stderr, (s), (p)), fflush(stderr)) |
229 | #define lua_stdin_is_tty() isatty(0) | ||
230 | #elif defined(LUA_WIN) | ||
231 | #include <io.h> | ||
232 | #include <stdio.h> | ||
233 | #define lua_stdin_is_tty() _isatty(_fileno(stdin)) | ||
234 | #else | ||
235 | #define lua_stdin_is_tty() 1 /* assume stdin is a tty */ | ||
236 | #endif | ||
237 | 223 | ||
238 | 224 | ||
239 | /* | 225 | /* |
240 | @@ LUA_PROMPT is the default prompt used by stand-alone Lua. | 226 | @@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is, |
241 | @@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. | 227 | ** strings that are internalized. (Cannot be smaller than reserved words |
242 | ** CHANGE them if you want different prompts. (You can also change the | 228 | ** or tags for metamethods, as these strings must be internalized; |
243 | ** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) | 229 | ** #("function") = 8, #("__newindex") = 10.) |
244 | */ | 230 | */ |
245 | #define LUA_PROMPT "> " | 231 | #define LUAI_MAXSHORTLEN 40 |
246 | #define LUA_PROMPT2 ">> " | 232 | |
247 | 233 | ||
248 | 234 | ||
249 | /* | 235 | /* |
250 | @@ LUA_PROGNAME is the default name for the stand-alone Lua program. | 236 | ** {================================================================== |
251 | ** CHANGE it if your stand-alone interpreter has a different name and | 237 | ** Compatibility with previous versions |
252 | ** your system is not able to detect that name automatically. | 238 | ** =================================================================== |
253 | */ | 239 | */ |
254 | #define LUA_PROGNAME "lua" | ||
255 | |||
256 | 240 | ||
257 | /* | 241 | /* |
258 | @@ LUA_MAXINPUT is the maximum length for an input line in the | 242 | @@ LUA_COMPAT_ALL controls all compatibility options. |
259 | @* stand-alone interpreter. | 243 | ** You can define it to get all options, or change specific options |
260 | ** CHANGE it if you need longer lines. | 244 | ** to fit your specific needs. |
261 | */ | 245 | */ |
262 | #define LUA_MAXINPUT 512 | 246 | #if defined(LUA_COMPAT_ALL) /* { */ |
263 | |||
264 | 247 | ||
265 | /* | 248 | /* |
266 | @@ lua_readline defines how to show a prompt and then read a line from | 249 | @@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. |
267 | @* the standard input. | 250 | ** You can replace it with 'table.unpack'. |
268 | @@ lua_saveline defines how to "save" a read line in a "history". | ||
269 | @@ lua_freeline defines how to free a line read by lua_readline. | ||
270 | ** CHANGE them if you want to improve this functionality (e.g., by using | ||
271 | ** GNU readline and history facilities). | ||
272 | */ | 251 | */ |
273 | #if defined(LUA_USE_READLINE) | 252 | #define LUA_COMPAT_UNPACK |
274 | #include <stdio.h> | ||
275 | #include <readline/readline.h> | ||
276 | #include <readline/history.h> | ||
277 | #define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) | ||
278 | #define lua_saveline(L,idx) \ | ||
279 | if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ | ||
280 | add_history(lua_tostring(L, idx)); /* add it to history */ | ||
281 | #define lua_freeline(L,b) ((void)L, free(b)) | ||
282 | #else | ||
283 | #define lua_readline(L,b,p) \ | ||
284 | ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ | ||
285 | fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ | ||
286 | #define lua_saveline(L,idx) { (void)L; (void)idx; } | ||
287 | #define lua_freeline(L,b) { (void)L; (void)b; } | ||
288 | #endif | ||
289 | |||
290 | #endif | ||
291 | |||
292 | /* }================================================================== */ | ||
293 | |||
294 | 253 | ||
295 | /* | 254 | /* |
296 | @@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles | 255 | @@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. |
297 | @* as a percentage. | 256 | ** You can replace it with 'package.searchers'. |
298 | ** CHANGE it if you want the GC to run faster or slower (higher values | ||
299 | ** mean larger pauses which mean slower collection.) You can also change | ||
300 | ** this value dynamically. | ||
301 | */ | 257 | */ |
302 | #define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ | 258 | #define LUA_COMPAT_LOADERS |
303 | |||
304 | 259 | ||
305 | /* | 260 | /* |
306 | @@ LUAI_GCMUL defines the default speed of garbage collection relative to | 261 | @@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. |
307 | @* memory allocation as a percentage. | 262 | ** You can call your C function directly (with light C functions). |
308 | ** CHANGE it if you want to change the granularity of the garbage | ||
309 | ** collection. (Higher values mean coarser collections. 0 represents | ||
310 | ** infinity, where each step performs a full collection.) You can also | ||
311 | ** change this value dynamically. | ||
312 | */ | 263 | */ |
313 | #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ | 264 | #define lua_cpcall(L,f,u) \ |
314 | 265 | (lua_pushcfunction(L, (f)), \ | |
266 | lua_pushlightuserdata(L,(u)), \ | ||
267 | lua_pcall(L,1,0,0)) | ||
315 | 268 | ||
316 | 269 | ||
317 | /* | 270 | /* |
318 | @@ LUA_COMPAT_GETN controls compatibility with old getn behavior. | 271 | @@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. |
319 | ** CHANGE it (define it) if you want exact compatibility with the | 272 | ** You can rewrite 'log10(x)' as 'log(x, 10)'. |
320 | ** behavior of setn/getn in Lua 5.0. | ||
321 | */ | 273 | */ |
322 | #undef LUA_COMPAT_GETN | 274 | #define LUA_COMPAT_LOG10 |
323 | 275 | ||
324 | /* | 276 | /* |
325 | @@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. | 277 | @@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base |
326 | ** CHANGE it to undefined as soon as you do not need a global 'loadlib' | 278 | ** library. You can rewrite 'loadstring(s)' as 'load(s)'. |
327 | ** function (the function is still available as 'package.loadlib'). | ||
328 | */ | 279 | */ |
329 | #undef LUA_COMPAT_LOADLIB | 280 | #define LUA_COMPAT_LOADSTRING |
330 | 281 | ||
331 | /* | 282 | /* |
332 | @@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. | 283 | @@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. |
333 | ** CHANGE it to undefined as soon as your programs use only '...' to | ||
334 | ** access vararg parameters (instead of the old 'arg' table). | ||
335 | */ | 284 | */ |
336 | #undef LUA_COMPAT_VARARG | 285 | #define LUA_COMPAT_MAXN |
337 | 286 | ||
338 | /* | 287 | /* |
339 | @@ LUA_COMPAT_MOD controls compatibility with old math.mod function. | 288 | @@ The following macros supply trivial compatibility for some |
340 | ** CHANGE it to undefined as soon as your programs use 'math.fmod' or | 289 | ** changes in the API. The macros themselves document how to |
341 | ** the new '%' operator instead of 'math.mod'. | 290 | ** change your code to avoid using them. |
342 | */ | 291 | */ |
343 | #undef LUA_COMPAT_MOD | 292 | #define lua_strlen(L,i) lua_rawlen(L, (i)) |
344 | 293 | ||
345 | /* | 294 | #define lua_objlen(L,i) lua_rawlen(L, (i)) |
346 | @@ LUA_COMPAT_LSTR controls compatibility with old long string nesting | ||
347 | @* facility. | ||
348 | ** CHANGE it to 2 if you want the old behaviour, or undefine it to turn | ||
349 | ** off the advisory error when nesting [[...]]. | ||
350 | */ | ||
351 | #undef LUA_COMPAT_LSTR | ||
352 | 295 | ||
353 | /* | 296 | #define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) |
354 | @@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. | 297 | #define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) |
355 | ** CHANGE it to undefined as soon as you rename 'string.gfind' to | ||
356 | ** 'string.gmatch'. | ||
357 | */ | ||
358 | #undef LUA_COMPAT_GFIND | ||
359 | 298 | ||
360 | /* | 299 | /* |
361 | @@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' | 300 | @@ LUA_COMPAT_MODULE controls compatibility with previous |
362 | @* behavior. | 301 | ** module functions 'module' (Lua) and 'luaL_register' (C). |
363 | ** CHANGE it to undefined as soon as you replace to 'luaL_registry' | ||
364 | ** your uses of 'luaL_openlib' | ||
365 | */ | 302 | */ |
366 | #undef LUA_COMPAT_OPENLIB | 303 | #define LUA_COMPAT_MODULE |
367 | 304 | ||
305 | #endif /* } */ | ||
306 | #define LUA_COMPAT_MODULE | ||
368 | 307 | ||
308 | /* }================================================================== */ | ||
369 | 309 | ||
370 | /* | ||
371 | @@ luai_apicheck is the assert macro used by the Lua-C API. | ||
372 | ** CHANGE luai_apicheck if you want Lua to perform some checks in the | ||
373 | ** parameters it gets from API calls. This may slow down the interpreter | ||
374 | ** a bit, but may be quite useful when debugging C code that interfaces | ||
375 | ** with Lua. A useful redefinition is to use assert.h. | ||
376 | */ | ||
377 | #if defined(LUA_USE_APICHECK) | ||
378 | #include <assert.h> | ||
379 | #define luai_apicheck(L,o) { (void)L; assert(o); } | ||
380 | #else | ||
381 | #define luai_apicheck(L,o) { (void)L; } | ||
382 | #endif | ||
383 | 310 | ||
384 | 311 | ||
385 | /* | 312 | /* |
@@ -388,108 +315,65 @@ | |||
388 | ** your machine. Probably you do not need to change this. | 315 | ** your machine. Probably you do not need to change this. |
389 | */ | 316 | */ |
390 | /* avoid overflows in comparison */ | 317 | /* avoid overflows in comparison */ |
391 | #if INT_MAX-20 < 32760 | 318 | #if INT_MAX-20 < 32760 /* { */ |
392 | #define LUAI_BITSINT 16 | 319 | #define LUAI_BITSINT 16 |
393 | #elif INT_MAX > 2147483640L | 320 | #elif INT_MAX > 2147483640L /* }{ */ |
394 | /* int has at least 32 bits */ | 321 | /* int has at least 32 bits */ |
395 | #define LUAI_BITSINT 32 | 322 | #define LUAI_BITSINT 32 |
396 | #else | 323 | #else /* }{ */ |
397 | #error "you must define LUA_BITSINT with number of bits in an integer" | 324 | #error "you must define LUA_BITSINT with number of bits in an integer" |
398 | #endif | 325 | #endif /* } */ |
399 | 326 | ||
400 | 327 | ||
401 | /* | 328 | /* |
402 | @@ LUAI_UINT32 is an unsigned integer with at least 32 bits. | 329 | @@ LUA_INT32 is an signed integer with exactly 32 bits. |
403 | @@ LUAI_INT32 is an signed integer with at least 32 bits. | ||
404 | @@ LUAI_UMEM is an unsigned integer big enough to count the total | 330 | @@ LUAI_UMEM is an unsigned integer big enough to count the total |
405 | @* memory used by Lua. | 331 | @* memory used by Lua. |
406 | @@ LUAI_MEM is a signed integer big enough to count the total memory | 332 | @@ LUAI_MEM is a signed integer big enough to count the total memory |
407 | @* used by Lua. | 333 | @* used by Lua. |
408 | ** CHANGE here if for some weird reason the default definitions are not | 334 | ** CHANGE here if for some weird reason the default definitions are not |
409 | ** good enough for your machine. (The definitions in the 'else' | 335 | ** good enough for your machine. Probably you do not need to change |
410 | ** part always works, but may waste space on machines with 64-bit | 336 | ** this. |
411 | ** longs.) Probably you do not need to change this. | ||
412 | */ | 337 | */ |
413 | #if LUAI_BITSINT >= 32 | 338 | #if LUAI_BITSINT >= 32 /* { */ |
414 | #define LUAI_UINT32 unsigned int | 339 | #define LUA_INT32 int |
415 | #define LUAI_INT32 int | ||
416 | #define LUAI_MAXINT32 INT_MAX | ||
417 | #define LUAI_UMEM size_t | 340 | #define LUAI_UMEM size_t |
418 | #define LUAI_MEM ptrdiff_t | 341 | #define LUAI_MEM ptrdiff_t |
419 | #else | 342 | #else /* }{ */ |
420 | /* 16-bit ints */ | 343 | /* 16-bit ints */ |
421 | #define LUAI_UINT32 unsigned long | 344 | #define LUA_INT32 long |
422 | #define LUAI_INT32 long | ||
423 | #define LUAI_MAXINT32 LONG_MAX | ||
424 | #define LUAI_UMEM unsigned long | 345 | #define LUAI_UMEM unsigned long |
425 | #define LUAI_MEM long | 346 | #define LUAI_MEM long |
426 | #endif | 347 | #endif /* } */ |
427 | |||
428 | |||
429 | /* | ||
430 | @@ LUAI_MAXCALLS limits the number of nested calls. | ||
431 | ** CHANGE it if you need really deep recursive calls. This limit is | ||
432 | ** arbitrary; its only purpose is to stop infinite recursion before | ||
433 | ** exhausting memory. | ||
434 | */ | ||
435 | #define LUAI_MAXCALLS 20000 | ||
436 | |||
437 | |||
438 | /* | ||
439 | @@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function | ||
440 | @* can use. | ||
441 | ** CHANGE it if you need lots of (Lua) stack space for your C | ||
442 | ** functions. This limit is arbitrary; its only purpose is to stop C | ||
443 | ** functions to consume unlimited stack space. (must be smaller than | ||
444 | ** -LUA_REGISTRYINDEX) | ||
445 | */ | ||
446 | #define LUAI_MAXCSTACK 8000 | ||
447 | |||
448 | |||
449 | |||
450 | /* | ||
451 | ** {================================================================== | ||
452 | ** CHANGE (to smaller values) the following definitions if your system | ||
453 | ** has a small C stack. (Or you may want to change them to larger | ||
454 | ** values if your system has a large C stack and these limits are | ||
455 | ** too rigid for you.) Some of these constants control the size of | ||
456 | ** stack-allocated arrays used by the compiler or the interpreter, while | ||
457 | ** others limit the maximum number of recursive calls that the compiler | ||
458 | ** or the interpreter can perform. Values too large may cause a C stack | ||
459 | ** overflow for some forms of deep constructs. | ||
460 | ** =================================================================== | ||
461 | */ | ||
462 | 348 | ||
463 | 349 | ||
464 | /* | 350 | /* |
465 | @@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and | 351 | @@ LUAI_MAXSTACK limits the size of the Lua stack. |
466 | @* syntactical nested non-terminals in a program. | 352 | ** CHANGE it if you need a different limit. This limit is arbitrary; |
353 | ** its only purpose is to stop Lua to consume unlimited stack | ||
354 | ** space (and to reserve some numbers for pseudo-indices). | ||
467 | */ | 355 | */ |
468 | #define LUAI_MAXCCALLS 200 | 356 | #if LUAI_BITSINT >= 32 |
357 | #define LUAI_MAXSTACK 1000000 | ||
358 | #else | ||
359 | #define LUAI_MAXSTACK 15000 | ||
360 | #endif | ||
469 | 361 | ||
362 | /* reserve some space for error handling */ | ||
363 | #define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) | ||
470 | 364 | ||
471 | /* | ||
472 | @@ LUAI_MAXVARS is the maximum number of local variables per function | ||
473 | @* (must be smaller than 250). | ||
474 | */ | ||
475 | #define LUAI_MAXVARS 200 | ||
476 | 365 | ||
477 | 366 | ||
478 | /* | ||
479 | @@ LUAI_MAXUPVALUES is the maximum number of upvalues per function | ||
480 | @* (must be smaller than 250). | ||
481 | */ | ||
482 | #define LUAI_MAXUPVALUES 60 | ||
483 | |||
484 | 367 | ||
485 | /* | 368 | /* |
486 | @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. | 369 | @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. |
370 | ** CHANGE it if it uses too much C-stack space. | ||
487 | */ | 371 | */ |
488 | #define LUAL_BUFFERSIZE 1024 | 372 | #define LUAL_BUFFERSIZE 1024 |
489 | 373 | ||
490 | /* }================================================================== */ | 374 | #ifndef SIMULATOR |
491 | 375 | typedef void FILE; | |
492 | 376 | #endif | |
493 | 377 | ||
494 | 378 | ||
495 | /* | 379 | /* |
@@ -516,237 +400,138 @@ | |||
516 | @@ LUA_NUMBER_FMT is the format for writing numbers. | 400 | @@ LUA_NUMBER_FMT is the format for writing numbers. |
517 | @@ lua_number2str converts a number to a string. | 401 | @@ lua_number2str converts a number to a string. |
518 | @@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. | 402 | @@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. |
519 | @@ lua_str2number converts a string to a number. | ||
520 | */ | 403 | */ |
521 | #define LUA_NUMBER_SCAN "%ld" | 404 | #define LUA_NUMBER_SCAN "%ld" |
522 | #define LUA_NUMBER_FMT "%ld" | 405 | #define LUA_NUMBER_FMT "%ld" |
523 | #define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ | 406 | #define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ |
524 | #define lua_number2str(s,n) snprintf((s), 32, LUA_NUMBER_FMT, (n)) | 407 | #define lua_number2str(s,n) snprintf((s), 32, LUA_NUMBER_FMT, (n)) |
525 | #define lua_str2number(s,p) strtol((s), (p), 10) | ||
526 | 408 | ||
527 | 409 | ||
528 | /* | 410 | /* |
529 | @@ The luai_num* macros define the primitive operations over numbers. | 411 | @@ l_mathop allows the addition of an 'l' or 'f' to all math operations |
530 | */ | 412 | */ |
531 | #if defined(LUA_CORE) | 413 | #define l_mathop(x) (x) |
532 | extern long rb_pow(long, long); | ||
533 | #define luai_numadd(a,b) ((a)+(b)) | ||
534 | #define luai_numsub(a,b) ((a)-(b)) | ||
535 | #define luai_nummul(a,b) ((a)*(b)) | ||
536 | #define luai_numdiv(a,b) ((a)/(b)) | ||
537 | #define luai_nummod(a,b) ((a)%(b)) | ||
538 | #define luai_numpow(a,b) (rb_pow(a,b)) | ||
539 | #define luai_numunm(a) (-(a)) | ||
540 | #define luai_numeq(a,b) ((a)==(b)) | ||
541 | #define luai_numlt(a,b) ((a)<(b)) | ||
542 | #define luai_numle(a,b) ((a)<=(b)) | ||
543 | #define luai_numisnan(a) (!luai_numeq((a), (a))) | ||
544 | #endif | ||
545 | 414 | ||
546 | 415 | ||
547 | /* | 416 | /* |
548 | @@ lua_number2int is a macro to convert lua_Number to int. | 417 | @@ lua_str2number converts a decimal numeric string to a number. |
549 | @@ lua_number2integer is a macro to convert lua_Number to lua_Integer. | 418 | @@ lua_strx2number converts an hexadecimal numeric string to a number. |
550 | ** CHANGE them if you know a faster way to convert a lua_Number to | 419 | ** In C99, 'strtod' does both conversions. C89, however, has no function |
551 | ** int (with any rounding method and without throwing errors) in your | 420 | ** to convert floating hexadecimal strings to numbers. For these |
552 | ** system. In Pentium machines, a naive typecast from double to int | 421 | ** systems, you can leave 'lua_strx2number' undefined and Lua will |
553 | ** in C is extremely slow, so any alternative is worth trying. | 422 | ** provide its own implementation. |
554 | */ | 423 | */ |
424 | #define lua_str2number(s,p) strtol((s), (p), 10) | ||
555 | 425 | ||
556 | /* On a Pentium, resort to a trick */ | 426 | #define lua_strx2number(s,p) strtoul((s), (p), 16) |
557 | #if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ | ||
558 | (defined(__i386) || defined (_M_IX86) || defined(__i386__)) | ||
559 | |||
560 | /* On a Microsoft compiler, use assembler */ | ||
561 | #if defined(_MSC_VER) | ||
562 | |||
563 | #define lua_number2int(i,d) __asm fld d __asm fistp i | ||
564 | #define lua_number2integer(i,n) lua_number2int(i, n) | ||
565 | |||
566 | /* the next trick should work on any Pentium, but sometimes clashes | ||
567 | with a DirectX idiosyncrasy */ | ||
568 | #else | ||
569 | 427 | ||
570 | union luai_Cast { double l_d; long l_l; }; | ||
571 | #define lua_number2int(i,d) \ | ||
572 | { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } | ||
573 | #define lua_number2integer(i,n) lua_number2int(i, n) | ||
574 | |||
575 | #endif | ||
576 | 428 | ||
429 | /* | ||
430 | @@ The luai_num* macros define the primitive operations over numbers. | ||
431 | */ | ||
577 | 432 | ||
578 | /* this option always works, but may be slow */ | ||
579 | #else | ||
580 | #define lua_number2int(i,d) ((i)=(int)(d)) | ||
581 | #define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) | ||
582 | 433 | ||
434 | /* these are quite standard operations */ | ||
435 | #if defined(LUA_CORE) | ||
436 | extern long rb_pow(long, long); | ||
437 | #define luai_numadd(L,a,b) ((a)+(b)) | ||
438 | #define luai_numsub(L,a,b) ((a)-(b)) | ||
439 | #define luai_nummul(L,a,b) ((a)*(b)) | ||
440 | #define luai_numdiv(L,a,b) ((a)/(b)) | ||
441 | #define luai_nummod(L,a,b) ((a)%(b)) | ||
442 | #define luai_numpow(L,a,b) (rb_pow(a,b)) | ||
443 | #define luai_numunm(L,a) (-(a)) | ||
444 | #define luai_numeq(a,b) ((a)==(b)) | ||
445 | #define luai_numlt(L,a,b) ((a)<(b)) | ||
446 | #define luai_numle(L,a,b) ((a)<=(b)) | ||
447 | #define luai_numisnan(L,a) (!luai_numeq((a), (a))) | ||
583 | #endif | 448 | #endif |
584 | 449 | ||
585 | /* }================================================================== */ | ||
586 | 450 | ||
587 | 451 | ||
588 | /* | 452 | /* |
589 | @@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. | 453 | @@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. |
590 | ** CHANGE it if your system requires alignments larger than double. (For | 454 | ** CHANGE that if ptrdiff_t is not adequate on your machine. (On most |
591 | ** instance, if your system supports long doubles and they must be | 455 | ** machines, ptrdiff_t gives a good choice between int or long.) |
592 | ** aligned in 16-byte boundaries, then you should add long double in the | ||
593 | ** union.) Probably you do not need to change this. | ||
594 | */ | 456 | */ |
595 | #define LUAI_USER_ALIGNMENT_T union { void *s; long l; } | 457 | #define LUA_INTEGER ptrdiff_t |
596 | |||
597 | 458 | ||
598 | /* | 459 | /* |
599 | @@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. | 460 | @@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned. |
600 | ** CHANGE them if you prefer to use longjmp/setjmp even with C++ | 461 | ** It must have at least 32 bits. |
601 | ** or if want/don't to use _longjmp/_setjmp instead of regular | ||
602 | ** longjmp/setjmp. By default, Lua handles errors with exceptions when | ||
603 | ** compiling as C++ code, with _longjmp/_setjmp when asked to use them, | ||
604 | ** and with longjmp/setjmp otherwise. | ||
605 | */ | 462 | */ |
606 | #if defined(__cplusplus) | 463 | #define LUA_UNSIGNED unsigned LUA_INT32 |
607 | /* C++ exceptions */ | ||
608 | #define LUAI_THROW(L,c) throw(c) | ||
609 | #define LUAI_TRY(L,c,a) try { a } catch(...) \ | ||
610 | { if ((c)->status == 0) (c)->status = -1; } | ||
611 | #define luai_jmpbuf int /* dummy variable */ | ||
612 | |||
613 | #elif defined(LUA_USE_ULONGJMP) | ||
614 | /* in Unix, try _longjmp/_setjmp (more efficient) */ | ||
615 | #define LUAI_THROW(L,c) _longjmp((c)->b, 1) | ||
616 | #define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } | ||
617 | #define luai_jmpbuf jmp_buf | ||
618 | |||
619 | #else | ||
620 | /* default handling with long jumps */ | ||
621 | #define LUAI_THROW(L,c) longjmp((c)->b, 1) | ||
622 | #define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } | ||
623 | #define luai_jmpbuf jmp_buf | ||
624 | 464 | ||
625 | #endif | ||
626 | 465 | ||
627 | 466 | ||
628 | /* | 467 | /* |
629 | @@ LUA_MAXCAPTURES is the maximum number of captures that a pattern | 468 | ** Some tricks with doubles |
630 | @* can do during pattern-matching. | ||
631 | ** CHANGE it if you need more captures. This limit is arbitrary. | ||
632 | */ | 469 | */ |
633 | #define LUA_MAXCAPTURES 32 | ||
634 | |||
635 | 470 | ||
471 | #if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ | ||
636 | /* | 472 | /* |
637 | @@ lua_tmpnam is the function that the OS library uses to create a | 473 | ** The next definitions activate some tricks to speed up the |
638 | @* temporary name. | 474 | ** conversion from doubles to integer types, mainly to LUA_UNSIGNED. |
639 | @@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. | 475 | ** |
640 | ** CHANGE them if you have an alternative to tmpnam (which is considered | 476 | @@ LUA_MSASMTRICK uses Microsoft assembler to avoid clashes with a |
641 | ** insecure) or if you want the original tmpnam anyway. By default, Lua | 477 | ** DirectX idiosyncrasy. |
642 | ** uses tmpnam except when POSIX is available, where it uses mkstemp. | 478 | ** |
479 | @@ LUA_IEEE754TRICK uses a trick that should work on any machine | ||
480 | ** using IEEE754 with a 32-bit integer type. | ||
481 | ** | ||
482 | @@ LUA_IEEELL extends the trick to LUA_INTEGER; should only be | ||
483 | ** defined when LUA_INTEGER is a 32-bit integer. | ||
484 | ** | ||
485 | @@ LUA_IEEEENDIAN is the endianness of doubles in your machine | ||
486 | ** (0 for little endian, 1 for big endian); if not defined, Lua will | ||
487 | ** check it dynamically for LUA_IEEE754TRICK (but not for LUA_NANTRICK). | ||
488 | ** | ||
489 | @@ LUA_NANTRICK controls the use of a trick to pack all types into | ||
490 | ** a single double value, using NaN values to represent non-number | ||
491 | ** values. The trick only works on 32-bit machines (ints and pointers | ||
492 | ** are 32-bit values) with numbers represented as IEEE 754-2008 doubles | ||
493 | ** with conventional endianess (12345678 or 87654321), in CPUs that do | ||
494 | ** not produce signaling NaN values (all NaNs are quiet). | ||
643 | */ | 495 | */ |
644 | #if defined(loslib_c) || defined(luaall_c) | ||
645 | |||
646 | #if defined(LUA_USE_MKSTEMP) | ||
647 | #include <unistd.h> | ||
648 | #define LUA_TMPNAMBUFSIZE 32 | ||
649 | #define lua_tmpnam(b,e) { \ | ||
650 | strcpy(b, "/tmp/lua_XXXXXX"); \ | ||
651 | e = mkstemp(b); \ | ||
652 | if (e != -1) close(e); \ | ||
653 | e = (e == -1); } | ||
654 | |||
655 | #else | ||
656 | #define LUA_TMPNAMBUFSIZE L_tmpnam | ||
657 | #define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } | ||
658 | #endif | ||
659 | |||
660 | #endif | ||
661 | |||
662 | |||
663 | /* | ||
664 | @@ lua_popen spawns a new process connected to the current one through | ||
665 | @* the file streams. | ||
666 | ** CHANGE it if you have a way to implement it in your system. | ||
667 | */ | ||
668 | #if defined(LUA_USE_POPEN) | ||
669 | |||
670 | #define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) | ||
671 | #define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) | ||
672 | 496 | ||
673 | #elif defined(LUA_WIN) | 497 | /* Microsoft compiler on a Pentium (32 bit) ? */ |
498 | #if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ | ||
674 | 499 | ||
675 | #define lua_popen(L,c,m) ((void)L, _popen(c,m)) | 500 | #define LUA_MSASMTRICK |
676 | #define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) | 501 | #define LUA_IEEEENDIAN 0 |
502 | #define LUA_NANTRICK | ||
677 | 503 | ||
678 | #else | ||
679 | 504 | ||
680 | #define lua_popen(L,c,m) ((void)((void)c, m), \ | 505 | /* pentium 32 bits? */ |
681 | luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) | 506 | #elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ |
682 | #define lua_pclose(L,file) ((void)((void)L, file), 0) | ||
683 | 507 | ||
684 | #endif | 508 | #define LUA_IEEE754TRICK |
509 | #define LUA_IEEELL | ||
510 | #define LUA_IEEEENDIAN 0 | ||
511 | #define LUA_NANTRICK | ||
685 | 512 | ||
686 | /* | 513 | /* pentium 64 bits? */ |
687 | @@ LUA_DL_* define which dynamic-library system Lua should use. | 514 | #elif defined(__x86_64) /* }{ */ |
688 | ** CHANGE here if Lua has problems choosing the appropriate | ||
689 | ** dynamic-library system for your platform (either Windows' DLL, Mac's | ||
690 | ** dyld, or Unix's dlopen). If your system is some kind of Unix, there | ||
691 | ** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for | ||
692 | ** it. To use dlopen you also need to adapt the src/Makefile (probably | ||
693 | ** adding -ldl to the linker options), so Lua does not select it | ||
694 | ** automatically. (When you change the makefile to add -ldl, you must | ||
695 | ** also add -DLUA_USE_DLOPEN.) | ||
696 | ** If you do not want any kind of dynamic library, undefine all these | ||
697 | ** options. | ||
698 | ** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. | ||
699 | */ | ||
700 | #if defined(LUA_USE_DLOPEN) | ||
701 | #define LUA_DL_DLOPEN | ||
702 | #endif | ||
703 | 515 | ||
704 | #if defined(LUA_WIN) | 516 | #define LUA_IEEE754TRICK |
705 | #define LUA_DL_DLL | 517 | #define LUA_IEEEENDIAN 0 |
706 | #endif | ||
707 | 518 | ||
519 | #elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ | ||
708 | 520 | ||
709 | /* | 521 | #define LUA_IEEE754TRICK |
710 | @@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State | 522 | #define LUA_IEEEENDIAN 1 |
711 | @* (the data goes just *before* the lua_State pointer). | ||
712 | ** CHANGE (define) this if you really need that. This value must be | ||
713 | ** a multiple of the maximum alignment required for your machine. | ||
714 | */ | ||
715 | #define LUAI_EXTRASPACE 0 | ||
716 | 523 | ||
524 | #else /* }{ */ | ||
717 | 525 | ||
718 | /* | 526 | /* assume IEEE754 and a 32-bit integer type */ |
719 | @@ luai_userstate* allow user-specific actions on threads. | 527 | #define LUA_IEEE754TRICK |
720 | ** CHANGE them if you defined LUAI_EXTRASPACE and need to do something | ||
721 | ** extra when a thread is created/deleted/resumed/yielded. | ||
722 | */ | ||
723 | #define luai_userstateopen(L) ((void)L) | ||
724 | #define luai_userstateclose(L) ((void)L) | ||
725 | #define luai_userstatethread(L,L1) ((void)L) | ||
726 | #define luai_userstatefree(L) ((void)L) | ||
727 | #define luai_userstateresume(L,n) ((void)L) | ||
728 | #define luai_userstateyield(L,n) ((void)L) | ||
729 | |||
730 | |||
731 | /* | ||
732 | @@ LUA_INTFRMLEN is the length modifier for integer conversions | ||
733 | @* in 'string.format'. | ||
734 | @@ LUA_INTFRM_T is the integer type correspoding to the previous length | ||
735 | @* modifier. | ||
736 | ** CHANGE them if your system supports long long or does not support long. | ||
737 | */ | ||
738 | 528 | ||
739 | #if defined(LUA_USELONGLONG) | 529 | #endif /* } */ |
740 | 530 | ||
741 | #define LUA_INTFRMLEN "ll" | 531 | #endif /* } */ |
742 | #define LUA_INTFRM_T long long | ||
743 | 532 | ||
744 | #else | 533 | /* }================================================================== */ |
745 | |||
746 | #define LUA_INTFRMLEN "l" | ||
747 | #define LUA_INTFRM_T long | ||
748 | 534 | ||
749 | #endif | ||
750 | 535 | ||
751 | 536 | ||
752 | 537 | ||
@@ -758,6 +543,7 @@ union luai_Cast { double l_d; long l_l; }; | |||
758 | */ | 543 | */ |
759 | 544 | ||
760 | #include "rockconf.h" | 545 | #include "rockconf.h" |
546 | #define LUA_USE_CTYPE 1 | ||
761 | 547 | ||
762 | #endif | 548 | #endif |
763 | 549 | ||
diff --git a/apps/plugins/lua/luadir.c b/apps/plugins/lua/luadir.c index c8c21d2c65..3c65b28bc7 100644 --- a/apps/plugins/lua/luadir.c +++ b/apps/plugins/lua/luadir.c | |||
@@ -98,7 +98,7 @@ static int dir_iter_factory (lua_State *L) { | |||
98 | lua_setmetatable (L, -2); | 98 | lua_setmetatable (L, -2); |
99 | d->dir = rb->opendir (path); | 99 | d->dir = rb->opendir (path); |
100 | if (d->dir == NULL) | 100 | if (d->dir == NULL) |
101 | luaL_error (L, "cannot open %s: %d", path, errno); | 101 | luaL_error (L, "cannot open dir %s: %d", path, errno); |
102 | 102 | ||
103 | return 2; | 103 | return 2; |
104 | } | 104 | } |
@@ -125,7 +125,7 @@ static int dir_create_meta (lua_State *L) { | |||
125 | return 1; | 125 | return 1; |
126 | } | 126 | } |
127 | 127 | ||
128 | static const struct luaL_reg fslib[] = { | 128 | static const struct luaL_Reg fslib[] = { |
129 | {"dir", dir_iter_factory}, | 129 | {"dir", dir_iter_factory}, |
130 | {"mkdir", make_dir}, | 130 | {"mkdir", make_dir}, |
131 | {"rmdir", remove_dir}, | 131 | {"rmdir", remove_dir}, |
diff --git a/apps/plugins/lua/lualib.h b/apps/plugins/lua/lualib.h index d4f69fc4af..da82005c9d 100644 --- a/apps/plugins/lua/lualib.h +++ b/apps/plugins/lua/lualib.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lualib.h,v 1.43.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Lua standard libraries | 3 | ** Lua standard libraries |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -11,43 +11,43 @@ | |||
11 | #include "lua.h" | 11 | #include "lua.h" |
12 | 12 | ||
13 | 13 | ||
14 | /* Key to file-handle type */ | ||
15 | #define LUA_FILEHANDLE "FILE*" | ||
16 | 14 | ||
15 | LUAMOD_API int (luaopen_base) (lua_State *L); | ||
17 | 16 | ||
18 | #define LUA_COLIBNAME "coroutine" | 17 | #define LUA_COLIBNAME "coroutine" |
19 | LUALIB_API int (luaopen_base) (lua_State *L); | 18 | LUAMOD_API int (luaopen_coroutine) (lua_State *L); |
20 | 19 | ||
21 | #define LUA_TABLIBNAME "table" | 20 | #define LUA_TABLIBNAME "table" |
22 | LUALIB_API int (luaopen_table) (lua_State *L); | 21 | LUAMOD_API int (luaopen_table) (lua_State *L); |
23 | 22 | ||
24 | #define LUA_IOLIBNAME "io" | 23 | #define LUA_IOLIBNAME "io" |
25 | LUALIB_API int (luaopen_io) (lua_State *L); | 24 | LUAMOD_API int (luaopen_io) (lua_State *L); |
26 | 25 | ||
27 | #define LUA_OSLIBNAME "os" | 26 | #define LUA_OSLIBNAME "os" |
28 | LUALIB_API int (luaopen_os) (lua_State *L); | 27 | LUAMOD_API int (luaopen_os) (lua_State *L); |
29 | 28 | ||
30 | #define LUA_STRLIBNAME "string" | 29 | #define LUA_STRLIBNAME "string" |
31 | LUALIB_API int (luaopen_string) (lua_State *L); | 30 | LUAMOD_API int (luaopen_string) (lua_State *L); |
31 | |||
32 | #define LUA_BITLIBNAME "bit32" | ||
33 | LUAMOD_API int (luaopen_bit32) (lua_State *L); | ||
32 | 34 | ||
33 | #define LUA_MATHLIBNAME "math" | 35 | #define LUA_MATHLIBNAME "math" |
34 | LUALIB_API int (luaopen_math) (lua_State *L); | 36 | LUAMOD_API int (luaopen_math) (lua_State *L); |
35 | 37 | ||
36 | #define LUA_DBLIBNAME "debug" | 38 | #define LUA_DBLIBNAME "debug" |
37 | LUALIB_API int (luaopen_debug) (lua_State *L); | 39 | LUAMOD_API int (luaopen_debug) (lua_State *L); |
38 | 40 | ||
39 | #define LUA_LOADLIBNAME "package" | 41 | #define LUA_LOADLIBNAME "package" |
40 | LUALIB_API int (luaopen_package) (lua_State *L); | 42 | LUAMOD_API int (luaopen_package) (lua_State *L); |
41 | 43 | ||
42 | #define LUA_BITLIBNAME "bit" | ||
43 | LUALIB_API int (luaopen_bit) (lua_State *L); | ||
44 | 44 | ||
45 | /* open all previous libraries */ | 45 | /* open all previous libraries */ |
46 | LUALIB_API void (luaL_openlibs) (lua_State *L); | 46 | LUALIB_API void (luaL_openlibs) (lua_State *L); |
47 | 47 | ||
48 | 48 | ||
49 | 49 | ||
50 | #ifndef lua_assert | 50 | #if !defined(lua_assert) |
51 | #define lua_assert(x) ((void)0) | 51 | #define lua_assert(x) ((void)0) |
52 | #endif | 52 | #endif |
53 | 53 | ||
diff --git a/apps/plugins/lua/lundump.c b/apps/plugins/lua/lundump.c index 8010a45795..0db70d20ea 100644 --- a/apps/plugins/lua/lundump.c +++ b/apps/plugins/lua/lundump.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ | 2 | ** $Id: lundump.c,v 2.22.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** load precompiled Lua chunks | 3 | ** load precompiled Lua chunks |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -27,28 +27,24 @@ typedef struct { | |||
27 | const char* name; | 27 | const char* name; |
28 | } LoadState; | 28 | } LoadState; |
29 | 29 | ||
30 | #ifdef LUAC_TRUST_BINARIES | 30 | static l_noret error(LoadState* S, const char* why) |
31 | #define IF(c,s) | ||
32 | #define error(S,s) | ||
33 | #else | ||
34 | #define IF(c,s) if (c) error(S,s) | ||
35 | |||
36 | static void error(LoadState* S, const char* why) | ||
37 | { | 31 | { |
38 | luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); | 32 | luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why); |
39 | luaD_throw(S->L,LUA_ERRSYNTAX); | 33 | luaD_throw(S->L,LUA_ERRSYNTAX); |
40 | } | 34 | } |
41 | #endif | ||
42 | 35 | ||
43 | #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) | 36 | #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) |
44 | #define LoadByte(S) (lu_byte)LoadChar(S) | 37 | #define LoadByte(S) (lu_byte)LoadChar(S) |
45 | #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) | 38 | #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) |
46 | #define LoadVector(S,b,n,size) LoadMem(S,b,n,size) | 39 | #define LoadVector(S,b,n,size) LoadMem(S,b,n,size) |
47 | 40 | ||
41 | #if !defined(luai_verifycode) | ||
42 | #define luai_verifycode(L,b,f) /* empty */ | ||
43 | #endif | ||
44 | |||
48 | static void LoadBlock(LoadState* S, void* b, size_t size) | 45 | static void LoadBlock(LoadState* S, void* b, size_t size) |
49 | { | 46 | { |
50 | size_t r=luaZ_read(S->Z,b,size); | 47 | if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated"); |
51 | IF (r!=0, "unexpected end"); | ||
52 | } | 48 | } |
53 | 49 | ||
54 | static int LoadChar(LoadState* S) | 50 | static int LoadChar(LoadState* S) |
@@ -62,7 +58,7 @@ static int LoadInt(LoadState* S) | |||
62 | { | 58 | { |
63 | int x; | 59 | int x; |
64 | LoadVar(S,x); | 60 | LoadVar(S,x); |
65 | IF (x<0, "bad integer"); | 61 | if (x<0) error(S,"corrupted"); |
66 | return x; | 62 | return x; |
67 | } | 63 | } |
68 | 64 | ||
@@ -82,7 +78,7 @@ static TString* LoadString(LoadState* S) | |||
82 | else | 78 | else |
83 | { | 79 | { |
84 | char* s=luaZ_openspace(S->L,S->b,size); | 80 | char* s=luaZ_openspace(S->L,S->b,size); |
85 | LoadBlock(S,s,size); | 81 | LoadBlock(S,s,size*sizeof(char)); |
86 | return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ | 82 | return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ |
87 | } | 83 | } |
88 | } | 84 | } |
@@ -95,7 +91,7 @@ static void LoadCode(LoadState* S, Proto* f) | |||
95 | LoadVector(S,f->code,n,sizeof(Instruction)); | 91 | LoadVector(S,f->code,n,sizeof(Instruction)); |
96 | } | 92 | } |
97 | 93 | ||
98 | static Proto* LoadFunction(LoadState* S, TString* p); | 94 | static void LoadFunction(LoadState* S, Proto* f); |
99 | 95 | ||
100 | static void LoadConstants(LoadState* S, Proto* f) | 96 | static void LoadConstants(LoadState* S, Proto* f) |
101 | { | 97 | { |
@@ -111,10 +107,10 @@ static void LoadConstants(LoadState* S, Proto* f) | |||
111 | switch (t) | 107 | switch (t) |
112 | { | 108 | { |
113 | case LUA_TNIL: | 109 | case LUA_TNIL: |
114 | setnilvalue(o); | 110 | setnilvalue(o); |
115 | break; | 111 | break; |
116 | case LUA_TBOOLEAN: | 112 | case LUA_TBOOLEAN: |
117 | setbvalue(o,LoadChar(S)!=0); | 113 | setbvalue(o,LoadChar(S)); |
118 | break; | 114 | break; |
119 | case LUA_TNUMBER: | 115 | case LUA_TNUMBER: |
120 | setnvalue(o,LoadNumber(S)); | 116 | setnvalue(o,LoadNumber(S)); |
@@ -122,21 +118,38 @@ static void LoadConstants(LoadState* S, Proto* f) | |||
122 | case LUA_TSTRING: | 118 | case LUA_TSTRING: |
123 | setsvalue2n(S->L,o,LoadString(S)); | 119 | setsvalue2n(S->L,o,LoadString(S)); |
124 | break; | 120 | break; |
125 | default: | 121 | default: lua_assert(0); |
126 | error(S,"bad constant"); | ||
127 | break; | ||
128 | } | 122 | } |
129 | } | 123 | } |
130 | n=LoadInt(S); | 124 | n=LoadInt(S); |
131 | f->p=luaM_newvector(S->L,n,Proto*); | 125 | f->p=luaM_newvector(S->L,n,Proto*); |
132 | f->sizep=n; | 126 | f->sizep=n; |
133 | for (i=0; i<n; i++) f->p[i]=NULL; | 127 | for (i=0; i<n; i++) f->p[i]=NULL; |
134 | for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source); | 128 | for (i=0; i<n; i++) |
129 | { | ||
130 | f->p[i]=luaF_newproto(S->L); | ||
131 | LoadFunction(S,f->p[i]); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | static void LoadUpvalues(LoadState* S, Proto* f) | ||
136 | { | ||
137 | int i,n; | ||
138 | n=LoadInt(S); | ||
139 | f->upvalues=luaM_newvector(S->L,n,Upvaldesc); | ||
140 | f->sizeupvalues=n; | ||
141 | for (i=0; i<n; i++) f->upvalues[i].name=NULL; | ||
142 | for (i=0; i<n; i++) | ||
143 | { | ||
144 | f->upvalues[i].instack=LoadByte(S); | ||
145 | f->upvalues[i].idx=LoadByte(S); | ||
146 | } | ||
135 | } | 147 | } |
136 | 148 | ||
137 | static void LoadDebug(LoadState* S, Proto* f) | 149 | static void LoadDebug(LoadState* S, Proto* f) |
138 | { | 150 | { |
139 | int i,n; | 151 | int i,n; |
152 | f->source=LoadString(S); | ||
140 | n=LoadInt(S); | 153 | n=LoadInt(S); |
141 | f->lineinfo=luaM_newvector(S->L,n,int); | 154 | f->lineinfo=luaM_newvector(S->L,n,int); |
142 | f->sizelineinfo=n; | 155 | f->sizelineinfo=n; |
@@ -152,49 +165,48 @@ static void LoadDebug(LoadState* S, Proto* f) | |||
152 | f->locvars[i].endpc=LoadInt(S); | 165 | f->locvars[i].endpc=LoadInt(S); |
153 | } | 166 | } |
154 | n=LoadInt(S); | 167 | n=LoadInt(S); |
155 | f->upvalues=luaM_newvector(S->L,n,TString*); | 168 | for (i=0; i<n; i++) f->upvalues[i].name=LoadString(S); |
156 | f->sizeupvalues=n; | ||
157 | for (i=0; i<n; i++) f->upvalues[i]=NULL; | ||
158 | for (i=0; i<n; i++) f->upvalues[i]=LoadString(S); | ||
159 | } | 169 | } |
160 | 170 | ||
161 | static Proto* LoadFunction(LoadState* S, TString* p) | 171 | static void LoadFunction(LoadState* S, Proto* f) |
162 | { | 172 | { |
163 | Proto* f; | ||
164 | if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); | ||
165 | f=luaF_newproto(S->L); | ||
166 | setptvalue2s(S->L,S->L->top,f); incr_top(S->L); | ||
167 | f->source=LoadString(S); if (f->source==NULL) f->source=p; | ||
168 | f->linedefined=LoadInt(S); | 173 | f->linedefined=LoadInt(S); |
169 | f->lastlinedefined=LoadInt(S); | 174 | f->lastlinedefined=LoadInt(S); |
170 | f->nups=LoadByte(S); | ||
171 | f->numparams=LoadByte(S); | 175 | f->numparams=LoadByte(S); |
172 | f->is_vararg=LoadByte(S); | 176 | f->is_vararg=LoadByte(S); |
173 | f->maxstacksize=LoadByte(S); | 177 | f->maxstacksize=LoadByte(S); |
174 | LoadCode(S,f); | 178 | LoadCode(S,f); |
175 | LoadConstants(S,f); | 179 | LoadConstants(S,f); |
180 | LoadUpvalues(S,f); | ||
176 | LoadDebug(S,f); | 181 | LoadDebug(S,f); |
177 | IF (!luaG_checkcode(f), "bad code"); | ||
178 | S->L->top--; | ||
179 | S->L->nCcalls--; | ||
180 | return f; | ||
181 | } | 182 | } |
182 | 183 | ||
184 | /* the code below must be consistent with the code in luaU_header */ | ||
185 | #define N0 LUAC_HEADERSIZE | ||
186 | #define N1 (sizeof(LUA_SIGNATURE)-sizeof(char)) | ||
187 | #define N2 N1+2 | ||
188 | #define N3 N2+6 | ||
189 | |||
183 | static void LoadHeader(LoadState* S) | 190 | static void LoadHeader(LoadState* S) |
184 | { | 191 | { |
185 | char h[LUAC_HEADERSIZE]; | 192 | lu_byte h[LUAC_HEADERSIZE]; |
186 | char s[LUAC_HEADERSIZE]; | 193 | lu_byte s[LUAC_HEADERSIZE]; |
187 | luaU_header(h); | 194 | luaU_header(h); |
188 | LoadBlock(S,s,LUAC_HEADERSIZE); | 195 | memcpy(s,h,sizeof(char)); /* first char already read */ |
189 | IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); | 196 | LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char)); |
197 | if (memcmp(h,s,N0)==0) return; | ||
198 | if (memcmp(h,s,N1)!=0) error(S,"not a"); | ||
199 | if (memcmp(h,s,N2)!=0) error(S,"version mismatch in"); | ||
200 | if (memcmp(h,s,N3)!=0) error(S,"incompatible"); else error(S,"corrupted"); | ||
190 | } | 201 | } |
191 | 202 | ||
192 | /* | 203 | /* |
193 | ** load precompiled chunk | 204 | ** load precompiled chunk |
194 | */ | 205 | */ |
195 | Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) | 206 | Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) |
196 | { | 207 | { |
197 | LoadState S; | 208 | LoadState S; |
209 | Closure* cl; | ||
198 | if (*name=='@' || *name=='=') | 210 | if (*name=='@' || *name=='=') |
199 | S.name=name+1; | 211 | S.name=name+1; |
200 | else if (*name==LUA_SIGNATURE[0]) | 212 | else if (*name==LUA_SIGNATURE[0]) |
@@ -205,23 +217,43 @@ Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) | |||
205 | S.Z=Z; | 217 | S.Z=Z; |
206 | S.b=buff; | 218 | S.b=buff; |
207 | LoadHeader(&S); | 219 | LoadHeader(&S); |
208 | return LoadFunction(&S,luaS_newliteral(L,"=?")); | 220 | cl=luaF_newLclosure(L,1); |
221 | setclLvalue(L,L->top,cl); incr_top(L); | ||
222 | cl->l.p=luaF_newproto(L); | ||
223 | LoadFunction(&S,cl->l.p); | ||
224 | if (cl->l.p->sizeupvalues != 1) | ||
225 | { | ||
226 | Proto* p=cl->l.p; | ||
227 | cl=luaF_newLclosure(L,cl->l.p->sizeupvalues); | ||
228 | cl->l.p=p; | ||
229 | setclLvalue(L,L->top-1,cl); | ||
230 | } | ||
231 | luai_verifycode(L,buff,cl->l.p); | ||
232 | return cl; | ||
209 | } | 233 | } |
210 | 234 | ||
235 | #define MYINT(s) (s[0]-'0') | ||
236 | #undef VERSION | ||
237 | #define VERSION MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR) | ||
238 | #define FORMAT 0 /* this is the official format */ | ||
239 | |||
211 | /* | 240 | /* |
212 | * make header | 241 | * make header for precompiled chunks |
242 | * if you change the code below be sure to update LoadHeader and FORMAT above | ||
243 | * and LUAC_HEADERSIZE in lundump.h | ||
213 | */ | 244 | */ |
214 | void luaU_header (char* h) | 245 | void luaU_header (lu_byte* h) |
215 | { | 246 | { |
216 | int x=1; | 247 | int x=1; |
217 | memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); | 248 | memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char)); |
218 | h+=sizeof(LUA_SIGNATURE)-1; | 249 | h+=sizeof(LUA_SIGNATURE)-sizeof(char); |
219 | *h++=(char)LUAC_VERSION; | 250 | *h++=cast_byte(VERSION); |
220 | *h++=(char)LUAC_FORMAT; | 251 | *h++=cast_byte(FORMAT); |
221 | *h++=(char)*(char*)&x; /* endianness */ | 252 | *h++=cast_byte(*(char*)&x); /* endianness */ |
222 | *h++=(char)sizeof(int); | 253 | *h++=cast_byte(sizeof(int)); |
223 | *h++=(char)sizeof(size_t); | 254 | *h++=cast_byte(sizeof(size_t)); |
224 | *h++=(char)sizeof(Instruction); | 255 | *h++=cast_byte(sizeof(Instruction)); |
225 | *h++=(char)sizeof(lua_Number); | 256 | *h++=cast_byte(sizeof(lua_Number)); |
226 | *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ | 257 | *h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */ |
258 | memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char)); | ||
227 | } | 259 | } |
diff --git a/apps/plugins/lua/lundump.h b/apps/plugins/lua/lundump.h index f791a4f173..5255db259d 100644 --- a/apps/plugins/lua/lundump.h +++ b/apps/plugins/lua/lundump.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lundump.h,v 1.39.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** load precompiled Lua chunks | 3 | ** load precompiled Lua chunks |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -11,26 +11,18 @@ | |||
11 | #include "lzio.h" | 11 | #include "lzio.h" |
12 | 12 | ||
13 | /* load one chunk; from lundump.c */ | 13 | /* load one chunk; from lundump.c */ |
14 | LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); | 14 | LUAI_FUNC Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); |
15 | 15 | ||
16 | /* make header; from lundump.c */ | 16 | /* make header; from lundump.c */ |
17 | LUAI_FUNC void luaU_header (char* h); | 17 | LUAI_FUNC void luaU_header (lu_byte* h); |
18 | 18 | ||
19 | /* dump one chunk; from ldump.c */ | 19 | /* dump one chunk; from ldump.c */ |
20 | LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); | 20 | LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); |
21 | 21 | ||
22 | #ifdef luac_c | 22 | /* data to catch conversion errors */ |
23 | /* print one chunk; from print.c */ | 23 | #define LUAC_TAIL "\x19\x93\r\n\x1a\n" |
24 | LUAI_FUNC void luaU_print (const Proto* f, int full); | ||
25 | #endif | ||
26 | |||
27 | /* for header of binary files -- this is Lua 5.1 */ | ||
28 | #define LUAC_VERSION 0x51 | ||
29 | |||
30 | /* for header of binary files -- this is the official format */ | ||
31 | #define LUAC_FORMAT 0 | ||
32 | 24 | ||
33 | /* size of header of binary files */ | 25 | /* size in bytes of header of binary files */ |
34 | #define LUAC_HEADERSIZE 12 | 26 | #define LUAC_HEADERSIZE (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char)) |
35 | 27 | ||
36 | #endif | 28 | #endif |
diff --git a/apps/plugins/lua/lvm.c b/apps/plugins/lua/lvm.c index ee3256ab94..141b9fd19c 100644 --- a/apps/plugins/lua/lvm.c +++ b/apps/plugins/lua/lvm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $ | 2 | ** $Id: lvm.c,v 2.155.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -35,7 +35,7 @@ | |||
35 | const TValue *luaV_tonumber (const TValue *obj, TValue *n) { | 35 | const TValue *luaV_tonumber (const TValue *obj, TValue *n) { |
36 | lua_Number num; | 36 | lua_Number num; |
37 | if (ttisnumber(obj)) return obj; | 37 | if (ttisnumber(obj)) return obj; |
38 | if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { | 38 | if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) { |
39 | setnvalue(n, num); | 39 | setnvalue(n, num); |
40 | return n; | 40 | return n; |
41 | } | 41 | } |
@@ -50,58 +50,60 @@ int luaV_tostring (lua_State *L, StkId obj) { | |||
50 | else { | 50 | else { |
51 | char s[LUAI_MAXNUMBER2STR]; | 51 | char s[LUAI_MAXNUMBER2STR]; |
52 | lua_Number n = nvalue(obj); | 52 | lua_Number n = nvalue(obj); |
53 | lua_number2str(s, n); | 53 | int l = lua_number2str(s, n); |
54 | setsvalue2s(L, obj, luaS_new(L, s)); | 54 | setsvalue2s(L, obj, luaS_newlstr(L, s, l)); |
55 | return 1; | 55 | return 1; |
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | 59 | ||
60 | static void traceexec (lua_State *L, const Instruction *pc) { | 60 | static void traceexec (lua_State *L) { |
61 | CallInfo *ci = L->ci; | ||
61 | lu_byte mask = L->hookmask; | 62 | lu_byte mask = L->hookmask; |
62 | const Instruction *oldpc = L->savedpc; | 63 | int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0); |
63 | L->savedpc = pc; | 64 | if (counthook) |
64 | if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { | 65 | resethookcount(L); /* reset count */ |
65 | resethookcount(L); | 66 | if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ |
66 | luaD_callhook(L, LUA_HOOKCOUNT, -1); | 67 | ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ |
68 | return; /* do not call hook again (VM yielded, so it did not move) */ | ||
67 | } | 69 | } |
70 | if (counthook) | ||
71 | luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ | ||
68 | if (mask & LUA_MASKLINE) { | 72 | if (mask & LUA_MASKLINE) { |
69 | Proto *p = ci_func(L->ci)->l.p; | 73 | Proto *p = ci_func(ci)->p; |
70 | int npc = pcRel(pc, p); | 74 | int npc = pcRel(ci->u.l.savedpc, p); |
71 | int newline = getline(p, npc); | 75 | int newline = getfuncline(p, npc); |
72 | /* call linehook when enter a new function, when jump back (loop), | 76 | if (npc == 0 || /* call linehook when enter a new function, */ |
73 | or when enter a new line */ | 77 | ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ |
74 | if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) | 78 | newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ |
75 | luaD_callhook(L, LUA_HOOKLINE, newline); | 79 | luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ |
80 | } | ||
81 | L->oldpc = ci->u.l.savedpc; | ||
82 | if (L->status == LUA_YIELD) { /* did hook yield? */ | ||
83 | if (counthook) | ||
84 | L->hookcount = 1; /* undo decrement to zero */ | ||
85 | ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ | ||
86 | ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ | ||
87 | ci->func = L->top - 1; /* protect stack below results */ | ||
88 | luaD_throw(L, LUA_YIELD); | ||
76 | } | 89 | } |
77 | } | 90 | } |
78 | 91 | ||
79 | 92 | ||
80 | static void callTMres (lua_State *L, StkId res, const TValue *f, | ||
81 | const TValue *p1, const TValue *p2) { | ||
82 | ptrdiff_t result = savestack(L, res); | ||
83 | setobj2s(L, L->top, f); /* push function */ | ||
84 | setobj2s(L, L->top+1, p1); /* 1st argument */ | ||
85 | setobj2s(L, L->top+2, p2); /* 2nd argument */ | ||
86 | luaD_checkstack(L, 3); | ||
87 | L->top += 3; | ||
88 | luaD_call(L, L->top - 3, 1); | ||
89 | res = restorestack(L, result); | ||
90 | L->top--; | ||
91 | setobjs2s(L, res, L->top); | ||
92 | } | ||
93 | |||
94 | |||
95 | |||
96 | static void callTM (lua_State *L, const TValue *f, const TValue *p1, | 93 | static void callTM (lua_State *L, const TValue *f, const TValue *p1, |
97 | const TValue *p2, const TValue *p3) { | 94 | const TValue *p2, TValue *p3, int hasres) { |
98 | setobj2s(L, L->top, f); /* push function */ | 95 | ptrdiff_t result = savestack(L, p3); |
99 | setobj2s(L, L->top+1, p1); /* 1st argument */ | 96 | setobj2s(L, L->top++, f); /* push function */ |
100 | setobj2s(L, L->top+2, p2); /* 2nd argument */ | 97 | setobj2s(L, L->top++, p1); /* 1st argument */ |
101 | setobj2s(L, L->top+3, p3); /* 3th argument */ | 98 | setobj2s(L, L->top++, p2); /* 2nd argument */ |
102 | luaD_checkstack(L, 4); | 99 | if (!hasres) /* no result? 'p3' is third argument */ |
103 | L->top += 4; | 100 | setobj2s(L, L->top++, p3); /* 3rd argument */ |
104 | luaD_call(L, L->top - 4, 0); | 101 | /* metamethod may yield only when called from Lua code */ |
102 | luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); | ||
103 | if (hasres) { /* if has result, move it to its place */ | ||
104 | p3 = restorestack(L, result); | ||
105 | setobjs2s(L, p3, --L->top); | ||
106 | } | ||
105 | } | 107 | } |
106 | 108 | ||
107 | 109 | ||
@@ -112,7 +114,7 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
112 | if (ttistable(t)) { /* `t' is a table? */ | 114 | if (ttistable(t)) { /* `t' is a table? */ |
113 | Table *h = hvalue(t); | 115 | Table *h = hvalue(t); |
114 | const TValue *res = luaH_get(h, key); /* do a primitive get */ | 116 | const TValue *res = luaH_get(h, key); /* do a primitive get */ |
115 | if (!ttisnil(res) || /* result is no nil? */ | 117 | if (!ttisnil(res) || /* result is not nil? */ |
116 | (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ | 118 | (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ |
117 | setobj2s(L, val, res); | 119 | setobj2s(L, val, res); |
118 | return; | 120 | return; |
@@ -122,10 +124,10 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
122 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) | 124 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) |
123 | luaG_typeerror(L, t, "index"); | 125 | luaG_typeerror(L, t, "index"); |
124 | if (ttisfunction(tm)) { | 126 | if (ttisfunction(tm)) { |
125 | callTMres(L, val, tm, t, key); | 127 | callTM(L, tm, t, key, val, 1); |
126 | return; | 128 | return; |
127 | } | 129 | } |
128 | t = tm; /* else repeat with `tm' */ | 130 | t = tm; /* else repeat with 'tm' */ |
129 | } | 131 | } |
130 | luaG_runerror(L, "loop in gettable"); | 132 | luaG_runerror(L, "loop in gettable"); |
131 | } | 133 | } |
@@ -137,22 +139,34 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
137 | const TValue *tm; | 139 | const TValue *tm; |
138 | if (ttistable(t)) { /* `t' is a table? */ | 140 | if (ttistable(t)) { /* `t' is a table? */ |
139 | Table *h = hvalue(t); | 141 | Table *h = hvalue(t); |
140 | TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ | 142 | TValue *oldval = cast(TValue *, luaH_get(h, key)); |
141 | if (!ttisnil(oldval) || /* result is no nil? */ | 143 | /* if previous value is not nil, there must be a previous entry |
142 | (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ | 144 | in the table; moreover, a metamethod has no relevance */ |
143 | setobj2t(L, oldval, val); | 145 | if (!ttisnil(oldval) || |
144 | luaC_barriert(L, h, val); | 146 | /* previous value is nil; must check the metamethod */ |
147 | ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && | ||
148 | /* no metamethod; is there a previous entry in the table? */ | ||
149 | (oldval != luaO_nilobject || | ||
150 | /* no previous entry; must create one. (The next test is | ||
151 | always true; we only need the assignment.) */ | ||
152 | (oldval = luaH_newkey(L, h, key), 1)))) { | ||
153 | /* no metamethod and (now) there is an entry with given key */ | ||
154 | setobj2t(L, oldval, val); /* assign new value to that entry */ | ||
155 | invalidateTMcache(h); | ||
156 | luaC_barrierback(L, obj2gco(h), val); | ||
145 | return; | 157 | return; |
146 | } | 158 | } |
147 | /* else will try the tag method */ | 159 | /* else will try the metamethod */ |
148 | } | 160 | } |
149 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) | 161 | else /* not a table; check metamethod */ |
150 | luaG_typeerror(L, t, "index"); | 162 | if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) |
163 | luaG_typeerror(L, t, "index"); | ||
164 | /* there is a metamethod */ | ||
151 | if (ttisfunction(tm)) { | 165 | if (ttisfunction(tm)) { |
152 | callTM(L, tm, t, key, val); | 166 | callTM(L, tm, t, key, val, 0); |
153 | return; | 167 | return; |
154 | } | 168 | } |
155 | t = tm; /* else repeat with `tm' */ | 169 | t = tm; /* else repeat with 'tm' */ |
156 | } | 170 | } |
157 | luaG_runerror(L, "loop in settable"); | 171 | luaG_runerror(L, "loop in settable"); |
158 | } | 172 | } |
@@ -164,12 +178,12 @@ static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, | |||
164 | if (ttisnil(tm)) | 178 | if (ttisnil(tm)) |
165 | tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ | 179 | tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ |
166 | if (ttisnil(tm)) return 0; | 180 | if (ttisnil(tm)) return 0; |
167 | callTMres(L, res, tm, p1, p2); | 181 | callTM(L, tm, p1, p2, res, 1); |
168 | return 1; | 182 | return 1; |
169 | } | 183 | } |
170 | 184 | ||
171 | 185 | ||
172 | static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, | 186 | static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2, |
173 | TMS event) { | 187 | TMS event) { |
174 | const TValue *tm1 = fasttm(L, mt1, event); | 188 | const TValue *tm1 = fasttm(L, mt1, event); |
175 | const TValue *tm2; | 189 | const TValue *tm2; |
@@ -177,7 +191,7 @@ static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, | |||
177 | if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ | 191 | if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ |
178 | tm2 = fasttm(L, mt2, event); | 192 | tm2 = fasttm(L, mt2, event); |
179 | if (tm2 == NULL) return NULL; /* no metamethod */ | 193 | if (tm2 == NULL) return NULL; /* no metamethod */ |
180 | if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ | 194 | if (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */ |
181 | return tm1; | 195 | return tm1; |
182 | return NULL; | 196 | return NULL; |
183 | } | 197 | } |
@@ -185,14 +199,10 @@ static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, | |||
185 | 199 | ||
186 | static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, | 200 | static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, |
187 | TMS event) { | 201 | TMS event) { |
188 | const TValue *tm1 = luaT_gettmbyobj(L, p1, event); | 202 | if (!call_binTM(L, p1, p2, L->top, event)) |
189 | const TValue *tm2; | 203 | return -1; /* no metamethod */ |
190 | if (ttisnil(tm1)) return -1; /* no metamethod? */ | 204 | else |
191 | tm2 = luaT_gettmbyobj(L, p2, event); | 205 | return !l_isfalse(L->top); |
192 | if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ | ||
193 | return -1; | ||
194 | callTMres(L, L->top, tm1, p1, p2); | ||
195 | return !l_isfalse(L->top); | ||
196 | } | 206 | } |
197 | 207 | ||
198 | 208 | ||
@@ -220,125 +230,261 @@ static int l_strcmp (const TString *ls, const TString *rs) { | |||
220 | 230 | ||
221 | int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { | 231 | int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { |
222 | int res; | 232 | int res; |
223 | if (ttype(l) != ttype(r)) | 233 | if (ttisnumber(l) && ttisnumber(r)) |
224 | return luaG_ordererror(L, l, r); | 234 | return luai_numlt(L, nvalue(l), nvalue(r)); |
225 | else if (ttisnumber(l)) | 235 | else if (ttisstring(l) && ttisstring(r)) |
226 | return luai_numlt(nvalue(l), nvalue(r)); | ||
227 | else if (ttisstring(l)) | ||
228 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; | 236 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; |
229 | else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) | 237 | else if ((res = call_orderTM(L, l, r, TM_LT)) < 0) |
230 | return res; | 238 | luaG_ordererror(L, l, r); |
231 | return luaG_ordererror(L, l, r); | 239 | return res; |
232 | } | 240 | } |
233 | 241 | ||
234 | 242 | ||
235 | static int lessequal (lua_State *L, const TValue *l, const TValue *r) { | 243 | int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { |
236 | int res; | 244 | int res; |
237 | if (ttype(l) != ttype(r)) | 245 | if (ttisnumber(l) && ttisnumber(r)) |
238 | return luaG_ordererror(L, l, r); | 246 | return luai_numle(L, nvalue(l), nvalue(r)); |
239 | else if (ttisnumber(l)) | 247 | else if (ttisstring(l) && ttisstring(r)) |
240 | return luai_numle(nvalue(l), nvalue(r)); | ||
241 | else if (ttisstring(l)) | ||
242 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; | 248 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; |
243 | else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ | 249 | else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ |
244 | return res; | 250 | return res; |
245 | else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ | 251 | else if ((res = call_orderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */ |
246 | return !res; | 252 | luaG_ordererror(L, l, r); |
247 | return luaG_ordererror(L, l, r); | 253 | return !res; |
248 | } | 254 | } |
249 | 255 | ||
250 | 256 | ||
251 | int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { | 257 | /* |
258 | ** equality of Lua values. L == NULL means raw equality (no metamethods) | ||
259 | */ | ||
260 | int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) { | ||
252 | const TValue *tm; | 261 | const TValue *tm; |
253 | lua_assert(ttype(t1) == ttype(t2)); | 262 | lua_assert(ttisequal(t1, t2)); |
254 | switch (ttype(t1)) { | 263 | switch (ttype(t1)) { |
255 | case LUA_TNIL: return 1; | 264 | case LUA_TNIL: return 1; |
256 | case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); | 265 | case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); |
257 | case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ | 266 | case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ |
258 | case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); | 267 | case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); |
268 | case LUA_TLCF: return fvalue(t1) == fvalue(t2); | ||
269 | case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2)); | ||
270 | case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2)); | ||
259 | case LUA_TUSERDATA: { | 271 | case LUA_TUSERDATA: { |
260 | if (uvalue(t1) == uvalue(t2)) return 1; | 272 | if (uvalue(t1) == uvalue(t2)) return 1; |
261 | tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, | 273 | else if (L == NULL) return 0; |
262 | TM_EQ); | 274 | tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ); |
263 | break; /* will try TM */ | 275 | break; /* will try TM */ |
264 | } | 276 | } |
265 | case LUA_TTABLE: { | 277 | case LUA_TTABLE: { |
266 | if (hvalue(t1) == hvalue(t2)) return 1; | 278 | if (hvalue(t1) == hvalue(t2)) return 1; |
267 | tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); | 279 | else if (L == NULL) return 0; |
280 | tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); | ||
268 | break; /* will try TM */ | 281 | break; /* will try TM */ |
269 | } | 282 | } |
270 | default: return gcvalue(t1) == gcvalue(t2); | 283 | default: |
284 | lua_assert(iscollectable(t1)); | ||
285 | return gcvalue(t1) == gcvalue(t2); | ||
271 | } | 286 | } |
272 | if (tm == NULL) return 0; /* no TM? */ | 287 | if (tm == NULL) return 0; /* no TM? */ |
273 | callTMres(L, L->top, tm, t1, t2); /* call TM */ | 288 | callTM(L, tm, t1, t2, L->top, 1); /* call TM */ |
274 | return !l_isfalse(L->top); | 289 | return !l_isfalse(L->top); |
275 | } | 290 | } |
276 | 291 | ||
277 | 292 | ||
278 | void luaV_concat (lua_State *L, int total, int last) { | 293 | void luaV_concat (lua_State *L, int total) { |
294 | lua_assert(total >= 2); | ||
279 | do { | 295 | do { |
280 | StkId top = L->base + last + 1; | 296 | StkId top = L->top; |
281 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 297 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
282 | if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { | 298 | if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { |
283 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) | 299 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) |
284 | luaG_concaterror(L, top-2, top-1); | 300 | luaG_concaterror(L, top-2, top-1); |
285 | } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ | 301 | } |
286 | (void)tostring(L, top - 2); /* result is first op (as string) */ | 302 | else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ |
303 | (void)tostring(L, top - 2); /* result is first operand */ | ||
304 | else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { | ||
305 | setobjs2s(L, top - 2, top - 1); /* result is second op. */ | ||
306 | } | ||
287 | else { | 307 | else { |
288 | /* at least two string values; get as many as possible */ | 308 | /* at least two non-empty string values; get as many as possible */ |
289 | size_t tl = tsvalue(top-1)->len; | 309 | size_t tl = tsvalue(top-1)->len; |
290 | char *buffer; | 310 | char *buffer; |
291 | int i; | 311 | int i; |
292 | /* collect total length */ | 312 | /* collect total length */ |
293 | for (n = 1; n < total && tostring(L, top-n-1); n++) { | 313 | for (i = 1; i < total && tostring(L, top-i-1); i++) { |
294 | size_t l = tsvalue(top-n-1)->len; | 314 | size_t l = tsvalue(top-i-1)->len; |
295 | if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); | 315 | if (l >= (MAX_SIZET/sizeof(char)) - tl) |
316 | luaG_runerror(L, "string length overflow"); | ||
296 | tl += l; | 317 | tl += l; |
297 | } | 318 | } |
298 | buffer = luaZ_openspace(L, &G(L)->buff, tl); | 319 | buffer = luaZ_openspace(L, &G(L)->buff, tl); |
299 | tl = 0; | 320 | tl = 0; |
300 | for (i=n; i>0; i--) { /* concat all strings */ | 321 | n = i; |
322 | do { /* concat all strings */ | ||
301 | size_t l = tsvalue(top-i)->len; | 323 | size_t l = tsvalue(top-i)->len; |
302 | memcpy(buffer+tl, svalue(top-i), l); | 324 | memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); |
303 | tl += l; | 325 | tl += l; |
304 | } | 326 | } while (--i > 0); |
305 | setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); | 327 | setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); |
306 | } | 328 | } |
307 | total -= n-1; /* got `n' strings to create 1 new */ | 329 | total -= n-1; /* got 'n' strings to create 1 new */ |
308 | last -= n-1; | 330 | L->top -= n-1; /* popped 'n' strings and pushed one */ |
309 | } while (total > 1); /* repeat until only 1 result left */ | 331 | } while (total > 1); /* repeat until only 1 result left */ |
310 | } | 332 | } |
311 | 333 | ||
312 | 334 | ||
313 | static void Arith (lua_State *L, StkId ra, const TValue *rb, | 335 | void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { |
314 | const TValue *rc, TMS op) { | 336 | const TValue *tm; |
337 | switch (ttypenv(rb)) { | ||
338 | case LUA_TTABLE: { | ||
339 | Table *h = hvalue(rb); | ||
340 | tm = fasttm(L, h->metatable, TM_LEN); | ||
341 | if (tm) break; /* metamethod? break switch to call it */ | ||
342 | setnvalue(ra, cast_num(luaH_getn(h))); /* else primitive len */ | ||
343 | return; | ||
344 | } | ||
345 | case LUA_TSTRING: { | ||
346 | setnvalue(ra, cast_num(tsvalue(rb)->len)); | ||
347 | return; | ||
348 | } | ||
349 | default: { /* try metamethod */ | ||
350 | tm = luaT_gettmbyobj(L, rb, TM_LEN); | ||
351 | if (ttisnil(tm)) /* no metamethod? */ | ||
352 | luaG_typeerror(L, rb, "get length of"); | ||
353 | break; | ||
354 | } | ||
355 | } | ||
356 | callTM(L, tm, rb, rb, ra, 1); | ||
357 | } | ||
358 | |||
359 | |||
360 | void luaV_arith (lua_State *L, StkId ra, const TValue *rb, | ||
361 | const TValue *rc, TMS op) { | ||
315 | TValue tempb, tempc; | 362 | TValue tempb, tempc; |
316 | const TValue *b, *c; | 363 | const TValue *b, *c; |
317 | if ((b = luaV_tonumber(rb, &tempb)) != NULL && | 364 | if ((b = luaV_tonumber(rb, &tempb)) != NULL && |
318 | (c = luaV_tonumber(rc, &tempc)) != NULL) { | 365 | (c = luaV_tonumber(rc, &tempc)) != NULL) { |
319 | lua_Number nb = nvalue(b), nc = nvalue(c); | 366 | lua_Number res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c)); |
320 | switch (op) { | 367 | setnvalue(ra, res); |
321 | case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; | ||
322 | case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; | ||
323 | case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; | ||
324 | case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; | ||
325 | case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; | ||
326 | case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; | ||
327 | case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; | ||
328 | default: lua_assert(0); break; | ||
329 | } | ||
330 | } | 368 | } |
331 | else if (!call_binTM(L, rb, rc, ra, op)) | 369 | else if (!call_binTM(L, rb, rc, ra, op)) |
332 | luaG_aritherror(L, rb, rc); | 370 | luaG_aritherror(L, rb, rc); |
333 | } | 371 | } |
334 | 372 | ||
335 | 373 | ||
374 | /* | ||
375 | ** check whether cached closure in prototype 'p' may be reused, that is, | ||
376 | ** whether there is a cached closure with the same upvalues needed by | ||
377 | ** new closure to be created. | ||
378 | */ | ||
379 | static Closure *getcached (Proto *p, UpVal **encup, StkId base) { | ||
380 | Closure *c = p->cache; | ||
381 | if (c != NULL) { /* is there a cached closure? */ | ||
382 | int nup = p->sizeupvalues; | ||
383 | Upvaldesc *uv = p->upvalues; | ||
384 | int i; | ||
385 | for (i = 0; i < nup; i++) { /* check whether it has right upvalues */ | ||
386 | TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v; | ||
387 | if (c->l.upvals[i]->v != v) | ||
388 | return NULL; /* wrong upvalue; cannot reuse closure */ | ||
389 | } | ||
390 | } | ||
391 | return c; /* return cached closure (or NULL if no cached closure) */ | ||
392 | } | ||
393 | |||
394 | |||
395 | /* | ||
396 | ** create a new Lua closure, push it in the stack, and initialize | ||
397 | ** its upvalues. Note that the call to 'luaC_barrierproto' must come | ||
398 | ** before the assignment to 'p->cache', as the function needs the | ||
399 | ** original value of that field. | ||
400 | */ | ||
401 | static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, | ||
402 | StkId ra) { | ||
403 | int nup = p->sizeupvalues; | ||
404 | Upvaldesc *uv = p->upvalues; | ||
405 | int i; | ||
406 | Closure *ncl = luaF_newLclosure(L, nup); | ||
407 | ncl->l.p = p; | ||
408 | setclLvalue(L, ra, ncl); /* anchor new closure in stack */ | ||
409 | for (i = 0; i < nup; i++) { /* fill in its upvalues */ | ||
410 | if (uv[i].instack) /* upvalue refers to local variable? */ | ||
411 | ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx); | ||
412 | else /* get upvalue from enclosing function */ | ||
413 | ncl->l.upvals[i] = encup[uv[i].idx]; | ||
414 | } | ||
415 | luaC_barrierproto(L, p, ncl); | ||
416 | p->cache = ncl; /* save it on cache for reuse */ | ||
417 | } | ||
418 | |||
419 | |||
420 | /* | ||
421 | ** finish execution of an opcode interrupted by an yield | ||
422 | */ | ||
423 | void luaV_finishOp (lua_State *L) { | ||
424 | CallInfo *ci = L->ci; | ||
425 | StkId base = ci->u.l.base; | ||
426 | Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ | ||
427 | OpCode op = GET_OPCODE(inst); | ||
428 | switch (op) { /* finish its execution */ | ||
429 | case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: | ||
430 | case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: | ||
431 | case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { | ||
432 | setobjs2s(L, base + GETARG_A(inst), --L->top); | ||
433 | break; | ||
434 | } | ||
435 | case OP_LE: case OP_LT: case OP_EQ: { | ||
436 | int res = !l_isfalse(L->top - 1); | ||
437 | L->top--; | ||
438 | /* metamethod should not be called when operand is K */ | ||
439 | lua_assert(!ISK(GETARG_B(inst))); | ||
440 | if (op == OP_LE && /* "<=" using "<" instead? */ | ||
441 | ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE))) | ||
442 | res = !res; /* invert result */ | ||
443 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); | ||
444 | if (res != GETARG_A(inst)) /* condition failed? */ | ||
445 | ci->u.l.savedpc++; /* skip jump instruction */ | ||
446 | break; | ||
447 | } | ||
448 | case OP_CONCAT: { | ||
449 | StkId top = L->top - 1; /* top when 'call_binTM' was called */ | ||
450 | int b = GETARG_B(inst); /* first element to concatenate */ | ||
451 | int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ | ||
452 | setobj2s(L, top - 2, top); /* put TM result in proper position */ | ||
453 | if (total > 1) { /* are there elements to concat? */ | ||
454 | L->top = top - 1; /* top is one after last element (at top-2) */ | ||
455 | luaV_concat(L, total); /* concat them (may yield again) */ | ||
456 | } | ||
457 | /* move final result to final position */ | ||
458 | setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); | ||
459 | L->top = ci->top; /* restore top */ | ||
460 | break; | ||
461 | } | ||
462 | case OP_TFORCALL: { | ||
463 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); | ||
464 | L->top = ci->top; /* correct top */ | ||
465 | break; | ||
466 | } | ||
467 | case OP_CALL: { | ||
468 | if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ | ||
469 | L->top = ci->top; /* adjust results */ | ||
470 | break; | ||
471 | } | ||
472 | case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: | ||
473 | break; | ||
474 | default: lua_assert(0); | ||
475 | } | ||
476 | } | ||
477 | |||
478 | |||
336 | 479 | ||
337 | /* | 480 | /* |
338 | ** some macros for common tasks in `luaV_execute' | 481 | ** some macros for common tasks in `luaV_execute' |
339 | */ | 482 | */ |
340 | 483 | ||
341 | #define runtime_check(L, c) { if (!(c)) break; } | 484 | #if !defined luai_runtimecheck |
485 | #define luai_runtimecheck(L, c) /* void */ | ||
486 | #endif | ||
487 | |||
342 | 488 | ||
343 | #define RA(i) (base+GETARG_A(i)) | 489 | #define RA(i) (base+GETARG_A(i)) |
344 | /* to be used after possible stack reallocation */ | 490 | /* to be used after possible stack reallocation */ |
@@ -348,13 +494,27 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb, | |||
348 | ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) | 494 | ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) |
349 | #define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ | 495 | #define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ |
350 | ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) | 496 | ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) |
351 | #define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) | 497 | #define KBx(i) \ |
498 | (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++))) | ||
499 | |||
352 | 500 | ||
501 | /* execute a jump instruction */ | ||
502 | #define dojump(ci,i,e) \ | ||
503 | { int a = GETARG_A(i); \ | ||
504 | if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \ | ||
505 | ci->u.l.savedpc += GETARG_sBx(i) + e; } | ||
353 | 506 | ||
354 | #define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} | 507 | /* for test instructions, execute the jump instruction that follows it */ |
508 | #define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); } | ||
355 | 509 | ||
356 | 510 | ||
357 | #define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } | 511 | #define Protect(x) { {x;}; base = ci->u.l.base; } |
512 | |||
513 | #define checkGC(L,c) \ | ||
514 | Protect( luaC_condGC(L,{L->top = (c); /* limit of live values */ \ | ||
515 | luaC_step(L); \ | ||
516 | L->top = ci->top;}) /* restore top */ \ | ||
517 | luai_threadyield(L); ) | ||
358 | 518 | ||
359 | 519 | ||
360 | #define arith_op(op,tm) { \ | 520 | #define arith_op(op,tm) { \ |
@@ -362,401 +522,345 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb, | |||
362 | TValue *rc = RKC(i); \ | 522 | TValue *rc = RKC(i); \ |
363 | if (ttisnumber(rb) && ttisnumber(rc)) { \ | 523 | if (ttisnumber(rb) && ttisnumber(rc)) { \ |
364 | lua_Number nb = nvalue(rb), nc = nvalue(rc); \ | 524 | lua_Number nb = nvalue(rb), nc = nvalue(rc); \ |
365 | setnvalue(ra, op(nb, nc)); \ | 525 | setnvalue(ra, op(L, nb, nc)); \ |
366 | } \ | 526 | } \ |
367 | else \ | 527 | else { Protect(luaV_arith(L, ra, rb, rc, tm)); } } |
368 | Protect(Arith(L, ra, rb, rc, tm)); \ | ||
369 | } | ||
370 | 528 | ||
371 | 529 | ||
530 | #define vmdispatch(o) switch(o) | ||
531 | #define vmcase(l,b) case l: {b} break; | ||
532 | #define vmcasenb(l,b) case l: {b} /* nb = no break */ | ||
372 | 533 | ||
373 | void luaV_execute (lua_State *L, int nexeccalls) { | 534 | void luaV_execute (lua_State *L) { |
535 | CallInfo *ci = L->ci; | ||
374 | LClosure *cl; | 536 | LClosure *cl; |
375 | StkId base; | ||
376 | TValue *k; | 537 | TValue *k; |
377 | const Instruction *pc; | 538 | StkId base; |
378 | reentry: /* entry point */ | 539 | newframe: /* reentry point when frame changes (call/return) */ |
379 | lua_assert(isLua(L->ci)); | 540 | lua_assert(ci == L->ci); |
380 | pc = L->savedpc; | 541 | cl = clLvalue(ci->func); |
381 | cl = &clvalue(L->ci->func)->l; | ||
382 | base = L->base; | ||
383 | k = cl->p->k; | 542 | k = cl->p->k; |
543 | base = ci->u.l.base; | ||
384 | /* main loop of interpreter */ | 544 | /* main loop of interpreter */ |
385 | for (;;) { | 545 | for (;;) { |
386 | const Instruction i = *pc++; | 546 | Instruction i = *(ci->u.l.savedpc++); |
387 | StkId ra; | 547 | StkId ra; |
388 | if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && | 548 | if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && |
389 | (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { | 549 | (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { |
390 | traceexec(L, pc); | 550 | Protect(traceexec(L)); |
391 | if (L->status == LUA_YIELD) { /* did hook yield? */ | ||
392 | L->savedpc = pc - 1; | ||
393 | return; | ||
394 | } | ||
395 | base = L->base; | ||
396 | } | 551 | } |
397 | /* warning!! several calls may realloc the stack and invalidate `ra' */ | 552 | /* WARNING: several calls may realloc the stack and invalidate `ra' */ |
398 | ra = RA(i); | 553 | ra = RA(i); |
399 | lua_assert(base == L->base && L->base == L->ci->base); | 554 | lua_assert(base == ci->u.l.base); |
400 | lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); | 555 | lua_assert(base <= L->top && L->top < L->stack + L->stacksize); |
401 | lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); | 556 | vmdispatch (GET_OPCODE(i)) { |
402 | switch (GET_OPCODE(i)) { | 557 | vmcase(OP_MOVE, |
403 | case OP_MOVE: { | ||
404 | setobjs2s(L, ra, RB(i)); | 558 | setobjs2s(L, ra, RB(i)); |
405 | continue; | 559 | ) |
406 | } | 560 | vmcase(OP_LOADK, |
407 | case OP_LOADK: { | 561 | TValue *rb = k + GETARG_Bx(i); |
408 | setobj2s(L, ra, KBx(i)); | 562 | setobj2s(L, ra, rb); |
409 | continue; | 563 | ) |
410 | } | 564 | vmcase(OP_LOADKX, |
411 | case OP_LOADBOOL: { | 565 | TValue *rb; |
566 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); | ||
567 | rb = k + GETARG_Ax(*ci->u.l.savedpc++); | ||
568 | setobj2s(L, ra, rb); | ||
569 | ) | ||
570 | vmcase(OP_LOADBOOL, | ||
412 | setbvalue(ra, GETARG_B(i)); | 571 | setbvalue(ra, GETARG_B(i)); |
413 | if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ | 572 | if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ |
414 | continue; | 573 | ) |
415 | } | 574 | vmcase(OP_LOADNIL, |
416 | case OP_LOADNIL: { | 575 | int b = GETARG_B(i); |
417 | TValue *rb = RB(i); | ||
418 | do { | 576 | do { |
419 | setnilvalue(rb--); | 577 | setnilvalue(ra++); |
420 | } while (rb >= ra); | 578 | } while (b--); |
421 | continue; | 579 | ) |
422 | } | 580 | vmcase(OP_GETUPVAL, |
423 | case OP_GETUPVAL: { | ||
424 | int b = GETARG_B(i); | 581 | int b = GETARG_B(i); |
425 | setobj2s(L, ra, cl->upvals[b]->v); | 582 | setobj2s(L, ra, cl->upvals[b]->v); |
426 | continue; | 583 | ) |
427 | } | 584 | vmcase(OP_GETTABUP, |
428 | case OP_GETGLOBAL: { | 585 | int b = GETARG_B(i); |
429 | TValue g; | 586 | Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); |
430 | TValue *rb = KBx(i); | 587 | ) |
431 | sethvalue(L, &g, cl->env); | 588 | vmcase(OP_GETTABLE, |
432 | lua_assert(ttisstring(rb)); | ||
433 | Protect(luaV_gettable(L, &g, rb, ra)); | ||
434 | continue; | ||
435 | } | ||
436 | case OP_GETTABLE: { | ||
437 | Protect(luaV_gettable(L, RB(i), RKC(i), ra)); | 589 | Protect(luaV_gettable(L, RB(i), RKC(i), ra)); |
438 | continue; | 590 | ) |
439 | } | 591 | vmcase(OP_SETTABUP, |
440 | case OP_SETGLOBAL: { | 592 | int a = GETARG_A(i); |
441 | TValue g; | 593 | Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i))); |
442 | sethvalue(L, &g, cl->env); | 594 | ) |
443 | lua_assert(ttisstring(KBx(i))); | 595 | vmcase(OP_SETUPVAL, |
444 | Protect(luaV_settable(L, &g, KBx(i), ra)); | ||
445 | continue; | ||
446 | } | ||
447 | case OP_SETUPVAL: { | ||
448 | UpVal *uv = cl->upvals[GETARG_B(i)]; | 596 | UpVal *uv = cl->upvals[GETARG_B(i)]; |
449 | setobj(L, uv->v, ra); | 597 | setobj(L, uv->v, ra); |
450 | luaC_barrier(L, uv, ra); | 598 | luaC_barrier(L, uv, ra); |
451 | continue; | 599 | ) |
452 | } | 600 | vmcase(OP_SETTABLE, |
453 | case OP_SETTABLE: { | ||
454 | Protect(luaV_settable(L, ra, RKB(i), RKC(i))); | 601 | Protect(luaV_settable(L, ra, RKB(i), RKC(i))); |
455 | continue; | 602 | ) |
456 | } | 603 | vmcase(OP_NEWTABLE, |
457 | case OP_NEWTABLE: { | ||
458 | int b = GETARG_B(i); | 604 | int b = GETARG_B(i); |
459 | int c = GETARG_C(i); | 605 | int c = GETARG_C(i); |
460 | sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); | 606 | Table *t = luaH_new(L); |
461 | Protect(luaC_checkGC(L)); | 607 | sethvalue(L, ra, t); |
462 | continue; | 608 | if (b != 0 || c != 0) |
463 | } | 609 | luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); |
464 | case OP_SELF: { | 610 | checkGC(L, ra + 1); |
611 | ) | ||
612 | vmcase(OP_SELF, | ||
465 | StkId rb = RB(i); | 613 | StkId rb = RB(i); |
466 | setobjs2s(L, ra+1, rb); | 614 | setobjs2s(L, ra+1, rb); |
467 | Protect(luaV_gettable(L, rb, RKC(i), ra)); | 615 | Protect(luaV_gettable(L, rb, RKC(i), ra)); |
468 | continue; | 616 | ) |
469 | } | 617 | vmcase(OP_ADD, |
470 | case OP_ADD: { | ||
471 | arith_op(luai_numadd, TM_ADD); | 618 | arith_op(luai_numadd, TM_ADD); |
472 | continue; | 619 | ) |
473 | } | 620 | vmcase(OP_SUB, |
474 | case OP_SUB: { | ||
475 | arith_op(luai_numsub, TM_SUB); | 621 | arith_op(luai_numsub, TM_SUB); |
476 | continue; | 622 | ) |
477 | } | 623 | vmcase(OP_MUL, |
478 | case OP_MUL: { | ||
479 | arith_op(luai_nummul, TM_MUL); | 624 | arith_op(luai_nummul, TM_MUL); |
480 | continue; | 625 | ) |
481 | } | 626 | vmcase(OP_DIV, |
482 | case OP_DIV: { | ||
483 | arith_op(luai_numdiv, TM_DIV); | 627 | arith_op(luai_numdiv, TM_DIV); |
484 | continue; | 628 | ) |
485 | } | 629 | vmcase(OP_MOD, |
486 | case OP_MOD: { | ||
487 | arith_op(luai_nummod, TM_MOD); | 630 | arith_op(luai_nummod, TM_MOD); |
488 | continue; | 631 | ) |
489 | } | 632 | vmcase(OP_POW, |
490 | case OP_POW: { | ||
491 | arith_op(luai_numpow, TM_POW); | 633 | arith_op(luai_numpow, TM_POW); |
492 | continue; | 634 | ) |
493 | } | 635 | vmcase(OP_UNM, |
494 | case OP_UNM: { | ||
495 | TValue *rb = RB(i); | 636 | TValue *rb = RB(i); |
496 | if (ttisnumber(rb)) { | 637 | if (ttisnumber(rb)) { |
497 | lua_Number nb = nvalue(rb); | 638 | lua_Number nb = nvalue(rb); |
498 | setnvalue(ra, luai_numunm(nb)); | 639 | setnvalue(ra, luai_numunm(L, nb)); |
499 | } | 640 | } |
500 | else { | 641 | else { |
501 | Protect(Arith(L, ra, rb, rb, TM_UNM)); | 642 | Protect(luaV_arith(L, ra, rb, rb, TM_UNM)); |
502 | } | 643 | } |
503 | continue; | 644 | ) |
504 | } | 645 | vmcase(OP_NOT, |
505 | case OP_NOT: { | 646 | TValue *rb = RB(i); |
506 | int res = l_isfalse(RB(i)); /* next assignment may change this value */ | 647 | int res = l_isfalse(rb); /* next assignment may change this value */ |
507 | setbvalue(ra, res); | 648 | setbvalue(ra, res); |
508 | continue; | 649 | ) |
509 | } | 650 | vmcase(OP_LEN, |
510 | case OP_LEN: { | 651 | Protect(luaV_objlen(L, ra, RB(i))); |
511 | const TValue *rb = RB(i); | 652 | ) |
512 | switch (ttype(rb)) { | 653 | vmcase(OP_CONCAT, |
513 | case LUA_TTABLE: { | ||
514 | setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); | ||
515 | break; | ||
516 | } | ||
517 | case LUA_TSTRING: { | ||
518 | setnvalue(ra, cast_num(tsvalue(rb)->len)); | ||
519 | break; | ||
520 | } | ||
521 | default: { /* try metamethod */ | ||
522 | Protect( | ||
523 | if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) | ||
524 | luaG_typeerror(L, rb, "get length of"); | ||
525 | ) | ||
526 | } | ||
527 | } | ||
528 | continue; | ||
529 | } | ||
530 | case OP_CONCAT: { | ||
531 | int b = GETARG_B(i); | 654 | int b = GETARG_B(i); |
532 | int c = GETARG_C(i); | 655 | int c = GETARG_C(i); |
533 | Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); | 656 | StkId rb; |
534 | setobjs2s(L, RA(i), base+b); | 657 | L->top = base + c + 1; /* mark the end of concat operands */ |
535 | continue; | 658 | Protect(luaV_concat(L, c - b + 1)); |
536 | } | 659 | ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */ |
537 | case OP_JMP: { | 660 | rb = b + base; |
538 | dojump(L, pc, GETARG_sBx(i)); | 661 | setobjs2s(L, ra, rb); |
539 | continue; | 662 | checkGC(L, (ra >= rb ? ra + 1 : rb)); |
540 | } | 663 | L->top = ci->top; /* restore top */ |
541 | case OP_EQ: { | 664 | ) |
665 | vmcase(OP_JMP, | ||
666 | dojump(ci, i, 0); | ||
667 | ) | ||
668 | vmcase(OP_EQ, | ||
542 | TValue *rb = RKB(i); | 669 | TValue *rb = RKB(i); |
543 | TValue *rc = RKC(i); | 670 | TValue *rc = RKC(i); |
544 | Protect( | 671 | Protect( |
545 | if (equalobj(L, rb, rc) == GETARG_A(i)) | 672 | if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i)) |
546 | dojump(L, pc, GETARG_sBx(*pc)); | 673 | ci->u.l.savedpc++; |
674 | else | ||
675 | donextjump(ci); | ||
547 | ) | 676 | ) |
548 | pc++; | 677 | ) |
549 | continue; | 678 | vmcase(OP_LT, |
550 | } | ||
551 | case OP_LT: { | ||
552 | Protect( | 679 | Protect( |
553 | if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) | 680 | if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) |
554 | dojump(L, pc, GETARG_sBx(*pc)); | 681 | ci->u.l.savedpc++; |
682 | else | ||
683 | donextjump(ci); | ||
555 | ) | 684 | ) |
556 | pc++; | 685 | ) |
557 | continue; | 686 | vmcase(OP_LE, |
558 | } | ||
559 | case OP_LE: { | ||
560 | Protect( | 687 | Protect( |
561 | if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) | 688 | if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) |
562 | dojump(L, pc, GETARG_sBx(*pc)); | 689 | ci->u.l.savedpc++; |
690 | else | ||
691 | donextjump(ci); | ||
563 | ) | 692 | ) |
564 | pc++; | 693 | ) |
565 | continue; | 694 | vmcase(OP_TEST, |
566 | } | 695 | if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) |
567 | case OP_TEST: { | 696 | ci->u.l.savedpc++; |
568 | if (l_isfalse(ra) != GETARG_C(i)) | 697 | else |
569 | dojump(L, pc, GETARG_sBx(*pc)); | 698 | donextjump(ci); |
570 | pc++; | 699 | ) |
571 | continue; | 700 | vmcase(OP_TESTSET, |
572 | } | ||
573 | case OP_TESTSET: { | ||
574 | TValue *rb = RB(i); | 701 | TValue *rb = RB(i); |
575 | if (l_isfalse(rb) != GETARG_C(i)) { | 702 | if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) |
703 | ci->u.l.savedpc++; | ||
704 | else { | ||
576 | setobjs2s(L, ra, rb); | 705 | setobjs2s(L, ra, rb); |
577 | dojump(L, pc, GETARG_sBx(*pc)); | 706 | donextjump(ci); |
578 | } | 707 | } |
579 | pc++; | 708 | ) |
580 | continue; | 709 | vmcase(OP_CALL, |
581 | } | ||
582 | case OP_CALL: { | ||
583 | int b = GETARG_B(i); | 710 | int b = GETARG_B(i); |
584 | int nresults = GETARG_C(i) - 1; | 711 | int nresults = GETARG_C(i) - 1; |
585 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ | 712 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ |
586 | L->savedpc = pc; | 713 | if (luaD_precall(L, ra, nresults)) { /* C function? */ |
587 | switch (luaD_precall(L, ra, nresults)) { | 714 | if (nresults >= 0) L->top = ci->top; /* adjust results */ |
588 | case PCRLUA: { | 715 | base = ci->u.l.base; |
589 | nexeccalls++; | ||
590 | goto reentry; /* restart luaV_execute over new Lua function */ | ||
591 | } | ||
592 | case PCRC: { | ||
593 | /* it was a C function (`precall' called it); adjust results */ | ||
594 | if (nresults >= 0) L->top = L->ci->top; | ||
595 | base = L->base; | ||
596 | continue; | ||
597 | } | ||
598 | default: { | ||
599 | return; /* yield */ | ||
600 | } | ||
601 | } | 716 | } |
602 | } | 717 | else { /* Lua function */ |
603 | case OP_TAILCALL: { | 718 | ci = L->ci; |
719 | ci->callstatus |= CIST_REENTRY; | ||
720 | goto newframe; /* restart luaV_execute over new Lua function */ | ||
721 | } | ||
722 | ) | ||
723 | vmcase(OP_TAILCALL, | ||
604 | int b = GETARG_B(i); | 724 | int b = GETARG_B(i); |
605 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ | 725 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ |
606 | L->savedpc = pc; | ||
607 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); | 726 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); |
608 | switch (luaD_precall(L, ra, LUA_MULTRET)) { | 727 | if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */ |
609 | case PCRLUA: { | 728 | base = ci->u.l.base; |
610 | /* tail call: put new frame in place of previous one */ | 729 | else { |
611 | CallInfo *ci = L->ci - 1; /* previous frame */ | 730 | /* tail call: put called frame (n) in place of caller one (o) */ |
612 | int aux; | 731 | CallInfo *nci = L->ci; /* called frame */ |
613 | StkId func = ci->func; | 732 | CallInfo *oci = nci->previous; /* caller frame */ |
614 | StkId pfunc = (ci+1)->func; /* previous function index */ | 733 | StkId nfunc = nci->func; /* called function */ |
615 | if (L->openupval) luaF_close(L, ci->base); | 734 | StkId ofunc = oci->func; /* caller function */ |
616 | L->base = ci->base = ci->func + ((ci+1)->base - pfunc); | 735 | /* last stack slot filled by 'precall' */ |
617 | for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ | 736 | StkId lim = nci->u.l.base + getproto(nfunc)->numparams; |
618 | setobjs2s(L, func+aux, pfunc+aux); | 737 | int aux; |
619 | ci->top = L->top = func+aux; /* correct top */ | 738 | /* close all upvalues from previous call */ |
620 | lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); | 739 | if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); |
621 | ci->savedpc = L->savedpc; | 740 | /* move new frame into old one */ |
622 | ci->tailcalls++; /* one more call lost */ | 741 | for (aux = 0; nfunc + aux < lim; aux++) |
623 | L->ci--; /* remove new frame */ | 742 | setobjs2s(L, ofunc + aux, nfunc + aux); |
624 | goto reentry; | 743 | oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */ |
625 | } | 744 | oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ |
626 | case PCRC: { /* it was a C function (`precall' called it) */ | 745 | oci->u.l.savedpc = nci->u.l.savedpc; |
627 | base = L->base; | 746 | oci->callstatus |= CIST_TAIL; /* function was tail called */ |
628 | continue; | 747 | ci = L->ci = oci; /* remove new frame */ |
629 | } | 748 | lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); |
630 | default: { | 749 | goto newframe; /* restart luaV_execute over new Lua function */ |
631 | return; /* yield */ | ||
632 | } | ||
633 | } | 750 | } |
634 | } | 751 | ) |
635 | case OP_RETURN: { | 752 | vmcasenb(OP_RETURN, |
636 | int b = GETARG_B(i); | 753 | int b = GETARG_B(i); |
637 | if (b != 0) L->top = ra+b-1; | 754 | if (b != 0) L->top = ra+b-1; |
638 | if (L->openupval) luaF_close(L, base); | 755 | if (cl->p->sizep > 0) luaF_close(L, base); |
639 | L->savedpc = pc; | ||
640 | b = luaD_poscall(L, ra); | 756 | b = luaD_poscall(L, ra); |
641 | if (--nexeccalls == 0) /* was previous function running `here'? */ | 757 | if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ |
642 | return; /* no: return */ | 758 | return; /* external invocation: return */ |
643 | else { /* yes: continue its execution */ | 759 | else { /* invocation via reentry: continue execution */ |
644 | if (b) L->top = L->ci->top; | 760 | ci = L->ci; |
645 | lua_assert(isLua(L->ci)); | 761 | if (b) L->top = ci->top; |
646 | lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); | 762 | lua_assert(isLua(ci)); |
647 | goto reentry; | 763 | lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); |
764 | goto newframe; /* restart luaV_execute over new Lua function */ | ||
648 | } | 765 | } |
649 | } | 766 | ) |
650 | case OP_FORLOOP: { | 767 | vmcase(OP_FORLOOP, |
651 | lua_Number step = nvalue(ra+2); | 768 | lua_Number step = nvalue(ra+2); |
652 | lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ | 769 | lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */ |
653 | lua_Number limit = nvalue(ra+1); | 770 | lua_Number limit = nvalue(ra+1); |
654 | if (luai_numlt(0, step) ? luai_numle(idx, limit) | 771 | if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit) |
655 | : luai_numle(limit, idx)) { | 772 | : luai_numle(L, limit, idx)) { |
656 | dojump(L, pc, GETARG_sBx(i)); /* jump back */ | 773 | ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ |
657 | setnvalue(ra, idx); /* update internal index... */ | 774 | setnvalue(ra, idx); /* update internal index... */ |
658 | setnvalue(ra+3, idx); /* ...and external index */ | 775 | setnvalue(ra+3, idx); /* ...and external index */ |
659 | } | 776 | } |
660 | continue; | 777 | ) |
661 | } | 778 | vmcase(OP_FORPREP, |
662 | case OP_FORPREP: { | ||
663 | const TValue *init = ra; | 779 | const TValue *init = ra; |
664 | const TValue *plimit = ra+1; | 780 | const TValue *plimit = ra+1; |
665 | const TValue *pstep = ra+2; | 781 | const TValue *pstep = ra+2; |
666 | L->savedpc = pc; /* next steps may throw errors */ | ||
667 | if (!tonumber(init, ra)) | 782 | if (!tonumber(init, ra)) |
668 | luaG_runerror(L, LUA_QL("for") " initial value must be a number"); | 783 | luaG_runerror(L, LUA_QL("for") " initial value must be a number"); |
669 | else if (!tonumber(plimit, ra+1)) | 784 | else if (!tonumber(plimit, ra+1)) |
670 | luaG_runerror(L, LUA_QL("for") " limit must be a number"); | 785 | luaG_runerror(L, LUA_QL("for") " limit must be a number"); |
671 | else if (!tonumber(pstep, ra+2)) | 786 | else if (!tonumber(pstep, ra+2)) |
672 | luaG_runerror(L, LUA_QL("for") " step must be a number"); | 787 | luaG_runerror(L, LUA_QL("for") " step must be a number"); |
673 | setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); | 788 | setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep))); |
674 | dojump(L, pc, GETARG_sBx(i)); | 789 | ci->u.l.savedpc += GETARG_sBx(i); |
675 | continue; | 790 | ) |
676 | } | 791 | vmcasenb(OP_TFORCALL, |
677 | case OP_TFORLOOP: { | ||
678 | StkId cb = ra + 3; /* call base */ | 792 | StkId cb = ra + 3; /* call base */ |
679 | setobjs2s(L, cb+2, ra+2); | 793 | setobjs2s(L, cb+2, ra+2); |
680 | setobjs2s(L, cb+1, ra+1); | 794 | setobjs2s(L, cb+1, ra+1); |
681 | setobjs2s(L, cb, ra); | 795 | setobjs2s(L, cb, ra); |
682 | L->top = cb+3; /* func. + 2 args (state and index) */ | 796 | L->top = cb + 3; /* func. + 2 args (state and index) */ |
683 | Protect(luaD_call(L, cb, GETARG_C(i))); | 797 | Protect(luaD_call(L, cb, GETARG_C(i), 1)); |
684 | L->top = L->ci->top; | 798 | L->top = ci->top; |
685 | cb = RA(i) + 3; /* previous call may change the stack */ | 799 | i = *(ci->u.l.savedpc++); /* go to next instruction */ |
686 | if (!ttisnil(cb)) { /* continue loop? */ | 800 | ra = RA(i); |
687 | setobjs2s(L, cb-1, cb); /* save control variable */ | 801 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP); |
688 | dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ | 802 | goto l_tforloop; |
803 | ) | ||
804 | vmcase(OP_TFORLOOP, | ||
805 | l_tforloop: | ||
806 | if (!ttisnil(ra + 1)) { /* continue loop? */ | ||
807 | setobjs2s(L, ra, ra + 1); /* save control variable */ | ||
808 | ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ | ||
689 | } | 809 | } |
690 | pc++; | 810 | ) |
691 | continue; | 811 | vmcase(OP_SETLIST, |
692 | } | ||
693 | case OP_SETLIST: { | ||
694 | int n = GETARG_B(i); | 812 | int n = GETARG_B(i); |
695 | int c = GETARG_C(i); | 813 | int c = GETARG_C(i); |
696 | int last; | 814 | int last; |
697 | Table *h; | 815 | Table *h; |
698 | if (n == 0) { | 816 | if (n == 0) n = cast_int(L->top - ra) - 1; |
699 | n = cast_int(L->top - ra) - 1; | 817 | if (c == 0) { |
700 | L->top = L->ci->top; | 818 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); |
819 | c = GETARG_Ax(*ci->u.l.savedpc++); | ||
701 | } | 820 | } |
702 | if (c == 0) c = cast_int(*pc++); | 821 | luai_runtimecheck(L, ttistable(ra)); |
703 | runtime_check(L, ttistable(ra)); | ||
704 | h = hvalue(ra); | 822 | h = hvalue(ra); |
705 | last = ((c-1)*LFIELDS_PER_FLUSH) + n; | 823 | last = ((c-1)*LFIELDS_PER_FLUSH) + n; |
706 | if (last > h->sizearray) /* needs more space? */ | 824 | if (last > h->sizearray) /* needs more space? */ |
707 | luaH_resizearray(L, h, last); /* pre-alloc it at once */ | 825 | luaH_resizearray(L, h, last); /* pre-allocate it at once */ |
708 | for (; n > 0; n--) { | 826 | for (; n > 0; n--) { |
709 | TValue *val = ra+n; | 827 | TValue *val = ra+n; |
710 | setobj2t(L, luaH_setnum(L, h, last--), val); | 828 | luaH_setint(L, h, last--, val); |
711 | luaC_barriert(L, h, val); | 829 | luaC_barrierback(L, obj2gco(h), val); |
712 | } | 830 | } |
713 | continue; | 831 | L->top = ci->top; /* correct top (in case of previous open call) */ |
714 | } | 832 | ) |
715 | case OP_CLOSE: { | 833 | vmcase(OP_CLOSURE, |
716 | luaF_close(L, ra); | 834 | Proto *p = cl->p->p[GETARG_Bx(i)]; |
717 | continue; | 835 | Closure *ncl = getcached(p, cl->upvals, base); /* cached closure */ |
718 | } | 836 | if (ncl == NULL) /* no match? */ |
719 | case OP_CLOSURE: { | 837 | pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ |
720 | Proto *p; | 838 | else |
721 | Closure *ncl; | 839 | setclLvalue(L, ra, ncl); /* push cashed closure */ |
722 | int nup, j; | 840 | checkGC(L, ra + 1); |
723 | p = cl->p->p[GETARG_Bx(i)]; | 841 | ) |
724 | nup = p->nups; | 842 | vmcase(OP_VARARG, |
725 | ncl = luaF_newLclosure(L, nup, cl->env); | ||
726 | ncl->l.p = p; | ||
727 | for (j=0; j<nup; j++, pc++) { | ||
728 | if (GET_OPCODE(*pc) == OP_GETUPVAL) | ||
729 | ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)]; | ||
730 | else { | ||
731 | lua_assert(GET_OPCODE(*pc) == OP_MOVE); | ||
732 | ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); | ||
733 | } | ||
734 | } | ||
735 | setclvalue(L, ra, ncl); | ||
736 | Protect(luaC_checkGC(L)); | ||
737 | continue; | ||
738 | } | ||
739 | case OP_VARARG: { | ||
740 | int b = GETARG_B(i) - 1; | 843 | int b = GETARG_B(i) - 1; |
741 | int j; | 844 | int j; |
742 | CallInfo *ci = L->ci; | 845 | int n = cast_int(base - ci->func) - cl->p->numparams - 1; |
743 | int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; | 846 | if (b < 0) { /* B == 0? */ |
744 | if (b == LUA_MULTRET) { | 847 | b = n; /* get all var. arguments */ |
745 | Protect(luaD_checkstack(L, n)); | 848 | Protect(luaD_checkstack(L, n)); |
746 | ra = RA(i); /* previous call may change the stack */ | 849 | ra = RA(i); /* previous call may change the stack */ |
747 | b = n; | ||
748 | L->top = ra + n; | 850 | L->top = ra + n; |
749 | } | 851 | } |
750 | for (j = 0; j < b; j++) { | 852 | for (j = 0; j < b; j++) { |
751 | if (j < n) { | 853 | if (j < n) { |
752 | setobjs2s(L, ra + j, ci->base - n + j); | 854 | setobjs2s(L, ra + j, base - n + j); |
753 | } | 855 | } |
754 | else { | 856 | else { |
755 | setnilvalue(ra + j); | 857 | setnilvalue(ra + j); |
756 | } | 858 | } |
757 | } | 859 | } |
758 | continue; | 860 | ) |
759 | } | 861 | vmcase(OP_EXTRAARG, |
862 | lua_assert(0); | ||
863 | ) | ||
760 | } | 864 | } |
761 | } | 865 | } |
762 | } | 866 | } |
diff --git a/apps/plugins/lua/lvm.h b/apps/plugins/lua/lvm.h index dff2a139f7..5380270da6 100644 --- a/apps/plugins/lua/lvm.h +++ b/apps/plugins/lua/lvm.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lvm.h,v 2.18.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -13,24 +13,32 @@ | |||
13 | #include "ltm.h" | 13 | #include "ltm.h" |
14 | 14 | ||
15 | 15 | ||
16 | #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) | 16 | #define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) |
17 | 17 | ||
18 | #define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ | 18 | #define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) |
19 | (((o) = luaV_tonumber(o,n)) != NULL)) | ||
20 | 19 | ||
21 | #define equalobj(L,o1,o2) \ | 20 | #define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2)) |
22 | (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) | 21 | |
22 | #define luaV_rawequalobj(o1,o2) equalobj(NULL,o1,o2) | ||
23 | |||
24 | |||
25 | /* not to called directly */ | ||
26 | LUAI_FUNC int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2); | ||
23 | 27 | ||
24 | 28 | ||
25 | LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); | 29 | LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); |
26 | LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); | 30 | LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); |
27 | LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); | 31 | LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); |
28 | LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); | 32 | LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); |
29 | LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, | 33 | LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, |
30 | StkId val); | 34 | StkId val); |
31 | LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, | 35 | LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, |
32 | StkId val); | 36 | StkId val); |
33 | LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); | 37 | LUAI_FUNC void luaV_finishOp (lua_State *L); |
34 | LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); | 38 | LUAI_FUNC void luaV_execute (lua_State *L); |
39 | LUAI_FUNC void luaV_concat (lua_State *L, int total); | ||
40 | LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb, | ||
41 | const TValue *rc, TMS op); | ||
42 | LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); | ||
35 | 43 | ||
36 | #endif | 44 | #endif |
diff --git a/apps/plugins/lua/lzio.c b/apps/plugins/lua/lzio.c index 293edd59b0..20efea9830 100644 --- a/apps/plugins/lua/lzio.c +++ b/apps/plugins/lua/lzio.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ | 2 | ** $Id: lzio.c,v 1.35.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** a generic input stream interface | 3 | ** Buffered streams |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
6 | 6 | ||
@@ -25,23 +25,11 @@ int luaZ_fill (ZIO *z) { | |||
25 | lua_unlock(L); | 25 | lua_unlock(L); |
26 | buff = z->reader(L, z->data, &size); | 26 | buff = z->reader(L, z->data, &size); |
27 | lua_lock(L); | 27 | lua_lock(L); |
28 | if (buff == NULL || size == 0) return EOZ; | 28 | if (buff == NULL || size == 0) |
29 | z->n = size - 1; | 29 | return EOZ; |
30 | z->n = size - 1; /* discount char being returned */ | ||
30 | z->p = buff; | 31 | z->p = buff; |
31 | return char2int(*(z->p++)); | 32 | return cast_uchar(*(z->p++)); |
32 | } | ||
33 | |||
34 | |||
35 | int luaZ_lookahead (ZIO *z) { | ||
36 | if (z->n == 0) { | ||
37 | if (luaZ_fill(z) == EOZ) | ||
38 | return EOZ; | ||
39 | else { | ||
40 | z->n++; /* luaZ_fill removed first byte; put back it */ | ||
41 | z->p--; | ||
42 | } | ||
43 | } | ||
44 | return char2int(*z->p); | ||
45 | } | 33 | } |
46 | 34 | ||
47 | 35 | ||
@@ -58,8 +46,14 @@ void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { | |||
58 | size_t luaZ_read (ZIO *z, void *b, size_t n) { | 46 | size_t luaZ_read (ZIO *z, void *b, size_t n) { |
59 | while (n) { | 47 | while (n) { |
60 | size_t m; | 48 | size_t m; |
61 | if (luaZ_lookahead(z) == EOZ) | 49 | if (z->n == 0) { /* no bytes in buffer? */ |
62 | return n; /* return number of missing bytes */ | 50 | if (luaZ_fill(z) == EOZ) /* try to read more */ |
51 | return n; /* no more input; return number of missing bytes */ | ||
52 | else { | ||
53 | z->n++; /* luaZ_fill consumed first byte; put it back */ | ||
54 | z->p--; | ||
55 | } | ||
56 | } | ||
63 | m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ | 57 | m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ |
64 | memcpy(b, z->p, m); | 58 | memcpy(b, z->p, m); |
65 | z->n -= m; | 59 | z->n -= m; |
diff --git a/apps/plugins/lua/lzio.h b/apps/plugins/lua/lzio.h index 9aa9e4b537..441f7479cb 100644 --- a/apps/plugins/lua/lzio.h +++ b/apps/plugins/lua/lzio.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id$ | 2 | ** $Id: lzio.h,v 1.26.1.1 2013/04/12 18:48:47 roberto Exp $ |
3 | ** Buffered streams | 3 | ** Buffered streams |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -17,9 +17,8 @@ | |||
17 | 17 | ||
18 | typedef struct Zio ZIO; | 18 | typedef struct Zio ZIO; |
19 | 19 | ||
20 | #define char2int(c) cast(int, cast(unsigned char, (c))) | 20 | #define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) |
21 | 21 | ||
22 | #define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) | ||
23 | 22 | ||
24 | typedef struct Mbuffer { | 23 | typedef struct Mbuffer { |
25 | char *buffer; | 24 | char *buffer; |
@@ -47,7 +46,6 @@ LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); | |||
47 | LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, | 46 | LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, |
48 | void *data); | 47 | void *data); |
49 | LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ | 48 | LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ |
50 | LUAI_FUNC int luaZ_lookahead (ZIO *z); | ||
51 | 49 | ||
52 | 50 | ||
53 | 51 | ||
@@ -56,7 +54,7 @@ LUAI_FUNC int luaZ_lookahead (ZIO *z); | |||
56 | struct Zio { | 54 | struct Zio { |
57 | size_t n; /* bytes still unread */ | 55 | size_t n; /* bytes still unread */ |
58 | const char *p; /* current position in buffer */ | 56 | const char *p; /* current position in buffer */ |
59 | lua_Reader reader; | 57 | lua_Reader reader; /* reader function */ |
60 | void* data; /* additional data */ | 58 | void* data; /* additional data */ |
61 | lua_State *L; /* Lua state (for reader) */ | 59 | lua_State *L; /* Lua state (for reader) */ |
62 | }; | 60 | }; |
diff --git a/apps/plugins/lua/rockconf.h b/apps/plugins/lua/rockconf.h index a13146d7e9..eda1e05084 100644 --- a/apps/plugins/lua/rockconf.h +++ b/apps/plugins/lua/rockconf.h | |||
@@ -25,10 +25,6 @@ | |||
25 | #include "plugin.h" | 25 | #include "plugin.h" |
26 | #include <tlsf.h> | 26 | #include <tlsf.h> |
27 | 27 | ||
28 | #undef LUAI_THROW | ||
29 | #undef LUAI_TRY | ||
30 | #undef luai_jmpbuf | ||
31 | |||
32 | #undef LUA_PATH_DEFAULT | 28 | #undef LUA_PATH_DEFAULT |
33 | #define LUA_PATH_DEFAULT "$/?.lua;" "$/?/init.lua;" VIEWERS_DIR"/lua/?.lua;" VIEWERS_DIR"/lua/?/init.lua;" | 29 | #define LUA_PATH_DEFAULT "$/?.lua;" "$/?/init.lua;" VIEWERS_DIR"/lua/?.lua;" VIEWERS_DIR"/lua/?/init.lua;" |
34 | 30 | ||
@@ -36,20 +32,11 @@ | |||
36 | 32 | ||
37 | #include "lib/pluginlib_exit.h" | 33 | #include "lib/pluginlib_exit.h" |
38 | 34 | ||
39 | #define LUAI_THROW(L,c) longjmp((c)->b, 1) | ||
40 | #define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } | ||
41 | #define luai_jmpbuf jmp_buf | ||
42 | |||
43 | extern char curpath[MAX_PATH]; | 35 | extern char curpath[MAX_PATH]; |
44 | struct tm *gmtime(const time_t *timep); | 36 | struct tm *gmtime(const time_t *timep); |
45 | long strtol(const char *nptr, char **endptr, int base); | 37 | long strtol(const char *nptr, char **endptr, int base); |
46 | unsigned long strtoul(const char *str, char **endptr, int base); | 38 | unsigned long strtoul(const char *str, char **endptr, int base); |
47 | size_t strftime(char* dst, size_t max, const char* format, const struct tm* tm); | 39 | size_t strftime(char* dst, size_t max, const char* format, const struct tm* tm); |
48 | long lfloor(long x); | ||
49 | long lpow(long x, long y); | ||
50 | |||
51 | #define floor lfloor | ||
52 | #define pow lpow | ||
53 | 40 | ||
54 | /* Simple substitutions */ | 41 | /* Simple substitutions */ |
55 | #define malloc tlsf_malloc | 42 | #define malloc tlsf_malloc |
@@ -63,5 +50,17 @@ long lpow(long x, long y); | |||
63 | #define strcpy rb->strcpy | 50 | #define strcpy rb->strcpy |
64 | #define strlen rb->strlen | 51 | #define strlen rb->strlen |
65 | 52 | ||
53 | #define getlocaledecpoint() '.' | ||
54 | #define abort() exit(EXIT_FAILURE) | ||
55 | #define difftime(t1,t0) ((t1) - (t0)) | ||
56 | #define localtime gmtime | ||
57 | #if CONFIG_RTC | ||
58 | #define time(x) mktime(rb->get_time()) | ||
59 | #define mktime rb->mktime | ||
60 | #else | ||
61 | #define time(x) (0) | ||
62 | #define mktime(x) (0) | ||
63 | #endif | ||
64 | |||
66 | #endif /* _ROCKCONF_H_ */ | 65 | #endif /* _ROCKCONF_H_ */ |
67 | 66 | ||
diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c index 27c1177748..f214aca694 100644 --- a/apps/plugins/lua/rocklib.c +++ b/apps/plugins/lua/rocklib.c | |||
@@ -156,7 +156,19 @@ static int rli_tostring(lua_State *L) | |||
156 | return 1; | 156 | return 1; |
157 | } | 157 | } |
158 | 158 | ||
159 | static const struct luaL_reg rli_lib [] = | 159 | int rli_checkboolean (lua_State *L, int narg) { |
160 | int b = lua_toboolean(L, narg); | ||
161 | if (b == 0) | ||
162 | luaL_checktype(L, narg, LUA_TBOOLEAN); | ||
163 | return b; | ||
164 | } | ||
165 | |||
166 | |||
167 | int rli_optboolean (lua_State *L, int narg, int def) { | ||
168 | return luaL_opt(L, rli_checkboolean, narg, def); | ||
169 | } | ||
170 | |||
171 | static const struct luaL_Reg rli_lib [] = | ||
160 | { | 172 | { |
161 | {"__tostring", rli_tostring}, | 173 | {"__tostring", rli_tostring}, |
162 | {"set", rli_set}, | 174 | {"set", rli_set}, |
@@ -472,8 +484,8 @@ RB_WRAP(read_bmp_file) | |||
472 | { | 484 | { |
473 | struct bitmap bm; | 485 | struct bitmap bm; |
474 | const char* filename = luaL_checkstring(L, 1); | 486 | const char* filename = luaL_checkstring(L, 1); |
475 | bool dither = luaL_optboolean(L, 2, true); | 487 | bool dither = rli_optboolean(L, 2, true); |
476 | bool transparent = luaL_optboolean(L, 3, false); | 488 | bool transparent = rli_optboolean(L, 3, false); |
477 | int format = FORMAT_NATIVE; | 489 | int format = FORMAT_NATIVE; |
478 | 490 | ||
479 | if(dither) | 491 | if(dither) |
@@ -516,7 +528,7 @@ static void fill_text_message(lua_State *L, struct text_message * message, | |||
516 | { | 528 | { |
517 | int i; | 529 | int i; |
518 | luaL_checktype(L, pos, LUA_TTABLE); | 530 | luaL_checktype(L, pos, LUA_TTABLE); |
519 | int n = luaL_getn(L, pos); | 531 | int n = lua_rawlen(L, pos); |
520 | const char **lines = (const char**) tlsf_malloc(n * sizeof(const char*)); | 532 | const char **lines = (const char**) tlsf_malloc(n * sizeof(const char*)); |
521 | if(lines == NULL) | 533 | if(lines == NULL) |
522 | luaL_error(L, "Can't allocate %d bytes!", n * sizeof(const char*)); | 534 | luaL_error(L, "Can't allocate %d bytes!", n * sizeof(const char*)); |
@@ -565,7 +577,7 @@ RB_WRAP(do_menu) | |||
565 | luaL_checktype(L, 2, LUA_TTABLE); | 577 | luaL_checktype(L, 2, LUA_TTABLE); |
566 | start_selected = luaL_optint(L, 3, 0); | 578 | start_selected = luaL_optint(L, 3, 0); |
567 | 579 | ||
568 | n = luaL_getn(L, 2); | 580 | n = lua_rawlen(L, 2); |
569 | items = (const char**) tlsf_malloc(n * sizeof(const char*)); | 581 | items = (const char**) tlsf_malloc(n * sizeof(const char*)); |
570 | if(items == NULL) | 582 | if(items == NULL) |
571 | luaL_error(L, "Can't allocate %d bytes!", n * sizeof(const char*)); | 583 | luaL_error(L, "Can't allocate %d bytes!", n * sizeof(const char*)); |
@@ -758,8 +770,9 @@ extern const luaL_Reg rocklib_aux[]; | |||
758 | */ | 770 | */ |
759 | LUALIB_API int luaopen_rock(lua_State *L) | 771 | LUALIB_API int luaopen_rock(lua_State *L) |
760 | { | 772 | { |
761 | luaL_register(L, LUA_ROCKLIBNAME, rocklib); | 773 | rli_init(L); |
762 | luaL_register(L, LUA_ROCKLIBNAME, rocklib_aux); | 774 | luaL_newlib(L, rocklib); |
775 | luaL_setfuncs(L, rocklib_aux, 0); | ||
763 | 776 | ||
764 | RB_CONSTANT(HZ); | 777 | RB_CONSTANT(HZ); |
765 | 778 | ||
@@ -797,7 +810,6 @@ LUALIB_API int luaopen_rock(lua_State *L) | |||
797 | RB_STRING_CONSTANT(PLUGIN_DATA_DIR); | 810 | RB_STRING_CONSTANT(PLUGIN_DATA_DIR); |
798 | RB_STRING_CONSTANT(VIEWERS_DATA_DIR); | 811 | RB_STRING_CONSTANT(VIEWERS_DATA_DIR); |
799 | 812 | ||
800 | rli_init(L); | ||
801 | 813 | ||
802 | return 1; | 814 | return 1; |
803 | } | 815 | } |
diff --git a/apps/plugins/lua/rocklib.h b/apps/plugins/lua/rocklib.h index 84b5fd2de0..2b259ee53e 100644 --- a/apps/plugins/lua/rocklib.h +++ b/apps/plugins/lua/rocklib.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #define LUA_ROCKLIBNAME "rb" | 25 | #define LUA_ROCKLIBNAME "rb" |
26 | LUALIB_API int (luaopen_rock) (lua_State *L); | 26 | LUALIB_API int (luaopen_rock) (lua_State *L); |
27 | const char* get_current_path(lua_State *L, int level); | 27 | const char* get_current_path(lua_State *L, int level); |
28 | int rli_checkboolean (lua_State *L, int narg); | ||
28 | 29 | ||
29 | #endif /* _ROCKLIB_H_ */ | 30 | #endif /* _ROCKLIB_H_ */ |
30 | 31 | ||
diff --git a/apps/plugins/lua/rocklib_aux.pl b/apps/plugins/lua/rocklib_aux.pl index 9103fccbda..61e0115bdf 100755 --- a/apps/plugins/lua/rocklib_aux.pl +++ b/apps/plugins/lua/rocklib_aux.pl | |||
@@ -133,6 +133,7 @@ print <<EOF | |||
133 | 133 | ||
134 | #define _ROCKCONF_H_ /* We don't need strcmp() etc. wrappers */ | 134 | #define _ROCKCONF_H_ /* We don't need strcmp() etc. wrappers */ |
135 | #include "lua.h" | 135 | #include "lua.h" |
136 | #include "rocklib.h" | ||
136 | #include "lauxlib.h" | 137 | #include "lauxlib.h" |
137 | #include "plugin.h" | 138 | #include "plugin.h" |
138 | 139 | ||
@@ -207,7 +208,7 @@ sub in_string | |||
207 | sub in_bool | 208 | sub in_bool |
208 | { | 209 | { |
209 | my ($name, $type, $pos) = @_; | 210 | my ($name, $type, $pos) = @_; |
210 | return sprintf("\tbool %s = luaL_checkboolean(L, %d);\n", $name, $pos) | 211 | return sprintf("\tbool %s = rli_checkboolean(L, %d);\n", $name, $pos) |
211 | } | 212 | } |
212 | 213 | ||
213 | sub out_void | 214 | sub out_void |
diff --git a/apps/plugins/lua/rocklibc.h b/apps/plugins/lua/rocklibc.h index 44f916fded..430889bb70 100644 --- a/apps/plugins/lua/rocklibc.h +++ b/apps/plugins/lua/rocklibc.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <errno.h> | 30 | #include <errno.h> |
31 | #define PREFIX(_x_) sim_ ## _x_ | 31 | #define PREFIX(_x_) sim_ ## _x_ |
32 | #else | 32 | #else |
33 | #undef errno | ||
33 | extern int errno; | 34 | extern int errno; |
34 | #define EINVAL 22 /* Invalid argument */ | 35 | #define EINVAL 22 /* Invalid argument */ |
35 | #define ERANGE 34 /* Math result not representable */ | 36 | #define ERANGE 34 /* Math result not representable */ |
@@ -43,7 +44,8 @@ extern int errno; | |||
43 | #define memcmp rb->memcmp | 44 | #define memcmp rb->memcmp |
44 | #define strlen rb->strlen | 45 | #define strlen rb->strlen |
45 | 46 | ||
46 | extern int PREFIX(fscanf)(int fd, const char *fmt, ...); | 47 | extern int PREFIX(fscanf)(void *fd, const char *fmt, ...); |
48 | extern int PREFIX(getc)(int fd); | ||
47 | 49 | ||
48 | #endif /* _ROCKLIBC_H_ */ | 50 | #endif /* _ROCKLIBC_H_ */ |
49 | 51 | ||
diff --git a/apps/plugins/lua/rocklua.c b/apps/plugins/lua/rocklua.c index 5539618a43..4f328dd84a 100644 --- a/apps/plugins/lua/rocklua.c +++ b/apps/plugins/lua/rocklua.c | |||
@@ -26,7 +26,8 @@ | |||
26 | #include "rocklib.h" | 26 | #include "rocklib.h" |
27 | #include "luadir.h" | 27 | #include "luadir.h" |
28 | 28 | ||
29 | 29 | #undef LUA_BITLIBNAME | |
30 | #define LUA_BITLIBNAME "bit" | ||
30 | 31 | ||
31 | static const luaL_Reg lualibs[] = { | 32 | static const luaL_Reg lualibs[] = { |
32 | {"", luaopen_base}, | 33 | {"", luaopen_base}, |
@@ -34,7 +35,7 @@ static const luaL_Reg lualibs[] = { | |||
34 | {LUA_STRLIBNAME, luaopen_string}, | 35 | {LUA_STRLIBNAME, luaopen_string}, |
35 | {LUA_OSLIBNAME, luaopen_os}, | 36 | {LUA_OSLIBNAME, luaopen_os}, |
36 | {LUA_ROCKLIBNAME, luaopen_rock}, | 37 | {LUA_ROCKLIBNAME, luaopen_rock}, |
37 | {LUA_BITLIBNAME, luaopen_bit}, | 38 | {LUA_BITLIBNAME, luaopen_bit32}, |
38 | {LUA_IOLIBNAME, luaopen_io}, | 39 | {LUA_IOLIBNAME, luaopen_io}, |
39 | {LUA_LOADLIBNAME, luaopen_package}, | 40 | {LUA_LOADLIBNAME, luaopen_package}, |
40 | {LUA_MATHLIBNAME, luaopen_math}, | 41 | {LUA_MATHLIBNAME, luaopen_math}, |
@@ -43,11 +44,10 @@ static const luaL_Reg lualibs[] = { | |||
43 | }; | 44 | }; |
44 | 45 | ||
45 | static void rocklua_openlibs(lua_State *L) { | 46 | static void rocklua_openlibs(lua_State *L) { |
46 | const luaL_Reg *lib = lualibs; | 47 | const luaL_Reg *lib; |
47 | for (; lib->func; lib++) { | 48 | for (lib = lualibs; lib->func; lib++) { |
48 | lua_pushcfunction(L, lib->func); | 49 | luaL_requiref(L, lib->name, lib->func, 1); |
49 | lua_pushstring(L, lib->name); | 50 | lua_pop(L, 1); /* remove lib */ |
50 | lua_call(L, 1, 0); | ||
51 | } | 51 | } |
52 | } | 52 | } |
53 | 53 | ||
diff --git a/apps/plugins/lua/strcspn.c b/apps/plugins/lua/strcspn.c deleted file mode 100644 index 0a19eaebf2..0000000000 --- a/apps/plugins/lua/strcspn.c +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | #include "rocklibc.h" | ||
2 | |||
3 | #undef strcspn | ||
4 | size_t strcspn(const char *s, const char *reject) | ||
5 | { | ||
6 | size_t l=0; | ||
7 | int a=1,i,al=strlen(reject); | ||
8 | |||
9 | while((a)&&(*s)) | ||
10 | { | ||
11 | for(i=0;(a)&&(i<al);i++) | ||
12 | if (*s==reject[i]) a=0; | ||
13 | if (a) l++; | ||
14 | s++; | ||
15 | } | ||
16 | return l; | ||
17 | } | ||
diff --git a/apps/plugins/lua/strspn.c b/apps/plugins/lua/strspn.c new file mode 100644 index 0000000000..e95500a1dc --- /dev/null +++ b/apps/plugins/lua/strspn.c | |||
@@ -0,0 +1,19 @@ | |||
1 | #include "rocklibc.h" | ||
2 | |||
3 | #undef strspn | ||
4 | |||
5 | size_t strspn(const char *s, const char *accept) | ||
6 | { | ||
7 | size_t count; | ||
8 | for (count = 0; *s != 0; s++, count++) { | ||
9 | const char *ac; | ||
10 | for (ac = accept; *ac != 0; ac++) { | ||
11 | if (*ac == *s) | ||
12 | break; | ||
13 | } | ||
14 | if (*ac == 0) /* no acceptable char found */ | ||
15 | break; | ||
16 | } | ||
17 | return count; | ||
18 | } | ||
19 | |||