diff options
Diffstat (limited to 'apps/plugins/lua')
64 files changed, 5483 insertions, 8838 deletions
diff --git a/apps/plugins/lua/SOURCES b/apps/plugins/lua/SOURCES index e3d9947e1e..baebfabe65 100644 --- a/apps/plugins/lua/SOURCES +++ b/apps/plugins/lua/SOURCES | |||
@@ -31,13 +31,12 @@ rocklib.c | |||
31 | tlsf_helper.c | 31 | tlsf_helper.c |
32 | fscanf.c | 32 | fscanf.c |
33 | gmtime.c | 33 | gmtime.c |
34 | strspn.c | 34 | strcspn.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 | ||
42 | rocklua.c | 41 | rocklua.c |
43 | luadir.c | 42 | luadir.c |
diff --git a/apps/plugins/lua/fscanf.c b/apps/plugins/lua/fscanf.c index ee42daeab7..9f5f129d3c 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)(void *fd, const char *fmt, ...) | 282 | int PREFIX(fscanf)(int 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 deleted file mode 100644 index 84a280e2c2..0000000000 --- a/apps/plugins/lua/getc.c +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
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 d011431ead..487d6b173a 100644 --- a/apps/plugins/lua/lapi.c +++ b/apps/plugins/lua/lapi.c | |||
@@ -1,10 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 2.171.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 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> | ||
8 | #include <stdarg.h> | 10 | #include <stdarg.h> |
9 | #include <string.h> | 11 | #include <string.h> |
10 | 12 | ||
@@ -30,80 +32,76 @@ | |||
30 | 32 | ||
31 | 33 | ||
32 | const char lua_ident[] = | 34 | const char lua_ident[] = |
33 | "$LuaVersion: " LUA_COPYRIGHT " $" | 35 | "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" |
34 | "$LuaAuthors: " LUA_AUTHORS " $"; | 36 | "$Authors: " LUA_AUTHORS " $\n" |
37 | "$URL: www.lua.org $\n"; | ||
35 | 38 | ||
36 | 39 | ||
37 | /* value at a non-valid index */ | ||
38 | #define NONVALIDVALUE cast(TValue *, luaO_nilobject) | ||
39 | 40 | ||
40 | /* corresponding test */ | 41 | #define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) |
41 | #define isvalid(o) ((o) != luaO_nilobject) | ||
42 | 42 | ||
43 | /* test for pseudo index */ | 43 | #define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) |
44 | #define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) | ||
45 | 44 | ||
46 | /* test for valid but not pseudo index */ | 45 | #define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} |
47 | #define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) | ||
48 | 46 | ||
49 | #define api_checkvalidindex(L, o) api_check(L, isvalid(o), "invalid index") | ||
50 | 47 | ||
51 | #define api_checkstackindex(L, i, o) \ | ||
52 | api_check(L, isstackindex(i, o), "index not in the stack") | ||
53 | 48 | ||
54 | 49 | static TValue *index2adr (lua_State *L, int idx) { | |
55 | static TValue *index2addr (lua_State *L, int idx) { | ||
56 | CallInfo *ci = L->ci; | ||
57 | if (idx > 0) { | 50 | if (idx > 0) { |
58 | TValue *o = ci->func + idx; | 51 | TValue *o = L->base + (idx - 1); |
59 | api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); | 52 | api_check(L, idx <= L->ci->top - L->base); |
60 | if (o >= L->top) return NONVALIDVALUE; | 53 | if (o >= L->top) return cast(TValue *, luaO_nilobject); |
61 | else return o; | 54 | else return o; |
62 | } | 55 | } |
63 | else if (!ispseudo(idx)) { /* negative index */ | 56 | else if (idx > LUA_REGISTRYINDEX) { |
64 | api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); | 57 | api_check(L, idx != 0 && -idx <= L->top - L->base); |
65 | return L->top + idx; | 58 | return L->top + idx; |
66 | } | 59 | } |
67 | else if (idx == LUA_REGISTRYINDEX) | 60 | else switch (idx) { /* pseudo-indices */ |
68 | return &G(L)->l_registry; | 61 | case LUA_REGISTRYINDEX: return registry(L); |
69 | else { /* upvalues */ | 62 | case LUA_ENVIRONINDEX: { |
70 | idx = LUA_REGISTRYINDEX - idx; | 63 | Closure *func = curr_func(L); |
71 | api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); | 64 | sethvalue(L, &L->env, func->c.env); |
72 | if (ttislcf(ci->func)) /* light C function? */ | 65 | return &L->env; |
73 | return NONVALIDVALUE; /* it has no upvalues */ | 66 | } |
74 | else { | 67 | case LUA_GLOBALSINDEX: return gt(L); |
75 | CClosure *func = clCvalue(ci->func); | 68 | default: { |
76 | return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; | 69 | Closure *func = curr_func(L); |
70 | idx = LUA_GLOBALSINDEX - idx; | ||
71 | return (idx <= func->c.nupvalues) | ||
72 | ? &func->c.upvalue[idx-1] | ||
73 | : cast(TValue *, luaO_nilobject); | ||
77 | } | 74 | } |
78 | } | 75 | } |
79 | } | 76 | } |
80 | 77 | ||
81 | 78 | ||
82 | /* | 79 | static Table *getcurrenv (lua_State *L) { |
83 | ** to be called by 'lua_checkstack' in protected mode, to grow stack | 80 | if (L->ci == L->base_ci) /* no enclosing function? */ |
84 | ** capturing memory errors | 81 | return hvalue(gt(L)); /* use global table as environment */ |
85 | */ | 82 | else { |
86 | static void growstack (lua_State *L, void *ud) { | 83 | Closure *func = curr_func(L); |
87 | int size = *(int *)ud; | 84 | return func->c.env; |
88 | luaD_growstack(L, size); | 85 | } |
86 | } | ||
87 | |||
88 | |||
89 | void luaA_pushobject (lua_State *L, const TValue *o) { | ||
90 | setobj2s(L, L->top, o); | ||
91 | api_incr_top(L); | ||
89 | } | 92 | } |
90 | 93 | ||
91 | 94 | ||
92 | LUA_API int lua_checkstack (lua_State *L, int size) { | 95 | LUA_API int lua_checkstack (lua_State *L, int size) { |
93 | int res; | 96 | int res = 1; |
94 | CallInfo *ci = L->ci; | ||
95 | lua_lock(L); | 97 | lua_lock(L); |
96 | if (L->stack_last - L->top > size) /* stack large enough? */ | 98 | if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) |
97 | res = 1; /* yes; check is OK */ | 99 | res = 0; /* stack overflow */ |
98 | else { /* no; need to grow stack */ | 100 | else if (size > 0) { |
99 | int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; | 101 | luaD_checkstack(L, size); |
100 | if (inuse > LUAI_MAXSTACK - size) /* can grow without overflow? */ | 102 | if (L->ci->top < L->top + size) |
101 | res = 0; /* no */ | 103 | L->ci->top = L->top + size; |
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 */ | ||
107 | lua_unlock(L); | 105 | lua_unlock(L); |
108 | return res; | 106 | return res; |
109 | } | 107 | } |
@@ -114,8 +112,8 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { | |||
114 | if (from == to) return; | 112 | if (from == to) return; |
115 | lua_lock(to); | 113 | lua_lock(to); |
116 | api_checknelems(from, n); | 114 | api_checknelems(from, n); |
117 | api_check(from, G(from) == G(to), "moving among independent states"); | 115 | api_check(from, G(from) == G(to)); |
118 | api_check(from, to->ci->top - to->top >= n, "not enough elements to move"); | 116 | api_check(from, to->ci->top - to->top >= n); |
119 | from->top -= n; | 117 | from->top -= n; |
120 | for (i = 0; i < n; i++) { | 118 | for (i = 0; i < n; i++) { |
121 | setobj2s(to, to->top++, from->top + i); | 119 | setobj2s(to, to->top++, from->top + i); |
@@ -124,6 +122,11 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { | |||
124 | } | 122 | } |
125 | 123 | ||
126 | 124 | ||
125 | LUA_API void lua_setlevel (lua_State *from, lua_State *to) { | ||
126 | to->nCcalls = from->nCcalls; | ||
127 | } | ||
128 | |||
129 | |||
127 | LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { | 130 | LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { |
128 | lua_CFunction old; | 131 | lua_CFunction old; |
129 | lua_lock(L); | 132 | lua_lock(L); |
@@ -134,10 +137,16 @@ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { | |||
134 | } | 137 | } |
135 | 138 | ||
136 | 139 | ||
137 | LUA_API const lua_Number *lua_version (lua_State *L) { | 140 | LUA_API lua_State *lua_newthread (lua_State *L) { |
138 | static const lua_Number version = LUA_VERSION_NUM; | 141 | lua_State *L1; |
139 | if (L == NULL) return &version; | 142 | lua_lock(L); |
140 | else return G(L)->version; | 143 | luaC_checkGC(L); |
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; | ||
141 | } | 150 | } |
142 | 151 | ||
143 | 152 | ||
@@ -147,32 +156,21 @@ LUA_API const lua_Number *lua_version (lua_State *L) { | |||
147 | */ | 156 | */ |
148 | 157 | ||
149 | 158 | ||
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 | |||
160 | LUA_API int lua_gettop (lua_State *L) { | 159 | LUA_API int lua_gettop (lua_State *L) { |
161 | return cast_int(L->top - (L->ci->func + 1)); | 160 | return cast_int(L->top - L->base); |
162 | } | 161 | } |
163 | 162 | ||
164 | 163 | ||
165 | LUA_API void lua_settop (lua_State *L, int idx) { | 164 | LUA_API void lua_settop (lua_State *L, int idx) { |
166 | StkId func = L->ci->func; | ||
167 | lua_lock(L); | 165 | lua_lock(L); |
168 | if (idx >= 0) { | 166 | if (idx >= 0) { |
169 | api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); | 167 | api_check(L, idx <= L->stack_last - L->base); |
170 | while (L->top < (func + 1) + idx) | 168 | while (L->top < L->base + idx) |
171 | setnilvalue(L->top++); | 169 | setnilvalue(L->top++); |
172 | L->top = (func + 1) + idx; | 170 | L->top = L->base + idx; |
173 | } | 171 | } |
174 | else { | 172 | else { |
175 | api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); | 173 | api_check(L, -(idx+1) <= (L->top - L->base)); |
176 | L->top += idx+1; /* `subtract' index (index is negative) */ | 174 | L->top += idx+1; /* `subtract' index (index is negative) */ |
177 | } | 175 | } |
178 | lua_unlock(L); | 176 | lua_unlock(L); |
@@ -182,8 +180,8 @@ LUA_API void lua_settop (lua_State *L, int idx) { | |||
182 | LUA_API void lua_remove (lua_State *L, int idx) { | 180 | LUA_API void lua_remove (lua_State *L, int idx) { |
183 | StkId p; | 181 | StkId p; |
184 | lua_lock(L); | 182 | lua_lock(L); |
185 | p = index2addr(L, idx); | 183 | p = index2adr(L, idx); |
186 | api_checkstackindex(L, idx, p); | 184 | api_checkvalidindex(L, p); |
187 | while (++p < L->top) setobjs2s(L, p-1, p); | 185 | while (++p < L->top) setobjs2s(L, p-1, p); |
188 | L->top--; | 186 | L->top--; |
189 | lua_unlock(L); | 187 | lua_unlock(L); |
@@ -194,47 +192,42 @@ LUA_API void lua_insert (lua_State *L, int idx) { | |||
194 | StkId p; | 192 | StkId p; |
195 | StkId q; | 193 | StkId q; |
196 | lua_lock(L); | 194 | lua_lock(L); |
197 | p = index2addr(L, idx); | 195 | p = index2adr(L, idx); |
198 | api_checkstackindex(L, idx, p); | 196 | api_checkvalidindex(L, p); |
199 | for (q = L->top; q > p; q--) /* use L->top as a temporary */ | 197 | for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); |
200 | setobjs2s(L, q, q - 1); | ||
201 | setobjs2s(L, p, L->top); | 198 | setobjs2s(L, p, L->top); |
202 | lua_unlock(L); | 199 | lua_unlock(L); |
203 | } | 200 | } |
204 | 201 | ||
205 | 202 | ||
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 | |||
217 | LUA_API void lua_replace (lua_State *L, int idx) { | 203 | LUA_API void lua_replace (lua_State *L, int idx) { |
204 | StkId o; | ||
218 | lua_lock(L); | 205 | 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"); | ||
219 | api_checknelems(L, 1); | 209 | api_checknelems(L, 1); |
220 | moveto(L, L->top - 1, idx); | 210 | o = index2adr(L, 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 | } | ||
221 | L->top--; | 223 | L->top--; |
222 | lua_unlock(L); | 224 | lua_unlock(L); |
223 | } | 225 | } |
224 | 226 | ||
225 | 227 | ||
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 | |||
235 | LUA_API void lua_pushvalue (lua_State *L, int idx) { | 228 | LUA_API void lua_pushvalue (lua_State *L, int idx) { |
236 | lua_lock(L); | 229 | lua_lock(L); |
237 | setobj2s(L, L->top, index2addr(L, idx)); | 230 | setobj2s(L, L->top, index2adr(L, idx)); |
238 | api_incr_top(L); | 231 | api_incr_top(L); |
239 | lua_unlock(L); | 232 | lua_unlock(L); |
240 | } | 233 | } |
@@ -247,26 +240,26 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) { | |||
247 | 240 | ||
248 | 241 | ||
249 | LUA_API int lua_type (lua_State *L, int idx) { | 242 | LUA_API int lua_type (lua_State *L, int idx) { |
250 | StkId o = index2addr(L, idx); | 243 | StkId o = index2adr(L, idx); |
251 | return (isvalid(o) ? ttypenv(o) : LUA_TNONE); | 244 | return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); |
252 | } | 245 | } |
253 | 246 | ||
254 | 247 | ||
255 | LUA_API const char *lua_typename (lua_State *L, int t) { | 248 | LUA_API const char *lua_typename (lua_State *L, int t) { |
256 | UNUSED(L); | 249 | UNUSED(L); |
257 | return ttypename(t); | 250 | return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; |
258 | } | 251 | } |
259 | 252 | ||
260 | 253 | ||
261 | LUA_API int lua_iscfunction (lua_State *L, int idx) { | 254 | LUA_API int lua_iscfunction (lua_State *L, int idx) { |
262 | StkId o = index2addr(L, idx); | 255 | StkId o = index2adr(L, idx); |
263 | return (ttislcf(o) || (ttisCclosure(o))); | 256 | return iscfunction(o); |
264 | } | 257 | } |
265 | 258 | ||
266 | 259 | ||
267 | LUA_API int lua_isnumber (lua_State *L, int idx) { | 260 | LUA_API int lua_isnumber (lua_State *L, int idx) { |
268 | TValue n; | 261 | TValue n; |
269 | const TValue *o = index2addr(L, idx); | 262 | const TValue *o = index2adr(L, idx); |
270 | return tonumber(o, &n); | 263 | return tonumber(o, &n); |
271 | } | 264 | } |
272 | 265 | ||
@@ -278,116 +271,77 @@ LUA_API int lua_isstring (lua_State *L, int idx) { | |||
278 | 271 | ||
279 | 272 | ||
280 | LUA_API int lua_isuserdata (lua_State *L, int idx) { | 273 | LUA_API int lua_isuserdata (lua_State *L, int idx) { |
281 | const TValue *o = index2addr(L, idx); | 274 | const TValue *o = index2adr(L, idx); |
282 | return (ttisuserdata(o) || ttislightuserdata(o)); | 275 | return (ttisuserdata(o) || ttislightuserdata(o)); |
283 | } | 276 | } |
284 | 277 | ||
285 | 278 | ||
286 | LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { | 279 | LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { |
287 | StkId o1 = index2addr(L, index1); | 280 | StkId o1 = index2adr(L, index1); |
288 | StkId o2 = index2addr(L, index2); | 281 | StkId o2 = index2adr(L, index2); |
289 | return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; | 282 | return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 |
283 | : luaO_rawequalObj(o1, o2); | ||
290 | } | 284 | } |
291 | 285 | ||
292 | 286 | ||
293 | LUA_API void lua_arith (lua_State *L, int op) { | 287 | LUA_API int lua_equal (lua_State *L, int index1, int index2) { |
294 | StkId o1; /* 1st operand */ | 288 | StkId o1, o2; |
295 | StkId o2; /* 2nd operand */ | 289 | int i; |
296 | lua_lock(L); | 290 | lua_lock(L); /* may call tag method */ |
297 | if (op != LUA_OPUNM) /* all other operations expect two operands */ | 291 | o1 = index2adr(L, index1); |
298 | api_checknelems(L, 2); | 292 | o2 = index2adr(L, index2); |
299 | else { /* for unary minus, add fake 2nd operand */ | 293 | i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); |
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--; | ||
312 | lua_unlock(L); | 294 | lua_unlock(L); |
295 | return i; | ||
313 | } | 296 | } |
314 | 297 | ||
315 | 298 | ||
316 | LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { | 299 | LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { |
317 | StkId o1, o2; | 300 | StkId o1, o2; |
318 | int i = 0; | 301 | int i; |
319 | lua_lock(L); /* may call tag method */ | 302 | lua_lock(L); /* may call tag method */ |
320 | o1 = index2addr(L, index1); | 303 | o1 = index2adr(L, index1); |
321 | o2 = index2addr(L, index2); | 304 | o2 = index2adr(L, index2); |
322 | if (isvalid(o1) && isvalid(o2)) { | 305 | i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 |
323 | switch (op) { | 306 | : luaV_lessthan(L, o1, o2); |
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 | } | ||
330 | lua_unlock(L); | 307 | lua_unlock(L); |
331 | return i; | 308 | return i; |
332 | } | 309 | } |
333 | 310 | ||
334 | 311 | ||
335 | LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) { | 312 | |
313 | LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { | ||
336 | TValue n; | 314 | TValue n; |
337 | const TValue *o = index2addr(L, idx); | 315 | const TValue *o = index2adr(L, idx); |
338 | if (tonumber(o, &n)) { | 316 | if (tonumber(o, &n)) |
339 | if (isnum) *isnum = 1; | ||
340 | return nvalue(o); | 317 | return nvalue(o); |
341 | } | 318 | else |
342 | else { | ||
343 | if (isnum) *isnum = 0; | ||
344 | return 0; | 319 | return 0; |
345 | } | ||
346 | } | 320 | } |
347 | 321 | ||
348 | 322 | ||
349 | LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) { | 323 | LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { |
350 | TValue n; | 324 | TValue n; |
351 | const TValue *o = index2addr(L, idx); | 325 | const TValue *o = index2adr(L, idx); |
352 | if (tonumber(o, &n)) { | 326 | if (tonumber(o, &n)) { |
353 | lua_Integer res; | 327 | lua_Integer res; |
354 | lua_Number num = nvalue(o); | 328 | lua_Number num = nvalue(o); |
355 | lua_number2integer(res, num); | 329 | lua_number2integer(res, num); |
356 | if (isnum) *isnum = 1; | ||
357 | return res; | ||
358 | } | ||
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; | 330 | return res; |
375 | } | 331 | } |
376 | else { | 332 | else |
377 | if (isnum) *isnum = 0; | ||
378 | return 0; | 333 | return 0; |
379 | } | ||
380 | } | 334 | } |
381 | 335 | ||
382 | 336 | ||
383 | LUA_API int lua_toboolean (lua_State *L, int idx) { | 337 | LUA_API int lua_toboolean (lua_State *L, int idx) { |
384 | const TValue *o = index2addr(L, idx); | 338 | const TValue *o = index2adr(L, idx); |
385 | return !l_isfalse(o); | 339 | return !l_isfalse(o); |
386 | } | 340 | } |
387 | 341 | ||
388 | 342 | ||
389 | LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { | 343 | LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { |
390 | StkId o = index2addr(L, idx); | 344 | StkId o = index2adr(L, idx); |
391 | if (!ttisstring(o)) { | 345 | if (!ttisstring(o)) { |
392 | lua_lock(L); /* `luaV_tostring' may create a new string */ | 346 | lua_lock(L); /* `luaV_tostring' may create a new string */ |
393 | if (!luaV_tostring(L, o)) { /* conversion failed? */ | 347 | if (!luaV_tostring(L, o)) { /* conversion failed? */ |
@@ -396,7 +350,7 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { | |||
396 | return NULL; | 350 | return NULL; |
397 | } | 351 | } |
398 | luaC_checkGC(L); | 352 | luaC_checkGC(L); |
399 | o = index2addr(L, idx); /* previous call may reallocate the stack */ | 353 | o = index2adr(L, idx); /* previous call may reallocate the stack */ |
400 | lua_unlock(L); | 354 | lua_unlock(L); |
401 | } | 355 | } |
402 | if (len != NULL) *len = tsvalue(o)->len; | 356 | if (len != NULL) *len = tsvalue(o)->len; |
@@ -404,29 +358,33 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { | |||
404 | } | 358 | } |
405 | 359 | ||
406 | 360 | ||
407 | LUA_API size_t lua_rawlen (lua_State *L, int idx) { | 361 | LUA_API size_t lua_objlen (lua_State *L, int idx) { |
408 | StkId o = index2addr(L, idx); | 362 | StkId o = index2adr(L, idx); |
409 | switch (ttypenv(o)) { | 363 | switch (ttype(o)) { |
410 | case LUA_TSTRING: return tsvalue(o)->len; | 364 | case LUA_TSTRING: return tsvalue(o)->len; |
411 | case LUA_TUSERDATA: return uvalue(o)->len; | 365 | case LUA_TUSERDATA: return uvalue(o)->len; |
412 | case LUA_TTABLE: return luaH_getn(hvalue(o)); | 366 | 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 | } | ||
413 | default: return 0; | 374 | default: return 0; |
414 | } | 375 | } |
415 | } | 376 | } |
416 | 377 | ||
417 | 378 | ||
418 | LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { | 379 | LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { |
419 | StkId o = index2addr(L, idx); | 380 | StkId o = index2adr(L, idx); |
420 | if (ttislcf(o)) return fvalue(o); | 381 | return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; |
421 | else if (ttisCclosure(o)) | ||
422 | return clCvalue(o)->f; | ||
423 | else return NULL; /* not a C function */ | ||
424 | } | 382 | } |
425 | 383 | ||
426 | 384 | ||
427 | LUA_API void *lua_touserdata (lua_State *L, int idx) { | 385 | LUA_API void *lua_touserdata (lua_State *L, int idx) { |
428 | StkId o = index2addr(L, idx); | 386 | StkId o = index2adr(L, idx); |
429 | switch (ttypenv(o)) { | 387 | switch (ttype(o)) { |
430 | case LUA_TUSERDATA: return (rawuvalue(o) + 1); | 388 | case LUA_TUSERDATA: return (rawuvalue(o) + 1); |
431 | case LUA_TLIGHTUSERDATA: return pvalue(o); | 389 | case LUA_TLIGHTUSERDATA: return pvalue(o); |
432 | default: return NULL; | 390 | default: return NULL; |
@@ -435,18 +393,16 @@ LUA_API void *lua_touserdata (lua_State *L, int idx) { | |||
435 | 393 | ||
436 | 394 | ||
437 | LUA_API lua_State *lua_tothread (lua_State *L, int idx) { | 395 | LUA_API lua_State *lua_tothread (lua_State *L, int idx) { |
438 | StkId o = index2addr(L, idx); | 396 | StkId o = index2adr(L, idx); |
439 | return (!ttisthread(o)) ? NULL : thvalue(o); | 397 | return (!ttisthread(o)) ? NULL : thvalue(o); |
440 | } | 398 | } |
441 | 399 | ||
442 | 400 | ||
443 | LUA_API const void *lua_topointer (lua_State *L, int idx) { | 401 | LUA_API const void *lua_topointer (lua_State *L, int idx) { |
444 | StkId o = index2addr(L, idx); | 402 | StkId o = index2adr(L, idx); |
445 | switch (ttype(o)) { | 403 | switch (ttype(o)) { |
446 | case LUA_TTABLE: return hvalue(o); | 404 | case LUA_TTABLE: return hvalue(o); |
447 | case LUA_TLCL: return clLvalue(o); | 405 | case LUA_TFUNCTION: return clvalue(o); |
448 | case LUA_TCCL: return clCvalue(o); | ||
449 | case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); | ||
450 | case LUA_TTHREAD: return thvalue(o); | 406 | case LUA_TTHREAD: return thvalue(o); |
451 | case LUA_TUSERDATA: | 407 | case LUA_TUSERDATA: |
452 | case LUA_TLIGHTUSERDATA: | 408 | case LUA_TLIGHTUSERDATA: |
@@ -473,8 +429,6 @@ LUA_API void lua_pushnil (lua_State *L) { | |||
473 | LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { | 429 | LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { |
474 | lua_lock(L); | 430 | lua_lock(L); |
475 | setnvalue(L->top, n); | 431 | setnvalue(L->top, n); |
476 | luai_checknum(L, L->top, | ||
477 | luaG_runerror(L, "C API - attempt to push a signaling NaN")); | ||
478 | api_incr_top(L); | 432 | api_incr_top(L); |
479 | lua_unlock(L); | 433 | lua_unlock(L); |
480 | } | 434 | } |
@@ -488,43 +442,20 @@ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { | |||
488 | } | 442 | } |
489 | 443 | ||
490 | 444 | ||
491 | LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) { | 445 | LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { |
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; | ||
503 | lua_lock(L); | 446 | lua_lock(L); |
504 | luaC_checkGC(L); | 447 | luaC_checkGC(L); |
505 | ts = luaS_newlstr(L, s, len); | 448 | setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); |
506 | setsvalue2s(L, L->top, ts); | ||
507 | api_incr_top(L); | 449 | api_incr_top(L); |
508 | lua_unlock(L); | 450 | lua_unlock(L); |
509 | return getstr(ts); | ||
510 | } | 451 | } |
511 | 452 | ||
512 | 453 | ||
513 | LUA_API const char *lua_pushstring (lua_State *L, const char *s) { | 454 | LUA_API void lua_pushstring (lua_State *L, const char *s) { |
514 | if (s == NULL) { | 455 | if (s == NULL) |
515 | lua_pushnil(L); | 456 | lua_pushnil(L); |
516 | return NULL; | 457 | else |
517 | } | 458 | lua_pushlstring(L, s, strlen(s)); |
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 | } | ||
528 | } | 459 | } |
529 | 460 | ||
530 | 461 | ||
@@ -553,22 +484,17 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { | |||
553 | 484 | ||
554 | 485 | ||
555 | LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { | 486 | LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { |
487 | Closure *cl; | ||
556 | lua_lock(L); | 488 | lua_lock(L); |
557 | if (n == 0) { | 489 | luaC_checkGC(L); |
558 | setfvalue(L->top, fn); | 490 | api_checknelems(L, n); |
559 | } | 491 | cl = luaF_newCclosure(L, n, getcurrenv(L)); |
560 | else { | 492 | cl->c.f = fn; |
561 | Closure *cl; | 493 | L->top -= n; |
562 | api_checknelems(L, n); | 494 | while (n--) |
563 | api_check(L, n <= MAXUPVAL, "upvalue index too large"); | 495 | setobj2n(L, &cl->c.upvalue[n], L->top+n); |
564 | luaC_checkGC(L); | 496 | setclvalue(L, L->top, cl); |
565 | cl = luaF_newCclosure(L, n); | 497 | lua_assert(iswhite(obj2gco(cl))); |
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 | } | ||
572 | api_incr_top(L); | 498 | api_incr_top(L); |
573 | lua_unlock(L); | 499 | lua_unlock(L); |
574 | } | 500 | } |
@@ -605,21 +531,11 @@ LUA_API int lua_pushthread (lua_State *L) { | |||
605 | */ | 531 | */ |
606 | 532 | ||
607 | 533 | ||
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 | |||
619 | LUA_API void lua_gettable (lua_State *L, int idx) { | 534 | LUA_API void lua_gettable (lua_State *L, int idx) { |
620 | StkId t; | 535 | StkId t; |
621 | lua_lock(L); | 536 | lua_lock(L); |
622 | t = index2addr(L, idx); | 537 | t = index2adr(L, idx); |
538 | api_checkvalidindex(L, t); | ||
623 | luaV_gettable(L, t, L->top - 1, L->top - 1); | 539 | luaV_gettable(L, t, L->top - 1, L->top - 1); |
624 | lua_unlock(L); | 540 | lua_unlock(L); |
625 | } | 541 | } |
@@ -627,11 +543,13 @@ LUA_API void lua_gettable (lua_State *L, int idx) { | |||
627 | 543 | ||
628 | LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { | 544 | LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { |
629 | StkId t; | 545 | StkId t; |
546 | TValue key; | ||
630 | lua_lock(L); | 547 | lua_lock(L); |
631 | t = index2addr(L, idx); | 548 | t = index2adr(L, idx); |
632 | setsvalue2s(L, L->top, luaS_new(L, k)); | 549 | api_checkvalidindex(L, t); |
550 | setsvalue(L, &key, luaS_new(L, k)); | ||
551 | luaV_gettable(L, t, &key, L->top); | ||
633 | api_incr_top(L); | 552 | api_incr_top(L); |
634 | luaV_gettable(L, t, L->top - 1, L->top - 1); | ||
635 | lua_unlock(L); | 553 | lua_unlock(L); |
636 | } | 554 | } |
637 | 555 | ||
@@ -639,46 +557,29 @@ LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { | |||
639 | LUA_API void lua_rawget (lua_State *L, int idx) { | 557 | LUA_API void lua_rawget (lua_State *L, int idx) { |
640 | StkId t; | 558 | StkId t; |
641 | lua_lock(L); | 559 | lua_lock(L); |
642 | t = index2addr(L, idx); | 560 | t = index2adr(L, idx); |
643 | api_check(L, ttistable(t), "table expected"); | 561 | api_check(L, ttistable(t)); |
644 | setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); | 562 | setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); |
645 | lua_unlock(L); | 563 | lua_unlock(L); |
646 | } | 564 | } |
647 | 565 | ||
648 | 566 | ||
649 | LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { | 567 | LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { |
650 | StkId t; | 568 | StkId o; |
651 | lua_lock(L); | ||
652 | t = index2addr(L, idx); | ||
653 | api_check(L, ttistable(t), "table expected"); | ||
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); | 569 | lua_lock(L); |
664 | t = index2addr(L, idx); | 570 | o = index2adr(L, idx); |
665 | api_check(L, ttistable(t), "table expected"); | 571 | api_check(L, ttistable(o)); |
666 | setpvalue(&k, cast(void *, p)); | 572 | setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); |
667 | setobj2s(L, L->top, luaH_get(hvalue(t), &k)); | ||
668 | api_incr_top(L); | 573 | api_incr_top(L); |
669 | lua_unlock(L); | 574 | lua_unlock(L); |
670 | } | 575 | } |
671 | 576 | ||
672 | 577 | ||
673 | LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { | 578 | LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { |
674 | Table *t; | ||
675 | lua_lock(L); | 579 | lua_lock(L); |
676 | luaC_checkGC(L); | 580 | luaC_checkGC(L); |
677 | t = luaH_new(L); | 581 | sethvalue(L, L->top, luaH_new(L, narray, nrec)); |
678 | sethvalue(L, L->top, t); | ||
679 | api_incr_top(L); | 582 | api_incr_top(L); |
680 | if (narray > 0 || nrec > 0) | ||
681 | luaH_resize(L, t, narray, nrec); | ||
682 | lua_unlock(L); | 583 | lua_unlock(L); |
683 | } | 584 | } |
684 | 585 | ||
@@ -688,8 +589,8 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { | |||
688 | Table *mt = NULL; | 589 | Table *mt = NULL; |
689 | int res; | 590 | int res; |
690 | lua_lock(L); | 591 | lua_lock(L); |
691 | obj = index2addr(L, objindex); | 592 | obj = index2adr(L, objindex); |
692 | switch (ttypenv(obj)) { | 593 | switch (ttype(obj)) { |
693 | case LUA_TTABLE: | 594 | case LUA_TTABLE: |
694 | mt = hvalue(obj)->metatable; | 595 | mt = hvalue(obj)->metatable; |
695 | break; | 596 | break; |
@@ -697,7 +598,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { | |||
697 | mt = uvalue(obj)->metatable; | 598 | mt = uvalue(obj)->metatable; |
698 | break; | 599 | break; |
699 | default: | 600 | default: |
700 | mt = G(L)->mt[ttypenv(obj)]; | 601 | mt = G(L)->mt[ttype(obj)]; |
701 | break; | 602 | break; |
702 | } | 603 | } |
703 | if (mt == NULL) | 604 | if (mt == NULL) |
@@ -712,15 +613,25 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { | |||
712 | } | 613 | } |
713 | 614 | ||
714 | 615 | ||
715 | LUA_API void lua_getuservalue (lua_State *L, int idx) { | 616 | LUA_API void lua_getfenv (lua_State *L, int idx) { |
716 | StkId o; | 617 | StkId o; |
717 | lua_lock(L); | 618 | lua_lock(L); |
718 | o = index2addr(L, idx); | 619 | o = index2adr(L, idx); |
719 | api_check(L, ttisuserdata(o), "userdata expected"); | 620 | api_checkvalidindex(L, o); |
720 | if (uvalue(o)->env) { | 621 | switch (ttype(o)) { |
721 | sethvalue(L, L->top, uvalue(o)->env); | 622 | case LUA_TFUNCTION: |
722 | } else | 623 | sethvalue(L, L->top, clvalue(o)->c.env); |
723 | setnilvalue(L->top); | 624 | break; |
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 | } | ||
724 | api_incr_top(L); | 635 | api_incr_top(L); |
725 | lua_unlock(L); | 636 | lua_unlock(L); |
726 | } | 637 | } |
@@ -731,24 +642,12 @@ LUA_API void lua_getuservalue (lua_State *L, int idx) { | |||
731 | */ | 642 | */ |
732 | 643 | ||
733 | 644 | ||
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 | |||
747 | LUA_API void lua_settable (lua_State *L, int idx) { | 645 | LUA_API void lua_settable (lua_State *L, int idx) { |
748 | StkId t; | 646 | StkId t; |
749 | lua_lock(L); | 647 | lua_lock(L); |
750 | api_checknelems(L, 2); | 648 | api_checknelems(L, 2); |
751 | t = index2addr(L, idx); | 649 | t = index2adr(L, idx); |
650 | api_checkvalidindex(L, t); | ||
752 | luaV_settable(L, t, L->top - 2, L->top - 1); | 651 | luaV_settable(L, t, L->top - 2, L->top - 1); |
753 | L->top -= 2; /* pop index and value */ | 652 | L->top -= 2; /* pop index and value */ |
754 | lua_unlock(L); | 653 | lua_unlock(L); |
@@ -757,12 +656,14 @@ LUA_API void lua_settable (lua_State *L, int idx) { | |||
757 | 656 | ||
758 | LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { | 657 | LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { |
759 | StkId t; | 658 | StkId t; |
659 | TValue key; | ||
760 | lua_lock(L); | 660 | lua_lock(L); |
761 | api_checknelems(L, 1); | 661 | api_checknelems(L, 1); |
762 | t = index2addr(L, idx); | 662 | t = index2adr(L, idx); |
763 | setsvalue2s(L, L->top++, luaS_new(L, k)); | 663 | api_checkvalidindex(L, t); |
764 | luaV_settable(L, t, L->top - 1, L->top - 2); | 664 | setsvalue(L, &key, luaS_new(L, k)); |
765 | L->top -= 2; /* pop value and key */ | 665 | luaV_settable(L, t, &key, L->top - 1); |
666 | L->top--; /* pop value */ | ||
766 | lua_unlock(L); | 667 | lua_unlock(L); |
767 | } | 668 | } |
768 | 669 | ||
@@ -771,39 +672,23 @@ LUA_API void lua_rawset (lua_State *L, int idx) { | |||
771 | StkId t; | 672 | StkId t; |
772 | lua_lock(L); | 673 | lua_lock(L); |
773 | api_checknelems(L, 2); | 674 | api_checknelems(L, 2); |
774 | t = index2addr(L, idx); | 675 | t = index2adr(L, idx); |
775 | api_check(L, ttistable(t), "table expected"); | 676 | api_check(L, ttistable(t)); |
776 | setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); | 677 | setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); |
777 | invalidateTMcache(hvalue(t)); | 678 | luaC_barriert(L, hvalue(t), L->top-1); |
778 | luaC_barrierback(L, gcvalue(t), L->top-1); | ||
779 | L->top -= 2; | 679 | L->top -= 2; |
780 | lua_unlock(L); | 680 | lua_unlock(L); |
781 | } | 681 | } |
782 | 682 | ||
783 | 683 | ||
784 | LUA_API void lua_rawseti (lua_State *L, int idx, int n) { | 684 | LUA_API void lua_rawseti (lua_State *L, int idx, int n) { |
785 | StkId t; | 685 | StkId o; |
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; | ||
800 | lua_lock(L); | 686 | lua_lock(L); |
801 | api_checknelems(L, 1); | 687 | api_checknelems(L, 1); |
802 | t = index2addr(L, idx); | 688 | o = index2adr(L, idx); |
803 | api_check(L, ttistable(t), "table expected"); | 689 | api_check(L, ttistable(o)); |
804 | setpvalue(&k, cast(void *, p)); | 690 | setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); |
805 | setobj2t(L, luaH_set(L, hvalue(t), &k), L->top - 1); | 691 | luaC_barriert(L, hvalue(o), L->top-1); |
806 | luaC_barrierback(L, gcvalue(t), L->top - 1); | ||
807 | L->top--; | 692 | L->top--; |
808 | lua_unlock(L); | 693 | lua_unlock(L); |
809 | } | 694 | } |
@@ -814,32 +699,29 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |||
814 | Table *mt; | 699 | Table *mt; |
815 | lua_lock(L); | 700 | lua_lock(L); |
816 | api_checknelems(L, 1); | 701 | api_checknelems(L, 1); |
817 | obj = index2addr(L, objindex); | 702 | obj = index2adr(L, objindex); |
703 | api_checkvalidindex(L, obj); | ||
818 | if (ttisnil(L->top - 1)) | 704 | if (ttisnil(L->top - 1)) |
819 | mt = NULL; | 705 | mt = NULL; |
820 | else { | 706 | else { |
821 | api_check(L, ttistable(L->top - 1), "table expected"); | 707 | api_check(L, ttistable(L->top - 1)); |
822 | mt = hvalue(L->top - 1); | 708 | mt = hvalue(L->top - 1); |
823 | } | 709 | } |
824 | switch (ttypenv(obj)) { | 710 | switch (ttype(obj)) { |
825 | case LUA_TTABLE: { | 711 | case LUA_TTABLE: { |
826 | hvalue(obj)->metatable = mt; | 712 | hvalue(obj)->metatable = mt; |
827 | if (mt) { | 713 | if (mt) |
828 | luaC_objbarrierback(L, gcvalue(obj), mt); | 714 | luaC_objbarriert(L, hvalue(obj), mt); |
829 | luaC_checkfinalizer(L, gcvalue(obj), mt); | ||
830 | } | ||
831 | break; | 715 | break; |
832 | } | 716 | } |
833 | case LUA_TUSERDATA: { | 717 | case LUA_TUSERDATA: { |
834 | uvalue(obj)->metatable = mt; | 718 | uvalue(obj)->metatable = mt; |
835 | if (mt) { | 719 | if (mt) |
836 | luaC_objbarrier(L, rawuvalue(obj), mt); | 720 | luaC_objbarrier(L, rawuvalue(obj), mt); |
837 | luaC_checkfinalizer(L, gcvalue(obj), mt); | ||
838 | } | ||
839 | break; | 721 | break; |
840 | } | 722 | } |
841 | default: { | 723 | default: { |
842 | G(L)->mt[ttypenv(obj)] = mt; | 724 | G(L)->mt[ttype(obj)] = mt; |
843 | break; | 725 | break; |
844 | } | 726 | } |
845 | } | 727 | } |
@@ -849,21 +731,32 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |||
849 | } | 731 | } |
850 | 732 | ||
851 | 733 | ||
852 | LUA_API void lua_setuservalue (lua_State *L, int idx) { | 734 | LUA_API int lua_setfenv (lua_State *L, int idx) { |
853 | StkId o; | 735 | StkId o; |
736 | int res = 1; | ||
854 | lua_lock(L); | 737 | lua_lock(L); |
855 | api_checknelems(L, 1); | 738 | api_checknelems(L, 1); |
856 | o = index2addr(L, idx); | 739 | o = index2adr(L, idx); |
857 | api_check(L, ttisuserdata(o), "userdata expected"); | 740 | api_checkvalidindex(L, o); |
858 | if (ttisnil(L->top - 1)) | 741 | api_check(L, ttistable(L->top - 1)); |
859 | uvalue(o)->env = NULL; | 742 | switch (ttype(o)) { |
860 | else { | 743 | case LUA_TFUNCTION: |
861 | api_check(L, ttistable(L->top - 1), "table expected"); | 744 | clvalue(o)->c.env = hvalue(L->top - 1); |
862 | uvalue(o)->env = hvalue(L->top - 1); | 745 | break; |
863 | luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); | 746 | case LUA_TUSERDATA: |
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; | ||
864 | } | 755 | } |
756 | if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); | ||
865 | L->top--; | 757 | L->top--; |
866 | lua_unlock(L); | 758 | lua_unlock(L); |
759 | return res; | ||
867 | } | 760 | } |
868 | 761 | ||
869 | 762 | ||
@@ -872,37 +765,21 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) { | |||
872 | */ | 765 | */ |
873 | 766 | ||
874 | 767 | ||
875 | #define checkresults(L,na,nr) \ | 768 | #define adjustresults(L,nres) \ |
876 | api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ | 769 | { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } |
877 | "results from function overflow current stack size") | ||
878 | |||
879 | 770 | ||
880 | LUA_API int lua_getctx (lua_State *L, int *ctx) { | ||
881 | if (L->ci->callstatus & CIST_YIELDED) { | ||
882 | if (ctx) *ctx = L->ci->u.c.ctx; | ||
883 | return L->ci->u.c.status; | ||
884 | } | ||
885 | else return LUA_OK; | ||
886 | } | ||
887 | 771 | ||
772 | #define checkresults(L,na,nr) \ | ||
773 | api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) | ||
774 | |||
888 | 775 | ||
889 | LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx, | 776 | LUA_API void lua_call (lua_State *L, int nargs, int nresults) { |
890 | lua_CFunction k) { | ||
891 | StkId func; | 777 | StkId func; |
892 | lua_lock(L); | 778 | lua_lock(L); |
893 | api_check(L, k == NULL || !isLua(L->ci), | ||
894 | "cannot use continuations inside hooks"); | ||
895 | api_checknelems(L, nargs+1); | 779 | api_checknelems(L, nargs+1); |
896 | api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); | ||
897 | checkresults(L, nargs, nresults); | 780 | checkresults(L, nargs, nresults); |
898 | func = L->top - (nargs+1); | 781 | func = L->top - (nargs+1); |
899 | if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ | 782 | luaD_call(L, func, nresults); |
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 */ | ||
906 | adjustresults(L, nresults); | 783 | adjustresults(L, nresults); |
907 | lua_unlock(L); | 784 | lua_unlock(L); |
908 | } | 785 | } |
@@ -920,75 +797,76 @@ struct CallS { /* data to `f_call' */ | |||
920 | 797 | ||
921 | static void f_call (lua_State *L, void *ud) { | 798 | static void f_call (lua_State *L, void *ud) { |
922 | struct CallS *c = cast(struct CallS *, ud); | 799 | struct CallS *c = cast(struct CallS *, ud); |
923 | luaD_call(L, c->func, c->nresults, 0); | 800 | luaD_call(L, c->func, c->nresults); |
924 | } | 801 | } |
925 | 802 | ||
926 | 803 | ||
927 | 804 | ||
928 | LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, | 805 | LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { |
929 | int ctx, lua_CFunction k) { | ||
930 | struct CallS c; | 806 | struct CallS c; |
931 | int status; | 807 | int status; |
932 | ptrdiff_t func; | 808 | ptrdiff_t func; |
933 | lua_lock(L); | 809 | lua_lock(L); |
934 | api_check(L, k == NULL || !isLua(L->ci), | ||
935 | "cannot use continuations inside hooks"); | ||
936 | api_checknelems(L, nargs+1); | 810 | api_checknelems(L, nargs+1); |
937 | api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); | ||
938 | checkresults(L, nargs, nresults); | 811 | checkresults(L, nargs, nresults); |
939 | if (errfunc == 0) | 812 | if (errfunc == 0) |
940 | func = 0; | 813 | func = 0; |
941 | else { | 814 | else { |
942 | StkId o = index2addr(L, errfunc); | 815 | StkId o = index2adr(L, errfunc); |
943 | api_checkstackindex(L, errfunc, o); | 816 | api_checkvalidindex(L, o); |
944 | func = savestack(L, o); | 817 | func = savestack(L, o); |
945 | } | 818 | } |
946 | c.func = L->top - (nargs+1); /* function to be called */ | 819 | c.func = L->top - (nargs+1); /* function to be called */ |
947 | if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ | 820 | c.nresults = nresults; |
948 | c.nresults = nresults; /* do a 'conventional' protected call */ | 821 | status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); |
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 | } | ||
967 | adjustresults(L, nresults); | 822 | adjustresults(L, nresults); |
968 | lua_unlock(L); | 823 | lua_unlock(L); |
969 | return status; | 824 | return status; |
970 | } | 825 | } |
971 | 826 | ||
972 | 827 | ||
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 | |||
973 | LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, | 862 | LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, |
974 | const char *chunkname, const char *mode) { | 863 | const char *chunkname) { |
975 | ZIO z; | 864 | ZIO z; |
976 | int status; | 865 | int status; |
977 | lua_lock(L); | 866 | lua_lock(L); |
978 | if (!chunkname) chunkname = "?"; | 867 | if (!chunkname) chunkname = "?"; |
979 | luaZ_init(L, &z, reader, data); | 868 | luaZ_init(L, &z, reader, data); |
980 | status = luaD_protectedparser(L, &z, chunkname, mode); | 869 | status = luaD_protectedparser(L, &z, chunkname); |
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 | } | ||
992 | lua_unlock(L); | 870 | lua_unlock(L); |
993 | return status; | 871 | return status; |
994 | } | 872 | } |
@@ -1001,7 +879,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { | |||
1001 | api_checknelems(L, 1); | 879 | api_checknelems(L, 1); |
1002 | o = L->top - 1; | 880 | o = L->top - 1; |
1003 | if (isLfunction(o)) | 881 | if (isLfunction(o)) |
1004 | status = luaU_dump(L, getproto(o), writer, data, 0); | 882 | status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); |
1005 | else | 883 | else |
1006 | status = 1; | 884 | status = 1; |
1007 | lua_unlock(L); | 885 | lua_unlock(L); |
@@ -1009,7 +887,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { | |||
1009 | } | 887 | } |
1010 | 888 | ||
1011 | 889 | ||
1012 | LUA_API int lua_status (lua_State *L) { | 890 | LUA_API int lua_status (lua_State *L) { |
1013 | return L->status; | 891 | return L->status; |
1014 | } | 892 | } |
1015 | 893 | ||
@@ -1025,40 +903,38 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { | |||
1025 | g = G(L); | 903 | g = G(L); |
1026 | switch (what) { | 904 | switch (what) { |
1027 | case LUA_GCSTOP: { | 905 | case LUA_GCSTOP: { |
1028 | g->gcrunning = 0; | 906 | g->GCthreshold = MAX_LUMEM; |
1029 | break; | 907 | break; |
1030 | } | 908 | } |
1031 | case LUA_GCRESTART: { | 909 | case LUA_GCRESTART: { |
1032 | luaE_setdebt(g, 0); | 910 | g->GCthreshold = g->totalbytes; |
1033 | g->gcrunning = 1; | ||
1034 | break; | 911 | break; |
1035 | } | 912 | } |
1036 | case LUA_GCCOLLECT: { | 913 | case LUA_GCCOLLECT: { |
1037 | luaC_fullgc(L, 0); | 914 | luaC_fullgc(L); |
1038 | break; | 915 | break; |
1039 | } | 916 | } |
1040 | case LUA_GCCOUNT: { | 917 | case LUA_GCCOUNT: { |
1041 | /* GC values are expressed in Kbytes: #bytes/2^10 */ | 918 | /* GC values are expressed in Kbytes: #bytes/2^10 */ |
1042 | res = cast_int(gettotalbytes(g) >> 10); | 919 | res = cast_int(g->totalbytes >> 10); |
1043 | break; | 920 | break; |
1044 | } | 921 | } |
1045 | case LUA_GCCOUNTB: { | 922 | case LUA_GCCOUNTB: { |
1046 | res = cast_int(gettotalbytes(g) & 0x3ff); | 923 | res = cast_int(g->totalbytes & 0x3ff); |
1047 | break; | 924 | break; |
1048 | } | 925 | } |
1049 | case LUA_GCSTEP: { | 926 | case LUA_GCSTEP: { |
1050 | if (g->gckind == KGC_GEN) { /* generational mode? */ | 927 | lu_mem a = (cast(lu_mem, data) << 10); |
1051 | res = (g->GCestimate == 0); /* true if it will do major collection */ | 928 | if (a <= g->totalbytes) |
1052 | luaC_forcestep(L); /* do a single step */ | 929 | g->GCthreshold = g->totalbytes - a; |
1053 | } | 930 | else |
1054 | else { | 931 | g->GCthreshold = 0; |
1055 | lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE; | 932 | while (g->GCthreshold <= g->totalbytes) { |
1056 | if (g->gcrunning) | 933 | luaC_step(L); |
1057 | debt += g->GCdebt; /* include current debt */ | 934 | if (g->gcstate == GCSpause) { /* end of cycle? */ |
1058 | luaE_setdebt(g, debt); | 935 | res = 1; /* signal it */ |
1059 | luaC_forcestep(L); | 936 | break; |
1060 | if (g->gcstate == GCSpause) /* end of cycle? */ | 937 | } |
1061 | res = 1; /* signal it */ | ||
1062 | } | 938 | } |
1063 | break; | 939 | break; |
1064 | } | 940 | } |
@@ -1067,28 +943,11 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { | |||
1067 | g->gcpause = data; | 943 | g->gcpause = data; |
1068 | break; | 944 | break; |
1069 | } | 945 | } |
1070 | case LUA_GCSETMAJORINC: { | ||
1071 | res = g->gcmajorinc; | ||
1072 | g->gcmajorinc = data; | ||
1073 | break; | ||
1074 | } | ||
1075 | case LUA_GCSETSTEPMUL: { | 946 | case LUA_GCSETSTEPMUL: { |
1076 | res = g->gcstepmul; | 947 | res = g->gcstepmul; |
1077 | g->gcstepmul = data; | 948 | g->gcstepmul = data; |
1078 | break; | 949 | break; |
1079 | } | 950 | } |
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 | } | ||
1092 | default: res = -1; /* invalid option */ | 951 | default: res = -1; /* invalid option */ |
1093 | } | 952 | } |
1094 | lua_unlock(L); | 953 | lua_unlock(L); |
@@ -1106,7 +965,7 @@ LUA_API int lua_error (lua_State *L) { | |||
1106 | lua_lock(L); | 965 | lua_lock(L); |
1107 | api_checknelems(L, 1); | 966 | api_checknelems(L, 1); |
1108 | luaG_errormsg(L); | 967 | luaG_errormsg(L); |
1109 | /* code unreachable; will unlock when control actually leaves the kernel */ | 968 | lua_unlock(L); |
1110 | return 0; /* to avoid warnings */ | 969 | return 0; /* to avoid warnings */ |
1111 | } | 970 | } |
1112 | 971 | ||
@@ -1115,8 +974,8 @@ LUA_API int lua_next (lua_State *L, int idx) { | |||
1115 | StkId t; | 974 | StkId t; |
1116 | int more; | 975 | int more; |
1117 | lua_lock(L); | 976 | lua_lock(L); |
1118 | t = index2addr(L, idx); | 977 | t = index2adr(L, idx); |
1119 | api_check(L, ttistable(t), "table expected"); | 978 | api_check(L, ttistable(t)); |
1120 | more = luaH_next(L, hvalue(t), L->top - 1); | 979 | more = luaH_next(L, hvalue(t), L->top - 1); |
1121 | if (more) { | 980 | if (more) { |
1122 | api_incr_top(L); | 981 | api_incr_top(L); |
@@ -1133,7 +992,8 @@ LUA_API void lua_concat (lua_State *L, int n) { | |||
1133 | api_checknelems(L, n); | 992 | api_checknelems(L, n); |
1134 | if (n >= 2) { | 993 | if (n >= 2) { |
1135 | luaC_checkGC(L); | 994 | luaC_checkGC(L); |
1136 | luaV_concat(L, n); | 995 | luaV_concat(L, n, cast_int(L->top - L->base) - 1); |
996 | L->top -= (n-1); | ||
1137 | } | 997 | } |
1138 | else if (n == 0) { /* push empty string */ | 998 | else if (n == 0) { /* push empty string */ |
1139 | setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); | 999 | setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); |
@@ -1144,16 +1004,6 @@ LUA_API void lua_concat (lua_State *L, int n) { | |||
1144 | } | 1004 | } |
1145 | 1005 | ||
1146 | 1006 | ||
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 | |||
1157 | LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { | 1007 | LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { |
1158 | lua_Alloc f; | 1008 | lua_Alloc f; |
1159 | lua_lock(L); | 1009 | lua_lock(L); |
@@ -1176,7 +1026,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { | |||
1176 | Udata *u; | 1026 | Udata *u; |
1177 | lua_lock(L); | 1027 | lua_lock(L); |
1178 | luaC_checkGC(L); | 1028 | luaC_checkGC(L); |
1179 | u = luaS_newudata(L, size, NULL); | 1029 | u = luaS_newudata(L, size, getcurrenv(L)); |
1180 | setuvalue(L, L->top, u); | 1030 | setuvalue(L, L->top, u); |
1181 | api_incr_top(L); | 1031 | api_incr_top(L); |
1182 | lua_unlock(L); | 1032 | lua_unlock(L); |
@@ -1185,36 +1035,30 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { | |||
1185 | 1035 | ||
1186 | 1036 | ||
1187 | 1037 | ||
1188 | static const char *aux_upvalue (StkId fi, int n, TValue **val, | 1038 | |
1189 | GCObject **owner) { | 1039 | static const char *aux_upvalue (StkId fi, int n, TValue **val) { |
1190 | switch (ttype(fi)) { | 1040 | Closure *f; |
1191 | case LUA_TCCL: { /* C closure */ | 1041 | if (!ttisfunction(fi)) return NULL; |
1192 | CClosure *f = clCvalue(fi); | 1042 | f = clvalue(fi); |
1193 | if (!(1 <= n && n <= f->nupvalues)) return NULL; | 1043 | if (f->c.isC) { |
1194 | *val = &f->upvalue[n-1]; | 1044 | if (!(1 <= n && n <= f->c.nupvalues)) return NULL; |
1195 | if (owner) *owner = obj2gco(f); | 1045 | *val = &f->c.upvalue[n-1]; |
1196 | return ""; | 1046 | return ""; |
1197 | } | 1047 | } |
1198 | case LUA_TLCL: { /* Lua closure */ | 1048 | else { |
1199 | LClosure *f = clLvalue(fi); | 1049 | Proto *p = f->l.p; |
1200 | TString *name; | 1050 | if (!(1 <= n && n <= p->sizeupvalues)) return NULL; |
1201 | Proto *p = f->p; | 1051 | *val = f->l.upvals[n-1]->v; |
1202 | if (!(1 <= n && n <= p->sizeupvalues)) return NULL; | 1052 | return getstr(p->upvalues[n-1]); |
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 */ | ||
1209 | } | 1053 | } |
1210 | } | 1054 | } |
1211 | 1055 | ||
1212 | 1056 | ||
1213 | LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { | 1057 | LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { |
1214 | const char *name; | 1058 | const char *name; |
1215 | TValue *val = NULL; /* to avoid warnings */ | 1059 | TValue *val; |
1216 | lua_lock(L); | 1060 | lua_lock(L); |
1217 | name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL); | 1061 | name = aux_upvalue(index2adr(L, funcindex), n, &val); |
1218 | if (name) { | 1062 | if (name) { |
1219 | setobj2s(L, L->top, val); | 1063 | setobj2s(L, L->top, val); |
1220 | api_incr_top(L); | 1064 | api_incr_top(L); |
@@ -1226,59 +1070,18 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { | |||
1226 | 1070 | ||
1227 | LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { | 1071 | LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { |
1228 | const char *name; | 1072 | const char *name; |
1229 | TValue *val = NULL; /* to avoid warnings */ | 1073 | TValue *val; |
1230 | GCObject *owner = NULL; /* to avoid warnings */ | ||
1231 | StkId fi; | 1074 | StkId fi; |
1232 | lua_lock(L); | 1075 | lua_lock(L); |
1233 | fi = index2addr(L, funcindex); | 1076 | fi = index2adr(L, funcindex); |
1234 | api_checknelems(L, 1); | 1077 | api_checknelems(L, 1); |
1235 | name = aux_upvalue(fi, n, &val, &owner); | 1078 | name = aux_upvalue(fi, n, &val); |
1236 | if (name) { | 1079 | if (name) { |
1237 | L->top--; | 1080 | L->top--; |
1238 | setobj(L, val, L->top); | 1081 | setobj(L, val, L->top); |
1239 | luaC_barrier(L, owner, L->top); | 1082 | luaC_barrier(L, clvalue(fi), L->top); |
1240 | } | 1083 | } |
1241 | lua_unlock(L); | 1084 | lua_unlock(L); |
1242 | return name; | 1085 | return name; |
1243 | } | 1086 | } |
1244 | 1087 | ||
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 c7d34ad848..f968ffc992 100644 --- a/apps/plugins/lua/lapi.h +++ b/apps/plugins/lua/lapi.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.h,v 2.7.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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,17 +8,9 @@ | |||
8 | #define lapi_h | 8 | #define lapi_h |
9 | 9 | ||
10 | 10 | ||
11 | #include "llimits.h" | 11 | #include "lobject.h" |
12 | #include "lstate.h" | ||
13 | 12 | ||
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") | ||
22 | 13 | ||
14 | LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); | ||
23 | 15 | ||
24 | #endif | 16 | #endif |
diff --git a/apps/plugins/lua/lauxlib.c b/apps/plugins/lua/lauxlib.c index f451fb7c9e..b8020b7475 100644 --- a/apps/plugins/lua/lauxlib.c +++ b/apps/plugins/lua/lauxlib.c | |||
@@ -1,10 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lauxlib.c,v 1.248.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 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> | ||
8 | #include <errno.h> | 9 | #include <errno.h> |
9 | #include <stdarg.h> | 10 | #include <stdarg.h> |
10 | #include <stdio.h> | 11 | #include <stdio.h> |
@@ -22,127 +23,14 @@ | |||
22 | #include "lua.h" | 23 | #include "lua.h" |
23 | 24 | ||
24 | #include "lauxlib.h" | 25 | #include "lauxlib.h" |
25 | #include "rocklibc.h" | ||
26 | 26 | ||
27 | 27 | ||
28 | /* | 28 | #define FREELIST_REF 0 /* free list of references */ |
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 | } | ||
100 | 29 | ||
101 | 30 | ||
102 | static int countlevels (lua_State *L) { | 31 | /* convert a stack index to positive */ |
103 | lua_Debug ar; | 32 | #define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ |
104 | int li = 1, le = 1; | 33 | lua_gettop(L) + (i) + 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 | /* }====================================================== */ | ||
146 | 34 | ||
147 | 35 | ||
148 | /* | 36 | /* |
@@ -151,6 +39,7 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, | |||
151 | ** ======================================================= | 39 | ** ======================================================= |
152 | */ | 40 | */ |
153 | 41 | ||
42 | |||
154 | LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { | 43 | LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { |
155 | lua_Debug ar; | 44 | lua_Debug ar; |
156 | if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ | 45 | if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ |
@@ -163,13 +52,13 @@ LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { | |||
163 | ar.name, extramsg); | 52 | ar.name, extramsg); |
164 | } | 53 | } |
165 | if (ar.name == NULL) | 54 | if (ar.name == NULL) |
166 | ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; | 55 | ar.name = "?"; |
167 | return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", | 56 | return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", |
168 | narg, ar.name, extramsg); | 57 | narg, ar.name, extramsg); |
169 | } | 58 | } |
170 | 59 | ||
171 | 60 | ||
172 | static int typeerror (lua_State *L, int narg, const char *tname) { | 61 | LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { |
173 | const char *msg = lua_pushfstring(L, "%s expected, got %s", | 62 | const char *msg = lua_pushfstring(L, "%s expected, got %s", |
174 | tname, luaL_typename(L, narg)); | 63 | tname, luaL_typename(L, narg)); |
175 | return luaL_argerror(L, narg, msg); | 64 | return luaL_argerror(L, narg, msg); |
@@ -177,7 +66,7 @@ static int typeerror (lua_State *L, int narg, const char *tname) { | |||
177 | 66 | ||
178 | 67 | ||
179 | static void tag_error (lua_State *L, int narg, int tag) { | 68 | static void tag_error (lua_State *L, int narg, int tag) { |
180 | typeerror(L, narg, lua_typename(L, tag)); | 69 | luaL_typerror(L, narg, lua_typename(L, tag)); |
181 | } | 70 | } |
182 | 71 | ||
183 | 72 | ||
@@ -204,74 +93,24 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { | |||
204 | return lua_error(L); | 93 | return lua_error(L); |
205 | } | 94 | } |
206 | 95 | ||
207 | 96 | /* }====================================================== */ | |
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 | } | ||
224 | |||
225 | |||
226 | #if !defined(inspectstat) /* { */ | ||
227 | |||
228 | #if defined(LUA_USE_POSIX) | ||
229 | |||
230 | #include <sys/wait.h> | ||
231 | |||
232 | /* | ||
233 | ** use appropriate macros to interpret 'pclose' return status | ||
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 | 97 | ||
247 | 98 | ||
248 | LUALIB_API int luaL_execresult (lua_State *L, int stat) { | 99 | LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, |
249 | const char *what = "exit"; /* type of termination */ | 100 | const char *const lst[]) { |
250 | if (stat == -1) /* error? */ | 101 | const char *name = (def) ? luaL_optstring(L, narg, def) : |
251 | return luaL_fileresult(L, 0, NULL); | 102 | luaL_checkstring(L, narg); |
252 | else { | 103 | int i; |
253 | inspectstat(stat, what); /* interpret result */ | 104 | for (i=0; lst[i]; i++) |
254 | if (*what == 'e' && stat == 0) /* successful termination? */ | 105 | if (strcmp(lst[i], name) == 0) |
255 | lua_pushboolean(L, 1); | 106 | return i; |
256 | else | 107 | return luaL_argerror(L, narg, |
257 | lua_pushnil(L); | 108 | lua_pushfstring(L, "invalid option " LUA_QS, name)); |
258 | lua_pushstring(L, what); | ||
259 | lua_pushinteger(L, stat); | ||
260 | return 3; /* return true/nil,what,code */ | ||
261 | } | ||
262 | } | 109 | } |
263 | 110 | ||
264 | /* }====================================================== */ | ||
265 | |||
266 | |||
267 | /* | ||
268 | ** {====================================================== | ||
269 | ** Userdata's metatable manipulation | ||
270 | ** ======================================================= | ||
271 | */ | ||
272 | 111 | ||
273 | LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { | 112 | LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { |
274 | luaL_getmetatable(L, tname); /* try to get metatable */ | 113 | lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ |
275 | if (!lua_isnil(L, -1)) /* name already in use? */ | 114 | if (!lua_isnil(L, -1)) /* name already in use? */ |
276 | return 0; /* leave previous value on top, but return 0 */ | 115 | return 0; /* leave previous value on top, but return 0 */ |
277 | lua_pop(L, 1); | 116 | lua_pop(L, 1); |
@@ -282,64 +121,25 @@ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { | |||
282 | } | 121 | } |
283 | 122 | ||
284 | 123 | ||
285 | LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) { | 124 | LUALIB_API void *luaL_checkudata (lua_State *L, int ud, 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) { | ||
292 | void *p = lua_touserdata(L, ud); | 125 | void *p = lua_touserdata(L, ud); |
293 | if (p != NULL) { /* value is a userdata? */ | 126 | if (p != NULL) { /* value is a userdata? */ |
294 | if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ | 127 | if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ |
295 | luaL_getmetatable(L, tname); /* get correct metatable */ | 128 | lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ |
296 | if (!lua_rawequal(L, -1, -2)) /* not the same? */ | 129 | if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ |
297 | p = NULL; /* value is a userdata with wrong metatable */ | 130 | lua_pop(L, 2); /* remove both metatables */ |
298 | lua_pop(L, 2); /* remove both metatables */ | 131 | return p; |
299 | return p; | 132 | } |
300 | } | 133 | } |
301 | } | 134 | } |
302 | return NULL; /* value is not a userdata with a metatable */ | 135 | luaL_typerror(L, ud, tname); /* else error */ |
136 | return NULL; /* to avoid warnings */ | ||
303 | } | 137 | } |
304 | 138 | ||
305 | 139 | ||
306 | LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { | 140 | LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { |
307 | void *p = luaL_testudata(L, ud, tname); | 141 | if (!lua_checkstack(L, space)) |
308 | if (p == NULL) typeerror(L, ud, tname); | 142 | luaL_error(L, "stack overflow (%s)", mes); |
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 | } | ||
343 | } | 143 | } |
344 | 144 | ||
345 | 145 | ||
@@ -374,9 +174,8 @@ LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, | |||
374 | 174 | ||
375 | 175 | ||
376 | LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { | 176 | LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { |
377 | int isnum; | 177 | lua_Number d = lua_tonumber(L, narg); |
378 | lua_Number d = lua_tonumberx(L, narg, &isnum); | 178 | if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ |
379 | if (!isnum) | ||
380 | tag_error(L, narg, LUA_TNUMBER); | 179 | tag_error(L, narg, LUA_TNUMBER); |
381 | return d; | 180 | return d; |
382 | } | 181 | } |
@@ -388,18 +187,8 @@ LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { | |||
388 | 187 | ||
389 | 188 | ||
390 | LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { | 189 | LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { |
391 | int isnum; | 190 | lua_Integer d = lua_tointeger(L, narg); |
392 | lua_Integer d = lua_tointegerx(L, narg, &isnum); | 191 | if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ |
393 | if (!isnum) | ||
394 | tag_error(L, narg, LUA_TNUMBER); | ||
395 | return d; | ||
396 | } | ||
397 | |||
398 | |||
399 | LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) { | ||
400 | int isnum; | ||
401 | lua_Unsigned d = lua_tounsignedx(L, narg, &isnum); | ||
402 | if (!isnum) | ||
403 | tag_error(L, narg, LUA_TNUMBER); | 192 | tag_error(L, narg, LUA_TNUMBER); |
404 | return d; | 193 | return d; |
405 | } | 194 | } |
@@ -411,56 +200,255 @@ LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, | |||
411 | } | 200 | } |
412 | 201 | ||
413 | 202 | ||
414 | LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg, | 203 | LUALIB_API int luaL_checkboolean (lua_State *L, int narg) { |
415 | lua_Unsigned def) { | 204 | int b = lua_toboolean(L, narg); |
416 | return luaL_opt(L, luaL_checkunsigned, narg, def); | 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 */ | ||
417 | } | 281 | } |
418 | 282 | ||
419 | /* }====================================================== */ | ||
420 | 283 | ||
421 | 284 | ||
422 | /* | 285 | /* |
423 | ** {====================================================== | 286 | ** {====================================================== |
424 | ** Generic Buffer manipulation | 287 | ** getn-setn: size for arrays |
425 | ** ======================================================= | 288 | ** ======================================================= |
426 | */ | 289 | */ |
427 | 290 | ||
428 | /* | 291 | #if defined(LUA_COMPAT_GETN) |
429 | ** check whether buffer is using a userdata on the stack as a temporary | 292 | |
430 | ** buffer | 293 | static int checkint (lua_State *L, int topop) { |
431 | */ | 294 | int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; |
432 | #define buffonstack(B) ((B)->b != (B)->initb) | 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 | } | ||
313 | |||
314 | |||
315 | LUALIB_API void luaL_setn (lua_State *L, int t, int n) { | ||
316 | t = abs_index(L, t); | ||
317 | lua_pushliteral(L, "n"); | ||
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 | } | ||
332 | |||
333 | |||
334 | LUALIB_API int luaL_getn (lua_State *L, int t) { | ||
335 | int n; | ||
336 | t = abs_index(L, t); | ||
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 | } | ||
346 | |||
347 | #endif | ||
348 | |||
349 | /* }====================================================== */ | ||
350 | |||
351 | |||
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 | |||
433 | 396 | ||
434 | 397 | ||
435 | /* | 398 | /* |
436 | ** returns a pointer to a free area with at least 'sz' bytes | 399 | ** {====================================================== |
400 | ** Generic Buffer manipulation | ||
401 | ** ======================================================= | ||
437 | */ | 402 | */ |
438 | LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { | 403 | |
439 | lua_State *L = B->L; | 404 | |
440 | if (B->size - B->n < sz) { /* not enough space? */ | 405 | #define bufflen(B) ((B)->p - (B)->buffer) |
441 | char *newbuff; | 406 | #define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) |
442 | size_t newsize = B->size * 2; /* double buffer size */ | 407 | |
443 | if (newsize - B->n < sz) /* not big enough? */ | 408 | #define LIMIT (LUA_MINSTACK/2) |
444 | newsize = B->n + sz; | 409 | |
445 | if (newsize < B->n || newsize - B->n < sz) | 410 | |
446 | luaL_error(L, "buffer too large"); | 411 | static int emptybuffer (luaL_Buffer *B) { |
447 | /* create larger buffer */ | 412 | size_t l = bufflen(B); |
448 | newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char)); | 413 | if (l == 0) return 0; /* put nothing on stack */ |
449 | /* move content to new buffer */ | 414 | else { |
450 | memcpy(newbuff, B->b, B->n * sizeof(char)); | 415 | lua_pushlstring(B->L, B->buffer, l); |
451 | if (buffonstack(B)) | 416 | B->p = B->buffer; |
452 | lua_remove(L, -2); /* remove old buffer */ | 417 | B->lvl++; |
453 | B->b = newbuff; | 418 | return 1; |
454 | B->size = newsize; | 419 | } |
420 | } | ||
421 | |||
422 | |||
423 | static void adjuststack (luaL_Buffer *B) { | ||
424 | if (B->lvl > 1) { | ||
425 | lua_State *L = B->L; | ||
426 | int toget = 1; /* number of levels to concat */ | ||
427 | size_t toplen = lua_strlen(L, -1); | ||
428 | do { | ||
429 | size_t l = lua_strlen(L, -(toget+1)); | ||
430 | if (B->lvl - toget + 1 >= LIMIT || toplen > l) { | ||
431 | toplen += l; | ||
432 | toget++; | ||
433 | } | ||
434 | else break; | ||
435 | } while (toget < B->lvl); | ||
436 | lua_concat(L, toget); | ||
437 | B->lvl = B->lvl - toget + 1; | ||
455 | } | 438 | } |
456 | return &B->b[B->n]; | 439 | } |
440 | |||
441 | |||
442 | LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { | ||
443 | if (emptybuffer(B)) | ||
444 | adjuststack(B); | ||
445 | return B->buffer; | ||
457 | } | 446 | } |
458 | 447 | ||
459 | 448 | ||
460 | LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { | 449 | LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { |
461 | char *b = luaL_prepbuffsize(B, l); | 450 | while (l--) |
462 | memcpy(b, s, l * sizeof(char)); | 451 | luaL_addchar(B, *s++); |
463 | luaL_addsize(B, l); | ||
464 | } | 452 | } |
465 | 453 | ||
466 | 454 | ||
@@ -470,72 +458,57 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { | |||
470 | 458 | ||
471 | 459 | ||
472 | LUALIB_API void luaL_pushresult (luaL_Buffer *B) { | 460 | LUALIB_API void luaL_pushresult (luaL_Buffer *B) { |
473 | lua_State *L = B->L; | 461 | emptybuffer(B); |
474 | lua_pushlstring(L, B->b, B->n); | 462 | lua_concat(B->L, B->lvl); |
475 | if (buffonstack(B)) | 463 | B->lvl = 1; |
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); | ||
483 | } | 464 | } |
484 | 465 | ||
485 | 466 | ||
486 | LUALIB_API void luaL_addvalue (luaL_Buffer *B) { | 467 | LUALIB_API void luaL_addvalue (luaL_Buffer *B) { |
487 | lua_State *L = B->L; | 468 | lua_State *L = B->L; |
488 | size_t l; | 469 | size_t vl; |
489 | const char *s = lua_tolstring(L, -1, &l); | 470 | const char *s = lua_tolstring(L, -1, &vl); |
490 | if (buffonstack(B)) | 471 | if (vl <= bufffree(B)) { /* fit into buffer? */ |
491 | lua_insert(L, -2); /* put value below buffer */ | 472 | memcpy(B->p, s, vl); /* put it there */ |
492 | luaL_addlstring(B, s, l); | 473 | B->p += vl; |
493 | lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ | 474 | lua_pop(L, 1); /* remove from stack */ |
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 | } | ||
494 | } | 482 | } |
495 | 483 | ||
496 | 484 | ||
497 | LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { | 485 | LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { |
498 | B->L = L; | 486 | B->L = L; |
499 | B->b = B->initb; | 487 | B->p = B->buffer; |
500 | B->n = 0; | 488 | B->lvl = 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); | ||
508 | } | 489 | } |
509 | 490 | ||
510 | /* }====================================================== */ | 491 | /* }====================================================== */ |
511 | 492 | ||
512 | 493 | ||
513 | /* | ||
514 | ** {====================================================== | ||
515 | ** Reference system | ||
516 | ** ======================================================= | ||
517 | */ | ||
518 | |||
519 | /* index of free-list header */ | ||
520 | #define freelist 0 | ||
521 | |||
522 | |||
523 | LUALIB_API int luaL_ref (lua_State *L, int t) { | 494 | LUALIB_API int luaL_ref (lua_State *L, int t) { |
524 | int ref; | 495 | int ref; |
496 | t = abs_index(L, t); | ||
525 | if (lua_isnil(L, -1)) { | 497 | if (lua_isnil(L, -1)) { |
526 | lua_pop(L, 1); /* remove from stack */ | 498 | lua_pop(L, 1); /* remove from stack */ |
527 | return LUA_REFNIL; /* `nil' has a unique fixed reference */ | 499 | return LUA_REFNIL; /* `nil' has a unique fixed reference */ |
528 | } | 500 | } |
529 | t = lua_absindex(L, t); | 501 | lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ |
530 | lua_rawgeti(L, t, freelist); /* get first free element */ | 502 | ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ |
531 | ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ | ||
532 | lua_pop(L, 1); /* remove it from stack */ | 503 | lua_pop(L, 1); /* remove it from stack */ |
533 | if (ref != 0) { /* any free element? */ | 504 | if (ref != 0) { /* any free element? */ |
534 | lua_rawgeti(L, t, ref); /* remove it from list */ | 505 | lua_rawgeti(L, t, ref); /* remove it from list */ |
535 | lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ | 506 | lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ |
507 | } | ||
508 | else { /* no free elements */ | ||
509 | ref = (int)lua_objlen(L, t); | ||
510 | ref++; /* create new reference */ | ||
536 | } | 511 | } |
537 | else /* no free elements */ | ||
538 | ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ | ||
539 | lua_rawseti(L, t, ref); | 512 | lua_rawseti(L, t, ref); |
540 | return ref; | 513 | return ref; |
541 | } | 514 | } |
@@ -543,15 +516,14 @@ LUALIB_API int luaL_ref (lua_State *L, int t) { | |||
543 | 516 | ||
544 | LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { | 517 | LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { |
545 | if (ref >= 0) { | 518 | if (ref >= 0) { |
546 | t = lua_absindex(L, t); | 519 | t = abs_index(L, t); |
547 | lua_rawgeti(L, t, freelist); | 520 | lua_rawgeti(L, t, FREELIST_REF); |
548 | lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ | 521 | lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ |
549 | lua_pushinteger(L, ref); | 522 | lua_pushinteger(L, ref); |
550 | lua_rawseti(L, t, freelist); /* t[freelist] = ref */ | 523 | lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ |
551 | } | 524 | } |
552 | } | 525 | } |
553 | 526 | ||
554 | /* }====================================================== */ | ||
555 | 527 | ||
556 | 528 | ||
557 | /* | 529 | /* |
@@ -561,28 +533,22 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { | |||
561 | */ | 533 | */ |
562 | 534 | ||
563 | typedef struct LoadF { | 535 | typedef struct LoadF { |
564 | int n; /* number of pre-read characters */ | 536 | int extraline; |
565 | int f; | 537 | int f; |
566 | char buff[LUAL_BUFFERSIZE]; /* area for reading file */ | 538 | char buff[LUAL_BUFFERSIZE]; |
567 | } LoadF; | 539 | } LoadF; |
568 | 540 | ||
569 | 541 | static const char *getF(lua_State *L, void *ud, size_t *size) { | |
570 | static const char *getF (lua_State *L, void *ud, size_t *size) { | ||
571 | LoadF *lf = (LoadF *)ud; | 542 | LoadF *lf = (LoadF *)ud; |
572 | (void)L; /* not used */ | 543 | (void)L; |
573 | if (lf->n > 0) { /* are there pre-read characters to be read? */ | 544 | if (lf->extraline) { |
574 | *size = lf->n; /* return them (chars already in buffer) */ | 545 | lf->extraline = 0; |
575 | lf->n = 0; /* no more pre-read characters */ | 546 | *size = 1; |
576 | } | 547 | return "\n"; |
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; | ||
584 | } | 548 | } |
585 | return lf->buff; | 549 | *size = rb->read(lf->f, lf->buff, LUAL_BUFFERSIZE); |
550 | if (*size <= 0) return NULL; | ||
551 | return (*size > 0) ? lf->buff : NULL; | ||
586 | } | 552 | } |
587 | 553 | ||
588 | 554 | ||
@@ -594,68 +560,16 @@ static int errfile (lua_State *L, const char *what, int fnameindex) { | |||
594 | return LUA_ERRFILE; | 560 | return LUA_ERRFILE; |
595 | } | 561 | } |
596 | 562 | ||
597 | 563 | LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { | |
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) { | ||
634 | LoadF lf; | 564 | LoadF lf; |
635 | int status, readstatus; | 565 | int status; |
636 | int c; | ||
637 | int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ | 566 | int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ |
638 | lua_pushfstring(L, "@%s", filename); | 567 | lf.extraline = 0; |
639 | lf.n = 0; | ||
640 | lf.f = rb->open(filename, O_RDONLY); | 568 | lf.f = rb->open(filename, O_RDONLY); |
569 | lua_pushfstring(L, "@%s", filename); | ||
641 | if (lf.f < 0) return errfile(L, "open", fnameindex); | 570 | if (lf.f < 0) return errfile(L, "open", fnameindex); |
642 | if (skipcomment(&lf, &c)) /* read initial portion */ | 571 | status = lua_load(L, getF, &lf, lua_tostring(L, -1)); |
643 | lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ | 572 | rb->close(lf.f); |
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 | } | ||
659 | lua_remove(L, fnameindex); | 573 | lua_remove(L, fnameindex); |
660 | return status; | 574 | return status; |
661 | } | 575 | } |
@@ -669,7 +583,7 @@ typedef struct LoadS { | |||
669 | 583 | ||
670 | static const char *getS (lua_State *L, void *ud, size_t *size) { | 584 | static const char *getS (lua_State *L, void *ud, size_t *size) { |
671 | LoadS *ls = (LoadS *)ud; | 585 | LoadS *ls = (LoadS *)ud; |
672 | (void)L; /* not used */ | 586 | (void)L; |
673 | if (ls->size == 0) return NULL; | 587 | if (ls->size == 0) return NULL; |
674 | *size = ls->size; | 588 | *size = ls->size; |
675 | ls->size = 0; | 589 | ls->size = 0; |
@@ -677,245 +591,27 @@ static const char *getS (lua_State *L, void *ud, size_t *size) { | |||
677 | } | 591 | } |
678 | 592 | ||
679 | 593 | ||
680 | LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, | 594 | LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, |
681 | const char *name, const char *mode) { | 595 | const char *name) { |
682 | LoadS ls; | 596 | LoadS ls; |
683 | ls.s = buff; | 597 | ls.s = buff; |
684 | ls.size = size; | 598 | ls.size = size; |
685 | return lua_load(L, getS, &ls, name, mode); | 599 | return lua_load(L, getS, &ls, name); |
686 | } | 600 | } |
687 | 601 | ||
688 | 602 | ||
689 | LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { | 603 | LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { |
690 | return luaL_loadbuffer(L, s, strlen(s), s); | 604 | return luaL_loadbuffer(L, s, strlen(s), s); |
691 | } | 605 | } |
692 | 606 | ||
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 | } | ||
823 | 607 | ||
824 | 608 | ||
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 | ||
839 | /* }====================================================== */ | 609 | /* }====================================================== */ |
840 | 610 | ||
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 | |||
916 | 611 | ||
917 | static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { | 612 | static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { |
918 | (void)ud; (void)osize; /* not used */ | 613 | (void)ud; |
614 | (void)osize; | ||
919 | if (nsize == 0) { | 615 | if (nsize == 0) { |
920 | free(ptr); | 616 | free(ptr); |
921 | return NULL; | 617 | return NULL; |
@@ -926,11 +622,12 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { | |||
926 | 622 | ||
927 | 623 | ||
928 | static int panic (lua_State *L) { | 624 | static int panic (lua_State *L) { |
929 | DEBUGF("PANIC: unprotected error in call to Lua API (%s)\n", | 625 | DEBUGF("PANIC: unprotected error in call to Lua API (%s)\n", |
930 | lua_tostring(L, -1)); | 626 | lua_tostring(L, -1)); |
931 | rb->splashf(5 * HZ, "PANIC: unprotected error in call to Lua API (%s)", | 627 | rb->splashf(5 * HZ, "PANIC: unprotected error in call to Lua API (%s)", |
932 | lua_tostring(L, -1)); | 628 | lua_tostring(L, -1)); |
933 | return 0; /* return to Lua to abort */ | 629 | |
630 | return 0; | ||
934 | } | 631 | } |
935 | 632 | ||
936 | 633 | ||
@@ -940,20 +637,3 @@ LUALIB_API lua_State *luaL_newstate (void) { | |||
940 | return L; | 637 | return L; |
941 | } | 638 | } |
942 | 639 | ||
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 0fb023b8e7..a36de351fe 100644 --- a/apps/plugins/lua/lauxlib.h +++ b/apps/plugins/lua/lauxlib.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lauxlib.h,v 1.120.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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,6 +15,18 @@ | |||
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 | |||
18 | 30 | ||
19 | /* extra error code for `luaL_load' */ | 31 | /* extra error code for `luaL_load' */ |
20 | #define LUA_ERRFILE (LUA_ERRERR+1) | 32 | #define LUA_ERRFILE (LUA_ERRERR+1) |
@@ -26,12 +38,14 @@ typedef struct luaL_Reg { | |||
26 | } luaL_Reg; | 38 | } luaL_Reg; |
27 | 39 | ||
28 | 40 | ||
29 | LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver); | ||
30 | #define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) | ||
31 | 41 | ||
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); | ||
32 | LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); | 46 | LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); |
33 | LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); | 47 | LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); |
34 | LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); | 48 | LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); |
35 | LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); | 49 | LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); |
36 | LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, | 50 | LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, |
37 | size_t *l); | 51 | size_t *l); |
@@ -43,17 +57,16 @@ LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); | |||
43 | LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); | 57 | LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); |
44 | LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, | 58 | LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, |
45 | lua_Integer def); | 59 | lua_Integer def); |
46 | LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg); | 60 | |
47 | LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg, | 61 | LUALIB_API int (luaL_checkboolean) (lua_State *L, int numArg); |
48 | lua_Unsigned def); | 62 | LUALIB_API int (luaL_optboolean) (lua_State *L, int nArg, |
63 | int def); | ||
49 | 64 | ||
50 | LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); | 65 | LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); |
51 | LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); | 66 | LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); |
52 | LUALIB_API void (luaL_checkany) (lua_State *L, int narg); | 67 | LUALIB_API void (luaL_checkany) (lua_State *L, int narg); |
53 | 68 | ||
54 | LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); | 69 | 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); | ||
57 | LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); | 70 | LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); |
58 | 71 | ||
59 | LUALIB_API void (luaL_where) (lua_State *L, int lvl); | 72 | LUALIB_API void (luaL_where) (lua_State *L, int lvl); |
@@ -62,41 +75,25 @@ LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); | |||
62 | LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, | 75 | LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, |
63 | const char *const lst[]); | 76 | const char *const lst[]); |
64 | 77 | ||
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 | |||
72 | LUALIB_API int (luaL_ref) (lua_State *L, int t); | 78 | LUALIB_API int (luaL_ref) (lua_State *L, int t); |
73 | LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); | 79 | LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); |
74 | 80 | ||
75 | LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, | 81 | LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); |
76 | const char *mode); | 82 | LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, |
77 | 83 | const char *name); | |
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); | ||
82 | LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); | 84 | LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); |
83 | 85 | ||
84 | LUALIB_API lua_State *(luaL_newstate) (void); | 86 | LUALIB_API lua_State *(luaL_newstate) (void); |
85 | 87 | ||
86 | LUALIB_API int (luaL_len) (lua_State *L, int idx); | ||
87 | 88 | ||
88 | LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, | 89 | LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, |
89 | const char *r); | 90 | const char *r); |
90 | 91 | ||
91 | LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); | 92 | LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, |
93 | const char *fname, int szhint); | ||
92 | 94 | ||
93 | LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); | ||
94 | 95 | ||
95 | LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, | ||
96 | const char *msg, int level); | ||
97 | 96 | ||
98 | LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, | ||
99 | lua_CFunction openf, int glb); | ||
100 | 97 | ||
101 | /* | 98 | /* |
102 | ** =============================================================== | 99 | ** =============================================================== |
@@ -104,12 +101,6 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, | |||
104 | ** =============================================================== | 101 | ** =============================================================== |
105 | */ | 102 | */ |
106 | 103 | ||
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 | |||
113 | #define luaL_argcheck(L, cond,numarg,extramsg) \ | 104 | #define luaL_argcheck(L, cond,numarg,extramsg) \ |
114 | ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) | 105 | ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) |
115 | #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) | 106 | #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) |
@@ -131,81 +122,56 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, | |||
131 | 122 | ||
132 | #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) | 123 | #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) |
133 | 124 | ||
134 | #define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) | ||
135 | |||
136 | |||
137 | /* | 125 | /* |
138 | ** {====================================================== | 126 | ** {====================================================== |
139 | ** Generic Buffer manipulation | 127 | ** Generic Buffer manipulation |
140 | ** ======================================================= | 128 | ** ======================================================= |
141 | */ | 129 | */ |
142 | 130 | ||
131 | |||
132 | |||
143 | typedef struct luaL_Buffer { | 133 | typedef struct luaL_Buffer { |
144 | char *b; /* buffer address */ | 134 | char *p; /* current position in buffer */ |
145 | size_t size; /* buffer size */ | 135 | int lvl; /* number of strings in the stack (level) */ |
146 | size_t n; /* number of characters in buffer */ | ||
147 | lua_State *L; | 136 | lua_State *L; |
148 | char initb[LUAL_BUFFERSIZE]; /* initial buffer */ | 137 | char buffer[LUAL_BUFFERSIZE]; |
149 | } luaL_Buffer; | 138 | } luaL_Buffer; |
150 | 139 | ||
151 | |||
152 | #define luaL_addchar(B,c) \ | 140 | #define luaL_addchar(B,c) \ |
153 | ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ | 141 | ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ |
154 | ((B)->b[(B)->n++] = (c))) | 142 | (*(B)->p++ = (char)(c))) |
155 | 143 | ||
156 | #define luaL_addsize(B,s) ((B)->n += (s)) | 144 | /* compatibility only */ |
145 | #define luaL_putchar(B,c) luaL_addchar(B,c) | ||
146 | |||
147 | #define luaL_addsize(B,n) ((B)->p += (n)) | ||
157 | 148 | ||
158 | LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); | 149 | LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); |
159 | LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); | 150 | LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); |
160 | LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); | 151 | LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); |
161 | LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); | 152 | LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); |
162 | LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); | 153 | LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); |
163 | LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); | 154 | 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); | ||
166 | 155 | ||
167 | #define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) | ||
168 | 156 | ||
169 | /* }====================================================== */ | 157 | /* }====================================================== */ |
170 | 158 | ||
171 | 159 | ||
160 | /* compatibility with ref system */ | ||
172 | 161 | ||
173 | /* | 162 | /* pre-defined references */ |
174 | ** {====================================================== | 163 | #define LUA_NOREF (-2) |
175 | ** File handles for IO library | 164 | #define LUA_REFNIL (-1) |
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 | |||
195 | |||
196 | 165 | ||
197 | /* compatibility with old module system */ | 166 | #define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ |
198 | #if defined(LUA_COMPAT_MODULE) | 167 | (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) |
199 | 168 | ||
200 | LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, | 169 | #define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) |
201 | int sizehint); | ||
202 | LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, | ||
203 | const luaL_Reg *l, int nup); | ||
204 | 170 | ||
205 | #define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) | 171 | #define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) |
206 | 172 | ||
207 | #endif | ||
208 | 173 | ||
174 | #define luaL_reg luaL_Reg | ||
209 | 175 | ||
210 | #endif | 176 | #endif |
211 | 177 | ||
diff --git a/apps/plugins/lua/lbaselib.c b/apps/plugins/lua/lbaselib.c index 5255b3cd9b..008e3629fe 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.276.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 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,68 +20,62 @@ | |||
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 | ||
23 | static int luaB_print (lua_State *L) { | 32 | static int luaB_print (lua_State *L) { |
24 | int n = lua_gettop(L); /* number of arguments */ | 33 | int n = lua_gettop(L); /* number of arguments */ |
25 | int i; | 34 | int i; |
26 | lua_getglobal(L, "tostring"); | 35 | lua_getglobal(L, "tostring"); |
27 | for (i=1; i<=n; i++) { | 36 | for (i=1; i<=n; i++) { |
28 | const char *s; | 37 | const char *s; |
29 | size_t l; | ||
30 | lua_pushvalue(L, -1); /* function to be called */ | 38 | lua_pushvalue(L, -1); /* function to be called */ |
31 | lua_pushvalue(L, i); /* value to print */ | 39 | lua_pushvalue(L, i); /* value to print */ |
32 | lua_call(L, 1, 1); | 40 | lua_call(L, 1, 1); |
33 | s = lua_tolstring(L, -1, &l); /* get result */ | 41 | s = lua_tostring(L, -1); /* get result */ |
34 | if (s == NULL) | 42 | if (s == NULL) |
35 | return luaL_error(L, | 43 | return luaL_error(L, LUA_QL("tostring") " must return a string to " |
36 | LUA_QL("tostring") " must return a string to " LUA_QL("print")); | 44 | LUA_QL("print")); |
37 | if (i>1) luai_writestring("\t", 1); | 45 | if (i>1) fputs("\t", stdout); |
38 | luai_writestring(s, l); | 46 | fputs(s, stdout); |
39 | lua_pop(L, 1); /* pop result */ | 47 | lua_pop(L, 1); /* pop result */ |
40 | } | 48 | } |
41 | luai_writeline(); | 49 | fputs("\n", stdout); |
42 | return 0; | 50 | return 0; |
43 | } | 51 | } |
52 | #endif | ||
44 | 53 | ||
45 | 54 | ||
46 | #define SPACECHARS " \f\n\r\t\v" | ||
47 | |||
48 | static int luaB_tonumber (lua_State *L) { | 55 | static int luaB_tonumber (lua_State *L) { |
49 | if (lua_isnoneornil(L, 2)) { /* standard conversion */ | 56 | int base = luaL_optint(L, 2, 10); |
50 | int isnum; | 57 | if (base == 10) { /* standard conversion */ |
51 | lua_Number n = lua_tonumberx(L, 1, &isnum); | ||
52 | if (isnum) { | ||
53 | lua_pushnumber(L, n); | ||
54 | return 1; | ||
55 | } /* else not a number; must be something */ | ||
56 | luaL_checkany(L, 1); | 58 | luaL_checkany(L, 1); |
59 | if (lua_isnumber(L, 1)) { | ||
60 | lua_pushnumber(L, lua_tonumber(L, 1)); | ||
61 | return 1; | ||
62 | } | ||
57 | } | 63 | } |
58 | else { | 64 | else { |
59 | size_t l; | 65 | const char *s1 = luaL_checkstring(L, 1); |
60 | const char *s = luaL_checklstring(L, 1, &l); | 66 | char *s2; |
61 | const char *e = s + l; /* end point for 's' */ | 67 | unsigned long n; |
62 | int base = luaL_checkint(L, 2); | ||
63 | int neg = 0; | ||
64 | luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); | 68 | luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); |
65 | s += strspn(s, SPACECHARS); /* skip initial spaces */ | 69 | n = strtoul(s1, &s2, base); |
66 | if (*s == '-') { s++; neg = 1; } /* handle signal */ | 70 | if (s1 != s2) { /* at least one valid digit? */ |
67 | else if (*s == '+') s++; | 71 | while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ |
68 | if (isalnum((unsigned char)*s)) { | 72 | if (*s2 == '\0') { /* no invalid trailing characters? */ |
69 | lua_Number n = 0; | 73 | lua_pushnumber(L, (lua_Number)n); |
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); | ||
80 | return 1; | 74 | return 1; |
81 | } /* else not a number */ | 75 | } |
82 | } /* else not a number */ | 76 | } |
83 | } | 77 | } |
84 | lua_pushnil(L); /* not a number */ | 78 | lua_pushnil(L); /* else not a number */ |
85 | return 1; | 79 | return 1; |
86 | } | 80 | } |
87 | 81 | ||
@@ -115,26 +109,61 @@ static int luaB_setmetatable (lua_State *L) { | |||
115 | luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, | 109 | luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, |
116 | "nil or table expected"); | 110 | "nil or table expected"); |
117 | if (luaL_getmetafield(L, 1, "__metatable")) | 111 | if (luaL_getmetafield(L, 1, "__metatable")) |
118 | return luaL_error(L, "cannot change a protected metatable"); | 112 | luaL_error(L, "cannot change a protected metatable"); |
119 | lua_settop(L, 2); | 113 | lua_settop(L, 2); |
120 | lua_setmetatable(L, 1); | 114 | lua_setmetatable(L, 1); |
121 | return 1; | 115 | return 1; |
122 | } | 116 | } |
123 | 117 | ||
124 | 118 | ||
125 | static int luaB_rawequal (lua_State *L) { | 119 | static void getfunc (lua_State *L, int opt) { |
126 | luaL_checkany(L, 1); | 120 | if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); |
127 | luaL_checkany(L, 2); | 121 | else { |
128 | lua_pushboolean(L, lua_rawequal(L, 1, 2)); | 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); | ||
129 | return 1; | 141 | return 1; |
130 | } | 142 | } |
131 | 143 | ||
132 | 144 | ||
133 | static int luaB_rawlen (lua_State *L) { | 145 | static int luaB_setfenv (lua_State *L) { |
134 | int t = lua_type(L, 1); | 146 | luaL_checktype(L, 2, LUA_TTABLE); |
135 | luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, | 147 | getfunc(L, 0); |
136 | "table or string expected"); | 148 | lua_pushvalue(L, 2); |
137 | lua_pushinteger(L, lua_rawlen(L, 1)); | 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) { | ||
164 | luaL_checkany(L, 1); | ||
165 | luaL_checkany(L, 2); | ||
166 | lua_pushboolean(L, lua_rawequal(L, 1, 2)); | ||
138 | return 1; | 167 | return 1; |
139 | } | 168 | } |
140 | 169 | ||
@@ -157,29 +186,32 @@ static int luaB_rawset (lua_State *L) { | |||
157 | } | 186 | } |
158 | 187 | ||
159 | 188 | ||
189 | static int luaB_gcinfo (lua_State *L) { | ||
190 | lua_pushinteger(L, lua_getgccount(L)); | ||
191 | return 1; | ||
192 | } | ||
193 | |||
194 | |||
160 | static int luaB_collectgarbage (lua_State *L) { | 195 | static int luaB_collectgarbage (lua_State *L) { |
161 | static const char *const opts[] = {"stop", "restart", "collect", | 196 | static const char *const opts[] = {"stop", "restart", "collect", |
162 | "count", "step", "setpause", "setstepmul", | 197 | "count", "step", "setpause", "setstepmul", NULL}; |
163 | "setmajorinc", "isrunning", "generational", "incremental", NULL}; | ||
164 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, | 198 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, |
165 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, | 199 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; |
166 | LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; | 200 | int o = luaL_checkoption(L, 1, "collect", opts); |
167 | int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; | ||
168 | int ex = luaL_optint(L, 2, 0); | 201 | int ex = luaL_optint(L, 2, 0); |
169 | int res = lua_gc(L, o, ex); | 202 | int res = lua_gc(L, optsnum[o], ex); |
170 | switch (o) { | 203 | switch (optsnum[o]) { |
171 | case LUA_GCCOUNT: { | 204 | case LUA_GCCOUNT: { |
172 | int b = lua_gc(L, LUA_GCCOUNTB, 0); | 205 | int b = lua_gc(L, LUA_GCCOUNTB, 0); |
173 | lua_pushnumber(L, res + ((lua_Number)b/1024)); | 206 | lua_pushnumber(L, res + ((lua_Number)b/1024)); |
174 | lua_pushinteger(L, b); | 207 | return 1; |
175 | return 2; | ||
176 | } | 208 | } |
177 | case LUA_GCSTEP: case LUA_GCISRUNNING: { | 209 | case LUA_GCSTEP: { |
178 | lua_pushboolean(L, res); | 210 | lua_pushboolean(L, res); |
179 | return 1; | 211 | return 1; |
180 | } | 212 | } |
181 | default: { | 213 | default: { |
182 | lua_pushinteger(L, res); | 214 | lua_pushnumber(L, res); |
183 | return 1; | 215 | return 1; |
184 | } | 216 | } |
185 | } | 217 | } |
@@ -193,23 +225,6 @@ static int luaB_type (lua_State *L) { | |||
193 | } | 225 | } |
194 | 226 | ||
195 | 227 | ||
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 | |||
213 | static int luaB_next (lua_State *L) { | 228 | static int luaB_next (lua_State *L) { |
214 | luaL_checktype(L, 1, LUA_TTABLE); | 229 | luaL_checktype(L, 1, LUA_TTABLE); |
215 | lua_settop(L, 2); /* create a 2nd argument if there isn't one */ | 230 | lua_settop(L, 2); /* create a 2nd argument if there isn't one */ |
@@ -223,7 +238,11 @@ static int luaB_next (lua_State *L) { | |||
223 | 238 | ||
224 | 239 | ||
225 | static int luaB_pairs (lua_State *L) { | 240 | static int luaB_pairs (lua_State *L) { |
226 | return pairsmeta(L, "__pairs", 0, luaB_next); | 241 | luaL_checktype(L, 1, LUA_TTABLE); |
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; | ||
227 | } | 246 | } |
228 | 247 | ||
229 | 248 | ||
@@ -233,25 +252,23 @@ static int ipairsaux (lua_State *L) { | |||
233 | i++; /* next value */ | 252 | i++; /* next value */ |
234 | lua_pushinteger(L, i); | 253 | lua_pushinteger(L, i); |
235 | lua_rawgeti(L, 1, i); | 254 | lua_rawgeti(L, 1, i); |
236 | return (lua_isnil(L, -1)) ? 1 : 2; | 255 | return (lua_isnil(L, -1)) ? 0 : 2; |
237 | } | 256 | } |
238 | 257 | ||
239 | 258 | ||
240 | static int luaB_ipairs (lua_State *L) { | 259 | static int luaB_ipairs (lua_State *L) { |
241 | return pairsmeta(L, "__ipairs", 1, ipairsaux); | 260 | luaL_checktype(L, 1, LUA_TTABLE); |
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; | ||
242 | } | 265 | } |
243 | 266 | ||
244 | 267 | ||
245 | static int load_aux (lua_State *L, int status, int envidx) { | 268 | static int load_aux (lua_State *L, int status) { |
246 | if (status == LUA_OK) { | 269 | if (status == 0) /* 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 | } | ||
252 | return 1; | 270 | return 1; |
253 | } | 271 | else { |
254 | else { /* error (message is on top of the stack) */ | ||
255 | lua_pushnil(L); | 272 | lua_pushnil(L); |
256 | lua_insert(L, -2); /* put before error message */ | 273 | lua_insert(L, -2); /* put before error message */ |
257 | return 2; /* return nil plus error message */ | 274 | return 2; /* return nil plus error message */ |
@@ -259,28 +276,18 @@ static int load_aux (lua_State *L, int status, int envidx) { | |||
259 | } | 276 | } |
260 | 277 | ||
261 | 278 | ||
262 | static int luaB_loadfile (lua_State *L) { | 279 | static int luaB_loadstring (lua_State *L) { |
263 | const char *fname = luaL_optstring(L, 1, NULL); | 280 | size_t l; |
264 | const char *mode = luaL_optstring(L, 2, NULL); | 281 | const char *s = luaL_checklstring(L, 1, &l); |
265 | int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ | 282 | const char *chunkname = luaL_optstring(L, 2, s); |
266 | int status = luaL_loadfilex(L, fname, mode); | 283 | return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); |
267 | return load_aux(L, status, env); | ||
268 | } | 284 | } |
269 | 285 | ||
270 | 286 | ||
271 | /* | 287 | static int luaB_loadfile (lua_State *L) { |
272 | ** {====================================================== | 288 | const char *fname = luaL_optstring(L, 1, NULL); |
273 | ** Generic Read function | 289 | return load_aux(L, luaL_loadfile(L, fname)); |
274 | ** ======================================================= | 290 | } |
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 | 291 | ||
285 | 292 | ||
286 | /* | 293 | /* |
@@ -290,66 +297,66 @@ static int luaB_loadfile (lua_State *L) { | |||
290 | ** reserved slot inside the stack. | 297 | ** reserved slot inside the stack. |
291 | */ | 298 | */ |
292 | static const char *generic_reader (lua_State *L, void *ud, size_t *size) { | 299 | static const char *generic_reader (lua_State *L, void *ud, size_t *size) { |
293 | (void)(ud); /* not used */ | 300 | (void)ud; /* to avoid warnings */ |
294 | luaL_checkstack(L, 2, "too many nested functions"); | 301 | luaL_checkstack(L, 2, "too many nested functions"); |
295 | lua_pushvalue(L, 1); /* get function */ | 302 | lua_pushvalue(L, 1); /* get function */ |
296 | lua_call(L, 0, 1); /* call it */ | 303 | lua_call(L, 0, 1); /* call it */ |
297 | if (lua_isnil(L, -1)) { | 304 | if (lua_isnil(L, -1)) { |
298 | lua_pop(L, 1); /* pop result */ | ||
299 | *size = 0; | 305 | *size = 0; |
300 | return NULL; | 306 | return NULL; |
301 | } | 307 | } |
302 | else if (!lua_isstring(L, -1)) | 308 | else if (lua_isstring(L, -1)) { |
303 | luaL_error(L, "reader function must return a string"); | 309 | lua_replace(L, 3); /* save string in a reserved stack slot */ |
304 | lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ | 310 | return lua_tolstring(L, 3, size); |
305 | return lua_tolstring(L, RESERVEDSLOT, size); | 311 | } |
312 | else luaL_error(L, "reader function must return a string"); | ||
313 | return NULL; /* to avoid warnings */ | ||
306 | } | 314 | } |
307 | 315 | ||
308 | 316 | ||
309 | static int luaB_load (lua_State *L) { | 317 | static int luaB_load (lua_State *L) { |
310 | int status; | 318 | int status; |
311 | size_t l; | 319 | const char *cname = luaL_optstring(L, 2, "=(load)"); |
312 | const char *s = lua_tolstring(L, 1, &l); | 320 | luaL_checktype(L, 1, LUA_TFUNCTION); |
313 | const char *mode = luaL_optstring(L, 3, "bt"); | 321 | lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ |
314 | int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ | 322 | status = lua_load(L, generic_reader, NULL, cname); |
315 | if (s != NULL) { /* loading a string? */ | 323 | return load_aux(L, status); |
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; | ||
333 | } | 324 | } |
334 | 325 | ||
335 | 326 | ||
336 | static int luaB_dofile (lua_State *L) { | 327 | static int luaB_dofile (lua_State *L) { |
337 | const char *fname = luaL_optstring(L, 1, NULL); | 328 | const char *fname = luaL_optstring(L, 1, NULL); |
338 | lua_settop(L, 1); | 329 | int n = lua_gettop(L); |
339 | if (luaL_loadfile(L, fname) != LUA_OK) | 330 | if (luaL_loadfile(L, fname) != 0) lua_error(L); |
340 | return lua_error(L); | 331 | lua_call(L, 0, LUA_MULTRET); |
341 | lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); | 332 | return lua_gettop(L) - n; |
342 | return dofilecont(L); | ||
343 | } | 333 | } |
344 | 334 | ||
345 | 335 | ||
346 | static int luaB_assert (lua_State *L) { | 336 | static int luaB_assert (lua_State *L) { |
337 | luaL_checkany(L, 1); | ||
347 | if (!lua_toboolean(L, 1)) | 338 | if (!lua_toboolean(L, 1)) |
348 | return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); | 339 | return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); |
349 | return lua_gettop(L); | 340 | return lua_gettop(L); |
350 | } | 341 | } |
351 | 342 | ||
352 | 343 | ||
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 | |||
353 | static int luaB_select (lua_State *L) { | 360 | static int luaB_select (lua_State *L) { |
354 | int n = lua_gettop(L); | 361 | int n = lua_gettop(L); |
355 | if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { | 362 | if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { |
@@ -366,50 +373,75 @@ static int luaB_select (lua_State *L) { | |||
366 | } | 373 | } |
367 | 374 | ||
368 | 375 | ||
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 | |||
388 | static int luaB_pcall (lua_State *L) { | 376 | static int luaB_pcall (lua_State *L) { |
389 | int status; | 377 | int status; |
390 | luaL_checkany(L, 1); | 378 | luaL_checkany(L, 1); |
391 | lua_pushnil(L); | 379 | status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); |
392 | lua_insert(L, 1); /* create space for status result */ | 380 | lua_pushboolean(L, (status == 0)); |
393 | status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont); | 381 | lua_insert(L, 1); |
394 | return finishpcall(L, (status == LUA_OK)); | 382 | return lua_gettop(L); /* return status + all results */ |
395 | } | 383 | } |
396 | 384 | ||
397 | 385 | ||
398 | static int luaB_xpcall (lua_State *L) { | 386 | static int luaB_xpcall (lua_State *L) { |
399 | int status; | 387 | int status; |
400 | int n = lua_gettop(L); | 388 | luaL_checkany(L, 2); |
401 | luaL_argcheck(L, n >= 2, 2, "value expected"); | 389 | lua_settop(L, 2); |
402 | lua_pushvalue(L, 1); /* exchange function... */ | 390 | lua_insert(L, 1); /* put error function under function to be called */ |
403 | lua_copy(L, 2, 1); /* ...and error handler */ | 391 | status = lua_pcall(L, 0, LUA_MULTRET, 1); |
404 | lua_replace(L, 2); | 392 | lua_pushboolean(L, (status == 0)); |
405 | status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont); | 393 | lua_replace(L, 1); |
406 | return finishpcall(L, (status == LUA_OK)); | 394 | return lua_gettop(L); /* return status + all results */ |
407 | } | 395 | } |
408 | 396 | ||
409 | 397 | ||
410 | static int luaB_tostring (lua_State *L) { | 398 | static int luaB_tostring (lua_State *L) { |
411 | luaL_checkany(L, 1); | 399 | luaL_checkany(L, 1); |
412 | luaL_tolstring(L, 1, NULL); | 400 | if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ |
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); | ||
413 | return 1; | 445 | return 1; |
414 | } | 446 | } |
415 | 447 | ||
@@ -419,40 +451,207 @@ static const luaL_Reg base_funcs[] = { | |||
419 | {"collectgarbage", luaB_collectgarbage}, | 451 | {"collectgarbage", luaB_collectgarbage}, |
420 | {"dofile", luaB_dofile}, | 452 | {"dofile", luaB_dofile}, |
421 | {"error", luaB_error}, | 453 | {"error", luaB_error}, |
454 | {"gcinfo", luaB_gcinfo}, | ||
455 | {"getfenv", luaB_getfenv}, | ||
422 | {"getmetatable", luaB_getmetatable}, | 456 | {"getmetatable", luaB_getmetatable}, |
423 | {"ipairs", luaB_ipairs}, | ||
424 | {"loadfile", luaB_loadfile}, | 457 | {"loadfile", luaB_loadfile}, |
425 | {"load", luaB_load}, | 458 | {"load", luaB_load}, |
426 | #if defined(LUA_COMPAT_LOADSTRING) | 459 | {"loadstring", luaB_loadstring}, |
427 | {"loadstring", luaB_load}, | ||
428 | #endif | ||
429 | {"next", luaB_next}, | 460 | {"next", luaB_next}, |
430 | {"pairs", luaB_pairs}, | ||
431 | {"pcall", luaB_pcall}, | 461 | {"pcall", luaB_pcall}, |
462 | #if 0 | ||
432 | {"print", luaB_print}, | 463 | {"print", luaB_print}, |
464 | #endif | ||
433 | {"rawequal", luaB_rawequal}, | 465 | {"rawequal", luaB_rawequal}, |
434 | {"rawlen", luaB_rawlen}, | ||
435 | {"rawget", luaB_rawget}, | 466 | {"rawget", luaB_rawget}, |
436 | {"rawset", luaB_rawset}, | 467 | {"rawset", luaB_rawset}, |
437 | {"select", luaB_select}, | 468 | {"select", luaB_select}, |
469 | {"setfenv", luaB_setfenv}, | ||
438 | {"setmetatable", luaB_setmetatable}, | 470 | {"setmetatable", luaB_setmetatable}, |
439 | {"tonumber", luaB_tonumber}, | 471 | {"tonumber", luaB_tonumber}, |
440 | {"tostring", luaB_tostring}, | 472 | {"tostring", luaB_tostring}, |
441 | {"type", luaB_type}, | 473 | {"type", luaB_type}, |
474 | {"unpack", luaB_unpack}, | ||
442 | {"xpcall", luaB_xpcall}, | 475 | {"xpcall", luaB_xpcall}, |
443 | {NULL, NULL} | 476 | {NULL, NULL} |
444 | }; | 477 | }; |
445 | 478 | ||
446 | 479 | ||
447 | LUAMOD_API int luaopen_base (lua_State *L) { | 480 | /* |
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) { | ||
448 | /* set global _G */ | 631 | /* set global _G */ |
449 | lua_pushglobaltable(L); | 632 | lua_pushvalue(L, LUA_GLOBALSINDEX); |
450 | lua_pushglobaltable(L); | 633 | lua_setglobal(L, "_G"); |
451 | lua_setfield(L, -2, "_G"); | ||
452 | /* open lib into global table */ | 634 | /* open lib into global table */ |
453 | luaL_setfuncs(L, base_funcs, 0); | 635 | luaL_register(L, "_G", base_funcs); |
454 | lua_pushliteral(L, LUA_VERSION); | 636 | lua_pushliteral(L, LUA_VERSION); |
455 | lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */ | 637 | lua_setglobal(L, "_VERSION"); /* set global _VERSION */ |
456 | return 1; | 638 | /* `ipairs' and `pairs' need auxliliary functions as upvalues */ |
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; | ||
457 | } | 656 | } |
458 | 657 | ||
diff --git a/apps/plugins/lua/lbitlib.c b/apps/plugins/lua/lbitlib.c index 31c7b66f12..76c8d1d39b 100644 --- a/apps/plugins/lua/lbitlib.c +++ b/apps/plugins/lua/lbitlib.c | |||
@@ -1,212 +1,126 @@ | |||
1 | /* | 1 | /* Bitwise operations library */ |
2 | ** $Id: lbitlib.c,v 1.18.1.2 2013/07/09 18:01:41 roberto Exp $ | 2 | /* (c) Reuben Thomas 2000-2008 */ |
3 | ** Standard library for bitwise operations | 3 | /* bitlib is copyright Reuben Thomas 2000-2008, and is released under the MIT |
4 | ** See Copyright Notice in lua.h | 4 | license, like Lua (see http://www.lua.org/copyright.html; it's |
5 | */ | 5 | basically the same as the BSD license). There is no warranty. */ |
6 | 6 | ||
7 | #define lbitlib_c | 7 | #include "config.h" |
8 | #define LUA_LIB | ||
9 | 8 | ||
10 | #include "lua.h" | 9 | #include "lua.h" |
11 | |||
12 | #include "lauxlib.h" | 10 | #include "lauxlib.h" |
13 | #include "lualib.h" | 11 | #include "lualib.h" |
12 | #include <limits.h> | ||
14 | 13 | ||
15 | 14 | ||
16 | /* number of bits to consider in a number */ | 15 | /* FIXME: Assume lua_Integer is ptrdiff_t */ |
17 | #if !defined(LUA_NBITS) | 16 | #define LUA_INTEGER_MAX INTPTR_MAX |
18 | #define LUA_NBITS 32 | 17 | #define LUA_INTEGER_MIN INTPTR_MIN |
19 | #endif | ||
20 | |||
21 | |||
22 | #define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) | ||
23 | |||
24 | /* macro to trim extra bits */ | ||
25 | #define trim(x) ((x) & ALLONES) | ||
26 | |||
27 | |||
28 | /* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ | ||
29 | #define mask(n) (~((ALLONES << 1) << ((n) - 1))) | ||
30 | 18 | ||
19 | /* FIXME: Assume size_t is an unsigned lua_Integer */ | ||
20 | typedef size_t lua_UInteger; | ||
21 | #define LUA_UINTEGER_MAX UINT_MAX | ||
31 | 22 | ||
32 | typedef lua_Unsigned b_uint; | ||
33 | 23 | ||
24 | /* Bit type size and limits */ | ||
34 | 25 | ||
26 | #define BIT_BITS (CHAR_BIT * sizeof(lua_Integer)) | ||
35 | 27 | ||
36 | static b_uint andaux (lua_State *L) { | 28 | /* This code may give warnings if BITLIB_FLOAT_* are too big to fit in |
37 | int i, n = lua_gettop(L); | 29 | long, but that doesn't matter since in that case they won't be |
38 | b_uint r = ~(b_uint)0; | 30 | used. */ |
39 | for (i = 1; i <= n; i++) | 31 | #define BIT_MAX (LUA_INTEGER_MAX) |
40 | r &= luaL_checkunsigned(L, i); | ||
41 | return trim(r); | ||
42 | } | ||
43 | 32 | ||
33 | #define BIT_MIN (LUA_INTEGER_MIN) | ||
44 | 34 | ||
45 | static int b_and (lua_State *L) { | 35 | #define BIT_UMAX (LUA_UINTEGER_MAX) |
46 | b_uint r = andaux(L); | ||
47 | lua_pushunsigned(L, r); | ||
48 | return 1; | ||
49 | } | ||
50 | 36 | ||
51 | 37 | ||
52 | static int b_test (lua_State *L) { | 38 | /* Define TOBIT to get a bit value */ |
53 | b_uint r = andaux(L); | 39 | #ifdef BUILTIN_CAST |
54 | lua_pushboolean(L, r != 0); | 40 | #define |
55 | return 1; | 41 | #define TOBIT(L, n, res) \ |
56 | } | 42 | ((void)(res), luaL_checkinteger((L), (n))) |
43 | #else | ||
57 | 44 | ||
45 | #define TOBIT(L, n, res) \ | ||
46 | ((lua_Integer)(((res) = luaL_checknumber(L, (n)) % BIT_UMAX), \ | ||
47 | (res) > BIT_MAX ? ((res) -= BIT_UMAX, (res) -= 1) : \ | ||
48 | ((res) < BIT_MIN ? ((res) += BIT_UMAX, (res) += 1) : (res)))) | ||
49 | #endif | ||
58 | 50 | ||
59 | static int b_or (lua_State *L) { | ||
60 | int i, n = lua_gettop(L); | ||
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 | } | ||
67 | 51 | ||
52 | #define BIT_TRUNCATE(i) \ | ||
53 | ((i) & BIT_UMAX) | ||
68 | 54 | ||
69 | static int b_xor (lua_State *L) { | ||
70 | int i, n = lua_gettop(L); | ||
71 | b_uint r = 0; | ||
72 | for (i = 1; i <= n; i++) | ||
73 | r ^= luaL_checkunsigned(L, i); | ||
74 | lua_pushunsigned(L, trim(r)); | ||
75 | return 1; | ||
76 | } | ||
77 | 55 | ||
56 | /* Operations | ||
78 | 57 | ||
79 | static int b_not (lua_State *L) { | 58 | The macros MONADIC and VARIADIC only deal with bitwise operations. |
80 | b_uint r = ~luaL_checkunsigned(L, 1); | ||
81 | lua_pushunsigned(L, trim(r)); | ||
82 | return 1; | ||
83 | } | ||
84 | 59 | ||
60 | LOGICAL_SHIFT truncates its left-hand operand before shifting so | ||
61 | that any extra bits at the most-significant end are not shifted | ||
62 | into the result. | ||
85 | 63 | ||
86 | static int b_shift (lua_State *L, b_uint r, int i) { | 64 | ARITHMETIC_SHIFT does not truncate its left-hand operand, so that |
87 | if (i < 0) { /* shift right? */ | 65 | the sign bits are not removed and right shift work properly. |
88 | i = -i; | 66 | */ |
89 | r = trim(r); | 67 | |
90 | if (i >= LUA_NBITS) r = 0; | 68 | #define MONADIC(name, op) \ |
91 | else r >>= i; | 69 | static int bit_ ## name(lua_State *L) { \ |
92 | } | 70 | lua_Number f; \ |
93 | else { /* shift left */ | 71 | lua_pushinteger(L, BIT_TRUNCATE(op TOBIT(L, 1, f))); \ |
94 | if (i >= LUA_NBITS) r = 0; | 72 | return 1; \ |
95 | else r <<= i; | ||
96 | r = trim(r); | ||
97 | } | 73 | } |
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 | } | ||
111 | 74 | ||
112 | 75 | #define VARIADIC(name, op) \ | |
113 | static int b_arshift (lua_State *L) { | 76 | static int bit_ ## name(lua_State *L) { \ |
114 | b_uint r = luaL_checkunsigned(L, 1); | 77 | lua_Number f; \ |
115 | int i = luaL_checkint(L, 2); | 78 | int n = lua_gettop(L), i; \ |
116 | if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1)))) | 79 | lua_Integer w = TOBIT(L, 1, f); \ |
117 | return b_shift(L, r, -i); | 80 | for (i = 2; i <= n; i++) \ |
118 | else { /* arithmetic shift for 'negative' number */ | 81 | w op TOBIT(L, i, f); \ |
119 | if (i >= LUA_NBITS) r = ALLONES; | 82 | lua_pushinteger(L, BIT_TRUNCATE(w)); \ |
120 | else | 83 | return 1; \ |
121 | r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */ | ||
122 | lua_pushunsigned(L, r); | ||
123 | return 1; | ||
124 | } | 84 | } |
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 | |||
138 | 85 | ||
139 | static int b_lrot (lua_State *L) { | 86 | #define LOGICAL_SHIFT(name, op) \ |
140 | return b_rot(L, luaL_checkint(L, 2)); | 87 | static int bit_ ## name(lua_State *L) { \ |
141 | } | 88 | lua_Number f; \ |
142 | 89 | lua_pushinteger(L, BIT_TRUNCATE(BIT_TRUNCATE((lua_UInteger)TOBIT(L, 1, f)) op \ | |
143 | 90 | (unsigned)luaL_checknumber(L, 2))); \ | |
144 | static int b_rrot (lua_State *L) { | 91 | return 1; \ |
145 | return b_rot(L, -luaL_checkint(L, 2)); | 92 | } |
146 | } | ||
147 | |||
148 | |||
149 | /* | ||
150 | ** get field and width arguments for field-manipulation functions, | ||
151 | ** checking whether they are valid. | ||
152 | ** ('luaL_error' called without 'return' to avoid later warnings about | ||
153 | ** 'width' being used uninitialized.) | ||
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 | 93 | ||
94 | #define ARITHMETIC_SHIFT(name, op) \ | ||
95 | static int bit_ ## name(lua_State *L) { \ | ||
96 | lua_Number f; \ | ||
97 | lua_pushinteger(L, BIT_TRUNCATE((lua_Integer)TOBIT(L, 1, f) op \ | ||
98 | (unsigned)luaL_checknumber(L, 2))); \ | ||
99 | return 1; \ | ||
100 | } | ||
189 | 101 | ||
190 | static const luaL_Reg bitlib[] = { | 102 | MONADIC(bnot, ~) |
191 | {"arshift", b_arshift}, | 103 | VARIADIC(band, &=) |
192 | {"band", b_and}, | 104 | VARIADIC(bor, |=) |
193 | {"bnot", b_not}, | 105 | VARIADIC(bxor, ^=) |
194 | {"bor", b_or}, | 106 | ARITHMETIC_SHIFT(lshift, <<) |
195 | {"bxor", b_xor}, | 107 | LOGICAL_SHIFT(rshift, >>) |
196 | {"btest", b_test}, | 108 | ARITHMETIC_SHIFT(arshift, >>) |
197 | {"extract", b_extract}, | 109 | |
198 | {"lrotate", b_lrot}, | 110 | static const struct luaL_reg bitlib[] = { |
199 | {"lshift", b_lshift}, | 111 | {"bnot", bit_bnot}, |
200 | {"replace", b_replace}, | 112 | {"band", bit_band}, |
201 | {"rrotate", b_rrot}, | 113 | {"bor", bit_bor}, |
202 | {"rshift", b_rshift}, | 114 | {"bxor", bit_bxor}, |
115 | {"lshift", bit_lshift}, | ||
116 | {"rshift", bit_rshift}, | ||
117 | {"arshift", bit_arshift}, | ||
203 | {NULL, NULL} | 118 | {NULL, NULL} |
204 | }; | 119 | }; |
205 | 120 | ||
206 | 121 | LUALIB_API int luaopen_bit (lua_State *L) { | |
207 | 122 | luaL_register(L, "bit", bitlib); | |
208 | LUAMOD_API int luaopen_bit32 (lua_State *L) { | 123 | lua_pushnumber(L, BIT_BITS); |
209 | luaL_newlib(L, bitlib); | 124 | lua_setfield(L, -2, "bits"); |
210 | return 1; | 125 | return 1; |
211 | } | 126 | } |
212 | |||
diff --git a/apps/plugins/lua/lcode.c b/apps/plugins/lua/lcode.c index 820b95c0e1..cff626b7fa 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.62.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 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,9 +21,7 @@ | |||
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" | ||
25 | #include "ltable.h" | 24 | #include "ltable.h" |
26 | #include "lvm.h" | ||
27 | 25 | ||
28 | 26 | ||
29 | #define hasjumps(e) ((e)->t != (e)->f) | 27 | #define hasjumps(e) ((e)->t != (e)->f) |
@@ -36,23 +34,25 @@ static int isnumeral(expdesc *e) { | |||
36 | 34 | ||
37 | void luaK_nil (FuncState *fs, int from, int n) { | 35 | void luaK_nil (FuncState *fs, int from, int n) { |
38 | Instruction *previous; | 36 | Instruction *previous; |
39 | int l = from + n - 1; /* last register to set nil */ | ||
40 | if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ | 37 | if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ |
41 | previous = &fs->f->code[fs->pc-1]; | 38 | if (fs->pc == 0) { /* function start? */ |
42 | if (GET_OPCODE(*previous) == OP_LOADNIL) { | 39 | if (from >= fs->nactvar) |
43 | int pfrom = GETARG_A(*previous); | 40 | return; /* positions are already clean */ |
44 | int pl = pfrom + GETARG_B(*previous); | 41 | } |
45 | if ((pfrom <= from && from <= pl + 1) || | 42 | else { |
46 | (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ | 43 | previous = &fs->f->code[fs->pc-1]; |
47 | if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ | 44 | if (GET_OPCODE(*previous) == OP_LOADNIL) { |
48 | if (pl > l) l = pl; /* l = max(l, pl) */ | 45 | int pfrom = GETARG_A(*previous); |
49 | SETARG_A(*previous, from); | 46 | int pto = GETARG_B(*previous); |
50 | SETARG_B(*previous, l - from); | 47 | if (pfrom <= from && from <= pto+1) { /* can connect both? */ |
51 | return; | 48 | if (from+n-1 > pto) |
49 | SETARG_B(*previous, from+n-1); | ||
50 | return; | ||
51 | } | ||
52 | } | 52 | } |
53 | } /* else go through */ | 53 | } |
54 | } | 54 | } |
55 | luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ | 55 | luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ |
56 | } | 56 | } |
57 | 57 | ||
58 | 58 | ||
@@ -176,19 +176,6 @@ 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 | |||
192 | void luaK_patchtohere (FuncState *fs, int list) { | 179 | void luaK_patchtohere (FuncState *fs, int list) { |
193 | luaK_getlabel(fs); | 180 | luaK_getlabel(fs); |
194 | luaK_concat(fs, &fs->jpc, list); | 181 | luaK_concat(fs, &fs->jpc, list); |
@@ -209,55 +196,6 @@ void luaK_concat (FuncState *fs, int *l1, int l2) { | |||
209 | } | 196 | } |
210 | 197 | ||
211 | 198 | ||
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 | |||
261 | void luaK_checkstack (FuncState *fs, int n) { | 199 | void luaK_checkstack (FuncState *fs, int n) { |
262 | int newstack = fs->freereg + n; | 200 | int newstack = fs->freereg + n; |
263 | if (newstack > fs->f->maxstacksize) { | 201 | if (newstack > fs->f->maxstacksize) { |
@@ -284,59 +222,42 @@ static void freereg (FuncState *fs, int reg) { | |||
284 | 222 | ||
285 | static void freeexp (FuncState *fs, expdesc *e) { | 223 | static void freeexp (FuncState *fs, expdesc *e) { |
286 | if (e->k == VNONRELOC) | 224 | if (e->k == VNONRELOC) |
287 | freereg(fs, e->u.info); | 225 | freereg(fs, e->u.s.info); |
288 | } | 226 | } |
289 | 227 | ||
290 | 228 | ||
291 | static int addk (FuncState *fs, TValue *key, TValue *v) { | 229 | static int addk (FuncState *fs, TValue *k, TValue *v) { |
292 | lua_State *L = fs->ls->L; | 230 | lua_State *L = fs->L; |
293 | TValue *idx = luaH_set(L, fs->h, key); | 231 | TValue *idx = luaH_set(L, fs->h, k); |
294 | Proto *f = fs->f; | 232 | Proto *f = fs->f; |
295 | int k, oldsize; | 233 | int oldsize = f->sizek; |
296 | if (ttisnumber(idx)) { | 234 | if (ttisnumber(idx)) { |
297 | lua_Number n = nvalue(idx); | 235 | lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); |
298 | lua_number2int(k, n); | 236 | return cast_int(nvalue(idx)); |
299 | if (luaV_rawequalobj(&f->k[k], v)) | 237 | } |
300 | return k; | 238 | else { /* constant not found; create a new entry */ |
301 | /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); | 239 | setnvalue(idx, cast_num(fs->nk)); |
302 | go through and create a new entry for this value */ | 240 | luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, |
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++; | ||
303 | } | 246 | } |
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; | ||
316 | } | 247 | } |
317 | 248 | ||
318 | 249 | ||
319 | int luaK_stringK (FuncState *fs, TString *s) { | 250 | int luaK_stringK (FuncState *fs, TString *s) { |
320 | TValue o; | 251 | TValue o; |
321 | setsvalue(fs->ls->L, &o, s); | 252 | setsvalue(fs->L, &o, s); |
322 | return addk(fs, &o, &o); | 253 | return addk(fs, &o, &o); |
323 | } | 254 | } |
324 | 255 | ||
325 | 256 | ||
326 | int luaK_numberK (FuncState *fs, lua_Number r) { | 257 | int luaK_numberK (FuncState *fs, lua_Number r) { |
327 | int n; | ||
328 | lua_State *L = fs->ls->L; | ||
329 | TValue o; | 258 | TValue o; |
330 | setnvalue(&o, r); | 259 | setnvalue(&o, r); |
331 | if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ | 260 | return addk(fs, &o, &o); |
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; | ||
340 | } | 261 | } |
341 | 262 | ||
342 | 263 | ||
@@ -351,7 +272,7 @@ static int nilK (FuncState *fs) { | |||
351 | TValue k, v; | 272 | TValue k, v; |
352 | setnilvalue(&v); | 273 | setnilvalue(&v); |
353 | /* cannot use nil as key; instead use table itself to represent nil */ | 274 | /* cannot use nil as key; instead use table itself to represent nil */ |
354 | sethvalue(fs->ls->L, &k, fs->h); | 275 | sethvalue(fs->L, &k, fs->h); |
355 | return addk(fs, &k, &v); | 276 | return addk(fs, &k, &v); |
356 | } | 277 | } |
357 | 278 | ||
@@ -371,7 +292,7 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { | |||
371 | void luaK_setoneret (FuncState *fs, expdesc *e) { | 292 | void luaK_setoneret (FuncState *fs, expdesc *e) { |
372 | if (e->k == VCALL) { /* expression is an open function call? */ | 293 | if (e->k == VCALL) { /* expression is an open function call? */ |
373 | e->k = VNONRELOC; | 294 | e->k = VNONRELOC; |
374 | e->u.info = GETARG_A(getcode(fs, e)); | 295 | e->u.s.info = GETARG_A(getcode(fs, e)); |
375 | } | 296 | } |
376 | else if (e->k == VVARARG) { | 297 | else if (e->k == VVARARG) { |
377 | SETARG_B(getcode(fs, e), 2); | 298 | SETARG_B(getcode(fs, e), 2); |
@@ -387,18 +308,19 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
387 | break; | 308 | break; |
388 | } | 309 | } |
389 | case VUPVAL: { | 310 | case VUPVAL: { |
390 | e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); | 311 | e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.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); | ||
391 | e->k = VRELOCABLE; | 317 | e->k = VRELOCABLE; |
392 | break; | 318 | break; |
393 | } | 319 | } |
394 | case VINDEXED: { | 320 | case VINDEXED: { |
395 | OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ | 321 | freereg(fs, e->u.s.aux); |
396 | freereg(fs, e->u.ind.idx); | 322 | freereg(fs, e->u.s.info); |
397 | if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ | 323 | e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); |
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); | ||
402 | e->k = VRELOCABLE; | 324 | e->k = VRELOCABLE; |
403 | break; | 325 | break; |
404 | } | 326 | } |
@@ -425,16 +347,16 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
425 | luaK_nil(fs, reg, 1); | 347 | luaK_nil(fs, reg, 1); |
426 | break; | 348 | break; |
427 | } | 349 | } |
428 | case VFALSE: case VTRUE: { | 350 | case VFALSE: case VTRUE: { |
429 | luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); | 351 | luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); |
430 | break; | 352 | break; |
431 | } | 353 | } |
432 | case VK: { | 354 | case VK: { |
433 | luaK_codek(fs, reg, e->u.info); | 355 | luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); |
434 | break; | 356 | break; |
435 | } | 357 | } |
436 | case VKNUM: { | 358 | case VKNUM: { |
437 | luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); | 359 | luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); |
438 | break; | 360 | break; |
439 | } | 361 | } |
440 | case VRELOCABLE: { | 362 | case VRELOCABLE: { |
@@ -443,8 +365,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
443 | break; | 365 | break; |
444 | } | 366 | } |
445 | case VNONRELOC: { | 367 | case VNONRELOC: { |
446 | if (reg != e->u.info) | 368 | if (reg != e->u.s.info) |
447 | luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); | 369 | luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); |
448 | break; | 370 | break; |
449 | } | 371 | } |
450 | default: { | 372 | default: { |
@@ -452,7 +374,7 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
452 | return; /* nothing to do... */ | 374 | return; /* nothing to do... */ |
453 | } | 375 | } |
454 | } | 376 | } |
455 | e->u.info = reg; | 377 | e->u.s.info = reg; |
456 | e->k = VNONRELOC; | 378 | e->k = VNONRELOC; |
457 | } | 379 | } |
458 | 380 | ||
@@ -468,7 +390,7 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) { | |||
468 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { | 390 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { |
469 | discharge2reg(fs, e, reg); | 391 | discharge2reg(fs, e, reg); |
470 | if (e->k == VJMP) | 392 | if (e->k == VJMP) |
471 | luaK_concat(fs, &e->t, e->u.info); /* put this jump in `t' list */ | 393 | luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ |
472 | if (hasjumps(e)) { | 394 | if (hasjumps(e)) { |
473 | int final; /* position after whole expression */ | 395 | int final; /* position after whole expression */ |
474 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ | 396 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ |
@@ -484,7 +406,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { | |||
484 | patchlistaux(fs, e->t, final, reg, p_t); | 406 | patchlistaux(fs, e->t, final, reg, p_t); |
485 | } | 407 | } |
486 | e->f = e->t = NO_JUMP; | 408 | e->f = e->t = NO_JUMP; |
487 | e->u.info = reg; | 409 | e->u.s.info = reg; |
488 | e->k = VNONRELOC; | 410 | e->k = VNONRELOC; |
489 | } | 411 | } |
490 | 412 | ||
@@ -500,20 +422,14 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) { | |||
500 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | 422 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { |
501 | luaK_dischargevars(fs, e); | 423 | luaK_dischargevars(fs, e); |
502 | if (e->k == VNONRELOC) { | 424 | if (e->k == VNONRELOC) { |
503 | if (!hasjumps(e)) return e->u.info; /* exp is already in a register */ | 425 | if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ |
504 | if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ | 426 | if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ |
505 | exp2reg(fs, e, e->u.info); /* put value on it */ | 427 | exp2reg(fs, e, e->u.s.info); /* put value on it */ |
506 | return e->u.info; | 428 | return e->u.s.info; |
507 | } | 429 | } |
508 | } | 430 | } |
509 | luaK_exp2nextreg(fs, e); /* default */ | 431 | luaK_exp2nextreg(fs, e); /* default */ |
510 | return e->u.info; | 432 | return e->u.s.info; |
511 | } | ||
512 | |||
513 | |||
514 | void luaK_exp2anyregup (FuncState *fs, expdesc *e) { | ||
515 | if (e->k != VUPVAL || hasjumps(e)) | ||
516 | luaK_exp2anyreg(fs, e); | ||
517 | } | 433 | } |
518 | 434 | ||
519 | 435 | ||
@@ -528,24 +444,22 @@ void luaK_exp2val (FuncState *fs, expdesc *e) { | |||
528 | int luaK_exp2RK (FuncState *fs, expdesc *e) { | 444 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
529 | luaK_exp2val(fs, e); | 445 | luaK_exp2val(fs, e); |
530 | switch (e->k) { | 446 | switch (e->k) { |
447 | case VKNUM: | ||
531 | case VTRUE: | 448 | case VTRUE: |
532 | case VFALSE: | 449 | case VFALSE: |
533 | case VNIL: { | 450 | case VNIL: { |
534 | if (fs->nk <= MAXINDEXRK) { /* constant fits in RK operand? */ | 451 | if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ |
535 | e->u.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE)); | 452 | e->u.s.info = (e->k == VNIL) ? nilK(fs) : |
453 | (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : | ||
454 | boolK(fs, (e->k == VTRUE)); | ||
536 | e->k = VK; | 455 | e->k = VK; |
537 | return RKASK(e->u.info); | 456 | return RKASK(e->u.s.info); |
538 | } | 457 | } |
539 | else break; | 458 | else break; |
540 | } | 459 | } |
541 | case VKNUM: { | ||
542 | e->u.info = luaK_numberK(fs, e->u.nval); | ||
543 | e->k = VK; | ||
544 | /* go through */ | ||
545 | } | ||
546 | case VK: { | 460 | case VK: { |
547 | if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */ | 461 | if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ |
548 | return RKASK(e->u.info); | 462 | return RKASK(e->u.s.info); |
549 | else break; | 463 | else break; |
550 | } | 464 | } |
551 | default: break; | 465 | default: break; |
@@ -559,18 +473,22 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { | |||
559 | switch (var->k) { | 473 | switch (var->k) { |
560 | case VLOCAL: { | 474 | case VLOCAL: { |
561 | freeexp(fs, ex); | 475 | freeexp(fs, ex); |
562 | exp2reg(fs, ex, var->u.info); | 476 | exp2reg(fs, ex, var->u.s.info); |
563 | return; | 477 | return; |
564 | } | 478 | } |
565 | case VUPVAL: { | 479 | case VUPVAL: { |
566 | int e = luaK_exp2anyreg(fs, ex); | 480 | int e = luaK_exp2anyreg(fs, ex); |
567 | luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); | 481 | luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.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); | ||
568 | break; | 487 | break; |
569 | } | 488 | } |
570 | case VINDEXED: { | 489 | case VINDEXED: { |
571 | OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; | ||
572 | int e = luaK_exp2RK(fs, ex); | 490 | int e = luaK_exp2RK(fs, ex); |
573 | luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); | 491 | luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); |
574 | break; | 492 | break; |
575 | } | 493 | } |
576 | default: { | 494 | default: { |
@@ -583,20 +501,20 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { | |||
583 | 501 | ||
584 | 502 | ||
585 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { | 503 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { |
586 | int ereg; | 504 | int func; |
587 | luaK_exp2anyreg(fs, e); | 505 | luaK_exp2anyreg(fs, e); |
588 | ereg = e->u.info; /* register where 'e' was placed */ | ||
589 | freeexp(fs, e); | 506 | freeexp(fs, e); |
590 | e->u.info = fs->freereg; /* base register for op_self */ | 507 | func = fs->freereg; |
591 | e->k = VNONRELOC; | 508 | luaK_reserveregs(fs, 2); |
592 | luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ | 509 | luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); |
593 | luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key)); | ||
594 | freeexp(fs, key); | 510 | freeexp(fs, key); |
511 | e->u.s.info = func; | ||
512 | e->k = VNONRELOC; | ||
595 | } | 513 | } |
596 | 514 | ||
597 | 515 | ||
598 | static void invertjump (FuncState *fs, expdesc *e) { | 516 | static void invertjump (FuncState *fs, expdesc *e) { |
599 | Instruction *pc = getjumpcontrol(fs, e->u.info); | 517 | Instruction *pc = getjumpcontrol(fs, e->u.s.info); |
600 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && | 518 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && |
601 | GET_OPCODE(*pc) != OP_TEST); | 519 | GET_OPCODE(*pc) != OP_TEST); |
602 | SETARG_A(*pc, !(GETARG_A(*pc))); | 520 | SETARG_A(*pc, !(GETARG_A(*pc))); |
@@ -614,7 +532,7 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { | |||
614 | } | 532 | } |
615 | discharge2anyreg(fs, e); | 533 | discharge2anyreg(fs, e); |
616 | freeexp(fs, e); | 534 | freeexp(fs, e); |
617 | return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); | 535 | return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); |
618 | } | 536 | } |
619 | 537 | ||
620 | 538 | ||
@@ -622,15 +540,19 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { | |||
622 | int pc; /* pc of last jump */ | 540 | int pc; /* pc of last jump */ |
623 | luaK_dischargevars(fs, e); | 541 | luaK_dischargevars(fs, e); |
624 | switch (e->k) { | 542 | switch (e->k) { |
625 | case VJMP: { | ||
626 | invertjump(fs, e); | ||
627 | pc = e->u.info; | ||
628 | break; | ||
629 | } | ||
630 | case VK: case VKNUM: case VTRUE: { | 543 | case VK: case VKNUM: case VTRUE: { |
631 | pc = NO_JUMP; /* always true; do nothing */ | 544 | pc = NO_JUMP; /* always true; do nothing */ |
632 | break; | 545 | break; |
633 | } | 546 | } |
547 | case VFALSE: { | ||
548 | pc = luaK_jump(fs); /* always jump */ | ||
549 | break; | ||
550 | } | ||
551 | case VJMP: { | ||
552 | invertjump(fs, e); | ||
553 | pc = e->u.s.info; | ||
554 | break; | ||
555 | } | ||
634 | default: { | 556 | default: { |
635 | pc = jumponcond(fs, e, 0); | 557 | pc = jumponcond(fs, e, 0); |
636 | break; | 558 | break; |
@@ -642,18 +564,22 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { | |||
642 | } | 564 | } |
643 | 565 | ||
644 | 566 | ||
645 | void luaK_goiffalse (FuncState *fs, expdesc *e) { | 567 | static void luaK_goiffalse (FuncState *fs, expdesc *e) { |
646 | int pc; /* pc of last jump */ | 568 | int pc; /* pc of last jump */ |
647 | luaK_dischargevars(fs, e); | 569 | luaK_dischargevars(fs, e); |
648 | switch (e->k) { | 570 | switch (e->k) { |
649 | case VJMP: { | ||
650 | pc = e->u.info; | ||
651 | break; | ||
652 | } | ||
653 | case VNIL: case VFALSE: { | 571 | case VNIL: case VFALSE: { |
654 | pc = NO_JUMP; /* always false; do nothing */ | 572 | pc = NO_JUMP; /* always false; do nothing */ |
655 | break; | 573 | break; |
656 | } | 574 | } |
575 | case VTRUE: { | ||
576 | pc = luaK_jump(fs); /* always jump */ | ||
577 | break; | ||
578 | } | ||
579 | case VJMP: { | ||
580 | pc = e->u.s.info; | ||
581 | break; | ||
582 | } | ||
657 | default: { | 583 | default: { |
658 | pc = jumponcond(fs, e, 1); | 584 | pc = jumponcond(fs, e, 1); |
659 | break; | 585 | break; |
@@ -684,7 +610,7 @@ static void codenot (FuncState *fs, expdesc *e) { | |||
684 | case VNONRELOC: { | 610 | case VNONRELOC: { |
685 | discharge2anyreg(fs, e); | 611 | discharge2anyreg(fs, e); |
686 | freeexp(fs, e); | 612 | freeexp(fs, e); |
687 | e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); | 613 | e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); |
688 | e->k = VRELOCABLE; | 614 | e->k = VRELOCABLE; |
689 | break; | 615 | break; |
690 | } | 616 | } |
@@ -701,28 +627,38 @@ static void codenot (FuncState *fs, expdesc *e) { | |||
701 | 627 | ||
702 | 628 | ||
703 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | 629 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { |
704 | lua_assert(!hasjumps(t)); | 630 | t->u.s.aux = luaK_exp2RK(fs, k); |
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); | ||
709 | t->k = VINDEXED; | 631 | t->k = VINDEXED; |
710 | } | 632 | } |
711 | 633 | ||
712 | 634 | ||
713 | static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { | 635 | static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { |
714 | lua_Number r; | 636 | lua_Number v1, v2, r; |
715 | if (!isnumeral(e1) || !isnumeral(e2)) return 0; | 637 | if (!isnumeral(e1) || !isnumeral(e2)) return 0; |
716 | if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) | 638 | v1 = e1->u.nval; |
717 | return 0; /* do not attempt to divide by 0 */ | 639 | v2 = e2->u.nval; |
718 | r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); | 640 | switch (op) { |
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 */ | ||
719 | e1->u.nval = r; | 656 | e1->u.nval = r; |
720 | return 1; | 657 | return 1; |
721 | } | 658 | } |
722 | 659 | ||
723 | 660 | ||
724 | static void codearith (FuncState *fs, OpCode op, | 661 | static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { |
725 | expdesc *e1, expdesc *e2, int line) { | ||
726 | if (constfolding(op, e1, e2)) | 662 | if (constfolding(op, e1, e2)) |
727 | return; | 663 | return; |
728 | else { | 664 | else { |
@@ -736,9 +672,8 @@ static void codearith (FuncState *fs, OpCode op, | |||
736 | freeexp(fs, e2); | 672 | freeexp(fs, e2); |
737 | freeexp(fs, e1); | 673 | freeexp(fs, e1); |
738 | } | 674 | } |
739 | e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); | 675 | e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); |
740 | e1->k = VRELOCABLE; | 676 | e1->k = VRELOCABLE; |
741 | luaK_fixline(fs, line); | ||
742 | } | 677 | } |
743 | } | 678 | } |
744 | 679 | ||
@@ -754,28 +689,25 @@ static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, | |||
754 | temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ | 689 | temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ |
755 | cond = 1; | 690 | cond = 1; |
756 | } | 691 | } |
757 | e1->u.info = condjump(fs, op, cond, o1, o2); | 692 | e1->u.s.info = condjump(fs, op, cond, o1, o2); |
758 | e1->k = VJMP; | 693 | e1->k = VJMP; |
759 | } | 694 | } |
760 | 695 | ||
761 | 696 | ||
762 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { | 697 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { |
763 | expdesc e2; | 698 | expdesc e2; |
764 | e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; | 699 | e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; |
765 | switch (op) { | 700 | switch (op) { |
766 | case OPR_MINUS: { | 701 | case OPR_MINUS: { |
767 | if (isnumeral(e)) /* minus constant? */ | 702 | if (!isnumeral(e)) |
768 | e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ | 703 | luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ |
769 | else { | 704 | codearith(fs, OP_UNM, e, &e2); |
770 | luaK_exp2anyreg(fs, e); | ||
771 | codearith(fs, OP_UNM, e, &e2, line); | ||
772 | } | ||
773 | break; | 705 | break; |
774 | } | 706 | } |
775 | case OPR_NOT: codenot(fs, e); break; | 707 | case OPR_NOT: codenot(fs, e); break; |
776 | case OPR_LEN: { | 708 | case OPR_LEN: { |
777 | luaK_exp2anyreg(fs, e); /* cannot operate on constants */ | 709 | luaK_exp2anyreg(fs, e); /* cannot operate on constants */ |
778 | codearith(fs, OP_LEN, e, &e2, line); | 710 | codearith(fs, OP_LEN, e, &e2); |
779 | break; | 711 | break; |
780 | } | 712 | } |
781 | default: lua_assert(0); | 713 | default: lua_assert(0); |
@@ -810,8 +742,7 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | |||
810 | } | 742 | } |
811 | 743 | ||
812 | 744 | ||
813 | void luaK_posfix (FuncState *fs, BinOpr op, | 745 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { |
814 | expdesc *e1, expdesc *e2, int line) { | ||
815 | switch (op) { | 746 | switch (op) { |
816 | case OPR_AND: { | 747 | case OPR_AND: { |
817 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ | 748 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ |
@@ -830,30 +761,29 @@ void luaK_posfix (FuncState *fs, BinOpr op, | |||
830 | case OPR_CONCAT: { | 761 | case OPR_CONCAT: { |
831 | luaK_exp2val(fs, e2); | 762 | luaK_exp2val(fs, e2); |
832 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { | 763 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { |
833 | lua_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1); | 764 | lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); |
834 | freeexp(fs, e1); | 765 | freeexp(fs, e1); |
835 | SETARG_B(getcode(fs, e2), e1->u.info); | 766 | SETARG_B(getcode(fs, e2), e1->u.s.info); |
836 | e1->k = VRELOCABLE; e1->u.info = e2->u.info; | 767 | e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; |
837 | } | 768 | } |
838 | else { | 769 | else { |
839 | luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ | 770 | luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ |
840 | codearith(fs, OP_CONCAT, e1, e2, line); | 771 | codearith(fs, OP_CONCAT, e1, e2); |
841 | } | 772 | } |
842 | break; | 773 | break; |
843 | } | 774 | } |
844 | case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: | 775 | case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; |
845 | case OPR_MOD: case OPR_POW: { | 776 | case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; |
846 | codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line); | 777 | case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; |
847 | break; | 778 | case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; |
848 | } | 779 | case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; |
849 | case OPR_EQ: case OPR_LT: case OPR_LE: { | 780 | case OPR_POW: codearith(fs, OP_POW, e1, e2); break; |
850 | codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2); | 781 | case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; |
851 | break; | 782 | case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; |
852 | } | 783 | case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; |
853 | case OPR_NE: case OPR_GT: case OPR_GE: { | 784 | case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; |
854 | codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2); | 785 | case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; |
855 | break; | 786 | case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; |
856 | } | ||
857 | default: lua_assert(0); | 787 | default: lua_assert(0); |
858 | } | 788 | } |
859 | } | 789 | } |
@@ -864,18 +794,46 @@ void luaK_fixline (FuncState *fs, int line) { | |||
864 | } | 794 | } |
865 | 795 | ||
866 | 796 | ||
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 | |||
867 | void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { | 827 | void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { |
868 | int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; | 828 | int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; |
869 | int b = (tostore == LUA_MULTRET) ? 0 : tostore; | 829 | int b = (tostore == LUA_MULTRET) ? 0 : tostore; |
870 | lua_assert(tostore != 0); | 830 | lua_assert(tostore != 0); |
871 | if (c <= MAXARG_C) | 831 | if (c <= MAXARG_C) |
872 | luaK_codeABC(fs, OP_SETLIST, base, b, c); | 832 | luaK_codeABC(fs, OP_SETLIST, base, b, c); |
873 | else if (c <= MAXARG_Ax) { | 833 | else { |
874 | luaK_codeABC(fs, OP_SETLIST, base, b, 0); | 834 | luaK_codeABC(fs, OP_SETLIST, base, b, 0); |
875 | codeextraarg(fs, c); | 835 | luaK_code(fs, cast(Instruction, c), fs->ls->lastline); |
876 | } | 836 | } |
877 | else | ||
878 | luaX_syntaxerror(fs->ls, "constructor too long"); | ||
879 | fs->freereg = base + 1; /* free registers with list values */ | 837 | fs->freereg = base + 1; /* free registers with list values */ |
880 | } | 838 | } |
881 | 839 | ||
diff --git a/apps/plugins/lua/lcode.h b/apps/plugins/lua/lcode.h index 6a1424cf5a..751b2b5695 100644 --- a/apps/plugins/lua/lcode.h +++ b/apps/plugins/lua/lcode.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.h,v 1.58.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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 (ORDER OP) | 24 | ** grep "ORDER OPR" if you change these enums |
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_EQ, OPR_LT, OPR_LE, | 29 | OPR_NE, OPR_EQ, |
30 | OPR_NE, OPR_GT, OPR_GE, | 30 | OPR_LT, OPR_LE, 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,17 +36,14 @@ 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.info]) | 39 | #define getcode(fs,e) ((fs)->f->code[(e)->u.s.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 | |||
47 | LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); | 45 | LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); |
48 | LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); | 46 | 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); | ||
50 | LUAI_FUNC void luaK_fixline (FuncState *fs, int line); | 47 | LUAI_FUNC void luaK_fixline (FuncState *fs, int line); |
51 | LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); | 48 | LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); |
52 | LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); | 49 | LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); |
@@ -55,14 +52,12 @@ LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); | |||
55 | LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); | 52 | LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); |
56 | LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); | 53 | LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); |
57 | LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); | 54 | LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); |
58 | LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); | ||
59 | LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); | 55 | LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); |
60 | LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); | 56 | LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); |
61 | LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); | 57 | LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); |
62 | LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); | 58 | LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); |
63 | LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); | 59 | LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); |
64 | LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); | 60 | LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); |
65 | LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); | ||
66 | LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); | 61 | LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); |
67 | LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); | 62 | LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); |
68 | LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); | 63 | LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); |
@@ -70,13 +65,11 @@ LUAI_FUNC int luaK_jump (FuncState *fs); | |||
70 | LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); | 65 | LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); |
71 | LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); | 66 | LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); |
72 | LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); | 67 | LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); |
73 | LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level); | ||
74 | LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); | 68 | LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); |
75 | LUAI_FUNC int luaK_getlabel (FuncState *fs); | 69 | LUAI_FUNC int luaK_getlabel (FuncState *fs); |
76 | LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); | 70 | LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); |
77 | LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); | 71 | LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); |
78 | LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, | 72 | LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); |
79 | expdesc *v2, int line); | ||
80 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); | 73 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); |
81 | 74 | ||
82 | 75 | ||
diff --git a/apps/plugins/lua/lctype.h b/apps/plugins/lua/lctype.h deleted file mode 100644 index b09b21a337..0000000000 --- a/apps/plugins/lua/lctype.h +++ /dev/null | |||
@@ -1,95 +0,0 @@ | |||
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 20d663efff..50ad3d3803 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.90.1.3 2013/05/16 16:04:15 roberto Exp $ | 2 | ** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 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,20 +30,23 @@ | |||
30 | 30 | ||
31 | 31 | ||
32 | 32 | ||
33 | #define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) | ||
34 | |||
35 | |||
36 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); | 33 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); |
37 | 34 | ||
38 | 35 | ||
39 | static int currentpc (CallInfo *ci) { | 36 | static int currentpc (lua_State *L, CallInfo *ci) { |
40 | lua_assert(isLua(ci)); | 37 | if (!isLua(ci)) return -1; /* function is not a Lua function? */ |
41 | return pcRel(ci->u.l.savedpc, ci_func(ci)->p); | 38 | if (ci == L->ci) |
39 | ci->savedpc = L->savedpc; | ||
40 | return pcRel(ci->savedpc, ci_func(ci)->l.p); | ||
42 | } | 41 | } |
43 | 42 | ||
44 | 43 | ||
45 | static int currentline (CallInfo *ci) { | 44 | static int currentline (lua_State *L, CallInfo *ci) { |
46 | return getfuncline(ci_func(ci)->p, currentpc(ci)); | 45 | int pc = currentpc(L, 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); | ||
47 | } | 50 | } |
48 | 51 | ||
49 | 52 | ||
@@ -55,8 +58,6 @@ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { | |||
55 | mask = 0; | 58 | mask = 0; |
56 | func = NULL; | 59 | func = NULL; |
57 | } | 60 | } |
58 | if (isLua(L->ci)) | ||
59 | L->oldpc = L->ci->u.l.savedpc; | ||
60 | L->hook = func; | 61 | L->hook = func; |
61 | L->basehookcount = count; | 62 | L->basehookcount = count; |
62 | resethookcount(L); | 63 | resethookcount(L); |
@@ -83,13 +84,19 @@ LUA_API int lua_gethookcount (lua_State *L) { | |||
83 | LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { | 84 | LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { |
84 | int status; | 85 | int status; |
85 | CallInfo *ci; | 86 | 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 = ci->previous) | 88 | for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { |
89 | level--; | 89 | level--; |
90 | if (level == 0 && ci != &L->base_ci) { /* level found? */ | 90 | if (f_isLua(ci)) /* Lua function? */ |
91 | level -= ci->tailcalls; /* skip lost tail calls */ | ||
92 | } | ||
93 | if (level == 0 && ci > L->base_ci) { /* level found? */ | ||
91 | status = 1; | 94 | status = 1; |
92 | ar->i_ci = ci; | 95 | ar->i_ci = cast_int(ci - L->base_ci); |
96 | } | ||
97 | else if (level < 0) { /* level is of a lost tail call? */ | ||
98 | status = 1; | ||
99 | ar->i_ci = 0; | ||
93 | } | 100 | } |
94 | else status = 0; /* no such level */ | 101 | else status = 0; /* no such level */ |
95 | lua_unlock(L); | 102 | lua_unlock(L); |
@@ -97,78 +104,43 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { | |||
97 | } | 104 | } |
98 | 105 | ||
99 | 106 | ||
100 | static const char *upvalname (Proto *p, int uv) { | 107 | static Proto *getluaproto (CallInfo *ci) { |
101 | TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); | 108 | return (isLua(ci) ? ci_func(ci)->l.p : NULL); |
102 | if (s == NULL) return "?"; | ||
103 | else return getstr(s); | ||
104 | } | 109 | } |
105 | 110 | ||
106 | 111 | ||
107 | static const char *findvararg (CallInfo *ci, int n, StkId *pos) { | 112 | static const char *findlocal (lua_State *L, CallInfo *ci, int n) { |
108 | int nparams = clLvalue(ci->func)->p->numparams; | 113 | const char *name; |
109 | if (n >= ci->u.l.base - ci->func - nparams) | 114 | Proto *fp = getluaproto(ci); |
110 | return NULL; /* no such vararg */ | 115 | if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) |
116 | return name; /* is a local variable in a Lua function */ | ||
111 | else { | 117 | else { |
112 | *pos = ci->func + nparams + n; | 118 | StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; |
113 | return "(*vararg)"; /* generic name for any vararg */ | 119 | if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ |
114 | } | 120 | return "(*temporary)"; |
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 */ | ||
136 | else | 121 | else |
137 | return NULL; /* no name */ | 122 | return NULL; |
138 | } | 123 | } |
139 | *pos = base + (n - 1); | ||
140 | return name; | ||
141 | } | 124 | } |
142 | 125 | ||
143 | 126 | ||
144 | LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { | 127 | LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { |
145 | const char *name; | 128 | CallInfo *ci = L->base_ci + ar->i_ci; |
129 | const char *name = findlocal(L, ci, n); | ||
146 | lua_lock(L); | 130 | lua_lock(L); |
147 | if (ar == NULL) { /* information about non-active function? */ | 131 | if (name) |
148 | if (!isLfunction(L->top - 1)) /* not a Lua function? */ | 132 | luaA_pushobject(L, ci->base + (n - 1)); |
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 | } | ||
161 | lua_unlock(L); | 133 | lua_unlock(L); |
162 | return name; | 134 | return name; |
163 | } | 135 | } |
164 | 136 | ||
165 | 137 | ||
166 | LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { | 138 | LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { |
167 | StkId pos = 0; /* to avoid warnings */ | 139 | CallInfo *ci = L->base_ci + ar->i_ci; |
168 | const char *name = findlocal(L, ar->i_ci, n, &pos); | 140 | const char *name = findlocal(L, ci, n); |
169 | lua_lock(L); | 141 | lua_lock(L); |
170 | if (name) | 142 | if (name) |
171 | setobjs2s(L, pos, L->top - 1); | 143 | setobjs2s(L, ci->base + (n - 1), L->top - 1); |
172 | L->top--; /* pop value */ | 144 | L->top--; /* pop value */ |
173 | lua_unlock(L); | 145 | lua_unlock(L); |
174 | return name; | 146 | return name; |
@@ -176,45 +148,55 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { | |||
176 | 148 | ||
177 | 149 | ||
178 | static void funcinfo (lua_Debug *ar, Closure *cl) { | 150 | static void funcinfo (lua_Debug *ar, Closure *cl) { |
179 | if (noLuaClosure(cl)) { | 151 | if (cl->c.isC) { |
180 | ar->source = "=[C]"; | 152 | ar->source = "=[C]"; |
181 | ar->linedefined = -1; | 153 | ar->linedefined = -1; |
182 | ar->lastlinedefined = -1; | 154 | ar->lastlinedefined = -1; |
183 | ar->what = "C"; | 155 | ar->what = "C"; |
184 | } | 156 | } |
185 | else { | 157 | else { |
186 | Proto *p = cl->l.p; | 158 | ar->source = getstr(cl->l.p->source); |
187 | ar->source = p->source ? getstr(p->source) : "=?"; | 159 | ar->linedefined = cl->l.p->linedefined; |
188 | ar->linedefined = p->linedefined; | 160 | ar->lastlinedefined = cl->l.p->lastlinedefined; |
189 | ar->lastlinedefined = p->lastlinedefined; | ||
190 | ar->what = (ar->linedefined == 0) ? "main" : "Lua"; | 161 | ar->what = (ar->linedefined == 0) ? "main" : "Lua"; |
191 | } | 162 | } |
192 | luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); | 163 | luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); |
193 | } | 164 | } |
194 | 165 | ||
195 | 166 | ||
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 | |||
196 | static void collectvalidlines (lua_State *L, Closure *f) { | 177 | static void collectvalidlines (lua_State *L, Closure *f) { |
197 | if (noLuaClosure(f)) { | 178 | if (f == NULL || f->c.isC) { |
198 | setnilvalue(L->top); | 179 | setnilvalue(L->top); |
199 | api_incr_top(L); | ||
200 | } | 180 | } |
201 | else { | 181 | else { |
202 | int i; | 182 | Table *t = luaH_new(L, 0, 0); |
203 | TValue v; | ||
204 | int *lineinfo = f->l.p->lineinfo; | 183 | int *lineinfo = f->l.p->lineinfo; |
205 | Table *t = luaH_new(L); /* new table to store active lines */ | 184 | int i; |
206 | sethvalue(L, L->top, t); /* push it on stack */ | 185 | for (i=0; i<f->l.p->sizelineinfo; i++) |
207 | api_incr_top(L); | 186 | setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); |
208 | setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ | 187 | sethvalue(L, L->top, t); |
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 */ | ||
211 | } | 188 | } |
189 | incr_top(L); | ||
212 | } | 190 | } |
213 | 191 | ||
214 | 192 | ||
215 | static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | 193 | static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, |
216 | Closure *f, CallInfo *ci) { | 194 | Closure *f, CallInfo *ci) { |
217 | int status = 1; | 195 | int status = 1; |
196 | if (f == NULL) { | ||
197 | info_tailcall(ar); | ||
198 | return status; | ||
199 | } | ||
218 | for (; *what; what++) { | 200 | for (; *what; what++) { |
219 | switch (*what) { | 201 | switch (*what) { |
220 | case 'S': { | 202 | case 'S': { |
@@ -222,31 +204,15 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | |||
222 | break; | 204 | break; |
223 | } | 205 | } |
224 | case 'l': { | 206 | case 'l': { |
225 | ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; | 207 | ar->currentline = (ci) ? currentline(L, ci) : -1; |
226 | break; | 208 | break; |
227 | } | 209 | } |
228 | case 'u': { | 210 | case 'u': { |
229 | ar->nups = (f == NULL) ? 0 : f->c.nupvalues; | 211 | ar->nups = 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; | ||
242 | break; | 212 | break; |
243 | } | 213 | } |
244 | case 'n': { | 214 | case 'n': { |
245 | /* calling function is a known Lua function? */ | 215 | ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; |
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; | ||
250 | if (ar->namewhat == NULL) { | 216 | if (ar->namewhat == NULL) { |
251 | ar->namewhat = ""; /* not found */ | 217 | ar->namewhat = ""; /* not found */ |
252 | ar->name = NULL; | 218 | ar->name = NULL; |
@@ -265,30 +231,29 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | |||
265 | 231 | ||
266 | LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | 232 | LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { |
267 | int status; | 233 | int status; |
268 | Closure *cl; | 234 | Closure *f = NULL; |
269 | CallInfo *ci; | 235 | CallInfo *ci = NULL; |
270 | StkId func; | ||
271 | lua_lock(L); | 236 | lua_lock(L); |
272 | if (*what == '>') { | 237 | if (*what == '>') { |
273 | ci = NULL; | 238 | StkId func = L->top - 1; |
274 | func = L->top - 1; | 239 | luai_apicheck(L, ttisfunction(func)); |
275 | api_check(L, ttisfunction(func), "function expected"); | ||
276 | what++; /* skip the '>' */ | 240 | what++; /* skip the '>' */ |
241 | f = clvalue(func); | ||
277 | L->top--; /* pop function */ | 242 | L->top--; /* pop function */ |
278 | } | 243 | } |
279 | else { | 244 | else if (ar->i_ci != 0) { /* no tail call? */ |
280 | ci = ar->i_ci; | 245 | ci = L->base_ci + ar->i_ci; |
281 | func = ci->func; | ||
282 | lua_assert(ttisfunction(ci->func)); | 246 | lua_assert(ttisfunction(ci->func)); |
247 | f = clvalue(ci->func); | ||
283 | } | 248 | } |
284 | cl = ttisclosure(func) ? clvalue(func) : NULL; | 249 | status = auxgetinfo(L, what, ar, f, ci); |
285 | status = auxgetinfo(L, what, ar, cl, ci); | ||
286 | if (strchr(what, 'f')) { | 250 | if (strchr(what, 'f')) { |
287 | setobjs2s(L, L->top, func); | 251 | if (f == NULL) setnilvalue(L->top); |
288 | api_incr_top(L); | 252 | else setclvalue(L, L->top, f); |
253 | incr_top(L); | ||
289 | } | 254 | } |
290 | if (strchr(what, 'L')) | 255 | if (strchr(what, 'L')) |
291 | collectvalidlines(L, cl); | 256 | collectvalidlines(L, f); |
292 | lua_unlock(L); | 257 | lua_unlock(L); |
293 | return status; | 258 | return status; |
294 | } | 259 | } |
@@ -296,231 +261,315 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | |||
296 | 261 | ||
297 | /* | 262 | /* |
298 | ** {====================================================== | 263 | ** {====================================================== |
299 | ** Symbolic Execution | 264 | ** Symbolic Execution and code checker |
300 | ** ======================================================= | 265 | ** ======================================================= |
301 | */ | 266 | */ |
302 | 267 | ||
303 | static const char *getobjname (Proto *p, int lastpc, int reg, | 268 | #define check(x) if (!(x)) return 0; |
304 | const char **name); | ||
305 | 269 | ||
270 | #define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) | ||
306 | 271 | ||
307 | /* | 272 | #define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) |
308 | ** find a "name" for the RK value 'c' | 273 | |
309 | */ | 274 | |
310 | static void kname (Proto *p, int pc, int c, const char **name) { | 275 | |
311 | if (ISK(c)) { /* is 'c' a constant? */ | 276 | static int precheck (const Proto *pt) { |
312 | TValue *kvalue = &p->k[INDEXK(c)]; | 277 | check(pt->maxstacksize <= MAXSTACK); |
313 | if (ttisstring(kvalue)) { /* literal constant? */ | 278 | check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); |
314 | *name = svalue(kvalue); /* it is its own name */ | 279 | check(!(pt->is_vararg & VARARG_NEEDSARG) || |
315 | return; | 280 | (pt->is_vararg & VARARG_HASARG)); |
316 | } | 281 | check(pt->sizeupvalues <= pt->nups); |
317 | /* else no reasonable name found */ | 282 | check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); |
318 | } | 283 | check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); |
319 | else { /* 'c' is a register */ | 284 | return 1; |
320 | const char *what = getobjname(p, pc, c, name); /* search for 'c' */ | 285 | } |
321 | if (what && *what == 'c') { /* found a constant name? */ | 286 | |
322 | return; /* 'name' already filled */ | 287 | |
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; | ||
323 | } | 298 | } |
324 | /* else no reasonable name found */ | 299 | default: return 0; /* invalid instruction after an open call */ |
325 | } | 300 | } |
326 | *name = "?"; /* no reasonable name found */ | ||
327 | } | 301 | } |
328 | 302 | ||
329 | 303 | ||
330 | static int filterpc (int pc, int jmptarget) { | 304 | static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { |
331 | if (pc < jmptarget) /* is code conditional (inside a jump)? */ | 305 | switch (mode) { |
332 | return -1; /* cannot know who sets that register */ | 306 | case OpArgN: check(r == 0); break; |
333 | else return pc; /* current position sets that register */ | 307 | case OpArgU: break; |
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; | ||
334 | } | 314 | } |
335 | 315 | ||
336 | 316 | ||
337 | /* | 317 | static Instruction symbexec (const Proto *pt, int lastpc, int reg) { |
338 | ** try to find last instruction before 'lastpc' that modified register 'reg' | ||
339 | */ | ||
340 | static int findsetreg (Proto *p, int lastpc, int reg) { | ||
341 | int pc; | 318 | int pc; |
342 | int setreg = -1; /* keep last instruction that changed 'reg' */ | 319 | int last; /* stores position of last instruction that changed `reg' */ |
343 | int jmptarget = 0; /* any code before this address is conditional */ | 320 | last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ |
321 | check(precheck(pt)); | ||
344 | for (pc = 0; pc < lastpc; pc++) { | 322 | for (pc = 0; pc < lastpc; pc++) { |
345 | Instruction i = p->code[pc]; | 323 | Instruction i = pt->code[pc]; |
346 | OpCode op = GET_OPCODE(i); | 324 | OpCode op = GET_OPCODE(i); |
347 | int a = GETARG_A(i); | 325 | 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 | } | ||
348 | switch (op) { | 373 | 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 | } | ||
349 | case OP_LOADNIL: { | 382 | case OP_LOADNIL: { |
350 | int b = GETARG_B(i); | 383 | if (a <= reg && reg <= b) |
351 | if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ | 384 | last = pc; /* set registers from `a' to `b' */ |
352 | setreg = filterpc(pc, jmptarget); | 385 | break; |
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 */ | ||
353 | break; | 410 | break; |
354 | } | 411 | } |
355 | case OP_TFORCALL: { | 412 | case OP_FORLOOP: |
356 | if (reg >= a + 2) /* affect all regs above its base */ | 413 | case OP_FORPREP: |
357 | setreg = filterpc(pc, jmptarget); | 414 | checkreg(pt, a+3); |
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 */ | ||
358 | break; | 421 | break; |
359 | } | 422 | } |
360 | case OP_CALL: | 423 | case OP_CALL: |
361 | case OP_TAILCALL: { | 424 | case OP_TAILCALL: { |
362 | if (reg >= a) /* affect all registers above base */ | 425 | if (b != 0) { |
363 | setreg = filterpc(pc, jmptarget); | 426 | checkreg(pt, a+b-1); |
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 */ | ||
364 | break; | 435 | break; |
365 | } | 436 | } |
366 | case OP_JMP: { | 437 | case OP_RETURN: { |
367 | int b = GETARG_sBx(i); | 438 | b--; /* b = num. returns */ |
368 | int dest = pc + 1 + b; | 439 | if (b > 0) checkreg(pt, a+b-1); |
369 | /* jump is forward and do not skip `lastpc'? */ | 440 | break; |
370 | if (pc < dest && dest <= lastpc) { | 441 | } |
371 | if (dest > jmptarget) | 442 | case OP_SETLIST: { |
372 | jmptarget = dest; /* update 'jmptarget' */ | 443 | if (b > 0) checkreg(pt, a + b); |
444 | if (c == 0) { | ||
445 | pc++; | ||
446 | check(pc < pt->sizecode - 1); | ||
373 | } | 447 | } |
374 | break; | 448 | break; |
375 | } | 449 | } |
376 | case OP_TEST: { | 450 | case OP_CLOSURE: { |
377 | if (reg == a) /* jumped code can change 'a' */ | 451 | int nup, j; |
378 | setreg = filterpc(pc, jmptarget); | 452 | check(b < pt->sizep); |
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 */ | ||
379 | break; | 461 | break; |
380 | } | 462 | } |
381 | default: | 463 | case OP_VARARG: { |
382 | if (testAMode(op) && reg == a) /* any instruction that set A */ | 464 | check((pt->is_vararg & VARARG_ISVARARG) && |
383 | setreg = filterpc(pc, jmptarget); | 465 | !(pt->is_vararg & VARARG_NEEDSARG)); |
466 | b--; | ||
467 | if (b == LUA_MULTRET) check(checkopenop(pt, pc)); | ||
468 | checkreg(pt, a+b-1); | ||
384 | break; | 469 | break; |
470 | } | ||
471 | default: break; | ||
385 | } | 472 | } |
386 | } | 473 | } |
387 | return setreg; | 474 | return pt->code[last]; |
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); | ||
388 | } | 486 | } |
389 | 487 | ||
390 | 488 | ||
391 | static const char *getobjname (Proto *p, int lastpc, int reg, | 489 | static const char *kname (Proto *p, int c) { |
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, | ||
392 | const char **name) { | 498 | const char **name) { |
393 | int pc; | 499 | if (isLua(ci)) { /* a Lua function? */ |
394 | *name = luaF_getlocalname(p, reg + 1, lastpc); | 500 | Proto *p = ci_func(ci)->l.p; |
395 | if (*name) /* is a local? */ | 501 | int pc = currentpc(L, ci); |
396 | return "local"; | 502 | Instruction i; |
397 | /* else try symbolic execution */ | 503 | *name = luaF_getlocalname(p, stackpos+1, pc); |
398 | pc = findsetreg(p, lastpc, reg); | 504 | if (*name) /* is a local? */ |
399 | if (pc != -1) { /* could find instruction? */ | 505 | return "local"; |
400 | Instruction i = p->code[pc]; | 506 | i = symbexec(p, pc, stackpos); /* try symbolic execution */ |
401 | OpCode op = GET_OPCODE(i); | 507 | lua_assert(pc != -1); |
402 | switch (op) { | 508 | switch (GET_OPCODE(i)) { |
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 | } | ||
403 | case OP_MOVE: { | 515 | case OP_MOVE: { |
404 | int b = GETARG_B(i); /* move from 'b' to 'a' */ | 516 | int a = GETARG_A(i); |
405 | if (b < GETARG_A(i)) | 517 | int b = GETARG_B(i); /* move from `b' to `a' */ |
406 | return getobjname(p, pc, b, name); /* get name for 'b' */ | 518 | if (b < a) |
519 | return getobjname(L, ci, b, name); /* get name for `b' */ | ||
407 | break; | 520 | break; |
408 | } | 521 | } |
409 | case OP_GETTABUP: | ||
410 | case OP_GETTABLE: { | 522 | case OP_GETTABLE: { |
411 | int k = GETARG_C(i); /* key index */ | 523 | int k = GETARG_C(i); /* key index */ |
412 | int t = GETARG_B(i); /* table index */ | 524 | *name = kname(p, k); |
413 | const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ | 525 | return "field"; |
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"; | ||
418 | } | 526 | } |
419 | case OP_GETUPVAL: { | 527 | case OP_GETUPVAL: { |
420 | *name = upvalname(p, GETARG_B(i)); | 528 | int u = GETARG_B(i); /* upvalue index */ |
529 | *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; | ||
421 | return "upvalue"; | 530 | return "upvalue"; |
422 | } | 531 | } |
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 | } | ||
433 | case OP_SELF: { | 532 | case OP_SELF: { |
434 | int k = GETARG_C(i); /* key index */ | 533 | int k = GETARG_C(i); /* key index */ |
435 | kname(p, pc, k, name); | 534 | *name = kname(p, k); |
436 | return "method"; | 535 | return "method"; |
437 | } | 536 | } |
438 | default: break; /* go through to return NULL */ | 537 | default: break; |
439 | } | 538 | } |
440 | } | 539 | } |
441 | return NULL; /* could not find reasonable name */ | 540 | return NULL; /* no useful name found */ |
442 | } | 541 | } |
443 | 542 | ||
444 | 543 | ||
445 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { | 544 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { |
446 | TMS tm; | 545 | Instruction i; |
447 | Proto *p = ci_func(ci)->p; /* calling function */ | 546 | if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) |
448 | int pc = currentpc(ci); /* calling instruction index */ | 547 | return NULL; /* calling function is not Lua (or is unknown) */ |
449 | Instruction i = p->code[pc]; /* calling instruction */ | 548 | ci--; /* calling function */ |
450 | switch (GET_OPCODE(i)) { | 549 | i = ci_func(ci)->l.p->code[currentpc(L, ci)]; |
451 | case OP_CALL: | 550 | if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || |
452 | case OP_TAILCALL: /* get function name */ | 551 | GET_OPCODE(i) == OP_TFORLOOP) |
453 | return getobjname(p, pc, GETARG_A(i), name); | 552 | return getobjname(L, ci, GETARG_A(i), name); |
454 | case OP_TFORCALL: { /* for iterator */ | 553 | else |
455 | *name = "for iterator"; | 554 | return NULL; /* no useful name can be found */ |
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"; | ||
481 | } | 555 | } |
482 | 556 | ||
483 | /* }====================================================== */ | ||
484 | |||
485 | |||
486 | 557 | ||
487 | /* | 558 | /* only ANSI way to check whether a pointer points to an array */ |
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 | */ | ||
491 | static int isinstack (CallInfo *ci, const TValue *o) { | 559 | static int isinstack (CallInfo *ci, const TValue *o) { |
492 | StkId p; | 560 | StkId p; |
493 | for (p = ci->u.l.base; p < ci->top; p++) | 561 | for (p = ci->base; p < ci->top; p++) |
494 | if (o == p) return 1; | 562 | if (o == p) return 1; |
495 | return 0; | 563 | return 0; |
496 | } | 564 | } |
497 | 565 | ||
498 | 566 | ||
499 | static const char *getupvalname (CallInfo *ci, const TValue *o, | 567 | void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { |
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; | ||
515 | const char *name = NULL; | 568 | const char *name = NULL; |
516 | const char *t = objtypename(o); | 569 | const char *t = luaT_typenames[ttype(o)]; |
517 | const char *kind = NULL; | 570 | const char *kind = (isinstack(L->ci, o)) ? |
518 | if (isLua(ci)) { | 571 | getobjname(L, L->ci, cast_int(o - L->base), &name) : |
519 | kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ | 572 | NULL; |
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 | } | ||
524 | if (kind) | 573 | if (kind) |
525 | luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", | 574 | luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", |
526 | op, kind, name, t); | 575 | op, kind, name, t); |
@@ -529,14 +578,14 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { | |||
529 | } | 578 | } |
530 | 579 | ||
531 | 580 | ||
532 | l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) { | 581 | void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { |
533 | if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; | 582 | if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; |
534 | lua_assert(!ttisstring(p1) && !ttisnumber(p1)); | 583 | lua_assert(!ttisstring(p1) && !ttisnumber(p1)); |
535 | luaG_typeerror(L, p1, "concatenate"); | 584 | luaG_typeerror(L, p1, "concatenate"); |
536 | } | 585 | } |
537 | 586 | ||
538 | 587 | ||
539 | l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { | 588 | void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { |
540 | TValue temp; | 589 | TValue temp; |
541 | if (luaV_tonumber(p1, &temp) == NULL) | 590 | if (luaV_tonumber(p1, &temp) == NULL) |
542 | p2 = p1; /* first operand is wrong */ | 591 | p2 = p1; /* first operand is wrong */ |
@@ -544,13 +593,14 @@ l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { | |||
544 | } | 593 | } |
545 | 594 | ||
546 | 595 | ||
547 | l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { | 596 | int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { |
548 | const char *t1 = objtypename(p1); | 597 | const char *t1 = luaT_typenames[ttype(p1)]; |
549 | const char *t2 = objtypename(p2); | 598 | const char *t2 = luaT_typenames[ttype(p2)]; |
550 | if (t1 == t2) | 599 | if (t1[2] == t2[2]) |
551 | luaG_runerror(L, "attempt to compare two %s values", t1); | 600 | luaG_runerror(L, "attempt to compare two %s values", t1); |
552 | else | 601 | else |
553 | luaG_runerror(L, "attempt to compare %s with %s", t1, t2); | 602 | luaG_runerror(L, "attempt to compare %s with %s", t1, t2); |
603 | return 0; | ||
554 | } | 604 | } |
555 | 605 | ||
556 | 606 | ||
@@ -558,32 +608,27 @@ static void addinfo (lua_State *L, const char *msg) { | |||
558 | CallInfo *ci = L->ci; | 608 | CallInfo *ci = L->ci; |
559 | if (isLua(ci)) { /* is Lua code? */ | 609 | if (isLua(ci)) { /* is Lua code? */ |
560 | char buff[LUA_IDSIZE]; /* add file:line information */ | 610 | char buff[LUA_IDSIZE]; /* add file:line information */ |
561 | int line = currentline(ci); | 611 | int line = currentline(L, ci); |
562 | TString *src = ci_func(ci)->p->source; | 612 | luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); |
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 | } | ||
568 | luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); | 613 | luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); |
569 | } | 614 | } |
570 | } | 615 | } |
571 | 616 | ||
572 | 617 | ||
573 | l_noret luaG_errormsg (lua_State *L) { | 618 | void luaG_errormsg (lua_State *L) { |
574 | if (L->errfunc != 0) { /* is there an error handling function? */ | 619 | if (L->errfunc != 0) { /* is there an error handling function? */ |
575 | StkId errfunc = restorestack(L, L->errfunc); | 620 | StkId errfunc = restorestack(L, L->errfunc); |
576 | if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); | 621 | if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); |
577 | setobjs2s(L, L->top, L->top - 1); /* move argument */ | 622 | setobjs2s(L, L->top, L->top - 1); /* move argument */ |
578 | setobjs2s(L, L->top - 1, errfunc); /* push function */ | 623 | setobjs2s(L, L->top - 1, errfunc); /* push function */ |
579 | L->top++; | 624 | incr_top(L); |
580 | luaD_call(L, L->top - 2, 1, 0); /* call it */ | 625 | luaD_call(L, L->top - 2, 1); /* call it */ |
581 | } | 626 | } |
582 | luaD_throw(L, LUA_ERRRUN); | 627 | luaD_throw(L, LUA_ERRRUN); |
583 | } | 628 | } |
584 | 629 | ||
585 | 630 | ||
586 | l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { | 631 | void luaG_runerror (lua_State *L, const char *fmt, ...) { |
587 | va_list argp; | 632 | va_list argp; |
588 | va_start(argp, fmt); | 633 | va_start(argp, fmt); |
589 | addinfo(L, luaO_pushvfstring(L, fmt, argp)); | 634 | addinfo(L, luaO_pushvfstring(L, fmt, argp)); |
diff --git a/apps/plugins/lua/ldebug.h b/apps/plugins/lua/ldebug.h index 6445c763ea..22226b4096 100644 --- a/apps/plugins/lua/ldebug.h +++ b/apps/plugins/lua/ldebug.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.h,v 2.7.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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,22 +13,21 @@ | |||
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 getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) | 16 | #define getline(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)) | ||
22 | 20 | ||
23 | 21 | LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, | |
24 | LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, | 22 | const char *opname); |
25 | const char *opname); | 23 | LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); |
26 | LUAI_FUNC l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2); | 24 | LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, |
27 | LUAI_FUNC l_noret luaG_aritherror (lua_State *L, const TValue *p1, | 25 | const TValue *p2); |
28 | const TValue *p2); | 26 | LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, |
29 | LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, | 27 | const TValue *p2); |
30 | const TValue *p2); | 28 | LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); |
31 | LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); | 29 | LUAI_FUNC void luaG_errormsg (lua_State *L); |
32 | LUAI_FUNC l_noret luaG_errormsg (lua_State *L); | 30 | LUAI_FUNC int luaG_checkcode (const Proto *pt); |
31 | LUAI_FUNC int luaG_checkopenop (Instruction i); | ||
33 | 32 | ||
34 | #endif | 33 | #endif |
diff --git a/apps/plugins/lua/ldo.c b/apps/plugins/lua/ldo.c index e9dd5fa951..f303c744c7 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.108.1.3 2013/11/08 18:22:50 roberto Exp $ | 2 | ** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 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,7 +14,6 @@ | |||
14 | 14 | ||
15 | #include "lua.h" | 15 | #include "lua.h" |
16 | 16 | ||
17 | #include "lapi.h" | ||
18 | #include "ldebug.h" | 17 | #include "ldebug.h" |
19 | #include "ldo.h" | 18 | #include "ldo.h" |
20 | #include "lfunc.h" | 19 | #include "lfunc.h" |
@@ -40,38 +39,6 @@ | |||
40 | ** ======================================================= | 39 | ** ======================================================= |
41 | */ | 40 | */ |
42 | 41 | ||
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 | |||
75 | 42 | ||
76 | /* chain list of long jump buffers */ | 43 | /* chain list of long jump buffers */ |
77 | struct lua_longjmp { | 44 | struct lua_longjmp { |
@@ -81,17 +48,18 @@ struct lua_longjmp { | |||
81 | }; | 48 | }; |
82 | 49 | ||
83 | 50 | ||
84 | static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { | 51 | void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { |
85 | switch (errcode) { | 52 | switch (errcode) { |
86 | case LUA_ERRMEM: { /* memory error? */ | 53 | case LUA_ERRMEM: { |
87 | setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ | 54 | setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); |
88 | break; | 55 | break; |
89 | } | 56 | } |
90 | case LUA_ERRERR: { | 57 | case LUA_ERRERR: { |
91 | setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); | 58 | setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); |
92 | break; | 59 | break; |
93 | } | 60 | } |
94 | default: { | 61 | case LUA_ERRSYNTAX: |
62 | case LUA_ERRRUN: { | ||
95 | setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ | 63 | setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ |
96 | break; | 64 | break; |
97 | } | 65 | } |
@@ -100,39 +68,55 @@ static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { | |||
100 | } | 68 | } |
101 | 69 | ||
102 | 70 | ||
103 | l_noret luaD_throw (lua_State *L, int errcode) { | 71 | static void restore_stack_limit (lua_State *L) { |
104 | if (L->errorJmp) { /* thread has an error handler? */ | 72 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); |
105 | L->errorJmp->status = errcode; /* set status */ | 73 | if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ |
106 | LUAI_THROW(L, L->errorJmp); /* jump to it */ | 74 | int inuse = cast_int(L->ci - L->base_ci); |
75 | if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ | ||
76 | luaD_reallocCI(L, LUAI_MAXCALLS); | ||
107 | } | 77 | } |
108 | else { /* thread has no error handler */ | 78 | } |
109 | L->status = cast_byte(errcode); /* mark it as dead */ | 79 | |
110 | if (G(L)->mainthread->errorJmp) { /* main thread has a handler? */ | 80 | |
111 | setobjs2s(L, G(L)->mainthread->top++, L->top - 1); /* copy error obj. */ | 81 | static void resetstack (lua_State *L, int status) { |
112 | luaD_throw(G(L)->mainthread, errcode); /* re-throw in main thread */ | 82 | L->ci = L->base_ci; |
113 | } | 83 | L->base = L->ci->base; |
114 | else { /* no handler at all; abort */ | 84 | luaF_close(L, L->base); /* close eventual pending closures */ |
115 | if (G(L)->panic) { /* panic function? */ | 85 | luaD_seterrorobj(L, status, L->base); |
116 | lua_unlock(L); | 86 | L->nCcalls = L->baseCcalls; |
117 | G(L)->panic(L); /* call it (last chance to jump out) */ | 87 | L->allowhook = 1; |
118 | } | 88 | restore_stack_limit(L); |
119 | abort(); | 89 | L->errfunc = 0; |
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); | ||
120 | } | 105 | } |
106 | exit(EXIT_FAILURE); | ||
121 | } | 107 | } |
122 | } | 108 | } |
123 | 109 | ||
124 | 110 | ||
125 | int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | 111 | int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { |
126 | unsigned short oldnCcalls = L->nCcalls; | ||
127 | struct lua_longjmp lj; | 112 | struct lua_longjmp lj; |
128 | lj.status = LUA_OK; | 113 | lj.status = 0; |
129 | lj.previous = L->errorJmp; /* chain new error handler */ | 114 | lj.previous = L->errorJmp; /* chain new error handler */ |
130 | L->errorJmp = &lj; | 115 | L->errorJmp = &lj; |
131 | LUAI_TRY(L, &lj, | 116 | LUAI_TRY(L, &lj, |
132 | (*f)(L, ud); | 117 | (*f)(L, ud); |
133 | ); | 118 | ); |
134 | L->errorJmp = lj.previous; /* restore old error handler */ | 119 | L->errorJmp = lj.previous; /* restore old error handler */ |
135 | L->nCcalls = oldnCcalls; | ||
136 | return lj.status; | 120 | return lj.status; |
137 | } | 121 | } |
138 | 122 | ||
@@ -145,127 +129,112 @@ static void correctstack (lua_State *L, TValue *oldstack) { | |||
145 | L->top = (L->top - oldstack) + L->stack; | 129 | L->top = (L->top - oldstack) + L->stack; |
146 | for (up = L->openupval; up != NULL; up = up->gch.next) | 130 | for (up = L->openupval; up != NULL; up = up->gch.next) |
147 | gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; | 131 | gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; |
148 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | 132 | for (ci = L->base_ci; ci <= L->ci; ci++) { |
149 | ci->top = (ci->top - oldstack) + L->stack; | 133 | ci->top = (ci->top - oldstack) + L->stack; |
134 | ci->base = (ci->base - oldstack) + L->stack; | ||
150 | ci->func = (ci->func - oldstack) + L->stack; | 135 | ci->func = (ci->func - oldstack) + L->stack; |
151 | if (isLua(ci)) | ||
152 | ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; | ||
153 | } | 136 | } |
137 | L->base = (L->base - oldstack) + L->stack; | ||
154 | } | 138 | } |
155 | 139 | ||
156 | 140 | ||
157 | /* some space for error handling */ | ||
158 | #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) | ||
159 | |||
160 | |||
161 | void luaD_reallocstack (lua_State *L, int newsize) { | 141 | void luaD_reallocstack (lua_State *L, int newsize) { |
162 | TValue *oldstack = L->stack; | 142 | TValue *oldstack = L->stack; |
163 | int lim = L->stacksize; | 143 | int realsize = newsize + 1 + EXTRA_STACK; |
164 | lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); | 144 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); |
165 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); | 145 | luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); |
166 | luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); | 146 | L->stacksize = realsize; |
167 | for (; lim < newsize; lim++) | 147 | L->stack_last = L->stack+newsize; |
168 | setnilvalue(L->stack + lim); /* erase new segment */ | ||
169 | L->stacksize = newsize; | ||
170 | L->stack_last = L->stack + newsize - EXTRA_STACK; | ||
171 | correctstack(L, oldstack); | 148 | correctstack(L, oldstack); |
172 | } | 149 | } |
173 | 150 | ||
174 | 151 | ||
175 | void luaD_growstack (lua_State *L, int n) { | 152 | void luaD_reallocCI (lua_State *L, int newsize) { |
176 | int size = L->stacksize; | 153 | CallInfo *oldci = L->base_ci; |
177 | if (size > LUAI_MAXSTACK) /* error after extra size? */ | 154 | luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); |
178 | luaD_throw(L, LUA_ERRERR); | 155 | L->size_ci = newsize; |
179 | else { | 156 | L->ci = (L->ci - oldci) + L->base_ci; |
180 | int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; | 157 | L->end_ci = L->base_ci + L->size_ci - 1; |
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 | } | ||
191 | } | 158 | } |
192 | 159 | ||
193 | 160 | ||
194 | static int stackinuse (lua_State *L) { | 161 | void luaD_growstack (lua_State *L, int n) { |
195 | CallInfo *ci; | 162 | if (n <= L->stacksize) /* double size is enough? */ |
196 | StkId lim = L->top; | 163 | luaD_reallocstack(L, 2*L->stacksize); |
197 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | 164 | else |
198 | lua_assert(ci->top <= L->stack_last); | 165 | luaD_reallocstack(L, L->stacksize + n); |
199 | if (lim < ci->top) lim = ci->top; | ||
200 | } | ||
201 | return cast_int(lim - L->stack) + 1; /* part of stack in use */ | ||
202 | } | 166 | } |
203 | 167 | ||
204 | 168 | ||
205 | void luaD_shrinkstack (lua_State *L) { | 169 | static CallInfo *growCI (lua_State *L) { |
206 | int inuse = stackinuse(L); | 170 | if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ |
207 | int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; | 171 | luaD_throw(L, LUA_ERRERR); |
208 | if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK; | 172 | else { |
209 | if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */ | 173 | luaD_reallocCI(L, 2*L->size_ci); |
210 | goodsize >= L->stacksize) /* would grow instead of shrink? */ | 174 | if (L->size_ci > LUAI_MAXCALLS) |
211 | condmovestack(L); /* don't change stack (change only for debugging) */ | 175 | luaG_runerror(L, "stack overflow"); |
212 | else | 176 | } |
213 | luaD_reallocstack(L, goodsize); /* shrink it */ | 177 | return ++L->ci; |
214 | } | 178 | } |
215 | 179 | ||
216 | 180 | ||
217 | void luaD_hook (lua_State *L, int event, int line) { | 181 | void luaD_callhook (lua_State *L, int event, int line) { |
218 | lua_Hook hook = L->hook; | 182 | lua_Hook hook = L->hook; |
219 | if (hook && L->allowhook) { | 183 | if (hook && L->allowhook) { |
220 | CallInfo *ci = L->ci; | ||
221 | ptrdiff_t top = savestack(L, L->top); | 184 | ptrdiff_t top = savestack(L, L->top); |
222 | ptrdiff_t ci_top = savestack(L, ci->top); | 185 | ptrdiff_t ci_top = savestack(L, L->ci->top); |
223 | lua_Debug ar; | 186 | lua_Debug ar; |
224 | ar.event = event; | 187 | ar.event = event; |
225 | ar.currentline = line; | 188 | ar.currentline = line; |
226 | ar.i_ci = ci; | 189 | if (event == LUA_HOOKTAILRET) |
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); | ||
227 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 193 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
228 | ci->top = L->top + LUA_MINSTACK; | 194 | L->ci->top = L->top + LUA_MINSTACK; |
229 | lua_assert(ci->top <= L->stack_last); | 195 | lua_assert(L->ci->top <= L->stack_last); |
230 | L->allowhook = 0; /* cannot call hooks inside a hook */ | 196 | L->allowhook = 0; /* cannot call hooks inside a hook */ |
231 | ci->callstatus |= CIST_HOOKED; | ||
232 | lua_unlock(L); | 197 | lua_unlock(L); |
233 | (*hook)(L, &ar); | 198 | (*hook)(L, &ar); |
234 | lua_lock(L); | 199 | lua_lock(L); |
235 | lua_assert(!L->allowhook); | 200 | lua_assert(!L->allowhook); |
236 | L->allowhook = 1; | 201 | L->allowhook = 1; |
237 | ci->top = restorestack(L, ci_top); | 202 | L->ci->top = restorestack(L, ci_top); |
238 | L->top = restorestack(L, top); | 203 | 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; | ||
251 | } | 204 | } |
252 | luaD_hook(L, hook, -1); | ||
253 | ci->u.l.savedpc--; /* correct 'pc' */ | ||
254 | } | 205 | } |
255 | 206 | ||
256 | 207 | ||
257 | static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { | 208 | static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { |
258 | int i; | 209 | int i; |
259 | int nfixargs = p->numparams; | 210 | int nfixargs = p->numparams; |
211 | Table *htab = NULL; | ||
260 | StkId base, fixed; | 212 | StkId base, fixed; |
261 | lua_assert(actual >= nfixargs); | 213 | for (; actual < nfixargs; ++actual) |
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 | ||
262 | /* move fixed parameters to final position */ | 227 | /* move fixed parameters to final position */ |
263 | luaD_checkstack(L, p->maxstacksize); /* check again for new 'base' */ | ||
264 | fixed = L->top - actual; /* first fixed argument */ | 228 | fixed = L->top - actual; /* first fixed argument */ |
265 | base = L->top; /* final position of first argument */ | 229 | base = L->top; /* final position of first argument */ |
266 | for (i=0; i<nfixargs; i++) { | 230 | for (i=0; i<nfixargs; i++) { |
267 | setobjs2s(L, L->top++, fixed + i); | 231 | setobjs2s(L, L->top++, fixed+i); |
268 | setnilvalue(fixed + i); | 232 | setnilvalue(fixed+i); |
233 | } | ||
234 | /* add `arg' parameter */ | ||
235 | if (htab) { | ||
236 | sethvalue(L, L->top++, htab); | ||
237 | lua_assert(iswhite(obj2gco(htab))); | ||
269 | } | 238 | } |
270 | return base; | 239 | return base; |
271 | } | 240 | } |
@@ -287,93 +256,100 @@ static StkId tryfuncTM (lua_State *L, StkId func) { | |||
287 | 256 | ||
288 | 257 | ||
289 | 258 | ||
290 | #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) | 259 | #define inc_ci(L) \ |
260 | ((L->ci == L->end_ci) ? growCI(L) : \ | ||
261 | (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) | ||
291 | 262 | ||
292 | 263 | ||
293 | /* | ||
294 | ** returns true if function has been executed (C function) | ||
295 | */ | ||
296 | int luaD_precall (lua_State *L, StkId func, int nresults) { | 264 | int luaD_precall (lua_State *L, StkId func, int nresults) { |
297 | lua_CFunction f; | 265 | LClosure *cl; |
298 | CallInfo *ci; | 266 | ptrdiff_t funcr; |
299 | int n; /* number of arguments (Lua) or returns (C) */ | 267 | if (!ttisfunction(func)) /* `func' is not a function? */ |
300 | ptrdiff_t funcr = savestack(L, func); | 268 | func = tryfuncTM(L, func); /* check the `function' tag method */ |
301 | switch (ttype(func)) { | 269 | funcr = savestack(L, func); |
302 | case LUA_TLCF: /* light C function */ | 270 | cl = &clvalue(func)->l; |
303 | f = fvalue(func); | 271 | L->ci->savedpc = L->savedpc; |
304 | goto Cfunc; | 272 | if (!cl->isC) { /* Lua function? prepare its call */ |
305 | case LUA_TCCL: { /* C closure */ | 273 | CallInfo *ci; |
306 | f = clCvalue(func)->f; | 274 | StkId st, base; |
307 | Cfunc: | 275 | Proto *p = cl->p; |
308 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 276 | luaD_checkstack(L, p->maxstacksize); |
309 | ci = next_ci(L); /* now 'enter' new function */ | 277 | func = restorestack(L, funcr); |
310 | ci->nresults = nresults; | 278 | if (!p->is_vararg) { /* no varargs? */ |
311 | ci->func = restorestack(L, funcr); | 279 | base = func + 1; |
312 | ci->top = L->top + LUA_MINSTACK; | 280 | if (L->top > base + p->numparams) |
313 | lua_assert(ci->top <= L->stack_last); | 281 | L->top = base + p->numparams; |
314 | ci->callstatus = 0; | ||
315 | luaC_checkGC(L); /* stack grow uses memory */ | ||
316 | if (L->hookmask & LUA_MASKCALL) | ||
317 | luaD_hook(L, LUA_HOOKCALL, -1); | ||
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; | ||
324 | } | 282 | } |
325 | case LUA_TLCL: { /* Lua function: prepare its call */ | 283 | else { /* vararg function */ |
326 | StkId base; | 284 | int nargs = cast_int(L->top - func) - 1; |
327 | Proto *p = clLvalue(func)->p; | 285 | base = adjust_varargs(L, p, nargs); |
328 | n = cast_int(L->top - func) - 1; /* number of real arguments */ | 286 | func = restorestack(L, funcr); /* previous call may change the stack */ |
329 | luaD_checkstack(L, p->maxstacksize); | 287 | } |
330 | for (; n < p->numparams; n++) | 288 | ci = inc_ci(L); /* now `enter' new function */ |
331 | setnilvalue(L->top++); /* complete missing arguments */ | 289 | ci->func = func; |
332 | if (!p->is_vararg) { | 290 | L->base = ci->base = base; |
333 | func = restorestack(L, funcr); | 291 | ci->top = L->base + p->maxstacksize; |
334 | base = func + 1; | 292 | lua_assert(ci->top <= L->stack_last); |
335 | } | 293 | L->savedpc = p->code; /* starting point */ |
336 | else { | 294 | ci->tailcalls = 0; |
337 | base = adjust_varargs(L, p, n); | 295 | ci->nresults = nresults; |
338 | func = restorestack(L, funcr); /* previous call can change stack */ | 296 | for (st = L->top; st < ci->top; st++) |
339 | } | 297 | setnilvalue(st); |
340 | ci = next_ci(L); /* now 'enter' new function */ | 298 | L->top = ci->top; |
341 | ci->nresults = nresults; | 299 | if (L->hookmask & LUA_MASKCALL) { |
342 | ci->func = func; | 300 | L->savedpc++; /* hooks assume 'pc' is already incremented */ |
343 | ci->u.l.base = base; | 301 | luaD_callhook(L, LUA_HOOKCALL, -1); |
344 | ci->top = base + p->maxstacksize; | 302 | L->savedpc--; /* correct 'pc' */ |
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; | ||
353 | } | 303 | } |
354 | default: { /* not a function */ | 304 | return PCRLUA; |
355 | func = tryfuncTM(L, func); /* retry with 'function' tag method */ | 305 | } |
356 | return luaD_precall(L, func, nresults); /* now it must be a function */ | 306 | else { /* if is a C function, call it */ |
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; | ||
357 | } | 326 | } |
358 | } | 327 | } |
359 | } | 328 | } |
360 | 329 | ||
361 | 330 | ||
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 | |||
362 | int luaD_poscall (lua_State *L, StkId firstResult) { | 342 | int luaD_poscall (lua_State *L, StkId firstResult) { |
363 | StkId res; | 343 | StkId res; |
364 | int wanted, i; | 344 | int wanted, i; |
365 | CallInfo *ci = L->ci; | 345 | CallInfo *ci; |
366 | if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { | 346 | if (L->hookmask & LUA_MASKRET) |
367 | if (L->hookmask & LUA_MASKRET) { | 347 | firstResult = callrethooks(L, firstResult); |
368 | ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ | 348 | ci = L->ci--; |
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 | } | ||
374 | res = ci->func; /* res == final position of 1st result */ | 349 | res = ci->func; /* res == final position of 1st result */ |
375 | wanted = ci->nresults; | 350 | wanted = ci->nresults; |
376 | L->ci = ci = ci->previous; /* back to caller */ | 351 | L->base = (ci - 1)->base; /* restore base */ |
352 | L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ | ||
377 | /* move results to correct place */ | 353 | /* move results to correct place */ |
378 | for (i = wanted; i != 0 && firstResult < L->top; i--) | 354 | for (i = wanted; i != 0 && firstResult < L->top; i--) |
379 | setobjs2s(L, res++, firstResult++); | 355 | setobjs2s(L, res++, firstResult++); |
@@ -389,226 +365,112 @@ int luaD_poscall (lua_State *L, StkId firstResult) { | |||
389 | ** The arguments are on the stack, right after the function. | 365 | ** The arguments are on the stack, right after the function. |
390 | ** When returns, all the results are on the stack, starting at the original | 366 | ** When returns, all the results are on the stack, starting at the original |
391 | ** function position. | 367 | ** function position. |
392 | */ | 368 | */ |
393 | void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) { | 369 | void luaD_call (lua_State *L, StkId func, int nResults) { |
394 | if (++L->nCcalls >= LUAI_MAXCCALLS) { | 370 | if (++L->nCcalls >= LUAI_MAXCCALLS) { |
395 | if (L->nCcalls == LUAI_MAXCCALLS) | 371 | if (L->nCcalls == LUAI_MAXCCALLS) |
396 | luaG_runerror(L, "C stack overflow"); | 372 | luaG_runerror(L, "C stack overflow"); |
397 | else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) | 373 | else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) |
398 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ | 374 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ |
399 | } | 375 | } |
400 | if (!allowyield) L->nny++; | 376 | if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ |
401 | if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ | 377 | luaV_execute(L, 1); /* call it */ |
402 | luaV_execute(L); /* call it */ | ||
403 | if (!allowyield) L->nny--; | ||
404 | L->nCcalls--; | 378 | L->nCcalls--; |
379 | luaC_checkGC(L); | ||
405 | } | 380 | } |
406 | 381 | ||
407 | 382 | ||
408 | static void finishCcall (lua_State *L) { | ||
409 | CallInfo *ci = L->ci; | ||
410 | int n; | ||
411 | lua_assert(ci->u.c.k != NULL); /* must have a continuation */ | ||
412 | lua_assert(L->nny == 0); | ||
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; | ||
416 | } | ||
417 | /* finish 'lua_callk'/'lua_pcall' */ | ||
418 | adjustresults(L, ci->nresults); | ||
419 | /* call continuation function */ | ||
420 | if (!(ci->callstatus & CIST_STAT)) /* no call status? */ | ||
421 | ci->u.c.status = LUA_YIELD; /* 'default' status */ | ||
422 | lua_assert(ci->u.c.status != LUA_OK); | ||
423 | ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED; | ||
424 | lua_unlock(L); | ||
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' */ | ||
443 | } | ||
444 | } | ||
445 | } | ||
446 | |||
447 | |||
448 | /* | ||
449 | ** check whether thread has a suspended protected call | ||
450 | */ | ||
451 | static CallInfo *findpcall (lua_State *L) { | ||
452 | CallInfo *ci; | ||
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' */ | ||
490 | } | ||
491 | |||
492 | |||
493 | /* | ||
494 | ** do the work for 'lua_resume' in protected mode | ||
495 | */ | ||
496 | static void resume (lua_State *L, void *ud) { | 383 | static void resume (lua_State *L, void *ud) { |
497 | int nCcalls = L->nCcalls; | ||
498 | StkId firstArg = cast(StkId, ud); | 384 | StkId firstArg = cast(StkId, ud); |
499 | CallInfo *ci = L->ci; | 385 | CallInfo *ci = L->ci; |
500 | if (nCcalls >= LUAI_MAXCCALLS) | 386 | if (L->status == 0) { /* start coroutine? */ |
501 | resume_error(L, "C stack overflow", firstArg); | 387 | lua_assert(ci == L->base_ci && firstArg > L->base); |
502 | if (L->status == LUA_OK) { /* may be starting a coroutine */ | 388 | if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) |
503 | if (ci != &L->base_ci) /* not in base level? */ | 389 | return; |
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 | } | 390 | } |
509 | else if (L->status != LUA_YIELD) | ||
510 | resume_error(L, "cannot resume dead coroutine", firstArg); | ||
511 | else { /* resuming from previous yield */ | 391 | else { /* resuming from previous yield */ |
512 | L->status = LUA_OK; | 392 | lua_assert(L->status == LUA_YIELD); |
513 | ci->func = restorestack(L, ci->extra); | 393 | L->status = 0; |
514 | if (isLua(ci)) /* yielded inside a hook? */ | 394 | if (!f_isLua(ci)) { /* `common' yield? */ |
515 | luaV_execute(L); /* just continue running Lua code */ | 395 | /* finish interrupted execution of `OP_CALL' */ |
516 | else { /* 'common' yield */ | 396 | lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || |
517 | if (ci->u.c.k != NULL) { /* does it have a continuation? */ | 397 | GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); |
518 | int n; | 398 | if (luaD_poscall(L, firstArg)) /* complete it... */ |
519 | ci->u.c.status = LUA_YIELD; /* 'default' status */ | 399 | L->top = L->ci->top; /* and correct top if not multiple results */ |
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 | } | 400 | } |
529 | unroll(L, NULL); | 401 | else /* yielded inside a hook: just continue its execution */ |
402 | L->base = L->ci->base; | ||
530 | } | 403 | } |
531 | lua_assert(nCcalls == L->nCcalls); | 404 | luaV_execute(L, cast_int(L->ci - L->base_ci)); |
405 | } | ||
406 | |||
407 | |||
408 | static int resume_error (lua_State *L, const char *msg) { | ||
409 | L->top = L->ci->base; | ||
410 | setsvalue2s(L, L->top, luaS_new(L, msg)); | ||
411 | incr_top(L); | ||
412 | lua_unlock(L); | ||
413 | return LUA_ERRRUN; | ||
532 | } | 414 | } |
533 | 415 | ||
534 | 416 | ||
535 | LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { | 417 | LUA_API int lua_resume (lua_State *L, int nargs) { |
536 | int status; | 418 | int status; |
537 | int oldnny = L->nny; /* save 'nny' */ | ||
538 | lua_lock(L); | 419 | 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"); | ||
539 | luai_userstateresume(L, nargs); | 424 | luai_userstateresume(L, nargs); |
540 | L->nCcalls = (from) ? from->nCcalls + 1 : 1; | 425 | lua_assert(L->errfunc == 0); |
541 | L->nny = 0; /* allow yields */ | 426 | L->baseCcalls = ++L->nCcalls; |
542 | api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); | ||
543 | status = luaD_rawrunprotected(L, resume, L->top - nargs); | 427 | status = luaD_rawrunprotected(L, resume, L->top - nargs); |
544 | if (status == -1) /* error calling 'lua_resume'? */ | 428 | if (status != 0) { /* error? */ |
545 | status = LUA_ERRRUN; | 429 | L->status = cast_byte(status); /* mark thread as `dead' */ |
546 | else { /* yield or regular error */ | 430 | luaD_seterrorobj(L, status, L->top); |
547 | while (status != LUA_OK && status != LUA_YIELD) { /* error? */ | 431 | L->ci->top = L->top; |
548 | if (recover(L, status)) /* recover point? */ | ||
549 | status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */ | ||
550 | else { /* unrecoverable error */ | ||
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); | ||
558 | } | 432 | } |
559 | L->nny = oldnny; /* restore 'nny' */ | 433 | else { |
560 | L->nCcalls--; | 434 | lua_assert(L->nCcalls == L->baseCcalls); |
561 | lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); | 435 | status = L->status; |
436 | } | ||
437 | --L->nCcalls; | ||
562 | lua_unlock(L); | 438 | lua_unlock(L); |
563 | return status; | 439 | return status; |
564 | } | 440 | } |
565 | 441 | ||
566 | 442 | ||
567 | LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) { | 443 | LUA_API int lua_yield (lua_State *L, int nresults) { |
568 | CallInfo *ci = L->ci; | ||
569 | luai_userstateyield(L, nresults); | 444 | luai_userstateyield(L, nresults); |
570 | lua_lock(L); | 445 | lua_lock(L); |
571 | api_checknelems(L, nresults); | 446 | if (L->nCcalls > L->baseCcalls) |
572 | if (L->nny > 0) { | 447 | luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); |
573 | if (L != G(L)->mainthread) | 448 | L->base = L->top - nresults; /* protect stack slots below */ |
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 | } | ||
578 | L->status = LUA_YIELD; | 449 | 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 */ | ||
590 | lua_unlock(L); | 450 | lua_unlock(L); |
591 | return 0; /* return to 'luaD_hook' */ | 451 | return -1; |
592 | } | 452 | } |
593 | 453 | ||
594 | 454 | ||
595 | int luaD_pcall (lua_State *L, Pfunc func, void *u, | 455 | int luaD_pcall (lua_State *L, Pfunc func, void *u, |
596 | ptrdiff_t old_top, ptrdiff_t ef) { | 456 | ptrdiff_t old_top, ptrdiff_t ef) { |
597 | int status; | 457 | int status; |
598 | CallInfo *old_ci = L->ci; | 458 | unsigned short oldnCcalls = L->nCcalls; |
459 | ptrdiff_t old_ci = saveci(L, L->ci); | ||
599 | lu_byte old_allowhooks = L->allowhook; | 460 | lu_byte old_allowhooks = L->allowhook; |
600 | unsigned short old_nny = L->nny; | ||
601 | ptrdiff_t old_errfunc = L->errfunc; | 461 | ptrdiff_t old_errfunc = L->errfunc; |
602 | L->errfunc = ef; | 462 | L->errfunc = ef; |
603 | status = luaD_rawrunprotected(L, func, u); | 463 | status = luaD_rawrunprotected(L, func, u); |
604 | if (status != LUA_OK) { /* an error occurred? */ | 464 | if (status != 0) { /* an error occurred? */ |
605 | StkId oldtop = restorestack(L, old_top); | 465 | StkId oldtop = restorestack(L, old_top); |
606 | luaF_close(L, oldtop); /* close possible pending closures */ | 466 | luaF_close(L, oldtop); /* close eventual pending closures */ |
607 | seterrorobj(L, status, oldtop); | 467 | luaD_seterrorobj(L, status, oldtop); |
608 | L->ci = old_ci; | 468 | L->nCcalls = oldnCcalls; |
469 | L->ci = restoreci(L, old_ci); | ||
470 | L->base = L->ci->base; | ||
471 | L->savedpc = L->ci->savedpc; | ||
609 | L->allowhook = old_allowhooks; | 472 | L->allowhook = old_allowhooks; |
610 | L->nny = old_nny; | 473 | restore_stack_limit(L); |
611 | luaD_shrinkstack(L); | ||
612 | } | 474 | } |
613 | L->errfunc = old_errfunc; | 475 | L->errfunc = old_errfunc; |
614 | return status; | 476 | return status; |
@@ -621,60 +483,35 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, | |||
621 | */ | 483 | */ |
622 | struct SParser { /* data to `f_parser' */ | 484 | struct SParser { /* data to `f_parser' */ |
623 | ZIO *z; | 485 | ZIO *z; |
624 | Mbuffer buff; /* dynamic structure used by the scanner */ | 486 | Mbuffer buff; /* buffer to be used by the scanner */ |
625 | Dyndata dyd; /* dynamic structures used by the parser */ | ||
626 | const char *mode; | ||
627 | const char *name; | 487 | const char *name; |
628 | }; | 488 | }; |
629 | 489 | ||
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 | |||
640 | static void f_parser (lua_State *L, void *ud) { | 490 | static void f_parser (lua_State *L, void *ud) { |
641 | int i; | 491 | int i; |
492 | Proto *tf; | ||
642 | Closure *cl; | 493 | Closure *cl; |
643 | struct SParser *p = cast(struct SParser *, ud); | 494 | struct SParser *p = cast(struct SParser *, ud); |
644 | int c = zgetc(p->z); /* read first character */ | 495 | int c = luaZ_lookahead(p->z); |
645 | if (c == LUA_SIGNATURE[0]) { | 496 | luaC_checkGC(L); |
646 | checkmode(L, p->mode, "binary"); | 497 | tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, |
647 | cl = luaU_undump(L, p->z, &p->buff, p->name); | 498 | &p->buff, p->name); |
648 | } | 499 | cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); |
649 | else { | 500 | cl->l.p = tf; |
650 | checkmode(L, p->mode, "text"); | 501 | for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ |
651 | cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); | 502 | cl->l.upvals[i] = luaF_newupval(L); |
652 | } | 503 | setclvalue(L, L->top, cl); |
653 | lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues); | 504 | incr_top(L); |
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 | } | ||
659 | } | 505 | } |
660 | 506 | ||
661 | 507 | ||
662 | int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, | 508 | int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { |
663 | const char *mode) { | ||
664 | struct SParser p; | 509 | struct SParser p; |
665 | int status; | 510 | int status; |
666 | L->nny++; /* cannot yield during parsing */ | 511 | p.z = z; p.name = name; |
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; | ||
671 | luaZ_initbuffer(L, &p.buff); | 512 | luaZ_initbuffer(L, &p.buff); |
672 | status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); | 513 | status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); |
673 | luaZ_freebuffer(L, &p.buff); | 514 | 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--; | ||
678 | return status; | 515 | return status; |
679 | } | 516 | } |
680 | 517 | ||
diff --git a/apps/plugins/lua/ldo.h b/apps/plugins/lua/ldo.h index d3d3082c9b..4c97134805 100644 --- a/apps/plugins/lua/ldo.h +++ b/apps/plugins/lua/ldo.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.h,v 2.20.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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,34 +13,45 @@ | |||
13 | #include "lzio.h" | 13 | #include "lzio.h" |
14 | 14 | ||
15 | 15 | ||
16 | #define luaD_checkstack(L,n) if (L->stack_last - L->top <= (n)) \ | 16 | #define luaD_checkstack(L,n) \ |
17 | luaD_growstack(L, n); else condmovestack(L); | 17 | if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ |
18 | luaD_growstack(L, n); \ | ||
19 | else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); | ||
18 | 20 | ||
19 | 21 | ||
20 | #define incr_top(L) {L->top++; luaD_checkstack(L,0);} | 22 | #define incr_top(L) {luaD_checkstack(L,1); L->top++;} |
21 | 23 | ||
22 | #define savestack(L,p) ((char *)(p) - (char *)L->stack) | 24 | #define savestack(L,p) ((char *)(p) - (char *)L->stack) |
23 | #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) | 25 | #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) |
24 | 26 | ||
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 | |||
25 | 36 | ||
26 | /* type of protected functions, to be ran by `runprotected' */ | 37 | /* type of protected functions, to be ran by `runprotected' */ |
27 | typedef void (*Pfunc) (lua_State *L, void *ud); | 38 | typedef void (*Pfunc) (lua_State *L, void *ud); |
28 | 39 | ||
29 | LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, | 40 | LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); |
30 | const char *mode); | 41 | LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); |
31 | LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); | ||
32 | LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); | 42 | LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); |
33 | LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults, | 43 | LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); |
34 | int allowyield); | ||
35 | LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, | 44 | LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, |
36 | ptrdiff_t oldtop, ptrdiff_t ef); | 45 | ptrdiff_t oldtop, ptrdiff_t ef); |
37 | LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); | 46 | LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); |
47 | LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); | ||
38 | LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); | 48 | LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); |
39 | LUAI_FUNC void luaD_growstack (lua_State *L, int n); | 49 | LUAI_FUNC void luaD_growstack (lua_State *L, int n); |
40 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); | ||
41 | 50 | ||
42 | LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); | 51 | LUAI_FUNC void luaD_throw (lua_State *L, int errcode); |
43 | LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); | 52 | LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); |
44 | 53 | ||
54 | LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); | ||
55 | |||
45 | #endif | 56 | #endif |
46 | 57 | ||
diff --git a/apps/plugins/lua/ldump.c b/apps/plugins/lua/ldump.c index 61fa2cd892..c9d3d4870f 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.17.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 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) | 63 | if (s==NULL || getstr(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*sizeof(char),D); | 72 | DumpBlock(getstr(s),size,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, DumpState* D); | 78 | static void DumpFunction(const Proto* f, const TString* p, 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(ttypenv(o),D); | 87 | DumpChar(ttype(o),D); |
88 | switch (ttypenv(o)) | 88 | switch (ttype(o)) |
89 | { | 89 | { |
90 | case LUA_TNIL: | 90 | case LUA_TNIL: |
91 | break; | 91 | break; |
@@ -98,29 +98,19 @@ 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: lua_assert(0); | 101 | default: |
102 | lua_assert(0); /* cannot happen */ | ||
103 | break; | ||
102 | } | 104 | } |
103 | } | 105 | } |
104 | n=f->sizep; | 106 | n=f->sizep; |
105 | DumpInt(n,D); | 107 | DumpInt(n,D); |
106 | for (i=0; i<n; i++) DumpFunction(f->p[i],D); | 108 | for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,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 | } | ||
118 | } | 109 | } |
119 | 110 | ||
120 | static void DumpDebug(const Proto* f, DumpState* D) | 111 | static void DumpDebug(const Proto* f, DumpState* D) |
121 | { | 112 | { |
122 | int i,n; | 113 | int i,n; |
123 | DumpString((D->strip) ? NULL : f->source,D); | ||
124 | n= (D->strip) ? 0 : f->sizelineinfo; | 114 | n= (D->strip) ? 0 : f->sizelineinfo; |
125 | DumpVector(f->lineinfo,n,sizeof(int),D); | 115 | DumpVector(f->lineinfo,n,sizeof(int),D); |
126 | n= (D->strip) ? 0 : f->sizelocvars; | 116 | n= (D->strip) ? 0 : f->sizelocvars; |
@@ -133,25 +123,26 @@ static void DumpDebug(const Proto* f, DumpState* D) | |||
133 | } | 123 | } |
134 | n= (D->strip) ? 0 : f->sizeupvalues; | 124 | n= (D->strip) ? 0 : f->sizeupvalues; |
135 | DumpInt(n,D); | 125 | DumpInt(n,D); |
136 | for (i=0; i<n; i++) DumpString(f->upvalues[i].name,D); | 126 | for (i=0; i<n; i++) DumpString(f->upvalues[i],D); |
137 | } | 127 | } |
138 | 128 | ||
139 | static void DumpFunction(const Proto* f, DumpState* D) | 129 | static void DumpFunction(const Proto* f, const TString* p, DumpState* D) |
140 | { | 130 | { |
131 | DumpString((f->source==p || D->strip) ? NULL : f->source,D); | ||
141 | DumpInt(f->linedefined,D); | 132 | DumpInt(f->linedefined,D); |
142 | DumpInt(f->lastlinedefined,D); | 133 | DumpInt(f->lastlinedefined,D); |
134 | DumpChar(f->nups,D); | ||
143 | DumpChar(f->numparams,D); | 135 | DumpChar(f->numparams,D); |
144 | DumpChar(f->is_vararg,D); | 136 | DumpChar(f->is_vararg,D); |
145 | DumpChar(f->maxstacksize,D); | 137 | DumpChar(f->maxstacksize,D); |
146 | DumpCode(f,D); | 138 | DumpCode(f,D); |
147 | DumpConstants(f,D); | 139 | DumpConstants(f,D); |
148 | DumpUpvalues(f,D); | ||
149 | DumpDebug(f,D); | 140 | DumpDebug(f,D); |
150 | } | 141 | } |
151 | 142 | ||
152 | static void DumpHeader(DumpState* D) | 143 | static void DumpHeader(DumpState* D) |
153 | { | 144 | { |
154 | lu_byte h[LUAC_HEADERSIZE]; | 145 | char h[LUAC_HEADERSIZE]; |
155 | luaU_header(h); | 146 | luaU_header(h); |
156 | DumpBlock(h,LUAC_HEADERSIZE,D); | 147 | DumpBlock(h,LUAC_HEADERSIZE,D); |
157 | } | 148 | } |
@@ -168,6 +159,6 @@ int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip | |||
168 | D.strip=strip; | 159 | D.strip=strip; |
169 | D.status=0; | 160 | D.status=0; |
170 | DumpHeader(&D); | 161 | DumpHeader(&D); |
171 | DumpFunction(f,&D); | 162 | DumpFunction(f,NULL,&D); |
172 | return D.status; | 163 | return D.status; |
173 | } | 164 | } |
diff --git a/apps/plugins/lua/lfunc.c b/apps/plugins/lua/lfunc.c index e90e1520ce..813e88f583 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.30.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 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,24 +20,30 @@ | |||
20 | 20 | ||
21 | 21 | ||
22 | 22 | ||
23 | Closure *luaF_newCclosure (lua_State *L, int n) { | 23 | Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { |
24 | Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n), NULL, 0)->cl; | 24 | Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); |
25 | c->c.nupvalues = cast_byte(n); | 25 | luaC_link(L, obj2gco(c), LUA_TFUNCTION); |
26 | c->c.isC = 1; | ||
27 | c->c.env = e; | ||
28 | c->c.nupvalues = cast_byte(nelems); | ||
26 | return c; | 29 | return c; |
27 | } | 30 | } |
28 | 31 | ||
29 | 32 | ||
30 | Closure *luaF_newLclosure (lua_State *L, int n) { | 33 | Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { |
31 | Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n), NULL, 0)->cl; | 34 | Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); |
32 | c->l.p = NULL; | 35 | luaC_link(L, obj2gco(c), LUA_TFUNCTION); |
33 | c->l.nupvalues = cast_byte(n); | 36 | c->l.isC = 0; |
34 | while (n--) c->l.upvals[n] = NULL; | 37 | c->l.env = e; |
38 | c->l.nupvalues = cast_byte(nelems); | ||
39 | while (nelems--) c->l.upvals[nelems] = NULL; | ||
35 | return c; | 40 | return c; |
36 | } | 41 | } |
37 | 42 | ||
38 | 43 | ||
39 | UpVal *luaF_newupval (lua_State *L) { | 44 | UpVal *luaF_newupval (lua_State *L) { |
40 | UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv; | 45 | UpVal *uv = luaM_new(L, UpVal); |
46 | luaC_link(L, obj2gco(uv), LUA_TUPVAL); | ||
41 | uv->v = &uv->u.value; | 47 | uv->v = &uv->u.value; |
42 | setnilvalue(uv->v); | 48 | setnilvalue(uv->v); |
43 | return uv; | 49 | return uv; |
@@ -49,20 +55,21 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { | |||
49 | GCObject **pp = &L->openupval; | 55 | GCObject **pp = &L->openupval; |
50 | UpVal *p; | 56 | UpVal *p; |
51 | UpVal *uv; | 57 | UpVal *uv; |
52 | while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { | 58 | while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { |
53 | GCObject *o = obj2gco(p); | ||
54 | lua_assert(p->v != &p->u.value); | 59 | lua_assert(p->v != &p->u.value); |
55 | lua_assert(!isold(o) || isold(obj2gco(L))); | ||
56 | if (p->v == level) { /* found a corresponding upvalue? */ | 60 | if (p->v == level) { /* found a corresponding upvalue? */ |
57 | if (isdead(g, o)) /* is it dead? */ | 61 | if (isdead(g, obj2gco(p))) /* is it dead? */ |
58 | changewhite(o); /* resurrect it */ | 62 | changewhite(obj2gco(p)); /* ressurect it */ |
59 | return p; | 63 | return p; |
60 | } | 64 | } |
61 | pp = &p->next; | 65 | pp = &p->next; |
62 | } | 66 | } |
63 | /* not found: create a new one */ | 67 | uv = luaM_new(L, UpVal); /* not found: create a new one */ |
64 | uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv; | 68 | uv->tt = LUA_TUPVAL; |
69 | uv->marked = luaC_white(g); | ||
65 | uv->v = level; /* current value lives in the stack */ | 70 | uv->v = level; /* current value lives in the stack */ |
71 | uv->next = *pp; /* chain it in the proper position */ | ||
72 | *pp = obj2gco(uv); | ||
66 | uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ | 73 | uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ |
67 | uv->u.l.next = g->uvhead.u.l.next; | 74 | uv->u.l.next = g->uvhead.u.l.next; |
68 | uv->u.l.next->u.l.prev = uv; | 75 | uv->u.l.next->u.l.prev = uv; |
@@ -89,42 +96,41 @@ void luaF_freeupval (lua_State *L, UpVal *uv) { | |||
89 | void luaF_close (lua_State *L, StkId level) { | 96 | void luaF_close (lua_State *L, StkId level) { |
90 | UpVal *uv; | 97 | UpVal *uv; |
91 | global_State *g = G(L); | 98 | global_State *g = G(L); |
92 | while (L->openupval != NULL && (uv = gco2uv(L->openupval))->v >= level) { | 99 | while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { |
93 | GCObject *o = obj2gco(uv); | 100 | GCObject *o = obj2gco(uv); |
94 | lua_assert(!isblack(o) && uv->v != &uv->u.value); | 101 | lua_assert(!isblack(o) && uv->v != &uv->u.value); |
95 | L->openupval = uv->next; /* remove from `open' list */ | 102 | L->openupval = uv->next; /* remove from `open' list */ |
96 | if (isdead(g, o)) | 103 | if (isdead(g, o)) |
97 | luaF_freeupval(L, uv); /* free upvalue */ | 104 | luaF_freeupval(L, uv); /* free upvalue */ |
98 | else { | 105 | else { |
99 | unlinkupval(uv); /* remove upvalue from 'uvhead' list */ | 106 | unlinkupval(uv); |
100 | setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ | 107 | setobj(L, &uv->u.value, uv->v); |
101 | uv->v = &uv->u.value; /* now current value lives here */ | 108 | uv->v = &uv->u.value; /* now current value lives here */ |
102 | gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */ | 109 | luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ |
103 | g->allgc = o; | ||
104 | luaC_checkupvalcolor(g, uv); | ||
105 | } | 110 | } |
106 | } | 111 | } |
107 | } | 112 | } |
108 | 113 | ||
109 | 114 | ||
110 | Proto *luaF_newproto (lua_State *L) { | 115 | Proto *luaF_newproto (lua_State *L) { |
111 | Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p; | 116 | Proto *f = luaM_new(L, Proto); |
117 | luaC_link(L, obj2gco(f), LUA_TPROTO); | ||
112 | f->k = NULL; | 118 | f->k = NULL; |
113 | f->sizek = 0; | 119 | f->sizek = 0; |
114 | f->p = NULL; | 120 | f->p = NULL; |
115 | f->sizep = 0; | 121 | f->sizep = 0; |
116 | f->code = NULL; | 122 | f->code = NULL; |
117 | f->cache = NULL; | ||
118 | f->sizecode = 0; | 123 | f->sizecode = 0; |
119 | f->lineinfo = NULL; | ||
120 | f->sizelineinfo = 0; | 124 | f->sizelineinfo = 0; |
121 | f->upvalues = NULL; | ||
122 | f->sizeupvalues = 0; | 125 | f->sizeupvalues = 0; |
126 | f->nups = 0; | ||
127 | f->upvalues = NULL; | ||
123 | f->numparams = 0; | 128 | f->numparams = 0; |
124 | f->is_vararg = 0; | 129 | f->is_vararg = 0; |
125 | f->maxstacksize = 0; | 130 | f->maxstacksize = 0; |
126 | f->locvars = NULL; | 131 | f->lineinfo = NULL; |
127 | f->sizelocvars = 0; | 132 | f->sizelocvars = 0; |
133 | f->locvars = NULL; | ||
128 | f->linedefined = 0; | 134 | f->linedefined = 0; |
129 | f->lastlinedefined = 0; | 135 | f->lastlinedefined = 0; |
130 | f->source = NULL; | 136 | f->source = NULL; |
@@ -133,16 +139,23 @@ Proto *luaF_newproto (lua_State *L) { | |||
133 | 139 | ||
134 | 140 | ||
135 | void luaF_freeproto (lua_State *L, Proto *f) { | 141 | void luaF_freeproto (lua_State *L, Proto *f) { |
136 | luaM_freearray(L, f->code, f->sizecode); | 142 | luaM_freearray(L, f->code, f->sizecode, Instruction); |
137 | luaM_freearray(L, f->p, f->sizep); | 143 | luaM_freearray(L, f->p, f->sizep, Proto *); |
138 | luaM_freearray(L, f->k, f->sizek); | 144 | luaM_freearray(L, f->k, f->sizek, TValue); |
139 | luaM_freearray(L, f->lineinfo, f->sizelineinfo); | 145 | luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); |
140 | luaM_freearray(L, f->locvars, f->sizelocvars); | 146 | luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); |
141 | luaM_freearray(L, f->upvalues, f->sizeupvalues); | 147 | luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); |
142 | luaM_free(L, f); | 148 | luaM_free(L, f); |
143 | } | 149 | } |
144 | 150 | ||
145 | 151 | ||
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 | |||
146 | /* | 159 | /* |
147 | ** Look for n-th local variable at line `line' in function `func'. | 160 | ** Look for n-th local variable at line `line' in function `func'. |
148 | ** Returns NULL if not found. | 161 | ** Returns NULL if not found. |
diff --git a/apps/plugins/lua/lfunc.h b/apps/plugins/lua/lfunc.h index ca0d3a3e0b..4c2b7fd138 100644 --- a/apps/plugins/lua/lfunc.h +++ b/apps/plugins/lua/lfunc.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lfunc.h,v 2.8.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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,12 +19,13 @@ | |||
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); | 22 | LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); |
23 | LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems); | 23 | LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); |
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); | ||
28 | LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); | 29 | LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); |
29 | LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, | 30 | LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, |
30 | int pc); | 31 | int pc); |
diff --git a/apps/plugins/lua/lgc.c b/apps/plugins/lua/lgc.c index 52460dcdd5..d9e0b78294 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.140.1.2 2013/04/26 18:22:05 roberto Exp $ | 2 | ** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 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,1079 +23,583 @@ | |||
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 | ||
26 | 30 | ||
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) | ||
32 | |||
33 | /* maximum number of elements to sweep in each single step */ | ||
34 | #define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) | ||
35 | |||
36 | /* maximum number of finalizers to call in each GC step */ | ||
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 | ||
52 | 31 | ||
32 | #define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) | ||
53 | 33 | ||
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) \ | 34 | #define makewhite(g,x) \ |
60 | (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) | 35 | ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) |
61 | 36 | ||
62 | #define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) | 37 | #define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) |
63 | #define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) | 38 | #define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) |
64 | 39 | ||
40 | #define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) | ||
65 | 41 | ||
66 | #define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) | ||
67 | 42 | ||
68 | #define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) | 43 | #define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) |
44 | #define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) | ||
69 | 45 | ||
70 | 46 | ||
71 | #define checkconsistency(obj) \ | 47 | #define KEYWEAK bitmask(KEYWEAKBIT) |
72 | lua_longassert(!iscollectable(obj) || righttt(obj)) | 48 | #define VALUEWEAK bitmask(VALUEWEAKBIT) |
49 | |||
73 | 50 | ||
74 | 51 | ||
75 | #define markvalue(g,o) { checkconsistency(o); \ | 52 | #define markvalue(g,o) { checkconsistency(o); \ |
76 | if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } | 53 | if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } |
77 | 54 | ||
78 | #define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \ | 55 | #define markobject(g,t) { if (iswhite(obj2gco(t))) \ |
79 | reallymarkobject(g, obj2gco(t)); } | 56 | reallymarkobject(g, obj2gco(t)); } |
80 | 57 | ||
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 | |||
96 | 58 | ||
97 | /* | 59 | #define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) |
98 | ** link table 'h' into list pointed by 'p' | ||
99 | */ | ||
100 | #define linktable(h,p) ((h)->gclist = *(p), *(p) = obj2gco(h)) | ||
101 | 60 | ||
102 | 61 | ||
103 | /* | ||
104 | ** if key is not marked, mark its entry as dead (therefore removing it | ||
105 | ** from the table) | ||
106 | */ | ||
107 | static void removeentry (Node *n) { | 62 | static void removeentry (Node *n) { |
108 | lua_assert(ttisnil(gval(n))); | 63 | lua_assert(ttisnil(gval(n))); |
109 | if (valiswhite(gkey(n))) | 64 | if (iscollectable(gkey(n))) |
110 | setdeadvalue(gkey(n)); /* unused and unmarked key; remove it */ | 65 | setttype(gkey(n), LUA_TDEADKEY); /* dead 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)); | ||
128 | } | 66 | } |
129 | 67 | ||
130 | 68 | ||
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 | */ | ||
243 | static void reallymarkobject (global_State *g, GCObject *o) { | 69 | static void reallymarkobject (global_State *g, GCObject *o) { |
244 | lu_mem size; | 70 | lua_assert(iswhite(o) && !isdead(g, o)); |
245 | white2gray(o); | 71 | white2gray(o); |
246 | switch (gch(o)->tt) { | 72 | switch (o->gch.tt) { |
247 | case LUA_TSHRSTR: | 73 | case LUA_TSTRING: { |
248 | case LUA_TLNGSTR: { | 74 | return; |
249 | size = sizestring(gco2ts(o)); | ||
250 | break; /* nothing else to mark; make it black */ | ||
251 | } | 75 | } |
252 | case LUA_TUSERDATA: { | 76 | case LUA_TUSERDATA: { |
253 | Table *mt = gco2u(o)->metatable; | 77 | Table *mt = gco2u(o)->metatable; |
254 | markobject(g, mt); | 78 | gray2black(o); /* udata are never gray */ |
79 | if (mt) markobject(g, mt); | ||
255 | markobject(g, gco2u(o)->env); | 80 | markobject(g, gco2u(o)->env); |
256 | size = sizeudata(gco2u(o)); | 81 | return; |
257 | break; | ||
258 | } | 82 | } |
259 | case LUA_TUPVAL: { | 83 | case LUA_TUPVAL: { |
260 | UpVal *uv = gco2uv(o); | 84 | UpVal *uv = gco2uv(o); |
261 | markvalue(g, uv->v); | 85 | markvalue(g, uv->v); |
262 | if (uv->v != &uv->u.value) /* open? */ | 86 | if (uv->v == &uv->u.value) /* closed? */ |
263 | return; /* open upvalues remain gray */ | 87 | gray2black(o); /* open upvalues are never black */ |
264 | size = sizeof(UpVal); | ||
265 | break; | ||
266 | } | ||
267 | case LUA_TLCL: { | ||
268 | gco2lcl(o)->gclist = g->gray; | ||
269 | g->gray = o; | ||
270 | return; | 88 | return; |
271 | } | 89 | } |
272 | case LUA_TCCL: { | 90 | case LUA_TFUNCTION: { |
273 | gco2ccl(o)->gclist = g->gray; | 91 | gco2cl(o)->c.gclist = g->gray; |
274 | g->gray = o; | 92 | g->gray = o; |
275 | return; | 93 | break; |
276 | } | 94 | } |
277 | case LUA_TTABLE: { | 95 | case LUA_TTABLE: { |
278 | linktable(gco2t(o), &g->gray); | 96 | gco2h(o)->gclist = g->gray; |
279 | return; | 97 | g->gray = o; |
98 | break; | ||
280 | } | 99 | } |
281 | case LUA_TTHREAD: { | 100 | case LUA_TTHREAD: { |
282 | gco2th(o)->gclist = g->gray; | 101 | gco2th(o)->gclist = g->gray; |
283 | g->gray = o; | 102 | g->gray = o; |
284 | return; | 103 | break; |
285 | } | 104 | } |
286 | case LUA_TPROTO: { | 105 | case LUA_TPROTO: { |
287 | gco2p(o)->gclist = g->gray; | 106 | gco2p(o)->gclist = g->gray; |
288 | g->gray = o; | 107 | g->gray = o; |
289 | return; | 108 | break; |
290 | } | 109 | } |
291 | default: lua_assert(0); return; | 110 | default: lua_assert(0); |
292 | } | 111 | } |
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]); | ||
305 | } | 112 | } |
306 | 113 | ||
307 | 114 | ||
308 | /* | 115 | static void marktmu (global_State *g) { |
309 | ** mark all objects in list of being-finalized | 116 | GCObject *u = g->tmudata; |
310 | */ | 117 | if (u) { |
311 | static void markbeingfnz (global_State *g) { | 118 | do { |
312 | GCObject *o; | 119 | u = u->gch.next; |
313 | for (o = g->tobefnz; o != NULL; o = gch(o)->next) { | 120 | makewhite(g, u); /* may be marked, if left from previous GC */ |
314 | makewhite(g, o); | 121 | reallymarkobject(g, u); |
315 | reallymarkobject(g, o); | 122 | } while (u != g->tmudata); |
316 | } | 123 | } |
317 | } | 124 | } |
318 | 125 | ||
319 | 126 | ||
320 | /* | 127 | /* move `dead' udata that need finalization to list `tmudata' */ |
321 | ** mark all values stored in marked open upvalues. (See comment in | 128 | size_t luaC_separateudata (lua_State *L, int all) { |
322 | ** 'lstate.h'.) | 129 | global_State *g = G(L); |
323 | */ | 130 | size_t deadmem = 0; |
324 | static void remarkupvals (global_State *g) { | 131 | GCObject **p = &g->mainthread->next; |
325 | UpVal *uv; | 132 | GCObject *curr; |
326 | for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { | 133 | while ((curr = *p) != NULL) { |
327 | if (isgray(obj2gco(uv))) | 134 | if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) |
328 | markvalue(g, uv->v); | 135 | p = &curr->gch.next; /* don't bother with them */ |
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 | } | ||
329 | } | 153 | } |
154 | return deadmem; | ||
330 | } | 155 | } |
331 | 156 | ||
332 | 157 | ||
333 | /* | 158 | static int traversetable (global_State *g, Table *h) { |
334 | ** mark root set and reset all gray lists, to start a new | 159 | int i; |
335 | ** incremental (or full) collection | 160 | int weakkey = 0; |
336 | */ | 161 | int weakvalue = 0; |
337 | static void restartcollection (global_State *g) { | 162 | const TValue *mode; |
338 | g->gray = g->grayagain = NULL; | 163 | if (h->metatable) |
339 | g->weak = g->allweak = g->ephemeron = NULL; | 164 | markobject(g, h->metatable); |
340 | markobject(g, g->mainthread); | 165 | mode = gfasttm(g, h->metatable, TM_MODE); |
341 | markvalue(g, &g->l_registry); | 166 | if (mode && ttisstring(mode)) { /* is there a weak mode? */ |
342 | markmt(g); | 167 | weakkey = (strchr(svalue(mode), 'k') != NULL); |
343 | markbeingfnz(g); /* mark any finalizing object left from previous cycle */ | 168 | weakvalue = (strchr(svalue(mode), 'v') != NULL); |
344 | } | 169 | if (weakkey || weakvalue) { /* is really weak? */ |
345 | 170 | h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ | |
346 | /* }====================================================== */ | 171 | h->marked |= cast_byte((weakkey << KEYWEAKBIT) | |
347 | 172 | (weakvalue << VALUEWEAKBIT)); | |
348 | 173 | h->gclist = g->weak; /* must be cleared after GC, ... */ | |
349 | /* | 174 | g->weak = obj2gco(h); /* ... so put in the appropriate list */ |
350 | ** {====================================================== | 175 | } |
351 | ** Traverse functions | 176 | } |
352 | ** ======================================================= | 177 | if (weakkey && weakvalue) return 1; |
353 | */ | 178 | if (!weakvalue) { |
354 | 179 | i = h->sizearray; | |
355 | static void traverseweakvalue (global_State *g, Table *h) { | 180 | while (i--) |
356 | Node *n, *limit = gnodelast(h); | 181 | markvalue(g, &h->array[i]); |
357 | /* if there is array part, assume it may have white values (do not | 182 | } |
358 | traverse it just to check) */ | 183 | i = sizenode(h); |
359 | int hasclears = (h->sizearray > 0); | 184 | while (i--) { |
360 | for (n = gnode(h, 0); n < limit; n++) { | 185 | Node *n = gnode(h, i); |
361 | checkdeadkey(n); | 186 | lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); |
362 | if (ttisnil(gval(n))) /* entry is empty? */ | 187 | if (ttisnil(gval(n))) |
363 | removeentry(n); /* remove it */ | 188 | removeentry(n); /* remove empty entries */ |
364 | else { | 189 | else { |
365 | lua_assert(!ttisnil(gkey(n))); | 190 | lua_assert(!ttisnil(gkey(n))); |
366 | markvalue(g, gkey(n)); /* mark key */ | 191 | if (!weakkey) markvalue(g, gkey(n)); |
367 | if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ | 192 | if (!weakvalue) markvalue(g, gval(n)); |
368 | hasclears = 1; /* table will have to be cleared */ | ||
369 | } | 193 | } |
370 | } | 194 | } |
371 | if (hasclears) | 195 | return weakkey || weakvalue; |
372 | linktable(h, &g->weak); /* has to be cleared later */ | ||
373 | else /* no white values */ | ||
374 | linktable(h, &g->grayagain); /* no need to clean */ | ||
375 | } | 196 | } |
376 | 197 | ||
377 | 198 | ||
378 | static int traverseephemeron (global_State *g, Table *h) { | 199 | /* |
379 | int marked = 0; /* true if an object is marked in this traversal */ | 200 | ** All marks are conditional because a GC may happen while the |
380 | int hasclears = 0; /* true if table has white keys */ | 201 | ** prototype is still being created |
381 | int prop = 0; /* true if table has entry "white-key -> white-value" */ | 202 | */ |
382 | Node *n, *limit = gnodelast(h); | 203 | static void traverseproto (global_State *g, Proto *f) { |
383 | int i; | 204 | int i; |
384 | /* traverse array part (numeric keys are 'strong') */ | 205 | if (f->source) stringmark(f->source); |
385 | for (i = 0; i < h->sizearray; i++) { | 206 | for (i=0; i<f->sizek; i++) /* mark literals */ |
386 | if (valiswhite(&h->array[i])) { | 207 | markvalue(g, &f->k[i]); |
387 | marked = 1; | 208 | for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */ |
388 | reallymarkobject(g, gcvalue(&h->array[i])); | 209 | if (f->upvalues[i]) |
389 | } | 210 | stringmark(f->upvalues[i]); |
390 | } | 211 | } |
391 | /* traverse hash part */ | 212 | for (i=0; i<f->sizep; i++) { /* mark nested protos */ |
392 | for (n = gnode(h, 0); n < limit; n++) { | 213 | if (f->p[i]) |
393 | checkdeadkey(n); | 214 | markobject(g, f->p[i]); |
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 | } | ||
405 | } | 215 | } |
406 | if (prop) | 216 | for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */ |
407 | linktable(h, &g->ephemeron); /* have to propagate again */ | 217 | if (f->locvars[i].varname) |
408 | else if (hasclears) /* does table have white keys? */ | 218 | stringmark(f->locvars[i].varname); |
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; | ||
413 | } | ||
414 | |||
415 | |||
416 | static void traversestrongtable (global_State *g, Table *h) { | ||
417 | Node *n, *limit = gnodelast(h); | ||
418 | int i; | ||
419 | for (i = 0; i < h->sizearray; i++) /* traverse array part */ | ||
420 | markvalue(g, &h->array[i]); | ||
421 | for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ | ||
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 | } | ||
430 | } | 219 | } |
431 | } | 220 | } |
432 | 221 | ||
433 | 222 | ||
434 | static lu_mem traversetable (global_State *g, Table *h) { | ||
435 | const char *weakkey, *weakvalue; | ||
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 */ | ||
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)); | ||
454 | } | ||
455 | 223 | ||
456 | 224 | static void traverseclosure (global_State *g, Closure *cl) { | |
457 | static int traverseproto (global_State *g, Proto *f) { | 225 | markobject(g, cl->c.env); |
458 | int i; | 226 | if (cl->c.isC) { |
459 | if (f->cache && iswhite(obj2gco(f->cache))) | 227 | int i; |
460 | f->cache = NULL; /* allow cache to be collected */ | 228 | for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */ |
461 | markobject(g, f->source); | 229 | markvalue(g, &cl->c.upvalue[i]); |
462 | for (i = 0; i < f->sizek; i++) /* mark literals */ | 230 | } |
463 | markvalue(g, &f->k[i]); | 231 | else { |
464 | for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ | 232 | int i; |
465 | markobject(g, f->upvalues[i].name); | 233 | lua_assert(cl->l.nupvalues == cl->l.p->nups); |
466 | for (i = 0; i < f->sizep; i++) /* mark nested protos */ | 234 | markobject(g, cl->l.p); |
467 | markobject(g, f->p[i]); | 235 | for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */ |
468 | for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ | 236 | markobject(g, cl->l.upvals[i]); |
469 | markobject(g, f->locvars[i].varname); | 237 | } |
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; | ||
476 | } | 238 | } |
477 | 239 | ||
478 | 240 | ||
479 | static lu_mem traverseCclosure (global_State *g, CClosure *cl) { | 241 | static void checkstacksizes (lua_State *L, StkId max) { |
480 | int i; | 242 | int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ |
481 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ | 243 | int s_used = cast_int(max - L->stack); /* part of stack in use */ |
482 | markvalue(g, &cl->upvalue[i]); | 244 | if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ |
483 | return sizeCclosure(cl->nupvalues); | 245 | return; /* do not touch the stacks */ |
246 | if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) | ||
247 | luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ | ||
248 | condhardstacktests(luaD_reallocCI(L, ci_used + 1)); | ||
249 | if (4*s_used < L->stacksize && | ||
250 | 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) | ||
251 | luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ | ||
252 | condhardstacktests(luaD_reallocstack(L, s_used)); | ||
484 | } | 253 | } |
485 | 254 | ||
486 | static lu_mem traverseLclosure (global_State *g, LClosure *cl) { | ||
487 | int i; | ||
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 | 255 | ||
494 | 256 | static void traversestack (global_State *g, lua_State *l) { | |
495 | static lu_mem traversestack (global_State *g, lua_State *th) { | 257 | StkId o, lim; |
496 | int n = 0; | 258 | CallInfo *ci; |
497 | StkId o = th->stack; | 259 | markvalue(g, gt(l)); |
498 | if (o == NULL) | 260 | lim = l->top; |
499 | return 1; /* stack not completely built yet */ | 261 | for (ci = l->base_ci; ci <= l->ci; ci++) { |
500 | for (; o < th->top; o++) /* mark live elements in the stack */ | 262 | lua_assert(ci->top <= l->stack_last); |
501 | markvalue(g, o); | 263 | if (lim < ci->top) lim = ci->top; |
502 | if (g->gcstate == GCSatomic) { /* final traversal? */ | ||
503 | StkId lim = th->stack + th->stacksize; /* real end of stack */ | ||
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 | } | 264 | } |
512 | return sizeof(lua_State) + sizeof(TValue) * th->stacksize + | 265 | for (o = l->stack; o < l->top; o++) |
513 | sizeof(CallInfo) * n; | 266 | markvalue(g, o); |
267 | for (; o <= lim; o++) | ||
268 | setnilvalue(o); | ||
269 | checkstacksizes(l, lim); | ||
514 | } | 270 | } |
515 | 271 | ||
516 | 272 | ||
517 | /* | 273 | /* |
518 | ** traverse one gray object, turning it to black (except for threads, | 274 | ** traverse one gray object, turning it to black. |
519 | ** which are always gray). | 275 | ** Returns `quantity' traversed. |
520 | */ | 276 | */ |
521 | static void propagatemark (global_State *g) { | 277 | static l_mem propagatemark (global_State *g) { |
522 | lu_mem size; | ||
523 | GCObject *o = g->gray; | 278 | GCObject *o = g->gray; |
524 | lua_assert(isgray(o)); | 279 | lua_assert(isgray(o)); |
525 | gray2black(o); | 280 | gray2black(o); |
526 | switch (gch(o)->tt) { | 281 | switch (o->gch.tt) { |
527 | case LUA_TTABLE: { | 282 | case LUA_TTABLE: { |
528 | Table *h = gco2t(o); | 283 | Table *h = gco2h(o); |
529 | g->gray = h->gclist; /* remove from 'gray' list */ | 284 | g->gray = h->gclist; |
530 | size = traversetable(g, h); | 285 | if (traversetable(g, h)) /* table is weak? */ |
531 | break; | 286 | black2gray(o); /* keep it gray */ |
532 | } | 287 | return sizeof(Table) + sizeof(TValue) * h->sizearray + |
533 | case LUA_TLCL: { | 288 | sizeof(Node) * sizenode(h); |
534 | LClosure *cl = gco2lcl(o); | 289 | } |
535 | g->gray = cl->gclist; /* remove from 'gray' list */ | 290 | case LUA_TFUNCTION: { |
536 | size = traverseLclosure(g, cl); | 291 | Closure *cl = gco2cl(o); |
537 | break; | 292 | g->gray = cl->c.gclist; |
538 | } | 293 | traverseclosure(g, cl); |
539 | case LUA_TCCL: { | 294 | return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : |
540 | CClosure *cl = gco2ccl(o); | 295 | sizeLclosure(cl->l.nupvalues); |
541 | g->gray = cl->gclist; /* remove from 'gray' list */ | ||
542 | size = traverseCclosure(g, cl); | ||
543 | break; | ||
544 | } | 296 | } |
545 | case LUA_TTHREAD: { | 297 | case LUA_TTHREAD: { |
546 | lua_State *th = gco2th(o); | 298 | lua_State *th = gco2th(o); |
547 | g->gray = th->gclist; /* remove from 'gray' list */ | 299 | g->gray = th->gclist; |
548 | th->gclist = g->grayagain; | 300 | th->gclist = g->grayagain; |
549 | g->grayagain = o; /* insert into 'grayagain' list */ | 301 | g->grayagain = o; |
550 | black2gray(o); | 302 | black2gray(o); |
551 | size = traversestack(g, th); | 303 | traversestack(g, th); |
552 | break; | 304 | return sizeof(lua_State) + sizeof(TValue) * th->stacksize + |
305 | sizeof(CallInfo) * th->size_ci; | ||
553 | } | 306 | } |
554 | case LUA_TPROTO: { | 307 | case LUA_TPROTO: { |
555 | Proto *p = gco2p(o); | 308 | Proto *p = gco2p(o); |
556 | g->gray = p->gclist; /* remove from 'gray' list */ | 309 | g->gray = p->gclist; |
557 | size = traverseproto(g, p); | 310 | traverseproto(g, p); |
558 | break; | 311 | return sizeof(Proto) + sizeof(Instruction) * p->sizecode + |
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; | ||
559 | } | 317 | } |
560 | default: lua_assert(0); return; | 318 | default: lua_assert(0); return 0; |
561 | } | 319 | } |
562 | g->GCmemtrav += size; | ||
563 | } | ||
564 | |||
565 | |||
566 | static void propagateall (global_State *g) { | ||
567 | while (g->gray) propagatemark(g); | ||
568 | } | ||
569 | |||
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 | |||
577 | /* | ||
578 | ** retraverse all gray lists. Because tables may be reinserted in other | ||
579 | ** lists when traversed, traverse the original lists to avoid traversing | ||
580 | ** twice the same table (which is not wrong, but inefficient) | ||
581 | */ | ||
582 | static void retraversegrays (global_State *g) { | ||
583 | GCObject *weak = g->weak; /* save original lists */ | ||
584 | GCObject *grayagain = g->grayagain; | ||
585 | GCObject *ephemeron = g->ephemeron; | ||
586 | g->weak = g->grayagain = g->ephemeron = NULL; | ||
587 | propagateall(g); /* traverse main gray list */ | ||
588 | propagatelist(g, grayagain); | ||
589 | propagatelist(g, weak); | ||
590 | propagatelist(g, ephemeron); | ||
591 | } | 320 | } |
592 | 321 | ||
593 | 322 | ||
594 | static void convergeephemerons (global_State *g) { | 323 | static size_t propagateall (global_State *g) { |
595 | int changed; | 324 | size_t m = 0; |
596 | do { | 325 | while (g->gray) m += propagatemark(g); |
597 | GCObject *w; | 326 | return m; |
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); | ||
609 | } | 327 | } |
610 | 328 | ||
611 | /* }====================================================== */ | ||
612 | |||
613 | 329 | ||
614 | /* | 330 | /* |
615 | ** {====================================================== | 331 | ** The next function tells whether a key or value can be cleared from |
616 | ** Sweep Functions | 332 | ** a weak table. Non-collectable objects are never removed from weak |
617 | ** ======================================================= | 333 | ** tables. Strings behave as `values', so are never removed too. for |
618 | */ | 334 | ** other objects: if really collected, cannot keep them; for userdata |
619 | 335 | ** being finalized, keep them in keys, but not in values | |
620 | |||
621 | /* | ||
622 | ** clear entries with unmarked keys from all weaktables in list 'l' up | ||
623 | ** to element 'f' | ||
624 | */ | 336 | */ |
625 | static void clearkeys (global_State *g, GCObject *l, GCObject *f) { | 337 | static int iscleared (const TValue *o, int iskey) { |
626 | for (; l != f; l = gco2t(l)->gclist) { | 338 | if (!iscollectable(o)) return 0; |
627 | Table *h = gco2t(l); | 339 | if (ttisstring(o)) { |
628 | Node *n, *limit = gnodelast(h); | 340 | stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ |
629 | for (n = gnode(h, 0); n < limit; n++) { | 341 | return 0; |
630 | if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { | ||
631 | setnilvalue(gval(n)); /* remove value ... */ | ||
632 | removeentry(n); /* and remove entry from table */ | ||
633 | } | ||
634 | } | ||
635 | } | 342 | } |
343 | return iswhite(gcvalue(o)) || | ||
344 | (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); | ||
636 | } | 345 | } |
637 | 346 | ||
638 | 347 | ||
639 | /* | 348 | /* |
640 | ** clear entries with unmarked values from all weaktables in list 'l' up | 349 | ** clear collected entries from weaktables |
641 | ** to element 'f' | ||
642 | */ | 350 | */ |
643 | static void clearvalues (global_State *g, GCObject *l, GCObject *f) { | 351 | static void cleartable (GCObject *l) { |
644 | for (; l != f; l = gco2t(l)->gclist) { | 352 | while (l) { |
645 | Table *h = gco2t(l); | 353 | Table *h = gco2h(l); |
646 | Node *n, *limit = gnodelast(h); | 354 | int i = h->sizearray; |
647 | int i; | 355 | lua_assert(testbit(h->marked, VALUEWEAKBIT) || |
648 | for (i = 0; i < h->sizearray; i++) { | 356 | testbit(h->marked, KEYWEAKBIT)); |
649 | TValue *o = &h->array[i]; | 357 | if (testbit(h->marked, VALUEWEAKBIT)) { |
650 | if (iscleared(g, o)) /* value was collected? */ | 358 | while (i--) { |
651 | setnilvalue(o); /* remove value */ | 359 | TValue *o = &h->array[i]; |
360 | if (iscleared(o, 0)) /* value was collected? */ | ||
361 | setnilvalue(o); /* remove value */ | ||
362 | } | ||
652 | } | 363 | } |
653 | for (n = gnode(h, 0); n < limit; n++) { | 364 | i = sizenode(h); |
654 | if (!ttisnil(gval(n)) && iscleared(g, gval(n))) { | 365 | while (i--) { |
366 | Node *n = gnode(h, i); | ||
367 | if (!ttisnil(gval(n)) && /* non-empty entry? */ | ||
368 | (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { | ||
655 | setnilvalue(gval(n)); /* remove value ... */ | 369 | setnilvalue(gval(n)); /* remove value ... */ |
656 | removeentry(n); /* and remove entry from table */ | 370 | removeentry(n); /* remove entry from table */ |
657 | } | 371 | } |
658 | } | 372 | } |
373 | l = h->gclist; | ||
659 | } | 374 | } |
660 | } | 375 | } |
661 | 376 | ||
662 | 377 | ||
663 | static void freeobj (lua_State *L, GCObject *o) { | 378 | static void freeobj (lua_State *L, GCObject *o) { |
664 | switch (gch(o)->tt) { | 379 | switch (o->gch.tt) { |
665 | case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; | 380 | case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; |
666 | case LUA_TLCL: { | 381 | case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; |
667 | luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); | 382 | case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; |
668 | break; | 383 | case LUA_TTABLE: luaH_free(L, gco2h(o)); break; |
669 | } | 384 | case LUA_TTHREAD: { |
670 | case LUA_TCCL: { | 385 | lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); |
671 | luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); | 386 | luaE_freethread(L, gco2th(o)); |
672 | break; | 387 | break; |
673 | } | 388 | } |
674 | case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; | 389 | case LUA_TSTRING: { |
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--; | 390 | G(L)->strt.nuse--; |
680 | /* go through */ | ||
681 | case LUA_TLNGSTR: { | ||
682 | luaM_freemem(L, o, sizestring(gco2ts(o))); | 391 | luaM_freemem(L, o, sizestring(gco2ts(o))); |
683 | break; | 392 | break; |
684 | } | 393 | } |
394 | case LUA_TUSERDATA: { | ||
395 | luaM_freemem(L, o, sizeudata(gco2u(o))); | ||
396 | break; | ||
397 | } | ||
685 | default: lua_assert(0); | 398 | default: lua_assert(0); |
686 | } | 399 | } |
687 | } | 400 | } |
688 | 401 | ||
689 | 402 | ||
690 | #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) | ||
691 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); | ||
692 | |||
693 | 403 | ||
694 | /* | 404 | #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) |
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 | 405 | ||
707 | 406 | ||
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 | */ | ||
719 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | 407 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { |
408 | GCObject *curr; | ||
720 | global_State *g = G(L); | 409 | global_State *g = G(L); |
721 | int ow = otherwhite(g); | 410 | int deadmask = otherwhite(g); |
722 | int toclear, toset; /* bits to clear and to set in all live objects */ | 411 | while ((curr = *p) != NULL && count-- > 0) { |
723 | int tostop; /* stop sweep when this is true */ | 412 | if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ |
724 | if (isgenerational(g)) { /* generational mode? */ | 413 | sweepwholelist(L, &gco2th(curr)->openupval); |
725 | toclear = ~0; /* clear nothing */ | 414 | if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ |
726 | toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */ | 415 | lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); |
727 | tostop = bitmask(OLDBIT); /* do not sweep old generation */ | 416 | makewhite(g, curr); /* make it white (for next cycle) */ |
728 | } | 417 | p = &curr->gch.next; |
729 | else { /* normal mode */ | 418 | } |
730 | toclear = maskcolors; /* clear all color bits + old bit */ | 419 | else { /* must erase `curr' */ |
731 | toset = luaC_white(g); /* make object white */ | 420 | lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); |
732 | tostop = 0; /* do not stop */ | 421 | *p = curr->gch.next; |
733 | } | 422 | if (curr == g->rootgc) /* is the first element of the list? */ |
734 | while (*p != NULL && count-- > 0) { | 423 | g->rootgc = curr->gch.next; /* adjust first */ |
735 | GCObject *curr = *p; | 424 | freeobj(L, curr); |
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 */ | ||
749 | } | 425 | } |
750 | } | 426 | } |
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; | ||
766 | return p; | 427 | return p; |
767 | } | 428 | } |
768 | 429 | ||
769 | /* }====================================================== */ | ||
770 | |||
771 | |||
772 | /* | ||
773 | ** {====================================================== | ||
774 | ** Finalization | ||
775 | ** ======================================================= | ||
776 | */ | ||
777 | 430 | ||
778 | static void checkSizes (lua_State *L) { | 431 | static void checkSizes (lua_State *L) { |
779 | global_State *g = G(L); | 432 | global_State *g = G(L); |
780 | if (g->gckind != KGC_EMERGENCY) { /* do not change sizes in emergency */ | 433 | /* check size of string hash */ |
781 | int hs = g->strt.size / 2; /* half the size of the string table */ | 434 | if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && |
782 | if (g->strt.nuse < cast(lu_int32, hs)) /* using less than that half? */ | 435 | g->strt.size > MINSTRTABSIZE*2) |
783 | luaS_resize(L, hs); /* halve its size */ | 436 | luaS_resize(L, g->strt.size/2); /* table is too big */ |
784 | luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ | 437 | /* check size of 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); | ||
785 | } | 441 | } |
786 | } | 442 | } |
787 | 443 | ||
788 | 444 | ||
789 | static GCObject *udata2finalize (global_State *g) { | 445 | static void GCTM (lua_State *L) { |
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) { | ||
810 | global_State *g = G(L); | 446 | global_State *g = G(L); |
447 | GCObject *o = g->tmudata->gch.next; /* get first element */ | ||
448 | Udata *udata = rawgco2u(o); | ||
811 | const TValue *tm; | 449 | const TValue *tm; |
812 | TValue v; | 450 | /* remove udata from `tmudata' */ |
813 | setgcovalue(L, &v, udata2finalize(g)); | 451 | if (o == g->tmudata) /* last element? */ |
814 | tm = luaT_gettmbyobj(L, &v, TM_GC); | 452 | g->tmudata = NULL; |
815 | if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ | 453 | else |
816 | int status; | 454 | g->tmudata->gch.next = udata->uv.next; |
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) { | ||
817 | lu_byte oldah = L->allowhook; | 460 | lu_byte oldah = L->allowhook; |
818 | int running = g->gcrunning; | 461 | lu_mem oldt = g->GCthreshold; |
819 | L->allowhook = 0; /* stop debug hooks during GC metamethod */ | 462 | L->allowhook = 0; /* stop debug hooks during GC tag method */ |
820 | g->gcrunning = 0; /* avoid GC steps */ | 463 | g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ |
821 | setobj2s(L, L->top, tm); /* push finalizer... */ | 464 | setobj2s(L, L->top, tm); |
822 | setobj2s(L, L->top + 1, &v); /* ... and its argument */ | 465 | setuvalue(L, L->top+1, udata); |
823 | L->top += 2; /* and (next line) call the finalizer */ | 466 | L->top += 2; |
824 | status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); | 467 | luaD_call(L, L->top - 2, 0); |
825 | L->allowhook = oldah; /* restore hooks */ | 468 | L->allowhook = oldah; /* restore hooks */ |
826 | g->gcrunning = running; /* restore state */ | 469 | g->GCthreshold = oldt; /* restore threshold */ |
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 | } | ||
837 | } | 470 | } |
838 | } | 471 | } |
839 | 472 | ||
840 | 473 | ||
841 | /* | 474 | /* |
842 | ** move all unreachable objects (or 'all' objects) that need | 475 | ** Call all GC tag methods |
843 | ** finalization from list 'finobj' to list 'tobefnz' (to be finalized) | ||
844 | */ | 476 | */ |
845 | static void separatetobefnz (lua_State *L, int all) { | 477 | void luaC_callGCTM (lua_State *L) { |
846 | global_State *g = G(L); | 478 | while (G(L)->tmudata) |
847 | GCObject **p = &g->finobj; | 479 | GCTM(L); |
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 | } | ||
866 | } | 480 | } |
867 | 481 | ||
868 | 482 | ||
869 | /* | 483 | void luaC_freeall (lua_State *L) { |
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) { | ||
874 | global_State *g = G(L); | 484 | global_State *g = G(L); |
875 | if (testbit(gch(o)->marked, SEPARATED) || /* obj. is already separated... */ | 485 | int i; |
876 | isfinalized(o) || /* ... or is finalized... */ | 486 | g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ |
877 | gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ | 487 | sweepwholelist(L, &g->rootgc); |
878 | return; /* nothing to be done */ | 488 | for (i = 0; i < g->strt.size; i++) /* free all string lists */ |
879 | else { /* move 'o' to 'finobj' list */ | 489 | sweepwholelist(L, &g->strt.hash[i]); |
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 | } | ||
897 | } | ||
898 | |||
899 | /* }====================================================== */ | ||
900 | |||
901 | |||
902 | /* | ||
903 | ** {====================================================== | ||
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); | ||
921 | } | 490 | } |
922 | 491 | ||
923 | 492 | ||
924 | #define sweepphases \ | 493 | static void markmt (global_State *g) { |
925 | (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) | 494 | int i; |
926 | 495 | for (i=0; i<NUM_TAGS; i++) | |
927 | 496 | if (g->mt[i]) markobject(g, g->mt[i]); | |
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) { | ||
937 | global_State *g = G(L); | ||
938 | int n = 0; | ||
939 | g->gcstate = GCSsweepstring; | ||
940 | lua_assert(g->sweepgc == NULL && g->sweepfin == NULL); | ||
941 | /* prepare to sweep strings, finalizable objects, and regular objects */ | ||
942 | g->sweepstrgc = 0; | ||
943 | g->sweepfin = sweeptolive(L, &g->finobj, &n); | ||
944 | g->sweepgc = sweeptolive(L, &g->allgc, &n); | ||
945 | return n; | ||
946 | } | 497 | } |
947 | 498 | ||
948 | 499 | ||
949 | /* | 500 | /* mark root set */ |
950 | ** change GC mode | 501 | static void markroot (lua_State *L) { |
951 | */ | ||
952 | void luaC_changemode (lua_State *L, int mode) { | ||
953 | global_State *g = G(L); | 502 | global_State *g = G(L); |
954 | if (mode == g->gckind) return; /* nothing to change */ | 503 | g->gray = NULL; |
955 | if (mode == KGC_GEN) { /* change to generational mode */ | 504 | g->grayagain = NULL; |
956 | /* make sure gray lists are consistent */ | 505 | g->weak = NULL; |
957 | luaC_runtilstate(L, bitmask(GCSpropagate)); | 506 | markobject(g, g->mainthread); |
958 | g->GCestimate = gettotalbytes(g); | 507 | /* make global table be traversed before main stack */ |
959 | g->gckind = KGC_GEN; | 508 | markvalue(g, gt(g->mainthread)); |
960 | } | 509 | markvalue(g, registry(L)); |
961 | else { /* change to incremental mode */ | 510 | markmt(g); |
962 | /* sweep all objects to turn them back to white | 511 | g->gcstate = GCSpropagate; |
963 | (as white has not changed, nothing extra will be collected) */ | ||
964 | g->gckind = KGC_NORMAL; | ||
965 | entersweep(L); | ||
966 | luaC_runtilstate(L, ~sweepphases); | ||
967 | } | ||
968 | } | 512 | } |
969 | 513 | ||
970 | 514 | ||
971 | /* | 515 | static void remarkupvals (global_State *g) { |
972 | ** call all pending finalizers | 516 | UpVal *uv; |
973 | */ | 517 | for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { |
974 | static void callallpendingfinalizers (lua_State *L, int propagateerrors) { | 518 | lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); |
975 | global_State *g = G(L); | 519 | if (isgray(obj2gco(uv))) |
976 | while (g->tobefnz) { | 520 | markvalue(g, uv->v); |
977 | resetoldbit(g->tobefnz); | ||
978 | GCTM(L, propagateerrors); | ||
979 | } | 521 | } |
980 | } | 522 | } |
981 | 523 | ||
982 | 524 | ||
983 | void luaC_freeallobjects (lua_State *L) { | 525 | static void atomic (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); | 526 | global_State *g = G(L); |
1001 | l_mem work = -cast(l_mem, g->GCmemtrav); /* start counting work */ | 527 | size_t udsize; /* total size of userdata to be finalized */ |
1002 | GCObject *origweak, *origall; | ||
1003 | lua_assert(!iswhite(obj2gco(g->mainthread))); | ||
1004 | markobject(g, L); /* mark running thread */ | ||
1005 | /* registry and global metatables may be changed by API */ | ||
1006 | markvalue(g, &g->l_registry); | ||
1007 | markmt(g); /* mark basic metatables */ | ||
1008 | /* remark occasional upvalues of (maybe) dead threads */ | 528 | /* remark occasional upvalues of (maybe) dead threads */ |
1009 | remarkupvals(g); | 529 | remarkupvals(g); |
1010 | propagateall(g); /* propagate changes */ | 530 | /* traverse objects cautch by write barrier and by 'remarkupvals' */ |
1011 | work += g->GCmemtrav; /* stop counting (do not (re)count grays) */ | 531 | propagateall(g); |
1012 | /* traverse objects caught by write barrier and by 'remarkupvals' */ | 532 | /* remark weak tables */ |
1013 | retraversegrays(g); | 533 | g->gray = g->weak; |
1014 | work -= g->GCmemtrav; /* restart counting */ | 534 | g->weak = NULL; |
1015 | convergeephemerons(g); | 535 | lua_assert(!iswhite(obj2gco(g->mainthread))); |
1016 | /* at this point, all strongly accessible objects are marked. */ | 536 | markobject(g, L); /* mark running thread */ |
1017 | /* clear values from weak tables, before checking finalizers */ | 537 | markmt(g); /* mark basic metatables (again) */ |
1018 | clearvalues(g, g->weak, NULL); | 538 | propagateall(g); |
1019 | clearvalues(g, g->allweak, NULL); | 539 | /* remark gray again */ |
1020 | origweak = g->weak; origall = g->allweak; | 540 | g->gray = g->grayagain; |
1021 | work += g->GCmemtrav; /* stop counting (objects being finalized) */ | 541 | g->grayagain = NULL; |
1022 | separatetobefnz(L, 0); /* separate objects to be finalized */ | 542 | propagateall(g); |
1023 | markbeingfnz(g); /* mark objects that will be finalized */ | 543 | udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ |
1024 | propagateall(g); /* remark, to propagate `preserveness' */ | 544 | marktmu(g); /* mark `preserved' userdata */ |
1025 | work -= g->GCmemtrav; /* restart counting */ | 545 | udsize += propagateall(g); /* remark, to propagate `preserveness' */ |
1026 | convergeephemerons(g); | 546 | cleartable(g->weak); /* remove collected objects from weak tables */ |
1027 | /* at this point, all resurrected objects are marked. */ | 547 | /* flip current white */ |
1028 | /* remove dead objects from weak tables */ | 548 | g->currentwhite = cast_byte(otherwhite(g)); |
1029 | clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */ | 549 | g->sweepstrgc = 0; |
1030 | clearkeys(g, g->allweak, NULL); /* clear keys from all allweak tables */ | 550 | g->sweepgc = &g->rootgc; |
1031 | /* clear values from resurrected weak tables */ | 551 | g->gcstate = GCSsweepstring; |
1032 | clearvalues(g, g->weak, origweak); | 552 | g->estimate = g->totalbytes - udsize; /* first estimate */ |
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' */ | ||
1037 | } | 553 | } |
1038 | 554 | ||
1039 | 555 | ||
1040 | static lu_mem singlestep (lua_State *L) { | 556 | static l_mem singlestep (lua_State *L) { |
1041 | global_State *g = G(L); | 557 | global_State *g = G(L); |
558 | /*lua_checkmemory(L);*/ | ||
1042 | switch (g->gcstate) { | 559 | switch (g->gcstate) { |
1043 | case GCSpause: { | 560 | case GCSpause: { |
1044 | /* start to count memory traversed */ | 561 | markroot(L); /* start a new collection */ |
1045 | g->GCmemtrav = g->strt.size * sizeof(GCObject*); | 562 | return 0; |
1046 | lua_assert(!isgenerational(g)); | ||
1047 | restartcollection(g); | ||
1048 | g->gcstate = GCSpropagate; | ||
1049 | return g->GCmemtrav; | ||
1050 | } | 563 | } |
1051 | case GCSpropagate: { | 564 | case GCSpropagate: { |
1052 | if (g->gray) { | 565 | if (g->gray) |
1053 | lu_mem oldtrav = g->GCmemtrav; | 566 | return propagatemark(g); |
1054 | propagatemark(g); | ||
1055 | return g->GCmemtrav - oldtrav; /* memory traversed in this step */ | ||
1056 | } | ||
1057 | else { /* no more `gray' objects */ | 567 | else { /* no more `gray' objects */ |
1058 | lu_mem work; | 568 | atomic(L); /* finish mark phase */ |
1059 | int sw; | 569 | return 0; |
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; | ||
1066 | } | 570 | } |
1067 | } | 571 | } |
1068 | case GCSsweepstring: { | 572 | case GCSsweepstring: { |
1069 | int i; | 573 | lu_mem old = g->totalbytes; |
1070 | for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++) | 574 | sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); |
1071 | sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]); | 575 | if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ |
1072 | g->sweepstrgc += i; | 576 | g->gcstate = GCSsweep; /* end sweep-string phase */ |
1073 | if (g->sweepstrgc >= g->strt.size) /* no more strings to sweep? */ | 577 | lua_assert(old >= g->totalbytes); |
1074 | g->gcstate = GCSsweepudata; | 578 | g->estimate -= old - g->totalbytes; |
1075 | return i * GCSWEEPCOST; | 579 | return GCSWEEPCOST; |
1076 | } | ||
1077 | case GCSsweepudata: { | ||
1078 | if (g->sweepfin) { | ||
1079 | g->sweepfin = sweeplist(L, g->sweepfin, GCSWEEPMAX); | ||
1080 | return GCSWEEPMAX*GCSWEEPCOST; | ||
1081 | } | ||
1082 | else { | ||
1083 | g->gcstate = GCSsweep; | ||
1084 | return 0; | ||
1085 | } | ||
1086 | } | 580 | } |
1087 | case GCSsweep: { | 581 | case GCSsweep: { |
1088 | if (g->sweepgc) { | 582 | lu_mem old = g->totalbytes; |
1089 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); | 583 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); |
1090 | return GCSWEEPMAX*GCSWEEPCOST; | 584 | if (*g->sweepgc == NULL) { /* nothing more to sweep? */ |
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; | ||
1091 | } | 598 | } |
1092 | else { | 599 | else { |
1093 | /* sweep main thread */ | 600 | g->gcstate = GCSpause; /* end collection */ |
1094 | GCObject *mt = obj2gco(g->mainthread); | 601 | g->gcdept = 0; |
1095 | sweeplist(L, &mt, 1); | 602 | return 0; |
1096 | checkSizes(L); | ||
1097 | g->gcstate = GCSpause; /* finish collection */ | ||
1098 | return GCSWEEPCOST; | ||
1099 | } | 603 | } |
1100 | } | 604 | } |
1101 | default: lua_assert(0); return 0; | 605 | default: lua_assert(0); return 0; |
@@ -1103,118 +607,105 @@ static lu_mem singlestep (lua_State *L) { | |||
1103 | } | 607 | } |
1104 | 608 | ||
1105 | 609 | ||
1106 | /* | 610 | void luaC_step (lua_State *L) { |
1107 | ** advances the garbage collector until it reaches a state allowed | ||
1108 | ** by 'statemask' | ||
1109 | */ | ||
1110 | void luaC_runtilstate (lua_State *L, int statesmask) { | ||
1111 | global_State *g = G(L); | 611 | global_State *g = G(L); |
1112 | while (!testbit(statesmask, g->gcstate)) | 612 | l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; |
1113 | singlestep(L); | 613 | if (lim == 0) |
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 | } | ||
1114 | } | 633 | } |
1115 | 634 | ||
1116 | 635 | ||
1117 | static void generationalcollection (lua_State *L) { | 636 | void luaC_fullgc (lua_State *L) { |
1118 | global_State *g = G(L); | 637 | global_State *g = G(L); |
1119 | lua_assert(g->gcstate == GCSpropagate); | 638 | if (g->gcstate <= GCSpropagate) { |
1120 | if (g->GCestimate == 0) { /* signal for another major collection? */ | 639 | /* reset sweep marks to sweep all elements (returning them to white) */ |
1121 | luaC_fullgc(L, 0); /* perform a full regular collection */ | 640 | g->sweepstrgc = 0; |
1122 | g->GCestimate = gettotalbytes(g); /* update control */ | 641 | g->sweepgc = &g->rootgc; |
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); | ||
1123 | } | 653 | } |
1124 | else { | 654 | markroot(L); |
1125 | lu_mem estimate = g->GCestimate; | 655 | while (g->gcstate != GCSpause) { |
1126 | luaC_runtilstate(L, bitmask(GCSpause)); /* run complete (minor) cycle */ | 656 | singlestep(L); |
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 | |||
1133 | } | 657 | } |
1134 | setpause(g, gettotalbytes(g)); | 658 | setthreshold(g); |
1135 | lua_assert(g->gcstate == GCSpropagate); | ||
1136 | } | 659 | } |
1137 | 660 | ||
1138 | 661 | ||
1139 | static void incstep (lua_State *L) { | 662 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { |
1140 | global_State *g = G(L); | 663 | global_State *g = G(L); |
1141 | l_mem debt = g->GCdebt; | 664 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
1142 | int stepmul = g->gcstepmul; | 665 | lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); |
1143 | if (stepmul < 40) stepmul = 40; /* avoid ridiculous low values (and 0) */ | 666 | lua_assert(ttype(&o->gch) != LUA_TTABLE); |
1144 | /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */ | 667 | /* must keep invariant? */ |
1145 | debt = (debt / STEPMULADJ) + 1; | 668 | if (g->gcstate == GCSpropagate) |
1146 | debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; | 669 | reallymarkobject(g, v); /* restore invariant */ |
1147 | do { /* always perform at least one single step */ | 670 | else /* don't mind */ |
1148 | lu_mem work = singlestep(L); /* do some work */ | 671 | makewhite(g, o); /* mark as white just to avoid other barriers */ |
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 | } | ||
1157 | } | 672 | } |
1158 | 673 | ||
1159 | 674 | ||
1160 | /* | 675 | void luaC_barrierback (lua_State *L, Table *t) { |
1161 | ** performs a basic GC step | ||
1162 | */ | ||
1163 | void luaC_forcestep (lua_State *L) { | ||
1164 | global_State *g = G(L); | 676 | global_State *g = G(L); |
1165 | int i; | 677 | GCObject *o = obj2gco(t); |
1166 | if (isgenerational(g)) generationalcollection(L); | 678 | lua_assert(isblack(o) && !isdead(g, o)); |
1167 | else incstep(L); | 679 | lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); |
1168 | /* run a few finalizers (or all of them at the end of a collect cycle) */ | 680 | black2gray(o); /* make table gray (again) */ |
1169 | for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++) | 681 | t->gclist = g->grayagain; |
1170 | GCTM(L, 1); /* call one finalizer */ | 682 | g->grayagain = o; |
1171 | } | 683 | } |
1172 | 684 | ||
1173 | 685 | ||
1174 | /* | 686 | void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { |
1175 | ** performs a basic GC step only if collector is running | ||
1176 | */ | ||
1177 | void luaC_step (lua_State *L) { | ||
1178 | global_State *g = G(L); | 687 | global_State *g = G(L); |
1179 | if (g->gcrunning) luaC_forcestep(L); | 688 | o->gch.next = g->rootgc; |
1180 | else luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ | 689 | g->rootgc = o; |
690 | o->gch.marked = luaC_white(g); | ||
691 | o->gch.tt = tt; | ||
1181 | } | 692 | } |
1182 | 693 | ||
1183 | 694 | ||
1184 | 695 | void luaC_linkupval (lua_State *L, UpVal *uv) { | |
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) { | ||
1190 | global_State *g = G(L); | 696 | global_State *g = G(L); |
1191 | int origkind = g->gckind; | 697 | GCObject *o = obj2gco(uv); |
1192 | lua_assert(origkind != KGC_EMERGENCY); | 698 | o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ |
1193 | if (isemergency) /* do not run finalizers during emergency GC */ | 699 | g->rootgc = o; |
1194 | g->gckind = KGC_EMERGENCY; | 700 | if (isgray(o)) { |
1195 | else { | 701 | if (g->gcstate == GCSpropagate) { |
1196 | g->gckind = KGC_NORMAL; | 702 | gray2black(o); /* closed upvalues need barrier */ |
1197 | callallpendingfinalizers(L, 1); | 703 | luaC_barrier(L, uv, uv->v); |
1198 | } | 704 | } |
1199 | if (keepinvariant(g)) { /* may there be some black objects? */ | 705 | else { /* sweep phase: sweep it (turning it into white) */ |
1200 | /* must sweep all objects to turn them back to white | 706 | makewhite(g, o); |
1201 | (as white has not changed, nothing will be collected) */ | 707 | lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); |
1202 | entersweep(L); | 708 | } |
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)); | ||
1211 | } | 709 | } |
1212 | g->gckind = origkind; | ||
1213 | setpause(g, gettotalbytes(g)); | ||
1214 | if (!isemergency) /* do not run finalizers during emergency GC */ | ||
1215 | callallpendingfinalizers(L, 1); | ||
1216 | } | 710 | } |
1217 | 711 | ||
1218 | /* }====================================================== */ | ||
1219 | |||
1220 | |||
diff --git a/apps/plugins/lua/lgc.h b/apps/plugins/lua/lgc.h index 84bb1cdf99..5123ccb479 100644 --- a/apps/plugins/lua/lgc.h +++ b/apps/plugins/lua/lgc.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -9,107 +9,65 @@ | |||
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 | ||
34 | 12 | ||
35 | 13 | ||
36 | /* | 14 | /* |
37 | ** Possible states of the Garbage Collector | 15 | ** Possible states of the Garbage Collector |
38 | */ | 16 | */ |
39 | #define GCSpropagate 0 | 17 | #define GCSpause 0 |
40 | #define GCSatomic 1 | 18 | #define GCSpropagate 1 |
41 | #define GCSsweepstring 2 | 19 | #define GCSsweepstring 2 |
42 | #define GCSsweepudata 3 | 20 | #define GCSsweep 3 |
43 | #define GCSsweep 4 | 21 | #define GCSfinalize 4 |
44 | #define GCSpause 5 | ||
45 | |||
46 | 22 | ||
47 | #define issweepphase(g) \ | ||
48 | (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) | ||
49 | |||
50 | #define isgenerational(g) ((g)->gckind == KGC_GEN) | ||
51 | 23 | ||
52 | /* | 24 | /* |
53 | ** macros to tell when main invariant (white objects cannot point to black | 25 | ** some userful bit tricks |
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. | ||
59 | */ | 26 | */ |
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))) | ||
60 | 38 | ||
61 | #define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic) | ||
62 | 39 | ||
63 | 40 | ||
64 | /* | 41 | /* |
65 | ** Outside the collector, the state in generational mode is kept in | 42 | ** Layout for bit use in `marked' field: |
66 | ** 'propagate', so 'keepinvariant' is always true. | 43 | ** bit 0 - object is white (type 0) |
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) | ||
67 | */ | 51 | */ |
68 | #define keepinvariantout(g) \ | ||
69 | check_exp(g->gcstate == GCSpropagate || !isgenerational(g), \ | ||
70 | g->gcstate <= GCSatomic) | ||
71 | |||
72 | 52 | ||
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) */ | ||
95 | 53 | ||
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 | ||
96 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) | 62 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) |
97 | 63 | ||
98 | 64 | ||
99 | #define iswhite(x) testbits((x)->gch.marked, WHITEBITS) | 65 | #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) |
100 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) | 66 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) |
101 | #define isgray(x) /* neither white nor black */ \ | 67 | #define isgray(x) (!isblack(x) && !iswhite(x)) |
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) | ||
109 | 68 | ||
110 | #define otherwhite(g) (g->currentwhite ^ WHITEBITS) | 69 | #define otherwhite(g) (g->currentwhite ^ WHITEBITS) |
111 | #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) | 70 | #define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) |
112 | #define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked) | ||
113 | 71 | ||
114 | #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) | 72 | #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) |
115 | #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) | 73 | #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) |
@@ -119,39 +77,34 @@ | |||
119 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) | 77 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) |
120 | 78 | ||
121 | 79 | ||
122 | #define luaC_condGC(L,c) \ | 80 | #define luaC_checkGC(L) { \ |
123 | {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);} | 81 | condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ |
124 | #define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);) | 82 | if (G(L)->totalbytes >= G(L)->GCthreshold) \ |
83 | luaC_step(L); } | ||
125 | 84 | ||
126 | 85 | ||
127 | #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ | 86 | #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ |
128 | luaC_barrier_(L,obj2gco(p),gcvalue(v)); } | 87 | luaC_barrierf(L,obj2gco(p),gcvalue(v)); } |
129 | 88 | ||
130 | #define luaC_barrierback(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ | 89 | #define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ |
131 | luaC_barrierback_(L,p); } | 90 | luaC_barrierback(L,t); } |
132 | 91 | ||
133 | #define luaC_objbarrier(L,p,o) \ | 92 | #define luaC_objbarrier(L,p,o) \ |
134 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ | 93 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ |
135 | luaC_barrier_(L,obj2gco(p),obj2gco(o)); } | 94 | luaC_barrierf(L,obj2gco(p),obj2gco(o)); } |
136 | 95 | ||
137 | #define luaC_objbarrierback(L,p,o) \ | 96 | #define luaC_objbarriert(L,t,o) \ |
138 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) luaC_barrierback_(L,p); } | 97 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } |
139 | 98 | ||
140 | #define luaC_barrierproto(L,p,c) \ | 99 | LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); |
141 | { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); } | 100 | LUAI_FUNC void luaC_callGCTM (lua_State *L); |
142 | 101 | LUAI_FUNC void luaC_freeall (lua_State *L); | |
143 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); | ||
144 | LUAI_FUNC void luaC_step (lua_State *L); | 102 | LUAI_FUNC void luaC_step (lua_State *L); |
145 | LUAI_FUNC void luaC_forcestep (lua_State *L); | 103 | LUAI_FUNC void luaC_fullgc (lua_State *L); |
146 | LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); | 104 | LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); |
147 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); | 105 | LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); |
148 | LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, | 106 | LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); |
149 | GCObject **list, int offset); | 107 | LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); |
150 | LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); | 108 | |
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); | ||
156 | 109 | ||
157 | #endif | 110 | #endif |
diff --git a/apps/plugins/lua/liolib.c b/apps/plugins/lua/liolib.c index a282dd1ac0..7a43915f20 100644 --- a/apps/plugins/lua/liolib.c +++ b/apps/plugins/lua/liolib.c | |||
@@ -1,21 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: liolib.c,v 2.112.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 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> | ||
19 | #include <stdio.h> | 8 | #include <stdio.h> |
20 | #include <stdlib.h> | 9 | #include <stdlib.h> |
21 | #include <string.h> | 10 | #include <string.h> |
@@ -30,111 +19,46 @@ | |||
30 | #include "rocklibc.h" | 19 | #include "rocklibc.h" |
31 | 20 | ||
32 | 21 | ||
33 | #if !defined(lua_checkmode) | ||
34 | |||
35 | /* | ||
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')) | ||
45 | |||
46 | #endif | ||
47 | |||
48 | /* | ||
49 | ** {====================================================== | ||
50 | ** lua_popen spawns a new process connected to the current | ||
51 | ** one through the file streams. | ||
52 | ** ======================================================= | ||
53 | */ | ||
54 | |||
55 | #if !defined(lua_popen) /* { */ | ||
56 | |||
57 | #if defined(LUA_USE_POPEN) /* { */ | ||
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)) | ||
61 | |||
62 | #elif defined(LUA_WIN) /* }{ */ | ||
63 | |||
64 | #define lua_popen(L,c,m) ((void)L, _popen(c,m)) | ||
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 | 22 | ||
106 | #endif /* } */ | 23 | #define IO_INPUT 1 |
107 | 24 | #define IO_OUTPUT 2 | |
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 | 25 | ||
117 | 26 | ||
118 | #define IO_PREFIX "_IO_" | 27 | static const char *const fnames[] = {"input", "output"}; |
119 | #define IO_INPUT (IO_PREFIX "input") | ||
120 | #define IO_OUTPUT (IO_PREFIX "output") | ||
121 | 28 | ||
122 | 29 | ||
123 | typedef luaL_Stream LStream; | 30 | static int pushresult (lua_State *L, int i, const char *filename) { |
124 | 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 | } | ||
125 | 46 | ||
126 | #define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) | ||
127 | 47 | ||
128 | #define isclosed(p) ((p)->closef == NULL) | 48 | static void fileerror (lua_State *L, int arg, const char *filename) { |
49 | lua_pushfstring(L, "%s: %s", filename, strerror(errno)); | ||
50 | luaL_argerror(L, arg, lua_tostring(L, -1)); | ||
51 | } | ||
129 | 52 | ||
130 | 53 | ||
131 | static int io_type (lua_State *L) { | 54 | static int io_type (lua_State *L) { |
132 | LStream *p; | 55 | void *ud; |
133 | luaL_checkany(L, 1); | 56 | luaL_checkany(L, 1); |
134 | p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); | 57 | ud = lua_touserdata(L, 1); |
135 | if (p == NULL) | 58 | lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); |
59 | if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) | ||
136 | lua_pushnil(L); /* not a file */ | 60 | lua_pushnil(L); /* not a file */ |
137 | else if (isclosed(p)) | 61 | else if (*((int *)ud) < 0) |
138 | lua_pushliteral(L, "closed file"); | 62 | lua_pushliteral(L, "closed file"); |
139 | else | 63 | else |
140 | lua_pushliteral(L, "file"); | 64 | lua_pushliteral(L, "file"); |
@@ -142,97 +66,76 @@ static int io_type (lua_State *L) { | |||
142 | } | 66 | } |
143 | 67 | ||
144 | 68 | ||
145 | static int f_tostring (lua_State *L) { | 69 | static int* tofile (lua_State *L) { |
146 | LStream *p = tolstream(L); | 70 | int *f = (int*) luaL_checkudata(L, 1, LUA_FILEHANDLE); |
147 | if (isclosed(p)) | 71 | if (*f < 0) |
148 | lua_pushliteral(L, "file (closed)"); | ||
149 | else | ||
150 | lua_pushfstring(L, "file (%p)", p->f); | ||
151 | return 1; | ||
152 | } | ||
153 | |||
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"); | 72 | luaL_error(L, "attempt to use a closed file"); |
159 | lua_assert(p->f); | 73 | return f; |
160 | return p->f; | ||
161 | } | 74 | } |
162 | 75 | ||
163 | 76 | ||
77 | |||
164 | /* | 78 | /* |
165 | ** When creating file handles, always creates a `closed' file handle | 79 | ** When creating file handles, always creates a `closed' file handle |
166 | ** before opening the actual file; so, if there is a memory error, the | 80 | ** before opening the actual file; so, if there is a memory error, the |
167 | ** file is not left opened. | 81 | ** file is not left opened. |
168 | */ | 82 | */ |
169 | static LStream *newprefile (lua_State *L) { | 83 | static int* newfile (lua_State *L) { |
170 | LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); | 84 | int *pf = (int *)lua_newuserdata(L, sizeof(int)); |
171 | p->closef = NULL; /* mark file handle as 'closed' */ | 85 | *pf = -1; /* file handle is currently `closed' */ |
172 | luaL_setmetatable(L, LUA_FILEHANDLE); | 86 | luaL_getmetatable(L, LUA_FILEHANDLE); |
173 | return p; | 87 | lua_setmetatable(L, -2); |
88 | return pf; | ||
174 | } | 89 | } |
175 | 90 | ||
176 | 91 | ||
177 | static int aux_close (lua_State *L) { | 92 | /* |
178 | LStream *p = tolstream(L); | 93 | ** function to close regular files |
179 | lua_CFunction cf = p->closef; | 94 | */ |
180 | p->closef = NULL; /* mark stream as closed */ | 95 | static int io_fclose (lua_State *L) { |
181 | return (*cf)(L); /* close it */ | 96 | int *p = tofile(L); |
97 | int ok = (rb->close(*p) == 0); | ||
98 | *p = -1; | ||
99 | return pushresult(L, ok, NULL); | ||
182 | } | 100 | } |
183 | 101 | ||
184 | 102 | ||
185 | static int io_close (lua_State *L) { | 103 | static inline int aux_close (lua_State *L) { |
186 | if (lua_isnone(L, 1)) /* no argument? */ | 104 | return io_fclose(L); |
187 | lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ | ||
188 | tofile(L); /* make sure argument is an open stream */ | ||
189 | return aux_close(L); | ||
190 | } | 105 | } |
191 | 106 | ||
192 | 107 | ||
193 | static int f_gc (lua_State *L) { | 108 | static int io_close (lua_State *L) { |
194 | LStream *p = tolstream(L); | 109 | if (lua_isnone(L, 1)) |
195 | if (!isclosed(p) && p->f != NULL) | 110 | lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); |
196 | aux_close(L); /* ignore closed and incompletely open files */ | 111 | tofile(L); /* make sure argument is a file */ |
197 | return 0; | 112 | return aux_close(L); |
198 | } | ||
199 | |||
200 | |||
201 | /* | ||
202 | ** function to close regular files | ||
203 | */ | ||
204 | static int io_fclose (lua_State *L) { | ||
205 | LStream *p = tolstream(L); | ||
206 | int res = rb->close((int)p->f); | ||
207 | return luaL_fileresult(L, (res == 0), NULL); | ||
208 | } | 113 | } |
209 | 114 | ||
210 | 115 | ||
211 | static LStream *newfile (lua_State *L) { | 116 | static int io_gc (lua_State *L) { |
212 | LStream *p = newprefile(L); | 117 | int f = *(int*) luaL_checkudata(L, 1, LUA_FILEHANDLE); |
213 | p->f = NULL; | 118 | /* ignore closed files */ |
214 | p->closef = &io_fclose; | 119 | if (f >= 0) |
215 | return p; | 120 | aux_close(L); |
121 | return 0; | ||
216 | } | 122 | } |
217 | 123 | ||
218 | 124 | ||
219 | static void opencheck (lua_State *L, const char *fname, const char *mode) { | 125 | static int io_tostring (lua_State *L) { |
220 | LStream *p = newfile(L); | 126 | int f = *(int*) luaL_checkudata(L, 1, LUA_FILEHANDLE); |
221 | int flags = O_RDONLY; | 127 | if (f < 0) |
222 | if (strcmp(mode, "w") == 0) | 128 | lua_pushliteral(L, "file (closed)"); |
223 | flags = O_WRONLY; | 129 | else |
224 | p->f = (FILE*)rb->open(fname, flags); | 130 | lua_pushfstring(L, "file (%d)", f); |
225 | if (p->f == NULL) | 131 | return 1; |
226 | luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno)); | ||
227 | } | 132 | } |
228 | 133 | ||
229 | 134 | ||
230 | static int io_open (lua_State *L) { | 135 | static int io_open (lua_State *L) { |
231 | const char *filename = luaL_checkstring(L, 1); | 136 | const char *filename = luaL_checkstring(L, 1); |
232 | const char *mode = luaL_optstring(L, 2, "r"); | 137 | const char *mode = luaL_optstring(L, 2, "r"); |
233 | LStream *p = newfile(L); | 138 | int *pf = newfile(L); |
234 | const char *md = mode; /* to traverse/check mode */ | ||
235 | luaL_argcheck(L, lua_checkmode(md), 2, "invalid mode"); | ||
236 | int flags = 0; | 139 | int flags = 0; |
237 | if(*(mode+1) == '+') { | 140 | if(*(mode+1) == '+') { |
238 | flags = O_RDWR; | 141 | flags = O_RDWR; |
@@ -255,117 +158,84 @@ static int io_open (lua_State *L) { | |||
255 | } | 158 | } |
256 | if((*mode == 'w' || *mode == 'a') && !rb->file_exists(filename)) | 159 | if((*mode == 'w' || *mode == 'a') && !rb->file_exists(filename)) |
257 | flags |= O_CREAT; | 160 | flags |= O_CREAT; |
258 | int pf = rb->open(filename, flags, 0666); | 161 | *pf = rb->open(filename, flags, 0666); |
259 | p->f = (FILE*)pf; | 162 | return (*pf < 0) ? pushresult(L, 0, filename) : 1; |
260 | return (pf < 0) ? luaL_fileresult(L, 0, filename) : 1; | ||
261 | } | 163 | } |
262 | 164 | ||
263 | 165 | ||
264 | #if 0 | 166 | static int* getiofile (lua_State *L, int findex) { |
265 | /* | 167 | int *f; |
266 | ** function to close 'popen' files | 168 | lua_rawgeti(L, LUA_ENVIRONINDEX, findex); |
267 | */ | 169 | f = (int *)lua_touserdata(L, -1); |
268 | static int io_pclose (lua_State *L) { | 170 | if (f == NULL || *f < 0) |
269 | LStream *p = tolstream(L); | 171 | luaL_error(L, "standard %s file is closed", fnames[findex - 1]); |
270 | return luaL_execresult(L, lua_pclose(L, p->f)); | 172 | return f; |
271 | } | 173 | } |
272 | 174 | ||
273 | 175 | ||
274 | static int io_popen (lua_State *L) { | 176 | static int g_iofile (lua_State *L, int f, int flags) { |
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) { | ||
303 | if (!lua_isnoneornil(L, 1)) { | 177 | if (!lua_isnoneornil(L, 1)) { |
304 | const char *filename = lua_tostring(L, 1); | 178 | const char *filename = lua_tostring(L, 1); |
305 | if (filename) | 179 | if (filename) { |
306 | opencheck(L, filename, mode); | 180 | int *pf = newfile(L); |
181 | *pf = rb->open(filename, flags); | ||
182 | if (*pf < 0) | ||
183 | fileerror(L, 1, filename); | ||
184 | } | ||
307 | else { | 185 | else { |
308 | tofile(L); /* check that it's a valid file handle */ | 186 | tofile(L); /* check that it's a valid file handle */ |
309 | lua_pushvalue(L, 1); | 187 | lua_pushvalue(L, 1); |
310 | } | 188 | } |
311 | lua_setfield(L, LUA_REGISTRYINDEX, f); | 189 | lua_rawseti(L, LUA_ENVIRONINDEX, f); |
312 | } | 190 | } |
313 | /* return current value */ | 191 | /* return current value */ |
314 | lua_getfield(L, LUA_REGISTRYINDEX, f); | 192 | lua_rawgeti(L, LUA_ENVIRONINDEX, f); |
315 | return 1; | 193 | return 1; |
316 | } | 194 | } |
317 | 195 | ||
318 | 196 | ||
319 | static int io_input (lua_State *L) { | 197 | static int io_input (lua_State *L) { |
320 | return g_iofile(L, IO_INPUT, "r"); | 198 | return g_iofile(L, IO_INPUT, O_RDONLY); |
321 | } | 199 | } |
322 | 200 | ||
323 | 201 | ||
324 | static int io_output (lua_State *L) { | 202 | static int io_output (lua_State *L) { |
325 | return g_iofile(L, IO_OUTPUT, "w"); | 203 | return g_iofile(L, IO_OUTPUT, O_WRONLY); |
326 | } | 204 | } |
327 | 205 | ||
328 | 206 | ||
329 | static int io_readline (lua_State *L); | 207 | static int io_readline (lua_State *L); |
330 | 208 | ||
331 | 209 | ||
332 | static void aux_lines (lua_State *L, int toclose) { | 210 | static void aux_lines (lua_State *L, int idx, int toclose) { |
333 | int i; | 211 | lua_pushvalue(L, idx); |
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 */ | ||
339 | lua_pushboolean(L, toclose); /* close/not close file when finished */ | 212 | lua_pushboolean(L, toclose); /* close/not close file when finished */ |
340 | for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1); /* copy arguments */ | 213 | lua_pushcclosure(L, io_readline, 2); |
341 | lua_pushcclosure(L, io_readline, 3 + n); | ||
342 | } | 214 | } |
343 | 215 | ||
344 | 216 | ||
345 | static int f_lines (lua_State *L) { | 217 | static int f_lines (lua_State *L) { |
346 | tofile(L); /* check that it's a valid file handle */ | 218 | tofile(L); /* check that it's a valid file handle */ |
347 | aux_lines(L, 0); | 219 | aux_lines(L, 1, 0); |
348 | return 1; | 220 | return 1; |
349 | } | 221 | } |
350 | 222 | ||
351 | 223 | ||
352 | static int io_lines (lua_State *L) { | 224 | static int io_lines (lua_State *L) { |
353 | int toclose; | 225 | if (lua_isnoneornil(L, 1)) { /* no arguments? */ |
354 | if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ | 226 | /* will iterate over default input */ |
355 | if (lua_isnil(L, 1)) { /* no file name? */ | 227 | lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); |
356 | lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ | 228 | return f_lines(L); |
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 */ | ||
360 | } | 229 | } |
361 | else { /* open a new file */ | 230 | else { |
362 | const char *filename = luaL_checkstring(L, 1); | 231 | const char *filename = luaL_checkstring(L, 1); |
363 | opencheck(L, filename, "r"); | 232 | int *pf = newfile(L); |
364 | lua_replace(L, 1); /* put file at index 1 */ | 233 | *pf = rb->open(filename, O_RDONLY); |
365 | toclose = 1; /* close it after iteration */ | 234 | if (*pf < 0) |
235 | fileerror(L, 1, filename); | ||
236 | aux_lines(L, lua_gettop(L), 1); | ||
237 | return 1; | ||
366 | } | 238 | } |
367 | aux_lines(L, toclose); | ||
368 | return 1; | ||
369 | } | 239 | } |
370 | 240 | ||
371 | 241 | ||
@@ -375,89 +245,72 @@ static int io_lines (lua_State *L) { | |||
375 | ** ======================================================= | 245 | ** ======================================================= |
376 | */ | 246 | */ |
377 | 247 | ||
378 | 248 | static int read_number (lua_State *L, int *f) { | |
379 | static int read_number (lua_State *L, FILE *f) { | ||
380 | lua_Number d; | 249 | lua_Number d; |
381 | if (PREFIX(fscanf)(f, LUA_NUMBER_SCAN, &d) == 1) { | 250 | if (PREFIX(fscanf)(*f, LUA_NUMBER_SCAN, &d) == 1) { |
382 | lua_pushnumber(L, d); | 251 | lua_pushnumber(L, d); |
383 | return 1; | 252 | return 1; |
384 | } | 253 | } |
385 | else { | 254 | else return 0; /* read fails */ |
386 | lua_pushnil(L); /* "result" to be removed */ | ||
387 | return 0; /* read fails */ | ||
388 | } | ||
389 | } | 255 | } |
390 | 256 | ||
391 | 257 | ||
392 | static int test_eof (lua_State *L, FILE *f) { | 258 | static int test_eof (lua_State *L, int *f) { |
393 | ssize_t s = rb->lseek((int)f, 0, SEEK_CUR); | 259 | ssize_t s = rb->lseek(*f, 0, SEEK_CUR); |
394 | lua_pushlstring(L, NULL, 0); | 260 | lua_pushlstring(L, NULL, 0); |
395 | return s != rb->filesize((int)f); | 261 | return s != rb->filesize(*f); |
396 | } | 262 | } |
397 | 263 | ||
398 | 264 | ||
399 | /* Rockbox already defines read_line() */ | 265 | /* Rockbox already defines read_line() */ |
400 | static int _read_line (lua_State *L, FILE *f, int chop) { | 266 | static int _read_line (lua_State *L, int *f) { |
401 | luaL_Buffer b; | 267 | luaL_Buffer b; |
402 | luaL_buffinit(L, &b); | 268 | luaL_buffinit(L, &b); |
403 | for (;;) { | 269 | for (;;) { |
404 | size_t l; | 270 | size_t l; |
405 | size_t r; | 271 | size_t r; |
406 | char *p = luaL_prepbuffer(&b); | 272 | char *p = luaL_prepbuffer(&b); |
407 | r = rb->read_line((int)f, p, LUAL_BUFFERSIZE); | 273 | r = rb->read_line(*f, p, LUAL_BUFFERSIZE); |
408 | l = strlen(p); | 274 | l = strlen(p); |
409 | if (l == 0 || p[l-1] != '\n') | 275 | if (l == 0 || p[l-1] != '\n') |
410 | luaL_addsize(&b, l); | 276 | luaL_addsize(&b, l); |
411 | else { | 277 | else { |
412 | luaL_addsize(&b, l - chop); /* chop 'eol' if needed */ | 278 | luaL_addsize(&b, l - 1); /* do not include `eol' */ |
413 | luaL_pushresult(&b); /* close buffer */ | 279 | luaL_pushresult(&b); /* close buffer */ |
414 | return 1; /* read at least an `eol' */ | 280 | return 1; /* read at least an `eol' */ |
415 | } | 281 | } |
416 | if (r < LUAL_BUFFERSIZE) { /* eof? */ | 282 | if (r < LUAL_BUFFERSIZE) { /* eof? */ |
417 | luaL_pushresult(&b); /* close buffer */ | 283 | luaL_pushresult(&b); /* close buffer */ |
418 | return (lua_rawlen(L, -1) > 0); /* check whether read something */ | 284 | return (lua_objlen(L, -1) > 0); /* check whether read something */ |
419 | } | 285 | } |
420 | } | 286 | } |
421 | } | 287 | } |
422 | 288 | ||
423 | 289 | ||
424 | #define MAX_SIZE_T (~(size_t)0) | 290 | static int read_chars (lua_State *L, int *f, size_t n) { |
425 | 291 | size_t rlen; /* how much to read */ | |
426 | static void read_all (lua_State *L, FILE *f) { | ||
427 | size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ | ||
428 | luaL_Buffer b; | ||
429 | luaL_buffinit(L, &b); | ||
430 | for (;;) { | ||
431 | char *p = luaL_prepbuffsize(&b, rlen); | ||
432 | size_t nr = rb->read((int)f, p, rlen); | ||
433 | luaL_addsize(&b, nr); | ||
434 | if (nr < rlen) break; /* 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 */ | 292 | size_t nr; /* number of chars actually read */ |
444 | char *p; | ||
445 | luaL_Buffer b; | 293 | luaL_Buffer b; |
446 | luaL_buffinit(L, &b); | 294 | luaL_buffinit(L, &b); |
447 | p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ | 295 | rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ |
448 | nr = rb->read((int)f, p, n); /* try to read 'n' chars */ | 296 | do { |
449 | luaL_addsize(&b, nr); | 297 | char *p = luaL_prepbuffer(&b); |
298 | if (rlen > n) rlen = n; /* cannot read more than asked */ | ||
299 | nr = rb->read(*f, p, rlen); | ||
300 | luaL_addsize(&b, nr); | ||
301 | n -= nr; /* still have to read `n' chars */ | ||
302 | } while (n > 0 && nr == rlen); /* until end of count or eof */ | ||
450 | luaL_pushresult(&b); /* close buffer */ | 303 | luaL_pushresult(&b); /* close buffer */ |
451 | return (nr > 0); /* true iff read something */ | 304 | return (n == 0 || lua_objlen(L, -1) > 0); |
452 | } | 305 | } |
453 | 306 | ||
454 | 307 | ||
455 | static int g_read (lua_State *L, FILE *f, int first) { | 308 | static int g_read (lua_State *L, int *f, int first) { |
456 | int nargs = lua_gettop(L) - 1; | 309 | int nargs = lua_gettop(L) - 1; |
457 | int success; | 310 | int success; |
458 | int n; | 311 | int n; |
459 | if (nargs == 0) { /* no arguments? */ | 312 | if (nargs == 0) { /* no arguments? */ |
460 | success = _read_line(L, f, 1); | 313 | success = _read_line(L, f); |
461 | n = first+1; /* to return 1 result */ | 314 | n = first+1; /* to return 1 result */ |
462 | } | 315 | } |
463 | else { /* ensure stack space for all results and for auxlib's buffer */ | 316 | else { /* ensure stack space for all results and for auxlib's buffer */ |
@@ -476,13 +329,10 @@ static int g_read (lua_State *L, FILE *f, int first) { | |||
476 | success = read_number(L, f); | 329 | success = read_number(L, f); |
477 | break; | 330 | break; |
478 | case 'l': /* line */ | 331 | case 'l': /* line */ |
479 | success = _read_line(L, f, 1); | 332 | success = _read_line(L, f); |
480 | break; | ||
481 | case 'L': /* line with end-of-line */ | ||
482 | success = _read_line(L, f, 0); | ||
483 | break; | 333 | break; |
484 | case 'a': /* file */ | 334 | case 'a': /* file */ |
485 | read_all(L, f); /* read entire file */ | 335 | read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ |
486 | success = 1; /* always success */ | 336 | success = 1; /* always success */ |
487 | break; | 337 | break; |
488 | default: | 338 | default: |
@@ -510,24 +360,14 @@ static int f_read (lua_State *L) { | |||
510 | 360 | ||
511 | 361 | ||
512 | static int io_readline (lua_State *L) { | 362 | static int io_readline (lua_State *L) { |
513 | LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); | 363 | int *f = (int *) lua_touserdata(L, lua_upvalueindex(1)); |
514 | int i; | 364 | int sucess; |
515 | int n = (int)lua_tointeger(L, lua_upvalueindex(2)); | 365 | if (*f < 0) /* file is already closed? */ |
516 | if (isclosed(p)) /* file is already closed? */ | 366 | luaL_error(L, "file is already closed"); |
517 | return luaL_error(L, "file is already closed"); | 367 | sucess = _read_line(L, f); |
518 | lua_settop(L , 1); | 368 | if (sucess) return 1; |
519 | for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ | 369 | else { /* EOF */ |
520 | lua_pushvalue(L, lua_upvalueindex(3 + i)); | 370 | if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ |
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? */ | ||
531 | lua_settop(L, 0); | 371 | lua_settop(L, 0); |
532 | lua_pushvalue(L, lua_upvalueindex(1)); | 372 | lua_pushvalue(L, lua_upvalueindex(1)); |
533 | aux_close(L); /* close it */ | 373 | aux_close(L); /* close it */ |
@@ -539,23 +379,22 @@ static int io_readline (lua_State *L) { | |||
539 | /* }====================================================== */ | 379 | /* }====================================================== */ |
540 | 380 | ||
541 | 381 | ||
542 | static int g_write (lua_State *L, FILE *f, int arg) { | 382 | static int g_write (lua_State *L, int *f, int arg) { |
543 | int nargs = lua_gettop(L) - arg; | 383 | int nargs = lua_gettop(L) - 1; |
544 | int status = 1; | 384 | int status = 1; |
545 | for (; nargs--; arg++) { | 385 | for (; nargs--; arg++) { |
546 | if (lua_type(L, arg) == LUA_TNUMBER) { | 386 | if (lua_type(L, arg) == LUA_TNUMBER) { |
547 | /* optimization: could be done exactly as for strings */ | 387 | /* optimization: could be done exactly as for strings */ |
548 | status = status && | 388 | status = status && |
549 | rb->fdprintf((int)f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; | 389 | rb->fdprintf(*f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; |
550 | } | 390 | } |
551 | else { | 391 | else { |
552 | size_t l; | 392 | size_t l; |
553 | const char *s = luaL_checklstring(L, arg, &l); | 393 | const char *s = luaL_checklstring(L, arg, &l); |
554 | status = status && (rb->write((int)f, s, l) == (ssize_t)l); | 394 | status = status && (rb->write(*f, s, l) == (ssize_t)l); |
555 | } | 395 | } |
556 | } | 396 | } |
557 | if (status) return 1; /* file handle already on stack top */ | 397 | return pushresult(L, status, NULL); |
558 | else return luaL_fileresult(L, status, NULL); | ||
559 | } | 398 | } |
560 | 399 | ||
561 | 400 | ||
@@ -565,86 +404,47 @@ static int io_write (lua_State *L) { | |||
565 | 404 | ||
566 | 405 | ||
567 | static int f_write (lua_State *L) { | 406 | static int f_write (lua_State *L) { |
568 | FILE *f = tofile(L); | 407 | return g_write(L, tofile(L), 2); |
569 | lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ | ||
570 | return g_write(L, f, 2); | ||
571 | } | 408 | } |
572 | 409 | ||
573 | 410 | ||
574 | static int f_seek (lua_State *L) { | 411 | static int f_seek (lua_State *L) { |
575 | static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; | 412 | static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; |
576 | static const char *const modenames[] = {"set", "cur", "end", NULL}; | 413 | static const char *const modenames[] = {"set", "cur", "end", NULL}; |
577 | FILE *f = tofile(L); | 414 | int f = *tofile(L); |
578 | int op = luaL_checkoption(L, 2, "cur", modenames); | 415 | int op = luaL_checkoption(L, 2, "cur", modenames); |
579 | lua_Number p3 = luaL_optnumber(L, 3, 0); | 416 | long offset = luaL_optlong(L, 3, 0); |
580 | l_seeknum offset = (l_seeknum)p3; | 417 | op = rb->lseek(f, offset, mode[op]); |
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]); | ||
584 | if (op) | 418 | if (op) |
585 | return luaL_fileresult(L, 0, NULL); /* error */ | 419 | return pushresult(L, 0, NULL); /* error */ |
586 | else { | 420 | else { |
587 | lua_pushnumber(L, (lua_Number)rb->lseek((int)f, 0, SEEK_CUR)); | 421 | lua_pushinteger(L, rb->lseek(f, 0, SEEK_CUR)); |
588 | return 1; | 422 | return 1; |
589 | } | 423 | } |
590 | } | 424 | } |
591 | 425 | ||
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 | |||
603 | 426 | ||
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 | */ | ||
619 | static const luaL_Reg iolib[] = { | 427 | static const luaL_Reg iolib[] = { |
620 | {"close", io_close}, | 428 | {"close", io_close}, |
621 | /*{"flush", io_flush},*/ | ||
622 | {"input", io_input}, | 429 | {"input", io_input}, |
623 | {"lines", io_lines}, | 430 | {"lines", io_lines}, |
624 | {"open", io_open}, | 431 | {"open", io_open}, |
625 | {"output", io_output}, | 432 | {"output", io_output}, |
626 | /*{"popen", io_popen},*/ | ||
627 | {"read", io_read}, | 433 | {"read", io_read}, |
628 | /*{"tmpfile", io_tmpfile},*/ | ||
629 | {"type", io_type}, | 434 | {"type", io_type}, |
630 | {"write", io_write}, | 435 | {"write", io_write}, |
631 | {NULL, NULL} | 436 | {NULL, NULL} |
632 | }; | 437 | }; |
633 | 438 | ||
634 | 439 | ||
635 | /* | ||
636 | ** methods for file handles | ||
637 | */ | ||
638 | static const luaL_Reg flib[] = { | 440 | static const luaL_Reg flib[] = { |
639 | {"close", io_close}, | 441 | {"close", io_close}, |
640 | /*{"flush", f_flush},*/ | ||
641 | {"lines", f_lines}, | 442 | {"lines", f_lines}, |
642 | {"read", f_read}, | 443 | {"read", f_read}, |
643 | {"seek", f_seek}, | 444 | {"seek", f_seek}, |
644 | /*{"setvbuf", f_setvbuf},*/ | ||
645 | {"write", f_write}, | 445 | {"write", f_write}, |
646 | {"__gc", f_gc}, | 446 | {"__gc", io_gc}, |
647 | {"__tostring", f_tostring}, | 447 | {"__tostring", io_tostring}, |
648 | {NULL, NULL} | 448 | {NULL, NULL} |
649 | }; | 449 | }; |
650 | 450 | ||
@@ -653,40 +453,16 @@ static void createmeta (lua_State *L) { | |||
653 | luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ | 453 | luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ |
654 | lua_pushvalue(L, -1); /* push metatable */ | 454 | lua_pushvalue(L, -1); /* push metatable */ |
655 | lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ | 455 | lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ |
656 | luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ | 456 | luaL_register(L, NULL, flib); /* file methods */ |
657 | lua_pop(L, 1); /* pop new metatable */ | ||
658 | } | 457 | } |
659 | 458 | ||
660 | 459 | ||
661 | /* | 460 | LUALIB_API int luaopen_io (lua_State *L) { |
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 */ | ||
689 | createmeta(L); | 461 | createmeta(L); |
462 | lua_replace(L, LUA_ENVIRONINDEX); | ||
463 | /* open library */ | ||
464 | luaL_register(L, LUA_IOLIBNAME, iolib); | ||
690 | /* create (and set) default files */ | 465 | /* create (and set) default files */ |
466 | lua_pop(L, 1); /* pop environment for default files */ | ||
691 | return 1; | 467 | return 1; |
692 | } | 468 | } |
diff --git a/apps/plugins/lua/llex.c b/apps/plugins/lua/llex.c index 8d410f620d..85ac516be3 100644 --- a/apps/plugins/lua/llex.c +++ b/apps/plugins/lua/llex.c | |||
@@ -1,10 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llex.c,v 2.63.1.2 2013/08/30 15:49:41 roberto Exp $ | 2 | ** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 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> */ | ||
8 | #include <string.h> | 10 | #include <string.h> |
9 | 11 | ||
10 | #define llex_c | 12 | #define llex_c |
@@ -12,7 +14,6 @@ | |||
12 | 14 | ||
13 | #include "lua.h" | 15 | #include "lua.h" |
14 | 16 | ||
15 | #include "lctype.h" | ||
16 | #include "ldo.h" | 17 | #include "ldo.h" |
17 | #include "llex.h" | 18 | #include "llex.h" |
18 | #include "lobject.h" | 19 | #include "lobject.h" |
@@ -28,36 +29,35 @@ | |||
28 | 29 | ||
29 | 30 | ||
30 | 31 | ||
32 | |||
31 | #define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') | 33 | #define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') |
32 | 34 | ||
33 | 35 | ||
34 | /* ORDER RESERVED */ | 36 | /* ORDER RESERVED */ |
35 | static const char *const luaX_tokens [] = { | 37 | const char *const luaX_tokens [] = { |
36 | "and", "break", "do", "else", "elseif", | 38 | "and", "break", "do", "else", "elseif", |
37 | "end", "false", "for", "function", "goto", "if", | 39 | "end", "false", "for", "function", "if", |
38 | "in", "local", "nil", "not", "or", "repeat", | 40 | "in", "local", "nil", "not", "or", "repeat", |
39 | "return", "then", "true", "until", "while", | 41 | "return", "then", "true", "until", "while", |
40 | "..", "...", "==", ">=", "<=", "~=", "::", "<eof>", | 42 | "..", "...", "==", ">=", "<=", "~=", |
41 | "<number>", "<name>", "<string>" | 43 | "<number>", "<name>", "<string>", "<eof>", |
44 | NULL | ||
42 | }; | 45 | }; |
43 | 46 | ||
44 | 47 | ||
45 | #define save_and_next(ls) (save(ls, ls->current), next(ls)) | 48 | #define save_and_next(ls) (save(ls, ls->current), next(ls)) |
46 | 49 | ||
47 | 50 | ||
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 (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { | 53 | if (b->n + 1 > b->buffsize) { |
54 | size_t newsize; | 54 | size_t newsize; |
55 | if (luaZ_sizebuffer(b) >= MAX_SIZET/2) | 55 | if (b->buffsize >= MAX_SIZET/2) |
56 | lexerror(ls, "lexical element too long", 0); | 56 | luaX_lexerror(ls, "lexical element too long", 0); |
57 | newsize = luaZ_sizebuffer(b) * 2; | 57 | newsize = b->buffsize * 2; |
58 | luaZ_resizebuffer(ls->L, b, newsize); | 58 | luaZ_resizebuffer(ls->L, b, newsize); |
59 | } | 59 | } |
60 | b->buffer[luaZ_bufflen(b)++] = cast(char, c); | 60 | b->buffer[b->n++] = cast(char, c); |
61 | } | 61 | } |
62 | 62 | ||
63 | 63 | ||
@@ -66,24 +66,23 @@ 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 | ts->tsv.extra = cast_byte(i+1); /* reserved word */ | 69 | lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN); |
70 | ts->tsv.reserved = cast_byte(i+1); /* reserved word */ | ||
70 | } | 71 | } |
71 | } | 72 | } |
72 | 73 | ||
73 | 74 | ||
75 | #define MAXSRC 80 | ||
76 | |||
77 | |||
74 | const char *luaX_token2str (LexState *ls, int token) { | 78 | const char *luaX_token2str (LexState *ls, int token) { |
75 | if (token < FIRST_RESERVED) { /* single-byte symbols? */ | 79 | if (token < FIRST_RESERVED) { |
76 | lua_assert(token == cast(unsigned char, token)); | 80 | lua_assert(token == cast(unsigned char, token)); |
77 | return (lisprint(token)) ? luaO_pushfstring(ls->L, LUA_QL("%c"), token) : | 81 | return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : |
78 | luaO_pushfstring(ls->L, "char(%d)", token); | 82 | luaO_pushfstring(ls->L, "%c", 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; | ||
86 | } | 83 | } |
84 | else | ||
85 | return luaX_tokens[token-FIRST_RESERVED]; | ||
87 | } | 86 | } |
88 | 87 | ||
89 | 88 | ||
@@ -93,57 +92,38 @@ static const char *txtToken (LexState *ls, int token) { | |||
93 | case TK_STRING: | 92 | case TK_STRING: |
94 | case TK_NUMBER: | 93 | case TK_NUMBER: |
95 | save(ls, '\0'); | 94 | save(ls, '\0'); |
96 | return luaO_pushfstring(ls->L, LUA_QS, luaZ_buffer(ls->buff)); | 95 | return luaZ_buffer(ls->buff); |
97 | default: | 96 | default: |
98 | return luaX_token2str(ls, token); | 97 | return luaX_token2str(ls, token); |
99 | } | 98 | } |
100 | } | 99 | } |
101 | 100 | ||
102 | 101 | ||
103 | static l_noret lexerror (LexState *ls, const char *msg, int token) { | 102 | void luaX_lexerror (LexState *ls, const char *msg, int token) { |
104 | char buff[LUA_IDSIZE]; | 103 | char buff[MAXSRC]; |
105 | luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE); | 104 | luaO_chunkid(buff, getstr(ls->source), MAXSRC); |
106 | msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); | 105 | msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); |
107 | if (token) | 106 | if (token) |
108 | luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); | 107 | luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); |
109 | luaD_throw(ls->L, LUA_ERRSYNTAX); | 108 | luaD_throw(ls->L, LUA_ERRSYNTAX); |
110 | } | 109 | } |
111 | 110 | ||
112 | 111 | ||
113 | l_noret luaX_syntaxerror (LexState *ls, const char *msg) { | 112 | void luaX_syntaxerror (LexState *ls, const char *msg) { |
114 | lexerror(ls, msg, ls->t.token); | 113 | luaX_lexerror(ls, msg, ls->t.token); |
115 | } | 114 | } |
116 | 115 | ||
117 | 116 | ||
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 | */ | ||
123 | TString *luaX_newstring (LexState *ls, const char *str, size_t l) { | 117 | TString *luaX_newstring (LexState *ls, const char *str, size_t l) { |
124 | lua_State *L = ls->L; | 118 | lua_State *L = ls->L; |
125 | TValue *o; /* entry for `str' */ | 119 | TString *ts = luaS_newlstr(L, str, l); |
126 | TString *ts = luaS_newlstr(L, str, l); /* create new string */ | 120 | TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ |
127 | setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ | 121 | if (ttisnil(o)) |
128 | o = luaH_set(L, ls->fs->h, L->top - 1); | 122 | setbvalue(o, 1); /* make sure `str' will not be collected */ |
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 */ | ||
139 | return ts; | 123 | return ts; |
140 | } | 124 | } |
141 | 125 | ||
142 | 126 | ||
143 | /* | ||
144 | ** increment line number and skips newline sequence (any of | ||
145 | ** \n, \r, \n\r, or \r\n) | ||
146 | */ | ||
147 | static void inclinenumber (LexState *ls) { | 127 | static void inclinenumber (LexState *ls) { |
148 | int old = ls->current; | 128 | int old = ls->current; |
149 | lua_assert(currIsNewline(ls)); | 129 | lua_assert(currIsNewline(ls)); |
@@ -155,20 +135,17 @@ static void inclinenumber (LexState *ls) { | |||
155 | } | 135 | } |
156 | 136 | ||
157 | 137 | ||
158 | void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, | 138 | void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { |
159 | int firstchar) { | ||
160 | ls->decpoint = '.'; | 139 | ls->decpoint = '.'; |
161 | ls->L = L; | 140 | ls->L = L; |
162 | ls->current = firstchar; | ||
163 | ls->lookahead.token = TK_EOS; /* no look-ahead token */ | 141 | ls->lookahead.token = TK_EOS; /* no look-ahead token */ |
164 | ls->z = z; | 142 | ls->z = z; |
165 | ls->fs = NULL; | 143 | ls->fs = NULL; |
166 | ls->linenumber = 1; | 144 | ls->linenumber = 1; |
167 | ls->lastline = 1; | 145 | ls->lastline = 1; |
168 | ls->source = source; | 146 | ls->source = source; |
169 | ls->envn = luaS_new(L, LUA_ENV); /* create env name */ | ||
170 | luaS_fix(ls->envn); /* never collect this name */ | ||
171 | luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ | 147 | luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ |
148 | next(ls); /* read first char */ | ||
172 | } | 149 | } |
173 | 150 | ||
174 | 151 | ||
@@ -182,16 +159,13 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, | |||
182 | 159 | ||
183 | 160 | ||
184 | static int check_next (LexState *ls, const char *set) { | 161 | static int check_next (LexState *ls, const char *set) { |
185 | if (ls->current == '\0' || !strchr(set, ls->current)) | 162 | if (!strchr(set, ls->current)) |
186 | return 0; | 163 | return 0; |
187 | save_and_next(ls); | 164 | save_and_next(ls); |
188 | return 1; | 165 | return 1; |
189 | } | 166 | } |
190 | 167 | ||
191 | 168 | ||
192 | /* | ||
193 | ** change all characters 'from' in buffer to 'to' | ||
194 | */ | ||
195 | static void buffreplace (LexState *ls, char from, char to) { | 169 | static void buffreplace (LexState *ls, char from, char to) { |
196 | size_t n = luaZ_bufflen(ls->buff); | 170 | size_t n = luaZ_bufflen(ls->buff); |
197 | char *p = luaZ_buffer(ls->buff); | 171 | char *p = luaZ_buffer(ls->buff); |
@@ -200,59 +174,37 @@ static void buffreplace (LexState *ls, char from, char to) { | |||
200 | } | 174 | } |
201 | 175 | ||
202 | 176 | ||
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 | */ | ||
214 | static void trydecpoint (LexState *ls, SemInfo *seminfo) { | 177 | static void trydecpoint (LexState *ls, SemInfo *seminfo) { |
178 | /* format error: try to update decimal point separator */ | ||
179 | /* struct lconv *cv = localeconv(); */ | ||
215 | char old = ls->decpoint; | 180 | char old = ls->decpoint; |
216 | ls->decpoint = getlocaledecpoint(); | 181 | ls->decpoint = '.'; /* (cv ? cv->decimal_point[0] : '.'); */ |
217 | buffreplace(ls, old, ls->decpoint); /* try new decimal separator */ | 182 | buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ |
218 | if (!buff2d(ls->buff, &seminfo->r)) { | 183 | if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { |
219 | /* format error with correct decimal point: no more options */ | 184 | /* format error with correct decimal point: no more options */ |
220 | buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ | 185 | buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ |
221 | lexerror(ls, "malformed number", TK_NUMBER); | 186 | luaX_lexerror(ls, "malformed number", TK_NUMBER); |
222 | } | 187 | } |
223 | } | 188 | } |
224 | 189 | ||
225 | 190 | ||
226 | /* LUA_NUMBER */ | 191 | /* LUA_NUMBER */ |
227 | /* | ||
228 | ** this function is quite liberal in what it accepts, as 'luaO_str2d' | ||
229 | ** will reject ill-formed numerals. | ||
230 | */ | ||
231 | static void read_numeral (LexState *ls, SemInfo *seminfo) { | 192 | static void read_numeral (LexState *ls, SemInfo *seminfo) { |
232 | const char *expo = "Ee"; | 193 | lua_assert(isdigit(ls->current)); |
233 | int first = ls->current; | 194 | do { |
234 | lua_assert(lisdigit(ls->current)); | 195 | save_and_next(ls); |
235 | save_and_next(ls); | 196 | } while (isdigit(ls->current) || ls->current == '.'); |
236 | if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */ | 197 | if (check_next(ls, "Ee")) /* `E'? */ |
237 | expo = "Pp"; | 198 | check_next(ls, "+-"); /* optional exponent sign */ |
238 | for (;;) { | 199 | while (isalnum(ls->current) || ls->current == '_') |
239 | if (check_next(ls, expo)) /* exponent part? */ | 200 | save_and_next(ls); |
240 | check_next(ls, "+-"); /* optional exponent sign */ | ||
241 | if (lisxdigit(ls->current) || ls->current == '.') | ||
242 | save_and_next(ls); | ||
243 | else break; | ||
244 | } | ||
245 | save(ls, '\0'); | 201 | save(ls, '\0'); |
246 | buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ | 202 | buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ |
247 | if (!buff2d(ls->buff, &seminfo->r)) /* format error? */ | 203 | if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ |
248 | trydecpoint(ls, seminfo); /* try to update decimal point separator */ | 204 | trydecpoint(ls, seminfo); /* try to update decimal point separator */ |
249 | } | 205 | } |
250 | 206 | ||
251 | 207 | ||
252 | /* | ||
253 | ** skip a sequence '[=*[' or ']=*]' and return its number of '='s or | ||
254 | ** -1 if sequence is malformed | ||
255 | */ | ||
256 | static int skip_sep (LexState *ls) { | 208 | static int skip_sep (LexState *ls) { |
257 | int count = 0; | 209 | int count = 0; |
258 | int s = ls->current; | 210 | int s = ls->current; |
@@ -267,23 +219,43 @@ static int skip_sep (LexState *ls) { | |||
267 | 219 | ||
268 | 220 | ||
269 | static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { | 221 | 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 */ | ||
270 | save_and_next(ls); /* skip 2nd `[' */ | 224 | save_and_next(ls); /* skip 2nd `[' */ |
271 | if (currIsNewline(ls)) /* string starts with a newline? */ | 225 | if (currIsNewline(ls)) /* string starts with a newline? */ |
272 | inclinenumber(ls); /* skip it */ | 226 | inclinenumber(ls); /* skip it */ |
273 | for (;;) { | 227 | for (;;) { |
274 | switch (ls->current) { | 228 | switch (ls->current) { |
275 | case EOZ: | 229 | case EOZ: |
276 | lexerror(ls, (seminfo) ? "unfinished long string" : | 230 | luaX_lexerror(ls, (seminfo) ? "unfinished long string" : |
277 | "unfinished long comment", TK_EOS); | 231 | "unfinished long comment", TK_EOS); |
278 | break; /* to avoid warnings */ | 232 | 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 | ||
279 | case ']': { | 246 | case ']': { |
280 | if (skip_sep(ls) == sep) { | 247 | if (skip_sep(ls) == sep) { |
281 | save_and_next(ls); /* skip 2nd `]' */ | 248 | 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 | ||
282 | goto endloop; | 253 | goto endloop; |
283 | } | 254 | } |
284 | break; | 255 | break; |
285 | } | 256 | } |
286 | case '\n': case '\r': { | 257 | case '\n': |
258 | case '\r': { | ||
287 | save(ls, '\n'); | 259 | save(ls, '\n'); |
288 | inclinenumber(ls); | 260 | inclinenumber(ls); |
289 | if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ | 261 | if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ |
@@ -301,91 +273,51 @@ static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { | |||
301 | } | 273 | } |
302 | 274 | ||
303 | 275 | ||
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 | |||
342 | static void read_string (LexState *ls, int del, SemInfo *seminfo) { | 276 | static void read_string (LexState *ls, int del, SemInfo *seminfo) { |
343 | save_and_next(ls); /* keep delimiter (for error messages) */ | 277 | save_and_next(ls); |
344 | while (ls->current != del) { | 278 | while (ls->current != del) { |
345 | switch (ls->current) { | 279 | switch (ls->current) { |
346 | case EOZ: | 280 | case EOZ: |
347 | lexerror(ls, "unfinished string", TK_EOS); | 281 | luaX_lexerror(ls, "unfinished string", TK_EOS); |
348 | break; /* to avoid warnings */ | 282 | continue; /* to avoid warnings */ |
349 | case '\n': | 283 | case '\n': |
350 | case '\r': | 284 | case '\r': |
351 | lexerror(ls, "unfinished string", TK_STRING); | 285 | luaX_lexerror(ls, "unfinished string", TK_STRING); |
352 | break; /* to avoid warnings */ | 286 | continue; /* to avoid warnings */ |
353 | case '\\': { /* escape sequences */ | 287 | case '\\': { |
354 | int c; /* final character to be saved */ | 288 | int c; |
355 | next(ls); /* do not save the `\' */ | 289 | next(ls); /* do not save the `\' */ |
356 | switch (ls->current) { | 290 | switch (ls->current) { |
357 | case 'a': c = '\a'; goto read_save; | 291 | case 'a': c = '\a'; break; |
358 | case 'b': c = '\b'; goto read_save; | 292 | case 'b': c = '\b'; break; |
359 | case 'f': c = '\f'; goto read_save; | 293 | case 'f': c = '\f'; break; |
360 | case 'n': c = '\n'; goto read_save; | 294 | case 'n': c = '\n'; break; |
361 | case 'r': c = '\r'; goto read_save; | 295 | case 'r': c = '\r'; break; |
362 | case 't': c = '\t'; goto read_save; | 296 | case 't': c = '\t'; break; |
363 | case 'v': c = '\v'; goto read_save; | 297 | case 'v': c = '\v'; break; |
364 | case 'x': c = readhexaesc(ls); goto read_save; | 298 | case '\n': /* go through */ |
365 | case '\n': case '\r': | 299 | case '\r': save(ls, '\n'); inclinenumber(ls); continue; |
366 | inclinenumber(ls); c = '\n'; goto only_save; | 300 | case EOZ: continue; /* will raise an error next loop */ |
367 | case '\\': case '\"': case '\'': | ||
368 | c = ls->current; goto read_save; | ||
369 | case EOZ: goto no_save; /* will raise an error next loop */ | ||
370 | case 'z': { /* zap following span of spaces */ | ||
371 | next(ls); /* skip the 'z' */ | ||
372 | while (lisspace(ls->current)) { | ||
373 | if (currIsNewline(ls)) inclinenumber(ls); | ||
374 | else next(ls); | ||
375 | } | ||
376 | goto no_save; | ||
377 | } | ||
378 | default: { | 301 | default: { |
379 | if (!lisdigit(ls->current)) | 302 | if (!isdigit(ls->current)) |
380 | escerror(ls, &ls->current, 1, "invalid escape sequence"); | 303 | save_and_next(ls); /* handles \\, \", \', and \? */ |
381 | /* digital escape \ddd */ | 304 | else { /* \xxx */ |
382 | c = readdecesc(ls); | 305 | int i = 0; |
383 | goto only_save; | 306 | c = 0; |
307 | do { | ||
308 | c = 10*c + (ls->current-'0'); | ||
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 | } | ||
315 | continue; | ||
384 | } | 316 | } |
385 | } | 317 | } |
386 | read_save: next(ls); /* read next character */ | 318 | save(ls, c); |
387 | only_save: save(ls, c); /* save 'c' */ | 319 | next(ls); |
388 | no_save: break; | 320 | continue; |
389 | } | 321 | } |
390 | default: | 322 | default: |
391 | save_and_next(ls); | 323 | save_and_next(ls); |
@@ -401,41 +333,38 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
401 | luaZ_resetbuffer(ls->buff); | 333 | luaZ_resetbuffer(ls->buff); |
402 | for (;;) { | 334 | for (;;) { |
403 | switch (ls->current) { | 335 | switch (ls->current) { |
404 | case '\n': case '\r': { /* line breaks */ | 336 | case '\n': |
337 | case '\r': { | ||
405 | inclinenumber(ls); | 338 | inclinenumber(ls); |
406 | break; | 339 | continue; |
407 | } | 340 | } |
408 | case ' ': case '\f': case '\t': case '\v': { /* spaces */ | 341 | case '-': { |
409 | next(ls); | ||
410 | break; | ||
411 | } | ||
412 | case '-': { /* '-' or '--' (comment) */ | ||
413 | next(ls); | 342 | next(ls); |
414 | if (ls->current != '-') return '-'; | 343 | if (ls->current != '-') return '-'; |
415 | /* else is a comment */ | 344 | /* else is a comment */ |
416 | next(ls); | 345 | next(ls); |
417 | if (ls->current == '[') { /* long comment? */ | 346 | if (ls->current == '[') { |
418 | int sep = skip_sep(ls); | 347 | int sep = skip_sep(ls); |
419 | luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ | 348 | luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ |
420 | if (sep >= 0) { | 349 | if (sep >= 0) { |
421 | read_long_string(ls, NULL, sep); /* skip long comment */ | 350 | read_long_string(ls, NULL, sep); /* long comment */ |
422 | luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ | 351 | luaZ_resetbuffer(ls->buff); |
423 | break; | 352 | continue; |
424 | } | 353 | } |
425 | } | 354 | } |
426 | /* else short comment */ | 355 | /* else short comment */ |
427 | while (!currIsNewline(ls) && ls->current != EOZ) | 356 | while (!currIsNewline(ls) && ls->current != EOZ) |
428 | next(ls); /* skip until end of line (or end of file) */ | 357 | next(ls); |
429 | break; | 358 | continue; |
430 | } | 359 | } |
431 | case '[': { /* long string or simply '[' */ | 360 | case '[': { |
432 | int sep = skip_sep(ls); | 361 | int sep = skip_sep(ls); |
433 | if (sep >= 0) { | 362 | if (sep >= 0) { |
434 | read_long_string(ls, seminfo, sep); | 363 | read_long_string(ls, seminfo, sep); |
435 | return TK_STRING; | 364 | return TK_STRING; |
436 | } | 365 | } |
437 | else if (sep == -1) return '['; | 366 | else if (sep == -1) return '['; |
438 | else lexerror(ls, "invalid long string delimiter", TK_STRING); | 367 | else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); |
439 | } | 368 | } |
440 | case '=': { | 369 | case '=': { |
441 | next(ls); | 370 | next(ls); |
@@ -457,52 +386,56 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
457 | if (ls->current != '=') return '~'; | 386 | if (ls->current != '=') return '~'; |
458 | else { next(ls); return TK_NE; } | 387 | else { next(ls); return TK_NE; } |
459 | } | 388 | } |
460 | case ':': { | 389 | case '"': |
461 | next(ls); | 390 | case '\'': { |
462 | if (ls->current != ':') return ':'; | ||
463 | else { next(ls); return TK_DBCOLON; } | ||
464 | } | ||
465 | case '"': case '\'': { /* short literal strings */ | ||
466 | read_string(ls, ls->current, seminfo); | 391 | read_string(ls, ls->current, seminfo); |
467 | return TK_STRING; | 392 | return TK_STRING; |
468 | } | 393 | } |
469 | case '.': { /* '.', '..', '...', or number */ | 394 | case '.': { |
470 | save_and_next(ls); | 395 | save_and_next(ls); |
471 | if (check_next(ls, ".")) { | 396 | if (check_next(ls, ".")) { |
472 | if (check_next(ls, ".")) | 397 | if (check_next(ls, ".")) |
473 | return TK_DOTS; /* '...' */ | 398 | return TK_DOTS; /* ... */ |
474 | else return TK_CONCAT; /* '..' */ | 399 | else return TK_CONCAT; /* .. */ |
400 | } | ||
401 | else if (!isdigit(ls->current)) return '.'; | ||
402 | else { | ||
403 | read_numeral(ls, seminfo); | ||
404 | return TK_NUMBER; | ||
475 | } | 405 | } |
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; | ||
483 | } | 406 | } |
484 | case EOZ: { | 407 | case EOZ: { |
485 | return TK_EOS; | 408 | return TK_EOS; |
486 | } | 409 | } |
487 | default: { | 410 | default: { |
488 | if (lislalpha(ls->current)) { /* identifier or reserved word? */ | 411 | if (isspace(ls->current)) { |
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 */ | ||
489 | TString *ts; | 422 | TString *ts; |
490 | do { | 423 | do { |
491 | save_and_next(ls); | 424 | save_and_next(ls); |
492 | } while (lislalnum(ls->current)); | 425 | } while (isalnum(ls->current) || ls->current == '_'); |
493 | ts = luaX_newstring(ls, luaZ_buffer(ls->buff), | 426 | ts = luaX_newstring(ls, luaZ_buffer(ls->buff), |
494 | luaZ_bufflen(ls->buff)); | 427 | luaZ_bufflen(ls->buff)); |
495 | seminfo->ts = ts; | 428 | if (ts->tsv.reserved > 0) /* reserved word? */ |
496 | if (isreserved(ts)) /* reserved word? */ | 429 | return ts->tsv.reserved - 1 + FIRST_RESERVED; |
497 | return ts->tsv.extra - 1 + FIRST_RESERVED; | ||
498 | else { | 430 | else { |
431 | seminfo->ts = ts; | ||
499 | return TK_NAME; | 432 | return TK_NAME; |
500 | } | 433 | } |
501 | } | 434 | } |
502 | else { /* single-char tokens (+ - / ...) */ | 435 | else { |
503 | int c = ls->current; | 436 | int c = ls->current; |
504 | next(ls); | 437 | next(ls); |
505 | return c; | 438 | return c; /* single-char tokens (+ - / ...) */ |
506 | } | 439 | } |
507 | } | 440 | } |
508 | } | 441 | } |
@@ -521,9 +454,8 @@ void luaX_next (LexState *ls) { | |||
521 | } | 454 | } |
522 | 455 | ||
523 | 456 | ||
524 | int luaX_lookahead (LexState *ls) { | 457 | void luaX_lookahead (LexState *ls) { |
525 | lua_assert(ls->lookahead.token == TK_EOS); | 458 | lua_assert(ls->lookahead.token == TK_EOS); |
526 | ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); | 459 | ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); |
527 | return ls->lookahead.token; | ||
528 | } | 460 | } |
529 | 461 | ||
diff --git a/apps/plugins/lua/llex.h b/apps/plugins/lua/llex.h index a4acdd3021..fa8b7a2a28 100644 --- a/apps/plugins/lua/llex.h +++ b/apps/plugins/lua/llex.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llex.h,v 1.72.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
3 | ** Lexical Analyzer | 3 | ** Lexical Analyzer |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -13,6 +13,8 @@ | |||
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)) | ||
16 | 18 | ||
17 | 19 | ||
18 | /* | 20 | /* |
@@ -23,17 +25,21 @@ enum RESERVED { | |||
23 | /* terminal symbols denoted by reserved words */ | 25 | /* terminal symbols denoted by reserved words */ |
24 | TK_AND = FIRST_RESERVED, TK_BREAK, | 26 | TK_AND = FIRST_RESERVED, TK_BREAK, |
25 | TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, | 27 | TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, |
26 | TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, | 28 | TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, |
27 | TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, | 29 | TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, |
28 | /* other terminal symbols */ | 30 | /* other terminal symbols */ |
29 | TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_DBCOLON, TK_EOS, | 31 | TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, |
30 | TK_NUMBER, TK_NAME, TK_STRING | 32 | TK_NAME, TK_STRING, TK_EOS |
31 | }; | 33 | }; |
32 | 34 | ||
33 | /* number of reserved words */ | 35 | /* number of reserved words */ |
34 | #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) | 36 | #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) |
35 | 37 | ||
36 | 38 | ||
39 | /* array with token `names' */ | ||
40 | LUAI_DATA const char *const luaX_tokens []; | ||
41 | |||
42 | |||
37 | typedef union { | 43 | typedef union { |
38 | lua_Number r; | 44 | lua_Number r; |
39 | TString *ts; | 45 | TString *ts; |
@@ -46,32 +52,29 @@ typedef struct Token { | |||
46 | } Token; | 52 | } Token; |
47 | 53 | ||
48 | 54 | ||
49 | /* state of the lexer plus state of the parser when shared by all | ||
50 | functions */ | ||
51 | typedef struct LexState { | 55 | typedef struct LexState { |
52 | int current; /* current character (charint) */ | 56 | int current; /* current character (charint) */ |
53 | int linenumber; /* input line counter */ | 57 | int linenumber; /* input line counter */ |
54 | int lastline; /* line of last token `consumed' */ | 58 | int lastline; /* line of last token `consumed' */ |
55 | Token t; /* current token */ | 59 | Token t; /* current token */ |
56 | Token lookahead; /* look ahead token */ | 60 | Token lookahead; /* look ahead token */ |
57 | struct FuncState *fs; /* current function (parser) */ | 61 | struct FuncState *fs; /* `FuncState' is private to the parser */ |
58 | struct lua_State *L; | 62 | struct lua_State *L; |
59 | ZIO *z; /* input stream */ | 63 | ZIO *z; /* input stream */ |
60 | Mbuffer *buff; /* buffer for tokens */ | 64 | Mbuffer *buff; /* buffer for tokens */ |
61 | struct Dyndata *dyd; /* dynamic structures used by the parser */ | ||
62 | TString *source; /* current source name */ | 65 | TString *source; /* current source name */ |
63 | TString *envn; /* environment variable name */ | ||
64 | char decpoint; /* locale decimal point */ | 66 | char decpoint; /* locale decimal point */ |
65 | } LexState; | 67 | } LexState; |
66 | 68 | ||
67 | 69 | ||
68 | LUAI_FUNC void luaX_init (lua_State *L); | 70 | LUAI_FUNC void luaX_init (lua_State *L); |
69 | LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, | 71 | LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, |
70 | TString *source, int firstchar); | 72 | TString *source); |
71 | LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); | 73 | LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); |
72 | LUAI_FUNC void luaX_next (LexState *ls); | 74 | LUAI_FUNC void luaX_next (LexState *ls); |
73 | LUAI_FUNC int luaX_lookahead (LexState *ls); | 75 | LUAI_FUNC void luaX_lookahead (LexState *ls); |
74 | LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); | 76 | LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); |
77 | LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); | ||
75 | LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); | 78 | LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); |
76 | 79 | ||
77 | 80 | ||
diff --git a/apps/plugins/lua/llimits.h b/apps/plugins/lua/llimits.h index 152dd05515..a31ad160ad 100644 --- a/apps/plugins/lua/llimits.h +++ b/apps/plugins/lua/llimits.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llimits.h,v 1.103.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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 unsigned LUA_INT32 lu_int32; | 18 | typedef LUAI_UINT32 lu_int32; |
19 | 19 | ||
20 | typedef LUAI_UMEM lu_mem; | 20 | typedef LUAI_UMEM lu_mem; |
21 | 21 | ||
@@ -31,8 +31,6 @@ 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 | |||
36 | 34 | ||
37 | #define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ | 35 | #define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ |
38 | 36 | ||
@@ -46,10 +44,6 @@ typedef unsigned char lu_byte; | |||
46 | 44 | ||
47 | 45 | ||
48 | /* type to ensure maximum alignment */ | 46 | /* 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 | |||
53 | typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; | 47 | typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; |
54 | 48 | ||
55 | 49 | ||
@@ -58,75 +52,36 @@ typedef LUAI_UACNUMBER l_uacNumber; | |||
58 | 52 | ||
59 | 53 | ||
60 | /* internal assertions for in-house debugging */ | 54 | /* internal assertions for in-house debugging */ |
61 | #if defined(lua_assert) | 55 | #ifdef lua_assert |
56 | |||
62 | #define check_exp(c,e) (lua_assert(c), (e)) | 57 | #define check_exp(c,e) (lua_assert(c), (e)) |
63 | /* to avoid problems with conditions too long */ | 58 | #define api_check(l,e) lua_assert(e) |
64 | #define lua_longassert(c) { if (!(c)) lua_assert(0); } | 59 | |
65 | #else | 60 | #else |
61 | |||
66 | #define lua_assert(c) ((void)0) | 62 | #define lua_assert(c) ((void)0) |
67 | #define check_exp(c,e) (e) | 63 | #define check_exp(c,e) (e) |
68 | #define lua_longassert(c) ((void)0) | 64 | #define api_check luai_apicheck |
69 | #endif | ||
70 | 65 | ||
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) | ||
81 | #endif | 66 | #endif |
82 | 67 | ||
83 | #endif | ||
84 | |||
85 | #define api_check(l,e,msg) luai_apicheck(l,(e) && msg) | ||
86 | |||
87 | 68 | ||
88 | #if !defined(UNUSED) | 69 | #ifndef UNUSED |
89 | #define UNUSED(x) ((void)(x)) /* to avoid warnings */ | 70 | #define UNUSED(x) ((void)(x)) /* to avoid warnings */ |
90 | #endif | 71 | #endif |
91 | 72 | ||
92 | 73 | ||
74 | #ifndef cast | ||
93 | #define cast(t, exp) ((t)(exp)) | 75 | #define cast(t, exp) ((t)(exp)) |
76 | #endif | ||
94 | 77 | ||
95 | #define cast_byte(i) cast(lu_byte, (i)) | 78 | #define cast_byte(i) cast(lu_byte, (i)) |
96 | #define cast_num(i) cast(lua_Number, (i)) | 79 | #define cast_num(i) cast(lua_Number, (i)) |
97 | #define cast_int(i) cast(int, (i)) | 80 | #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 | ||
111 | 81 | ||
112 | 82 | ||
113 | 83 | ||
114 | /* | 84 | /* |
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 | /* | ||
130 | ** type for virtual-machine instructions | 85 | ** type for virtual-machine instructions |
131 | ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) | 86 | ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) |
132 | */ | 87 | */ |
@@ -140,170 +95,34 @@ typedef lu_int32 Instruction; | |||
140 | 95 | ||
141 | 96 | ||
142 | /* minimum size for the string table (must be power of 2) */ | 97 | /* minimum size for the string table (must be power of 2) */ |
143 | #if !defined(MINSTRTABSIZE) | 98 | #ifndef MINSTRTABSIZE |
144 | #define MINSTRTABSIZE 32 | 99 | #define MINSTRTABSIZE 32 |
145 | #endif | 100 | #endif |
146 | 101 | ||
147 | 102 | ||
148 | /* minimum size for string buffer */ | 103 | /* minimum size for string buffer */ |
149 | #if !defined(LUA_MINBUFFER) | 104 | #ifndef LUA_MINBUFFER |
150 | #define LUA_MINBUFFER 32 | 105 | #define LUA_MINBUFFER 32 |
151 | #endif | 106 | #endif |
152 | 107 | ||
153 | 108 | ||
154 | #if !defined(lua_lock) | 109 | #ifndef lua_lock |
155 | #define lua_lock(L) ((void) 0) | 110 | #define lua_lock(L) ((void) 0) |
156 | #define lua_unlock(L) ((void) 0) | 111 | #define lua_unlock(L) ((void) 0) |
157 | #endif | 112 | #endif |
158 | 113 | ||
159 | #if !defined(luai_threadyield) | 114 | #ifndef luai_threadyield |
160 | #define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} | 115 | #define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} |
161 | #endif | 116 | #endif |
162 | 117 | ||
163 | 118 | ||
164 | /* | 119 | /* |
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 | /* | ||
293 | ** macro to control inclusion of some hard tests on stack reallocation | 120 | ** macro to control inclusion of some hard tests on stack reallocation |
294 | */ | 121 | */ |
295 | #if !defined(HARDSTACKTESTS) | 122 | #ifndef HARDSTACKTESTS |
296 | #define condmovestack(L) ((void)0) | 123 | #define condhardstacktests(x) ((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) | ||
304 | #else | 124 | #else |
305 | #define condchangemem(L) \ | 125 | #define condhardstacktests(x) x |
306 | ((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1))) | ||
307 | #endif | 126 | #endif |
308 | 127 | ||
309 | #endif | 128 | #endif |
diff --git a/apps/plugins/lua/lmathlib.c b/apps/plugins/lua/lmathlib.c index 0b288e6a12..99a104050c 100644 --- a/apps/plugins/lua/lmathlib.c +++ b/apps/plugins/lua/lmathlib.c | |||
@@ -1,12 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lmathlib.c,v 1.83.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 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 | ||
8 | #include <stdlib.h> | 9 | #include <stdlib.h> |
9 | #include <math.h> | 10 | #include <math.h> |
11 | #endif | ||
10 | 12 | ||
11 | #define lmathlib_c | 13 | #define lmathlib_c |
12 | #define LUA_LIB | 14 | #define LUA_LIB |
@@ -18,9 +20,9 @@ | |||
18 | 20 | ||
19 | 21 | ||
20 | #undef PI | 22 | #undef PI |
21 | #define PI ((lua_Number)(3.1415926535897932384626433832795)) | 23 | #define PI (3.14159265358979323846) |
22 | #define RADIANS_PER_DEGREE ((lua_Number)(PI/180.0)) | 24 | #define RADIANS_PER_DEGREE (PI/180.0) |
23 | #define DEGREES_PER_RADIAN ((lua_Number)180.0/PI) | 25 | #define DEGREES_PER_RADIAN (180.0/PI) |
24 | 26 | ||
25 | 27 | ||
26 | static int math_abs (lua_State *L) { | 28 | static int math_abs (lua_State *L) { |
@@ -32,53 +34,52 @@ static int math_abs (lua_State *L) { | |||
32 | 34 | ||
33 | #if 0 | 35 | #if 0 |
34 | static int math_sin (lua_State *L) { | 36 | static int math_sin (lua_State *L) { |
35 | lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); | 37 | lua_pushnumber(L, sin(luaL_checknumber(L, 1))); |
36 | return 1; | 38 | return 1; |
37 | } | 39 | } |
38 | 40 | ||
39 | static int math_sinh (lua_State *L) { | 41 | static int math_sinh (lua_State *L) { |
40 | lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); | 42 | lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); |
41 | return 1; | 43 | return 1; |
42 | } | 44 | } |
43 | 45 | ||
44 | static int math_cos (lua_State *L) { | 46 | static int math_cos (lua_State *L) { |
45 | lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); | 47 | lua_pushnumber(L, cos(luaL_checknumber(L, 1))); |
46 | return 1; | 48 | return 1; |
47 | } | 49 | } |
48 | 50 | ||
49 | static int math_cosh (lua_State *L) { | 51 | static int math_cosh (lua_State *L) { |
50 | lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); | 52 | lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); |
51 | return 1; | 53 | return 1; |
52 | } | 54 | } |
53 | 55 | ||
54 | static int math_tan (lua_State *L) { | 56 | static int math_tan (lua_State *L) { |
55 | lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); | 57 | lua_pushnumber(L, tan(luaL_checknumber(L, 1))); |
56 | return 1; | 58 | return 1; |
57 | } | 59 | } |
58 | 60 | ||
59 | static int math_tanh (lua_State *L) { | 61 | static int math_tanh (lua_State *L) { |
60 | lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); | 62 | lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); |
61 | return 1; | 63 | return 1; |
62 | } | 64 | } |
63 | 65 | ||
64 | static int math_asin (lua_State *L) { | 66 | static int math_asin (lua_State *L) { |
65 | lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); | 67 | lua_pushnumber(L, asin(luaL_checknumber(L, 1))); |
66 | return 1; | 68 | return 1; |
67 | } | 69 | } |
68 | 70 | ||
69 | static int math_acos (lua_State *L) { | 71 | static int math_acos (lua_State *L) { |
70 | lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); | 72 | lua_pushnumber(L, acos(luaL_checknumber(L, 1))); |
71 | return 1; | 73 | return 1; |
72 | } | 74 | } |
73 | 75 | ||
74 | static int math_atan (lua_State *L) { | 76 | static int math_atan (lua_State *L) { |
75 | lua_pushnumber(L, l_mathop(atan)(luaL_checknumber(L, 1))); | 77 | lua_pushnumber(L, atan(luaL_checknumber(L, 1))); |
76 | return 1; | 78 | return 1; |
77 | } | 79 | } |
78 | 80 | ||
79 | static int math_atan2 (lua_State *L) { | 81 | static int math_atan2 (lua_State *L) { |
80 | lua_pushnumber(L, l_mathop(atan2)(luaL_checknumber(L, 1), | 82 | lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); |
81 | luaL_checknumber(L, 2))); | ||
82 | return 1; | 83 | return 1; |
83 | } | 84 | } |
84 | #endif | 85 | #endif |
@@ -103,48 +104,35 @@ static int math_fmod (lua_State *L) { | |||
103 | 104 | ||
104 | #if 0 | 105 | #if 0 |
105 | static int math_modf (lua_State *L) { | 106 | static int math_modf (lua_State *L) { |
106 | lua_Number ip; | 107 | double ip; |
107 | lua_Number fp = l_mathop(modf)(luaL_checknumber(L, 1), &ip); | 108 | double fp = modf(luaL_checknumber(L, 1), &ip); |
108 | lua_pushnumber(L, ip); | 109 | lua_pushnumber(L, ip); |
109 | lua_pushnumber(L, fp); | 110 | lua_pushnumber(L, fp); |
110 | return 2; | 111 | return 2; |
111 | } | 112 | } |
112 | 113 | ||
113 | static int math_sqrt (lua_State *L) { | 114 | static int math_sqrt (lua_State *L) { |
114 | lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); | 115 | lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); |
115 | return 1; | 116 | return 1; |
116 | } | 117 | } |
117 | 118 | ||
118 | static int math_pow (lua_State *L) { | 119 | static int math_pow (lua_State *L) { |
119 | lua_Number x = luaL_checknumber(L, 1); | 120 | lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); |
120 | lua_Number y = luaL_checknumber(L, 2); | ||
121 | lua_pushnumber(L, l_mathop(pow)(x, y)); | ||
122 | return 1; | 121 | return 1; |
123 | } | 122 | } |
124 | 123 | ||
125 | static int math_log (lua_State *L) { | 124 | static int math_log (lua_State *L) { |
126 | lua_Number x = luaL_checknumber(L, 1); | 125 | lua_pushnumber(L, log(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); | ||
136 | return 1; | 126 | return 1; |
137 | } | 127 | } |
138 | 128 | ||
139 | #if defined(LUA_COMPAT_LOG10) | ||
140 | static int math_log10 (lua_State *L) { | 129 | static int math_log10 (lua_State *L) { |
141 | lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); | 130 | lua_pushnumber(L, log10(luaL_checknumber(L, 1))); |
142 | return 1; | 131 | return 1; |
143 | } | 132 | } |
144 | #endif | ||
145 | 133 | ||
146 | static int math_exp (lua_State *L) { | 134 | static int math_exp (lua_State *L) { |
147 | lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); | 135 | lua_pushnumber(L, exp(luaL_checknumber(L, 1))); |
148 | return 1; | 136 | return 1; |
149 | } | 137 | } |
150 | #endif | 138 | #endif |
@@ -152,7 +140,6 @@ static int math_deg (lua_State *L) { | |||
152 | lua_pushnumber(L, luaL_checknumber(L, 1)*DEGREES_PER_RADIAN); | 140 | lua_pushnumber(L, luaL_checknumber(L, 1)*DEGREES_PER_RADIAN); |
153 | return 1; | 141 | return 1; |
154 | } | 142 | } |
155 | |||
156 | static int math_rad (lua_State *L) { | 143 | static int math_rad (lua_State *L) { |
157 | lua_pushnumber(L, (luaL_checknumber(L, 1)*100)/(DEGREES_PER_RADIAN*100)); | 144 | lua_pushnumber(L, (luaL_checknumber(L, 1)*100)/(DEGREES_PER_RADIAN*100)); |
158 | return 1; | 145 | return 1; |
@@ -161,15 +148,13 @@ static int math_rad (lua_State *L) { | |||
161 | #if 0 | 148 | #if 0 |
162 | static int math_frexp (lua_State *L) { | 149 | static int math_frexp (lua_State *L) { |
163 | int e; | 150 | int e; |
164 | lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); | 151 | lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); |
165 | lua_pushinteger(L, e); | 152 | lua_pushinteger(L, e); |
166 | return 2; | 153 | return 2; |
167 | } | 154 | } |
168 | 155 | ||
169 | static int math_ldexp (lua_State *L) { | 156 | static int math_ldexp (lua_State *L) { |
170 | lua_Number x = luaL_checknumber(L, 1); | 157 | lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); |
171 | int ep = luaL_checkint(L, 2); | ||
172 | lua_pushnumber(L, l_mathop(ldexp)(x, ep)); | ||
173 | return 1; | 158 | return 1; |
174 | } | 159 | } |
175 | #endif | 160 | #endif |
@@ -212,16 +197,16 @@ static int math_random (lua_State *L) { | |||
212 | break; | 197 | break; |
213 | } | 198 | } |
214 | case 1: { /* only upper limit */ | 199 | case 1: { /* only upper limit */ |
215 | lua_Number u = luaL_checknumber(L, 1); | 200 | int u = luaL_checkint(L, 1); |
216 | luaL_argcheck(L, 1 <= u, 1, "interval is empty"); | 201 | luaL_argcheck(L, 1<=u, 1, "interval is empty"); |
217 | lua_pushnumber(L, r%u+1); /* int between 1 and `u' */ | 202 | lua_pushnumber(L, r%u+1); /* int between 1 and `u' */ |
218 | break; | 203 | break; |
219 | } | 204 | } |
220 | case 2: { /* lower and upper limits */ | 205 | case 2: { /* lower and upper limits */ |
221 | lua_Number l = luaL_checknumber(L, 1); | 206 | int l = luaL_checkint(L, 1); |
222 | lua_Number u = luaL_checknumber(L, 2); | 207 | int u = luaL_checkint(L, 2); |
223 | luaL_argcheck(L, l <= u, 2, "interval is empty"); | 208 | luaL_argcheck(L, l<=u, 2, "interval is empty"); |
224 | lua_pushnumber(L, r%(u-l+1)+l); /* [l, u] */ | 209 | lua_pushnumber(L, r%(u-l+1)+l); /* int between `l' and `u' */ |
225 | break; | 210 | break; |
226 | } | 211 | } |
227 | default: return luaL_error(L, "wrong number of arguments"); | 212 | default: return luaL_error(L, "wrong number of arguments"); |
@@ -231,7 +216,7 @@ static int math_random (lua_State *L) { | |||
231 | 216 | ||
232 | 217 | ||
233 | static int math_randomseed (lua_State *L) { | 218 | static int math_randomseed (lua_State *L) { |
234 | rb->srand(luaL_checkunsigned(L, 1)); | 219 | rb->srand(luaL_checkint(L, 1)); |
235 | return 0; | 220 | return 0; |
236 | } | 221 | } |
237 | 222 | ||
@@ -258,9 +243,7 @@ static const luaL_Reg mathlib[] = { | |||
258 | #if 0 | 243 | #if 0 |
259 | {"frexp", math_frexp}, | 244 | {"frexp", math_frexp}, |
260 | {"ldexp", math_ldexp}, | 245 | {"ldexp", math_ldexp}, |
261 | #if defined(LUA_COMPAT_LOG10) | ||
262 | {"log10", math_log10}, | 246 | {"log10", math_log10}, |
263 | #endif | ||
264 | {"log", math_log}, | 247 | {"log", math_log}, |
265 | #endif | 248 | #endif |
266 | {"max", math_max}, | 249 | {"max", math_max}, |
@@ -276,7 +259,7 @@ static const luaL_Reg mathlib[] = { | |||
276 | {"sinh", math_sinh}, | 259 | {"sinh", math_sinh}, |
277 | {"sin", math_sin}, | 260 | {"sin", math_sin}, |
278 | {"sqrt", math_sqrt}, | 261 | {"sqrt", math_sqrt}, |
279 | {"tanh", math_tanh}, | 262 | {"tanh", math_tanh}, |
280 | {"tan", math_tan}, | 263 | {"tan", math_tan}, |
281 | #endif | 264 | #endif |
282 | {NULL, NULL} | 265 | {NULL, NULL} |
@@ -286,14 +269,17 @@ static const luaL_Reg mathlib[] = { | |||
286 | /* | 269 | /* |
287 | ** Open math library | 270 | ** Open math library |
288 | */ | 271 | */ |
289 | LUAMOD_API int luaopen_math (lua_State *L) { | 272 | LUALIB_API int luaopen_math (lua_State *L) { |
290 | luaL_newlib(L, mathlib); | 273 | luaL_register(L, LUA_MATHLIBNAME, mathlib); |
291 | #if 0 /* No use in adding floating point constants when there's no FP */ | 274 | #if 0 /* No use in adding floating point constants when there's no FP */ |
292 | lua_pushnumber(L, PI); | 275 | lua_pushnumber(L, PI); |
293 | lua_setfield(L, -2, "pi"); | 276 | lua_setfield(L, -2, "pi"); |
294 | lua_pushnumber(L, HUGE_VAL); | 277 | lua_pushnumber(L, HUGE_VAL); |
295 | lua_setfield(L, -2, "huge"); | 278 | 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 | ||
296 | #endif | 283 | #endif |
297 | return 1; | 284 | return 1; |
298 | } | 285 | } |
299 | |||
diff --git a/apps/plugins/lua/lmem.c b/apps/plugins/lua/lmem.c index ee343e3e03..ae7d8c965f 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.84.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 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,7 +14,6 @@ | |||
14 | 14 | ||
15 | #include "ldebug.h" | 15 | #include "ldebug.h" |
16 | #include "ldo.h" | 16 | #include "ldo.h" |
17 | #include "lgc.h" | ||
18 | #include "lmem.h" | 17 | #include "lmem.h" |
19 | #include "lobject.h" | 18 | #include "lobject.h" |
20 | #include "lstate.h" | 19 | #include "lstate.h" |
@@ -26,11 +25,12 @@ | |||
26 | ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); | 25 | ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); |
27 | ** (`osize' is the old size, `nsize' is the new size) | 26 | ** (`osize' is the old size, `nsize' is the new size) |
28 | ** | 27 | ** |
29 | ** * frealloc(ud, NULL, x, s) creates a new block of size `s' (no | 28 | ** Lua ensures that (ptr == NULL) iff (osize == 0). |
30 | ** matter 'x'). | 29 | ** |
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 *what) { | 47 | int limit, const char *errormsg) { |
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, "too many %s (limit is %d)", what, limit); | 52 | luaG_runerror(L, errormsg); |
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,8 +63,9 @@ void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, | |||
63 | } | 63 | } |
64 | 64 | ||
65 | 65 | ||
66 | l_noret luaM_toobig (lua_State *L) { | 66 | void *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 */ | ||
68 | } | 69 | } |
69 | 70 | ||
70 | 71 | ||
@@ -73,27 +74,13 @@ l_noret luaM_toobig (lua_State *L) { | |||
73 | ** generic allocation routine. | 74 | ** generic allocation routine. |
74 | */ | 75 | */ |
75 | void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { | 76 | 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 | size_t realosize = (block) ? osize : 0; | 78 | lua_assert((osize == 0) == (block == NULL)); |
79 | lua_assert((realosize == 0) == (block == NULL)); | 79 | block = (*g->frealloc)(g->ud, block, osize, nsize); |
80 | #if defined(HARDMEMTESTS) | 80 | if (block == NULL && nsize > 0) |
81 | if (nsize > realosize && g->gcrunning) | 81 | luaD_throw(L, LUA_ERRMEM); |
82 | luaC_fullgc(L, 1); /* force a GC whenever possible */ | 82 | lua_assert((nsize == 0) == (block == NULL)); |
83 | #endif | 83 | g->totalbytes = (g->totalbytes - osize) + nsize; |
84 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); | 84 | return block; |
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; | ||
98 | } | 85 | } |
99 | 86 | ||
diff --git a/apps/plugins/lua/lmem.h b/apps/plugins/lua/lmem.h index bd4f4e0726..97a888c7f8 100644 --- a/apps/plugins/lua/lmem.h +++ b/apps/plugins/lua/lmem.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lmem.h,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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,30 +13,23 @@ | |||
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 | |||
16 | 18 | ||
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 | */ | ||
24 | #define luaM_reallocv(L,b,on,n,e) \ | 19 | #define luaM_reallocv(L,b,on,n,e) \ |
25 | (cast(void, \ | 20 | ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ |
26 | (cast(size_t, (n)+1) > MAX_SIZET/(e)) ? (luaM_toobig(L), 0) : 0), \ | 21 | luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ |
27 | luaM_realloc_(L, (b), (on)*(e), (n)*(e))) | 22 | luaM_toobig(L)) |
28 | 23 | ||
29 | #define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) | 24 | #define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) |
30 | #define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) | 25 | #define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) |
31 | #define luaM_freearray(L, b, n) luaM_reallocv(L, (b), n, 0, sizeof((b)[0])) | 26 | #define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) |
32 | 27 | ||
33 | #define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) | 28 | #define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) |
34 | #define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) | 29 | #define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) |
35 | #define luaM_newvector(L,n,t) \ | 30 | #define luaM_newvector(L,n,t) \ |
36 | cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) | 31 | cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) |
37 | 32 | ||
38 | #define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) | ||
39 | |||
40 | #define luaM_growvector(L,v,nelems,size,t,limit,e) \ | 33 | #define luaM_growvector(L,v,nelems,size,t,limit,e) \ |
41 | if ((nelems)+1 > (size)) \ | 34 | if ((nelems)+1 > (size)) \ |
42 | ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) | 35 | ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) |
@@ -44,14 +37,13 @@ | |||
44 | #define luaM_reallocvector(L, v,oldn,n,t) \ | 37 | #define luaM_reallocvector(L, v,oldn,n,t) \ |
45 | ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) | 38 | ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) |
46 | 39 | ||
47 | LUAI_FUNC l_noret luaM_toobig (lua_State *L); | ||
48 | 40 | ||
49 | /* not to be called directly */ | ||
50 | LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, | 41 | LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, |
51 | size_t size); | 42 | size_t size); |
43 | LUAI_FUNC void *luaM_toobig (lua_State *L); | ||
52 | LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, | 44 | LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, |
53 | size_t size_elem, int limit, | 45 | size_t size_elem, int limit, |
54 | const char *what); | 46 | const char *errormsg); |
55 | 47 | ||
56 | #endif | 48 | #endif |
57 | 49 | ||
diff --git a/apps/plugins/lua/loadlib.c b/apps/plugins/lua/loadlib.c index f5a63386b5..1cc7ebd7db 100644 --- a/apps/plugins/lua/loadlib.c +++ b/apps/plugins/lua/loadlib.c | |||
@@ -1,22 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: loadlib.c,v 1.111.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: loadlib.c,v 1.52.1.3 2008/08/06 13:29:28 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 Windows, and a stub for other | 7 | ** that have dlfcn, an implementation for Darwin (Mac OS X), an |
8 | ** systems. | 8 | ** implementation for Windows, and a stub for other 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 | |||
20 | #include <stdlib.h> | 12 | #include <stdlib.h> |
21 | #include <string.h> | 13 | #include <string.h> |
22 | 14 | ||
@@ -28,296 +20,10 @@ | |||
28 | 20 | ||
29 | #include "lauxlib.h" | 21 | #include "lauxlib.h" |
30 | #include "lualib.h" | 22 | #include "lualib.h" |
23 | #include "rocklib.h" | ||
31 | 24 | ||
32 | 25 | ||
33 | /* | 26 | #define setprogdir(L) ((void)0) |
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 | |||
321 | 27 | ||
322 | 28 | ||
323 | /* | 29 | /* |
@@ -328,143 +34,70 @@ static int ll_loadlib (lua_State *L) { | |||
328 | 34 | ||
329 | 35 | ||
330 | static int readable (const char *filename) { | 36 | static int readable (const char *filename) { |
331 | return rb->file_exists(filename); | 37 | int f = rb->open(filename, O_RDONLY); /* try to open file */ |
38 | if (f < 0) return 0; /* open failed */ | ||
39 | rb->close(f); | ||
40 | return 1; | ||
332 | } | 41 | } |
333 | 42 | ||
334 | 43 | ||
335 | static const char *pushnexttemplate (lua_State *L, const char *path) { | 44 | static const char *pushnexttemplate (lua_State *L, const char *path) { |
336 | const char *l; | 45 | const char *l; |
337 | while (*path == *LUA_PATH_SEP) path++; /* skip separators */ | 46 | while (*path == *LUA_PATHSEP) path++; /* skip separators */ |
338 | if (*path == '\0') return NULL; /* no more templates */ | 47 | if (*path == '\0') return NULL; /* no more templates */ |
339 | l = strchr(path, *LUA_PATH_SEP); /* find next separator */ | 48 | l = strchr(path, *LUA_PATHSEP); /* find next separator */ |
340 | if (l == NULL) l = path + strlen(path); | 49 | if (l == NULL) l = path + strlen(path); |
341 | lua_pushlstring(L, path, l - path); /* template */ | 50 | lua_pushlstring(L, path, l - path); /* template */ |
342 | return l; | 51 | return l; |
343 | } | 52 | } |
344 | 53 | ||
345 | 54 | ||
346 | static const char *searchpath (lua_State *L, const char *name, | 55 | static const char *findfile (lua_State *L, const char *name, |
347 | const char *path, | 56 | const char *pname) { |
348 | const char *sep, | 57 | const char *path, *current_path = get_current_path(L, 2); |
349 | const char *dirsep) { | 58 | name = luaL_gsub(L, name, ".", LUA_DIRSEP); |
350 | luaL_Buffer msg; /* to build error message */ | 59 | lua_getfield(L, LUA_ENVIRONINDEX, pname); |
351 | luaL_buffinit(L, &msg); | 60 | path = lua_tostring(L, -1); |
352 | if (*sep != '\0') /* non-empty separator? */ | 61 | if (path == NULL) |
353 | name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ | 62 | luaL_error(L, LUA_QL("package.%s") " must be a string", pname); |
63 | lua_pushliteral(L, ""); /* error accumulator */ | ||
354 | while ((path = pushnexttemplate(L, path)) != NULL) { | 64 | while ((path = pushnexttemplate(L, path)) != NULL) { |
355 | const char *filename = luaL_gsub(L, lua_tostring(L, -1), | 65 | const char *filename; |
356 | LUA_PATH_MARK, name); | 66 | filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); |
67 | if(current_path != NULL) filename = luaL_gsub(L, filename, "$", current_path); | ||
357 | lua_remove(L, -2); /* remove path template */ | 68 | lua_remove(L, -2); /* remove path template */ |
358 | if (readable(filename)) /* does file exist and is readable? */ | 69 | if (readable(filename)) /* does file exist and is readable? */ |
359 | return filename; /* return that file name */ | 70 | return filename; /* return that file name */ |
360 | lua_pushfstring(L, "\n\tno file " LUA_QS, filename); | 71 | lua_pushfstring(L, "\n\tno file " LUA_QS, filename); |
361 | lua_remove(L, -2); /* remove file name */ | 72 | lua_remove(L, -2); /* remove file name */ |
362 | luaL_addvalue(&msg); /* concatenate error msg. entry */ | 73 | lua_concat(L, 2); /* add entry to possible error message */ |
363 | } | 74 | } |
364 | luaL_pushresult(&msg); /* create error message */ | ||
365 | return NULL; /* not found */ | 75 | return NULL; /* not found */ |
366 | } | 76 | } |
367 | 77 | ||
368 | 78 | ||
369 | static int ll_searchpath (lua_State *L) { | 79 | static void loaderror (lua_State *L, const char *filename) { |
370 | const char *f = searchpath(L, luaL_checkstring(L, 1), | 80 | luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", |
371 | luaL_checkstring(L, 2), | 81 | lua_tostring(L, 1), filename, lua_tostring(L, -1)); |
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 | } | ||
380 | } | 82 | } |
381 | 83 | ||
382 | 84 | ||
383 | static const char *findfile (lua_State *L, const char *name, | 85 | static int loader_Lua (lua_State *L) { |
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) { | ||
408 | const char *filename; | 86 | const char *filename; |
409 | const char *name = luaL_checkstring(L, 1); | 87 | const char *name = luaL_checkstring(L, 1); |
410 | filename = findfile(L, name, "path", LUA_LSUBSEP); | 88 | filename = findfile(L, name, "path"); |
411 | if (filename == NULL) return 1; /* module not found in this path */ | 89 | if (filename == NULL) return 1; /* library not found in this path */ |
412 | return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); | 90 | if (luaL_loadfile(L, filename) != 0) |
413 | } | 91 | loaderror(L, filename); |
414 | 92 | return 1; /* library loaded successfully */ | |
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); | ||
431 | } | 93 | } |
432 | 94 | ||
433 | 95 | ||
434 | static int searcher_C (lua_State *L) { | 96 | static int loader_preload (lua_State *L) { |
435 | const char *name = luaL_checkstring(L, 1); | 97 | const char *name = luaL_checkstring(L, 1); |
436 | const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); | 98 | lua_getfield(L, LUA_ENVIRONINDEX, "preload"); |
437 | if (filename == NULL) return 1; /* module not found in this path */ | 99 | if (!lua_istable(L, -1)) |
438 | return checkload(L, (loadfunc(L, filename, name) == 0), filename); | 100 | luaL_error(L, LUA_QL("package.preload") " must be a table"); |
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"); | ||
468 | lua_getfield(L, -1, name); | 101 | lua_getfield(L, -1, name); |
469 | if (lua_isnil(L, -1)) /* not found? */ | 102 | if (lua_isnil(L, -1)) /* not found? */ |
470 | lua_pushfstring(L, "\n\tno field package.preload['%s']", name); | 103 | lua_pushfstring(L, "\n\tno field package.preload['%s']", name); |
@@ -472,53 +105,48 @@ static int searcher_preload (lua_State *L) { | |||
472 | } | 105 | } |
473 | 106 | ||
474 | 107 | ||
475 | static void findloader (lua_State *L, const char *name) { | 108 | static const int sentinel_ = 0; |
476 | int i; | 109 | #define sentinel ((void *)&sentinel_) |
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 | } | ||
503 | 110 | ||
504 | 111 | ||
505 | static int ll_require (lua_State *L) { | 112 | static int ll_require (lua_State *L) { |
506 | const char *name = luaL_checkstring(L, 1); | 113 | const char *name = luaL_checkstring(L, 1); |
114 | int i; | ||
507 | lua_settop(L, 1); /* _LOADED table will be at index 2 */ | 115 | lua_settop(L, 1); /* _LOADED table will be at index 2 */ |
508 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); | 116 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); |
509 | lua_getfield(L, 2, name); /* _LOADED[name] */ | 117 | lua_getfield(L, 2, name); |
510 | if (lua_toboolean(L, -1)) /* is it there? */ | 118 | 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); | ||
511 | return 1; /* package is already loaded */ | 121 | return 1; /* package is already loaded */ |
512 | /* else must load package */ | 122 | } |
513 | lua_pop(L, 1); /* remove 'getfield' result */ | 123 | /* else must load it; iterate over available loaders */ |
514 | findloader(L, name); | 124 | lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); |
515 | lua_pushstring(L, name); /* pass name as argument to module loader */ | 125 | if (!lua_istable(L, -1)) |
516 | lua_insert(L, -2); /* name is 1st argument (before search data) */ | 126 | luaL_error(L, LUA_QL("package.loaders") " must be a table"); |
517 | lua_call(L, 2, 1); /* run loader to load module */ | 127 | lua_pushliteral(L, ""); /* error message accumulator */ |
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 */ | ||
518 | if (!lua_isnil(L, -1)) /* non-nil return? */ | 146 | if (!lua_isnil(L, -1)) /* non-nil return? */ |
519 | lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ | 147 | lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ |
520 | lua_getfield(L, 2, name); | 148 | lua_getfield(L, 2, name); |
521 | if (lua_isnil(L, -1)) { /* module did not set a value? */ | 149 | if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ |
522 | lua_pushboolean(L, 1); /* use true as result */ | 150 | lua_pushboolean(L, 1); /* use true as result */ |
523 | lua_pushvalue(L, -1); /* extra copy to be returned */ | 151 | lua_pushvalue(L, -1); /* extra copy to be returned */ |
524 | lua_setfield(L, 2, name); /* _LOADED[name] = true */ | 152 | lua_setfield(L, 2, name); /* _LOADED[name] = true */ |
@@ -535,31 +163,26 @@ static int ll_require (lua_State *L) { | |||
535 | ** 'module' function | 163 | ** 'module' function |
536 | ** ======================================================= | 164 | ** ======================================================= |
537 | */ | 165 | */ |
538 | #if defined(LUA_COMPAT_MODULE) | 166 | |
539 | 167 | ||
540 | /* | 168 | static void setfenv (lua_State *L) { |
541 | ** changes the environment variable of calling function | ||
542 | */ | ||
543 | static void set_env (lua_State *L) { | ||
544 | lua_Debug ar; | 169 | lua_Debug ar; |
545 | if (lua_getstack(L, 1, &ar) == 0 || | 170 | if (lua_getstack(L, 1, &ar) == 0 || |
546 | lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ | 171 | lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ |
547 | lua_iscfunction(L, -1)) | 172 | lua_iscfunction(L, -1)) |
548 | luaL_error(L, LUA_QL("module") " not called from a Lua function"); | 173 | luaL_error(L, LUA_QL("module") " not called from a Lua function"); |
549 | lua_pushvalue(L, -2); /* copy new environment table to top */ | 174 | lua_pushvalue(L, -2); |
550 | lua_setupvalue(L, -2, 1); | 175 | lua_setfenv(L, -2); |
551 | lua_pop(L, 1); /* remove function */ | 176 | lua_pop(L, 1); |
552 | } | 177 | } |
553 | 178 | ||
554 | 179 | ||
555 | static void dooptions (lua_State *L, int n) { | 180 | static void dooptions (lua_State *L, int n) { |
556 | int i; | 181 | int i; |
557 | for (i = 2; i <= n; i++) { | 182 | for (i = 2; i <= n; i++) { |
558 | if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ | 183 | lua_pushvalue(L, i); /* get option (a function) */ |
559 | lua_pushvalue(L, i); /* get option (a function) */ | 184 | lua_pushvalue(L, -2); /* module */ |
560 | lua_pushvalue(L, -2); /* module */ | 185 | lua_call(L, 1, 0); |
561 | lua_call(L, 1, 0); | ||
562 | } | ||
563 | } | 186 | } |
564 | } | 187 | } |
565 | 188 | ||
@@ -581,8 +204,17 @@ static void modinit (lua_State *L, const char *modname) { | |||
581 | 204 | ||
582 | static int ll_module (lua_State *L) { | 205 | static int ll_module (lua_State *L) { |
583 | const char *modname = luaL_checkstring(L, 1); | 206 | const char *modname = luaL_checkstring(L, 1); |
584 | int lastarg = lua_gettop(L); /* last parameter */ | 207 | int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ |
585 | luaL_pushmodule(L, modname, 1); /* get/create module table */ | 208 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); |
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 | } | ||
586 | /* check whether table already has a _NAME field */ | 218 | /* check whether table already has a _NAME field */ |
587 | lua_getfield(L, -1, "_NAME"); | 219 | lua_getfield(L, -1, "_NAME"); |
588 | if (!lua_isnil(L, -1)) /* is table an initialized module? */ | 220 | if (!lua_isnil(L, -1)) /* is table an initialized module? */ |
@@ -592,9 +224,9 @@ static int ll_module (lua_State *L) { | |||
592 | modinit(L, modname); | 224 | modinit(L, modname); |
593 | } | 225 | } |
594 | lua_pushvalue(L, -1); | 226 | lua_pushvalue(L, -1); |
595 | set_env(L); | 227 | setfenv(L); |
596 | dooptions(L, lastarg); | 228 | dooptions(L, loaded - 1); |
597 | return 1; | 229 | return 0; |
598 | } | 230 | } |
599 | 231 | ||
600 | 232 | ||
@@ -605,38 +237,22 @@ static int ll_seeall (lua_State *L) { | |||
605 | lua_pushvalue(L, -1); | 237 | lua_pushvalue(L, -1); |
606 | lua_setmetatable(L, 1); | 238 | lua_setmetatable(L, 1); |
607 | } | 239 | } |
608 | lua_pushglobaltable(L); | 240 | lua_pushvalue(L, LUA_GLOBALSINDEX); |
609 | lua_setfield(L, -2, "__index"); /* mt.__index = _G */ | 241 | lua_setfield(L, -2, "__index"); /* mt.__index = _G */ |
610 | return 0; | 242 | return 0; |
611 | } | 243 | } |
612 | 244 | ||
613 | #endif | 245 | |
614 | /* }====================================================== */ | 246 | /* }====================================================== */ |
615 | 247 | ||
616 | 248 | ||
617 | 249 | ||
618 | /* auxiliary mark (for internal use) */ | 250 | /* auxiliary mark (for internal use) */ |
619 | #define AUXMARK "\1" | 251 | #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 | |||
635 | 252 | ||
636 | static void setpath (lua_State *L, const char *fieldname, const char *envname1, | 253 | static void setpath (lua_State *L, const char *fieldname, const char *envname, |
637 | const char *envname2, const char *def) { | 254 | const char *def) { |
638 | (void)envname1; | 255 | (void)envname; |
639 | (void)envname2; | ||
640 | lua_pushstring(L, def); /* use default */ | 256 | lua_pushstring(L, def); /* use default */ |
641 | setprogdir(L); | 257 | setprogdir(L); |
642 | lua_setfield(L, -2, fieldname); | 258 | lua_setfield(L, -2, fieldname); |
@@ -644,72 +260,56 @@ static void setpath (lua_State *L, const char *fieldname, const char *envname1, | |||
644 | 260 | ||
645 | 261 | ||
646 | static const luaL_Reg pk_funcs[] = { | 262 | static const luaL_Reg pk_funcs[] = { |
647 | {"loadlib", ll_loadlib}, | ||
648 | {"searchpath", ll_searchpath}, | ||
649 | #if defined(LUA_COMPAT_MODULE) | ||
650 | {"seeall", ll_seeall}, | 263 | {"seeall", ll_seeall}, |
651 | #endif | ||
652 | {NULL, NULL} | 264 | {NULL, NULL} |
653 | }; | 265 | }; |
654 | 266 | ||
655 | 267 | ||
656 | static const luaL_Reg ll_funcs[] = { | 268 | static const luaL_Reg ll_funcs[] = { |
657 | #if defined(LUA_COMPAT_MODULE) | ||
658 | {"module", ll_module}, | 269 | {"module", ll_module}, |
659 | #endif | ||
660 | {"require", ll_require}, | 270 | {"require", ll_require}, |
661 | {NULL, NULL} | 271 | {NULL, NULL} |
662 | }; | 272 | }; |
663 | 273 | ||
664 | 274 | ||
665 | static void createsearcherstable (lua_State *L) { | 275 | static const lua_CFunction loaders[] = |
666 | static const lua_CFunction searchers[] = | 276 | {loader_preload, loader_Lua, NULL}; |
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 | } | ||
678 | 277 | ||
679 | 278 | ||
680 | LUAMOD_API int luaopen_package (lua_State *L) { | 279 | LUALIB_API int luaopen_package (lua_State *L) { |
681 | /* create table CLIBS to keep track of loaded C libraries */ | 280 | int i; |
682 | luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); | 281 | /* create new type _LOADLIB */ |
683 | lua_createtable(L, 0, 1); /* metatable for CLIBS */ | 282 | luaL_newmetatable(L, "_LOADLIB"); |
684 | lua_pushcfunction(L, gctm); | ||
685 | lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ | ||
686 | lua_setmetatable(L, -2); | ||
687 | /* create `package' table */ | 283 | /* create `package' table */ |
688 | luaL_newlib(L, pk_funcs); | 284 | luaL_register(L, LUA_LOADLIBNAME, pk_funcs); |
689 | createsearcherstable(L); | 285 | #if defined(LUA_COMPAT_LOADLIB) |
690 | #if defined(LUA_COMPAT_LOADERS) | 286 | lua_getfield(L, -1, "loadlib"); |
691 | lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ | 287 | lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); |
692 | lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */ | ||
693 | #endif | 288 | #endif |
694 | lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ | 289 | lua_pushvalue(L, -1); |
695 | /* set field 'path' */ | 290 | lua_replace(L, LUA_ENVIRONINDEX); |
696 | setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT); | 291 | /* create `loaders' table */ |
697 | /* set field 'cpath' */ | 292 | lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1); |
698 | setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT); | 293 | /* fill it with pre-defined loaders */ |
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' */ | ||
699 | /* store config information */ | 300 | /* store config information */ |
700 | lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" | 301 | lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" |
701 | LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); | 302 | LUA_EXECDIR "\n" LUA_IGMARK); |
702 | lua_setfield(L, -2, "config"); | 303 | lua_setfield(L, -2, "config"); |
703 | /* set field `loaded' */ | 304 | /* set field `loaded' */ |
704 | luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); | 305 | luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); |
705 | lua_setfield(L, -2, "loaded"); | 306 | lua_setfield(L, -2, "loaded"); |
706 | /* set field `preload' */ | 307 | /* set field `preload' */ |
707 | luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); | 308 | lua_newtable(L); |
708 | lua_setfield(L, -2, "preload"); | 309 | lua_setfield(L, -2, "preload"); |
709 | lua_pushglobaltable(L); | 310 | lua_pushvalue(L, LUA_GLOBALSINDEX); |
710 | lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ | 311 | luaL_register(L, NULL, ll_funcs); /* open lib into global table */ |
711 | luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ | 312 | lua_pop(L, 1); |
712 | lua_pop(L, 1); /* pop global table */ | ||
713 | return 1; /* return 'package' table */ | 313 | return 1; /* return 'package' table */ |
714 | } | 314 | } |
715 | 315 | ||
diff --git a/apps/plugins/lua/lobject.c b/apps/plugins/lua/lobject.c index 34bbb25c9a..62ad8e9359 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.58.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 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,8 +15,6 @@ | |||
15 | 15 | ||
16 | #include "lua.h" | 16 | #include "lua.h" |
17 | 17 | ||
18 | #include "lctype.h" | ||
19 | #include "ldebug.h" | ||
20 | #include "ldo.h" | 18 | #include "ldo.h" |
21 | #include "lmem.h" | 19 | #include "lmem.h" |
22 | #include "lobject.h" | 20 | #include "lobject.h" |
@@ -26,7 +24,7 @@ | |||
26 | 24 | ||
27 | 25 | ||
28 | 26 | ||
29 | LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; | 27 | const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; |
30 | 28 | ||
31 | 29 | ||
32 | /* | 30 | /* |
@@ -35,25 +33,25 @@ LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; | |||
35 | ** eeeee != 0 and (xxx) otherwise. | 33 | ** eeeee != 0 and (xxx) otherwise. |
36 | */ | 34 | */ |
37 | int luaO_int2fb (unsigned int x) { | 35 | int luaO_int2fb (unsigned int x) { |
38 | int e = 0; /* exponent */ | 36 | int e = 0; /* expoent */ |
39 | if (x < 8) return x; | 37 | while (x >= 16) { |
40 | while (x >= 0x10) { | ||
41 | x = (x+1) >> 1; | 38 | x = (x+1) >> 1; |
42 | e++; | 39 | e++; |
43 | } | 40 | } |
44 | return ((e+1) << 3) | (cast_int(x) - 8); | 41 | if (x < 8) return x; |
42 | else return ((e+1) << 3) | (cast_int(x) - 8); | ||
45 | } | 43 | } |
46 | 44 | ||
47 | 45 | ||
48 | /* converts back */ | 46 | /* converts back */ |
49 | int luaO_fb2int (int x) { | 47 | int luaO_fb2int (int x) { |
50 | int e = (x >> 3) & 0x1f; | 48 | int e = (x >> 3) & 31; |
51 | if (e == 0) return x; | 49 | if (e == 0) return x; |
52 | else return ((x & 7) + 8) << (e - 1); | 50 | else return ((x & 7)+8) << (e - 1); |
53 | } | 51 | } |
54 | 52 | ||
55 | 53 | ||
56 | int luaO_ceillog2 (unsigned int x) { | 54 | int luaO_log2 (unsigned int x) { |
57 | static const lu_byte log_2[256] = { | 55 | static const lu_byte log_2[256] = { |
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, | 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, |
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, | 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, |
@@ -64,169 +62,109 @@ int luaO_ceillog2 (unsigned int x) { | |||
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, | 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, |
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 | 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 |
66 | }; | 64 | }; |
67 | int l = 0; | 65 | int l = -1; |
68 | x--; | ||
69 | while (x >= 256) { l += 8; x >>= 8; } | 66 | while (x >= 256) { l += 8; x >>= 8; } |
70 | return l + log_2[x]; | 67 | 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 | } | ||
104 | 68 | ||
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; | ||
112 | } | 69 | } |
113 | 70 | ||
114 | 71 | ||
115 | /* | 72 | int luaO_rawequalObj (const TValue *t1, const TValue *t2) { |
116 | ** convert an hexadecimal numeric string to a number, following | 73 | if (ttype(t1) != ttype(t2)) return 0; |
117 | ** C99 specification for 'strtod' | 74 | else switch (ttype(t1)) { |
118 | */ | 75 | case LUA_TNIL: |
119 | static lua_Number lua_strx2number (const char *s, char **endptr) { | 76 | return 1; |
120 | lua_Number r = 0.0; | 77 | case LUA_TNUMBER: |
121 | int e = 0, i = 0; | 78 | return luai_numeq(nvalue(t1), nvalue(t2)); |
122 | int neg = 0; /* 1 if number is negative */ | 79 | case LUA_TBOOLEAN: |
123 | *endptr = cast(char *, s); /* nothing is valid yet */ | 80 | return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ |
124 | while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ | 81 | case LUA_TLIGHTUSERDATA: |
125 | neg = isneg(&s); /* check signal */ | 82 | return pvalue(t1) == pvalue(t2); |
126 | if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ | 83 | default: |
127 | return 0.0; /* invalid format (no '0x') */ | 84 | lua_assert(iscollectable(t1)); |
128 | s += 2; /* skip '0x' */ | 85 | return gcvalue(t1) == gcvalue(t2); |
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 */ | ||
133 | } | 86 | } |
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); | ||
154 | } | 87 | } |
155 | 88 | ||
156 | #endif | ||
157 | |||
158 | 89 | ||
159 | int luaO_str2d (const char *s, size_t len, lua_Number *result) { | 90 | int luaO_str2d (const char *s, lua_Number *result) { |
160 | char *endptr; | 91 | char *endptr; |
161 | if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ | 92 | *result = lua_str2number(s, &endptr); |
162 | return 0; | 93 | if (endptr == s) return 0; /* conversion failed */ |
163 | else if (strpbrk(s, "xX")) /* hexa? */ | 94 | if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ |
164 | *result = lua_strx2number(s, &endptr); | 95 | *result = cast_num(strtoul(s, &endptr, 16)); |
165 | else | 96 | if (*endptr == '\0') return 1; /* most common case */ |
166 | *result = lua_str2number(s, &endptr); | 97 | while (isspace(cast(unsigned char, *endptr))) endptr++; |
167 | if (endptr == s) return 0; /* nothing recognized */ | 98 | if (*endptr != '\0') return 0; /* invalid trailing characters? */ |
168 | while (lisspace(cast_uchar(*endptr))) endptr++; | 99 | return 1; |
169 | return (endptr == s + len); /* OK if no trailing characters */ | ||
170 | } | 100 | } |
171 | 101 | ||
172 | 102 | ||
173 | 103 | ||
174 | static void pushstr (lua_State *L, const char *str, size_t l) { | 104 | static void pushstr (lua_State *L, const char *str) { |
175 | setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); | 105 | setsvalue2s(L, L->top, luaS_new(L, str)); |
106 | incr_top(L); | ||
176 | } | 107 | } |
177 | 108 | ||
178 | 109 | ||
179 | /* this function handles only `%d', `%c', %f, %p, and `%s' formats */ | 110 | /* this function handles only `%d', `%c', %f, %p, and `%s' formats */ |
180 | const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { | 111 | const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { |
181 | int n = 0; | 112 | int n = 1; |
113 | pushstr(L, ""); | ||
182 | for (;;) { | 114 | for (;;) { |
183 | const char *e = strchr(fmt, '%'); | 115 | const char *e = strchr(fmt, '%'); |
184 | if (e == NULL) break; | 116 | if (e == NULL) break; |
185 | luaD_checkstack(L, 2); /* fmt + item */ | 117 | setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); |
186 | pushstr(L, fmt, e - fmt); | 118 | incr_top(L); |
187 | switch (*(e+1)) { | 119 | switch (*(e+1)) { |
188 | case 's': { | 120 | case 's': { |
189 | const char *s = va_arg(argp, char *); | 121 | const char *s = va_arg(argp, char *); |
190 | if (s == NULL) s = "(null)"; | 122 | if (s == NULL) s = "(null)"; |
191 | pushstr(L, s, strlen(s)); | 123 | pushstr(L, s); |
192 | break; | 124 | break; |
193 | } | 125 | } |
194 | case 'c': { | 126 | case 'c': { |
195 | char buff; | 127 | char buff[2]; |
196 | buff = cast(char, va_arg(argp, int)); | 128 | buff[0] = cast(char, va_arg(argp, int)); |
197 | pushstr(L, &buff, 1); | 129 | buff[1] = '\0'; |
130 | pushstr(L, buff); | ||
198 | break; | 131 | break; |
199 | } | 132 | } |
200 | case 'd': { | 133 | case 'd': { |
201 | setnvalue(L->top++, cast_num(va_arg(argp, int))); | 134 | setnvalue(L->top, cast_num(va_arg(argp, int))); |
135 | incr_top(L); | ||
202 | break; | 136 | break; |
203 | } | 137 | } |
204 | case 'f': { | 138 | case 'f': { |
205 | setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber))); | 139 | setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); |
140 | incr_top(L); | ||
206 | break; | 141 | break; |
207 | } | 142 | } |
208 | case 'p': { | 143 | case 'p': { |
209 | char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ | 144 | char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ |
210 | int l = snprintf(buff, sizeof(buff), "%p", va_arg(argp, void *)); | 145 | snprintf(buff, 4*sizeof(void *) + 8, "%p", va_arg(argp, void *)); |
211 | pushstr(L, buff, l); | 146 | pushstr(L, buff); |
212 | break; | 147 | break; |
213 | } | 148 | } |
214 | case '%': { | 149 | case '%': { |
215 | pushstr(L, "%", 1); | 150 | pushstr(L, "%"); |
216 | break; | 151 | break; |
217 | } | 152 | } |
218 | default: { | 153 | default: { |
219 | luaG_runerror(L, | 154 | char buff[3]; |
220 | "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"), | 155 | buff[0] = '%'; |
221 | *(e + 1)); | 156 | buff[1] = *(e+1); |
157 | buff[2] = '\0'; | ||
158 | pushstr(L, buff); | ||
159 | break; | ||
222 | } | 160 | } |
223 | } | 161 | } |
224 | n += 2; | 162 | n += 2; |
225 | fmt = e+2; | 163 | fmt = e+2; |
226 | } | 164 | } |
227 | luaD_checkstack(L, 1); | 165 | pushstr(L, fmt); |
228 | pushstr(L, fmt, strlen(fmt)); | 166 | luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); |
229 | if (n > 0) luaV_concat(L, n + 1); | 167 | L->top -= n; |
230 | return svalue(L->top - 1); | 168 | return svalue(L->top - 1); |
231 | } | 169 | } |
232 | 170 | ||
@@ -241,48 +179,36 @@ const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { | |||
241 | } | 179 | } |
242 | 180 | ||
243 | 181 | ||
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 | |||
253 | void luaO_chunkid (char *out, const char *source, size_t bufflen) { | 182 | void luaO_chunkid (char *out, const char *source, size_t bufflen) { |
254 | size_t l = strlen(source); | 183 | if (*source == '=') { |
255 | if (*source == '=') { /* 'literal' source */ | 184 | strncpy(out, source+1, bufflen); /* remove first char */ |
256 | if (l <= bufflen) /* small enough? */ | 185 | out[bufflen-1] = '\0'; /* ensures null termination */ |
257 | memcpy(out, source + 1, l * sizeof(char)); | ||
258 | else { /* truncate it */ | ||
259 | addstr(out, source + 1, bufflen - 1); | ||
260 | *out = '\0'; | ||
261 | } | ||
262 | } | ||
263 | else if (*source == '@') { /* file name */ | ||
264 | if (l <= bufflen) /* small enough? */ | ||
265 | memcpy(out, source + 1, l * sizeof(char)); | ||
266 | else { /* add '...' before rest of name */ | ||
267 | addstr(out, RETS, LL(RETS)); | ||
268 | bufflen -= LL(RETS); | ||
269 | memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); | ||
270 | } | ||
271 | } | 186 | } |
272 | else { /* string; format as [string "source"] */ | 187 | else { /* out = "source", or "...source" */ |
273 | const char *nl = strchr(source, '\n'); /* find first new line (if any) */ | 188 | if (*source == '@') { |
274 | addstr(out, PRE, LL(PRE)); /* add prefix */ | 189 | size_t l; |
275 | bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ | 190 | source++; /* skip the `@' */ |
276 | if (l < bufflen && nl == NULL) { /* small one-line source? */ | 191 | bufflen -= sizeof(" '...' "); |
277 | addstr(out, source, l); /* keep it */ | 192 | l = strlen(source); |
193 | strcpy(out, ""); | ||
194 | if (l > bufflen) { | ||
195 | source += (l-bufflen); /* get last part of file name */ | ||
196 | strcat(out, "..."); | ||
197 | } | ||
198 | strcat(out, source); | ||
278 | } | 199 | } |
279 | else { | 200 | else { /* out = [string "string"] */ |
280 | if (nl != NULL) l = nl - source; /* stop at first newline */ | 201 | size_t len = strcspn(source, "\n\r"); /* stop at first newline */ |
281 | if (l > bufflen) l = bufflen; | 202 | bufflen -= sizeof(" [string \"...\"] "); |
282 | addstr(out, source, l); | 203 | if (len > bufflen) len = bufflen; |
283 | addstr(out, RETS, LL(RETS)); | 204 | strcpy(out, "[string \""); |
205 | if (source[len] != '\0') { /* must truncate? */ | ||
206 | strncat(out, source, len); | ||
207 | strcat(out, "..."); | ||
208 | } | ||
209 | else | ||
210 | strcat(out, source); | ||
211 | strcat(out, "\"]"); | ||
284 | } | 212 | } |
285 | memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); | ||
286 | } | 213 | } |
287 | } | 214 | } |
288 | |||
diff --git a/apps/plugins/lua/lobject.h b/apps/plugins/lua/lobject.h index 3a630b944c..93288fe0fb 100644 --- a/apps/plugins/lua/lobject.h +++ b/apps/plugins/lua/lobject.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.h,v 2.71.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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,52 +16,18 @@ | |||
16 | #include "lua.h" | 16 | #include "lua.h" |
17 | 17 | ||
18 | 18 | ||
19 | /* | 19 | /* tags for values visible from Lua */ |
20 | ** Extra tags for non-values | 20 | #define LAST_TAG LUA_TTHREAD |
21 | */ | ||
22 | #define LUA_TPROTO LUA_NUMTAGS | ||
23 | #define LUA_TUPVAL (LUA_NUMTAGS+1) | ||
24 | #define LUA_TDEADKEY (LUA_NUMTAGS+2) | ||
25 | 21 | ||
26 | /* | 22 | #define NUM_TAGS (LAST_TAG+1) |
27 | ** number of all possible tags (including LUA_TNONE but excluding DEADKEY) | ||
28 | */ | ||
29 | #define LUA_TOTALTAGS (LUA_TUPVAL+2) | ||
30 | 23 | ||
31 | 24 | ||
32 | /* | 25 | /* |
33 | ** tags for Tagged Values have the following use of bits: | 26 | ** Extra tags for non-values |
34 | ** bits 0-3: actual tag (a LUA_T* value) | ||
35 | ** bits 4-5: variant bits | ||
36 | ** bit 6: whether value is collectable | ||
37 | */ | 27 | */ |
38 | 28 | #define LUA_TPROTO (LAST_TAG+1) | |
39 | #define VARBITS (3 << 4) | 29 | #define LUA_TUPVAL (LAST_TAG+2) |
40 | 30 | #define LUA_TDEADKEY (LAST_TAG+3) | |
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) | ||
65 | 31 | ||
66 | 32 | ||
67 | /* | 33 | /* |
@@ -86,165 +52,120 @@ typedef struct GCheader { | |||
86 | 52 | ||
87 | 53 | ||
88 | 54 | ||
55 | |||
89 | /* | 56 | /* |
90 | ** Union of all Lua values | 57 | ** Union of all Lua values |
91 | */ | 58 | */ |
92 | typedef union Value Value; | 59 | typedef union { |
93 | 60 | GCObject *gc; | |
94 | 61 | void *p; | |
95 | #define numfield lua_Number n; /* numbers */ | 62 | lua_Number n; |
96 | 63 | int b; | |
64 | } Value; | ||
97 | 65 | ||
98 | 66 | ||
99 | /* | 67 | /* |
100 | ** Tagged Values. This is the basic representation of values in Lua, | 68 | ** Tagged Values |
101 | ** an actual value plus a tag with its type. | ||
102 | */ | 69 | */ |
103 | 70 | ||
104 | #define TValuefields Value value_; int tt_ | 71 | #define TValuefields Value value; int tt |
105 | |||
106 | typedef struct lua_TValue TValue; | ||
107 | |||
108 | |||
109 | /* macro defining a nil value */ | ||
110 | #define NILCONSTANT {NULL}, LUA_TNIL | ||
111 | 72 | ||
112 | 73 | typedef struct lua_TValue { | |
113 | #define val_(o) ((o)->value_) | 74 | TValuefields; |
114 | #define num_(o) (val_(o).n) | 75 | } TValue; |
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))) | ||
128 | 76 | ||
129 | 77 | ||
130 | /* Macros to test type */ | 78 | /* Macros to test type */ |
131 | #define checktag(o,t) (rttype(o) == (t)) | 79 | #define ttisnil(o) (ttype(o) == LUA_TNIL) |
132 | #define checktype(o,t) (ttypenv(o) == (t)) | 80 | #define ttisnumber(o) (ttype(o) == LUA_TNUMBER) |
133 | #define ttisnumber(o) checktag((o), LUA_TNUMBER) | 81 | #define ttisstring(o) (ttype(o) == LUA_TSTRING) |
134 | #define ttisnil(o) checktag((o), LUA_TNIL) | 82 | #define ttistable(o) (ttype(o) == LUA_TTABLE) |
135 | #define ttisboolean(o) checktag((o), LUA_TBOOLEAN) | 83 | #define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) |
136 | #define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) | 84 | #define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) |
137 | #define ttisstring(o) checktype((o), LUA_TSTRING) | 85 | #define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) |
138 | #define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) | 86 | #define ttisthread(o) (ttype(o) == LUA_TTHREAD) |
139 | #define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) | 87 | #define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) |
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)) | ||
151 | 88 | ||
152 | /* Macros to access values */ | 89 | /* Macros to access values */ |
153 | #define nvalue(o) check_exp(ttisnumber(o), num_(o)) | 90 | #define ttype(o) ((o)->tt) |
154 | #define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) | 91 | #define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) |
155 | #define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) | 92 | #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) |
156 | #define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts) | 93 | #define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) |
94 | #define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) | ||
157 | #define tsvalue(o) (&rawtsvalue(o)->tsv) | 95 | #define tsvalue(o) (&rawtsvalue(o)->tsv) |
158 | #define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).gc->u) | 96 | #define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) |
159 | #define uvalue(o) (&rawuvalue(o)->uv) | 97 | #define uvalue(o) (&rawuvalue(o)->uv) |
160 | #define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl) | 98 | #define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) |
161 | #define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l) | 99 | #define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) |
162 | #define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c) | 100 | #define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) |
163 | #define fvalue(o) check_exp(ttislcf(o), val_(o).f) | 101 | #define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) |
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)) | ||
169 | 102 | ||
170 | #define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) | 103 | #define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) |
171 | 104 | ||
172 | 105 | /* | |
173 | #define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) | 106 | ** for internal debug only |
174 | 107 | */ | |
175 | 108 | #define checkconsistency(obj) \ | |
176 | /* Macros for internal tests */ | 109 | lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) |
177 | #define righttt(obj) (ttype(obj) == gcvalue(obj)->gch.tt) | ||
178 | 110 | ||
179 | #define checkliveness(g,obj) \ | 111 | #define checkliveness(g,obj) \ |
180 | lua_longassert(!iscollectable(obj) || \ | 112 | lua_assert(!iscollectable(obj) || \ |
181 | (righttt(obj) && !isdead(g,gcvalue(obj)))) | 113 | ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) |
182 | 114 | ||
183 | 115 | ||
184 | /* Macros to set values */ | 116 | /* Macros to set values */ |
185 | #define settt_(o,t) ((o)->tt_=(t)) | 117 | #define setnilvalue(obj) ((obj)->tt=LUA_TNIL) |
186 | 118 | ||
187 | #define setnvalue(obj,x) \ | 119 | #define setnvalue(obj,x) \ |
188 | { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); } | 120 | { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=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); } | ||
194 | 121 | ||
195 | #define setpvalue(obj,x) \ | 122 | #define setpvalue(obj,x) \ |
196 | { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); } | 123 | { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } |
197 | 124 | ||
198 | #define setbvalue(obj,x) \ | 125 | #define setbvalue(obj,x) \ |
199 | { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } | 126 | { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=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)); } | ||
204 | 127 | ||
205 | #define setsvalue(L,obj,x) \ | 128 | #define setsvalue(L,obj,x) \ |
206 | { TValue *io=(obj); \ | 129 | { TValue *i_o=(obj); \ |
207 | TString *x_ = (x); \ | 130 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ |
208 | val_(io).gc=cast(GCObject *, x_); settt_(io, ctb(x_->tsv.tt)); \ | 131 | checkliveness(G(L),i_o); } |
209 | checkliveness(G(L),io); } | ||
210 | 132 | ||
211 | #define setuvalue(L,obj,x) \ | 133 | #define setuvalue(L,obj,x) \ |
212 | { TValue *io=(obj); \ | 134 | { TValue *i_o=(obj); \ |
213 | val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TUSERDATA)); \ | 135 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ |
214 | checkliveness(G(L),io); } | 136 | checkliveness(G(L),i_o); } |
215 | 137 | ||
216 | #define setthvalue(L,obj,x) \ | 138 | #define setthvalue(L,obj,x) \ |
217 | { TValue *io=(obj); \ | 139 | { TValue *i_o=(obj); \ |
218 | val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTHREAD)); \ | 140 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ |
219 | checkliveness(G(L),io); } | 141 | checkliveness(G(L),i_o); } |
220 | 142 | ||
221 | #define setclLvalue(L,obj,x) \ | 143 | #define setclvalue(L,obj,x) \ |
222 | { TValue *io=(obj); \ | 144 | { TValue *i_o=(obj); \ |
223 | val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TLCL)); \ | 145 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ |
224 | checkliveness(G(L),io); } | 146 | checkliveness(G(L),i_o); } |
225 | |||
226 | #define setclCvalue(L,obj,x) \ | ||
227 | { TValue *io=(obj); \ | ||
228 | val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TCCL)); \ | ||
229 | checkliveness(G(L),io); } | ||
230 | 147 | ||
231 | #define sethvalue(L,obj,x) \ | 148 | #define sethvalue(L,obj,x) \ |
232 | { TValue *io=(obj); \ | 149 | { TValue *i_o=(obj); \ |
233 | val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \ | 150 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ |
234 | checkliveness(G(L),io); } | 151 | checkliveness(G(L),i_o); } |
152 | |||
153 | #define setptvalue(L,obj,x) \ | ||
154 | { TValue *i_o=(obj); \ | ||
155 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ | ||
156 | checkliveness(G(L),i_o); } | ||
235 | 157 | ||
236 | #define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) | ||
237 | 158 | ||
238 | 159 | ||
239 | 160 | ||
240 | #define setobj(L,obj1,obj2) \ | 161 | #define setobj(L,obj1,obj2) \ |
241 | { const TValue *io2=(obj2); TValue *io1=(obj1); \ | 162 | { const TValue *o2=(obj2); TValue *o1=(obj1); \ |
242 | io1->value_ = io2->value_; io1->tt_ = io2->tt_; \ | 163 | o1->value = o2->value; o1->tt=o2->tt; \ |
243 | checkliveness(G(L),io1); } | 164 | checkliveness(G(L),o1); } |
244 | 165 | ||
245 | 166 | ||
246 | /* | 167 | /* |
247 | ** different types of assignments, according to destination | 168 | ** different types of sets, according to destination |
248 | */ | 169 | */ |
249 | 170 | ||
250 | /* from stack to (same) stack */ | 171 | /* from stack to (same) stack */ |
@@ -262,204 +183,47 @@ typedef struct lua_TValue TValue; | |||
262 | #define setobj2n setobj | 183 | #define setobj2n setobj |
263 | #define setsvalue2n setsvalue | 184 | #define setsvalue2n setsvalue |
264 | 185 | ||
265 | 186 | #define setttype(obj, tt) (ttype(obj) = (tt)) | |
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 /* } */ | ||
324 | 187 | ||
325 | 188 | ||
326 | /* correspondence with standard representation */ | 189 | #define iscollectable(o) (ttype(o) >= LUA_TSTRING) |
327 | #undef val_ | ||
328 | #define val_(o) v_(o) | ||
329 | #undef num_ | ||
330 | #define num_(o) d_(o) | ||
331 | 190 | ||
332 | 191 | ||
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 | |||
401 | 192 | ||
402 | typedef TValue *StkId; /* index to stack elements */ | 193 | typedef TValue *StkId; /* index to stack elements */ |
403 | 194 | ||
404 | 195 | ||
405 | |||
406 | |||
407 | /* | 196 | /* |
408 | ** Header for string value; string bytes follow the end of this structure | 197 | ** String headers for string table |
409 | */ | 198 | */ |
410 | typedef union TString { | 199 | typedef union TString { |
411 | L_Umaxalign dummy; /* ensures maximum alignment for strings */ | 200 | L_Umaxalign dummy; /* ensures maximum alignment for strings */ |
412 | struct { | 201 | struct { |
413 | CommonHeader; | 202 | CommonHeader; |
414 | lu_byte extra; /* reserved words for short strings; "has hash" for longs */ | 203 | lu_byte reserved; |
415 | unsigned int hash; | 204 | unsigned int hash; |
416 | size_t len; /* number of characters in string */ | 205 | size_t len; |
417 | } tsv; | 206 | } tsv; |
418 | } TString; | 207 | } TString; |
419 | 208 | ||
420 | 209 | ||
421 | /* get the actual string (array of bytes) from a TString */ | ||
422 | #define getstr(ts) cast(const char *, (ts) + 1) | 210 | #define getstr(ts) cast(const char *, (ts) + 1) |
423 | |||
424 | /* get the actual string (array of bytes) from a Lua value */ | ||
425 | #define svalue(o) getstr(rawtsvalue(o)) | 211 | #define svalue(o) getstr(rawtsvalue(o)) |
426 | 212 | ||
427 | 213 | ||
428 | /* | 214 | |
429 | ** Header for userdata; memory area follows the end of this structure | ||
430 | */ | ||
431 | typedef union Udata { | 215 | typedef union Udata { |
432 | L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ | 216 | L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ |
433 | struct { | 217 | struct { |
434 | CommonHeader; | 218 | CommonHeader; |
435 | struct Table *metatable; | 219 | struct Table *metatable; |
436 | struct Table *env; | 220 | struct Table *env; |
437 | size_t len; /* number of bytes */ | 221 | size_t len; |
438 | } uv; | 222 | } uv; |
439 | } Udata; | 223 | } Udata; |
440 | 224 | ||
441 | 225 | ||
442 | 226 | ||
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 | |||
463 | 227 | ||
464 | /* | 228 | /* |
465 | ** Function Prototypes | 229 | ** Function Prototypes |
@@ -469,12 +233,11 @@ typedef struct Proto { | |||
469 | TValue *k; /* constants used by the function */ | 233 | TValue *k; /* constants used by the function */ |
470 | Instruction *code; | 234 | Instruction *code; |
471 | struct Proto **p; /* functions defined inside the function */ | 235 | struct Proto **p; /* functions defined inside the function */ |
472 | int *lineinfo; /* map from opcodes to source lines (debug information) */ | 236 | int *lineinfo; /* map from opcodes to source lines */ |
473 | LocVar *locvars; /* information about local variables (debug information) */ | 237 | struct LocVar *locvars; /* information about local variables */ |
474 | Upvaldesc *upvalues; /* upvalue information */ | 238 | TString **upvalues; /* upvalue names */ |
475 | union Closure *cache; /* last created closure with this prototype */ | 239 | TString *source; |
476 | TString *source; /* used for debug information */ | 240 | int sizeupvalues; |
477 | int sizeupvalues; /* size of 'upvalues' */ | ||
478 | int sizek; /* size of `k' */ | 241 | int sizek; /* size of `k' */ |
479 | int sizecode; | 242 | int sizecode; |
480 | int sizelineinfo; | 243 | int sizelineinfo; |
@@ -483,16 +246,31 @@ typedef struct Proto { | |||
483 | int linedefined; | 246 | int linedefined; |
484 | int lastlinedefined; | 247 | int lastlinedefined; |
485 | GCObject *gclist; | 248 | GCObject *gclist; |
486 | lu_byte numparams; /* number of fixed parameters */ | 249 | lu_byte nups; /* number of upvalues */ |
250 | lu_byte numparams; | ||
487 | lu_byte is_vararg; | 251 | lu_byte is_vararg; |
488 | lu_byte maxstacksize; /* maximum stack used by this function */ | 252 | lu_byte maxstacksize; |
489 | } Proto; | 253 | } Proto; |
490 | 254 | ||
491 | 255 | ||
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 | |||
492 | 269 | ||
493 | /* | 270 | /* |
494 | ** Lua Upvalues | 271 | ** Upvalues |
495 | */ | 272 | */ |
273 | |||
496 | typedef struct UpVal { | 274 | typedef struct UpVal { |
497 | CommonHeader; | 275 | CommonHeader; |
498 | TValue *v; /* points to stack or to its own value */ | 276 | TValue *v; /* points to stack or to its own value */ |
@@ -511,19 +289,20 @@ typedef struct UpVal { | |||
511 | */ | 289 | */ |
512 | 290 | ||
513 | #define ClosureHeader \ | 291 | #define ClosureHeader \ |
514 | CommonHeader; lu_byte nupvalues; GCObject *gclist | 292 | CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ |
293 | struct Table *env | ||
515 | 294 | ||
516 | typedef struct CClosure { | 295 | typedef struct CClosure { |
517 | ClosureHeader; | 296 | ClosureHeader; |
518 | lua_CFunction f; | 297 | lua_CFunction f; |
519 | TValue upvalue[1]; /* list of upvalues */ | 298 | TValue upvalue[1]; |
520 | } CClosure; | 299 | } CClosure; |
521 | 300 | ||
522 | 301 | ||
523 | typedef struct LClosure { | 302 | typedef struct LClosure { |
524 | ClosureHeader; | 303 | ClosureHeader; |
525 | struct Proto *p; | 304 | struct Proto *p; |
526 | UpVal *upvals[1]; /* list of upvalues */ | 305 | UpVal *upvals[1]; |
527 | } LClosure; | 306 | } LClosure; |
528 | 307 | ||
529 | 308 | ||
@@ -533,9 +312,8 @@ typedef union Closure { | |||
533 | } Closure; | 312 | } Closure; |
534 | 313 | ||
535 | 314 | ||
536 | #define isLfunction(o) ttisLclosure(o) | 315 | #define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) |
537 | 316 | #define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) | |
538 | #define getproto(o) (clLvalue(o)->p) | ||
539 | 317 | ||
540 | 318 | ||
541 | /* | 319 | /* |
@@ -559,7 +337,7 @@ typedef struct Node { | |||
559 | 337 | ||
560 | typedef struct Table { | 338 | typedef struct Table { |
561 | CommonHeader; | 339 | CommonHeader; |
562 | lu_byte flags; /* 1<<p means tagmethod(p) is not present */ | 340 | lu_byte flags; /* 1<<p means tagmethod(p) is not present */ |
563 | lu_byte lsizenode; /* log2 of size of `node' array */ | 341 | lu_byte lsizenode; /* log2 of size of `node' array */ |
564 | struct Table *metatable; | 342 | struct Table *metatable; |
565 | TValue *array; /* array part */ | 343 | TValue *array; /* array part */ |
@@ -582,21 +360,17 @@ typedef struct Table { | |||
582 | #define sizenode(t) (twoto((t)->lsizenode)) | 360 | #define sizenode(t) (twoto((t)->lsizenode)) |
583 | 361 | ||
584 | 362 | ||
585 | /* | ||
586 | ** (address of) a fixed nil value | ||
587 | */ | ||
588 | #define luaO_nilobject (&luaO_nilobject_) | 363 | #define luaO_nilobject (&luaO_nilobject_) |
589 | 364 | ||
365 | LUAI_DATA const TValue luaO_nilobject_; | ||
590 | 366 | ||
591 | LUAI_DDEC const TValue luaO_nilobject_; | 367 | #define ceillog2(x) (luaO_log2((x)-1) + 1) |
592 | |||
593 | 368 | ||
369 | LUAI_FUNC int luaO_log2 (unsigned int x); | ||
594 | LUAI_FUNC int luaO_int2fb (unsigned int x); | 370 | LUAI_FUNC int luaO_int2fb (unsigned int x); |
595 | LUAI_FUNC int luaO_fb2int (int x); | 371 | LUAI_FUNC int luaO_fb2int (int x); |
596 | LUAI_FUNC int luaO_ceillog2 (unsigned int x); | 372 | LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); |
597 | LUAI_FUNC lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2); | 373 | LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); |
598 | LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result); | ||
599 | LUAI_FUNC int luaO_hexavalue (int c); | ||
600 | LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, | 374 | LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, |
601 | va_list argp); | 375 | va_list argp); |
602 | LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); | 376 | 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 4190dc7624..4cc745230b 100644 --- a/apps/plugins/lua/lopcodes.c +++ b/apps/plugins/lua/lopcodes.c | |||
@@ -1,6 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.c,v 1.49.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ |
3 | ** Opcodes for Lua virtual machine | ||
4 | ** See Copyright Notice in lua.h | 3 | ** See Copyright Notice in lua.h |
5 | */ | 4 | */ |
6 | 5 | ||
@@ -14,16 +13,15 @@ | |||
14 | 13 | ||
15 | /* ORDER OP */ | 14 | /* ORDER OP */ |
16 | 15 | ||
17 | LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { | 16 | const char *const luaP_opnames[NUM_OPCODES+1] = { |
18 | "MOVE", | 17 | "MOVE", |
19 | "LOADK", | 18 | "LOADK", |
20 | "LOADKX", | ||
21 | "LOADBOOL", | 19 | "LOADBOOL", |
22 | "LOADNIL", | 20 | "LOADNIL", |
23 | "GETUPVAL", | 21 | "GETUPVAL", |
24 | "GETTABUP", | 22 | "GETGLOBAL", |
25 | "GETTABLE", | 23 | "GETTABLE", |
26 | "SETTABUP", | 24 | "SETGLOBAL", |
27 | "SETUPVAL", | 25 | "SETUPVAL", |
28 | "SETTABLE", | 26 | "SETTABLE", |
29 | "NEWTABLE", | 27 | "NEWTABLE", |
@@ -49,29 +47,27 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { | |||
49 | "RETURN", | 47 | "RETURN", |
50 | "FORLOOP", | 48 | "FORLOOP", |
51 | "FORPREP", | 49 | "FORPREP", |
52 | "TFORCALL", | ||
53 | "TFORLOOP", | 50 | "TFORLOOP", |
54 | "SETLIST", | 51 | "SETLIST", |
52 | "CLOSE", | ||
55 | "CLOSURE", | 53 | "CLOSURE", |
56 | "VARARG", | 54 | "VARARG", |
57 | "EXTRAARG", | ||
58 | NULL | 55 | NULL |
59 | }; | 56 | }; |
60 | 57 | ||
61 | 58 | ||
62 | #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) | 59 | #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) |
63 | 60 | ||
64 | LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { | 61 | const lu_byte luaP_opmodes[NUM_OPCODES] = { |
65 | /* T A B C mode opcode */ | 62 | /* T A B C mode opcode */ |
66 | opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ | 63 | opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ |
67 | ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ | 64 | ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ |
68 | ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ | ||
69 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ | 65 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ |
70 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ | 66 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ |
71 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ | 67 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ |
72 | ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ | 68 | ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ |
73 | ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ | 69 | ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ |
74 | ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ | 70 | ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ |
75 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ | 71 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ |
76 | ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ | 72 | ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ |
77 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ | 73 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ |
@@ -90,18 +86,17 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
90 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ | 86 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ |
91 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ | 87 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ |
92 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ | 88 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ |
93 | ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */ | 89 | ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ |
94 | ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ | 90 | ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ |
95 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ | 91 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ |
96 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ | 92 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ |
97 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ | 93 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ |
98 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ | 94 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ |
99 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ | 95 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ |
100 | ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ | 96 | ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ |
101 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ | ||
102 | ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ | 97 | ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ |
98 | ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ | ||
103 | ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ | 99 | ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ |
104 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ | 100 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ |
105 | ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ | ||
106 | }; | 101 | }; |
107 | 102 | ||
diff --git a/apps/plugins/lua/lopcodes.h b/apps/plugins/lua/lopcodes.h index 51f5791545..e1aed0f637 100644 --- a/apps/plugins/lua/lopcodes.h +++ b/apps/plugins/lua/lopcodes.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.142.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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,7 +17,6 @@ | |||
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) | ||
21 | `Bx' : 18 bits (`B' and `C' together) | 20 | `Bx' : 18 bits (`B' and `C' together) |
22 | `sBx' : signed Bx | 21 | `sBx' : signed Bx |
23 | 22 | ||
@@ -29,7 +28,7 @@ | |||
29 | ===========================================================================*/ | 28 | ===========================================================================*/ |
30 | 29 | ||
31 | 30 | ||
32 | enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ | 31 | enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ |
33 | 32 | ||
34 | 33 | ||
35 | /* | 34 | /* |
@@ -39,7 +38,6 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ | |||
39 | #define SIZE_B 9 | 38 | #define SIZE_B 9 |
40 | #define SIZE_Bx (SIZE_C + SIZE_B) | 39 | #define SIZE_Bx (SIZE_C + SIZE_B) |
41 | #define SIZE_A 8 | 40 | #define SIZE_A 8 |
42 | #define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A) | ||
43 | 41 | ||
44 | #define SIZE_OP 6 | 42 | #define SIZE_OP 6 |
45 | 43 | ||
@@ -48,7 +46,6 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ | |||
48 | #define POS_C (POS_A + SIZE_A) | 46 | #define POS_C (POS_A + SIZE_A) |
49 | #define POS_B (POS_C + SIZE_C) | 47 | #define POS_B (POS_C + SIZE_C) |
50 | #define POS_Bx POS_C | 48 | #define POS_Bx POS_C |
51 | #define POS_Ax POS_A | ||
52 | 49 | ||
53 | 50 | ||
54 | /* | 51 | /* |
@@ -64,12 +61,6 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ | |||
64 | #define MAXARG_sBx MAX_INT | 61 | #define MAXARG_sBx MAX_INT |
65 | #endif | 62 | #endif |
66 | 63 | ||
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 | |||
73 | 64 | ||
74 | #define MAXARG_A ((1<<SIZE_A)-1) | 65 | #define MAXARG_A ((1<<SIZE_A)-1) |
75 | #define MAXARG_B ((1<<SIZE_B)-1) | 66 | #define MAXARG_B ((1<<SIZE_B)-1) |
@@ -77,7 +68,7 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ | |||
77 | 68 | ||
78 | 69 | ||
79 | /* creates a mask with `n' 1 bits at position `p' */ | 70 | /* creates a mask with `n' 1 bits at position `p' */ |
80 | #define MASK1(n,p) ((~((~(Instruction)0)<<(n)))<<(p)) | 71 | #define MASK1(n,p) ((~((~(Instruction)0)<<n))<<p) |
81 | 72 | ||
82 | /* creates a mask with `n' 0 bits at position `p' */ | 73 | /* creates a mask with `n' 0 bits at position `p' */ |
83 | #define MASK0(n,p) (~MASK1(n,p)) | 74 | #define MASK0(n,p) (~MASK1(n,p)) |
@@ -90,24 +81,21 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ | |||
90 | #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ | 81 | #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ |
91 | ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP)))) | 82 | ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP)))) |
92 | 83 | ||
93 | #define getarg(i,pos,size) (cast(int, ((i)>>pos) & MASK1(size,0))) | 84 | #define GETARG_A(i) (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0))) |
94 | #define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ | 85 | #define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ |
95 | ((cast(Instruction, v)<<pos)&MASK1(size,pos)))) | 86 | ((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A)))) |
96 | 87 | ||
97 | #define GETARG_A(i) getarg(i, POS_A, SIZE_A) | 88 | #define GETARG_B(i) (cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0))) |
98 | #define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A) | 89 | #define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ |
90 | ((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B)))) | ||
99 | 91 | ||
100 | #define GETARG_B(i) getarg(i, POS_B, SIZE_B) | 92 | #define GETARG_C(i) (cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0))) |
101 | #define SETARG_B(i,v) setarg(i, v, POS_B, SIZE_B) | 93 | #define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ |
94 | ((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C)))) | ||
102 | 95 | ||
103 | #define GETARG_C(i) getarg(i, POS_C, SIZE_C) | 96 | #define GETARG_Bx(i) (cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0))) |
104 | #define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C) | 97 | #define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ |
105 | 98 | ((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx)))) | |
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) | ||
111 | 99 | ||
112 | #define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx) | 100 | #define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx) |
113 | #define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx)) | 101 | #define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx)) |
@@ -122,9 +110,6 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ | |||
122 | | (cast(Instruction, a)<<POS_A) \ | 110 | | (cast(Instruction, a)<<POS_A) \ |
123 | | (cast(Instruction, bc)<<POS_Bx)) | 111 | | (cast(Instruction, bc)<<POS_Bx)) |
124 | 112 | ||
125 | #define CREATE_Ax(o,a) ((cast(Instruction, o)<<POS_OP) \ | ||
126 | | (cast(Instruction, a)<<POS_Ax)) | ||
127 | |||
128 | 113 | ||
129 | /* | 114 | /* |
130 | ** Macros to operate RK indices | 115 | ** Macros to operate RK indices |
@@ -168,15 +153,14 @@ name args description | |||
168 | ------------------------------------------------------------------------*/ | 153 | ------------------------------------------------------------------------*/ |
169 | OP_MOVE,/* A B R(A) := R(B) */ | 154 | OP_MOVE,/* A B R(A) := R(B) */ |
170 | OP_LOADK,/* A Bx R(A) := Kst(Bx) */ | 155 | OP_LOADK,/* A Bx R(A) := Kst(Bx) */ |
171 | OP_LOADKX,/* A R(A) := Kst(extra arg) */ | ||
172 | OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ | 156 | OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ |
173 | OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */ | 157 | OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */ |
174 | OP_GETUPVAL,/* A B R(A) := UpValue[B] */ | 158 | OP_GETUPVAL,/* A B R(A) := UpValue[B] */ |
175 | 159 | ||
176 | OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */ | 160 | OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */ |
177 | OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ | 161 | OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ |
178 | 162 | ||
179 | OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */ | 163 | OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */ |
180 | OP_SETUPVAL,/* A B UpValue[B] := R(A) */ | 164 | OP_SETUPVAL,/* A B UpValue[B] := R(A) */ |
181 | OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ | 165 | OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ |
182 | 166 | ||
@@ -196,13 +180,14 @@ OP_LEN,/* A B R(A) := length of R(B) */ | |||
196 | 180 | ||
197 | OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ | 181 | OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ |
198 | 182 | ||
199 | OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A) + 1 */ | 183 | OP_JMP,/* sBx pc+=sBx */ |
184 | |||
200 | OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ | 185 | OP_EQ,/* 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++ */ | 186 | OP_LT,/* 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++ */ | 187 | OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ |
203 | 188 | ||
204 | OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ | 189 | OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ |
205 | OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ | 190 | OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ |
206 | 191 | ||
207 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ | 192 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := 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)) */ | 193 | OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ |
@@ -212,44 +197,39 @@ OP_FORLOOP,/* A sBx R(A)+=R(A+2); | |||
212 | if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/ | 197 | if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/ |
213 | OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */ | 198 | OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */ |
214 | 199 | ||
215 | OP_TFORCALL,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */ | 200 | OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); |
216 | OP_TFORLOOP,/* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/ | 201 | if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */ |
217 | |||
218 | OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ | 202 | OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ |
219 | 203 | ||
220 | OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ | 204 | OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/ |
221 | 205 | OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ | |
222 | OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */ | ||
223 | 206 | ||
224 | OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ | 207 | OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ |
225 | } OpCode; | 208 | } OpCode; |
226 | 209 | ||
227 | 210 | ||
228 | #define NUM_OPCODES (cast(int, OP_EXTRAARG) + 1) | 211 | #define NUM_OPCODES (cast(int, OP_VARARG) + 1) |
229 | 212 | ||
230 | 213 | ||
231 | 214 | ||
232 | /*=========================================================================== | 215 | /*=========================================================================== |
233 | Notes: | 216 | Notes: |
234 | (*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then `top' is | 217 | (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, |
235 | set to last_result+1, so next open instruction (OP_CALL, OP_RETURN, | 218 | and can be 0: OP_CALL then sets `top' to last_result+1, so |
236 | OP_SETLIST) may use `top'. | 219 | next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. |
237 | 220 | ||
238 | (*) In OP_VARARG, if (B == 0) then use actual number of varargs and | 221 | (*) In OP_VARARG, if (B == 0) then use actual number of varargs and |
239 | set top (like in OP_CALL with C == 0). | 222 | set top (like in OP_CALL with C == 0). |
240 | 223 | ||
241 | (*) In OP_RETURN, if (B == 0) then return up to `top'. | 224 | (*) In OP_RETURN, if (B == 0) then return up to `top' |
242 | 225 | ||
243 | (*) In OP_SETLIST, if (B == 0) then B = `top'; if (C == 0) then next | 226 | (*) In OP_SETLIST, if (B == 0) then B = `top'; |
244 | 'instruction' is EXTRAARG(real C). | 227 | if (C == 0) then next `instruction' is real C |
245 | |||
246 | (*) In OP_LOADKX, the next 'instruction' is always EXTRAARG. | ||
247 | 228 | ||
248 | (*) For comparisons, A specifies what condition the test should accept | 229 | (*) For comparisons, A specifies what condition the test should accept |
249 | (true or false). | 230 | (true or false). |
250 | |||
251 | (*) All `skips' (pc++) assume that next instruction is a jump. | ||
252 | 231 | ||
232 | (*) All `skips' (pc++) assume that next instruction is a jump | ||
253 | ===========================================================================*/ | 233 | ===========================================================================*/ |
254 | 234 | ||
255 | 235 | ||
@@ -259,8 +239,8 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ | |||
259 | ** bits 2-3: C arg mode | 239 | ** bits 2-3: C arg mode |
260 | ** bits 4-5: B arg mode | 240 | ** bits 4-5: B arg mode |
261 | ** bit 6: instruction set register A | 241 | ** bit 6: instruction set register A |
262 | ** bit 7: operator is a test (next instruction must be a jump) | 242 | ** bit 7: operator is a test |
263 | */ | 243 | */ |
264 | 244 | ||
265 | enum OpArgMask { | 245 | enum OpArgMask { |
266 | OpArgN, /* argument is not used */ | 246 | OpArgN, /* argument is not used */ |
@@ -269,7 +249,7 @@ enum OpArgMask { | |||
269 | OpArgK /* argument is a constant or register/constant */ | 249 | OpArgK /* argument is a constant or register/constant */ |
270 | }; | 250 | }; |
271 | 251 | ||
272 | LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES]; | 252 | LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; |
273 | 253 | ||
274 | #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) | 254 | #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) |
275 | #define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) | 255 | #define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) |
@@ -278,7 +258,7 @@ LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES]; | |||
278 | #define testTMode(m) (luaP_opmodes[m] & (1 << 7)) | 258 | #define testTMode(m) (luaP_opmodes[m] & (1 << 7)) |
279 | 259 | ||
280 | 260 | ||
281 | LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ | 261 | LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ |
282 | 262 | ||
283 | 263 | ||
284 | /* number of list items to accumulate before a SETLIST instruction */ | 264 | /* 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 350e848d38..6cb8c0541b 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.40.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 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,109 +19,31 @@ | |||
19 | #include "lualib.h" | 19 | #include "lualib.h" |
20 | 20 | ||
21 | 21 | ||
22 | /* | 22 | static int os_pushresult (lua_State *L, int i, const char *filename) { |
23 | ** list of valid conversion specifiers for the 'strftime' function | 23 | int en = errno; /* calls to Lua API may change this value */ |
24 | */ | 24 | if (i) { |
25 | #if !defined(LUA_STRFTIMEOPTIONS) | 25 | lua_pushboolean(L, 1); |
26 | |||
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); | ||
84 | else { | ||
85 | lua_pushboolean(L, stat); /* true if there is a shell */ | ||
86 | return 1; | 26 | return 1; |
87 | } | 27 | } |
28 | else { | ||
29 | lua_pushnil(L); | ||
30 | lua_pushfstring(L, "%s: %s", filename, strerror(en)); | ||
31 | lua_pushinteger(L, en); | ||
32 | return 3; | ||
33 | } | ||
88 | } | 34 | } |
89 | 35 | ||
90 | 36 | ||
91 | static int os_remove (lua_State *L) { | 37 | static int os_remove (lua_State *L) { |
92 | const char *filename = luaL_checkstring(L, 1); | 38 | const char *filename = luaL_checkstring(L, 1); |
93 | return luaL_fileresult(L, rb->remove(filename) == 0, filename); | 39 | return os_pushresult(L, rb->remove(filename) == 0, filename); |
94 | } | 40 | } |
95 | 41 | ||
96 | 42 | ||
97 | static int os_rename (lua_State *L) { | 43 | static int os_rename (lua_State *L) { |
98 | const char *fromname = luaL_checkstring(L, 1); | 44 | const char *fromname = luaL_checkstring(L, 1); |
99 | const char *toname = luaL_checkstring(L, 2); | 45 | const char *toname = luaL_checkstring(L, 2); |
100 | return luaL_fileresult(L, rb->rename(fromname, toname) == 0, NULL); | 46 | return os_pushresult(L, rb->rename(fromname, toname) == 0, fromname); |
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; | ||
125 | } | 47 | } |
126 | 48 | ||
127 | 49 | ||
@@ -145,6 +67,7 @@ static void setboolfield (lua_State *L, const char *key, int value) { | |||
145 | lua_setfield(L, -2, key); | 67 | lua_setfield(L, -2, key); |
146 | } | 68 | } |
147 | 69 | ||
70 | #if CONFIG_RTC | ||
148 | static int getboolfield (lua_State *L, const char *key) { | 71 | static int getboolfield (lua_State *L, const char *key) { |
149 | int res; | 72 | int res; |
150 | lua_getfield(L, -1, key); | 73 | lua_getfield(L, -1, key); |
@@ -155,10 +78,11 @@ static int getboolfield (lua_State *L, const char *key) { | |||
155 | 78 | ||
156 | 79 | ||
157 | static int getfield (lua_State *L, const char *key, int d) { | 80 | static int getfield (lua_State *L, const char *key, int d) { |
158 | int res, isnum; | 81 | int res; |
159 | lua_getfield(L, -1, key); | 82 | lua_getfield(L, -1, key); |
160 | res = (int)lua_tointegerx(L, -1, &isnum); | 83 | if (lua_isnumber(L, -1)) |
161 | if (!isnum) { | 84 | res = (int)lua_tointeger(L, -1); |
85 | else { | ||
162 | if (d < 0) | 86 | if (d < 0) |
163 | return luaL_error(L, "field " LUA_QS " missing in date table", key); | 87 | return luaL_error(L, "field " LUA_QS " missing in date table", key); |
164 | res = d; | 88 | res = d; |
@@ -166,42 +90,22 @@ static int getfield (lua_State *L, const char *key, int d) { | |||
166 | lua_pop(L, 1); | 90 | lua_pop(L, 1); |
167 | return res; | 91 | return res; |
168 | } | 92 | } |
169 | 93 | #endif | |
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 | } | ||
193 | 94 | ||
194 | 95 | ||
195 | static int os_date (lua_State *L) { | 96 | static int os_date (lua_State *L) { |
196 | const char *s = luaL_optstring(L, 1, "%c"); | 97 | const char *s = luaL_optstring(L, 1, "%c"); |
197 | time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); | 98 | time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, |
198 | struct tm tmr, *stm; | 99 | #if CONFIG_RTC |
199 | if (*s == '!') { /* UTC? */ | 100 | rb->mktime(rb->get_time()) |
200 | stm = l_gmtime(&t, &tmr); | 101 | #else |
102 | 0 | ||
103 | #endif | ||
104 | ); | ||
105 | struct tm *stm; | ||
106 | if (*s == '!') /* UTC? */ /* Rockbox doesn't support timezones */ | ||
201 | s++; /* skip `!' */ | 107 | s++; /* skip `!' */ |
202 | } | 108 | stm = gmtime(&t); |
203 | else | ||
204 | stm = l_localtime(&t, &tmr); | ||
205 | if (stm == NULL) /* invalid date? */ | 109 | if (stm == NULL) /* invalid date? */ |
206 | lua_pushnil(L); | 110 | lua_pushnil(L); |
207 | else if (strcmp(s, "*t") == 0) { | 111 | else if (strcmp(s, "*t") == 0) { |
@@ -217,17 +121,17 @@ static int os_date (lua_State *L) { | |||
217 | setboolfield(L, "isdst", stm->tm_isdst); | 121 | setboolfield(L, "isdst", stm->tm_isdst); |
218 | } | 122 | } |
219 | else { | 123 | else { |
220 | char cc[4]; | 124 | char cc[3]; |
221 | luaL_Buffer b; | 125 | luaL_Buffer b; |
222 | cc[0] = '%'; | 126 | cc[0] = '%'; cc[2] = '\0'; |
223 | luaL_buffinit(L, &b); | 127 | luaL_buffinit(L, &b); |
224 | while (*s) { | 128 | for (; *s; s++) { |
225 | if (*s != '%') /* no conversion specifier? */ | 129 | if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ |
226 | luaL_addchar(&b, *s++); | 130 | luaL_addchar(&b, *s); |
227 | else { | 131 | else { |
228 | size_t reslen; | 132 | size_t reslen; |
229 | char buff[200]; /* should be big enough for any conversion result */ | 133 | char buff[200]; /* should be big enough for any conversion result */ |
230 | s = checkoption(L, s + 1, cc); | 134 | cc[1] = *(++s); |
231 | reslen = strftime(buff, sizeof(buff), cc, stm); | 135 | reslen = strftime(buff, sizeof(buff), cc, stm); |
232 | luaL_addlstring(&b, buff, reslen); | 136 | luaL_addlstring(&b, buff, reslen); |
233 | } | 137 | } |
@@ -237,11 +141,11 @@ static int os_date (lua_State *L) { | |||
237 | return 1; | 141 | return 1; |
238 | } | 142 | } |
239 | 143 | ||
240 | |||
241 | static int os_time (lua_State *L) { | 144 | static int os_time (lua_State *L) { |
242 | time_t t; | 145 | time_t t = -1; |
146 | #if CONFIG_RTC | ||
243 | if (lua_isnoneornil(L, 1)) /* called without args? */ | 147 | if (lua_isnoneornil(L, 1)) /* called without args? */ |
244 | t = time(NULL); /* get current time */ | 148 | t = rb->mktime(rb->get_time()); /* get current time */ |
245 | else { | 149 | else { |
246 | struct tm ts; | 150 | struct tm ts; |
247 | luaL_checktype(L, 1, LUA_TTABLE); | 151 | luaL_checktype(L, 1, LUA_TTABLE); |
@@ -253,8 +157,9 @@ static int os_time (lua_State *L) { | |||
253 | ts.tm_mon = getfield(L, "month", -1) - 1; | 157 | ts.tm_mon = getfield(L, "month", -1) - 1; |
254 | ts.tm_year = getfield(L, "year", -1) - 1900; | 158 | ts.tm_year = getfield(L, "year", -1) - 1900; |
255 | ts.tm_isdst = getboolfield(L, "isdst"); | 159 | ts.tm_isdst = getboolfield(L, "isdst"); |
256 | t = mktime(&ts); | 160 | t = rb->mktime(&ts); |
257 | } | 161 | } |
162 | #endif | ||
258 | if (t == (time_t)(-1)) | 163 | if (t == (time_t)(-1)) |
259 | lua_pushnil(L); | 164 | lua_pushnil(L); |
260 | else | 165 | else |
@@ -263,54 +168,26 @@ static int os_time (lua_State *L) { | |||
263 | } | 168 | } |
264 | 169 | ||
265 | 170 | ||
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 | |||
272 | /* }====================================================== */ | 171 | /* }====================================================== */ |
273 | 172 | ||
274 | 173 | ||
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 | |||
289 | static int os_exit (lua_State *L) { | 174 | static int os_exit (lua_State *L) { |
290 | int status; | 175 | exit(luaL_optint(L, 1, EXIT_SUCCESS)); |
291 | if (lua_isboolean(L, 1)) | 176 | return EXIT_SUCCESS; /* never reached, surpress warning */ |
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; | ||
299 | } | 177 | } |
300 | 178 | ||
301 | |||
302 | static const luaL_Reg syslib[] = { | 179 | static const luaL_Reg syslib[] = { |
303 | {"clock", os_clock}, | 180 | //{"clock", os_clock}, |
304 | {"date", os_date}, | 181 | {"date", os_date}, |
305 | {"difftime", os_difftime}, | 182 | //{"difftime", os_difftime}, |
306 | {"execute", os_execute}, | 183 | //{"execute", os_execute}, |
307 | {"exit", os_exit}, | 184 | {"exit", os_exit}, |
308 | {"getenv", os_getenv}, | 185 | //{"getenv", os_getenv}, |
309 | {"remove", os_remove}, | 186 | {"remove", os_remove}, |
310 | {"rename", os_rename}, | 187 | {"rename", os_rename}, |
311 | /*{"setlocale", os_setlocale},*/ | 188 | //{"setlocale", os_setlocale}, |
312 | {"time", os_time}, | 189 | {"time", os_time}, |
313 | /*{"tmpname", os_tmpname},*/ | 190 | //{"tmpname", os_tmpname}, |
314 | {NULL, NULL} | 191 | {NULL, NULL} |
315 | }; | 192 | }; |
316 | 193 | ||
@@ -318,8 +195,8 @@ static const luaL_Reg syslib[] = { | |||
318 | 195 | ||
319 | 196 | ||
320 | 197 | ||
321 | LUAMOD_API int luaopen_os (lua_State *L) { | 198 | LUALIB_API int luaopen_os (lua_State *L) { |
322 | luaL_newlib(L, syslib); | 199 | luaL_register(L, LUA_OSLIBNAME, syslib); |
323 | return 1; | 200 | return 1; |
324 | } | 201 | } |
325 | 202 | ||
diff --git a/apps/plugins/lua/lparser.c b/apps/plugins/lua/lparser.c index 9e1a9ca2cf..800cdb1a3b 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.130.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 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,13 +27,11 @@ | |||
27 | 27 | ||
28 | 28 | ||
29 | 29 | ||
30 | /* maximum number of local variables per function (must be smaller | ||
31 | than 250, due to the bytecode format) */ | ||
32 | #define MAXVARS 200 | ||
33 | |||
34 | |||
35 | #define hasmultret(k) ((k) == VCALL || (k) == VVARARG) | 30 | #define hasmultret(k) ((k) == VCALL || (k) == VVARARG) |
36 | 31 | ||
32 | #define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) | ||
33 | |||
34 | #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) | ||
37 | 35 | ||
38 | 36 | ||
39 | /* | 37 | /* |
@@ -41,11 +39,10 @@ | |||
41 | */ | 39 | */ |
42 | typedef struct BlockCnt { | 40 | typedef struct BlockCnt { |
43 | struct BlockCnt *previous; /* chain */ | 41 | struct BlockCnt *previous; /* chain */ |
44 | short firstlabel; /* index of first label in this block */ | 42 | int breaklist; /* list of jumps out of this loop */ |
45 | short firstgoto; /* index of first pending goto in this block */ | 43 | lu_byte nactvar; /* # active locals outside the breakable structure */ |
46 | lu_byte nactvar; /* # active locals outside the block */ | ||
47 | lu_byte upval; /* true if some variable in the block is an upvalue */ | 44 | lu_byte upval; /* true if some variable in the block is an upvalue */ |
48 | lu_byte isloop; /* true if `block' is a loop */ | 45 | lu_byte isbreakable; /* true if `block' is a loop */ |
49 | } BlockCnt; | 46 | } BlockCnt; |
50 | 47 | ||
51 | 48 | ||
@@ -53,13 +50,11 @@ typedef struct BlockCnt { | |||
53 | /* | 50 | /* |
54 | ** prototypes for recursive non-terminal functions | 51 | ** prototypes for recursive non-terminal functions |
55 | */ | 52 | */ |
56 | static void statement (LexState *ls); | 53 | static void chunk (LexState *ls); |
57 | static void expr (LexState *ls, expdesc *v); | 54 | static void expr (LexState *ls, expdesc *v); |
58 | 55 | ||
59 | 56 | ||
60 | static void anchor_token (LexState *ls) { | 57 | 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); | ||
63 | if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { | 58 | if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { |
64 | TString *ts = ls->t.seminfo.ts; | 59 | TString *ts = ls->t.seminfo.ts; |
65 | luaX_newstring(ls, getstr(ts), ts->tsv.len); | 60 | luaX_newstring(ls, getstr(ts), ts->tsv.len); |
@@ -67,34 +62,18 @@ static void anchor_token (LexState *ls) { | |||
67 | } | 62 | } |
68 | 63 | ||
69 | 64 | ||
70 | /* semantic error */ | 65 | static void error_expected (LexState *ls, int token) { |
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) { | ||
78 | luaX_syntaxerror(ls, | 66 | luaX_syntaxerror(ls, |
79 | luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); | 67 | luaO_pushfstring(ls->L, LUA_QS " 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); | ||
93 | } | 68 | } |
94 | 69 | ||
95 | 70 | ||
96 | static void checklimit (FuncState *fs, int v, int l, const char *what) { | 71 | static void errorlimit (FuncState *fs, int limit, const char *what) { |
97 | if (v > l) errorlimit(fs, l, what); | 72 | const char *msg = (fs->f->linedefined == 0) ? |
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); | ||
98 | } | 77 | } |
99 | 78 | ||
100 | 79 | ||
@@ -112,7 +91,6 @@ static void check (LexState *ls, int c) { | |||
112 | error_expected(ls, c); | 91 | error_expected(ls, c); |
113 | } | 92 | } |
114 | 93 | ||
115 | |||
116 | static void checknext (LexState *ls, int c) { | 94 | static void checknext (LexState *ls, int c) { |
117 | check(ls, c); | 95 | check(ls, c); |
118 | luaX_next(ls); | 96 | luaX_next(ls); |
@@ -129,7 +107,7 @@ static void check_match (LexState *ls, int what, int who, int where) { | |||
129 | error_expected(ls, what); | 107 | error_expected(ls, what); |
130 | else { | 108 | else { |
131 | luaX_syntaxerror(ls, luaO_pushfstring(ls->L, | 109 | luaX_syntaxerror(ls, luaO_pushfstring(ls->L, |
132 | "%s expected (to close %s at line %d)", | 110 | LUA_QS " expected (to close " LUA_QS " at line %d)", |
133 | luaX_token2str(ls, what), luaX_token2str(ls, who), where)); | 111 | luaX_token2str(ls, what), luaX_token2str(ls, who), where)); |
134 | } | 112 | } |
135 | } | 113 | } |
@@ -148,7 +126,7 @@ static TString *str_checkname (LexState *ls) { | |||
148 | static void init_exp (expdesc *e, expkind k, int i) { | 126 | static void init_exp (expdesc *e, expkind k, int i) { |
149 | e->f = e->t = NO_JUMP; | 127 | e->f = e->t = NO_JUMP; |
150 | e->k = k; | 128 | e->k = k; |
151 | e->u.info = i; | 129 | e->u.s.info = i; |
152 | } | 130 | } |
153 | 131 | ||
154 | 132 | ||
@@ -157,7 +135,7 @@ static void codestring (LexState *ls, expdesc *e, TString *s) { | |||
157 | } | 135 | } |
158 | 136 | ||
159 | 137 | ||
160 | static void checkname (LexState *ls, expdesc *e) { | 138 | static void checkname(LexState *ls, expdesc *e) { |
161 | codestring(ls, e, str_checkname(ls)); | 139 | codestring(ls, e, str_checkname(ls)); |
162 | } | 140 | } |
163 | 141 | ||
@@ -167,7 +145,7 @@ static int registerlocalvar (LexState *ls, TString *varname) { | |||
167 | Proto *f = fs->f; | 145 | Proto *f = fs->f; |
168 | int oldsize = f->sizelocvars; | 146 | int oldsize = f->sizelocvars; |
169 | luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, | 147 | luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, |
170 | LocVar, SHRT_MAX, "local variables"); | 148 | LocVar, SHRT_MAX, "too many local variables"); |
171 | while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; | 149 | while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; |
172 | f->locvars[fs->nlocvars].varname = varname; | 150 | f->locvars[fs->nlocvars].varname = varname; |
173 | luaC_objbarrier(ls->L, f, varname); | 151 | luaC_objbarrier(ls->L, f, varname); |
@@ -175,30 +153,14 @@ static int registerlocalvar (LexState *ls, TString *varname) { | |||
175 | } | 153 | } |
176 | 154 | ||
177 | 155 | ||
178 | static void new_localvar (LexState *ls, TString *name) { | 156 | #define new_localvarliteral(ls,v,n) \ |
179 | FuncState *fs = ls->fs; | 157 | new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) |
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 | } | ||
188 | |||
189 | 158 | ||
190 | static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { | ||
191 | new_localvar(ls, luaX_newstring(ls, name, sz)); | ||
192 | } | ||
193 | 159 | ||
194 | #define new_localvarliteral(ls,v) \ | 160 | static void new_localvar (LexState *ls, TString *name, int n) { |
195 | new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) | 161 | FuncState *fs = ls->fs; |
196 | 162 | luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); | |
197 | 163 | fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); | |
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]; | ||
202 | } | 164 | } |
203 | 165 | ||
204 | 166 | ||
@@ -206,88 +168,77 @@ static void adjustlocalvars (LexState *ls, int nvars) { | |||
206 | FuncState *fs = ls->fs; | 168 | FuncState *fs = ls->fs; |
207 | fs->nactvar = cast_byte(fs->nactvar + nvars); | 169 | fs->nactvar = cast_byte(fs->nactvar + nvars); |
208 | for (; nvars; nvars--) { | 170 | for (; nvars; nvars--) { |
209 | getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; | 171 | getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; |
210 | } | 172 | } |
211 | } | 173 | } |
212 | 174 | ||
213 | 175 | ||
214 | static void removevars (FuncState *fs, int tolevel) { | 176 | static void removevars (LexState *ls, int tolevel) { |
215 | fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); | 177 | FuncState *fs = ls->fs; |
216 | while (fs->nactvar > tolevel) | 178 | while (fs->nactvar > tolevel) |
217 | getlocvar(fs, --fs->nactvar)->endpc = fs->pc; | 179 | getlocvar(fs, --fs->nactvar).endpc = fs->pc; |
218 | } | 180 | } |
219 | 181 | ||
220 | 182 | ||
221 | static int searchupvalue (FuncState *fs, TString *name) { | 183 | static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { |
222 | int i; | 184 | 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) { | ||
232 | Proto *f = fs->f; | 185 | Proto *f = fs->f; |
233 | int oldsize = f->sizeupvalues; | 186 | int oldsize = f->sizeupvalues; |
234 | checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); | 187 | for (i=0; i<f->nups; i++) { |
235 | luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, | 188 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { |
236 | Upvaldesc, MAXUPVAL, "upvalues"); | 189 | lua_assert(f->upvalues[i] == name); |
237 | while (oldsize < f->sizeupvalues) f->upvalues[oldsize++].name = NULL; | 190 | return i; |
238 | f->upvalues[fs->nups].instack = (v->k == VLOCAL); | 191 | } |
239 | f->upvalues[fs->nups].idx = cast_byte(v->u.info); | 192 | } |
240 | f->upvalues[fs->nups].name = name; | 193 | /* new one */ |
241 | luaC_objbarrier(fs->ls->L, f, name); | 194 | luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); |
242 | return fs->nups++; | 195 | luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, |
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++; | ||
243 | } | 204 | } |
244 | 205 | ||
245 | 206 | ||
246 | static int searchvar (FuncState *fs, TString *n) { | 207 | static int searchvar (FuncState *fs, TString *n) { |
247 | int i; | 208 | int i; |
248 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { | 209 | for (i=fs->nactvar-1; i >= 0; i--) { |
249 | if (luaS_eqstr(n, getlocvar(fs, i)->varname)) | 210 | if (n == getlocvar(fs, i).varname) |
250 | return i; | 211 | return i; |
251 | } | 212 | } |
252 | return -1; /* not found */ | 213 | return -1; /* not found */ |
253 | } | 214 | } |
254 | 215 | ||
255 | 216 | ||
256 | /* | ||
257 | Mark block where variable at given level was defined | ||
258 | (to emit close instructions later). | ||
259 | */ | ||
260 | static void markupval (FuncState *fs, int level) { | 217 | static void markupval (FuncState *fs, int level) { |
261 | BlockCnt *bl = fs->bl; | 218 | BlockCnt *bl = fs->bl; |
262 | while (bl->nactvar > level) bl = bl->previous; | 219 | while (bl && bl->nactvar > level) bl = bl->previous; |
263 | bl->upval = 1; | 220 | if (bl) bl->upval = 1; |
264 | } | 221 | } |
265 | 222 | ||
266 | 223 | ||
267 | /* | ||
268 | Find variable with given name 'n'. If it is an upvalue, add this | ||
269 | upvalue into all intermediate functions. | ||
270 | */ | ||
271 | static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | 224 | static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { |
272 | if (fs == NULL) /* no more levels? */ | 225 | if (fs == NULL) { /* no more levels? */ |
273 | return VVOID; /* default is global */ | 226 | init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ |
227 | return VGLOBAL; | ||
228 | } | ||
274 | else { | 229 | else { |
275 | int v = searchvar(fs, n); /* look up locals at current level */ | 230 | int v = searchvar(fs, n); /* look up at current level */ |
276 | if (v >= 0) { /* found? */ | 231 | if (v >= 0) { |
277 | init_exp(var, VLOCAL, v); /* variable is local */ | 232 | init_exp(var, VLOCAL, v); |
278 | if (!base) | 233 | if (!base) |
279 | markupval(fs, v); /* local will be used as an upval */ | 234 | markupval(fs, v); /* local will be used as an upval */ |
280 | return VLOCAL; | 235 | return VLOCAL; |
281 | } | 236 | } |
282 | else { /* not found as local at current level; try upvalues */ | 237 | else { /* not found at current level; try upper one */ |
283 | int idx = searchupvalue(fs, n); /* try existing upvalues */ | 238 | if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) |
284 | if (idx < 0) { /* not found? */ | 239 | return VGLOBAL; |
285 | if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */ | 240 | var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ |
286 | return VVOID; /* not found; is a global */ | 241 | var->k = VUPVAL; /* upvalue in this level */ |
287 | /* else was LOCAL or UPVAL */ | ||
288 | idx = newupvalue(fs, n, var); /* will be a new upvalue */ | ||
289 | } | ||
290 | init_exp(var, VUPVAL, idx); | ||
291 | return VUPVAL; | 242 | return VUPVAL; |
292 | } | 243 | } |
293 | } | 244 | } |
@@ -297,13 +248,8 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | |||
297 | static void singlevar (LexState *ls, expdesc *var) { | 248 | static void singlevar (LexState *ls, expdesc *var) { |
298 | TString *varname = str_checkname(ls); | 249 | TString *varname = str_checkname(ls); |
299 | FuncState *fs = ls->fs; | 250 | FuncState *fs = ls->fs; |
300 | if (singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */ | 251 | if (singlevaraux(fs, varname, var, 1) == VGLOBAL) |
301 | expdesc key; | 252 | var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ |
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 | } | ||
307 | } | 253 | } |
308 | 254 | ||
309 | 255 | ||
@@ -328,118 +274,18 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | |||
328 | 274 | ||
329 | 275 | ||
330 | static void enterlevel (LexState *ls) { | 276 | static void enterlevel (LexState *ls) { |
331 | lua_State *L = ls->L; | 277 | if (++ls->L->nCcalls > LUAI_MAXCCALLS) |
332 | ++L->nCcalls; | 278 | luaX_lexerror(ls, "chunk has too many syntax levels", 0); |
333 | checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); | ||
334 | } | 279 | } |
335 | 280 | ||
336 | 281 | ||
337 | #define leavelevel(ls) ((ls)->L->nCcalls--) | 282 | #define leavelevel(ls) ((ls)->L->nCcalls--) |
338 | 283 | ||
339 | 284 | ||
340 | static void closegoto (LexState *ls, int g, Labeldesc *label) { | 285 | static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { |
341 | int i; | 286 | bl->breaklist = NO_JUMP; |
342 | FuncState *fs = ls->fs; | 287 | bl->isbreakable = isbreakable; |
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; | ||
440 | bl->nactvar = fs->nactvar; | 288 | bl->nactvar = fs->nactvar; |
441 | bl->firstlabel = fs->ls->dyd->label.n; | ||
442 | bl->firstgoto = fs->ls->dyd->gt.n; | ||
443 | bl->upval = 0; | 289 | bl->upval = 0; |
444 | bl->previous = fs->bl; | 290 | bl->previous = fs->bl; |
445 | fs->bl = bl; | 291 | fs->bl = bl; |
@@ -447,108 +293,63 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { | |||
447 | } | 293 | } |
448 | 294 | ||
449 | 295 | ||
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 | |||
472 | static void leaveblock (FuncState *fs) { | 296 | static void leaveblock (FuncState *fs) { |
473 | BlockCnt *bl = fs->bl; | 297 | 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 */ | ||
483 | fs->bl = bl->previous; | 298 | fs->bl = bl->previous; |
484 | removevars(fs, bl->nactvar); | 299 | removevars(fs->ls, 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); | ||
485 | lua_assert(bl->nactvar == fs->nactvar); | 304 | lua_assert(bl->nactvar == fs->nactvar); |
486 | fs->freereg = fs->nactvar; /* free registers */ | 305 | fs->freereg = fs->nactvar; /* free registers */ |
487 | ls->dyd->label.n = bl->firstlabel; /* remove local labels */ | 306 | luaK_patchtohere(fs, bl->breaklist); |
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 */ | ||
492 | } | 307 | } |
493 | 308 | ||
494 | 309 | ||
495 | /* | 310 | static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { |
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; | ||
501 | FuncState *fs = ls->fs; | 311 | FuncState *fs = ls->fs; |
502 | Proto *f = fs->f; /* prototype of current function */ | 312 | Proto *f = fs->f; |
503 | if (fs->np >= f->sizep) { | 313 | int oldsize = f->sizep; |
504 | int oldsize = f->sizep; | 314 | int i; |
505 | luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); | 315 | luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, |
506 | while (oldsize < f->sizep) f->p[oldsize++] = NULL; | 316 | MAXARG_Bx, "constant table overflow"); |
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); | ||
507 | } | 324 | } |
508 | f->p[fs->np++] = clp = luaF_newproto(L); | ||
509 | luaC_objbarrier(L, f, clp); | ||
510 | return clp; | ||
511 | } | 325 | } |
512 | 326 | ||
513 | 327 | ||
514 | /* | 328 | static void lparser_open_func (LexState *ls, FuncState *fs) { |
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) { | ||
528 | lua_State *L = ls->L; | 329 | lua_State *L = ls->L; |
529 | Proto *f; | 330 | Proto *f = luaF_newproto(L); |
331 | fs->f = f; | ||
530 | fs->prev = ls->fs; /* linked list of funcstates */ | 332 | fs->prev = ls->fs; /* linked list of funcstates */ |
531 | fs->ls = ls; | 333 | fs->ls = ls; |
334 | fs->L = L; | ||
532 | ls->fs = fs; | 335 | ls->fs = fs; |
533 | fs->pc = 0; | 336 | fs->pc = 0; |
534 | fs->lasttarget = 0; | 337 | fs->lasttarget = -1; |
535 | fs->jpc = NO_JUMP; | 338 | fs->jpc = NO_JUMP; |
536 | fs->freereg = 0; | 339 | fs->freereg = 0; |
537 | fs->nk = 0; | 340 | fs->nk = 0; |
538 | fs->np = 0; | 341 | fs->np = 0; |
539 | fs->nups = 0; | ||
540 | fs->nlocvars = 0; | 342 | fs->nlocvars = 0; |
541 | fs->nactvar = 0; | 343 | fs->nactvar = 0; |
542 | fs->firstlocal = ls->dyd->actvar.n; | ||
543 | fs->bl = NULL; | 344 | fs->bl = NULL; |
544 | f = fs->f; | ||
545 | f->source = ls->source; | 345 | f->source = ls->source; |
546 | f->maxstacksize = 2; /* registers 0/1 are always valid */ | 346 | f->maxstacksize = 2; /* registers 0/1 are always valid */ |
547 | fs->h = luaH_new(L); | 347 | fs->h = luaH_new(L, 0, 0); |
548 | /* anchor table of constants (to avoid being collected) */ | 348 | /* anchor table of constants and prototype (to avoid being collected) */ |
549 | sethvalue2s(L, L->top, fs->h); | 349 | sethvalue2s(L, L->top, fs->h); |
550 | incr_top(L); | 350 | incr_top(L); |
551 | enterblock(fs, bl, 0); | 351 | setptvalue2s(L, L->top, f); |
352 | incr_top(L); | ||
552 | } | 353 | } |
553 | 354 | ||
554 | 355 | ||
@@ -556,8 +357,8 @@ static void close_func (LexState *ls) { | |||
556 | lua_State *L = ls->L; | 357 | lua_State *L = ls->L; |
557 | FuncState *fs = ls->fs; | 358 | FuncState *fs = ls->fs; |
558 | Proto *f = fs->f; | 359 | Proto *f = fs->f; |
360 | removevars(ls, 0); | ||
559 | luaK_ret(fs, 0, 0); /* final return */ | 361 | luaK_ret(fs, 0, 0); /* final return */ |
560 | leaveblock(fs); | ||
561 | luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); | 362 | luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); |
562 | f->sizecode = fs->pc; | 363 | f->sizecode = fs->pc; |
563 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); | 364 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); |
@@ -568,14 +369,32 @@ static void close_func (LexState *ls) { | |||
568 | f->sizep = fs->np; | 369 | f->sizep = fs->np; |
569 | luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); | 370 | luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); |
570 | f->sizelocvars = fs->nlocvars; | 371 | f->sizelocvars = fs->nlocvars; |
571 | luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); | 372 | luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); |
572 | f->sizeupvalues = fs->nups; | 373 | f->sizeupvalues = f->nups; |
374 | lua_assert(luaG_checkcode(f)); | ||
573 | lua_assert(fs->bl == NULL); | 375 | lua_assert(fs->bl == NULL); |
574 | ls->fs = fs->prev; | 376 | ls->fs = fs->prev; |
575 | /* last token read was anchored in defunct function; must re-anchor it */ | 377 | L->top -= 2; /* remove table and prototype from the stack */ |
576 | anchor_token(ls); | 378 | /* last token read was anchored in defunct function; must reanchor it */ |
577 | L->top--; /* pop table of constants */ | 379 | if (fs) anchor_token(ls); |
578 | luaC_checkGC(L); | 380 | } |
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; | ||
579 | } | 398 | } |
580 | 399 | ||
581 | 400 | ||
@@ -585,39 +404,11 @@ static void close_func (LexState *ls) { | |||
585 | /*============================================================*/ | 404 | /*============================================================*/ |
586 | 405 | ||
587 | 406 | ||
588 | /* | 407 | static void field (LexState *ls, expdesc *v) { |
589 | ** check whether current token is in the follow set of a block. | 408 | /* field -> ['.' | ':'] NAME */ |
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 */ | ||
618 | FuncState *fs = ls->fs; | 409 | FuncState *fs = ls->fs; |
619 | expdesc key; | 410 | expdesc key; |
620 | luaK_exp2anyregup(fs, v); | 411 | luaK_exp2anyreg(fs, v); |
621 | luaX_next(ls); /* skip the dot or colon */ | 412 | luaX_next(ls); /* skip the dot or colon */ |
622 | checkname(ls, &key); | 413 | checkname(ls, &key); |
623 | luaK_indexed(fs, v, &key); | 414 | luaK_indexed(fs, v, &key); |
@@ -656,7 +447,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) { | |||
656 | expdesc key, val; | 447 | expdesc key, val; |
657 | int rkkey; | 448 | int rkkey; |
658 | if (ls->t.token == TK_NAME) { | 449 | if (ls->t.token == TK_NAME) { |
659 | checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); | 450 | luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); |
660 | checkname(ls, &key); | 451 | checkname(ls, &key); |
661 | } | 452 | } |
662 | else /* ls->t.token == '[' */ | 453 | else /* ls->t.token == '[' */ |
@@ -665,7 +456,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) { | |||
665 | checknext(ls, '='); | 456 | checknext(ls, '='); |
666 | rkkey = luaK_exp2RK(fs, &key); | 457 | rkkey = luaK_exp2RK(fs, &key); |
667 | expr(ls, &val); | 458 | expr(ls, &val); |
668 | luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); | 459 | luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); |
669 | fs->freereg = reg; /* free registers */ | 460 | fs->freereg = reg; /* free registers */ |
670 | } | 461 | } |
671 | 462 | ||
@@ -675,7 +466,7 @@ static void closelistfield (FuncState *fs, struct ConsControl *cc) { | |||
675 | luaK_exp2nextreg(fs, &cc->v); | 466 | luaK_exp2nextreg(fs, &cc->v); |
676 | cc->v.k = VVOID; | 467 | cc->v.k = VVOID; |
677 | if (cc->tostore == LFIELDS_PER_FLUSH) { | 468 | if (cc->tostore == LFIELDS_PER_FLUSH) { |
678 | luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ | 469 | luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ |
679 | cc->tostore = 0; /* no more items pending */ | 470 | cc->tostore = 0; /* no more items pending */ |
680 | } | 471 | } |
681 | } | 472 | } |
@@ -685,51 +476,27 @@ static void lastlistfield (FuncState *fs, struct ConsControl *cc) { | |||
685 | if (cc->tostore == 0) return; | 476 | if (cc->tostore == 0) return; |
686 | if (hasmultret(cc->v.k)) { | 477 | if (hasmultret(cc->v.k)) { |
687 | luaK_setmultret(fs, &cc->v); | 478 | luaK_setmultret(fs, &cc->v); |
688 | luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET); | 479 | luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); |
689 | cc->na--; /* do not count last expression (unknown number of elements) */ | 480 | cc->na--; /* do not count last expression (unknown number of elements) */ |
690 | } | 481 | } |
691 | else { | 482 | else { |
692 | if (cc->v.k != VVOID) | 483 | if (cc->v.k != VVOID) |
693 | luaK_exp2nextreg(fs, &cc->v); | 484 | luaK_exp2nextreg(fs, &cc->v); |
694 | luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); | 485 | luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); |
695 | } | 486 | } |
696 | } | 487 | } |
697 | 488 | ||
698 | 489 | ||
699 | static void listfield (LexState *ls, struct ConsControl *cc) { | 490 | static void listfield (LexState *ls, struct ConsControl *cc) { |
700 | /* listfield -> exp */ | ||
701 | expr(ls, &cc->v); | 491 | expr(ls, &cc->v); |
702 | checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); | 492 | luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); |
703 | cc->na++; | 493 | cc->na++; |
704 | cc->tostore++; | 494 | cc->tostore++; |
705 | } | 495 | } |
706 | 496 | ||
707 | 497 | ||
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 | |||
730 | static void constructor (LexState *ls, expdesc *t) { | 498 | static void constructor (LexState *ls, expdesc *t) { |
731 | /* constructor -> '{' [ field { sep field } [sep] ] '}' | 499 | /* constructor -> ?? */ |
732 | sep -> ',' | ';' */ | ||
733 | FuncState *fs = ls->fs; | 500 | FuncState *fs = ls->fs; |
734 | int line = ls->linenumber; | 501 | int line = ls->linenumber; |
735 | int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); | 502 | int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); |
@@ -738,13 +505,30 @@ static void constructor (LexState *ls, expdesc *t) { | |||
738 | cc.t = t; | 505 | cc.t = t; |
739 | init_exp(t, VRELOCABLE, pc); | 506 | init_exp(t, VRELOCABLE, pc); |
740 | init_exp(&cc.v, VVOID, 0); /* no value (yet) */ | 507 | init_exp(&cc.v, VVOID, 0); /* no value (yet) */ |
741 | luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ | 508 | luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ |
742 | checknext(ls, '{'); | 509 | checknext(ls, '{'); |
743 | do { | 510 | do { |
744 | lua_assert(cc.v.k == VVOID || cc.tostore > 0); | 511 | lua_assert(cc.v.k == VVOID || cc.tostore > 0); |
745 | if (ls->t.token == '}') break; | 512 | if (ls->t.token == '}') break; |
746 | closelistfield(fs, &cc); | 513 | closelistfield(fs, &cc); |
747 | field(ls, &cc); | 514 | switch(ls->t.token) { |
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 | } | ||
748 | } while (testnext(ls, ',') || testnext(ls, ';')); | 532 | } while (testnext(ls, ',') || testnext(ls, ';')); |
749 | check_match(ls, '}', '{', line); | 533 | check_match(ls, '}', '{', line); |
750 | lastlistfield(fs, &cc); | 534 | lastlistfield(fs, &cc); |
@@ -766,13 +550,17 @@ static void parlist (LexState *ls) { | |||
766 | do { | 550 | do { |
767 | switch (ls->t.token) { | 551 | switch (ls->t.token) { |
768 | case TK_NAME: { /* param -> NAME */ | 552 | case TK_NAME: { /* param -> NAME */ |
769 | new_localvar(ls, str_checkname(ls)); | 553 | new_localvar(ls, str_checkname(ls), nparams++); |
770 | nparams++; | ||
771 | break; | 554 | break; |
772 | } | 555 | } |
773 | case TK_DOTS: { /* param -> `...' */ | 556 | case TK_DOTS: { /* param -> `...' */ |
774 | luaX_next(ls); | 557 | luaX_next(ls); |
775 | f->is_vararg = 1; | 558 | #if defined(LUA_COMPAT_VARARG) |
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; | ||
776 | break; | 564 | break; |
777 | } | 565 | } |
778 | default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected"); | 566 | default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected"); |
@@ -780,35 +568,33 @@ static void parlist (LexState *ls) { | |||
780 | } while (!f->is_vararg && testnext(ls, ',')); | 568 | } while (!f->is_vararg && testnext(ls, ',')); |
781 | } | 569 | } |
782 | adjustlocalvars(ls, nparams); | 570 | adjustlocalvars(ls, nparams); |
783 | f->numparams = cast_byte(fs->nactvar); | 571 | f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); |
784 | luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ | 572 | luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ |
785 | } | 573 | } |
786 | 574 | ||
787 | 575 | ||
788 | static void body (LexState *ls, expdesc *e, int ismethod, int line) { | 576 | static void body (LexState *ls, expdesc *e, int needself, int line) { |
789 | /* body -> `(' parlist `)' block END */ | 577 | /* body -> `(' parlist `)' chunk END */ |
790 | FuncState new_fs; | 578 | FuncState new_fs; |
791 | BlockCnt bl; | 579 | lparser_open_func(ls, &new_fs); |
792 | new_fs.f = addprototype(ls); | ||
793 | new_fs.f->linedefined = line; | 580 | new_fs.f->linedefined = line; |
794 | open_func(ls, &new_fs, &bl); | ||
795 | checknext(ls, '('); | 581 | checknext(ls, '('); |
796 | if (ismethod) { | 582 | if (needself) { |
797 | new_localvarliteral(ls, "self"); /* create 'self' parameter */ | 583 | new_localvarliteral(ls, "self", 0); |
798 | adjustlocalvars(ls, 1); | 584 | adjustlocalvars(ls, 1); |
799 | } | 585 | } |
800 | parlist(ls); | 586 | parlist(ls); |
801 | checknext(ls, ')'); | 587 | checknext(ls, ')'); |
802 | statlist(ls); | 588 | chunk(ls); |
803 | new_fs.f->lastlinedefined = ls->linenumber; | 589 | new_fs.f->lastlinedefined = ls->linenumber; |
804 | check_match(ls, TK_END, TK_FUNCTION, line); | 590 | check_match(ls, TK_END, TK_FUNCTION, line); |
805 | codeclosure(ls, e); | ||
806 | close_func(ls); | 591 | close_func(ls); |
592 | pushclosure(ls, &new_fs, e); | ||
807 | } | 593 | } |
808 | 594 | ||
809 | 595 | ||
810 | static int explist (LexState *ls, expdesc *v) { | 596 | static int explist1 (LexState *ls, expdesc *v) { |
811 | /* explist -> expr { `,' expr } */ | 597 | /* explist1 -> expr { `,' expr } */ |
812 | int n = 1; /* at least one expression */ | 598 | int n = 1; /* at least one expression */ |
813 | expr(ls, v); | 599 | expr(ls, v); |
814 | while (testnext(ls, ',')) { | 600 | while (testnext(ls, ',')) { |
@@ -820,17 +606,20 @@ static int explist (LexState *ls, expdesc *v) { | |||
820 | } | 606 | } |
821 | 607 | ||
822 | 608 | ||
823 | static void funcargs (LexState *ls, expdesc *f, int line) { | 609 | static void funcargs (LexState *ls, expdesc *f) { |
824 | FuncState *fs = ls->fs; | 610 | FuncState *fs = ls->fs; |
825 | expdesc args; | 611 | expdesc args; |
826 | int base, nparams; | 612 | int base, nparams; |
613 | int line = ls->linenumber; | ||
827 | switch (ls->t.token) { | 614 | switch (ls->t.token) { |
828 | case '(': { /* funcargs -> `(' [ explist ] `)' */ | 615 | case '(': { /* funcargs -> `(' [ explist1 ] `)' */ |
616 | if (line != ls->lastline) | ||
617 | luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); | ||
829 | luaX_next(ls); | 618 | luaX_next(ls); |
830 | if (ls->t.token == ')') /* arg list is empty? */ | 619 | if (ls->t.token == ')') /* arg list is empty? */ |
831 | args.k = VVOID; | 620 | args.k = VVOID; |
832 | else { | 621 | else { |
833 | explist(ls, &args); | 622 | explist1(ls, &args); |
834 | luaK_setmultret(fs, &args); | 623 | luaK_setmultret(fs, &args); |
835 | } | 624 | } |
836 | check_match(ls, ')', '(', line); | 625 | check_match(ls, ')', '(', line); |
@@ -847,10 +636,11 @@ static void funcargs (LexState *ls, expdesc *f, int line) { | |||
847 | } | 636 | } |
848 | default: { | 637 | default: { |
849 | luaX_syntaxerror(ls, "function arguments expected"); | 638 | luaX_syntaxerror(ls, "function arguments expected"); |
639 | return; | ||
850 | } | 640 | } |
851 | } | 641 | } |
852 | lua_assert(f->k == VNONRELOC); | 642 | lua_assert(f->k == VNONRELOC); |
853 | base = f->u.info; /* base register for call */ | 643 | base = f->u.s.info; /* base register for call */ |
854 | if (hasmultret(args.k)) | 644 | if (hasmultret(args.k)) |
855 | nparams = LUA_MULTRET; /* open call */ | 645 | nparams = LUA_MULTRET; /* open call */ |
856 | else { | 646 | else { |
@@ -874,8 +664,8 @@ static void funcargs (LexState *ls, expdesc *f, int line) { | |||
874 | */ | 664 | */ |
875 | 665 | ||
876 | 666 | ||
877 | static void primaryexp (LexState *ls, expdesc *v) { | 667 | static void prefixexp (LexState *ls, expdesc *v) { |
878 | /* primaryexp -> NAME | '(' expr ')' */ | 668 | /* prefixexp -> NAME | '(' expr ')' */ |
879 | switch (ls->t.token) { | 669 | switch (ls->t.token) { |
880 | case '(': { | 670 | case '(': { |
881 | int line = ls->linenumber; | 671 | int line = ls->linenumber; |
@@ -891,26 +681,26 @@ static void primaryexp (LexState *ls, expdesc *v) { | |||
891 | } | 681 | } |
892 | default: { | 682 | default: { |
893 | luaX_syntaxerror(ls, "unexpected symbol"); | 683 | luaX_syntaxerror(ls, "unexpected symbol"); |
684 | return; | ||
894 | } | 685 | } |
895 | } | 686 | } |
896 | } | 687 | } |
897 | 688 | ||
898 | 689 | ||
899 | static void suffixedexp (LexState *ls, expdesc *v) { | 690 | static void primaryexp (LexState *ls, expdesc *v) { |
900 | /* suffixedexp -> | 691 | /* primaryexp -> |
901 | primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ | 692 | prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ |
902 | FuncState *fs = ls->fs; | 693 | FuncState *fs = ls->fs; |
903 | int line = ls->linenumber; | 694 | prefixexp(ls, v); |
904 | primaryexp(ls, v); | ||
905 | for (;;) { | 695 | for (;;) { |
906 | switch (ls->t.token) { | 696 | switch (ls->t.token) { |
907 | case '.': { /* fieldsel */ | 697 | case '.': { /* field */ |
908 | fieldsel(ls, v); | 698 | field(ls, v); |
909 | break; | 699 | break; |
910 | } | 700 | } |
911 | case '[': { /* `[' exp1 `]' */ | 701 | case '[': { /* `[' exp1 `]' */ |
912 | expdesc key; | 702 | expdesc key; |
913 | luaK_exp2anyregup(fs, v); | 703 | luaK_exp2anyreg(fs, v); |
914 | yindex(ls, &key); | 704 | yindex(ls, &key); |
915 | luaK_indexed(fs, v, &key); | 705 | luaK_indexed(fs, v, &key); |
916 | break; | 706 | break; |
@@ -920,12 +710,12 @@ static void suffixedexp (LexState *ls, expdesc *v) { | |||
920 | luaX_next(ls); | 710 | luaX_next(ls); |
921 | checkname(ls, &key); | 711 | checkname(ls, &key); |
922 | luaK_self(fs, v, &key); | 712 | luaK_self(fs, v, &key); |
923 | funcargs(ls, v, line); | 713 | funcargs(ls, v); |
924 | break; | 714 | break; |
925 | } | 715 | } |
926 | case '(': case TK_STRING: case '{': { /* funcargs */ | 716 | case '(': case TK_STRING: case '{': { /* funcargs */ |
927 | luaK_exp2nextreg(fs, v); | 717 | luaK_exp2nextreg(fs, v); |
928 | funcargs(ls, v, line); | 718 | funcargs(ls, v); |
929 | break; | 719 | break; |
930 | } | 720 | } |
931 | default: return; | 721 | default: return; |
@@ -935,8 +725,8 @@ static void suffixedexp (LexState *ls, expdesc *v) { | |||
935 | 725 | ||
936 | 726 | ||
937 | static void simpleexp (LexState *ls, expdesc *v) { | 727 | static void simpleexp (LexState *ls, expdesc *v) { |
938 | /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | | 728 | /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | |
939 | constructor | FUNCTION body | suffixedexp */ | 729 | constructor | FUNCTION body | primaryexp */ |
940 | switch (ls->t.token) { | 730 | switch (ls->t.token) { |
941 | case TK_NUMBER: { | 731 | case TK_NUMBER: { |
942 | init_exp(v, VKNUM, 0); | 732 | init_exp(v, VKNUM, 0); |
@@ -963,6 +753,7 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
963 | FuncState *fs = ls->fs; | 753 | FuncState *fs = ls->fs; |
964 | check_condition(ls, fs->f->is_vararg, | 754 | check_condition(ls, fs->f->is_vararg, |
965 | "cannot use " LUA_QL("...") " outside a vararg function"); | 755 | "cannot use " LUA_QL("...") " outside a vararg function"); |
756 | fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ | ||
966 | init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); | 757 | init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); |
967 | break; | 758 | break; |
968 | } | 759 | } |
@@ -976,7 +767,7 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
976 | return; | 767 | return; |
977 | } | 768 | } |
978 | default: { | 769 | default: { |
979 | suffixedexp(ls, v); | 770 | primaryexp(ls, v); |
980 | return; | 771 | return; |
981 | } | 772 | } |
982 | } | 773 | } |
@@ -1020,11 +811,11 @@ static const struct { | |||
1020 | lu_byte left; /* left priority for each binary operator */ | 811 | lu_byte left; /* left priority for each binary operator */ |
1021 | lu_byte right; /* right priority */ | 812 | lu_byte right; /* right priority */ |
1022 | } priority[] = { /* ORDER OPR */ | 813 | } priority[] = { /* ORDER OPR */ |
1023 | {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `*' `/' `%' */ | 814 | {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ |
1024 | {10, 9}, {5, 4}, /* ^, .. (right associative) */ | 815 | {10, 9}, {5, 4}, /* power and concat (right associative) */ |
1025 | {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ | 816 | {3, 3}, {3, 3}, /* equality and inequality */ |
1026 | {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ | 817 | {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ |
1027 | {2, 2}, {1, 1} /* and, or */ | 818 | {2, 2}, {1, 1} /* logical (and/or) */ |
1028 | }; | 819 | }; |
1029 | 820 | ||
1030 | #define UNARY_PRIORITY 8 /* priority for unary operators */ | 821 | #define UNARY_PRIORITY 8 /* priority for unary operators */ |
@@ -1034,16 +825,15 @@ static const struct { | |||
1034 | ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } | 825 | ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } |
1035 | ** where `binop' is any binary operator with a priority higher than `limit' | 826 | ** where `binop' is any binary operator with a priority higher than `limit' |
1036 | */ | 827 | */ |
1037 | static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { | 828 | static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { |
1038 | BinOpr op; | 829 | BinOpr op; |
1039 | UnOpr uop; | 830 | UnOpr uop; |
1040 | enterlevel(ls); | 831 | enterlevel(ls); |
1041 | uop = getunopr(ls->t.token); | 832 | uop = getunopr(ls->t.token); |
1042 | if (uop != OPR_NOUNOPR) { | 833 | if (uop != OPR_NOUNOPR) { |
1043 | int line = ls->linenumber; | ||
1044 | luaX_next(ls); | 834 | luaX_next(ls); |
1045 | subexpr(ls, v, UNARY_PRIORITY); | 835 | subexpr(ls, v, UNARY_PRIORITY); |
1046 | luaK_prefix(ls->fs, uop, v, line); | 836 | luaK_prefix(ls->fs, uop, v); |
1047 | } | 837 | } |
1048 | else simpleexp(ls, v); | 838 | else simpleexp(ls, v); |
1049 | /* expand while operators have priorities higher than `limit' */ | 839 | /* expand while operators have priorities higher than `limit' */ |
@@ -1051,12 +841,11 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { | |||
1051 | while (op != OPR_NOBINOPR && priority[op].left > limit) { | 841 | while (op != OPR_NOBINOPR && priority[op].left > limit) { |
1052 | expdesc v2; | 842 | expdesc v2; |
1053 | BinOpr nextop; | 843 | BinOpr nextop; |
1054 | int line = ls->linenumber; | ||
1055 | luaX_next(ls); | 844 | luaX_next(ls); |
1056 | luaK_infix(ls->fs, op, v); | 845 | luaK_infix(ls->fs, op, v); |
1057 | /* read sub-expression with higher priority */ | 846 | /* read sub-expression with higher priority */ |
1058 | nextop = subexpr(ls, &v2, priority[op].right); | 847 | nextop = subexpr(ls, &v2, priority[op].right); |
1059 | luaK_posfix(ls->fs, op, v, &v2, line); | 848 | luaK_posfix(ls->fs, op, v, &v2); |
1060 | op = nextop; | 849 | op = nextop; |
1061 | } | 850 | } |
1062 | leavelevel(ls); | 851 | leavelevel(ls); |
@@ -1079,12 +868,23 @@ static void expr (LexState *ls, expdesc *v) { | |||
1079 | */ | 868 | */ |
1080 | 869 | ||
1081 | 870 | ||
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 | |||
1082 | static void block (LexState *ls) { | 881 | static void block (LexState *ls) { |
1083 | /* block -> statlist */ | 882 | /* block -> chunk */ |
1084 | FuncState *fs = ls->fs; | 883 | FuncState *fs = ls->fs; |
1085 | BlockCnt bl; | 884 | BlockCnt bl; |
1086 | enterblock(fs, &bl, 0); | 885 | enterblock(fs, &bl, 0); |
1087 | statlist(ls); | 886 | chunk(ls); |
887 | lua_assert(bl.breaklist == NO_JUMP); | ||
1088 | leaveblock(fs); | 888 | leaveblock(fs); |
1089 | } | 889 | } |
1090 | 890 | ||
@@ -1100,34 +900,29 @@ struct LHS_assign { | |||
1100 | 900 | ||
1101 | 901 | ||
1102 | /* | 902 | /* |
1103 | ** check whether, in an assignment to an upvalue/local variable, the | 903 | ** check whether, in an assignment to a local variable, the local variable |
1104 | ** upvalue/local variable is begin used in a previous assignment to a | 904 | ** is needed in a previous assignment (to a table). If so, save original |
1105 | ** table. If so, save original upvalue/local value in a safe place and | 905 | ** local value in a safe place and use this safe copy in the previous |
1106 | ** use this safe copy in the previous assignment. | 906 | ** assignment. |
1107 | */ | 907 | */ |
1108 | static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | 908 | static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { |
1109 | FuncState *fs = ls->fs; | 909 | FuncState *fs = ls->fs; |
1110 | int extra = fs->freereg; /* eventual position to save local variable */ | 910 | int extra = fs->freereg; /* eventual position to save local variable */ |
1111 | int conflict = 0; | 911 | int conflict = 0; |
1112 | for (; lh; lh = lh->prev) { /* check all previous assignments */ | 912 | for (; lh; lh = lh->prev) { |
1113 | if (lh->v.k == VINDEXED) { /* assigning to a table? */ | 913 | if (lh->v.k == VINDEXED) { |
1114 | /* table is the upvalue/local being assigned now? */ | 914 | if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ |
1115 | if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { | ||
1116 | conflict = 1; | 915 | conflict = 1; |
1117 | lh->v.u.ind.vt = VLOCAL; | 916 | lh->v.u.s.info = extra; /* previous assignment will use safe copy */ |
1118 | lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ | ||
1119 | } | 917 | } |
1120 | /* index is the local being assigned? (index cannot be upvalue) */ | 918 | if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ |
1121 | if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { | ||
1122 | conflict = 1; | 919 | conflict = 1; |
1123 | lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ | 920 | lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ |
1124 | } | 921 | } |
1125 | } | 922 | } |
1126 | } | 923 | } |
1127 | if (conflict) { | 924 | if (conflict) { |
1128 | /* copy upvalue/local value to a temporary (in position 'extra') */ | 925 | luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ |
1129 | OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; | ||
1130 | luaK_codeABC(fs, op, extra, v->u.info, 0); | ||
1131 | luaK_reserveregs(fs, 1); | 926 | luaK_reserveregs(fs, 1); |
1132 | } | 927 | } |
1133 | } | 928 | } |
@@ -1135,21 +930,22 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | |||
1135 | 930 | ||
1136 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | 931 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { |
1137 | expdesc e; | 932 | expdesc e; |
1138 | check_condition(ls, vkisvar(lh->v.k), "syntax error"); | 933 | check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, |
1139 | if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ | 934 | "syntax error"); |
935 | if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ | ||
1140 | struct LHS_assign nv; | 936 | struct LHS_assign nv; |
1141 | nv.prev = lh; | 937 | nv.prev = lh; |
1142 | suffixedexp(ls, &nv.v); | 938 | primaryexp(ls, &nv.v); |
1143 | if (nv.v.k != VINDEXED) | 939 | if (nv.v.k == VLOCAL) |
1144 | check_conflict(ls, lh, &nv.v); | 940 | check_conflict(ls, lh, &nv.v); |
1145 | checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, | 941 | luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, |
1146 | "C levels"); | 942 | "variables in assignment"); |
1147 | assignment(ls, &nv, nvars+1); | 943 | assignment(ls, &nv, nvars+1); |
1148 | } | 944 | } |
1149 | else { /* assignment -> `=' explist */ | 945 | else { /* assignment -> `=' explist1 */ |
1150 | int nexps; | 946 | int nexps; |
1151 | checknext(ls, '='); | 947 | checknext(ls, '='); |
1152 | nexps = explist(ls, &e); | 948 | nexps = explist1(ls, &e); |
1153 | if (nexps != nvars) { | 949 | if (nexps != nvars) { |
1154 | adjust_assign(ls, nvars, nexps, &e); | 950 | adjust_assign(ls, nvars, nexps, &e); |
1155 | if (nexps > nvars) | 951 | if (nexps > nvars) |
@@ -1176,57 +972,19 @@ static int cond (LexState *ls) { | |||
1176 | } | 972 | } |
1177 | 973 | ||
1178 | 974 | ||
1179 | static void gotostat (LexState *ls, int pc) { | 975 | static void breakstat (LexState *ls) { |
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 '::' */ | ||
1217 | FuncState *fs = ls->fs; | 976 | FuncState *fs = ls->fs; |
1218 | Labellist *ll = &ls->dyd->label; | 977 | BlockCnt *bl = fs->bl; |
1219 | int l; /* index of new label being created */ | 978 | int upval = 0; |
1220 | checkrepeated(fs, ll, label); /* check for repeated labels */ | 979 | while (bl && !bl->isbreakable) { |
1221 | checknext(ls, TK_DBCOLON); /* skip double colon */ | 980 | upval |= bl->upval; |
1222 | /* create new entry for this label */ | 981 | bl = bl->previous; |
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; | ||
1228 | } | 982 | } |
1229 | findgotos(ls, &ll->arr[l]); | 983 | if (!bl) |
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)); | ||
1230 | } | 988 | } |
1231 | 989 | ||
1232 | 990 | ||
@@ -1242,7 +1000,7 @@ static void whilestat (LexState *ls, int line) { | |||
1242 | enterblock(fs, &bl, 1); | 1000 | enterblock(fs, &bl, 1); |
1243 | checknext(ls, TK_DO); | 1001 | checknext(ls, TK_DO); |
1244 | block(ls); | 1002 | block(ls); |
1245 | luaK_jumpto(fs, whileinit); | 1003 | luaK_patchlist(fs, luaK_jump(fs), whileinit); |
1246 | check_match(ls, TK_END, TK_WHILE, line); | 1004 | check_match(ls, TK_END, TK_WHILE, line); |
1247 | leaveblock(fs); | 1005 | leaveblock(fs); |
1248 | luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ | 1006 | luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ |
@@ -1258,25 +1016,30 @@ static void repeatstat (LexState *ls, int line) { | |||
1258 | enterblock(fs, &bl1, 1); /* loop block */ | 1016 | enterblock(fs, &bl1, 1); /* loop block */ |
1259 | enterblock(fs, &bl2, 0); /* scope block */ | 1017 | enterblock(fs, &bl2, 0); /* scope block */ |
1260 | luaX_next(ls); /* skip REPEAT */ | 1018 | luaX_next(ls); /* skip REPEAT */ |
1261 | statlist(ls); | 1019 | chunk(ls); |
1262 | check_match(ls, TK_UNTIL, TK_REPEAT, line); | 1020 | check_match(ls, TK_UNTIL, TK_REPEAT, line); |
1263 | condexit = cond(ls); /* read condition (inside scope block) */ | 1021 | condexit = cond(ls); /* read condition (inside scope block) */ |
1264 | if (bl2.upval) /* upvalues? */ | 1022 | if (!bl2.upval) { /* no upvalues? */ |
1265 | luaK_patchclose(fs, condexit, bl2.nactvar); | 1023 | leaveblock(fs); /* finish scope */ |
1266 | leaveblock(fs); /* finish scope */ | 1024 | luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ |
1267 | luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ | 1025 | } |
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 | } | ||
1268 | leaveblock(fs); /* finish loop */ | 1032 | leaveblock(fs); /* finish loop */ |
1269 | } | 1033 | } |
1270 | 1034 | ||
1271 | 1035 | ||
1272 | static int exp1 (LexState *ls) { | 1036 | static int exp1 (LexState *ls) { |
1273 | expdesc e; | 1037 | expdesc e; |
1274 | int reg; | 1038 | int k; |
1275 | expr(ls, &e); | 1039 | expr(ls, &e); |
1040 | k = e.k; | ||
1276 | luaK_exp2nextreg(ls->fs, &e); | 1041 | luaK_exp2nextreg(ls->fs, &e); |
1277 | lua_assert(e.k == VNONRELOC); | 1042 | return k; |
1278 | reg = e.u.info; | ||
1279 | return reg; | ||
1280 | } | 1043 | } |
1281 | 1044 | ||
1282 | 1045 | ||
@@ -1294,15 +1057,10 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { | |||
1294 | block(ls); | 1057 | block(ls); |
1295 | leaveblock(fs); /* end of scope for declared variables */ | 1058 | leaveblock(fs); /* end of scope for declared variables */ |
1296 | luaK_patchtohere(fs, prep); | 1059 | luaK_patchtohere(fs, prep); |
1297 | if (isnum) /* numeric for? */ | 1060 | endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : |
1298 | endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); | 1061 | luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); |
1299 | else { /* generic for */ | 1062 | luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ |
1300 | luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); | 1063 | luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); |
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); | ||
1306 | } | 1064 | } |
1307 | 1065 | ||
1308 | 1066 | ||
@@ -1310,10 +1068,10 @@ static void fornum (LexState *ls, TString *varname, int line) { | |||
1310 | /* fornum -> NAME = exp1,exp1[,exp1] forbody */ | 1068 | /* fornum -> NAME = exp1,exp1[,exp1] forbody */ |
1311 | FuncState *fs = ls->fs; | 1069 | FuncState *fs = ls->fs; |
1312 | int base = fs->freereg; | 1070 | int base = fs->freereg; |
1313 | new_localvarliteral(ls, "(for index)"); | 1071 | new_localvarliteral(ls, "(for index)", 0); |
1314 | new_localvarliteral(ls, "(for limit)"); | 1072 | new_localvarliteral(ls, "(for limit)", 1); |
1315 | new_localvarliteral(ls, "(for step)"); | 1073 | new_localvarliteral(ls, "(for step)", 2); |
1316 | new_localvar(ls, varname); | 1074 | new_localvar(ls, varname, 3); |
1317 | checknext(ls, '='); | 1075 | checknext(ls, '='); |
1318 | exp1(ls); /* initial value */ | 1076 | exp1(ls); /* initial value */ |
1319 | checknext(ls, ','); | 1077 | checknext(ls, ','); |
@@ -1321,7 +1079,7 @@ static void fornum (LexState *ls, TString *varname, int line) { | |||
1321 | if (testnext(ls, ',')) | 1079 | if (testnext(ls, ',')) |
1322 | exp1(ls); /* optional step */ | 1080 | exp1(ls); /* optional step */ |
1323 | else { /* default step = 1 */ | 1081 | else { /* default step = 1 */ |
1324 | luaK_codek(fs, fs->freereg, luaK_numberK(fs, 1)); | 1082 | luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); |
1325 | luaK_reserveregs(fs, 1); | 1083 | luaK_reserveregs(fs, 1); |
1326 | } | 1084 | } |
1327 | forbody(ls, base, line, 1, 1); | 1085 | forbody(ls, base, line, 1, 1); |
@@ -1329,25 +1087,23 @@ static void fornum (LexState *ls, TString *varname, int line) { | |||
1329 | 1087 | ||
1330 | 1088 | ||
1331 | static void forlist (LexState *ls, TString *indexname) { | 1089 | static void forlist (LexState *ls, TString *indexname) { |
1332 | /* forlist -> NAME {,NAME} IN explist forbody */ | 1090 | /* forlist -> NAME {,NAME} IN explist1 forbody */ |
1333 | FuncState *fs = ls->fs; | 1091 | FuncState *fs = ls->fs; |
1334 | expdesc e; | 1092 | expdesc e; |
1335 | int nvars = 4; /* gen, state, control, plus at least one declared var */ | 1093 | int nvars = 0; |
1336 | int line; | 1094 | int line; |
1337 | int base = fs->freereg; | 1095 | int base = fs->freereg; |
1338 | /* create control variables */ | 1096 | /* create control variables */ |
1339 | new_localvarliteral(ls, "(for generator)"); | 1097 | new_localvarliteral(ls, "(for generator)", nvars++); |
1340 | new_localvarliteral(ls, "(for state)"); | 1098 | new_localvarliteral(ls, "(for state)", nvars++); |
1341 | new_localvarliteral(ls, "(for control)"); | 1099 | new_localvarliteral(ls, "(for control)", nvars++); |
1342 | /* create declared variables */ | 1100 | /* create declared variables */ |
1343 | new_localvar(ls, indexname); | 1101 | new_localvar(ls, indexname, nvars++); |
1344 | while (testnext(ls, ',')) { | 1102 | while (testnext(ls, ',')) |
1345 | new_localvar(ls, str_checkname(ls)); | 1103 | new_localvar(ls, str_checkname(ls), nvars++); |
1346 | nvars++; | ||
1347 | } | ||
1348 | checknext(ls, TK_IN); | 1104 | checknext(ls, TK_IN); |
1349 | line = ls->linenumber; | 1105 | line = ls->linenumber; |
1350 | adjust_assign(ls, 3, explist(ls, &e), &e); | 1106 | adjust_assign(ls, 3, explist1(ls, &e), &e); |
1351 | luaK_checkstack(fs, 3); /* extra space to call generator */ | 1107 | luaK_checkstack(fs, 3); /* extra space to call generator */ |
1352 | forbody(ls, base, line, nvars - 3, 0); | 1108 | forbody(ls, base, line, nvars - 3, 0); |
1353 | } | 1109 | } |
@@ -1371,77 +1127,65 @@ static void forstat (LexState *ls, int line) { | |||
1371 | } | 1127 | } |
1372 | 1128 | ||
1373 | 1129 | ||
1374 | static void test_then_block (LexState *ls, int *escapelist) { | 1130 | static int test_then_block (LexState *ls) { |
1375 | /* test_then_block -> [IF | ELSEIF] cond THEN block */ | 1131 | /* test_then_block -> [IF | ELSEIF] cond THEN block */ |
1376 | BlockCnt bl; | 1132 | int condexit; |
1377 | FuncState *fs = ls->fs; | ||
1378 | expdesc v; | ||
1379 | int jf; /* instruction to skip 'then' code (if condition is false) */ | ||
1380 | luaX_next(ls); /* skip IF or ELSEIF */ | 1133 | luaX_next(ls); /* skip IF or ELSEIF */ |
1381 | expr(ls, &v); /* read condition */ | 1134 | condexit = cond(ls); |
1382 | checknext(ls, TK_THEN); | 1135 | checknext(ls, TK_THEN); |
1383 | if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { | 1136 | block(ls); /* `then' part */ |
1384 | luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ | 1137 | return condexit; |
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); | ||
1406 | } | 1138 | } |
1407 | 1139 | ||
1408 | 1140 | ||
1409 | static void ifstat (LexState *ls, int line) { | 1141 | static void ifstat (LexState *ls, int line) { |
1410 | /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ | 1142 | /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ |
1411 | FuncState *fs = ls->fs; | 1143 | FuncState *fs = ls->fs; |
1412 | int escapelist = NO_JUMP; /* exit list for finished parts */ | 1144 | int flist; |
1413 | test_then_block(ls, &escapelist); /* IF cond THEN block */ | 1145 | int escapelist = NO_JUMP; |
1414 | while (ls->t.token == TK_ELSEIF) | 1146 | flist = test_then_block(ls); /* IF cond THEN block */ |
1415 | test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ | 1147 | while (ls->t.token == TK_ELSEIF) { |
1416 | if (testnext(ls, TK_ELSE)) | 1148 | luaK_concat(fs, &escapelist, luaK_jump(fs)); |
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) */ | ||
1417 | block(ls); /* `else' part */ | 1156 | block(ls); /* `else' part */ |
1157 | } | ||
1158 | else | ||
1159 | luaK_concat(fs, &escapelist, flist); | ||
1160 | luaK_patchtohere(fs, escapelist); | ||
1418 | check_match(ls, TK_END, TK_IF, line); | 1161 | check_match(ls, TK_END, TK_IF, line); |
1419 | luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ | ||
1420 | } | 1162 | } |
1421 | 1163 | ||
1422 | 1164 | ||
1423 | static void localfunc (LexState *ls) { | 1165 | static void localfunc (LexState *ls) { |
1424 | expdesc b; | 1166 | expdesc v, b; |
1425 | FuncState *fs = ls->fs; | 1167 | FuncState *fs = ls->fs; |
1426 | new_localvar(ls, str_checkname(ls)); /* new local variable */ | 1168 | new_localvar(ls, str_checkname(ls), 0); |
1427 | adjustlocalvars(ls, 1); /* enter its scope */ | 1169 | init_exp(&v, VLOCAL, fs->freereg); |
1428 | body(ls, &b, 0, ls->linenumber); /* function created in next register */ | 1170 | luaK_reserveregs(fs, 1); |
1171 | adjustlocalvars(ls, 1); | ||
1172 | body(ls, &b, 0, ls->linenumber); | ||
1173 | luaK_storevar(fs, &v, &b); | ||
1429 | /* debug information will only see the variable after this point! */ | 1174 | /* debug information will only see the variable after this point! */ |
1430 | getlocvar(fs, b.u.info)->startpc = fs->pc; | 1175 | getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; |
1431 | } | 1176 | } |
1432 | 1177 | ||
1433 | 1178 | ||
1434 | static void localstat (LexState *ls) { | 1179 | static void localstat (LexState *ls) { |
1435 | /* stat -> LOCAL NAME {`,' NAME} [`=' explist] */ | 1180 | /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ |
1436 | int nvars = 0; | 1181 | int nvars = 0; |
1437 | int nexps; | 1182 | int nexps; |
1438 | expdesc e; | 1183 | expdesc e; |
1439 | do { | 1184 | do { |
1440 | new_localvar(ls, str_checkname(ls)); | 1185 | new_localvar(ls, str_checkname(ls), nvars++); |
1441 | nvars++; | ||
1442 | } while (testnext(ls, ',')); | 1186 | } while (testnext(ls, ',')); |
1443 | if (testnext(ls, '=')) | 1187 | if (testnext(ls, '=')) |
1444 | nexps = explist(ls, &e); | 1188 | nexps = explist1(ls, &e); |
1445 | else { | 1189 | else { |
1446 | e.k = VVOID; | 1190 | e.k = VVOID; |
1447 | nexps = 0; | 1191 | nexps = 0; |
@@ -1452,26 +1196,26 @@ static void localstat (LexState *ls) { | |||
1452 | 1196 | ||
1453 | 1197 | ||
1454 | static int funcname (LexState *ls, expdesc *v) { | 1198 | static int funcname (LexState *ls, expdesc *v) { |
1455 | /* funcname -> NAME {fieldsel} [`:' NAME] */ | 1199 | /* funcname -> NAME {field} [`:' NAME] */ |
1456 | int ismethod = 0; | 1200 | int needself = 0; |
1457 | singlevar(ls, v); | 1201 | singlevar(ls, v); |
1458 | while (ls->t.token == '.') | 1202 | while (ls->t.token == '.') |
1459 | fieldsel(ls, v); | 1203 | field(ls, v); |
1460 | if (ls->t.token == ':') { | 1204 | if (ls->t.token == ':') { |
1461 | ismethod = 1; | 1205 | needself = 1; |
1462 | fieldsel(ls, v); | 1206 | field(ls, v); |
1463 | } | 1207 | } |
1464 | return ismethod; | 1208 | return needself; |
1465 | } | 1209 | } |
1466 | 1210 | ||
1467 | 1211 | ||
1468 | static void funcstat (LexState *ls, int line) { | 1212 | static void funcstat (LexState *ls, int line) { |
1469 | /* funcstat -> FUNCTION funcname body */ | 1213 | /* funcstat -> FUNCTION funcname body */ |
1470 | int ismethod; | 1214 | int needself; |
1471 | expdesc v, b; | 1215 | expdesc v, b; |
1472 | luaX_next(ls); /* skip FUNCTION */ | 1216 | luaX_next(ls); /* skip FUNCTION */ |
1473 | ismethod = funcname(ls, &v); | 1217 | needself = funcname(ls, &v); |
1474 | body(ls, &b, ismethod, line); | 1218 | body(ls, &b, needself, line); |
1475 | luaK_storevar(ls->fs, &v, &b); | 1219 | luaK_storevar(ls->fs, &v, &b); |
1476 | luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ | 1220 | luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ |
1477 | } | 1221 | } |
@@ -1481,27 +1225,26 @@ static void exprstat (LexState *ls) { | |||
1481 | /* stat -> func | assignment */ | 1225 | /* stat -> func | assignment */ |
1482 | FuncState *fs = ls->fs; | 1226 | FuncState *fs = ls->fs; |
1483 | struct LHS_assign v; | 1227 | struct LHS_assign v; |
1484 | suffixedexp(ls, &v.v); | 1228 | primaryexp(ls, &v.v); |
1485 | if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ | 1229 | if (v.v.k == VCALL) /* stat -> func */ |
1230 | SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ | ||
1231 | else { /* stat -> assignment */ | ||
1486 | v.prev = NULL; | 1232 | v.prev = NULL; |
1487 | assignment(ls, &v, 1); | 1233 | assignment(ls, &v, 1); |
1488 | } | 1234 | } |
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 | } | ||
1493 | } | 1235 | } |
1494 | 1236 | ||
1495 | 1237 | ||
1496 | static void retstat (LexState *ls) { | 1238 | static void retstat (LexState *ls) { |
1497 | /* stat -> RETURN [explist] [';'] */ | 1239 | /* stat -> RETURN explist */ |
1498 | FuncState *fs = ls->fs; | 1240 | FuncState *fs = ls->fs; |
1499 | expdesc e; | 1241 | expdesc e; |
1500 | int first, nret; /* registers with returned values */ | 1242 | int first, nret; /* registers with returned values */ |
1501 | if (block_follow(ls, 1) || ls->t.token == ';') | 1243 | luaX_next(ls); /* skip RETURN */ |
1244 | if (block_follow(ls->t.token) || ls->t.token == ';') | ||
1502 | first = nret = 0; /* return no values */ | 1245 | first = nret = 0; /* return no values */ |
1503 | else { | 1246 | else { |
1504 | nret = explist(ls, &e); /* optional return values */ | 1247 | nret = explist1(ls, &e); /* optional return values */ |
1505 | if (hasmultret(e.k)) { | 1248 | if (hasmultret(e.k)) { |
1506 | luaK_setmultret(fs, &e); | 1249 | luaK_setmultret(fs, &e); |
1507 | if (e.k == VCALL && nret == 1) { /* tail call? */ | 1250 | if (e.k == VCALL && nret == 1) { /* tail call? */ |
@@ -1522,43 +1265,37 @@ static void retstat (LexState *ls) { | |||
1522 | } | 1265 | } |
1523 | } | 1266 | } |
1524 | luaK_ret(fs, first, nret); | 1267 | luaK_ret(fs, first, nret); |
1525 | testnext(ls, ';'); /* skip optional semicolon */ | ||
1526 | } | 1268 | } |
1527 | 1269 | ||
1528 | 1270 | ||
1529 | static void statement (LexState *ls) { | 1271 | static int statement (LexState *ls) { |
1530 | int line = ls->linenumber; /* may be needed for error messages */ | 1272 | int line = ls->linenumber; /* may be needed for error messages */ |
1531 | enterlevel(ls); | ||
1532 | switch (ls->t.token) { | 1273 | switch (ls->t.token) { |
1533 | case ';': { /* stat -> ';' (empty statement) */ | ||
1534 | luaX_next(ls); /* skip ';' */ | ||
1535 | break; | ||
1536 | } | ||
1537 | case TK_IF: { /* stat -> ifstat */ | 1274 | case TK_IF: { /* stat -> ifstat */ |
1538 | ifstat(ls, line); | 1275 | ifstat(ls, line); |
1539 | break; | 1276 | return 0; |
1540 | } | 1277 | } |
1541 | case TK_WHILE: { /* stat -> whilestat */ | 1278 | case TK_WHILE: { /* stat -> whilestat */ |
1542 | whilestat(ls, line); | 1279 | whilestat(ls, line); |
1543 | break; | 1280 | return 0; |
1544 | } | 1281 | } |
1545 | case TK_DO: { /* stat -> DO block END */ | 1282 | case TK_DO: { /* stat -> DO block END */ |
1546 | luaX_next(ls); /* skip DO */ | 1283 | luaX_next(ls); /* skip DO */ |
1547 | block(ls); | 1284 | block(ls); |
1548 | check_match(ls, TK_END, TK_DO, line); | 1285 | check_match(ls, TK_END, TK_DO, line); |
1549 | break; | 1286 | return 0; |
1550 | } | 1287 | } |
1551 | case TK_FOR: { /* stat -> forstat */ | 1288 | case TK_FOR: { /* stat -> forstat */ |
1552 | forstat(ls, line); | 1289 | forstat(ls, line); |
1553 | break; | 1290 | return 0; |
1554 | } | 1291 | } |
1555 | case TK_REPEAT: { /* stat -> repeatstat */ | 1292 | case TK_REPEAT: { /* stat -> repeatstat */ |
1556 | repeatstat(ls, line); | 1293 | repeatstat(ls, line); |
1557 | break; | 1294 | return 0; |
1558 | } | 1295 | } |
1559 | case TK_FUNCTION: { /* stat -> funcstat */ | 1296 | case TK_FUNCTION: { |
1560 | funcstat(ls, line); | 1297 | funcstat(ls, line); /* stat -> funcstat */ |
1561 | break; | 1298 | return 0; |
1562 | } | 1299 | } |
1563 | case TK_LOCAL: { /* stat -> localstat */ | 1300 | case TK_LOCAL: { /* stat -> localstat */ |
1564 | luaX_next(ls); /* skip LOCAL */ | 1301 | luaX_next(ls); /* skip LOCAL */ |
@@ -1566,73 +1303,37 @@ static void statement (LexState *ls) { | |||
1566 | localfunc(ls); | 1303 | localfunc(ls); |
1567 | else | 1304 | else |
1568 | localstat(ls); | 1305 | localstat(ls); |
1569 | break; | 1306 | return 0; |
1570 | } | ||
1571 | case TK_DBCOLON: { /* stat -> label */ | ||
1572 | luaX_next(ls); /* skip double colon */ | ||
1573 | labelstat(ls, str_checkname(ls), line); | ||
1574 | break; | ||
1575 | } | 1307 | } |
1576 | case TK_RETURN: { /* stat -> retstat */ | 1308 | case TK_RETURN: { /* stat -> retstat */ |
1577 | luaX_next(ls); /* skip RETURN */ | ||
1578 | retstat(ls); | 1309 | retstat(ls); |
1579 | break; | 1310 | return 1; /* must be last statement */ |
1580 | } | 1311 | } |
1581 | case TK_BREAK: /* stat -> breakstat */ | 1312 | case TK_BREAK: { /* stat -> breakstat */ |
1582 | case TK_GOTO: { /* stat -> 'goto' NAME */ | 1313 | luaX_next(ls); /* skip BREAK */ |
1583 | gotostat(ls, luaK_jump(ls->fs)); | 1314 | breakstat(ls); |
1584 | break; | 1315 | return 1; /* must be last statement */ |
1585 | } | 1316 | } |
1586 | default: { /* stat -> func | assignment */ | 1317 | default: { |
1587 | exprstat(ls); | 1318 | exprstat(ls); |
1588 | break; | 1319 | return 0; /* to avoid warnings */ |
1589 | } | 1320 | } |
1590 | } | 1321 | } |
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); | ||
1595 | } | ||
1596 | |||
1597 | /* }====================================================================== */ | ||
1598 | |||
1599 | |||
1600 | /* | ||
1601 | ** compiles the main function, which is a regular vararg function with an | ||
1602 | ** upvalue named LUA_ENV | ||
1603 | */ | ||
1604 | static void mainfunc (LexState *ls, FuncState *fs) { | ||
1605 | BlockCnt bl; | ||
1606 | expdesc v; | ||
1607 | open_func(ls, fs, &bl); | ||
1608 | fs->f->is_vararg = 1; /* main function is always vararg */ | ||
1609 | init_exp(&v, VLOCAL, 0); /* create and... */ | ||
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 | } | 1322 | } |
1616 | 1323 | ||
1617 | 1324 | ||
1618 | Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | 1325 | static void chunk (LexState *ls) { |
1619 | Dyndata *dyd, const char *name, int firstchar) { | 1326 | /* chunk -> { stat [`;'] } */ |
1620 | LexState lexstate; | 1327 | int islast = 0; |
1621 | FuncState funcstate; | 1328 | enterlevel(ls); |
1622 | Closure *cl = luaF_newLclosure(L, 1); /* create main closure */ | 1329 | while (!islast && !block_follow(ls->t.token)) { |
1623 | /* anchor closure (to avoid being collected) */ | 1330 | islast = statement(ls); |
1624 | setclLvalue(L, L->top, cl); | 1331 | testnext(ls, ';'); |
1625 | incr_top(L); | 1332 | lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && |
1626 | funcstate.f = cl->l.p = luaF_newproto(L); | 1333 | ls->fs->freereg >= ls->fs->nactvar); |
1627 | funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ | 1334 | ls->fs->freereg = ls->fs->nactvar; /* free registers */ |
1628 | lexstate.buff = buff; | 1335 | } |
1629 | lexstate.dyd = dyd; | 1336 | leavelevel(ls); |
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 */ | ||
1637 | } | 1337 | } |
1638 | 1338 | ||
1339 | /* }====================================================================== */ | ||
diff --git a/apps/plugins/lua/lparser.h b/apps/plugins/lua/lparser.h index 0346e3c41a..f9b8e24913 100644 --- a/apps/plugins/lua/lparser.h +++ b/apps/plugins/lua/lparser.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.h,v 1.70.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -23,72 +23,34 @@ 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 */ | ||
27 | VLOCAL, /* info = local register */ | 26 | VLOCAL, /* info = local register */ |
28 | VUPVAL, /* info = index of upvalue in 'upvalues' */ | 27 | VUPVAL, /* info = index of upvalue in `upvalues' */ |
29 | VINDEXED, /* t = table register/upvalue; idx = index R/K */ | 28 | VGLOBAL, /* info = index of table; aux = index of global name in `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 */ | ||
32 | VCALL, /* info = instruction pc */ | 33 | VCALL, /* info = instruction pc */ |
33 | VVARARG /* info = instruction pc */ | 34 | VVARARG /* info = instruction pc */ |
34 | } expkind; | 35 | } expkind; |
35 | 36 | ||
36 | |||
37 | #define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) | ||
38 | #define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) | ||
39 | |||
40 | typedef struct expdesc { | 37 | typedef struct expdesc { |
41 | expkind k; | 38 | expkind k; |
42 | union { | 39 | union { |
43 | struct { /* for indexed variables (VINDEXED) */ | 40 | struct { int info, aux; } s; |
44 | short idx; /* index (R/K) */ | 41 | lua_Number nval; |
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 */ | ||
50 | } u; | 42 | } u; |
51 | int t; /* patch list of `exit when true' */ | 43 | int t; /* patch list of `exit when true' */ |
52 | int f; /* patch list of `exit when false' */ | 44 | int f; /* patch list of `exit when false' */ |
53 | } expdesc; | 45 | } expdesc; |
54 | 46 | ||
55 | 47 | ||
56 | /* description of active local variable */ | 48 | typedef struct upvaldesc { |
57 | typedef struct Vardesc { | 49 | lu_byte k; |
58 | short idx; /* variable index in stack */ | 50 | lu_byte info; |
59 | } Vardesc; | 51 | } upvaldesc; |
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; | ||
89 | 52 | ||
90 | 53 | ||
91 | /* control of blocks */ | ||
92 | struct BlockCnt; /* defined in lparser.c */ | 54 | struct BlockCnt; /* defined in lparser.c */ |
93 | 55 | ||
94 | 56 | ||
@@ -98,22 +60,23 @@ typedef struct FuncState { | |||
98 | Table *h; /* table to find (and reuse) elements in `k' */ | 60 | Table *h; /* table to find (and reuse) elements in `k' */ |
99 | struct FuncState *prev; /* enclosing function */ | 61 | struct FuncState *prev; /* enclosing function */ |
100 | struct LexState *ls; /* lexical state */ | 62 | struct LexState *ls; /* lexical state */ |
63 | struct lua_State *L; /* copy of the Lua state */ | ||
101 | struct BlockCnt *bl; /* chain of current blocks */ | 64 | struct BlockCnt *bl; /* chain of current blocks */ |
102 | int pc; /* next position to code (equivalent to `ncode') */ | 65 | int pc; /* next position to code (equivalent to `ncode') */ |
103 | int lasttarget; /* 'label' of last 'jump label' */ | 66 | int lasttarget; /* `pc' of last `jump target' */ |
104 | int jpc; /* list of pending jumps to `pc' */ | 67 | int jpc; /* list of pending jumps to `pc' */ |
68 | int freereg; /* first free register */ | ||
105 | int nk; /* number of elements in `k' */ | 69 | int nk; /* number of elements in `k' */ |
106 | int np; /* number of elements in `p' */ | 70 | int np; /* number of elements in `p' */ |
107 | int firstlocal; /* index of first local var (in Dyndata array) */ | 71 | short nlocvars; /* number of elements in `locvars' */ |
108 | short nlocvars; /* number of elements in 'f->locvars' */ | ||
109 | lu_byte nactvar; /* number of active local variables */ | 72 | lu_byte nactvar; /* number of active local variables */ |
110 | lu_byte nups; /* number of upvalues */ | 73 | upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ |
111 | lu_byte freereg; /* first free register */ | 74 | unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ |
112 | } FuncState; | 75 | } FuncState; |
113 | 76 | ||
114 | 77 | ||
115 | LUAI_FUNC Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | 78 | LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, |
116 | Dyndata *dyd, const char *name, int firstchar); | 79 | const char *name); |
117 | 80 | ||
118 | 81 | ||
119 | #endif | 82 | #endif |
diff --git a/apps/plugins/lua/lstate.c b/apps/plugins/lua/lstate.c index c7f2672be7..4313b83a0c 100644 --- a/apps/plugins/lua/lstate.c +++ b/apps/plugins/lua/lstate.c | |||
@@ -1,19 +1,17 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.99.1.2 2013/11/08 17:45:31 roberto Exp $ | 2 | ** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 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> | ||
10 | 9 | ||
11 | #define lstate_c | 10 | #define lstate_c |
12 | #define LUA_CORE | 11 | #define LUA_CORE |
13 | 12 | ||
14 | #include "lua.h" | 13 | #include "lua.h" |
15 | 14 | ||
16 | #include "lapi.h" | ||
17 | #include "ldebug.h" | 15 | #include "ldebug.h" |
18 | #include "ldo.h" | 16 | #include "ldo.h" |
19 | #include "lfunc.h" | 17 | #include "lfunc.h" |
@@ -26,240 +24,119 @@ | |||
26 | #include "ltm.h" | 24 | #include "ltm.h" |
27 | 25 | ||
28 | 26 | ||
29 | #if !defined(LUAI_GCPAUSE) | 27 | #define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) |
30 | #define LUAI_GCPAUSE 200 /* 200% */ | 28 | #define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) |
31 | #endif | 29 | #define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) |
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; | ||
65 | 30 | ||
66 | 31 | ||
67 | /* | 32 | /* |
68 | ** Main thread combines a thread state and the global state | 33 | ** Main thread combines a thread state and the global state |
69 | */ | 34 | */ |
70 | typedef struct LG { | 35 | typedef struct LG { |
71 | LX l; | 36 | lua_State l; |
72 | global_State g; | 37 | global_State g; |
73 | } LG; | 38 | } LG; |
74 | 39 | ||
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 | } | ||
131 | 40 | ||
132 | 41 | ||
133 | static void stack_init (lua_State *L1, lua_State *L) { | 42 | static void stack_init (lua_State *L1, lua_State *L) { |
134 | int i; CallInfo *ci; | 43 | /* initialize CallInfo array */ |
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; | ||
135 | /* initialize stack array */ | 48 | /* initialize stack array */ |
136 | L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue); | 49 | L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); |
137 | L1->stacksize = BASIC_STACK_SIZE; | 50 | L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; |
138 | for (i = 0; i < BASIC_STACK_SIZE; i++) | ||
139 | setnilvalue(L1->stack + i); /* erase new stack */ | ||
140 | L1->top = L1->stack; | 51 | L1->top = L1->stack; |
141 | L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; | 52 | L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; |
142 | /* initialize first ci */ | 53 | /* initialize first ci */ |
143 | ci = &L1->base_ci; | 54 | L1->ci->func = L1->top; |
144 | ci->next = ci->previous = NULL; | 55 | setnilvalue(L1->top++); /* `function' entry for this `ci' */ |
145 | ci->callstatus = 0; | 56 | L1->base = L1->ci->base = L1->top; |
146 | ci->func = L1->top; | 57 | L1->ci->top = L1->top + LUA_MINSTACK; |
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 */ | ||
159 | } | 58 | } |
160 | 59 | ||
161 | 60 | ||
162 | /* | 61 | static void freestack (lua_State *L, lua_State *L1) { |
163 | ** Create registry table and its predefined values | 62 | luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); |
164 | */ | 63 | luaM_freearray(L, L1->stack, L1->stacksize, TValue); |
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); | ||
177 | } | 64 | } |
178 | 65 | ||
179 | 66 | ||
180 | /* | 67 | /* |
181 | ** open parts of the state that may cause memory-allocation errors | 68 | ** open parts that may cause memory-allocation errors |
182 | */ | 69 | */ |
183 | static void f_luaopen (lua_State *L, void *ud) { | 70 | static void f_luaopen (lua_State *L, void *ud) { |
184 | global_State *g = G(L); | 71 | global_State *g = G(L); |
185 | UNUSED(ud); | 72 | UNUSED(ud); |
186 | stack_init(L, L); /* init stack */ | 73 | stack_init(L, L); /* init stack */ |
187 | init_registry(L, g); | 74 | sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ |
75 | sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ | ||
188 | luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ | 76 | luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ |
189 | luaT_init(L); | 77 | luaT_init(L); |
190 | luaX_init(L); | 78 | luaX_init(L); |
191 | /* pre-create memory-error message */ | 79 | luaS_fix(luaS_newliteral(L, MEMERRMSG)); |
192 | g->memerrmsg = luaS_newliteral(L, MEMERRMSG); | 80 | g->GCthreshold = 4*g->totalbytes; |
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); | ||
197 | } | 81 | } |
198 | 82 | ||
199 | 83 | ||
200 | /* | ||
201 | ** preinitialize a state with consistent values without allocating | ||
202 | ** any memory (to avoid errors) | ||
203 | */ | ||
204 | static void preinit_state (lua_State *L, global_State *g) { | 84 | static void preinit_state (lua_State *L, global_State *g) { |
205 | G(L) = g; | 85 | G(L) = g; |
206 | L->stack = NULL; | 86 | L->stack = NULL; |
207 | L->ci = NULL; | ||
208 | L->stacksize = 0; | 87 | L->stacksize = 0; |
209 | L->errorJmp = NULL; | 88 | L->errorJmp = NULL; |
210 | L->nCcalls = 0; | ||
211 | L->hook = NULL; | 89 | L->hook = NULL; |
212 | L->hookmask = 0; | 90 | L->hookmask = 0; |
213 | L->basehookcount = 0; | 91 | L->basehookcount = 0; |
214 | L->allowhook = 1; | 92 | L->allowhook = 1; |
215 | resethookcount(L); | 93 | resethookcount(L); |
216 | L->openupval = NULL; | 94 | L->openupval = NULL; |
217 | L->nny = 1; | 95 | L->size_ci = 0; |
218 | L->status = LUA_OK; | 96 | L->nCcalls = L->baseCcalls = 0; |
97 | L->status = 0; | ||
98 | L->base_ci = L->ci = NULL; | ||
99 | L->savedpc = NULL; | ||
219 | L->errfunc = 0; | 100 | L->errfunc = 0; |
101 | setnilvalue(gt(L)); | ||
220 | } | 102 | } |
221 | 103 | ||
222 | 104 | ||
223 | static void close_state (lua_State *L) { | 105 | static void close_state (lua_State *L) { |
224 | global_State *g = G(L); | 106 | global_State *g = G(L); |
225 | luaF_close(L, L->stack); /* close all upvalues for this thread */ | 107 | luaF_close(L, L->stack); /* close all upvalues for this thread */ |
226 | luaC_freeallobjects(L); /* collect all objects */ | 108 | luaC_freeall(L); /* collect all objects */ |
227 | if (g->version) /* closing a fully built state? */ | 109 | lua_assert(g->rootgc == obj2gco(L)); |
228 | luai_userstateclose(L); | 110 | lua_assert(g->strt.nuse == 0); |
229 | luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); | 111 | luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); |
230 | luaZ_freebuffer(L, &g->buff); | 112 | luaZ_freebuffer(L, &g->buff); |
231 | freestack(L); | 113 | freestack(L, L); |
232 | lua_assert(gettotalbytes(g) == sizeof(LG)); | 114 | lua_assert(g->totalbytes == sizeof(LG)); |
233 | (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ | 115 | (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); |
234 | } | 116 | } |
235 | 117 | ||
236 | 118 | ||
237 | LUA_API lua_State *lua_newthread (lua_State *L) { | 119 | lua_State *luaE_newthread (lua_State *L) { |
238 | lua_State *L1; | 120 | lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); |
239 | lua_lock(L); | 121 | luaC_link(L, obj2gco(L1), LUA_TTHREAD); |
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); | ||
244 | preinit_state(L1, G(L)); | 122 | preinit_state(L1, G(L)); |
123 | stack_init(L1, L); /* init stack */ | ||
124 | setobj2n(L, gt(L1), gt(L)); /* share table of globals */ | ||
245 | L1->hookmask = L->hookmask; | 125 | L1->hookmask = L->hookmask; |
246 | L1->basehookcount = L->basehookcount; | 126 | L1->basehookcount = L->basehookcount; |
247 | L1->hook = L->hook; | 127 | L1->hook = L->hook; |
248 | resethookcount(L1); | 128 | resethookcount(L1); |
249 | luai_userstatethread(L, L1); | 129 | lua_assert(iswhite(obj2gco(L1))); |
250 | stack_init(L1, L); /* init stack */ | ||
251 | lua_unlock(L); | ||
252 | return L1; | 130 | return L1; |
253 | } | 131 | } |
254 | 132 | ||
255 | 133 | ||
256 | void luaE_freethread (lua_State *L, lua_State *L1) { | 134 | void luaE_freethread (lua_State *L, lua_State *L1) { |
257 | LX *l = fromstate(L1); | ||
258 | luaF_close(L1, L1->stack); /* close all upvalues for this thread */ | 135 | luaF_close(L1, L1->stack); /* close all upvalues for this thread */ |
259 | lua_assert(L1->openupval == NULL); | 136 | lua_assert(L1->openupval == NULL); |
260 | luai_userstatefree(L, L1); | 137 | luai_userstatefree(L1); |
261 | freestack(L1); | 138 | freestack(L, L1); |
262 | luaM_free(L, l); | 139 | luaM_freemem(L, fromstate(L1), state_size(lua_State)); |
263 | } | 140 | } |
264 | 141 | ||
265 | 142 | ||
@@ -267,57 +144,71 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
267 | int i; | 144 | int i; |
268 | lua_State *L; | 145 | lua_State *L; |
269 | global_State *g; | 146 | global_State *g; |
270 | LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); | 147 | void *l = (*f)(ud, NULL, 0, state_size(LG)); |
271 | if (l == NULL) return NULL; | 148 | if (l == NULL) return NULL; |
272 | L = &l->l.l; | 149 | L = tostate(l); |
273 | g = &l->g; | 150 | g = &((LG *)L)->g; |
274 | L->next = NULL; | 151 | L->next = NULL; |
275 | L->tt = LUA_TTHREAD; | 152 | L->tt = LUA_TTHREAD; |
276 | g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); | 153 | g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); |
277 | L->marked = luaC_white(g); | 154 | L->marked = luaC_white(g); |
278 | g->gckind = KGC_NORMAL; | 155 | set2bits(L->marked, FIXEDBIT, SFIXEDBIT); |
279 | preinit_state(L, g); | 156 | preinit_state(L, g); |
280 | g->frealloc = f; | 157 | g->frealloc = f; |
281 | g->ud = ud; | 158 | g->ud = ud; |
282 | g->mainthread = L; | 159 | g->mainthread = L; |
283 | g->seed = makeseed(L); | ||
284 | g->uvhead.u.l.prev = &g->uvhead; | 160 | g->uvhead.u.l.prev = &g->uvhead; |
285 | g->uvhead.u.l.next = &g->uvhead; | 161 | g->uvhead.u.l.next = &g->uvhead; |
286 | g->gcrunning = 0; /* no GC while building state */ | 162 | g->GCthreshold = 0; /* mark it as unfinished state */ |
287 | g->GCestimate = 0; | ||
288 | g->strt.size = 0; | 163 | g->strt.size = 0; |
289 | g->strt.nuse = 0; | 164 | g->strt.nuse = 0; |
290 | g->strt.hash = NULL; | 165 | g->strt.hash = NULL; |
291 | setnilvalue(&g->l_registry); | 166 | setnilvalue(registry(L)); |
292 | luaZ_initbuffer(L, &g->buff); | 167 | luaZ_initbuffer(L, &g->buff); |
293 | g->panic = NULL; | 168 | g->panic = NULL; |
294 | g->version = NULL; | ||
295 | g->gcstate = GCSpause; | 169 | g->gcstate = GCSpause; |
296 | g->allgc = NULL; | 170 | g->rootgc = obj2gco(L); |
297 | g->finobj = NULL; | 171 | g->sweepstrgc = 0; |
298 | g->tobefnz = NULL; | 172 | g->sweepgc = &g->rootgc; |
299 | g->sweepgc = g->sweepfin = NULL; | 173 | g->gray = NULL; |
300 | g->gray = g->grayagain = NULL; | 174 | g->grayagain = NULL; |
301 | g->weak = g->ephemeron = g->allweak = NULL; | 175 | g->weak = NULL; |
176 | g->tmudata = NULL; | ||
302 | g->totalbytes = sizeof(LG); | 177 | g->totalbytes = sizeof(LG); |
303 | g->GCdebt = 0; | ||
304 | g->gcpause = LUAI_GCPAUSE; | 178 | g->gcpause = LUAI_GCPAUSE; |
305 | g->gcmajorinc = LUAI_GCMAJOR; | ||
306 | g->gcstepmul = LUAI_GCMUL; | 179 | g->gcstepmul = LUAI_GCMUL; |
307 | for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; | 180 | g->gcdept = 0; |
308 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { | 181 | for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL; |
182 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { | ||
309 | /* memory allocation error: free partial state */ | 183 | /* memory allocation error: free partial state */ |
310 | close_state(L); | 184 | close_state(L); |
311 | L = NULL; | 185 | L = NULL; |
312 | } | 186 | } |
187 | else | ||
188 | luai_userstateopen(L); | ||
313 | return L; | 189 | return L; |
314 | } | 190 | } |
315 | 191 | ||
316 | 192 | ||
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 | |||
317 | LUA_API void lua_close (lua_State *L) { | 199 | LUA_API void lua_close (lua_State *L) { |
318 | L = G(L)->mainthread; /* only the main thread can be closed */ | 200 | L = G(L)->mainthread; /* only the main thread can be closed */ |
319 | lua_lock(L); | 201 | 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); | ||
320 | close_state(L); | 212 | close_state(L); |
321 | } | 213 | } |
322 | 214 | ||
323 | |||
diff --git a/apps/plugins/lua/lstate.h b/apps/plugins/lua/lstate.h index daffd9aacf..94a6249461 100644 --- a/apps/plugins/lua/lstate.h +++ b/apps/plugins/lua/lstate.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 2.82.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -14,46 +14,25 @@ | |||
14 | #include "lzio.h" | 14 | #include "lzio.h" |
15 | 15 | ||
16 | 16 | ||
17 | /* | ||
18 | |||
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. | ||
38 | 17 | ||
39 | */ | 18 | struct lua_longjmp; /* defined in ldo.c */ |
40 | 19 | ||
41 | 20 | ||
42 | struct lua_longjmp; /* defined in ldo.c */ | 21 | /* table of globals */ |
22 | #define gt(L) (&L->l_gt) | ||
43 | 23 | ||
24 | /* registry */ | ||
25 | #define registry(L) (&G(L)->l_registry) | ||
44 | 26 | ||
45 | 27 | ||
46 | /* extra stack space to handle TM calls and some other extras */ | 28 | /* extra stack space to handle TM calls and some other extras */ |
47 | #define EXTRA_STACK 5 | 29 | #define EXTRA_STACK 5 |
48 | 30 | ||
49 | 31 | ||
50 | #define BASIC_STACK_SIZE (2*LUA_MINSTACK) | 32 | #define BASIC_CI_SIZE 8 |
51 | 33 | ||
34 | #define BASIC_STACK_SIZE (2*LUA_MINSTACK) | ||
52 | 35 | ||
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 | 36 | ||
58 | 37 | ||
59 | typedef struct stringtable { | 38 | typedef struct stringtable { |
@@ -64,87 +43,54 @@ typedef struct stringtable { | |||
64 | 43 | ||
65 | 44 | ||
66 | /* | 45 | /* |
67 | ** information about a call | 46 | ** informations about a call |
68 | */ | 47 | */ |
69 | typedef struct CallInfo { | 48 | typedef struct CallInfo { |
49 | StkId base; /* base for this function */ | ||
70 | StkId func; /* function index in the stack */ | 50 | StkId func; /* function index in the stack */ |
71 | StkId top; /* top for this function */ | 51 | StkId top; /* top for this function */ |
72 | struct CallInfo *previous, *next; /* dynamic call link */ | 52 | const Instruction *savedpc; |
73 | short nresults; /* expected number of results from this function */ | 53 | int nresults; /* expected number of results from this function */ |
74 | lu_byte callstatus; | 54 | int tailcalls; /* number of tail calls lost under this entry */ |
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; | ||
89 | } CallInfo; | 55 | } CallInfo; |
90 | 56 | ||
91 | 57 | ||
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 | |||
105 | 58 | ||
106 | #define isLua(ci) ((ci)->callstatus & CIST_LUA) | 59 | #define curr_func(L) (clvalue(L->ci->func)) |
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)) | ||
107 | 63 | ||
108 | 64 | ||
109 | /* | 65 | /* |
110 | ** `global state', shared by all threads of this state | 66 | ** `global state', shared by all threads of this state |
111 | */ | 67 | */ |
112 | typedef struct global_State { | 68 | typedef struct global_State { |
69 | stringtable strt; /* hash table for strings */ | ||
113 | lua_Alloc frealloc; /* function to reallocate memory */ | 70 | lua_Alloc frealloc; /* function to reallocate memory */ |
114 | void *ud; /* auxiliary data to `frealloc' */ | 71 | 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 */ | ||
122 | lu_byte currentwhite; | 72 | lu_byte currentwhite; |
123 | lu_byte gcstate; /* state of garbage collector */ | 73 | lu_byte gcstate; /* state of garbage collector */ |
124 | lu_byte gckind; /* kind of GC running */ | ||
125 | lu_byte gcrunning; /* true if GC is running */ | ||
126 | int sweepstrgc; /* position of sweep in `strt' */ | 74 | int sweepstrgc; /* position of sweep in `strt' */ |
127 | GCObject *allgc; /* list of all collectable objects */ | 75 | GCObject *rootgc; /* list of all collectable objects */ |
128 | GCObject *finobj; /* list of collectable objects with finalizers */ | 76 | GCObject **sweepgc; /* position of sweep in `rootgc' */ |
129 | GCObject **sweepgc; /* current position of sweep in list 'allgc' */ | ||
130 | GCObject **sweepfin; /* current position of sweep in list 'finobj' */ | ||
131 | GCObject *gray; /* list of gray objects */ | 77 | GCObject *gray; /* list of gray objects */ |
132 | GCObject *grayagain; /* list of objects to be traversed atomically */ | 78 | GCObject *grayagain; /* list of objects to be traversed atomically */ |
133 | GCObject *weak; /* list of tables with weak values */ | 79 | GCObject *weak; /* list of weak tables (to be cleared) */ |
134 | GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ | 80 | GCObject *tmudata; /* last element of list of userdata to be GC */ |
135 | GCObject *allweak; /* list of all-weak tables */ | 81 | Mbuffer buff; /* temporary buffer for string concatentation */ |
136 | GCObject *tobefnz; /* list of userdata to be GC */ | 82 | lu_mem GCthreshold; |
137 | UpVal uvhead; /* head of double-linked list of all open upvalues */ | 83 | lu_mem totalbytes; /* number of bytes currently allocated */ |
138 | Mbuffer buff; /* temporary buffer for string concatenation */ | 84 | lu_mem estimate; /* an estimate of number of bytes actually in use */ |
85 | lu_mem gcdept; /* how much GC is `behind schedule' */ | ||
139 | int gcpause; /* size of pause between successive GCs */ | 86 | int gcpause; /* size of pause between successive GCs */ |
140 | int gcmajorinc; /* pause between major collections (only in gen. mode) */ | ||
141 | int gcstepmul; /* GC `granularity' */ | 87 | int gcstepmul; /* GC `granularity' */ |
142 | lua_CFunction panic; /* to be called in unprotected errors */ | 88 | lua_CFunction panic; /* to be called in unprotected errors */ |
89 | TValue l_registry; | ||
143 | struct lua_State *mainthread; | 90 | struct lua_State *mainthread; |
144 | const lua_Number *version; /* pointer to version number */ | 91 | UpVal uvhead; /* head of double-linked list of all open upvalues */ |
145 | TString *memerrmsg; /* memory-error message */ | 92 | struct Table *mt[NUM_TAGS]; /* metatables for basic types */ |
146 | TString *tmname[TM_N]; /* array with tag-method names */ | 93 | TString *tmname[TM_N]; /* array with tag-method names */ |
147 | struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ | ||
148 | } global_State; | 94 | } global_State; |
149 | 95 | ||
150 | 96 | ||
@@ -155,24 +101,29 @@ struct lua_State { | |||
155 | CommonHeader; | 101 | CommonHeader; |
156 | lu_byte status; | 102 | lu_byte status; |
157 | StkId top; /* first free slot in the stack */ | 103 | StkId top; /* first free slot in the stack */ |
104 | StkId base; /* base of current function */ | ||
158 | global_State *l_G; | 105 | global_State *l_G; |
159 | CallInfo *ci; /* call info for current function */ | 106 | CallInfo *ci; /* call info for current function */ |
160 | const Instruction *oldpc; /* last pc traced */ | 107 | const Instruction *savedpc; /* `savedpc' of current function */ |
161 | StkId stack_last; /* last free slot in the stack */ | 108 | StkId stack_last; /* last free slot in the stack */ |
162 | StkId stack; /* stack base */ | 109 | StkId stack; /* stack base */ |
110 | CallInfo *end_ci; /* points after end of ci array*/ | ||
111 | CallInfo *base_ci; /* array of CallInfo's */ | ||
163 | int stacksize; | 112 | int stacksize; |
164 | unsigned short nny; /* number of non-yieldable calls in stack */ | 113 | int size_ci; /* size of array `base_ci' */ |
165 | unsigned short nCcalls; /* number of nested C calls */ | 114 | unsigned short nCcalls; /* number of nested C calls */ |
115 | unsigned short baseCcalls; /* nested C calls when resuming coroutine */ | ||
166 | lu_byte hookmask; | 116 | lu_byte hookmask; |
167 | lu_byte allowhook; | 117 | lu_byte allowhook; |
168 | int basehookcount; | 118 | int basehookcount; |
169 | int hookcount; | 119 | int hookcount; |
170 | lua_Hook hook; | 120 | lua_Hook hook; |
121 | TValue l_gt; /* table of globals */ | ||
122 | TValue env; /* temporary place for environments */ | ||
171 | GCObject *openupval; /* list of open upvalues in this stack */ | 123 | GCObject *openupval; /* list of open upvalues in this stack */ |
172 | GCObject *gclist; | 124 | GCObject *gclist; |
173 | struct lua_longjmp *errorJmp; /* current error recover point */ | 125 | struct lua_longjmp *errorJmp; /* current error recover point */ |
174 | ptrdiff_t errfunc; /* current error handling function (stack index) */ | 126 | ptrdiff_t errfunc; /* current error handling function (stack index) */ |
175 | CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ | ||
176 | }; | 127 | }; |
177 | 128 | ||
178 | 129 | ||
@@ -183,7 +134,7 @@ struct lua_State { | |||
183 | ** Union of all collectable objects | 134 | ** Union of all collectable objects |
184 | */ | 135 | */ |
185 | union GCObject { | 136 | union GCObject { |
186 | GCheader gch; /* common header */ | 137 | GCheader gch; |
187 | union TString ts; | 138 | union TString ts; |
188 | union Udata u; | 139 | union Udata u; |
189 | union Closure cl; | 140 | union Closure cl; |
@@ -194,35 +145,25 @@ union GCObject { | |||
194 | }; | 145 | }; |
195 | 146 | ||
196 | 147 | ||
197 | #define gch(o) (&(o)->gch) | ||
198 | |||
199 | /* macros to convert a GCObject into a specific value */ | 148 | /* macros to convert a GCObject into a specific value */ |
200 | #define rawgco2ts(o) \ | 149 | #define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) |
201 | check_exp(novariant((o)->gch.tt) == LUA_TSTRING, &((o)->ts)) | ||
202 | #define gco2ts(o) (&rawgco2ts(o)->tsv) | 150 | #define gco2ts(o) (&rawgco2ts(o)->tsv) |
203 | #define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) | 151 | #define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) |
204 | #define gco2u(o) (&rawgco2u(o)->uv) | 152 | #define gco2u(o) (&rawgco2u(o)->uv) |
205 | #define gco2lcl(o) check_exp((o)->gch.tt == LUA_TLCL, &((o)->cl.l)) | 153 | #define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) |
206 | #define gco2ccl(o) check_exp((o)->gch.tt == LUA_TCCL, &((o)->cl.c)) | 154 | #define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) |
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)) | ||
210 | #define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) | 155 | #define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) |
211 | #define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) | 156 | #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)) | ||
212 | #define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) | 159 | #define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) |
213 | 160 | ||
214 | /* macro to convert any Lua object into a GCObject */ | 161 | /* macro to convert any Lua object into a GCObject */ |
215 | #define obj2gco(v) (cast(GCObject *, (v))) | 162 | #define obj2gco(v) (cast(GCObject *, (v))) |
216 | 163 | ||
217 | 164 | ||
218 | /* actual number of total bytes allocated */ | 165 | LUAI_FUNC lua_State *luaE_newthread (lua_State *L); |
219 | #define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt) | ||
220 | |||
221 | LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); | ||
222 | LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); | 166 | 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 | |||
226 | 167 | ||
227 | #endif | 168 | #endif |
228 | 169 | ||
diff --git a/apps/plugins/lua/lstring.c b/apps/plugins/lua/lstring.c index af96c89c18..49113151cc 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.26.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 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,157 +18,78 @@ | |||
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 | |||
50 | 21 | ||
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 | */ | ||
64 | void luaS_resize (lua_State *L, int newsize) { | 22 | void luaS_resize (lua_State *L, int newsize) { |
23 | GCObject **newhash; | ||
24 | stringtable *tb; | ||
65 | int i; | 25 | int i; |
66 | stringtable *tb = &G(L)->strt; | 26 | if (G(L)->gcstate == GCSsweepstring) |
67 | /* cannot resize while GC is traversing strings */ | 27 | return; /* cannot resize during GC traverse */ |
68 | luaC_runtilstate(L, ~bitmask(GCSsweepstring)); | 28 | newhash = luaM_newvector(L, newsize, GCObject *); |
69 | if (newsize > tb->size) { | 29 | tb = &G(L)->strt; |
70 | luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); | 30 | for (i=0; i<newsize; i++) newhash[i] = NULL; |
71 | for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL; | ||
72 | } | ||
73 | /* rehash */ | 31 | /* rehash */ |
74 | for (i=0; i<tb->size; i++) { | 32 | for (i=0; i<tb->size; i++) { |
75 | GCObject *p = tb->hash[i]; | 33 | GCObject *p = tb->hash[i]; |
76 | tb->hash[i] = NULL; | ||
77 | while (p) { /* for each node in the list */ | 34 | while (p) { /* for each node in the list */ |
78 | GCObject *next = gch(p)->next; /* save next */ | 35 | GCObject *next = p->gch.next; /* save next */ |
79 | unsigned int h = lmod(gco2ts(p)->hash, newsize); /* new position */ | 36 | unsigned int h = gco2ts(p)->hash; |
80 | gch(p)->next = tb->hash[h]; /* chain it */ | 37 | int h1 = lmod(h, newsize); /* new position */ |
81 | tb->hash[h] = p; | 38 | lua_assert(cast_int(h%newsize) == lmod(h, newsize)); |
82 | resetoldbit(p); /* see MOVE OLD rule */ | 39 | p->gch.next = newhash[h1]; /* chain it */ |
40 | newhash[h1] = p; | ||
83 | p = next; | 41 | p = next; |
84 | } | 42 | } |
85 | } | 43 | } |
86 | if (newsize < tb->size) { | 44 | luaM_freearray(L, tb->hash, tb->size, TString *); |
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 | } | ||
91 | tb->size = newsize; | 45 | tb->size = newsize; |
46 | tb->hash = newhash; | ||
92 | } | 47 | } |
93 | 48 | ||
94 | 49 | ||
95 | /* | 50 | static TString *newlstr (lua_State *L, const char *str, size_t l, |
96 | ** creates a new string object | 51 | unsigned int h) { |
97 | */ | ||
98 | static TString *createstrobj (lua_State *L, const char *str, size_t l, | ||
99 | int tag, unsigned int h, GCObject **list) { | ||
100 | TString *ts; | 52 | TString *ts; |
101 | size_t totalsize; /* total size of TString object */ | 53 | stringtable *tb; |
102 | totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); | 54 | if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) |
103 | ts = &luaC_newobj(L, tag, totalsize, list, 0)->ts; | 55 | luaM_toobig(L); |
56 | ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); | ||
104 | ts->tsv.len = l; | 57 | ts->tsv.len = l; |
105 | ts->tsv.hash = h; | 58 | ts->tsv.hash = h; |
106 | ts->tsv.extra = 0; | 59 | ts->tsv.marked = luaC_white(G(L)); |
60 | ts->tsv.tt = LUA_TSTRING; | ||
61 | ts->tsv.reserved = 0; | ||
107 | memcpy(ts+1, str, l*sizeof(char)); | 62 | memcpy(ts+1, str, l*sizeof(char)); |
108 | ((char *)(ts+1))[l] = '\0'; /* ending 0 */ | 63 | ((char *)(ts+1))[l] = '\0'; /* ending 0 */ |
109 | return ts; | 64 | tb = &G(L)->strt; |
110 | } | 65 | h = lmod(h, tb->size); |
111 | 66 | ts->tsv.next = tb->hash[h]; /* chain new entry */ | |
112 | 67 | tb->hash[h] = obj2gco(ts); | |
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++; | 68 | tb->nuse++; |
126 | return s; | 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; | ||
127 | } | 72 | } |
128 | 73 | ||
129 | 74 | ||
130 | /* | 75 | TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { |
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) { | ||
134 | GCObject *o; | 76 | GCObject *o; |
135 | global_State *g = G(L); | 77 | unsigned int h = cast(unsigned int, l); /* seed */ |
136 | unsigned int h = luaS_hash(str, l, g->seed); | 78 | size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ |
137 | for (o = g->strt.hash[lmod(h, g->strt.size)]; | 79 | size_t l1; |
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)]; | ||
138 | o != NULL; | 83 | o != NULL; |
139 | o = gch(o)->next) { | 84 | o = o->gch.next) { |
140 | TString *ts = rawgco2ts(o); | 85 | TString *ts = rawgco2ts(o); |
141 | if (h == ts->tsv.hash && | 86 | if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { |
142 | l == ts->tsv.len && | 87 | /* string may be dead */ |
143 | (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { | 88 | if (isdead(G(L), o)) changewhite(o); |
144 | if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */ | ||
145 | changewhite(o); /* resurrect it */ | ||
146 | return ts; | 89 | return ts; |
147 | } | 90 | } |
148 | } | 91 | } |
149 | return newshrstr(L, str, l, h); /* not found; create a new string */ | 92 | return newlstr(L, str, l, h); /* not found */ |
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)); | ||
172 | } | 93 | } |
173 | 94 | ||
174 | 95 | ||
@@ -176,10 +97,15 @@ Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { | |||
176 | Udata *u; | 97 | Udata *u; |
177 | if (s > MAX_SIZET - sizeof(Udata)) | 98 | if (s > MAX_SIZET - sizeof(Udata)) |
178 | luaM_toobig(L); | 99 | luaM_toobig(L); |
179 | u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u; | 100 | u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); |
101 | u->uv.marked = luaC_white(G(L)); /* is not finalized */ | ||
102 | u->uv.tt = LUA_TUSERDATA; | ||
180 | u->uv.len = s; | 103 | u->uv.len = s; |
181 | u->uv.metatable = NULL; | 104 | u->uv.metatable = NULL; |
182 | u->uv.env = e; | 105 | 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); | ||
183 | return u; | 109 | return u; |
184 | } | 110 | } |
185 | 111 | ||
diff --git a/apps/plugins/lua/lstring.h b/apps/plugins/lua/lstring.h index 260e7f169b..c88e4c12a9 100644 --- a/apps/plugins/lua/lstring.h +++ b/apps/plugins/lua/lstring.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.h,v 1.49.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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,6 +7,7 @@ | |||
7 | #ifndef lstring_h | 7 | #ifndef lstring_h |
8 | #define lstring_h | 8 | #define lstring_h |
9 | 9 | ||
10 | |||
10 | #include "lgc.h" | 11 | #include "lgc.h" |
11 | #include "lobject.h" | 12 | #include "lobject.h" |
12 | #include "lstate.h" | 13 | #include "lstate.h" |
@@ -16,31 +17,15 @@ | |||
16 | 17 | ||
17 | #define sizeudata(u) (sizeof(union Udata)+(u)->len) | 18 | #define sizeudata(u) (sizeof(union Udata)+(u)->len) |
18 | 19 | ||
20 | #define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) | ||
19 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ | 21 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ |
20 | (sizeof(s)/sizeof(char))-1)) | 22 | (sizeof(s)/sizeof(char))-1)) |
21 | 23 | ||
22 | #define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) | 24 | #define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) |
23 | 25 | ||
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); | ||
40 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize); | 26 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize); |
41 | LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); | 27 | LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); |
42 | LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); | 28 | 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); | ||
44 | 29 | ||
45 | 30 | ||
46 | #endif | 31 | #endif |
diff --git a/apps/plugins/lua/lstrlib.c b/apps/plugins/lua/lstrlib.c index 04cc2f60d6..3d6103692f 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.178.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 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,58 +20,47 @@ | |||
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 | |||
32 | /* macro to `unsign' a character */ | 23 | /* macro to `unsign' a character */ |
33 | #define uchar(c) ((unsigned char)(c)) | 24 | #define uchar(c) ((unsigned char)(c)) |
34 | 25 | ||
35 | 26 | ||
36 | 27 | ||
37 | static int str_len (lua_State *L) { | 28 | static int str_len (lua_State *L) { |
38 | size_t l; | 29 | size_t l; |
39 | luaL_checklstring(L, 1, &l); | 30 | luaL_checklstring(L, 1, &l); |
40 | lua_pushinteger(L, (lua_Integer)l); | 31 | lua_pushinteger(L, l); |
41 | return 1; | 32 | return 1; |
42 | } | 33 | } |
43 | 34 | ||
44 | 35 | ||
45 | /* translate a relative string position: negative means back from end */ | 36 | static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { |
46 | static size_t posrelat (ptrdiff_t pos, size_t len) { | 37 | /* relative string position: negative means back from end */ |
47 | if (pos >= 0) return (size_t)pos; | 38 | if (pos < 0) pos += (ptrdiff_t)len + 1; |
48 | else if (0u - (size_t)pos > len) return 0; | 39 | return (pos >= 0) ? pos : 0; |
49 | else return len - ((size_t)-pos) + 1; | ||
50 | } | 40 | } |
51 | 41 | ||
52 | 42 | ||
53 | static int str_sub (lua_State *L) { | 43 | static int str_sub (lua_State *L) { |
54 | size_t l; | 44 | size_t l; |
55 | const char *s = luaL_checklstring(L, 1, &l); | 45 | const char *s = luaL_checklstring(L, 1, &l); |
56 | size_t start = posrelat(luaL_checkinteger(L, 2), l); | 46 | ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); |
57 | size_t end = posrelat(luaL_optinteger(L, 3, -1), l); | 47 | ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); |
58 | if (start < 1) start = 1; | 48 | if (start < 1) start = 1; |
59 | if (end > l) end = l; | 49 | if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; |
60 | if (start <= end) | 50 | if (start <= end) |
61 | lua_pushlstring(L, s + start - 1, end - start + 1); | 51 | lua_pushlstring(L, s+start-1, end-start+1); |
62 | else lua_pushliteral(L, ""); | 52 | else lua_pushliteral(L, ""); |
63 | return 1; | 53 | return 1; |
64 | } | 54 | } |
65 | 55 | ||
66 | 56 | ||
67 | static int str_reverse (lua_State *L) { | 57 | static int str_reverse (lua_State *L) { |
68 | size_t l, i; | 58 | size_t l; |
69 | luaL_Buffer b; | 59 | luaL_Buffer b; |
70 | const char *s = luaL_checklstring(L, 1, &l); | 60 | const char *s = luaL_checklstring(L, 1, &l); |
71 | char *p = luaL_buffinitsize(L, &b, l); | 61 | luaL_buffinit(L, &b); |
72 | for (i = 0; i < l; i++) | 62 | while (l--) luaL_addchar(&b, s[l]); |
73 | p[i] = s[l - i - 1]; | 63 | luaL_pushresult(&b); |
74 | luaL_pushresultsize(&b, l); | ||
75 | return 1; | 64 | return 1; |
76 | } | 65 | } |
77 | 66 | ||
@@ -81,10 +70,10 @@ static int str_lower (lua_State *L) { | |||
81 | size_t i; | 70 | size_t i; |
82 | luaL_Buffer b; | 71 | luaL_Buffer b; |
83 | const char *s = luaL_checklstring(L, 1, &l); | 72 | const char *s = luaL_checklstring(L, 1, &l); |
84 | char *p = luaL_buffinitsize(L, &b, l); | 73 | luaL_buffinit(L, &b); |
85 | for (i=0; i<l; i++) | 74 | for (i=0; i<l; i++) |
86 | p[i] = tolower(uchar(s[i])); | 75 | luaL_addchar(&b, tolower(uchar(s[i]))); |
87 | luaL_pushresultsize(&b, l); | 76 | luaL_pushresult(&b); |
88 | return 1; | 77 | return 1; |
89 | } | 78 | } |
90 | 79 | ||
@@ -94,38 +83,22 @@ static int str_upper (lua_State *L) { | |||
94 | size_t i; | 83 | size_t i; |
95 | luaL_Buffer b; | 84 | luaL_Buffer b; |
96 | const char *s = luaL_checklstring(L, 1, &l); | 85 | const char *s = luaL_checklstring(L, 1, &l); |
97 | char *p = luaL_buffinitsize(L, &b, l); | 86 | luaL_buffinit(L, &b); |
98 | for (i=0; i<l; i++) | 87 | for (i=0; i<l; i++) |
99 | p[i] = toupper(uchar(s[i])); | 88 | luaL_addchar(&b, toupper(uchar(s[i]))); |
100 | luaL_pushresultsize(&b, l); | 89 | luaL_pushresult(&b); |
101 | return 1; | 90 | return 1; |
102 | } | 91 | } |
103 | 92 | ||
104 | |||
105 | /* reasonable limit to avoid arithmetic overflow */ | ||
106 | #define MAXSIZE ((~(size_t)0) >> 1) | ||
107 | |||
108 | static int str_rep (lua_State *L) { | 93 | static int str_rep (lua_State *L) { |
109 | size_t l, lsep; | 94 | size_t l; |
95 | luaL_Buffer b; | ||
110 | const char *s = luaL_checklstring(L, 1, &l); | 96 | const char *s = luaL_checklstring(L, 1, &l); |
111 | int n = luaL_checkint(L, 2); | 97 | int n = luaL_checkint(L, 2); |
112 | const char *sep = luaL_optlstring(L, 3, "", &lsep); | 98 | luaL_buffinit(L, &b); |
113 | if (n <= 0) lua_pushliteral(L, ""); | 99 | while (n-- > 0) |
114 | else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */ | 100 | luaL_addlstring(&b, s, l); |
115 | return luaL_error(L, "resulting string too large"); | 101 | luaL_pushresult(&b); |
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 | } | ||
129 | return 1; | 102 | return 1; |
130 | } | 103 | } |
131 | 104 | ||
@@ -133,15 +106,15 @@ static int str_rep (lua_State *L) { | |||
133 | static int str_byte (lua_State *L) { | 106 | static int str_byte (lua_State *L) { |
134 | size_t l; | 107 | size_t l; |
135 | const char *s = luaL_checklstring(L, 1, &l); | 108 | const char *s = luaL_checklstring(L, 1, &l); |
136 | size_t posi = posrelat(luaL_optinteger(L, 2, 1), l); | 109 | ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); |
137 | size_t pose = posrelat(luaL_optinteger(L, 3, posi), l); | 110 | ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); |
138 | int n, i; | 111 | int n, i; |
139 | if (posi < 1) posi = 1; | 112 | if (posi <= 0) posi = 1; |
140 | if (pose > l) pose = l; | 113 | if ((size_t)pose > l) pose = l; |
141 | if (posi > pose) return 0; /* empty interval; return no values */ | 114 | if (posi > pose) return 0; /* empty interval; return no values */ |
142 | n = (int)(pose - posi + 1); | 115 | n = (int)(pose - posi + 1); |
143 | if (posi + n <= pose) /* (size_t -> int) overflow? */ | 116 | if (posi + n <= pose) /* overflow? */ |
144 | return luaL_error(L, "string slice too long"); | 117 | luaL_error(L, "string slice too long"); |
145 | luaL_checkstack(L, n, "string slice too long"); | 118 | luaL_checkstack(L, n, "string slice too long"); |
146 | for (i=0; i<n; i++) | 119 | for (i=0; i<n; i++) |
147 | lua_pushinteger(L, uchar(s[posi+i-1])); | 120 | lua_pushinteger(L, uchar(s[posi+i-1])); |
@@ -153,13 +126,13 @@ static int str_char (lua_State *L) { | |||
153 | int n = lua_gettop(L); /* number of arguments */ | 126 | int n = lua_gettop(L); /* number of arguments */ |
154 | int i; | 127 | int i; |
155 | luaL_Buffer b; | 128 | luaL_Buffer b; |
156 | char *p = luaL_buffinitsize(L, &b, n); | 129 | luaL_buffinit(L, &b); |
157 | for (i=1; i<=n; i++) { | 130 | for (i=1; i<=n; i++) { |
158 | int c = luaL_checkint(L, i); | 131 | int c = luaL_checkint(L, i); |
159 | luaL_argcheck(L, uchar(c) == c, i, "value out of range"); | 132 | luaL_argcheck(L, uchar(c) == c, i, "invalid value"); |
160 | p[i - 1] = uchar(c); | 133 | luaL_addchar(&b, uchar(c)); |
161 | } | 134 | } |
162 | luaL_pushresultsize(&b, n); | 135 | luaL_pushresult(&b); |
163 | return 1; | 136 | return 1; |
164 | } | 137 | } |
165 | 138 | ||
@@ -177,7 +150,7 @@ static int str_dump (lua_State *L) { | |||
177 | lua_settop(L, 1); | 150 | lua_settop(L, 1); |
178 | luaL_buffinit(L,&b); | 151 | luaL_buffinit(L,&b); |
179 | if (lua_dump(L, writer, &b) != 0) | 152 | if (lua_dump(L, writer, &b) != 0) |
180 | return luaL_error(L, "unable to dump given function"); | 153 | luaL_error(L, "unable to dump given function"); |
181 | luaL_pushresult(&b); | 154 | luaL_pushresult(&b); |
182 | return 1; | 155 | return 1; |
183 | } | 156 | } |
@@ -194,12 +167,9 @@ static int str_dump (lua_State *L) { | |||
194 | #define CAP_UNFINISHED (-1) | 167 | #define CAP_UNFINISHED (-1) |
195 | #define CAP_POSITION (-2) | 168 | #define CAP_POSITION (-2) |
196 | 169 | ||
197 | |||
198 | typedef struct MatchState { | 170 | typedef struct MatchState { |
199 | int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ | ||
200 | const char *src_init; /* init of source string */ | 171 | const char *src_init; /* init of source string */ |
201 | const char *src_end; /* end ('\0') of source string */ | 172 | const char *src_end; /* end (`\0') of source string */ |
202 | const char *p_end; /* end ('\0') of pattern */ | ||
203 | lua_State *L; | 173 | lua_State *L; |
204 | int level; /* total number of captures (finished or unfinished) */ | 174 | int level; /* total number of captures (finished or unfinished) */ |
205 | struct { | 175 | struct { |
@@ -209,16 +179,6 @@ typedef struct MatchState { | |||
209 | } MatchState; | 179 | } MatchState; |
210 | 180 | ||
211 | 181 | ||
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 | |||
222 | #define L_ESC '%' | 182 | #define L_ESC '%' |
223 | #define SPECIALS "^$*+?.([%-" | 183 | #define SPECIALS "^$*+?.([%-" |
224 | 184 | ||
@@ -226,7 +186,7 @@ static const char *match (MatchState *ms, const char *s, const char *p); | |||
226 | static int check_capture (MatchState *ms, int l) { | 186 | static int check_capture (MatchState *ms, int l) { |
227 | l -= '1'; | 187 | l -= '1'; |
228 | if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) | 188 | if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) |
229 | return luaL_error(ms->L, "invalid capture index %%%d", l + 1); | 189 | return luaL_error(ms->L, "invalid capture index"); |
230 | return l; | 190 | return l; |
231 | } | 191 | } |
232 | 192 | ||
@@ -242,16 +202,16 @@ static int capture_to_close (MatchState *ms) { | |||
242 | static const char *classend (MatchState *ms, const char *p) { | 202 | static const char *classend (MatchState *ms, const char *p) { |
243 | switch (*p++) { | 203 | switch (*p++) { |
244 | case L_ESC: { | 204 | case L_ESC: { |
245 | if (p == ms->p_end) | 205 | if (*p == '\0') |
246 | luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); | 206 | luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); |
247 | return p+1; | 207 | return p+1; |
248 | } | 208 | } |
249 | case '[': { | 209 | case '[': { |
250 | if (*p == '^') p++; | 210 | if (*p == '^') p++; |
251 | do { /* look for a `]' */ | 211 | do { /* look for a `]' */ |
252 | if (p == ms->p_end) | 212 | if (*p == '\0') |
253 | luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); | 213 | luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); |
254 | if (*(p++) == L_ESC && p < ms->p_end) | 214 | if (*(p++) == L_ESC && *p != '\0') |
255 | p++; /* skip escapes (e.g. `%]') */ | 215 | p++; /* skip escapes (e.g. `%]') */ |
256 | } while (*p != ']'); | 216 | } while (*p != ']'); |
257 | return p+1; | 217 | return p+1; |
@@ -269,14 +229,13 @@ static int match_class (int c, int cl) { | |||
269 | case 'a' : res = isalpha(c); break; | 229 | case 'a' : res = isalpha(c); break; |
270 | case 'c' : res = iscntrl(c); break; | 230 | case 'c' : res = iscntrl(c); break; |
271 | case 'd' : res = isdigit(c); break; | 231 | case 'd' : res = isdigit(c); break; |
272 | case 'g' : res = isgraph(c); break; | ||
273 | case 'l' : res = islower(c); break; | 232 | case 'l' : res = islower(c); break; |
274 | case 'p' : res = ispunct(c); break; | 233 | case 'p' : res = ispunct(c); break; |
275 | case 's' : res = isspace(c); break; | 234 | case 's' : res = isspace(c); break; |
276 | case 'u' : res = isupper(c); break; | 235 | case 'u' : res = isupper(c); break; |
277 | case 'w' : res = isalnum(c); break; | 236 | case 'w' : res = isalnum(c); break; |
278 | case 'x' : res = isxdigit(c); break; | 237 | case 'x' : res = isxdigit(c); break; |
279 | case 'z' : res = (c == 0); break; /* deprecated option */ | 238 | case 'z' : res = (c == 0); break; |
280 | default: return (cl == c); | 239 | default: return (cl == c); |
281 | } | 240 | } |
282 | return (islower(cl) ? res : !res); | 241 | return (islower(cl) ? res : !res); |
@@ -306,27 +265,23 @@ static int matchbracketclass (int c, const char *p, const char *ec) { | |||
306 | } | 265 | } |
307 | 266 | ||
308 | 267 | ||
309 | static int singlematch (MatchState *ms, const char *s, const char *p, | 268 | static int singlematch (int c, const char *p, const char *ep) { |
310 | const char *ep) { | 269 | switch (*p) { |
311 | if (s >= ms->src_end) | 270 | case '.': return 1; /* matches any char */ |
312 | return 0; | 271 | case L_ESC: return match_class(c, uchar(*(p+1))); |
313 | else { | 272 | case '[': return matchbracketclass(c, p, ep-1); |
314 | int c = uchar(*s); | 273 | default: return (uchar(*p) == c); |
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 | } | ||
321 | } | 274 | } |
322 | } | 275 | } |
323 | 276 | ||
324 | 277 | ||
278 | static const char *match (MatchState *ms, const char *s, const char *p); | ||
279 | |||
280 | |||
325 | static const char *matchbalance (MatchState *ms, const char *s, | 281 | static const char *matchbalance (MatchState *ms, const char *s, |
326 | const char *p) { | 282 | const char *p) { |
327 | if (p >= ms->p_end - 1) | 283 | if (*p == 0 || *(p+1) == 0) |
328 | luaL_error(ms->L, "malformed pattern " | 284 | luaL_error(ms->L, "unbalanced pattern"); |
329 | "(missing arguments to " LUA_QL("%%b") ")"); | ||
330 | if (*s != *p) return NULL; | 285 | if (*s != *p) return NULL; |
331 | else { | 286 | else { |
332 | int b = *p; | 287 | int b = *p; |
@@ -346,7 +301,7 @@ static const char *matchbalance (MatchState *ms, const char *s, | |||
346 | static const char *max_expand (MatchState *ms, const char *s, | 301 | static const char *max_expand (MatchState *ms, const char *s, |
347 | const char *p, const char *ep) { | 302 | const char *p, const char *ep) { |
348 | ptrdiff_t i = 0; /* counts maximum expand for item */ | 303 | ptrdiff_t i = 0; /* counts maximum expand for item */ |
349 | while (singlematch(ms, s + i, p, ep)) | 304 | while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep)) |
350 | i++; | 305 | i++; |
351 | /* keeps trying to match with the maximum repetitions */ | 306 | /* keeps trying to match with the maximum repetitions */ |
352 | while (i>=0) { | 307 | while (i>=0) { |
@@ -364,7 +319,7 @@ static const char *min_expand (MatchState *ms, const char *s, | |||
364 | const char *res = match(ms, s, ep+1); | 319 | const char *res = match(ms, s, ep+1); |
365 | if (res != NULL) | 320 | if (res != NULL) |
366 | return res; | 321 | return res; |
367 | else if (singlematch(ms, s, p, ep)) | 322 | else if (s<ms->src_end && singlematch(uchar(*s), p, ep)) |
368 | s++; /* try with one more repetition */ | 323 | s++; /* try with one more repetition */ |
369 | else return NULL; | 324 | else return NULL; |
370 | } | 325 | } |
@@ -408,105 +363,80 @@ static const char *match_capture (MatchState *ms, const char *s, int l) { | |||
408 | 363 | ||
409 | 364 | ||
410 | static const char *match (MatchState *ms, const char *s, const char *p) { | 365 | 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"); | ||
413 | init: /* using goto's to optimize tail recursion */ | 366 | init: /* using goto's to optimize tail recursion */ |
414 | if (p != ms->p_end) { /* end of pattern? */ | 367 | switch (*p) { |
415 | switch (*p) { | 368 | case '(': { /* start capture */ |
416 | case '(': { /* start capture */ | 369 | if (*(p+1) == ')') /* position capture? */ |
417 | if (*(p + 1) == ')') /* position capture? */ | 370 | return start_capture(ms, s, p+2, CAP_POSITION); |
418 | s = start_capture(ms, s, p + 2, CAP_POSITION); | 371 | else |
419 | else | 372 | return start_capture(ms, s, p+1, CAP_UNFINISHED); |
420 | s = start_capture(ms, s, p + 1, CAP_UNFINISHED); | 373 | } |
421 | break; | 374 | case ')': { /* end capture */ |
422 | } | 375 | return end_capture(ms, s, p+1); |
423 | case ')': { /* end capture */ | 376 | } |
424 | s = end_capture(ms, s, p + 1); | 377 | case L_ESC: { |
425 | break; | 378 | switch (*(p+1)) { |
426 | } | 379 | case 'b': { /* balanced string? */ |
427 | case '$': { | 380 | s = matchbalance(ms, s, p+2); |
428 | if ((p + 1) != ms->p_end) /* is the `$' the last char in pattern? */ | 381 | if (s == NULL) return NULL; |
429 | goto dflt; /* no; go to default */ | 382 | p+=4; goto init; /* else return match(ms, s, p+4); */ |
430 | s = (s == ms->src_end) ? s : NULL; /* check end of string */ | 383 | } |
431 | break; | 384 | case 'f': { /* frontier? */ |
432 | } | 385 | const char *ep; char previous; |
433 | case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ | 386 | p += 2; |
434 | switch (*(p + 1)) { | 387 | if (*p != '[') |
435 | case 'b': { /* balanced string? */ | 388 | luaL_error(ms->L, "missing " LUA_QL("[") " after " |
436 | s = matchbalance(ms, s, p + 2); | 389 | LUA_QL("%%f") " in pattern"); |
437 | if (s != NULL) { | 390 | ep = classend(ms, p); /* points to what is next */ |
438 | p += 4; goto init; /* return match(ms, s, p + 4); */ | 391 | previous = (s == ms->src_init) ? '\0' : *(s-1); |
439 | } /* else fail (s == NULL) */ | 392 | if (matchbracketclass(uchar(previous), p, ep-1) || |
440 | break; | 393 | !matchbracketclass(uchar(*s), p, ep-1)) return NULL; |
441 | } | 394 | p=ep; goto init; /* else return match(ms, s, ep); */ |
442 | case 'f': { /* frontier? */ | 395 | } |
443 | const char *ep; char previous; | 396 | default: { |
444 | p += 2; | 397 | if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ |
445 | if (*p != '[') | 398 | s = match_capture(ms, s, uchar(*(p+1))); |
446 | luaL_error(ms->L, "missing " LUA_QL("[") " after " | 399 | if (s == NULL) return NULL; |
447 | LUA_QL("%%f") " in pattern"); | 400 | p+=2; goto init; /* else return match(ms, s, p+2) */ |
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; | ||
456 | } | ||
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 | } | 401 | } |
466 | default: goto dflt; | 402 | goto dflt; /* case default */ |
467 | } | 403 | } |
468 | break; | ||
469 | } | 404 | } |
470 | default: dflt: { /* pattern class plus optional suffix */ | 405 | } |
471 | const char *ep = classend(ms, p); /* points to optional suffix */ | 406 | case '\0': { /* end of pattern */ |
472 | /* does not match at least once? */ | 407 | return s; /* match succeeded */ |
473 | if (!singlematch(ms, s, p, ep)) { | 408 | } |
474 | if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ | 409 | case '$': { |
475 | p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ | 410 | if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ |
476 | } | 411 | return (s == ms->src_end) ? s : NULL; /* check end of string */ |
477 | else /* '+' or no suffix */ | 412 | else goto dflt; |
478 | s = NULL; /* fail */ | 413 | } |
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); */ | ||
479 | } | 423 | } |
480 | else { /* matched once */ | 424 | case '*': { /* 0 or more repetitions */ |
481 | switch (*ep) { /* handle optional suffix */ | 425 | return max_expand(ms, s, p, ep); |
482 | case '?': { /* optional */ | 426 | } |
483 | const char *res; | 427 | case '+': { /* 1 or more repetitions */ |
484 | if ((res = match(ms, s + 1, ep + 1)) != NULL) | 428 | return (m ? max_expand(ms, s+1, p, ep) : NULL); |
485 | s = res; | 429 | } |
486 | else { | 430 | case '-': { /* 0 or more repetitions (minimum) */ |
487 | p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ | 431 | return min_expand(ms, s, p, ep); |
488 | } | 432 | } |
489 | break; | 433 | default: { |
490 | } | 434 | if (!m) return NULL; |
491 | case '+': /* 1 or more repetitions */ | 435 | s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ |
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 | } | ||
503 | } | 436 | } |
504 | break; | ||
505 | } | 437 | } |
506 | } | 438 | } |
507 | } | 439 | } |
508 | ms->matchdepth++; | ||
509 | return s; | ||
510 | } | 440 | } |
511 | 441 | ||
512 | 442 | ||
@@ -562,58 +492,37 @@ static int push_captures (MatchState *ms, const char *s, const char *e) { | |||
562 | } | 492 | } |
563 | 493 | ||
564 | 494 | ||
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 | |||
577 | static int str_find_aux (lua_State *L, int find) { | 495 | static int str_find_aux (lua_State *L, int find) { |
578 | size_t ls, lp; | 496 | size_t l1, l2; |
579 | const char *s = luaL_checklstring(L, 1, &ls); | 497 | const char *s = luaL_checklstring(L, 1, &l1); |
580 | const char *p = luaL_checklstring(L, 2, &lp); | 498 | const char *p = luaL_checklstring(L, 2, &l2); |
581 | size_t init = posrelat(luaL_optinteger(L, 3, 1), ls); | 499 | ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; |
582 | if (init < 1) init = 1; | 500 | if (init < 0) init = 0; |
583 | else if (init > ls + 1) { /* start after string's end? */ | 501 | else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; |
584 | lua_pushnil(L); /* cannot find anything */ | 502 | if (find && (lua_toboolean(L, 4) || /* explicit request? */ |
585 | return 1; | 503 | strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ |
586 | } | ||
587 | /* explicit request or no special characters? */ | ||
588 | if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { | ||
589 | /* do a plain search */ | 504 | /* do a plain search */ |
590 | const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp); | 505 | const char *s2 = lmemfind(s+init, l1-init, p, l2); |
591 | if (s2) { | 506 | if (s2) { |
592 | lua_pushinteger(L, s2 - s + 1); | 507 | lua_pushinteger(L, s2-s+1); |
593 | lua_pushinteger(L, s2 - s + lp); | 508 | lua_pushinteger(L, s2-s+l2); |
594 | return 2; | 509 | return 2; |
595 | } | 510 | } |
596 | } | 511 | } |
597 | else { | 512 | else { |
598 | MatchState ms; | 513 | MatchState ms; |
599 | const char *s1 = s + init - 1; | 514 | int anchor = (*p == '^') ? (p++, 1) : 0; |
600 | int anchor = (*p == '^'); | 515 | const char *s1=s+init; |
601 | if (anchor) { | ||
602 | p++; lp--; /* skip anchor character */ | ||
603 | } | ||
604 | ms.L = L; | 516 | ms.L = L; |
605 | ms.matchdepth = MAXCCALLS; | ||
606 | ms.src_init = s; | 517 | ms.src_init = s; |
607 | ms.src_end = s + ls; | 518 | ms.src_end = s+l1; |
608 | ms.p_end = p + lp; | ||
609 | do { | 519 | do { |
610 | const char *res; | 520 | const char *res; |
611 | ms.level = 0; | 521 | ms.level = 0; |
612 | lua_assert(ms.matchdepth == MAXCCALLS); | ||
613 | if ((res=match(&ms, s1, p)) != NULL) { | 522 | if ((res=match(&ms, s1, p)) != NULL) { |
614 | if (find) { | 523 | if (find) { |
615 | lua_pushinteger(L, s1 - s + 1); /* start */ | 524 | lua_pushinteger(L, s1-s+1); /* start */ |
616 | lua_pushinteger(L, res - s); /* end */ | 525 | lua_pushinteger(L, res-s); /* end */ |
617 | return push_captures(&ms, NULL, 0) + 2; | 526 | return push_captures(&ms, NULL, 0) + 2; |
618 | } | 527 | } |
619 | else | 528 | else |
@@ -638,21 +547,18 @@ static int str_match (lua_State *L) { | |||
638 | 547 | ||
639 | static int gmatch_aux (lua_State *L) { | 548 | static int gmatch_aux (lua_State *L) { |
640 | MatchState ms; | 549 | MatchState ms; |
641 | size_t ls, lp; | 550 | size_t ls; |
642 | const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); | 551 | const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); |
643 | const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp); | 552 | const char *p = lua_tostring(L, lua_upvalueindex(2)); |
644 | const char *src; | 553 | const char *src; |
645 | ms.L = L; | 554 | ms.L = L; |
646 | ms.matchdepth = MAXCCALLS; | ||
647 | ms.src_init = s; | 555 | ms.src_init = s; |
648 | ms.src_end = s+ls; | 556 | ms.src_end = s+ls; |
649 | ms.p_end = p + lp; | ||
650 | for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); | 557 | for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); |
651 | src <= ms.src_end; | 558 | src <= ms.src_end; |
652 | src++) { | 559 | src++) { |
653 | const char *e; | 560 | const char *e; |
654 | ms.level = 0; | 561 | ms.level = 0; |
655 | lua_assert(ms.matchdepth == MAXCCALLS); | ||
656 | if ((e = match(&ms, src, p)) != NULL) { | 562 | if ((e = match(&ms, src, p)) != NULL) { |
657 | lua_Integer newstart = e-s; | 563 | lua_Integer newstart = e-s; |
658 | if (e == src) newstart++; /* empty match? go at least one position */ | 564 | if (e == src) newstart++; /* empty match? go at least one position */ |
@@ -675,6 +581,12 @@ static int gmatch (lua_State *L) { | |||
675 | } | 581 | } |
676 | 582 | ||
677 | 583 | ||
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 | |||
678 | static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, | 590 | static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, |
679 | const char *e) { | 591 | const char *e) { |
680 | size_t l, i; | 592 | size_t l, i; |
@@ -684,12 +596,8 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, | |||
684 | luaL_addchar(b, news[i]); | 596 | luaL_addchar(b, news[i]); |
685 | else { | 597 | else { |
686 | i++; /* skip ESC */ | 598 | i++; /* skip ESC */ |
687 | if (!isdigit(uchar(news[i]))) { | 599 | 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); | ||
691 | luaL_addchar(b, news[i]); | 600 | luaL_addchar(b, news[i]); |
692 | } | ||
693 | else if (news[i] == '0') | 601 | else if (news[i] == '0') |
694 | luaL_addlstring(b, s, e - s); | 602 | luaL_addlstring(b, s, e - s); |
695 | else { | 603 | else { |
@@ -702,9 +610,14 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, | |||
702 | 610 | ||
703 | 611 | ||
704 | static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, | 612 | static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, |
705 | const char *e, int tr) { | 613 | const char *e) { |
706 | lua_State *L = ms->L; | 614 | lua_State *L = ms->L; |
707 | switch (tr) { | 615 | switch (lua_type(L, 3)) { |
616 | case LUA_TNUMBER: | ||
617 | case LUA_TSTRING: { | ||
618 | add_s(ms, b, s, e); | ||
619 | return; | ||
620 | } | ||
708 | case LUA_TFUNCTION: { | 621 | case LUA_TFUNCTION: { |
709 | int n; | 622 | int n; |
710 | lua_pushvalue(L, 3); | 623 | lua_pushvalue(L, 3); |
@@ -717,51 +630,41 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, | |||
717 | lua_gettable(L, 3); | 630 | lua_gettable(L, 3); |
718 | break; | 631 | break; |
719 | } | 632 | } |
720 | default: { /* LUA_TNUMBER or LUA_TSTRING */ | ||
721 | add_s(ms, b, s, e); | ||
722 | return; | ||
723 | } | ||
724 | } | 633 | } |
725 | if (!lua_toboolean(L, -1)) { /* nil or false? */ | 634 | if (!lua_toboolean(L, -1)) { /* nil or false? */ |
726 | lua_pop(L, 1); | 635 | lua_pop(L, 1); |
727 | lua_pushlstring(L, s, e - s); /* keep original text */ | 636 | lua_pushlstring(L, s, e - s); /* keep original text */ |
728 | } | 637 | } |
729 | else if (!lua_isstring(L, -1)) | 638 | else if (!lua_isstring(L, -1)) |
730 | luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); | 639 | luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); |
731 | luaL_addvalue(b); /* add result to accumulator */ | 640 | luaL_addvalue(b); /* add result to accumulator */ |
732 | } | 641 | } |
733 | 642 | ||
734 | 643 | ||
735 | static int str_gsub (lua_State *L) { | 644 | static int str_gsub (lua_State *L) { |
736 | size_t srcl, lp; | 645 | size_t srcl; |
737 | const char *src = luaL_checklstring(L, 1, &srcl); | 646 | const char *src = luaL_checklstring(L, 1, &srcl); |
738 | const char *p = luaL_checklstring(L, 2, &lp); | 647 | const char *p = luaL_checkstring(L, 2); |
739 | int tr = lua_type(L, 3); | 648 | int tr = lua_type(L, 3); |
740 | size_t max_s = luaL_optinteger(L, 4, srcl+1); | 649 | int max_s = luaL_optint(L, 4, srcl+1); |
741 | int anchor = (*p == '^'); | 650 | int anchor = (*p == '^') ? (p++, 1) : 0; |
742 | size_t n = 0; | 651 | int n = 0; |
743 | MatchState ms; | 652 | MatchState ms; |
744 | luaL_Buffer b; | 653 | luaL_Buffer b; |
745 | luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || | 654 | luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || |
746 | tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, | 655 | tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, |
747 | "string/function/table expected"); | 656 | "string/function/table expected"); |
748 | luaL_buffinit(L, &b); | 657 | luaL_buffinit(L, &b); |
749 | if (anchor) { | ||
750 | p++; lp--; /* skip anchor character */ | ||
751 | } | ||
752 | ms.L = L; | 658 | ms.L = L; |
753 | ms.matchdepth = MAXCCALLS; | ||
754 | ms.src_init = src; | 659 | ms.src_init = src; |
755 | ms.src_end = src+srcl; | 660 | ms.src_end = src+srcl; |
756 | ms.p_end = p + lp; | ||
757 | while (n < max_s) { | 661 | while (n < max_s) { |
758 | const char *e; | 662 | const char *e; |
759 | ms.level = 0; | 663 | ms.level = 0; |
760 | lua_assert(ms.matchdepth == MAXCCALLS); | ||
761 | e = match(&ms, src, p); | 664 | e = match(&ms, src, p); |
762 | if (e) { | 665 | if (e) { |
763 | n++; | 666 | n++; |
764 | add_value(&ms, &b, src, e, tr); | 667 | add_value(&ms, &b, src, e); |
765 | } | 668 | } |
766 | if (e && e>src) /* non empty match? */ | 669 | if (e && e>src) /* non empty match? */ |
767 | src = e; /* skip it */ | 670 | src = e; /* skip it */ |
@@ -779,46 +682,6 @@ static int str_gsub (lua_State *L) { | |||
779 | /* }====================================================== */ | 682 | /* }====================================================== */ |
780 | 683 | ||
781 | 684 | ||
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 | |||
822 | /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ | 685 | /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ |
823 | #define MAX_ITEM 512 | 686 | #define MAX_ITEM 512 |
824 | /* valid flags in a format specification */ | 687 | /* valid flags in a format specification */ |
@@ -835,20 +698,25 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { | |||
835 | const char *s = luaL_checklstring(L, arg, &l); | 698 | const char *s = luaL_checklstring(L, arg, &l); |
836 | luaL_addchar(b, '"'); | 699 | luaL_addchar(b, '"'); |
837 | while (l--) { | 700 | while (l--) { |
838 | if (*s == '"' || *s == '\\' || *s == '\n') { | 701 | switch (*s) { |
839 | luaL_addchar(b, '\\'); | 702 | case '"': case '\\': case '\n': { |
840 | luaL_addchar(b, *s); | 703 | luaL_addchar(b, '\\'); |
841 | } | 704 | luaL_addchar(b, *s); |
842 | else if (*s == '\0' || iscntrl(uchar(*s))) { | 705 | break; |
843 | char buff[10]; | 706 | } |
844 | if (!isdigit(uchar(*(s+1)))) | 707 | case '\r': { |
845 | snprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); | 708 | luaL_addlstring(b, "\\r", 2); |
846 | else | 709 | break; |
847 | snprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s)); | 710 | } |
848 | luaL_addstring(b, buff); | 711 | case '\0': { |
712 | luaL_addlstring(b, "\\000", 4); | ||
713 | break; | ||
714 | } | ||
715 | default: { | ||
716 | luaL_addchar(b, *s); | ||
717 | break; | ||
718 | } | ||
849 | } | 719 | } |
850 | else | ||
851 | luaL_addchar(b, *s); | ||
852 | s++; | 720 | s++; |
853 | } | 721 | } |
854 | luaL_addchar(b, '"'); | 722 | luaL_addchar(b, '"'); |
@@ -857,7 +725,7 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { | |||
857 | static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { | 725 | static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { |
858 | const char *p = strfrmt; | 726 | const char *p = strfrmt; |
859 | while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ | 727 | while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ |
860 | if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) | 728 | if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) |
861 | luaL_error(L, "invalid format (repeated flags)"); | 729 | luaL_error(L, "invalid format (repeated flags)"); |
862 | if (isdigit(uchar(*p))) p++; /* skip width */ | 730 | if (isdigit(uchar(*p))) p++; /* skip width */ |
863 | if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ | 731 | if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ |
@@ -869,28 +737,23 @@ static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { | |||
869 | if (isdigit(uchar(*p))) | 737 | if (isdigit(uchar(*p))) |
870 | luaL_error(L, "invalid format (width or precision too long)"); | 738 | luaL_error(L, "invalid format (width or precision too long)"); |
871 | *(form++) = '%'; | 739 | *(form++) = '%'; |
872 | memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char)); | 740 | strncpy(form, strfrmt, p - strfrmt + 1); |
873 | form += p - strfrmt + 1; | 741 | form += p - strfrmt + 1; |
874 | *form = '\0'; | 742 | *form = '\0'; |
875 | return p; | 743 | return p; |
876 | } | 744 | } |
877 | 745 | ||
878 | 746 | ||
879 | /* | 747 | static void addintlen (char *form) { |
880 | ** add length modifier into formats | ||
881 | */ | ||
882 | static void addlenmod (char *form, const char *lenmod) { | ||
883 | size_t l = strlen(form); | 748 | size_t l = strlen(form); |
884 | size_t lm = strlen(lenmod); | ||
885 | char spec = form[l - 1]; | 749 | char spec = form[l - 1]; |
886 | strcpy(form + l - 1, lenmod); | 750 | strcpy(form + l - 1, LUA_INTFRMLEN); |
887 | form[l + lm - 1] = spec; | 751 | form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; |
888 | form[l + lm] = '\0'; | 752 | form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; |
889 | } | 753 | } |
890 | 754 | ||
891 | 755 | ||
892 | static int str_format (lua_State *L) { | 756 | static int str_format (lua_State *L) { |
893 | int top = lua_gettop(L); | ||
894 | int arg = 1; | 757 | int arg = 1; |
895 | size_t sfl; | 758 | size_t sfl; |
896 | const char *strfrmt = luaL_checklstring(L, arg, &sfl); | 759 | const char *strfrmt = luaL_checklstring(L, arg, &sfl); |
@@ -904,61 +767,45 @@ static int str_format (lua_State *L) { | |||
904 | luaL_addchar(&b, *strfrmt++); /* %% */ | 767 | luaL_addchar(&b, *strfrmt++); /* %% */ |
905 | else { /* format item */ | 768 | else { /* format item */ |
906 | char form[MAX_FORMAT]; /* to store the format (`%...') */ | 769 | char form[MAX_FORMAT]; /* to store the format (`%...') */ |
907 | char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ | 770 | char buff[MAX_ITEM]; /* to store the formatted item */ |
908 | int nb = 0; /* number of bytes in added item */ | 771 | arg++; |
909 | if (++arg > top) | ||
910 | luaL_argerror(L, arg, "no value"); | ||
911 | strfrmt = scanformat(L, strfrmt, form); | 772 | strfrmt = scanformat(L, strfrmt, form); |
912 | switch (*strfrmt++) { | 773 | switch (*strfrmt++) { |
913 | case 'c': { | 774 | case 'c': { |
914 | nb = snprintf(buff, MAX_ITEM, form, luaL_checkint(L, arg)); | 775 | snprintf(buff, MAX_ITEM, form, (int)luaL_checknumber(L, arg)); |
915 | break; | 776 | break; |
916 | } | 777 | } |
917 | case 'd': case 'i': { | 778 | case 'd': case 'i': { |
918 | lua_Number n = luaL_checknumber(L, arg); | 779 | addintlen(form); |
919 | LUA_INTFRM_T ni = (LUA_INTFRM_T)n; | 780 | snprintf(buff, MAX_ITEM, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); |
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); | ||
925 | break; | 781 | break; |
926 | } | 782 | } |
927 | case 'o': case 'u': case 'x': case 'X': { | 783 | case 'o': case 'u': case 'x': case 'X': { |
928 | lua_Number n = luaL_checknumber(L, arg); | 784 | addintlen(form); |
929 | unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n; | 785 | snprintf(buff, MAX_ITEM, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); |
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); | ||
935 | break; | 786 | break; |
936 | } | 787 | } |
937 | case 'e': case 'E': case 'f': | 788 | case 'e': case 'E': case 'f': |
938 | #if defined(LUA_USE_AFORMAT) | ||
939 | case 'a': case 'A': | ||
940 | #endif | ||
941 | case 'g': case 'G': { | 789 | case 'g': case 'G': { |
942 | addlenmod(form, LUA_FLTFRMLEN); | 790 | snprintf(buff, MAX_ITEM, form, (double)luaL_checknumber(L, arg)); |
943 | nb = snprintf(buff, MAX_ITEM, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg)); | ||
944 | break; | 791 | break; |
945 | } | 792 | } |
946 | case 'q': { | 793 | case 'q': { |
947 | addquoted(L, &b, arg); | 794 | addquoted(L, &b, arg); |
948 | break; | 795 | continue; /* skip the 'addsize' at the end */ |
949 | } | 796 | } |
950 | case 's': { | 797 | case 's': { |
951 | size_t l; | 798 | size_t l; |
952 | const char *s = luaL_tolstring(L, arg, &l); | 799 | const char *s = luaL_checklstring(L, arg, &l); |
953 | if (!strchr(form, '.') && l >= 100) { | 800 | if (!strchr(form, '.') && l >= 100) { |
954 | /* no precision and string is too long to be formatted; | 801 | /* no precision and string is too long to be formatted; |
955 | keep original string */ | 802 | keep original string */ |
803 | lua_pushvalue(L, arg); | ||
956 | luaL_addvalue(&b); | 804 | luaL_addvalue(&b); |
957 | break; | 805 | continue; /* skip the `addsize' at the end */ |
958 | } | 806 | } |
959 | else { | 807 | else { |
960 | nb = snprintf(buff, MAX_ITEM, form, s); | 808 | snprintf(buff, MAX_ITEM, form, s); |
961 | lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ | ||
962 | break; | 809 | break; |
963 | } | 810 | } |
964 | } | 811 | } |
@@ -967,15 +814,13 @@ static int str_format (lua_State *L) { | |||
967 | LUA_QL("format"), *(strfrmt - 1)); | 814 | LUA_QL("format"), *(strfrmt - 1)); |
968 | } | 815 | } |
969 | } | 816 | } |
970 | luaL_addsize(&b, nb); | 817 | luaL_addlstring(&b, buff, strlen(buff)); |
971 | } | 818 | } |
972 | } | 819 | } |
973 | luaL_pushresult(&b); | 820 | luaL_pushresult(&b); |
974 | return 1; | 821 | return 1; |
975 | } | 822 | } |
976 | 823 | ||
977 | /* }====================================================== */ | ||
978 | |||
979 | 824 | ||
980 | static const luaL_Reg strlib[] = { | 825 | static const luaL_Reg strlib[] = { |
981 | {"byte", str_byte}, | 826 | {"byte", str_byte}, |
@@ -983,6 +828,7 @@ static const luaL_Reg strlib[] = { | |||
983 | {"dump", str_dump}, | 828 | {"dump", str_dump}, |
984 | {"find", str_find}, | 829 | {"find", str_find}, |
985 | {"format", str_format}, | 830 | {"format", str_format}, |
831 | {"gfind", gfind_nodef}, | ||
986 | {"gmatch", gmatch}, | 832 | {"gmatch", gmatch}, |
987 | {"gsub", str_gsub}, | 833 | {"gsub", str_gsub}, |
988 | {"len", str_len}, | 834 | {"len", str_len}, |
@@ -997,13 +843,13 @@ static const luaL_Reg strlib[] = { | |||
997 | 843 | ||
998 | 844 | ||
999 | static void createmetatable (lua_State *L) { | 845 | static void createmetatable (lua_State *L) { |
1000 | lua_createtable(L, 0, 1); /* table to be metatable for strings */ | 846 | lua_createtable(L, 0, 1); /* create metatable for strings */ |
1001 | lua_pushliteral(L, ""); /* dummy string */ | 847 | lua_pushliteral(L, ""); /* dummy string */ |
1002 | lua_pushvalue(L, -2); /* copy table */ | 848 | lua_pushvalue(L, -2); |
1003 | lua_setmetatable(L, -2); /* set table as metatable for strings */ | 849 | lua_setmetatable(L, -2); /* set string metatable */ |
1004 | lua_pop(L, 1); /* pop dummy string */ | 850 | lua_pop(L, 1); /* pop dummy string */ |
1005 | lua_pushvalue(L, -2); /* get string library */ | 851 | lua_pushvalue(L, -2); /* string library... */ |
1006 | lua_setfield(L, -2, "__index"); /* metatable.__index = string */ | 852 | lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ |
1007 | lua_pop(L, 1); /* pop metatable */ | 853 | lua_pop(L, 1); /* pop metatable */ |
1008 | } | 854 | } |
1009 | 855 | ||
@@ -1011,8 +857,12 @@ static void createmetatable (lua_State *L) { | |||
1011 | /* | 857 | /* |
1012 | ** Open string library | 858 | ** Open string library |
1013 | */ | 859 | */ |
1014 | LUAMOD_API int luaopen_string (lua_State *L) { | 860 | LUALIB_API int luaopen_string (lua_State *L) { |
1015 | luaL_newlib(L, strlib); | 861 | luaL_register(L, LUA_STRLIBNAME, strlib); |
862 | #if defined(LUA_COMPAT_GFIND) | ||
863 | lua_getfield(L, -1, "gmatch"); | ||
864 | lua_setfield(L, -2, "gfind"); | ||
865 | #endif | ||
1016 | createmetatable(L); | 866 | createmetatable(L); |
1017 | return 1; | 867 | return 1; |
1018 | } | 868 | } |
diff --git a/apps/plugins/lua/ltable.c b/apps/plugins/lua/ltable.c index e0fe98ce3e..ec84f4fabc 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.72.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 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,6 +18,7 @@ | |||
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> | ||
21 | #include <string.h> | 22 | #include <string.h> |
22 | 23 | ||
23 | #define ltable_c | 24 | #define ltable_c |
@@ -31,16 +32,14 @@ | |||
31 | #include "lmem.h" | 32 | #include "lmem.h" |
32 | #include "lobject.h" | 33 | #include "lobject.h" |
33 | #include "lstate.h" | 34 | #include "lstate.h" |
34 | #include "lstring.h" | ||
35 | #include "ltable.h" | 35 | #include "ltable.h" |
36 | #include "lvm.h" | ||
37 | 36 | ||
38 | 37 | ||
39 | /* | 38 | /* |
40 | ** max size of array part is 2^MAXBITS | 39 | ** max size of array part is 2^MAXBITS |
41 | */ | 40 | */ |
42 | #if LUAI_BITSINT >= 32 | 41 | #if LUAI_BITSINT > 26 |
43 | #define MAXBITS 30 | 42 | #define MAXBITS 26 |
44 | #else | 43 | #else |
45 | #define MAXBITS (LUAI_BITSINT-2) | 44 | #define MAXBITS (LUAI_BITSINT-2) |
46 | #endif | 45 | #endif |
@@ -48,10 +47,10 @@ | |||
48 | #define MAXASIZE (1 << MAXBITS) | 47 | #define MAXASIZE (1 << MAXBITS) |
49 | 48 | ||
50 | 49 | ||
51 | #define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) | 50 | #define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) |
52 | 51 | ||
53 | #define hashstr(t,str) hashpow2(t, (str)->tsv.hash) | 52 | #define hashstr(t,str) hashpow2(t, (str)->tsv.hash) |
54 | #define hashboolean(t,p) hashpow2(t, p) | 53 | #define hashboolean(t,p) hashpow2(t, p) |
55 | 54 | ||
56 | 55 | ||
57 | /* | 56 | /* |
@@ -73,11 +72,9 @@ | |||
73 | 72 | ||
74 | #define dummynode (&dummynode_) | 73 | #define dummynode (&dummynode_) |
75 | 74 | ||
76 | #define isdummy(n) ((n) == dummynode) | ||
77 | |||
78 | static const Node dummynode_ = { | 75 | static const Node dummynode_ = { |
79 | {NILCONSTANT}, /* value */ | 76 | {{NULL}, LUA_TNIL}, /* value */ |
80 | {{NILCONSTANT, NULL}} /* key */ | 77 | {{{NULL}, LUA_TNIL, NULL}} /* key */ |
81 | }; | 78 | }; |
82 | 79 | ||
83 | 80 | ||
@@ -104,22 +101,12 @@ static Node *mainposition (const Table *t, const TValue *key) { | |||
104 | switch (ttype(key)) { | 101 | switch (ttype(key)) { |
105 | case LUA_TNUMBER: | 102 | case LUA_TNUMBER: |
106 | return hashnum(t, nvalue(key)); | 103 | return hashnum(t, nvalue(key)); |
107 | case LUA_TLNGSTR: { | 104 | case LUA_TSTRING: |
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: | ||
116 | return hashstr(t, rawtsvalue(key)); | 105 | return hashstr(t, rawtsvalue(key)); |
117 | case LUA_TBOOLEAN: | 106 | case LUA_TBOOLEAN: |
118 | return hashboolean(t, bvalue(key)); | 107 | return hashboolean(t, bvalue(key)); |
119 | case LUA_TLIGHTUSERDATA: | 108 | case LUA_TLIGHTUSERDATA: |
120 | return hashpointer(t, pvalue(key)); | 109 | return hashpointer(t, pvalue(key)); |
121 | case LUA_TLCF: | ||
122 | return hashpointer(t, fvalue(key)); | ||
123 | default: | 110 | default: |
124 | return hashpointer(t, gcvalue(key)); | 111 | return hashpointer(t, gcvalue(key)); |
125 | } | 112 | } |
@@ -145,7 +132,7 @@ static int arrayindex (const TValue *key) { | |||
145 | /* | 132 | /* |
146 | ** returns the index of a `key' for table traversals. First goes all | 133 | ** returns the index of a `key' for table traversals. First goes all |
147 | ** elements in the array part, then elements in the hash part. The | 134 | ** elements in the array part, then elements in the hash part. The |
148 | ** beginning of a traversal is signaled by -1. | 135 | ** beginning of a traversal is signalled by -1. |
149 | */ | 136 | */ |
150 | static int findindex (lua_State *L, Table *t, StkId key) { | 137 | static int findindex (lua_State *L, Table *t, StkId key) { |
151 | int i; | 138 | int i; |
@@ -155,19 +142,19 @@ static int findindex (lua_State *L, Table *t, StkId key) { | |||
155 | return i-1; /* yes; that's the index (corrected to C) */ | 142 | return i-1; /* yes; that's the index (corrected to C) */ |
156 | else { | 143 | else { |
157 | Node *n = mainposition(t, key); | 144 | Node *n = mainposition(t, key); |
158 | for (;;) { /* check whether `key' is somewhere in the chain */ | 145 | do { /* check whether `key' is somewhere in the chain */ |
159 | /* key may be dead already, but it is ok to use it in `next' */ | 146 | /* key may be dead already, but it is ok to use it in `next' */ |
160 | if (luaV_rawequalobj(gkey(n), key) || | 147 | if (luaO_rawequalObj(key2tval(n), key) || |
161 | (ttisdeadkey(gkey(n)) && iscollectable(key) && | 148 | (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && |
162 | deadvalue(gkey(n)) == gcvalue(key))) { | 149 | gcvalue(gkey(n)) == gcvalue(key))) { |
163 | i = cast_int(n - gnode(t, 0)); /* key index in hash table */ | 150 | i = cast_int(n - gnode(t, 0)); /* key index in hash table */ |
164 | /* hash elements are numbered after array ones */ | 151 | /* hash elements are numbered after array ones */ |
165 | return i + t->sizearray; | 152 | return i + t->sizearray; |
166 | } | 153 | } |
167 | else n = gnext(n); | 154 | else n = gnext(n); |
168 | if (n == NULL) | 155 | } while (n); |
169 | luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ | 156 | luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ |
170 | } | 157 | return 0; /* to avoid warnings */ |
171 | } | 158 | } |
172 | } | 159 | } |
173 | 160 | ||
@@ -183,7 +170,7 @@ int luaH_next (lua_State *L, Table *t, StkId key) { | |||
183 | } | 170 | } |
184 | for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ | 171 | for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ |
185 | if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ | 172 | if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ |
186 | setobj2s(L, key, gkey(gnode(t, i))); | 173 | setobj2s(L, key, key2tval(gnode(t, i))); |
187 | setobj2s(L, key+1, gval(gnode(t, i))); | 174 | setobj2s(L, key+1, gval(gnode(t, i))); |
188 | return 1; | 175 | return 1; |
189 | } | 176 | } |
@@ -224,7 +211,7 @@ static int computesizes (int nums[], int *narray) { | |||
224 | static int countint (const TValue *key, int *nums) { | 211 | static int countint (const TValue *key, int *nums) { |
225 | int k = arrayindex(key); | 212 | int k = arrayindex(key); |
226 | if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ | 213 | if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ |
227 | nums[luaO_ceillog2(k)]++; /* count as such */ | 214 | nums[ceillog2(k)]++; /* count as such */ |
228 | return 1; | 215 | return 1; |
229 | } | 216 | } |
230 | else | 217 | else |
@@ -264,7 +251,7 @@ static int numusehash (const Table *t, int *nums, int *pnasize) { | |||
264 | while (i--) { | 251 | while (i--) { |
265 | Node *n = &t->node[i]; | 252 | Node *n = &t->node[i]; |
266 | if (!ttisnil(gval(n))) { | 253 | if (!ttisnil(gval(n))) { |
267 | ause += countint(gkey(n), nums); | 254 | ause += countint(key2tval(n), nums); |
268 | totaluse++; | 255 | totaluse++; |
269 | } | 256 | } |
270 | } | 257 | } |
@@ -290,7 +277,7 @@ static void setnodevector (lua_State *L, Table *t, int size) { | |||
290 | } | 277 | } |
291 | else { | 278 | else { |
292 | int i; | 279 | int i; |
293 | lsize = luaO_ceillog2(size); | 280 | lsize = ceillog2(size); |
294 | if (lsize > MAXBITS) | 281 | if (lsize > MAXBITS) |
295 | luaG_runerror(L, "table overflow"); | 282 | luaG_runerror(L, "table overflow"); |
296 | size = twoto(lsize); | 283 | size = twoto(lsize); |
@@ -307,7 +294,7 @@ static void setnodevector (lua_State *L, Table *t, int size) { | |||
307 | } | 294 | } |
308 | 295 | ||
309 | 296 | ||
310 | void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) { | 297 | static void resize (lua_State *L, Table *t, int nasize, int nhsize) { |
311 | int i; | 298 | int i; |
312 | int oldasize = t->sizearray; | 299 | int oldasize = t->sizearray; |
313 | int oldhsize = t->lsizenode; | 300 | int oldhsize = t->lsizenode; |
@@ -315,13 +302,13 @@ void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) { | |||
315 | if (nasize > oldasize) /* array part must grow? */ | 302 | if (nasize > oldasize) /* array part must grow? */ |
316 | setarrayvector(L, t, nasize); | 303 | setarrayvector(L, t, nasize); |
317 | /* create new hash part with appropriate size */ | 304 | /* create new hash part with appropriate size */ |
318 | setnodevector(L, t, nhsize); | 305 | setnodevector(L, t, nhsize); |
319 | if (nasize < oldasize) { /* array part must shrink? */ | 306 | if (nasize < oldasize) { /* array part must shrink? */ |
320 | t->sizearray = nasize; | 307 | t->sizearray = nasize; |
321 | /* re-insert elements from vanishing slice */ | 308 | /* re-insert elements from vanishing slice */ |
322 | for (i=nasize; i<oldasize; i++) { | 309 | for (i=nasize; i<oldasize; i++) { |
323 | if (!ttisnil(&t->array[i])) | 310 | if (!ttisnil(&t->array[i])) |
324 | luaH_setint(L, t, i + 1, &t->array[i]); | 311 | setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); |
325 | } | 312 | } |
326 | /* shrink array */ | 313 | /* shrink array */ |
327 | luaM_reallocvector(L, t->array, oldasize, nasize, TValue); | 314 | luaM_reallocvector(L, t->array, oldasize, nasize, TValue); |
@@ -329,26 +316,23 @@ void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) { | |||
329 | /* re-insert elements from hash part */ | 316 | /* re-insert elements from hash part */ |
330 | for (i = twoto(oldhsize) - 1; i >= 0; i--) { | 317 | for (i = twoto(oldhsize) - 1; i >= 0; i--) { |
331 | Node *old = nold+i; | 318 | Node *old = nold+i; |
332 | if (!ttisnil(gval(old))) { | 319 | if (!ttisnil(gval(old))) |
333 | /* doesn't need barrier/invalidate cache, as entry was | 320 | setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); |
334 | already present in the table */ | ||
335 | setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); | ||
336 | } | ||
337 | } | 321 | } |
338 | if (!isdummy(nold)) | 322 | if (nold != dummynode) |
339 | luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old array */ | 323 | luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ |
340 | } | 324 | } |
341 | 325 | ||
342 | 326 | ||
343 | void luaH_resizearray (lua_State *L, Table *t, int nasize) { | 327 | void luaH_resizearray (lua_State *L, Table *t, int nasize) { |
344 | int nsize = isdummy(t->node) ? 0 : sizenode(t); | 328 | int nsize = (t->node == dummynode) ? 0 : sizenode(t); |
345 | luaH_resize(L, t, nasize, nsize); | 329 | resize(L, t, nasize, nsize); |
346 | } | 330 | } |
347 | 331 | ||
348 | 332 | ||
349 | static void rehash (lua_State *L, Table *t, const TValue *ek) { | 333 | static void rehash (lua_State *L, Table *t, const TValue *ek) { |
350 | int nasize, na; | 334 | int nasize, na; |
351 | int nums[MAXBITS+1]; /* nums[i] = number of keys with 2^(i-1) < k <= 2^i */ | 335 | int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ |
352 | int i; | 336 | int i; |
353 | int totaluse; | 337 | int totaluse; |
354 | for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ | 338 | for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ |
@@ -361,7 +345,7 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) { | |||
361 | /* compute new size for array part */ | 345 | /* compute new size for array part */ |
362 | na = computesizes(nums, &nasize); | 346 | na = computesizes(nums, &nasize); |
363 | /* resize the table to new computed sizes */ | 347 | /* resize the table to new computed sizes */ |
364 | luaH_resize(L, t, nasize, totaluse - na); | 348 | resize(L, t, nasize, totaluse - na); |
365 | } | 349 | } |
366 | 350 | ||
367 | 351 | ||
@@ -371,28 +355,32 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) { | |||
371 | */ | 355 | */ |
372 | 356 | ||
373 | 357 | ||
374 | Table *luaH_new (lua_State *L) { | 358 | Table *luaH_new (lua_State *L, int narray, int nhash) { |
375 | Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table), NULL, 0)->h; | 359 | Table *t = luaM_new(L, Table); |
360 | luaC_link(L, obj2gco(t), LUA_TTABLE); | ||
376 | t->metatable = NULL; | 361 | t->metatable = NULL; |
377 | t->flags = cast_byte(~0); | 362 | t->flags = cast_byte(~0); |
363 | /* temporary values (kept only if some malloc fails) */ | ||
378 | t->array = NULL; | 364 | t->array = NULL; |
379 | t->sizearray = 0; | 365 | t->sizearray = 0; |
380 | setnodevector(L, t, 0); | 366 | t->lsizenode = 0; |
367 | t->node = cast(Node *, dummynode); | ||
368 | setarrayvector(L, t, narray); | ||
369 | setnodevector(L, t, nhash); | ||
381 | return t; | 370 | return t; |
382 | } | 371 | } |
383 | 372 | ||
384 | 373 | ||
385 | void luaH_free (lua_State *L, Table *t) { | 374 | void luaH_free (lua_State *L, Table *t) { |
386 | if (!isdummy(t->node)) | 375 | if (t->node != dummynode) |
387 | luaM_freearray(L, t->node, cast(size_t, sizenode(t))); | 376 | luaM_freearray(L, t->node, sizenode(t), Node); |
388 | luaM_freearray(L, t->array, t->sizearray); | 377 | luaM_freearray(L, t->array, t->sizearray, TValue); |
389 | luaM_free(L, t); | 378 | luaM_free(L, t); |
390 | } | 379 | } |
391 | 380 | ||
392 | 381 | ||
393 | static Node *getfreepos (Table *t) { | 382 | static Node *getfreepos (Table *t) { |
394 | while (t->lastfree > t->node) { | 383 | while (t->lastfree-- > t->node) { |
395 | t->lastfree--; | ||
396 | if (ttisnil(gkey(t->lastfree))) | 384 | if (ttisnil(gkey(t->lastfree))) |
397 | return t->lastfree; | 385 | return t->lastfree; |
398 | } | 386 | } |
@@ -402,28 +390,23 @@ static Node *getfreepos (Table *t) { | |||
402 | 390 | ||
403 | 391 | ||
404 | /* | 392 | /* |
405 | ** inserts a new key into a hash table; first, check whether key's main | 393 | ** inserts a new key into a hash table; first, check whether key's main |
406 | ** position is free. If not, check whether colliding node is in its main | 394 | ** position is free. If not, check whether colliding node is in its main |
407 | ** position or not: if it is not, move colliding node to an empty place and | 395 | ** position or not: if it is not, move colliding node to an empty place and |
408 | ** put new key in its main position; otherwise (colliding node is in its main | 396 | ** put new key in its main position; otherwise (colliding node is in its main |
409 | ** position), new key goes to an empty position. | 397 | ** position), new key goes to an empty position. |
410 | */ | 398 | */ |
411 | TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | 399 | static TValue *newkey (lua_State *L, Table *t, const TValue *key) { |
412 | Node *mp; | 400 | Node *mp = mainposition(t, key); |
413 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); | 401 | if (!ttisnil(gval(mp)) || mp == dummynode) { |
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? */ | ||
418 | Node *othern; | 402 | Node *othern; |
419 | Node *n = getfreepos(t); /* get a free place */ | 403 | Node *n = getfreepos(t); /* get a free place */ |
420 | if (n == NULL) { /* cannot find a free place? */ | 404 | if (n == NULL) { /* cannot find a free place? */ |
421 | rehash(L, t, key); /* grow table */ | 405 | rehash(L, t, key); /* grow table */ |
422 | /* whatever called 'newkey' take care of TM cache and GC barrier */ | 406 | return luaH_set(L, t, key); /* re-insert key into grown table */ |
423 | return luaH_set(L, t, key); /* insert key into grown table */ | ||
424 | } | 407 | } |
425 | lua_assert(!isdummy(n)); | 408 | lua_assert(n != dummynode); |
426 | othern = mainposition(t, gkey(mp)); | 409 | othern = mainposition(t, key2tval(mp)); |
427 | if (othern != mp) { /* is colliding node out of its main position? */ | 410 | if (othern != mp) { /* is colliding node out of its main position? */ |
428 | /* yes; move colliding node into free position */ | 411 | /* yes; move colliding node into free position */ |
429 | while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ | 412 | while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ |
@@ -439,8 +422,8 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
439 | mp = n; | 422 | mp = n; |
440 | } | 423 | } |
441 | } | 424 | } |
442 | setobj2t(L, gkey(mp), key); | 425 | gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; |
443 | luaC_barrierback(L, obj2gco(t), key); | 426 | luaC_barriert(L, t, key); |
444 | lua_assert(ttisnil(gval(mp))); | 427 | lua_assert(ttisnil(gval(mp))); |
445 | return gval(mp); | 428 | return gval(mp); |
446 | } | 429 | } |
@@ -449,7 +432,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
449 | /* | 432 | /* |
450 | ** search function for integers | 433 | ** search function for integers |
451 | */ | 434 | */ |
452 | const TValue *luaH_getint (Table *t, int key) { | 435 | const TValue *luaH_getnum (Table *t, int key) { |
453 | /* (1 <= key && key <= t->sizearray) */ | 436 | /* (1 <= key && key <= t->sizearray) */ |
454 | if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) | 437 | if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) |
455 | return &t->array[key-1]; | 438 | return &t->array[key-1]; |
@@ -467,13 +450,12 @@ const TValue *luaH_getint (Table *t, int key) { | |||
467 | 450 | ||
468 | 451 | ||
469 | /* | 452 | /* |
470 | ** search function for short strings | 453 | ** search function for strings |
471 | */ | 454 | */ |
472 | const TValue *luaH_getstr (Table *t, TString *key) { | 455 | const TValue *luaH_getstr (Table *t, TString *key) { |
473 | Node *n = hashstr(t, key); | 456 | Node *n = hashstr(t, key); |
474 | lua_assert(key->tsv.tt == LUA_TSHRSTR); | ||
475 | do { /* check whether `key' is somewhere in the chain */ | 457 | do { /* check whether `key' is somewhere in the chain */ |
476 | if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key)) | 458 | if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) |
477 | return gval(n); /* that's it */ | 459 | return gval(n); /* that's it */ |
478 | else n = gnext(n); | 460 | else n = gnext(n); |
479 | } while (n); | 461 | } while (n); |
@@ -486,20 +468,20 @@ const TValue *luaH_getstr (Table *t, TString *key) { | |||
486 | */ | 468 | */ |
487 | const TValue *luaH_get (Table *t, const TValue *key) { | 469 | const TValue *luaH_get (Table *t, const TValue *key) { |
488 | switch (ttype(key)) { | 470 | switch (ttype(key)) { |
489 | case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key)); | ||
490 | case LUA_TNIL: return luaO_nilobject; | 471 | case LUA_TNIL: return luaO_nilobject; |
472 | case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); | ||
491 | case LUA_TNUMBER: { | 473 | case LUA_TNUMBER: { |
492 | int k; | 474 | int k; |
493 | lua_Number n = nvalue(key); | 475 | lua_Number n = nvalue(key); |
494 | lua_number2int(k, n); | 476 | lua_number2int(k, n); |
495 | if (luai_numeq(cast_num(k), n)) /* index is int? */ | 477 | if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ |
496 | return luaH_getint(t, k); /* use specialized version */ | 478 | return luaH_getnum(t, k); /* use specialized version */ |
497 | /* else go through */ | 479 | /* else go through */ |
498 | } | 480 | } |
499 | default: { | 481 | default: { |
500 | Node *n = mainposition(t, key); | 482 | Node *n = mainposition(t, key); |
501 | do { /* check whether `key' is somewhere in the chain */ | 483 | do { /* check whether `key' is somewhere in the chain */ |
502 | if (luaV_rawequalobj(gkey(n), key)) | 484 | if (luaO_rawequalObj(key2tval(n), key)) |
503 | return gval(n); /* that's it */ | 485 | return gval(n); /* that's it */ |
504 | else n = gnext(n); | 486 | else n = gnext(n); |
505 | } while (n); | 487 | } while (n); |
@@ -509,29 +491,41 @@ const TValue *luaH_get (Table *t, const TValue *key) { | |||
509 | } | 491 | } |
510 | 492 | ||
511 | 493 | ||
512 | /* | ||
513 | ** beware: when using this function you probably need to check a GC | ||
514 | ** barrier and invalidate the TM cache. | ||
515 | */ | ||
516 | TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { | 494 | TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { |
517 | const TValue *p = luaH_get(t, key); | 495 | const TValue *p = luaH_get(t, key); |
496 | t->flags = 0; | ||
518 | if (p != luaO_nilobject) | 497 | if (p != luaO_nilobject) |
519 | return cast(TValue *, p); | 498 | return cast(TValue *, p); |
520 | else return luaH_newkey(L, t, key); | 499 | else { |
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 | } | ||
521 | } | 505 | } |
522 | 506 | ||
523 | 507 | ||
524 | void luaH_setint (lua_State *L, Table *t, int key, TValue *value) { | 508 | TValue *luaH_setnum (lua_State *L, Table *t, int key) { |
525 | const TValue *p = luaH_getint(t, key); | 509 | const TValue *p = luaH_getnum(t, key); |
526 | TValue *cell; | ||
527 | if (p != luaO_nilobject) | 510 | if (p != luaO_nilobject) |
528 | cell = cast(TValue *, p); | 511 | return cast(TValue *, p); |
529 | else { | 512 | else { |
530 | TValue k; | 513 | TValue k; |
531 | setnvalue(&k, cast_num(key)); | 514 | setnvalue(&k, cast_num(key)); |
532 | cell = luaH_newkey(L, t, &k); | 515 | return 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); | ||
533 | } | 528 | } |
534 | setobj2t(L, cell, value); | ||
535 | } | 529 | } |
536 | 530 | ||
537 | 531 | ||
@@ -539,20 +533,20 @@ static int unbound_search (Table *t, unsigned int j) { | |||
539 | unsigned int i = j; /* i is zero or a present index */ | 533 | unsigned int i = j; /* i is zero or a present index */ |
540 | j++; | 534 | j++; |
541 | /* find `i' and `j' such that i is present and j is not */ | 535 | /* find `i' and `j' such that i is present and j is not */ |
542 | while (!ttisnil(luaH_getint(t, j))) { | 536 | while (!ttisnil(luaH_getnum(t, j))) { |
543 | i = j; | 537 | i = j; |
544 | j *= 2; | 538 | j *= 2; |
545 | if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ | 539 | if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ |
546 | /* table was built with bad purposes: resort to linear search */ | 540 | /* table was built with bad purposes: resort to linear search */ |
547 | i = 1; | 541 | i = 1; |
548 | while (!ttisnil(luaH_getint(t, i))) i++; | 542 | while (!ttisnil(luaH_getnum(t, i))) i++; |
549 | return i - 1; | 543 | return i - 1; |
550 | } | 544 | } |
551 | } | 545 | } |
552 | /* now do a binary search between them */ | 546 | /* now do a binary search between them */ |
553 | while (j - i > 1) { | 547 | while (j - i > 1) { |
554 | unsigned int m = (i+j)/2; | 548 | unsigned int m = (i+j)/2; |
555 | if (ttisnil(luaH_getint(t, m))) j = m; | 549 | if (ttisnil(luaH_getnum(t, m))) j = m; |
556 | else i = m; | 550 | else i = m; |
557 | } | 551 | } |
558 | return i; | 552 | return i; |
@@ -576,7 +570,7 @@ int luaH_getn (Table *t) { | |||
576 | return i; | 570 | return i; |
577 | } | 571 | } |
578 | /* else must find a boundary in hash part */ | 572 | /* else must find a boundary in hash part */ |
579 | else if (isdummy(t->node)) /* hash part is empty? */ | 573 | else if (t->node == dummynode) /* hash part is empty? */ |
580 | return j; /* that is easy... */ | 574 | return j; /* that is easy... */ |
581 | else return unbound_search(t, j); | 575 | else return unbound_search(t, j); |
582 | } | 576 | } |
@@ -589,6 +583,6 @@ Node *luaH_mainposition (const Table *t, const TValue *key) { | |||
589 | return mainposition(t, key); | 583 | return mainposition(t, key); |
590 | } | 584 | } |
591 | 585 | ||
592 | int luaH_isdummy (Node *n) { return isdummy(n); } | 586 | int luaH_isdummy (Node *n) { return n == dummynode; } |
593 | 587 | ||
594 | #endif | 588 | #endif |
diff --git a/apps/plugins/lua/ltable.h b/apps/plugins/lua/ltable.h index d69449b2b8..aa28914871 100644 --- a/apps/plugins/lua/ltable.h +++ b/apps/plugins/lua/ltable.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.h,v 2.16.1.2 2013/08/30 15:49:41 roberto Exp $ | 2 | ** $Id$ |
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,25 +11,20 @@ | |||
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.tvk) | 14 | #define gkey(n) (&(n)->i_key.nk) |
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 invalidateTMcache(t) ((t)->flags = 0) | 18 | #define key2tval(n) (&(n)->i_key.tvk) |
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)))) | ||
23 | 20 | ||
24 | 21 | LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); | |
25 | LUAI_FUNC const TValue *luaH_getint (Table *t, int key); | 22 | LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); |
26 | LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value); | ||
27 | LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); | 23 | LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); |
24 | LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); | ||
28 | LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); | 25 | 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); | ||
30 | LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); | 26 | LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); |
31 | LUAI_FUNC Table *luaH_new (lua_State *L); | 27 | LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); |
32 | LUAI_FUNC void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize); | ||
33 | LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); | 28 | LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); |
34 | LUAI_FUNC void luaH_free (lua_State *L, Table *t); | 29 | LUAI_FUNC void luaH_free (lua_State *L, Table *t); |
35 | LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); | 30 | 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 6001224e39..b6d9cb4ac7 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.65.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 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,11 +16,43 @@ | |||
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_len(L, n)) | 19 | #define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(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 | |||
22 | 55 | ||
23 | #if defined(LUA_COMPAT_MAXN) | ||
24 | static int maxn (lua_State *L) { | 56 | static int maxn (lua_State *L) { |
25 | lua_Number max = 0; | 57 | lua_Number max = 0; |
26 | luaL_checktype(L, 1, LUA_TTABLE); | 58 | luaL_checktype(L, 1, LUA_TTABLE); |
@@ -35,7 +67,24 @@ static int maxn (lua_State *L) { | |||
35 | lua_pushnumber(L, max); | 67 | lua_pushnumber(L, max); |
36 | return 1; | 68 | return 1; |
37 | } | 69 | } |
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"); | ||
38 | #endif | 84 | #endif |
85 | lua_pushvalue(L, 1); | ||
86 | return 1; | ||
87 | } | ||
39 | 88 | ||
40 | 89 | ||
41 | static int tinsert (lua_State *L) { | 90 | static int tinsert (lua_State *L) { |
@@ -49,7 +98,7 @@ static int tinsert (lua_State *L) { | |||
49 | case 3: { | 98 | case 3: { |
50 | int i; | 99 | int i; |
51 | pos = luaL_checkint(L, 2); /* 2nd argument is the position */ | 100 | pos = luaL_checkint(L, 2); /* 2nd argument is the position */ |
52 | luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); | 101 | if (pos > e) e = pos; /* `grow' array if necessary */ |
53 | for (i = e; i > pos; i--) { /* move up elements */ | 102 | for (i = e; i > pos; i--) { /* move up elements */ |
54 | lua_rawgeti(L, 1, i-1); | 103 | lua_rawgeti(L, 1, i-1); |
55 | lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ | 104 | lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ |
@@ -60,23 +109,25 @@ static int tinsert (lua_State *L) { | |||
60 | return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); | 109 | return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); |
61 | } | 110 | } |
62 | } | 111 | } |
112 | luaL_setn(L, 1, e); /* new size */ | ||
63 | lua_rawseti(L, 1, pos); /* t[pos] = v */ | 113 | lua_rawseti(L, 1, pos); /* t[pos] = v */ |
64 | return 0; | 114 | return 0; |
65 | } | 115 | } |
66 | 116 | ||
67 | 117 | ||
68 | static int tremove (lua_State *L) { | 118 | static int tremove (lua_State *L) { |
69 | int size = aux_getn(L, 1); | 119 | int e = aux_getn(L, 1); |
70 | int pos = luaL_optint(L, 2, size); | 120 | int pos = luaL_optint(L, 2, e); |
71 | if (pos != size) /* validate 'pos' if given */ | 121 | if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ |
72 | luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); | 122 | return 0; /* nothing to remove */ |
123 | luaL_setn(L, 1, e - 1); /* t.n = n-1 */ | ||
73 | lua_rawgeti(L, 1, pos); /* result = t[pos] */ | 124 | lua_rawgeti(L, 1, pos); /* result = t[pos] */ |
74 | for ( ; pos < size; pos++) { | 125 | for ( ;pos<e; pos++) { |
75 | lua_rawgeti(L, 1, pos+1); | 126 | lua_rawgeti(L, 1, pos+1); |
76 | lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ | 127 | lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ |
77 | } | 128 | } |
78 | lua_pushnil(L); | 129 | lua_pushnil(L); |
79 | lua_rawseti(L, 1, pos); /* t[pos] = nil */ | 130 | lua_rawseti(L, 1, e); /* t[e] = nil */ |
80 | return 1; | 131 | return 1; |
81 | } | 132 | } |
82 | 133 | ||
@@ -86,7 +137,7 @@ static void addfield (lua_State *L, luaL_Buffer *b, int i) { | |||
86 | if (!lua_isstring(L, -1)) | 137 | if (!lua_isstring(L, -1)) |
87 | luaL_error(L, "invalid value (%s) at index %d in table for " | 138 | luaL_error(L, "invalid value (%s) at index %d in table for " |
88 | LUA_QL("concat"), luaL_typename(L, -1), i); | 139 | LUA_QL("concat"), luaL_typename(L, -1), i); |
89 | luaL_addvalue(b); | 140 | luaL_addvalue(b); |
90 | } | 141 | } |
91 | 142 | ||
92 | 143 | ||
@@ -97,7 +148,7 @@ static int tconcat (lua_State *L) { | |||
97 | const char *sep = luaL_optlstring(L, 2, "", &lsep); | 148 | const char *sep = luaL_optlstring(L, 2, "", &lsep); |
98 | luaL_checktype(L, 1, LUA_TTABLE); | 149 | luaL_checktype(L, 1, LUA_TTABLE); |
99 | i = luaL_optint(L, 3, 1); | 150 | i = luaL_optint(L, 3, 1); |
100 | last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1)); | 151 | last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1)); |
101 | luaL_buffinit(L, &b); | 152 | luaL_buffinit(L, &b); |
102 | for (; i < last; i++) { | 153 | for (; i < last; i++) { |
103 | addfield(L, &b, i); | 154 | addfield(L, &b, i); |
@@ -110,54 +161,12 @@ static int tconcat (lua_State *L) { | |||
110 | } | 161 | } |
111 | 162 | ||
112 | 163 | ||
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 | |||
154 | 164 | ||
155 | /* | 165 | /* |
156 | ** {====================================================== | 166 | ** {====================================================== |
157 | ** Quicksort | 167 | ** Quicksort |
158 | ** (based on `Algorithms in MODULA-3', Robert Sedgewick; | 168 | ** (based on `Algorithms in MODULA-3', Robert Sedgewick; |
159 | ** Addison-Wesley, 1993.) | 169 | ** Addison-Wesley, 1993.) |
160 | ** ======================================================= | ||
161 | */ | 170 | */ |
162 | 171 | ||
163 | 172 | ||
@@ -178,7 +187,7 @@ static int sort_comp (lua_State *L, int a, int b) { | |||
178 | return res; | 187 | return res; |
179 | } | 188 | } |
180 | else /* a < b? */ | 189 | else /* a < b? */ |
181 | return lua_compare(L, a, b, LUA_OPLT); | 190 | return lua_lessthan(L, a, b); |
182 | } | 191 | } |
183 | 192 | ||
184 | static void auxsort (lua_State *L, int l, int u) { | 193 | static void auxsort (lua_State *L, int l, int u) { |
@@ -215,12 +224,12 @@ static void auxsort (lua_State *L, int l, int u) { | |||
215 | for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ | 224 | for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ |
216 | /* repeat ++i until a[i] >= P */ | 225 | /* repeat ++i until a[i] >= P */ |
217 | while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { | 226 | while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { |
218 | if (i>=u) luaL_error(L, "invalid order function for sorting"); | 227 | if (i>u) luaL_error(L, "invalid order function for sorting"); |
219 | lua_pop(L, 1); /* remove a[i] */ | 228 | lua_pop(L, 1); /* remove a[i] */ |
220 | } | 229 | } |
221 | /* repeat --j until a[j] <= P */ | 230 | /* repeat --j until a[j] <= P */ |
222 | while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { | 231 | while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { |
223 | if (j<=l) luaL_error(L, "invalid order function for sorting"); | 232 | if (j<l) luaL_error(L, "invalid order function for sorting"); |
224 | lua_pop(L, 1); /* remove a[j] */ | 233 | lua_pop(L, 1); /* remove a[j] */ |
225 | } | 234 | } |
226 | if (j<i) { | 235 | if (j<i) { |
@@ -259,25 +268,20 @@ static int sort (lua_State *L) { | |||
259 | 268 | ||
260 | static const luaL_Reg tab_funcs[] = { | 269 | static const luaL_Reg tab_funcs[] = { |
261 | {"concat", tconcat}, | 270 | {"concat", tconcat}, |
262 | #if defined(LUA_COMPAT_MAXN) | 271 | {"foreach", foreach}, |
272 | {"foreachi", foreachi}, | ||
273 | {"getn", getn}, | ||
263 | {"maxn", maxn}, | 274 | {"maxn", maxn}, |
264 | #endif | ||
265 | {"insert", tinsert}, | 275 | {"insert", tinsert}, |
266 | {"pack", pack}, | ||
267 | {"unpack", unpack}, | ||
268 | {"remove", tremove}, | 276 | {"remove", tremove}, |
277 | {"setn", setn}, | ||
269 | {"sort", sort}, | 278 | {"sort", sort}, |
270 | {NULL, NULL} | 279 | {NULL, NULL} |
271 | }; | 280 | }; |
272 | 281 | ||
273 | 282 | ||
274 | LUAMOD_API int luaopen_table (lua_State *L) { | 283 | LUALIB_API int luaopen_table (lua_State *L) { |
275 | luaL_newlib(L, tab_funcs); | 284 | luaL_register(L, LUA_TABLIBNAME, 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 | ||
281 | return 1; | 285 | return 1; |
282 | } | 286 | } |
283 | 287 | ||
diff --git a/apps/plugins/lua/ltm.c b/apps/plugins/lua/ltm.c index 69b4ed7727..c27f0f6fab 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.14.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 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,22 +19,20 @@ | |||
19 | #include "ltm.h" | 19 | #include "ltm.h" |
20 | 20 | ||
21 | 21 | ||
22 | static const char udatatypename[] = "userdata"; | ||
23 | 22 | ||
24 | LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { | 23 | const char *const luaT_typenames[] = { |
25 | "no value", | 24 | "nil", "boolean", "userdata", "number", |
26 | "nil", "boolean", udatatypename, "number", | 25 | "string", "table", "function", "userdata", "thread", |
27 | "string", "table", "function", udatatypename, "thread", | 26 | "proto", "upval" |
28 | "proto", "upval" /* these last two cases are used for tests only */ | ||
29 | }; | 27 | }; |
30 | 28 | ||
31 | 29 | ||
32 | void luaT_init (lua_State *L) { | 30 | void luaT_init (lua_State *L) { |
33 | static const char *const luaT_eventname[] = { /* ORDER TM */ | 31 | static const char *const luaT_eventname[] = { /* ORDER TM */ |
34 | "__index", "__newindex", | 32 | "__index", "__newindex", |
35 | "__gc", "__mode", "__len", "__eq", | 33 | "__gc", "__mode", "__eq", |
36 | "__add", "__sub", "__mul", "__div", "__mod", | 34 | "__add", "__sub", "__mul", "__div", "__mod", |
37 | "__pow", "__unm", "__lt", "__le", | 35 | "__pow", "__unm", "__len", "__lt", "__le", |
38 | "__concat", "__call" | 36 | "__concat", "__call" |
39 | }; | 37 | }; |
40 | int i; | 38 | int i; |
@@ -62,7 +60,7 @@ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { | |||
62 | 60 | ||
63 | const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { | 61 | const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { |
64 | Table *mt; | 62 | Table *mt; |
65 | switch (ttypenv(o)) { | 63 | switch (ttype(o)) { |
66 | case LUA_TTABLE: | 64 | case LUA_TTABLE: |
67 | mt = hvalue(o)->metatable; | 65 | mt = hvalue(o)->metatable; |
68 | break; | 66 | break; |
@@ -70,7 +68,7 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { | |||
70 | mt = uvalue(o)->metatable; | 68 | mt = uvalue(o)->metatable; |
71 | break; | 69 | break; |
72 | default: | 70 | default: |
73 | mt = G(L)->mt[ttypenv(o)]; | 71 | mt = G(L)->mt[ttype(o)]; |
74 | } | 72 | } |
75 | return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); | 73 | return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); |
76 | } | 74 | } |
diff --git a/apps/plugins/lua/ltm.h b/apps/plugins/lua/ltm.h index 7f89c841f9..1b89683ef3 100644 --- a/apps/plugins/lua/ltm.h +++ b/apps/plugins/lua/ltm.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.h,v 2.11.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -20,7 +20,6 @@ typedef enum { | |||
20 | TM_NEWINDEX, | 20 | TM_NEWINDEX, |
21 | TM_GC, | 21 | TM_GC, |
22 | TM_MODE, | 22 | TM_MODE, |
23 | TM_LEN, | ||
24 | TM_EQ, /* last tag method with `fast' access */ | 23 | TM_EQ, /* last tag method with `fast' access */ |
25 | TM_ADD, | 24 | TM_ADD, |
26 | TM_SUB, | 25 | TM_SUB, |
@@ -29,6 +28,7 @@ typedef enum { | |||
29 | TM_MOD, | 28 | TM_MOD, |
30 | TM_POW, | 29 | TM_POW, |
31 | TM_UNM, | 30 | TM_UNM, |
31 | TM_LEN, | ||
32 | TM_LT, | 32 | TM_LT, |
33 | TM_LE, | 33 | TM_LE, |
34 | TM_CONCAT, | 34 | TM_CONCAT, |
@@ -43,10 +43,7 @@ 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 | #define ttypename(x) luaT_typenames_[(x) + 1] | 46 | LUAI_DATA const char *const luaT_typenames[]; |
47 | #define objtypename(x) ttypename(ttypenv(x)) | ||
48 | |||
49 | LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; | ||
50 | 47 | ||
51 | 48 | ||
52 | LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); | 49 | 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 149a2c37bc..a0c57dc60b 100644 --- a/apps/plugins/lua/lua.h +++ b/apps/plugins/lua/lua.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lua.h,v 1.285.1.2 2013/11/11 12:09:16 roberto Exp $ | 2 | ** $Id$ |
3 | ** Lua - A Scripting Language | 3 | ** Lua - An Extensible Extension 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,39 +16,35 @@ | |||
16 | #include "luaconf.h" | 16 | #include "luaconf.h" |
17 | 17 | ||
18 | 18 | ||
19 | #define LUA_VERSION_MAJOR "5" | 19 | #define LUA_VERSION "Lua 5.1" |
20 | #define LUA_VERSION_MINOR "2" | 20 | #define LUA_RELEASE "Lua 5.1.4" |
21 | #define LUA_VERSION_NUM 502 | 21 | #define LUA_VERSION_NUM 501 |
22 | #define LUA_VERSION_RELEASE "3" | 22 | #define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" |
23 | #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" | ||
23 | 24 | ||
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" | ||
28 | 25 | ||
26 | /* mark for precompiled code (`<esc>Lua') */ | ||
27 | #define LUA_SIGNATURE "\033Lua" | ||
29 | 28 | ||
30 | /* mark for precompiled code ('<esc>Lua') */ | 29 | /* option for multiple returns in `lua_pcall' and `lua_call' */ |
31 | #define LUA_SIGNATURE "\033Lua" | ||
32 | |||
33 | /* option for multiple returns in 'lua_pcall' and 'lua_call' */ | ||
34 | #define LUA_MULTRET (-1) | 30 | #define LUA_MULTRET (-1) |
35 | 31 | ||
36 | 32 | ||
37 | /* | 33 | /* |
38 | ** pseudo-indices | 34 | ** pseudo-indices |
39 | */ | 35 | */ |
40 | #define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX | 36 | #define LUA_REGISTRYINDEX (-10000) |
41 | #define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) | 37 | #define LUA_ENVIRONINDEX (-10001) |
38 | #define LUA_GLOBALSINDEX (-10002) | ||
39 | #define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) | ||
42 | 40 | ||
43 | 41 | ||
44 | /* thread status */ | 42 | /* thread status; 0 is OK */ |
45 | #define LUA_OK 0 | ||
46 | #define LUA_YIELD 1 | 43 | #define LUA_YIELD 1 |
47 | #define LUA_ERRRUN 2 | 44 | #define LUA_ERRRUN 2 |
48 | #define LUA_ERRSYNTAX 3 | 45 | #define LUA_ERRSYNTAX 3 |
49 | #define LUA_ERRMEM 4 | 46 | #define LUA_ERRMEM 4 |
50 | #define LUA_ERRGCMM 5 | 47 | #define LUA_ERRERR 5 |
51 | #define LUA_ERRERR 6 | ||
52 | 48 | ||
53 | 49 | ||
54 | typedef struct lua_State lua_State; | 50 | typedef struct lua_State lua_State; |
@@ -85,18 +81,18 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); | |||
85 | #define LUA_TUSERDATA 7 | 81 | #define LUA_TUSERDATA 7 |
86 | #define LUA_TTHREAD 8 | 82 | #define LUA_TTHREAD 8 |
87 | 83 | ||
88 | #define LUA_NUMTAGS 9 | ||
89 | |||
90 | 84 | ||
91 | 85 | ||
92 | /* minimum Lua stack available to a C function */ | 86 | /* minimum Lua stack available to a C function */ |
93 | #define LUA_MINSTACK 20 | 87 | #define LUA_MINSTACK 20 |
94 | 88 | ||
95 | 89 | ||
96 | /* predefined values in the registry */ | 90 | /* |
97 | #define LUA_RIDX_MAINTHREAD 1 | 91 | ** generic extra include file |
98 | #define LUA_RIDX_GLOBALS 2 | 92 | */ |
99 | #define LUA_RIDX_LAST LUA_RIDX_GLOBALS | 93 | #if defined(LUA_USER_H) |
94 | #include LUA_USER_H | ||
95 | #endif | ||
100 | 96 | ||
101 | 97 | ||
102 | /* type of numbers in Lua */ | 98 | /* type of numbers in Lua */ |
@@ -106,23 +102,6 @@ typedef LUA_NUMBER lua_Number; | |||
106 | /* type for integer functions */ | 102 | /* type for integer functions */ |
107 | typedef LUA_INTEGER lua_Integer; | 103 | typedef LUA_INTEGER lua_Integer; |
108 | 104 | ||
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[]; | ||
126 | 105 | ||
127 | 106 | ||
128 | /* | 107 | /* |
@@ -135,20 +114,15 @@ LUA_API lua_State *(lua_newthread) (lua_State *L); | |||
135 | LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); | 114 | LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); |
136 | 115 | ||
137 | 116 | ||
138 | LUA_API const lua_Number *(lua_version) (lua_State *L); | ||
139 | |||
140 | |||
141 | /* | 117 | /* |
142 | ** basic stack manipulation | 118 | ** basic stack manipulation |
143 | */ | 119 | */ |
144 | LUA_API int (lua_absindex) (lua_State *L, int idx); | ||
145 | LUA_API int (lua_gettop) (lua_State *L); | 120 | LUA_API int (lua_gettop) (lua_State *L); |
146 | LUA_API void (lua_settop) (lua_State *L, int idx); | 121 | LUA_API void (lua_settop) (lua_State *L, int idx); |
147 | LUA_API void (lua_pushvalue) (lua_State *L, int idx); | 122 | LUA_API void (lua_pushvalue) (lua_State *L, int idx); |
148 | LUA_API void (lua_remove) (lua_State *L, int idx); | 123 | LUA_API void (lua_remove) (lua_State *L, int idx); |
149 | LUA_API void (lua_insert) (lua_State *L, int idx); | 124 | LUA_API void (lua_insert) (lua_State *L, int idx); |
150 | LUA_API void (lua_replace) (lua_State *L, int idx); | 125 | LUA_API void (lua_replace) (lua_State *L, int idx); |
151 | LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); | ||
152 | LUA_API int (lua_checkstack) (lua_State *L, int sz); | 126 | LUA_API int (lua_checkstack) (lua_State *L, int sz); |
153 | 127 | ||
154 | LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); | 128 | LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); |
@@ -165,12 +139,15 @@ LUA_API int (lua_isuserdata) (lua_State *L, int idx); | |||
165 | LUA_API int (lua_type) (lua_State *L, int idx); | 139 | LUA_API int (lua_type) (lua_State *L, int idx); |
166 | LUA_API const char *(lua_typename) (lua_State *L, int tp); | 140 | LUA_API const char *(lua_typename) (lua_State *L, int tp); |
167 | 141 | ||
168 | LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); | 142 | LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); |
169 | LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); | 143 | LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); |
170 | LUA_API lua_Unsigned (lua_tounsignedx) (lua_State *L, int idx, int *isnum); | 144 | LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); |
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); | ||
171 | LUA_API int (lua_toboolean) (lua_State *L, int idx); | 148 | LUA_API int (lua_toboolean) (lua_State *L, int idx); |
172 | LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); | 149 | LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); |
173 | LUA_API size_t (lua_rawlen) (lua_State *L, int idx); | 150 | LUA_API size_t (lua_objlen) (lua_State *L, int idx); |
174 | LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); | 151 | LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); |
175 | LUA_API void *(lua_touserdata) (lua_State *L, int idx); | 152 | LUA_API void *(lua_touserdata) (lua_State *L, int idx); |
176 | LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); | 153 | LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); |
@@ -178,36 +155,13 @@ LUA_API const void *(lua_topointer) (lua_State *L, int idx); | |||
178 | 155 | ||
179 | 156 | ||
180 | /* | 157 | /* |
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 | /* | ||
203 | ** push functions (C -> stack) | 158 | ** push functions (C -> stack) |
204 | */ | 159 | */ |
205 | LUA_API void (lua_pushnil) (lua_State *L); | 160 | LUA_API void (lua_pushnil) (lua_State *L); |
206 | LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); | 161 | LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); |
207 | LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); | 162 | LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); |
208 | LUA_API void (lua_pushunsigned) (lua_State *L, lua_Unsigned n); | 163 | LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); |
209 | LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t l); | 164 | LUA_API void (lua_pushstring) (lua_State *L, const char *s); |
210 | LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); | ||
211 | LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, | 165 | LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, |
212 | va_list argp); | 166 | va_list argp); |
213 | LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); | 167 | LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); |
@@ -220,47 +174,35 @@ LUA_API int (lua_pushthread) (lua_State *L); | |||
220 | /* | 174 | /* |
221 | ** get functions (Lua -> stack) | 175 | ** get functions (Lua -> stack) |
222 | */ | 176 | */ |
223 | LUA_API void (lua_getglobal) (lua_State *L, const char *var); | ||
224 | LUA_API void (lua_gettable) (lua_State *L, int idx); | 177 | LUA_API void (lua_gettable) (lua_State *L, int idx); |
225 | LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); | 178 | LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); |
226 | LUA_API void (lua_rawget) (lua_State *L, int idx); | 179 | LUA_API void (lua_rawget) (lua_State *L, int idx); |
227 | LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); | 180 | 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); | ||
229 | LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); | 181 | LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); |
230 | LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); | 182 | LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); |
231 | LUA_API int (lua_getmetatable) (lua_State *L, int objindex); | 183 | LUA_API int (lua_getmetatable) (lua_State *L, int objindex); |
232 | LUA_API void (lua_getuservalue) (lua_State *L, int idx); | 184 | LUA_API void (lua_getfenv) (lua_State *L, int idx); |
233 | 185 | ||
234 | 186 | ||
235 | /* | 187 | /* |
236 | ** set functions (stack -> Lua) | 188 | ** set functions (stack -> Lua) |
237 | */ | 189 | */ |
238 | LUA_API void (lua_setglobal) (lua_State *L, const char *var); | ||
239 | LUA_API void (lua_settable) (lua_State *L, int idx); | 190 | LUA_API void (lua_settable) (lua_State *L, int idx); |
240 | LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); | 191 | LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); |
241 | LUA_API void (lua_rawset) (lua_State *L, int idx); | 192 | LUA_API void (lua_rawset) (lua_State *L, int idx); |
242 | LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); | 193 | 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); | ||
244 | LUA_API int (lua_setmetatable) (lua_State *L, int objindex); | 194 | LUA_API int (lua_setmetatable) (lua_State *L, int objindex); |
245 | LUA_API void (lua_setuservalue) (lua_State *L, int idx); | 195 | LUA_API int (lua_setfenv) (lua_State *L, int idx); |
246 | 196 | ||
247 | 197 | ||
248 | /* | 198 | /* |
249 | ** 'load' and 'call' functions (load and run Lua code) | 199 | ** `load' and `call' functions (load and run Lua code) |
250 | */ | 200 | */ |
251 | LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx, | 201 | LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); |
252 | lua_CFunction k); | 202 | LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); |
253 | #define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) | 203 | LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); |
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 | |||
261 | LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, | 204 | LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, |
262 | const char *chunkname, | 205 | const char *chunkname); |
263 | const char *mode); | ||
264 | 206 | ||
265 | LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); | 207 | LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); |
266 | 208 | ||
@@ -268,10 +210,8 @@ LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); | |||
268 | /* | 210 | /* |
269 | ** coroutine functions | 211 | ** coroutine functions |
270 | */ | 212 | */ |
271 | LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx, | 213 | LUA_API int (lua_yield) (lua_State *L, int nresults); |
272 | lua_CFunction k); | 214 | LUA_API int (lua_resume) (lua_State *L, int narg); |
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); | ||
275 | LUA_API int (lua_status) (lua_State *L); | 215 | LUA_API int (lua_status) (lua_State *L); |
276 | 216 | ||
277 | /* | 217 | /* |
@@ -286,10 +226,6 @@ LUA_API int (lua_status) (lua_State *L); | |||
286 | #define LUA_GCSTEP 5 | 226 | #define LUA_GCSTEP 5 |
287 | #define LUA_GCSETPAUSE 6 | 227 | #define LUA_GCSETPAUSE 6 |
288 | #define LUA_GCSETSTEPMUL 7 | 228 | #define LUA_GCSETSTEPMUL 7 |
289 | #define LUA_GCSETMAJORINC 8 | ||
290 | #define LUA_GCISRUNNING 9 | ||
291 | #define LUA_GCGEN 10 | ||
292 | #define LUA_GCINC 11 | ||
293 | 229 | ||
294 | LUA_API int (lua_gc) (lua_State *L, int what, int data); | 230 | LUA_API int (lua_gc) (lua_State *L, int what, int data); |
295 | 231 | ||
@@ -303,23 +239,18 @@ LUA_API int (lua_error) (lua_State *L); | |||
303 | LUA_API int (lua_next) (lua_State *L, int idx); | 239 | LUA_API int (lua_next) (lua_State *L, int idx); |
304 | 240 | ||
305 | LUA_API void (lua_concat) (lua_State *L, int n); | 241 | LUA_API void (lua_concat) (lua_State *L, int n); |
306 | LUA_API void (lua_len) (lua_State *L, int idx); | ||
307 | 242 | ||
308 | LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); | 243 | LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); |
309 | LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); | 244 | LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); |
310 | 245 | ||
311 | 246 | ||
312 | 247 | ||
313 | /* | 248 | /* |
314 | ** =============================================================== | 249 | ** =============================================================== |
315 | ** some useful macros | 250 | ** some useful macros |
316 | ** =============================================================== | 251 | ** =============================================================== |
317 | */ | 252 | */ |
318 | 253 | ||
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 | |||
323 | #define lua_pop(L,n) lua_settop(L, -(n)-1) | 254 | #define lua_pop(L,n) lua_settop(L, -(n)-1) |
324 | 255 | ||
325 | #define lua_newtable(L) lua_createtable(L, 0, 0) | 256 | #define lua_newtable(L) lua_createtable(L, 0, 0) |
@@ -328,6 +259,8 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); | |||
328 | 259 | ||
329 | #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) | 260 | #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) |
330 | 261 | ||
262 | #define lua_strlen(L,i) lua_objlen(L, (i)) | ||
263 | |||
331 | #define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) | 264 | #define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) |
332 | #define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) | 265 | #define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) |
333 | #define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) | 266 | #define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) |
@@ -340,14 +273,32 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); | |||
340 | #define lua_pushliteral(L, s) \ | 273 | #define lua_pushliteral(L, s) \ |
341 | lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) | 274 | lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) |
342 | 275 | ||
343 | #define lua_pushglobaltable(L) \ | 276 | #define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) |
344 | lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) | 277 | #define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) |
345 | 278 | ||
346 | #define lua_tostring(L,i) lua_tolstring(L, (i), NULL) | 279 | #define lua_tostring(L,i) lua_tolstring(L, (i), NULL) |
347 | 280 | ||
348 | 281 | ||
349 | 282 | ||
350 | /* | 283 | /* |
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 | /* | ||
351 | ** {====================================================================== | 302 | ** {====================================================================== |
352 | ** Debug API | 303 | ** Debug API |
353 | ** ======================================================================= | 304 | ** ======================================================================= |
@@ -361,7 +312,7 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); | |||
361 | #define LUA_HOOKRET 1 | 312 | #define LUA_HOOKRET 1 |
362 | #define LUA_HOOKLINE 2 | 313 | #define LUA_HOOKLINE 2 |
363 | #define LUA_HOOKCOUNT 3 | 314 | #define LUA_HOOKCOUNT 3 |
364 | #define LUA_HOOKTAILCALL 4 | 315 | #define LUA_HOOKTAILRET 4 |
365 | 316 | ||
366 | 317 | ||
367 | /* | 318 | /* |
@@ -375,50 +326,43 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); | |||
375 | typedef struct lua_Debug lua_Debug; /* activation record */ | 326 | typedef struct lua_Debug lua_Debug; /* activation record */ |
376 | 327 | ||
377 | 328 | ||
378 | /* Functions to be called by the debugger in specific events */ | 329 | /* Functions to be called by the debuger in specific events */ |
379 | typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); | 330 | typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); |
380 | 331 | ||
381 | 332 | ||
382 | LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); | 333 | LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); |
383 | LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); | 334 | LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); |
384 | LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); | 335 | LUA_API const char *lua_getlocal (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); | 336 | LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); |
386 | LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); | 337 | LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); |
387 | LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); | 338 | 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); | ||
392 | 339 | ||
393 | LUA_API int (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); | 340 | LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); |
394 | LUA_API lua_Hook (lua_gethook) (lua_State *L); | 341 | LUA_API lua_Hook lua_gethook (lua_State *L); |
395 | LUA_API int (lua_gethookmask) (lua_State *L); | 342 | LUA_API int lua_gethookmask (lua_State *L); |
396 | LUA_API int (lua_gethookcount) (lua_State *L); | 343 | LUA_API int lua_gethookcount (lua_State *L); |
397 | 344 | ||
398 | 345 | ||
399 | struct lua_Debug { | 346 | struct lua_Debug { |
400 | int event; | 347 | int event; |
401 | const char *name; /* (n) */ | 348 | const char *name; /* (n) */ |
402 | const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ | 349 | const char *namewhat; /* (n) `global', `local', `field', `method' */ |
403 | const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ | 350 | const char *what; /* (S) `Lua', `C', `main', `tail' */ |
404 | const char *source; /* (S) */ | 351 | const char *source; /* (S) */ |
405 | int currentline; /* (l) */ | 352 | int currentline; /* (l) */ |
353 | int nups; /* (u) number of upvalues */ | ||
406 | int linedefined; /* (S) */ | 354 | int linedefined; /* (S) */ |
407 | int lastlinedefined; /* (S) */ | 355 | 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) */ | ||
412 | char short_src[LUA_IDSIZE]; /* (S) */ | 356 | char short_src[LUA_IDSIZE]; /* (S) */ |
413 | /* private part */ | 357 | /* private part */ |
414 | struct CallInfo *i_ci; /* active function */ | 358 | int i_ci; /* active function */ |
415 | }; | 359 | }; |
416 | 360 | ||
417 | /* }====================================================================== */ | 361 | /* }====================================================================== */ |
418 | 362 | ||
419 | 363 | ||
420 | /****************************************************************************** | 364 | /****************************************************************************** |
421 | * Copyright (C) 1994-2013 Lua.org, PUC-Rio. | 365 | * Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. |
422 | * | 366 | * |
423 | * Permission is hereby granted, free of charge, to any person obtaining | 367 | * Permission is hereby granted, free of charge, to any person obtaining |
424 | * a copy of this software and associated documentation files (the | 368 | * 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 ed83e8f640..109e680a17 100644 --- a/apps/plugins/lua/luaconf.h +++ b/apps/plugins/lua/luaconf.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: luaconf.h,v 1.176.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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,44 +24,30 @@ | |||
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(LUA_ANSI) && defined(__STRICT_ANSI__) | 27 | #if 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) && !defined(_WIN32_WCE) | 32 | #if !defined(LUA_ANSI) && defined(_WIN32) |
33 | #define LUA_WIN /* enable goodies for regular Windows platforms */ | 33 | #define LUA_WIN |
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 | |||
43 | #if defined(LUA_USE_LINUX) | 36 | #if defined(LUA_USE_LINUX) |
44 | #define LUA_USE_POSIX | 37 | #define LUA_USE_POSIX |
45 | #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ | 38 | #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ |
46 | #define LUA_USE_READLINE /* needs some extra libraries */ | 39 | #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 */ | ||
50 | #endif | 40 | #endif |
51 | 41 | ||
52 | #if defined(LUA_USE_MACOSX) | 42 | #if defined(LUA_USE_MACOSX) |
53 | #define LUA_USE_POSIX | 43 | #define LUA_USE_POSIX |
54 | #define LUA_USE_DLOPEN /* does not need -ldl */ | 44 | #define LUA_DL_DYLD /* does not need extra library */ |
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 */ | ||
59 | #endif | 45 | #endif |
60 | 46 | ||
61 | 47 | ||
62 | 48 | ||
63 | /* | 49 | /* |
64 | @@ LUA_USE_POSIX includes all functionality listed as X/Open System | 50 | @@ LUA_USE_POSIX includes all functionallity listed as X/Open System |
65 | @* Interfaces Extension (XSI). | 51 | @* Interfaces Extension (XSI). |
66 | ** CHANGE it (define it) if your system is XSI compatible. | 52 | ** CHANGE it (define it) if your system is XSI compatible. |
67 | */ | 53 | */ |
@@ -70,10 +56,20 @@ | |||
70 | #define LUA_USE_ISATTY | 56 | #define LUA_USE_ISATTY |
71 | #define LUA_USE_POPEN | 57 | #define LUA_USE_POPEN |
72 | #define LUA_USE_ULONGJMP | 58 | #define LUA_USE_ULONGJMP |
73 | #define LUA_USE_GMTIME_R | ||
74 | #endif | 59 | #endif |
75 | 60 | ||
76 | 61 | ||
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 | |||
77 | 73 | ||
78 | /* | 74 | /* |
79 | @@ LUA_PATH_DEFAULT is the default path that Lua uses to look for | 75 | @@ LUA_PATH_DEFAULT is the default path that Lua uses to look for |
@@ -84,7 +80,7 @@ | |||
84 | ** hierarchy or if you want to install your libraries in | 80 | ** hierarchy or if you want to install your libraries in |
85 | ** non-conventional directories. | 81 | ** non-conventional directories. |
86 | */ | 82 | */ |
87 | #if defined(_WIN32) /* { */ | 83 | #if defined(_WIN32) |
88 | /* | 84 | /* |
89 | ** In Windows, any exclamation mark ('!') in the path is replaced by the | 85 | ** In Windows, any exclamation mark ('!') in the path is replaced by the |
90 | ** path of the directory of the executable file of the current process. | 86 | ** path of the directory of the executable file of the current process. |
@@ -92,23 +88,21 @@ | |||
92 | #define LUA_LDIR "!\\lua\\" | 88 | #define LUA_LDIR "!\\lua\\" |
93 | #define LUA_CDIR "!\\" | 89 | #define LUA_CDIR "!\\" |
94 | #define LUA_PATH_DEFAULT \ | 90 | #define LUA_PATH_DEFAULT \ |
95 | LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ | 91 | ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ |
96 | LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" | 92 | LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" |
97 | #define LUA_CPATH_DEFAULT \ | 93 | #define LUA_CPATH_DEFAULT \ |
98 | LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" | 94 | ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" |
99 | 95 | ||
100 | #else /* }{ */ | 96 | #else |
101 | |||
102 | #define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" | ||
103 | #define LUA_ROOT "/usr/local/" | 97 | #define LUA_ROOT "/usr/local/" |
104 | #define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR | 98 | #define LUA_LDIR LUA_ROOT "share/lua/5.1/" |
105 | #define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR | 99 | #define LUA_CDIR LUA_ROOT "lib/lua/5.1/" |
106 | #define LUA_PATH_DEFAULT \ | 100 | #define LUA_PATH_DEFAULT \ |
107 | LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ | 101 | "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ |
108 | LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" | 102 | LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" |
109 | #define LUA_CPATH_DEFAULT \ | 103 | #define LUA_CPATH_DEFAULT \ |
110 | LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" | 104 | "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" |
111 | #endif /* } */ | 105 | #endif |
112 | 106 | ||
113 | 107 | ||
114 | /* | 108 | /* |
@@ -124,67 +118,79 @@ | |||
124 | 118 | ||
125 | 119 | ||
126 | /* | 120 | /* |
127 | @@ LUA_ENV is the name of the variable that holds the current | 121 | @@ LUA_PATHSEP is the character that separates templates in a path. |
128 | @@ environment, used to access global names. | 122 | @@ LUA_PATH_MARK is the string that marks the substitution points in a |
129 | ** CHANGE it if you do not like this name. | 123 | @* template. |
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.) | ||
130 | */ | 142 | */ |
131 | #define LUA_ENV "_ENV" | 143 | #define LUA_INTEGER ptrdiff_t |
132 | 144 | ||
133 | 145 | ||
134 | /* | 146 | /* |
135 | @@ LUA_API is a mark for all core API functions. | 147 | @@ LUA_API is a mark for all core API functions. |
136 | @@ LUALIB_API is a mark for all auxiliary library functions. | 148 | @@ LUALIB_API is a mark for all standard library functions. |
137 | @@ LUAMOD_API is a mark for all standard library opening functions. | ||
138 | ** CHANGE them if you need to define those functions in some special way. | 149 | ** CHANGE them if you need to define those functions in some special way. |
139 | ** For instance, if you want to create one Windows DLL with the core and | 150 | ** For instance, if you want to create one Windows DLL with the core and |
140 | ** the libraries, you may want to use the following definition (define | 151 | ** the libraries, you may want to use the following definition (define |
141 | ** LUA_BUILD_AS_DLL to get it). | 152 | ** LUA_BUILD_AS_DLL to get it). |
142 | */ | 153 | */ |
143 | #if defined(LUA_BUILD_AS_DLL) /* { */ | 154 | #if defined(LUA_BUILD_AS_DLL) |
144 | 155 | ||
145 | #if defined(LUA_CORE) || defined(LUA_LIB) /* { */ | 156 | #if defined(LUA_CORE) || defined(LUA_LIB) |
146 | #define LUA_API __declspec(dllexport) | 157 | #define LUA_API __declspec(dllexport) |
147 | #else /* }{ */ | 158 | #else |
148 | #define LUA_API __declspec(dllimport) | 159 | #define LUA_API __declspec(dllimport) |
149 | #endif /* } */ | 160 | #endif |
150 | 161 | ||
151 | #else /* }{ */ | 162 | #else |
152 | 163 | ||
153 | #define LUA_API extern | 164 | #define LUA_API extern |
154 | 165 | ||
155 | #endif /* } */ | 166 | #endif |
156 | |||
157 | 167 | ||
158 | /* more often than not the libs go together with the core */ | 168 | /* more often than not the libs go together with the core */ |
159 | #define LUALIB_API LUA_API | 169 | #define LUALIB_API LUA_API |
160 | #define LUAMOD_API LUALIB_API | ||
161 | 170 | ||
162 | 171 | ||
163 | /* | 172 | /* |
164 | @@ LUAI_FUNC is a mark for all extern functions that are not to be | 173 | @@ LUAI_FUNC is a mark for all extern functions that are not to be |
165 | @* exported to outside modules. | 174 | @* exported to outside modules. |
166 | @@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables | 175 | @@ LUAI_DATA is a mark for all extern (const) variables that are not to |
167 | @* that are not to be exported to outside modules (LUAI_DDEF for | 176 | @* be exported to outside modules. |
168 | @* definitions and LUAI_DDEC for declarations). | ||
169 | ** CHANGE them if you need to mark them in some special way. Elf/gcc | 177 | ** CHANGE them if you need to mark them in some special way. Elf/gcc |
170 | ** (versions 3.2 and later) mark them as "hidden" to optimize access | 178 | ** (versions 3.2 and later) mark them as "hidden" to optimize access |
171 | ** when Lua is compiled as a shared library. Not all elf targets support | 179 | ** when Lua is compiled as a shared library. |
172 | ** this attribute. Unfortunately, gcc does not offer a way to check | 180 | */ |
173 | ** whether the target offers that support, and those without support | 181 | #if defined(luaall_c) |
174 | ** give a warning about it. To avoid these warnings, change to the | 182 | #define LUAI_FUNC static |
175 | ** default definition. | 183 | #define LUAI_DATA /* empty */ |
176 | */ | 184 | |
177 | #if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ | 185 | #elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ |
178 | defined(__ELF__) /* { */ | 186 | defined(__ELF__) |
179 | #define LUAI_FUNC __attribute__((visibility("hidden"))) extern | 187 | #define LUAI_FUNC __attribute__((visibility("hidden"))) extern |
180 | #define LUAI_DDEC LUAI_FUNC | 188 | #define LUAI_DATA LUAI_FUNC |
181 | #define LUAI_DDEF /* empty */ | ||
182 | 189 | ||
183 | #else /* }{ */ | 190 | #else |
184 | #define LUAI_FUNC extern | 191 | #define LUAI_FUNC extern |
185 | #define LUAI_DDEC extern | 192 | #define LUAI_DATA extern |
186 | #define LUAI_DDEF /* empty */ | 193 | #endif |
187 | #endif /* } */ | ||
188 | 194 | ||
189 | 195 | ||
190 | 196 | ||
@@ -205,108 +211,175 @@ | |||
205 | 211 | ||
206 | 212 | ||
207 | /* | 213 | /* |
208 | @@ luai_writestring/luai_writeline define how 'print' prints its results. | 214 | ** {================================================================== |
209 | ** They are only used in libraries and the stand-alone program. (The #if | 215 | ** Stand-alone configuration |
210 | ** avoids including 'stdio.h' everywhere.) | 216 | ** =================================================================== |
211 | */ | 217 | */ |
212 | #if defined(LUA_LIB) || defined(lua_c) | 218 | |
213 | #define luai_writestring(s,l) DEBUGF("%s", (s)) | 219 | #if defined(lua_c) || defined(luaall_c) |
214 | #define luai_writeline() luai_writestring("\n", 1) | ||
215 | #endif | ||
216 | 220 | ||
217 | /* | 221 | /* |
218 | @@ luai_writestringerror defines how to print error messages. | 222 | @@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that |
219 | ** (A format string with one argument is enough for Lua...) | 223 | @* is, whether we're running lua interactively). |
224 | ** CHANGE it if you have a better definition for non-POSIX/non-Windows | ||
225 | ** systems. | ||
220 | */ | 226 | */ |
221 | #define luai_writestringerror(s,p) \ | 227 | #if defined(LUA_USE_ISATTY) |
222 | (fprintf(stderr, (s), (p)), fflush(stderr)) | 228 | #include <unistd.h> |
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 | ||
223 | 237 | ||
224 | 238 | ||
225 | /* | 239 | /* |
226 | @@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is, | 240 | @@ LUA_PROMPT is the default prompt used by stand-alone Lua. |
227 | ** strings that are internalized. (Cannot be smaller than reserved words | 241 | @@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. |
228 | ** or tags for metamethods, as these strings must be internalized; | 242 | ** CHANGE them if you want different prompts. (You can also change the |
229 | ** #("function") = 8, #("__newindex") = 10.) | 243 | ** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) |
230 | */ | 244 | */ |
231 | #define LUAI_MAXSHORTLEN 40 | 245 | #define LUA_PROMPT "> " |
232 | 246 | #define LUA_PROMPT2 ">> " | |
233 | 247 | ||
234 | 248 | ||
235 | /* | 249 | /* |
236 | ** {================================================================== | 250 | @@ LUA_PROGNAME is the default name for the stand-alone Lua program. |
237 | ** Compatibility with previous versions | 251 | ** CHANGE it if your stand-alone interpreter has a different name and |
238 | ** =================================================================== | 252 | ** your system is not able to detect that name automatically. |
239 | */ | 253 | */ |
254 | #define LUA_PROGNAME "lua" | ||
255 | |||
240 | 256 | ||
241 | /* | 257 | /* |
242 | @@ LUA_COMPAT_ALL controls all compatibility options. | 258 | @@ LUA_MAXINPUT is the maximum length for an input line in the |
243 | ** You can define it to get all options, or change specific options | 259 | @* stand-alone interpreter. |
244 | ** to fit your specific needs. | 260 | ** CHANGE it if you need longer lines. |
245 | */ | 261 | */ |
246 | #if defined(LUA_COMPAT_ALL) /* { */ | 262 | #define LUA_MAXINPUT 512 |
263 | |||
247 | 264 | ||
248 | /* | 265 | /* |
249 | @@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. | 266 | @@ lua_readline defines how to show a prompt and then read a line from |
250 | ** You can replace it with 'table.unpack'. | 267 | @* the standard input. |
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). | ||
251 | */ | 272 | */ |
252 | #define LUA_COMPAT_UNPACK | 273 | #if defined(LUA_USE_READLINE) |
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 | |||
253 | 294 | ||
254 | /* | 295 | /* |
255 | @@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. | 296 | @@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles |
256 | ** You can replace it with 'package.searchers'. | 297 | @* as a percentage. |
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. | ||
257 | */ | 301 | */ |
258 | #define LUA_COMPAT_LOADERS | 302 | #define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ |
303 | |||
259 | 304 | ||
260 | /* | 305 | /* |
261 | @@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. | 306 | @@ LUAI_GCMUL defines the default speed of garbage collection relative to |
262 | ** You can call your C function directly (with light C functions). | 307 | @* memory allocation as a percentage. |
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. | ||
263 | */ | 312 | */ |
264 | #define lua_cpcall(L,f,u) \ | 313 | #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ |
265 | (lua_pushcfunction(L, (f)), \ | 314 | |
266 | lua_pushlightuserdata(L,(u)), \ | ||
267 | lua_pcall(L,1,0,0)) | ||
268 | 315 | ||
269 | 316 | ||
270 | /* | 317 | /* |
271 | @@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. | 318 | @@ LUA_COMPAT_GETN controls compatibility with old getn behavior. |
272 | ** You can rewrite 'log10(x)' as 'log(x, 10)'. | 319 | ** CHANGE it (define it) if you want exact compatibility with the |
320 | ** behavior of setn/getn in Lua 5.0. | ||
273 | */ | 321 | */ |
274 | #define LUA_COMPAT_LOG10 | 322 | #undef LUA_COMPAT_GETN |
275 | 323 | ||
276 | /* | 324 | /* |
277 | @@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base | 325 | @@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. |
278 | ** library. You can rewrite 'loadstring(s)' as 'load(s)'. | 326 | ** CHANGE it to undefined as soon as you do not need a global 'loadlib' |
327 | ** function (the function is still available as 'package.loadlib'). | ||
279 | */ | 328 | */ |
280 | #define LUA_COMPAT_LOADSTRING | 329 | #undef LUA_COMPAT_LOADLIB |
281 | 330 | ||
282 | /* | 331 | /* |
283 | @@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. | 332 | @@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. |
333 | ** CHANGE it to undefined as soon as your programs use only '...' to | ||
334 | ** access vararg parameters (instead of the old 'arg' table). | ||
284 | */ | 335 | */ |
285 | #define LUA_COMPAT_MAXN | 336 | #undef LUA_COMPAT_VARARG |
286 | 337 | ||
287 | /* | 338 | /* |
288 | @@ The following macros supply trivial compatibility for some | 339 | @@ LUA_COMPAT_MOD controls compatibility with old math.mod function. |
289 | ** changes in the API. The macros themselves document how to | 340 | ** CHANGE it to undefined as soon as your programs use 'math.fmod' or |
290 | ** change your code to avoid using them. | 341 | ** the new '%' operator instead of 'math.mod'. |
291 | */ | 342 | */ |
292 | #define lua_strlen(L,i) lua_rawlen(L, (i)) | 343 | #undef LUA_COMPAT_MOD |
293 | 344 | ||
294 | #define lua_objlen(L,i) lua_rawlen(L, (i)) | 345 | /* |
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 | ||
295 | 352 | ||
296 | #define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) | 353 | /* |
297 | #define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) | 354 | @@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. |
355 | ** CHANGE it to undefined as soon as you rename 'string.gfind' to | ||
356 | ** 'string.gmatch'. | ||
357 | */ | ||
358 | #undef LUA_COMPAT_GFIND | ||
298 | 359 | ||
299 | /* | 360 | /* |
300 | @@ LUA_COMPAT_MODULE controls compatibility with previous | 361 | @@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' |
301 | ** module functions 'module' (Lua) and 'luaL_register' (C). | 362 | @* behavior. |
363 | ** CHANGE it to undefined as soon as you replace to 'luaL_registry' | ||
364 | ** your uses of 'luaL_openlib' | ||
302 | */ | 365 | */ |
303 | #define LUA_COMPAT_MODULE | 366 | #undef LUA_COMPAT_OPENLIB |
304 | 367 | ||
305 | #endif /* } */ | ||
306 | #define LUA_COMPAT_MODULE | ||
307 | 368 | ||
308 | /* }================================================================== */ | ||
309 | 369 | ||
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 | ||
310 | 383 | ||
311 | 384 | ||
312 | /* | 385 | /* |
@@ -315,65 +388,108 @@ | |||
315 | ** your machine. Probably you do not need to change this. | 388 | ** your machine. Probably you do not need to change this. |
316 | */ | 389 | */ |
317 | /* avoid overflows in comparison */ | 390 | /* avoid overflows in comparison */ |
318 | #if INT_MAX-20 < 32760 /* { */ | 391 | #if INT_MAX-20 < 32760 |
319 | #define LUAI_BITSINT 16 | 392 | #define LUAI_BITSINT 16 |
320 | #elif INT_MAX > 2147483640L /* }{ */ | 393 | #elif INT_MAX > 2147483640L |
321 | /* int has at least 32 bits */ | 394 | /* int has at least 32 bits */ |
322 | #define LUAI_BITSINT 32 | 395 | #define LUAI_BITSINT 32 |
323 | #else /* }{ */ | 396 | #else |
324 | #error "you must define LUA_BITSINT with number of bits in an integer" | 397 | #error "you must define LUA_BITSINT with number of bits in an integer" |
325 | #endif /* } */ | 398 | #endif |
326 | 399 | ||
327 | 400 | ||
328 | /* | 401 | /* |
329 | @@ LUA_INT32 is an signed integer with exactly 32 bits. | 402 | @@ LUAI_UINT32 is an unsigned integer with at least 32 bits. |
403 | @@ LUAI_INT32 is an signed integer with at least 32 bits. | ||
330 | @@ LUAI_UMEM is an unsigned integer big enough to count the total | 404 | @@ LUAI_UMEM is an unsigned integer big enough to count the total |
331 | @* memory used by Lua. | 405 | @* memory used by Lua. |
332 | @@ LUAI_MEM is a signed integer big enough to count the total memory | 406 | @@ LUAI_MEM is a signed integer big enough to count the total memory |
333 | @* used by Lua. | 407 | @* used by Lua. |
334 | ** CHANGE here if for some weird reason the default definitions are not | 408 | ** CHANGE here if for some weird reason the default definitions are not |
335 | ** good enough for your machine. Probably you do not need to change | 409 | ** good enough for your machine. (The definitions in the 'else' |
336 | ** this. | 410 | ** part always works, but may waste space on machines with 64-bit |
411 | ** longs.) Probably you do not need to change this. | ||
337 | */ | 412 | */ |
338 | #if LUAI_BITSINT >= 32 /* { */ | 413 | #if LUAI_BITSINT >= 32 |
339 | #define LUA_INT32 int | 414 | #define LUAI_UINT32 unsigned int |
415 | #define LUAI_INT32 int | ||
416 | #define LUAI_MAXINT32 INT_MAX | ||
340 | #define LUAI_UMEM size_t | 417 | #define LUAI_UMEM size_t |
341 | #define LUAI_MEM ptrdiff_t | 418 | #define LUAI_MEM ptrdiff_t |
342 | #else /* }{ */ | 419 | #else |
343 | /* 16-bit ints */ | 420 | /* 16-bit ints */ |
344 | #define LUA_INT32 long | 421 | #define LUAI_UINT32 unsigned long |
422 | #define LUAI_INT32 long | ||
423 | #define LUAI_MAXINT32 LONG_MAX | ||
345 | #define LUAI_UMEM unsigned long | 424 | #define LUAI_UMEM unsigned long |
346 | #define LUAI_MEM long | 425 | #define LUAI_MEM long |
347 | #endif /* } */ | 426 | #endif |
348 | 427 | ||
349 | 428 | ||
350 | /* | 429 | /* |
351 | @@ LUAI_MAXSTACK limits the size of the Lua stack. | 430 | @@ LUAI_MAXCALLS limits the number of nested calls. |
352 | ** CHANGE it if you need a different limit. This limit is arbitrary; | 431 | ** CHANGE it if you need really deep recursive calls. This limit is |
353 | ** its only purpose is to stop Lua to consume unlimited stack | 432 | ** arbitrary; its only purpose is to stop infinite recursion before |
354 | ** space (and to reserve some numbers for pseudo-indices). | 433 | ** exhausting memory. |
355 | */ | 434 | */ |
356 | #if LUAI_BITSINT >= 32 | 435 | #define LUAI_MAXCALLS 20000 |
357 | #define LUAI_MAXSTACK 1000000 | 436 | |
358 | #else | 437 | |
359 | #define LUAI_MAXSTACK 15000 | 438 | /* |
360 | #endif | 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 | |||
361 | 463 | ||
362 | /* reserve some space for error handling */ | 464 | /* |
363 | #define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) | 465 | @@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and |
466 | @* syntactical nested non-terminals in a program. | ||
467 | */ | ||
468 | #define LUAI_MAXCCALLS 200 | ||
364 | 469 | ||
365 | 470 | ||
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 | |||
477 | |||
478 | /* | ||
479 | @@ LUAI_MAXUPVALUES is the maximum number of upvalues per function | ||
480 | @* (must be smaller than 250). | ||
481 | */ | ||
482 | #define LUAI_MAXUPVALUES 60 | ||
366 | 483 | ||
367 | 484 | ||
368 | /* | 485 | /* |
369 | @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. | 486 | @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. |
370 | ** CHANGE it if it uses too much C-stack space. | ||
371 | */ | 487 | */ |
372 | #define LUAL_BUFFERSIZE 1024 | 488 | #define LUAL_BUFFERSIZE 1024 |
373 | 489 | ||
374 | #ifndef SIMULATOR | 490 | /* }================================================================== */ |
375 | typedef void FILE; | 491 | |
376 | #endif | 492 | |
377 | 493 | ||
378 | 494 | ||
379 | /* | 495 | /* |
@@ -400,138 +516,237 @@ typedef void FILE; | |||
400 | @@ LUA_NUMBER_FMT is the format for writing numbers. | 516 | @@ LUA_NUMBER_FMT is the format for writing numbers. |
401 | @@ lua_number2str converts a number to a string. | 517 | @@ lua_number2str converts a number to a string. |
402 | @@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. | 518 | @@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. |
519 | @@ lua_str2number converts a string to a number. | ||
403 | */ | 520 | */ |
404 | #define LUA_NUMBER_SCAN "%ld" | 521 | #define LUA_NUMBER_SCAN "%ld" |
405 | #define LUA_NUMBER_FMT "%ld" | 522 | #define LUA_NUMBER_FMT "%ld" |
406 | #define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ | 523 | #define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ |
407 | #define lua_number2str(s,n) snprintf((s), 32, LUA_NUMBER_FMT, (n)) | 524 | #define lua_number2str(s,n) snprintf((s), 32, LUA_NUMBER_FMT, (n)) |
525 | #define lua_str2number(s,p) strtol((s), (p), 10) | ||
408 | 526 | ||
409 | 527 | ||
410 | /* | 528 | /* |
411 | @@ l_mathop allows the addition of an 'l' or 'f' to all math operations | 529 | @@ The luai_num* macros define the primitive operations over numbers. |
412 | */ | 530 | */ |
413 | #define l_mathop(x) (x) | 531 | #if defined(LUA_CORE) |
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 | ||
414 | 545 | ||
415 | 546 | ||
416 | /* | 547 | /* |
417 | @@ lua_str2number converts a decimal numeric string to a number. | 548 | @@ lua_number2int is a macro to convert lua_Number to int. |
418 | @@ lua_strx2number converts an hexadecimal numeric string to a number. | 549 | @@ lua_number2integer is a macro to convert lua_Number to lua_Integer. |
419 | ** In C99, 'strtod' does both conversions. C89, however, has no function | 550 | ** CHANGE them if you know a faster way to convert a lua_Number to |
420 | ** to convert floating hexadecimal strings to numbers. For these | 551 | ** int (with any rounding method and without throwing errors) in your |
421 | ** systems, you can leave 'lua_strx2number' undefined and Lua will | 552 | ** system. In Pentium machines, a naive typecast from double to int |
422 | ** provide its own implementation. | 553 | ** in C is extremely slow, so any alternative is worth trying. |
423 | */ | 554 | */ |
424 | #define lua_str2number(s,p) strtol((s), (p), 10) | ||
425 | 555 | ||
426 | #define lua_strx2number(s,p) strtoul((s), (p), 16) | 556 | /* On a Pentium, resort to a trick */ |
557 | #if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ | ||
558 | (defined(__i386) || defined (_M_IX86) || defined(__i386__)) | ||
427 | 559 | ||
560 | /* On a Microsoft compiler, use assembler */ | ||
561 | #if defined(_MSC_VER) | ||
428 | 562 | ||
429 | /* | 563 | #define lua_number2int(i,d) __asm fld d __asm fistp i |
430 | @@ The luai_num* macros define the primitive operations over numbers. | 564 | #define lua_number2integer(i,n) lua_number2int(i, n) |
431 | */ | ||
432 | 565 | ||
566 | /* the next trick should work on any Pentium, but sometimes clashes | ||
567 | with a DirectX idiosyncrasy */ | ||
568 | #else | ||
569 | |||
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) | ||
433 | 574 | ||
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))) | ||
448 | #endif | 575 | #endif |
449 | 576 | ||
450 | 577 | ||
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 | |||
583 | #endif | ||
584 | |||
585 | /* }================================================================== */ | ||
586 | |||
451 | 587 | ||
452 | /* | 588 | /* |
453 | @@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. | 589 | @@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. |
454 | ** CHANGE that if ptrdiff_t is not adequate on your machine. (On most | 590 | ** CHANGE it if your system requires alignments larger than double. (For |
455 | ** machines, ptrdiff_t gives a good choice between int or long.) | 591 | ** instance, if your system supports long doubles and they must be |
592 | ** aligned in 16-byte boundaries, then you should add long double in the | ||
593 | ** union.) Probably you do not need to change this. | ||
456 | */ | 594 | */ |
457 | #define LUA_INTEGER ptrdiff_t | 595 | #define LUAI_USER_ALIGNMENT_T union { void *s; long l; } |
596 | |||
458 | 597 | ||
459 | /* | 598 | /* |
460 | @@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned. | 599 | @@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. |
461 | ** It must have at least 32 bits. | 600 | ** CHANGE them if you prefer to use longjmp/setjmp even with C++ |
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. | ||
462 | */ | 605 | */ |
463 | #define LUA_UNSIGNED unsigned LUA_INT32 | 606 | #if defined(__cplusplus) |
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 | ||
464 | 624 | ||
625 | #endif | ||
465 | 626 | ||
466 | 627 | ||
467 | /* | 628 | /* |
468 | ** Some tricks with doubles | 629 | @@ LUA_MAXCAPTURES is the maximum number of captures that a pattern |
630 | @* can do during pattern-matching. | ||
631 | ** CHANGE it if you need more captures. This limit is arbitrary. | ||
469 | */ | 632 | */ |
633 | #define LUA_MAXCAPTURES 32 | ||
634 | |||
470 | 635 | ||
471 | #if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ | ||
472 | /* | 636 | /* |
473 | ** The next definitions activate some tricks to speed up the | 637 | @@ lua_tmpnam is the function that the OS library uses to create a |
474 | ** conversion from doubles to integer types, mainly to LUA_UNSIGNED. | 638 | @* temporary name. |
475 | ** | 639 | @@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. |
476 | @@ LUA_MSASMTRICK uses Microsoft assembler to avoid clashes with a | 640 | ** CHANGE them if you have an alternative to tmpnam (which is considered |
477 | ** DirectX idiosyncrasy. | 641 | ** insecure) or if you want the original tmpnam anyway. By default, Lua |
478 | ** | 642 | ** uses tmpnam except when POSIX is available, where it uses mkstemp. |
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). | ||
495 | */ | 643 | */ |
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)) | ||
496 | 672 | ||
497 | /* Microsoft compiler on a Pentium (32 bit) ? */ | 673 | #elif defined(LUA_WIN) |
498 | #if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ | ||
499 | 674 | ||
500 | #define LUA_MSASMTRICK | 675 | #define lua_popen(L,c,m) ((void)L, _popen(c,m)) |
501 | #define LUA_IEEEENDIAN 0 | 676 | #define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) |
502 | #define LUA_NANTRICK | ||
503 | 677 | ||
678 | #else | ||
504 | 679 | ||
505 | /* pentium 32 bits? */ | 680 | #define lua_popen(L,c,m) ((void)((void)c, m), \ |
506 | #elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ | 681 | luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) |
682 | #define lua_pclose(L,file) ((void)((void)L, file), 0) | ||
507 | 683 | ||
508 | #define LUA_IEEE754TRICK | 684 | #endif |
509 | #define LUA_IEEELL | ||
510 | #define LUA_IEEEENDIAN 0 | ||
511 | #define LUA_NANTRICK | ||
512 | 685 | ||
513 | /* pentium 64 bits? */ | 686 | /* |
514 | #elif defined(__x86_64) /* }{ */ | 687 | @@ LUA_DL_* define which dynamic-library system Lua should use. |
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 | ||
515 | 703 | ||
516 | #define LUA_IEEE754TRICK | 704 | #if defined(LUA_WIN) |
517 | #define LUA_IEEEENDIAN 0 | 705 | #define LUA_DL_DLL |
706 | #endif | ||
518 | 707 | ||
519 | #elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ | ||
520 | 708 | ||
521 | #define LUA_IEEE754TRICK | 709 | /* |
522 | #define LUA_IEEEENDIAN 1 | 710 | @@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State |
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 | ||
523 | 716 | ||
524 | #else /* }{ */ | ||
525 | 717 | ||
526 | /* assume IEEE754 and a 32-bit integer type */ | 718 | /* |
527 | #define LUA_IEEE754TRICK | 719 | @@ luai_userstate* allow user-specific actions on threads. |
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) | ||
528 | 729 | ||
529 | #endif /* } */ | ||
530 | 730 | ||
531 | #endif /* } */ | 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 | */ | ||
532 | 738 | ||
533 | /* }================================================================== */ | 739 | #if defined(LUA_USELONGLONG) |
740 | |||
741 | #define LUA_INTFRMLEN "ll" | ||
742 | #define LUA_INTFRM_T long long | ||
534 | 743 | ||
744 | #else | ||
745 | |||
746 | #define LUA_INTFRMLEN "l" | ||
747 | #define LUA_INTFRM_T long | ||
748 | |||
749 | #endif | ||
535 | 750 | ||
536 | 751 | ||
537 | 752 | ||
@@ -543,7 +758,6 @@ extern long rb_pow(long, long); | |||
543 | */ | 758 | */ |
544 | 759 | ||
545 | #include "rockconf.h" | 760 | #include "rockconf.h" |
546 | #define LUA_USE_CTYPE 1 | ||
547 | 761 | ||
548 | #endif | 762 | #endif |
549 | 763 | ||
diff --git a/apps/plugins/lua/luadir.c b/apps/plugins/lua/luadir.c index 3c65b28bc7..c8c21d2c65 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 dir %s: %d", path, errno); | 101 | luaL_error (L, "cannot open %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 da82005c9d..d4f69fc4af 100644 --- a/apps/plugins/lua/lualib.h +++ b/apps/plugins/lua/lualib.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lualib.h,v 1.43.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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*" | ||
14 | 16 | ||
15 | LUAMOD_API int (luaopen_base) (lua_State *L); | ||
16 | 17 | ||
17 | #define LUA_COLIBNAME "coroutine" | 18 | #define LUA_COLIBNAME "coroutine" |
18 | LUAMOD_API int (luaopen_coroutine) (lua_State *L); | 19 | LUALIB_API int (luaopen_base) (lua_State *L); |
19 | 20 | ||
20 | #define LUA_TABLIBNAME "table" | 21 | #define LUA_TABLIBNAME "table" |
21 | LUAMOD_API int (luaopen_table) (lua_State *L); | 22 | LUALIB_API int (luaopen_table) (lua_State *L); |
22 | 23 | ||
23 | #define LUA_IOLIBNAME "io" | 24 | #define LUA_IOLIBNAME "io" |
24 | LUAMOD_API int (luaopen_io) (lua_State *L); | 25 | LUALIB_API int (luaopen_io) (lua_State *L); |
25 | 26 | ||
26 | #define LUA_OSLIBNAME "os" | 27 | #define LUA_OSLIBNAME "os" |
27 | LUAMOD_API int (luaopen_os) (lua_State *L); | 28 | LUALIB_API int (luaopen_os) (lua_State *L); |
28 | 29 | ||
29 | #define LUA_STRLIBNAME "string" | 30 | #define LUA_STRLIBNAME "string" |
30 | LUAMOD_API int (luaopen_string) (lua_State *L); | 31 | LUALIB_API int (luaopen_string) (lua_State *L); |
31 | |||
32 | #define LUA_BITLIBNAME "bit32" | ||
33 | LUAMOD_API int (luaopen_bit32) (lua_State *L); | ||
34 | 32 | ||
35 | #define LUA_MATHLIBNAME "math" | 33 | #define LUA_MATHLIBNAME "math" |
36 | LUAMOD_API int (luaopen_math) (lua_State *L); | 34 | LUALIB_API int (luaopen_math) (lua_State *L); |
37 | 35 | ||
38 | #define LUA_DBLIBNAME "debug" | 36 | #define LUA_DBLIBNAME "debug" |
39 | LUAMOD_API int (luaopen_debug) (lua_State *L); | 37 | LUALIB_API int (luaopen_debug) (lua_State *L); |
40 | 38 | ||
41 | #define LUA_LOADLIBNAME "package" | 39 | #define LUA_LOADLIBNAME "package" |
42 | LUAMOD_API int (luaopen_package) (lua_State *L); | 40 | LUALIB_API int (luaopen_package) (lua_State *L); |
43 | 41 | ||
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 | #if !defined(lua_assert) | 50 | #ifndef 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 0db70d20ea..8010a45795 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.22.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 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,24 +27,28 @@ typedef struct { | |||
27 | const char* name; | 27 | const char* name; |
28 | } LoadState; | 28 | } LoadState; |
29 | 29 | ||
30 | static l_noret error(LoadState* S, const char* why) | 30 | #ifdef LUAC_TRUST_BINARIES |
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) | ||
31 | { | 37 | { |
32 | luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why); | 38 | luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); |
33 | luaD_throw(S->L,LUA_ERRSYNTAX); | 39 | luaD_throw(S->L,LUA_ERRSYNTAX); |
34 | } | 40 | } |
41 | #endif | ||
35 | 42 | ||
36 | #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) | 43 | #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) |
37 | #define LoadByte(S) (lu_byte)LoadChar(S) | 44 | #define LoadByte(S) (lu_byte)LoadChar(S) |
38 | #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) | 45 | #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) |
39 | #define LoadVector(S,b,n,size) LoadMem(S,b,n,size) | 46 | #define LoadVector(S,b,n,size) LoadMem(S,b,n,size) |
40 | 47 | ||
41 | #if !defined(luai_verifycode) | ||
42 | #define luai_verifycode(L,b,f) /* empty */ | ||
43 | #endif | ||
44 | |||
45 | static void LoadBlock(LoadState* S, void* b, size_t size) | 48 | static void LoadBlock(LoadState* S, void* b, size_t size) |
46 | { | 49 | { |
47 | if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated"); | 50 | size_t r=luaZ_read(S->Z,b,size); |
51 | IF (r!=0, "unexpected end"); | ||
48 | } | 52 | } |
49 | 53 | ||
50 | static int LoadChar(LoadState* S) | 54 | static int LoadChar(LoadState* S) |
@@ -58,7 +62,7 @@ static int LoadInt(LoadState* S) | |||
58 | { | 62 | { |
59 | int x; | 63 | int x; |
60 | LoadVar(S,x); | 64 | LoadVar(S,x); |
61 | if (x<0) error(S,"corrupted"); | 65 | IF (x<0, "bad integer"); |
62 | return x; | 66 | return x; |
63 | } | 67 | } |
64 | 68 | ||
@@ -78,7 +82,7 @@ static TString* LoadString(LoadState* S) | |||
78 | else | 82 | else |
79 | { | 83 | { |
80 | char* s=luaZ_openspace(S->L,S->b,size); | 84 | char* s=luaZ_openspace(S->L,S->b,size); |
81 | LoadBlock(S,s,size*sizeof(char)); | 85 | LoadBlock(S,s,size); |
82 | return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ | 86 | return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ |
83 | } | 87 | } |
84 | } | 88 | } |
@@ -91,7 +95,7 @@ static void LoadCode(LoadState* S, Proto* f) | |||
91 | LoadVector(S,f->code,n,sizeof(Instruction)); | 95 | LoadVector(S,f->code,n,sizeof(Instruction)); |
92 | } | 96 | } |
93 | 97 | ||
94 | static void LoadFunction(LoadState* S, Proto* f); | 98 | static Proto* LoadFunction(LoadState* S, TString* p); |
95 | 99 | ||
96 | static void LoadConstants(LoadState* S, Proto* f) | 100 | static void LoadConstants(LoadState* S, Proto* f) |
97 | { | 101 | { |
@@ -107,10 +111,10 @@ static void LoadConstants(LoadState* S, Proto* f) | |||
107 | switch (t) | 111 | switch (t) |
108 | { | 112 | { |
109 | case LUA_TNIL: | 113 | case LUA_TNIL: |
110 | setnilvalue(o); | 114 | setnilvalue(o); |
111 | break; | 115 | break; |
112 | case LUA_TBOOLEAN: | 116 | case LUA_TBOOLEAN: |
113 | setbvalue(o,LoadChar(S)); | 117 | setbvalue(o,LoadChar(S)!=0); |
114 | break; | 118 | break; |
115 | case LUA_TNUMBER: | 119 | case LUA_TNUMBER: |
116 | setnvalue(o,LoadNumber(S)); | 120 | setnvalue(o,LoadNumber(S)); |
@@ -118,38 +122,21 @@ static void LoadConstants(LoadState* S, Proto* f) | |||
118 | case LUA_TSTRING: | 122 | case LUA_TSTRING: |
119 | setsvalue2n(S->L,o,LoadString(S)); | 123 | setsvalue2n(S->L,o,LoadString(S)); |
120 | break; | 124 | break; |
121 | default: lua_assert(0); | 125 | default: |
126 | error(S,"bad constant"); | ||
127 | break; | ||
122 | } | 128 | } |
123 | } | 129 | } |
124 | n=LoadInt(S); | 130 | n=LoadInt(S); |
125 | f->p=luaM_newvector(S->L,n,Proto*); | 131 | f->p=luaM_newvector(S->L,n,Proto*); |
126 | f->sizep=n; | 132 | f->sizep=n; |
127 | for (i=0; i<n; i++) f->p[i]=NULL; | 133 | for (i=0; i<n; i++) f->p[i]=NULL; |
128 | for (i=0; i<n; i++) | 134 | for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source); |
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 | } | ||
147 | } | 135 | } |
148 | 136 | ||
149 | static void LoadDebug(LoadState* S, Proto* f) | 137 | static void LoadDebug(LoadState* S, Proto* f) |
150 | { | 138 | { |
151 | int i,n; | 139 | int i,n; |
152 | f->source=LoadString(S); | ||
153 | n=LoadInt(S); | 140 | n=LoadInt(S); |
154 | f->lineinfo=luaM_newvector(S->L,n,int); | 141 | f->lineinfo=luaM_newvector(S->L,n,int); |
155 | f->sizelineinfo=n; | 142 | f->sizelineinfo=n; |
@@ -165,48 +152,49 @@ static void LoadDebug(LoadState* S, Proto* f) | |||
165 | f->locvars[i].endpc=LoadInt(S); | 152 | f->locvars[i].endpc=LoadInt(S); |
166 | } | 153 | } |
167 | n=LoadInt(S); | 154 | n=LoadInt(S); |
168 | for (i=0; i<n; i++) f->upvalues[i].name=LoadString(S); | 155 | f->upvalues=luaM_newvector(S->L,n,TString*); |
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); | ||
169 | } | 159 | } |
170 | 160 | ||
171 | static void LoadFunction(LoadState* S, Proto* f) | 161 | static Proto* LoadFunction(LoadState* S, TString* p) |
172 | { | 162 | { |
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; | ||
173 | f->linedefined=LoadInt(S); | 168 | f->linedefined=LoadInt(S); |
174 | f->lastlinedefined=LoadInt(S); | 169 | f->lastlinedefined=LoadInt(S); |
170 | f->nups=LoadByte(S); | ||
175 | f->numparams=LoadByte(S); | 171 | f->numparams=LoadByte(S); |
176 | f->is_vararg=LoadByte(S); | 172 | f->is_vararg=LoadByte(S); |
177 | f->maxstacksize=LoadByte(S); | 173 | f->maxstacksize=LoadByte(S); |
178 | LoadCode(S,f); | 174 | LoadCode(S,f); |
179 | LoadConstants(S,f); | 175 | LoadConstants(S,f); |
180 | LoadUpvalues(S,f); | ||
181 | LoadDebug(S,f); | 176 | LoadDebug(S,f); |
177 | IF (!luaG_checkcode(f), "bad code"); | ||
178 | S->L->top--; | ||
179 | S->L->nCcalls--; | ||
180 | return f; | ||
182 | } | 181 | } |
183 | 182 | ||
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 | |||
190 | static void LoadHeader(LoadState* S) | 183 | static void LoadHeader(LoadState* S) |
191 | { | 184 | { |
192 | lu_byte h[LUAC_HEADERSIZE]; | 185 | char h[LUAC_HEADERSIZE]; |
193 | lu_byte s[LUAC_HEADERSIZE]; | 186 | char s[LUAC_HEADERSIZE]; |
194 | luaU_header(h); | 187 | luaU_header(h); |
195 | memcpy(s,h,sizeof(char)); /* first char already read */ | 188 | LoadBlock(S,s,LUAC_HEADERSIZE); |
196 | LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char)); | 189 | IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); |
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"); | ||
201 | } | 190 | } |
202 | 191 | ||
203 | /* | 192 | /* |
204 | ** load precompiled chunk | 193 | ** load precompiled chunk |
205 | */ | 194 | */ |
206 | Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) | 195 | Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) |
207 | { | 196 | { |
208 | LoadState S; | 197 | LoadState S; |
209 | Closure* cl; | ||
210 | if (*name=='@' || *name=='=') | 198 | if (*name=='@' || *name=='=') |
211 | S.name=name+1; | 199 | S.name=name+1; |
212 | else if (*name==LUA_SIGNATURE[0]) | 200 | else if (*name==LUA_SIGNATURE[0]) |
@@ -217,43 +205,23 @@ Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) | |||
217 | S.Z=Z; | 205 | S.Z=Z; |
218 | S.b=buff; | 206 | S.b=buff; |
219 | LoadHeader(&S); | 207 | LoadHeader(&S); |
220 | cl=luaF_newLclosure(L,1); | 208 | return LoadFunction(&S,luaS_newliteral(L,"=?")); |
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; | ||
233 | } | 209 | } |
234 | 210 | ||
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 | |||
240 | /* | 211 | /* |
241 | * make header for precompiled chunks | 212 | * make header |
242 | * if you change the code below be sure to update LoadHeader and FORMAT above | ||
243 | * and LUAC_HEADERSIZE in lundump.h | ||
244 | */ | 213 | */ |
245 | void luaU_header (lu_byte* h) | 214 | void luaU_header (char* h) |
246 | { | 215 | { |
247 | int x=1; | 216 | int x=1; |
248 | memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char)); | 217 | memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); |
249 | h+=sizeof(LUA_SIGNATURE)-sizeof(char); | 218 | h+=sizeof(LUA_SIGNATURE)-1; |
250 | *h++=cast_byte(VERSION); | 219 | *h++=(char)LUAC_VERSION; |
251 | *h++=cast_byte(FORMAT); | 220 | *h++=(char)LUAC_FORMAT; |
252 | *h++=cast_byte(*(char*)&x); /* endianness */ | 221 | *h++=(char)*(char*)&x; /* endianness */ |
253 | *h++=cast_byte(sizeof(int)); | 222 | *h++=(char)sizeof(int); |
254 | *h++=cast_byte(sizeof(size_t)); | 223 | *h++=(char)sizeof(size_t); |
255 | *h++=cast_byte(sizeof(Instruction)); | 224 | *h++=(char)sizeof(Instruction); |
256 | *h++=cast_byte(sizeof(lua_Number)); | 225 | *h++=(char)sizeof(lua_Number); |
257 | *h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */ | 226 | *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ |
258 | memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char)); | ||
259 | } | 227 | } |
diff --git a/apps/plugins/lua/lundump.h b/apps/plugins/lua/lundump.h index 5255db259d..f791a4f173 100644 --- a/apps/plugins/lua/lundump.h +++ b/apps/plugins/lua/lundump.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lundump.h,v 1.39.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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,18 +11,26 @@ | |||
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 Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); | 14 | LUAI_FUNC Proto* 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 (lu_byte* h); | 17 | LUAI_FUNC void luaU_header (char* 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 | /* data to catch conversion errors */ | 22 | #ifdef luac_c |
23 | #define LUAC_TAIL "\x19\x93\r\n\x1a\n" | 23 | /* print one chunk; from print.c */ |
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 | ||
24 | 32 | ||
25 | /* size in bytes of header of binary files */ | 33 | /* size of header of binary files */ |
26 | #define LUAC_HEADERSIZE (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char)) | 34 | #define LUAC_HEADERSIZE 12 |
27 | 35 | ||
28 | #endif | 36 | #endif |
diff --git a/apps/plugins/lua/lvm.c b/apps/plugins/lua/lvm.c index 141b9fd19c..ee3256ab94 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.155.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 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), tsvalue(obj)->len, &num)) { | 38 | if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { |
39 | setnvalue(n, num); | 39 | setnvalue(n, num); |
40 | return n; | 40 | return n; |
41 | } | 41 | } |
@@ -50,60 +50,58 @@ 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 | int l = lua_number2str(s, n); | 53 | lua_number2str(s, n); |
54 | setsvalue2s(L, obj, luaS_newlstr(L, s, l)); | 54 | setsvalue2s(L, obj, luaS_new(L, s)); |
55 | return 1; | 55 | return 1; |
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | 59 | ||
60 | static void traceexec (lua_State *L) { | 60 | static void traceexec (lua_State *L, const Instruction *pc) { |
61 | CallInfo *ci = L->ci; | ||
62 | lu_byte mask = L->hookmask; | 61 | lu_byte mask = L->hookmask; |
63 | int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0); | 62 | const Instruction *oldpc = L->savedpc; |
64 | if (counthook) | 63 | L->savedpc = pc; |
65 | resethookcount(L); /* reset count */ | 64 | if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { |
66 | if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ | 65 | resethookcount(L); |
67 | ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ | 66 | luaD_callhook(L, LUA_HOOKCOUNT, -1); |
68 | return; /* do not call hook again (VM yielded, so it did not move) */ | ||
69 | } | 67 | } |
70 | if (counthook) | ||
71 | luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ | ||
72 | if (mask & LUA_MASKLINE) { | 68 | if (mask & LUA_MASKLINE) { |
73 | Proto *p = ci_func(ci)->p; | 69 | Proto *p = ci_func(L->ci)->l.p; |
74 | int npc = pcRel(ci->u.l.savedpc, p); | 70 | int npc = pcRel(pc, p); |
75 | int newline = getfuncline(p, npc); | 71 | int newline = getline(p, npc); |
76 | if (npc == 0 || /* call linehook when enter a new function, */ | 72 | /* call linehook when enter a new function, when jump back (loop), |
77 | ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ | 73 | or when enter a new line */ |
78 | newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ | 74 | if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) |
79 | luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ | 75 | luaD_callhook(L, LUA_HOOKLINE, newline); |
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); | ||
89 | } | 76 | } |
90 | } | 77 | } |
91 | 78 | ||
92 | 79 | ||
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 | |||
93 | static void callTM (lua_State *L, const TValue *f, const TValue *p1, | 96 | static void callTM (lua_State *L, const TValue *f, const TValue *p1, |
94 | const TValue *p2, TValue *p3, int hasres) { | 97 | const TValue *p2, const TValue *p3) { |
95 | ptrdiff_t result = savestack(L, p3); | 98 | setobj2s(L, L->top, f); /* push function */ |
96 | setobj2s(L, L->top++, f); /* push function */ | 99 | setobj2s(L, L->top+1, p1); /* 1st argument */ |
97 | setobj2s(L, L->top++, p1); /* 1st argument */ | 100 | setobj2s(L, L->top+2, p2); /* 2nd argument */ |
98 | setobj2s(L, L->top++, p2); /* 2nd argument */ | 101 | setobj2s(L, L->top+3, p3); /* 3th argument */ |
99 | if (!hasres) /* no result? 'p3' is third argument */ | 102 | luaD_checkstack(L, 4); |
100 | setobj2s(L, L->top++, p3); /* 3rd argument */ | 103 | L->top += 4; |
101 | /* metamethod may yield only when called from Lua code */ | 104 | luaD_call(L, L->top - 4, 0); |
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 | } | ||
107 | } | 105 | } |
108 | 106 | ||
109 | 107 | ||
@@ -114,7 +112,7 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
114 | if (ttistable(t)) { /* `t' is a table? */ | 112 | if (ttistable(t)) { /* `t' is a table? */ |
115 | Table *h = hvalue(t); | 113 | Table *h = hvalue(t); |
116 | const TValue *res = luaH_get(h, key); /* do a primitive get */ | 114 | const TValue *res = luaH_get(h, key); /* do a primitive get */ |
117 | if (!ttisnil(res) || /* result is not nil? */ | 115 | if (!ttisnil(res) || /* result is no nil? */ |
118 | (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ | 116 | (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ |
119 | setobj2s(L, val, res); | 117 | setobj2s(L, val, res); |
120 | return; | 118 | return; |
@@ -124,10 +122,10 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
124 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) | 122 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) |
125 | luaG_typeerror(L, t, "index"); | 123 | luaG_typeerror(L, t, "index"); |
126 | if (ttisfunction(tm)) { | 124 | if (ttisfunction(tm)) { |
127 | callTM(L, tm, t, key, val, 1); | 125 | callTMres(L, val, tm, t, key); |
128 | return; | 126 | return; |
129 | } | 127 | } |
130 | t = tm; /* else repeat with 'tm' */ | 128 | t = tm; /* else repeat with `tm' */ |
131 | } | 129 | } |
132 | luaG_runerror(L, "loop in gettable"); | 130 | luaG_runerror(L, "loop in gettable"); |
133 | } | 131 | } |
@@ -139,34 +137,22 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
139 | const TValue *tm; | 137 | const TValue *tm; |
140 | if (ttistable(t)) { /* `t' is a table? */ | 138 | if (ttistable(t)) { /* `t' is a table? */ |
141 | Table *h = hvalue(t); | 139 | Table *h = hvalue(t); |
142 | TValue *oldval = cast(TValue *, luaH_get(h, key)); | 140 | TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ |
143 | /* if previous value is not nil, there must be a previous entry | 141 | if (!ttisnil(oldval) || /* result is no nil? */ |
144 | in the table; moreover, a metamethod has no relevance */ | 142 | (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ |
145 | if (!ttisnil(oldval) || | 143 | setobj2t(L, oldval, val); |
146 | /* previous value is nil; must check the metamethod */ | 144 | luaC_barriert(L, h, val); |
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); | ||
157 | return; | 145 | return; |
158 | } | 146 | } |
159 | /* else will try the metamethod */ | 147 | /* else will try the tag method */ |
160 | } | 148 | } |
161 | else /* not a table; check metamethod */ | 149 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) |
162 | if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) | 150 | luaG_typeerror(L, t, "index"); |
163 | luaG_typeerror(L, t, "index"); | ||
164 | /* there is a metamethod */ | ||
165 | if (ttisfunction(tm)) { | 151 | if (ttisfunction(tm)) { |
166 | callTM(L, tm, t, key, val, 0); | 152 | callTM(L, tm, t, key, val); |
167 | return; | 153 | return; |
168 | } | 154 | } |
169 | t = tm; /* else repeat with 'tm' */ | 155 | t = tm; /* else repeat with `tm' */ |
170 | } | 156 | } |
171 | luaG_runerror(L, "loop in settable"); | 157 | luaG_runerror(L, "loop in settable"); |
172 | } | 158 | } |
@@ -178,12 +164,12 @@ static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, | |||
178 | if (ttisnil(tm)) | 164 | if (ttisnil(tm)) |
179 | tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ | 165 | tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ |
180 | if (ttisnil(tm)) return 0; | 166 | if (ttisnil(tm)) return 0; |
181 | callTM(L, tm, p1, p2, res, 1); | 167 | callTMres(L, res, tm, p1, p2); |
182 | return 1; | 168 | return 1; |
183 | } | 169 | } |
184 | 170 | ||
185 | 171 | ||
186 | static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2, | 172 | static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, |
187 | TMS event) { | 173 | TMS event) { |
188 | const TValue *tm1 = fasttm(L, mt1, event); | 174 | const TValue *tm1 = fasttm(L, mt1, event); |
189 | const TValue *tm2; | 175 | const TValue *tm2; |
@@ -191,7 +177,7 @@ static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2, | |||
191 | if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ | 177 | if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ |
192 | tm2 = fasttm(L, mt2, event); | 178 | tm2 = fasttm(L, mt2, event); |
193 | if (tm2 == NULL) return NULL; /* no metamethod */ | 179 | if (tm2 == NULL) return NULL; /* no metamethod */ |
194 | if (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */ | 180 | if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ |
195 | return tm1; | 181 | return tm1; |
196 | return NULL; | 182 | return NULL; |
197 | } | 183 | } |
@@ -199,10 +185,14 @@ static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2, | |||
199 | 185 | ||
200 | static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, | 186 | static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, |
201 | TMS event) { | 187 | TMS event) { |
202 | if (!call_binTM(L, p1, p2, L->top, event)) | 188 | const TValue *tm1 = luaT_gettmbyobj(L, p1, event); |
203 | return -1; /* no metamethod */ | 189 | const TValue *tm2; |
204 | else | 190 | if (ttisnil(tm1)) return -1; /* no metamethod? */ |
205 | return !l_isfalse(L->top); | 191 | tm2 = luaT_gettmbyobj(L, p2, event); |
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); | ||
206 | } | 196 | } |
207 | 197 | ||
208 | 198 | ||
@@ -230,261 +220,125 @@ static int l_strcmp (const TString *ls, const TString *rs) { | |||
230 | 220 | ||
231 | int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { | 221 | int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { |
232 | int res; | 222 | int res; |
233 | if (ttisnumber(l) && ttisnumber(r)) | 223 | if (ttype(l) != ttype(r)) |
234 | return luai_numlt(L, nvalue(l), nvalue(r)); | 224 | return luaG_ordererror(L, l, r); |
235 | else if (ttisstring(l) && ttisstring(r)) | 225 | else if (ttisnumber(l)) |
226 | return luai_numlt(nvalue(l), nvalue(r)); | ||
227 | else if (ttisstring(l)) | ||
236 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; | 228 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; |
237 | else if ((res = call_orderTM(L, l, r, TM_LT)) < 0) | 229 | else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) |
238 | luaG_ordererror(L, l, r); | 230 | return res; |
239 | return res; | 231 | return luaG_ordererror(L, l, r); |
240 | } | 232 | } |
241 | 233 | ||
242 | 234 | ||
243 | int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { | 235 | static int lessequal (lua_State *L, const TValue *l, const TValue *r) { |
244 | int res; | 236 | int res; |
245 | if (ttisnumber(l) && ttisnumber(r)) | 237 | if (ttype(l) != ttype(r)) |
246 | return luai_numle(L, nvalue(l), nvalue(r)); | 238 | return luaG_ordererror(L, l, r); |
247 | else if (ttisstring(l) && ttisstring(r)) | 239 | else if (ttisnumber(l)) |
240 | return luai_numle(nvalue(l), nvalue(r)); | ||
241 | else if (ttisstring(l)) | ||
248 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; | 242 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; |
249 | else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ | 243 | else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ |
250 | return res; | 244 | return res; |
251 | else if ((res = call_orderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */ | 245 | else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ |
252 | luaG_ordererror(L, l, r); | 246 | return !res; |
253 | return !res; | 247 | return luaG_ordererror(L, l, r); |
254 | } | 248 | } |
255 | 249 | ||
256 | 250 | ||
257 | /* | 251 | int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { |
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) { | ||
261 | const TValue *tm; | 252 | const TValue *tm; |
262 | lua_assert(ttisequal(t1, t2)); | 253 | lua_assert(ttype(t1) == ttype(t2)); |
263 | switch (ttype(t1)) { | 254 | switch (ttype(t1)) { |
264 | case LUA_TNIL: return 1; | 255 | case LUA_TNIL: return 1; |
265 | case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); | 256 | case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); |
266 | case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ | 257 | case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ |
267 | case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); | 258 | 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)); | ||
271 | case LUA_TUSERDATA: { | 259 | case LUA_TUSERDATA: { |
272 | if (uvalue(t1) == uvalue(t2)) return 1; | 260 | if (uvalue(t1) == uvalue(t2)) return 1; |
273 | else if (L == NULL) return 0; | 261 | tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, |
274 | tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ); | 262 | TM_EQ); |
275 | break; /* will try TM */ | 263 | break; /* will try TM */ |
276 | } | 264 | } |
277 | case LUA_TTABLE: { | 265 | case LUA_TTABLE: { |
278 | if (hvalue(t1) == hvalue(t2)) return 1; | 266 | if (hvalue(t1) == hvalue(t2)) return 1; |
279 | else if (L == NULL) return 0; | 267 | tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); |
280 | tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); | ||
281 | break; /* will try TM */ | 268 | break; /* will try TM */ |
282 | } | 269 | } |
283 | default: | 270 | default: return gcvalue(t1) == gcvalue(t2); |
284 | lua_assert(iscollectable(t1)); | ||
285 | return gcvalue(t1) == gcvalue(t2); | ||
286 | } | 271 | } |
287 | if (tm == NULL) return 0; /* no TM? */ | 272 | if (tm == NULL) return 0; /* no TM? */ |
288 | callTM(L, tm, t1, t2, L->top, 1); /* call TM */ | 273 | callTMres(L, L->top, tm, t1, t2); /* call TM */ |
289 | return !l_isfalse(L->top); | 274 | return !l_isfalse(L->top); |
290 | } | 275 | } |
291 | 276 | ||
292 | 277 | ||
293 | void luaV_concat (lua_State *L, int total) { | 278 | void luaV_concat (lua_State *L, int total, int last) { |
294 | lua_assert(total >= 2); | ||
295 | do { | 279 | do { |
296 | StkId top = L->top; | 280 | StkId top = L->base + last + 1; |
297 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 281 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
298 | if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { | 282 | if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { |
299 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) | 283 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) |
300 | luaG_concaterror(L, top-2, top-1); | 284 | luaG_concaterror(L, top-2, top-1); |
301 | } | 285 | } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ |
302 | else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ | 286 | (void)tostring(L, top - 2); /* result is first op (as string) */ |
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 | } | ||
307 | else { | 287 | else { |
308 | /* at least two non-empty string values; get as many as possible */ | 288 | /* at least two string values; get as many as possible */ |
309 | size_t tl = tsvalue(top-1)->len; | 289 | size_t tl = tsvalue(top-1)->len; |
310 | char *buffer; | 290 | char *buffer; |
311 | int i; | 291 | int i; |
312 | /* collect total length */ | 292 | /* collect total length */ |
313 | for (i = 1; i < total && tostring(L, top-i-1); i++) { | 293 | for (n = 1; n < total && tostring(L, top-n-1); n++) { |
314 | size_t l = tsvalue(top-i-1)->len; | 294 | size_t l = tsvalue(top-n-1)->len; |
315 | if (l >= (MAX_SIZET/sizeof(char)) - tl) | 295 | if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); |
316 | luaG_runerror(L, "string length overflow"); | ||
317 | tl += l; | 296 | tl += l; |
318 | } | 297 | } |
319 | buffer = luaZ_openspace(L, &G(L)->buff, tl); | 298 | buffer = luaZ_openspace(L, &G(L)->buff, tl); |
320 | tl = 0; | 299 | tl = 0; |
321 | n = i; | 300 | for (i=n; i>0; i--) { /* concat all strings */ |
322 | do { /* concat all strings */ | ||
323 | size_t l = tsvalue(top-i)->len; | 301 | size_t l = tsvalue(top-i)->len; |
324 | memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); | 302 | memcpy(buffer+tl, svalue(top-i), l); |
325 | tl += l; | 303 | tl += l; |
326 | } while (--i > 0); | 304 | } |
327 | setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); | 305 | setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); |
328 | } | 306 | } |
329 | total -= n-1; /* got 'n' strings to create 1 new */ | 307 | total -= n-1; /* got `n' strings to create 1 new */ |
330 | L->top -= n-1; /* popped 'n' strings and pushed one */ | 308 | last -= n-1; |
331 | } while (total > 1); /* repeat until only 1 result left */ | 309 | } while (total > 1); /* repeat until only 1 result left */ |
332 | } | 310 | } |
333 | 311 | ||
334 | 312 | ||
335 | void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { | 313 | static void Arith (lua_State *L, StkId ra, const TValue *rb, |
336 | const TValue *tm; | 314 | const TValue *rc, TMS op) { |
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) { | ||
362 | TValue tempb, tempc; | 315 | TValue tempb, tempc; |
363 | const TValue *b, *c; | 316 | const TValue *b, *c; |
364 | if ((b = luaV_tonumber(rb, &tempb)) != NULL && | 317 | if ((b = luaV_tonumber(rb, &tempb)) != NULL && |
365 | (c = luaV_tonumber(rc, &tempc)) != NULL) { | 318 | (c = luaV_tonumber(rc, &tempc)) != NULL) { |
366 | lua_Number res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c)); | 319 | lua_Number nb = nvalue(b), nc = nvalue(c); |
367 | setnvalue(ra, res); | 320 | switch (op) { |
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 | } | ||
368 | } | 330 | } |
369 | else if (!call_binTM(L, rb, rc, ra, op)) | 331 | else if (!call_binTM(L, rb, rc, ra, op)) |
370 | luaG_aritherror(L, rb, rc); | 332 | luaG_aritherror(L, rb, rc); |
371 | } | 333 | } |
372 | 334 | ||
373 | 335 | ||
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 | |||
479 | 336 | ||
480 | /* | 337 | /* |
481 | ** some macros for common tasks in `luaV_execute' | 338 | ** some macros for common tasks in `luaV_execute' |
482 | */ | 339 | */ |
483 | 340 | ||
484 | #if !defined luai_runtimecheck | 341 | #define runtime_check(L, c) { if (!(c)) break; } |
485 | #define luai_runtimecheck(L, c) /* void */ | ||
486 | #endif | ||
487 | |||
488 | 342 | ||
489 | #define RA(i) (base+GETARG_A(i)) | 343 | #define RA(i) (base+GETARG_A(i)) |
490 | /* to be used after possible stack reallocation */ | 344 | /* to be used after possible stack reallocation */ |
@@ -494,27 +348,13 @@ void luaV_finishOp (lua_State *L) { | |||
494 | ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) | 348 | ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) |
495 | #define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ | 349 | #define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ |
496 | ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) | 350 | ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) |
497 | #define KBx(i) \ | 351 | #define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) |
498 | (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++))) | ||
499 | |||
500 | 352 | ||
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; } | ||
506 | 353 | ||
507 | /* for test instructions, execute the jump instruction that follows it */ | 354 | #define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} |
508 | #define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); } | ||
509 | 355 | ||
510 | 356 | ||
511 | #define Protect(x) { {x;}; base = ci->u.l.base; } | 357 | #define Protect(x) { L->savedpc = pc; {x;}; base = 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); ) | ||
518 | 358 | ||
519 | 359 | ||
520 | #define arith_op(op,tm) { \ | 360 | #define arith_op(op,tm) { \ |
@@ -522,345 +362,401 @@ void luaV_finishOp (lua_State *L) { | |||
522 | TValue *rc = RKC(i); \ | 362 | TValue *rc = RKC(i); \ |
523 | if (ttisnumber(rb) && ttisnumber(rc)) { \ | 363 | if (ttisnumber(rb) && ttisnumber(rc)) { \ |
524 | lua_Number nb = nvalue(rb), nc = nvalue(rc); \ | 364 | lua_Number nb = nvalue(rb), nc = nvalue(rc); \ |
525 | setnvalue(ra, op(L, nb, nc)); \ | 365 | setnvalue(ra, op(nb, nc)); \ |
526 | } \ | 366 | } \ |
527 | else { Protect(luaV_arith(L, ra, rb, rc, tm)); } } | 367 | else \ |
368 | Protect(Arith(L, ra, rb, rc, tm)); \ | ||
369 | } | ||
528 | 370 | ||
529 | 371 | ||
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 */ | ||
533 | 372 | ||
534 | void luaV_execute (lua_State *L) { | 373 | void luaV_execute (lua_State *L, int nexeccalls) { |
535 | CallInfo *ci = L->ci; | ||
536 | LClosure *cl; | 374 | LClosure *cl; |
537 | TValue *k; | ||
538 | StkId base; | 375 | StkId base; |
539 | newframe: /* reentry point when frame changes (call/return) */ | 376 | TValue *k; |
540 | lua_assert(ci == L->ci); | 377 | const Instruction *pc; |
541 | cl = clLvalue(ci->func); | 378 | reentry: /* entry point */ |
379 | lua_assert(isLua(L->ci)); | ||
380 | pc = L->savedpc; | ||
381 | cl = &clvalue(L->ci->func)->l; | ||
382 | base = L->base; | ||
542 | k = cl->p->k; | 383 | k = cl->p->k; |
543 | base = ci->u.l.base; | ||
544 | /* main loop of interpreter */ | 384 | /* main loop of interpreter */ |
545 | for (;;) { | 385 | for (;;) { |
546 | Instruction i = *(ci->u.l.savedpc++); | 386 | const Instruction i = *pc++; |
547 | StkId ra; | 387 | StkId ra; |
548 | if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && | 388 | if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && |
549 | (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { | 389 | (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { |
550 | Protect(traceexec(L)); | 390 | traceexec(L, pc); |
391 | if (L->status == LUA_YIELD) { /* did hook yield? */ | ||
392 | L->savedpc = pc - 1; | ||
393 | return; | ||
394 | } | ||
395 | base = L->base; | ||
551 | } | 396 | } |
552 | /* WARNING: several calls may realloc the stack and invalidate `ra' */ | 397 | /* warning!! several calls may realloc the stack and invalidate `ra' */ |
553 | ra = RA(i); | 398 | ra = RA(i); |
554 | lua_assert(base == ci->u.l.base); | 399 | lua_assert(base == L->base && L->base == L->ci->base); |
555 | lua_assert(base <= L->top && L->top < L->stack + L->stacksize); | 400 | lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); |
556 | vmdispatch (GET_OPCODE(i)) { | 401 | lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); |
557 | vmcase(OP_MOVE, | 402 | switch (GET_OPCODE(i)) { |
403 | case OP_MOVE: { | ||
558 | setobjs2s(L, ra, RB(i)); | 404 | setobjs2s(L, ra, RB(i)); |
559 | ) | 405 | continue; |
560 | vmcase(OP_LOADK, | 406 | } |
561 | TValue *rb = k + GETARG_Bx(i); | 407 | case OP_LOADK: { |
562 | setobj2s(L, ra, rb); | 408 | setobj2s(L, ra, KBx(i)); |
563 | ) | 409 | continue; |
564 | vmcase(OP_LOADKX, | 410 | } |
565 | TValue *rb; | 411 | case OP_LOADBOOL: { |
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, | ||
571 | setbvalue(ra, GETARG_B(i)); | 412 | setbvalue(ra, GETARG_B(i)); |
572 | if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ | 413 | if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ |
573 | ) | 414 | continue; |
574 | vmcase(OP_LOADNIL, | 415 | } |
575 | int b = GETARG_B(i); | 416 | case OP_LOADNIL: { |
417 | TValue *rb = RB(i); | ||
576 | do { | 418 | do { |
577 | setnilvalue(ra++); | 419 | setnilvalue(rb--); |
578 | } while (b--); | 420 | } while (rb >= ra); |
579 | ) | 421 | continue; |
580 | vmcase(OP_GETUPVAL, | 422 | } |
423 | case OP_GETUPVAL: { | ||
581 | int b = GETARG_B(i); | 424 | int b = GETARG_B(i); |
582 | setobj2s(L, ra, cl->upvals[b]->v); | 425 | setobj2s(L, ra, cl->upvals[b]->v); |
583 | ) | 426 | continue; |
584 | vmcase(OP_GETTABUP, | 427 | } |
585 | int b = GETARG_B(i); | 428 | case OP_GETGLOBAL: { |
586 | Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); | 429 | TValue g; |
587 | ) | 430 | TValue *rb = KBx(i); |
588 | vmcase(OP_GETTABLE, | 431 | sethvalue(L, &g, cl->env); |
432 | lua_assert(ttisstring(rb)); | ||
433 | Protect(luaV_gettable(L, &g, rb, ra)); | ||
434 | continue; | ||
435 | } | ||
436 | case OP_GETTABLE: { | ||
589 | Protect(luaV_gettable(L, RB(i), RKC(i), ra)); | 437 | Protect(luaV_gettable(L, RB(i), RKC(i), ra)); |
590 | ) | 438 | continue; |
591 | vmcase(OP_SETTABUP, | 439 | } |
592 | int a = GETARG_A(i); | 440 | case OP_SETGLOBAL: { |
593 | Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i))); | 441 | TValue g; |
594 | ) | 442 | sethvalue(L, &g, cl->env); |
595 | vmcase(OP_SETUPVAL, | 443 | lua_assert(ttisstring(KBx(i))); |
444 | Protect(luaV_settable(L, &g, KBx(i), ra)); | ||
445 | continue; | ||
446 | } | ||
447 | case OP_SETUPVAL: { | ||
596 | UpVal *uv = cl->upvals[GETARG_B(i)]; | 448 | UpVal *uv = cl->upvals[GETARG_B(i)]; |
597 | setobj(L, uv->v, ra); | 449 | setobj(L, uv->v, ra); |
598 | luaC_barrier(L, uv, ra); | 450 | luaC_barrier(L, uv, ra); |
599 | ) | 451 | continue; |
600 | vmcase(OP_SETTABLE, | 452 | } |
453 | case OP_SETTABLE: { | ||
601 | Protect(luaV_settable(L, ra, RKB(i), RKC(i))); | 454 | Protect(luaV_settable(L, ra, RKB(i), RKC(i))); |
602 | ) | 455 | continue; |
603 | vmcase(OP_NEWTABLE, | 456 | } |
457 | case OP_NEWTABLE: { | ||
604 | int b = GETARG_B(i); | 458 | int b = GETARG_B(i); |
605 | int c = GETARG_C(i); | 459 | int c = GETARG_C(i); |
606 | Table *t = luaH_new(L); | 460 | sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); |
607 | sethvalue(L, ra, t); | 461 | Protect(luaC_checkGC(L)); |
608 | if (b != 0 || c != 0) | 462 | continue; |
609 | luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); | 463 | } |
610 | checkGC(L, ra + 1); | 464 | case OP_SELF: { |
611 | ) | ||
612 | vmcase(OP_SELF, | ||
613 | StkId rb = RB(i); | 465 | StkId rb = RB(i); |
614 | setobjs2s(L, ra+1, rb); | 466 | setobjs2s(L, ra+1, rb); |
615 | Protect(luaV_gettable(L, rb, RKC(i), ra)); | 467 | Protect(luaV_gettable(L, rb, RKC(i), ra)); |
616 | ) | 468 | continue; |
617 | vmcase(OP_ADD, | 469 | } |
470 | case OP_ADD: { | ||
618 | arith_op(luai_numadd, TM_ADD); | 471 | arith_op(luai_numadd, TM_ADD); |
619 | ) | 472 | continue; |
620 | vmcase(OP_SUB, | 473 | } |
474 | case OP_SUB: { | ||
621 | arith_op(luai_numsub, TM_SUB); | 475 | arith_op(luai_numsub, TM_SUB); |
622 | ) | 476 | continue; |
623 | vmcase(OP_MUL, | 477 | } |
478 | case OP_MUL: { | ||
624 | arith_op(luai_nummul, TM_MUL); | 479 | arith_op(luai_nummul, TM_MUL); |
625 | ) | 480 | continue; |
626 | vmcase(OP_DIV, | 481 | } |
482 | case OP_DIV: { | ||
627 | arith_op(luai_numdiv, TM_DIV); | 483 | arith_op(luai_numdiv, TM_DIV); |
628 | ) | 484 | continue; |
629 | vmcase(OP_MOD, | 485 | } |
486 | case OP_MOD: { | ||
630 | arith_op(luai_nummod, TM_MOD); | 487 | arith_op(luai_nummod, TM_MOD); |
631 | ) | 488 | continue; |
632 | vmcase(OP_POW, | 489 | } |
490 | case OP_POW: { | ||
633 | arith_op(luai_numpow, TM_POW); | 491 | arith_op(luai_numpow, TM_POW); |
634 | ) | 492 | continue; |
635 | vmcase(OP_UNM, | 493 | } |
494 | case OP_UNM: { | ||
636 | TValue *rb = RB(i); | 495 | TValue *rb = RB(i); |
637 | if (ttisnumber(rb)) { | 496 | if (ttisnumber(rb)) { |
638 | lua_Number nb = nvalue(rb); | 497 | lua_Number nb = nvalue(rb); |
639 | setnvalue(ra, luai_numunm(L, nb)); | 498 | setnvalue(ra, luai_numunm(nb)); |
640 | } | 499 | } |
641 | else { | 500 | else { |
642 | Protect(luaV_arith(L, ra, rb, rb, TM_UNM)); | 501 | Protect(Arith(L, ra, rb, rb, TM_UNM)); |
643 | } | 502 | } |
644 | ) | 503 | continue; |
645 | vmcase(OP_NOT, | 504 | } |
646 | TValue *rb = RB(i); | 505 | case OP_NOT: { |
647 | int res = l_isfalse(rb); /* next assignment may change this value */ | 506 | int res = l_isfalse(RB(i)); /* next assignment may change this value */ |
648 | setbvalue(ra, res); | 507 | setbvalue(ra, res); |
649 | ) | 508 | continue; |
650 | vmcase(OP_LEN, | 509 | } |
651 | Protect(luaV_objlen(L, ra, RB(i))); | 510 | case OP_LEN: { |
652 | ) | 511 | const TValue *rb = RB(i); |
653 | vmcase(OP_CONCAT, | 512 | switch (ttype(rb)) { |
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: { | ||
654 | int b = GETARG_B(i); | 531 | int b = GETARG_B(i); |
655 | int c = GETARG_C(i); | 532 | int c = GETARG_C(i); |
656 | StkId rb; | 533 | Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); |
657 | L->top = base + c + 1; /* mark the end of concat operands */ | 534 | setobjs2s(L, RA(i), base+b); |
658 | Protect(luaV_concat(L, c - b + 1)); | 535 | continue; |
659 | ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */ | 536 | } |
660 | rb = b + base; | 537 | case OP_JMP: { |
661 | setobjs2s(L, ra, rb); | 538 | dojump(L, pc, GETARG_sBx(i)); |
662 | checkGC(L, (ra >= rb ? ra + 1 : rb)); | 539 | continue; |
663 | L->top = ci->top; /* restore top */ | 540 | } |
664 | ) | 541 | case OP_EQ: { |
665 | vmcase(OP_JMP, | ||
666 | dojump(ci, i, 0); | ||
667 | ) | ||
668 | vmcase(OP_EQ, | ||
669 | TValue *rb = RKB(i); | 542 | TValue *rb = RKB(i); |
670 | TValue *rc = RKC(i); | 543 | TValue *rc = RKC(i); |
671 | Protect( | 544 | Protect( |
672 | if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i)) | 545 | if (equalobj(L, rb, rc) == GETARG_A(i)) |
673 | ci->u.l.savedpc++; | 546 | dojump(L, pc, GETARG_sBx(*pc)); |
674 | else | ||
675 | donextjump(ci); | ||
676 | ) | 547 | ) |
677 | ) | 548 | pc++; |
678 | vmcase(OP_LT, | 549 | continue; |
550 | } | ||
551 | case OP_LT: { | ||
679 | Protect( | 552 | Protect( |
680 | if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) | 553 | if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) |
681 | ci->u.l.savedpc++; | 554 | dojump(L, pc, GETARG_sBx(*pc)); |
682 | else | ||
683 | donextjump(ci); | ||
684 | ) | 555 | ) |
685 | ) | 556 | pc++; |
686 | vmcase(OP_LE, | 557 | continue; |
558 | } | ||
559 | case OP_LE: { | ||
687 | Protect( | 560 | Protect( |
688 | if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) | 561 | if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) |
689 | ci->u.l.savedpc++; | 562 | dojump(L, pc, GETARG_sBx(*pc)); |
690 | else | ||
691 | donextjump(ci); | ||
692 | ) | 563 | ) |
693 | ) | 564 | pc++; |
694 | vmcase(OP_TEST, | 565 | continue; |
695 | if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) | 566 | } |
696 | ci->u.l.savedpc++; | 567 | case OP_TEST: { |
697 | else | 568 | if (l_isfalse(ra) != GETARG_C(i)) |
698 | donextjump(ci); | 569 | dojump(L, pc, GETARG_sBx(*pc)); |
699 | ) | 570 | pc++; |
700 | vmcase(OP_TESTSET, | 571 | continue; |
572 | } | ||
573 | case OP_TESTSET: { | ||
701 | TValue *rb = RB(i); | 574 | TValue *rb = RB(i); |
702 | if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) | 575 | if (l_isfalse(rb) != GETARG_C(i)) { |
703 | ci->u.l.savedpc++; | ||
704 | else { | ||
705 | setobjs2s(L, ra, rb); | 576 | setobjs2s(L, ra, rb); |
706 | donextjump(ci); | 577 | dojump(L, pc, GETARG_sBx(*pc)); |
707 | } | 578 | } |
708 | ) | 579 | pc++; |
709 | vmcase(OP_CALL, | 580 | continue; |
581 | } | ||
582 | case OP_CALL: { | ||
710 | int b = GETARG_B(i); | 583 | int b = GETARG_B(i); |
711 | int nresults = GETARG_C(i) - 1; | 584 | int nresults = GETARG_C(i) - 1; |
712 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ | 585 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ |
713 | if (luaD_precall(L, ra, nresults)) { /* C function? */ | 586 | L->savedpc = pc; |
714 | if (nresults >= 0) L->top = ci->top; /* adjust results */ | 587 | switch (luaD_precall(L, ra, nresults)) { |
715 | base = ci->u.l.base; | 588 | case PCRLUA: { |
716 | } | 589 | nexeccalls++; |
717 | else { /* Lua function */ | 590 | goto reentry; /* restart luaV_execute over new Lua function */ |
718 | ci = L->ci; | 591 | } |
719 | ci->callstatus |= CIST_REENTRY; | 592 | case PCRC: { |
720 | goto newframe; /* restart luaV_execute over new Lua function */ | 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 | } | ||
721 | } | 601 | } |
722 | ) | 602 | } |
723 | vmcase(OP_TAILCALL, | 603 | case OP_TAILCALL: { |
724 | int b = GETARG_B(i); | 604 | int b = GETARG_B(i); |
725 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ | 605 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ |
606 | L->savedpc = pc; | ||
726 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); | 607 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); |
727 | if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */ | 608 | switch (luaD_precall(L, ra, LUA_MULTRET)) { |
728 | base = ci->u.l.base; | 609 | case PCRLUA: { |
729 | else { | 610 | /* tail call: put new frame in place of previous one */ |
730 | /* tail call: put called frame (n) in place of caller one (o) */ | 611 | CallInfo *ci = L->ci - 1; /* previous frame */ |
731 | CallInfo *nci = L->ci; /* called frame */ | 612 | int aux; |
732 | CallInfo *oci = nci->previous; /* caller frame */ | 613 | StkId func = ci->func; |
733 | StkId nfunc = nci->func; /* called function */ | 614 | StkId pfunc = (ci+1)->func; /* previous function index */ |
734 | StkId ofunc = oci->func; /* caller function */ | 615 | if (L->openupval) luaF_close(L, ci->base); |
735 | /* last stack slot filled by 'precall' */ | 616 | L->base = ci->base = ci->func + ((ci+1)->base - pfunc); |
736 | StkId lim = nci->u.l.base + getproto(nfunc)->numparams; | 617 | for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ |
737 | int aux; | 618 | setobjs2s(L, func+aux, pfunc+aux); |
738 | /* close all upvalues from previous call */ | 619 | ci->top = L->top = func+aux; /* correct top */ |
739 | if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); | 620 | lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); |
740 | /* move new frame into old one */ | 621 | ci->savedpc = L->savedpc; |
741 | for (aux = 0; nfunc + aux < lim; aux++) | 622 | ci->tailcalls++; /* one more call lost */ |
742 | setobjs2s(L, ofunc + aux, nfunc + aux); | 623 | L->ci--; /* remove new frame */ |
743 | oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */ | 624 | goto reentry; |
744 | oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ | 625 | } |
745 | oci->u.l.savedpc = nci->u.l.savedpc; | 626 | case PCRC: { /* it was a C function (`precall' called it) */ |
746 | oci->callstatus |= CIST_TAIL; /* function was tail called */ | 627 | base = L->base; |
747 | ci = L->ci = oci; /* remove new frame */ | 628 | continue; |
748 | lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); | 629 | } |
749 | goto newframe; /* restart luaV_execute over new Lua function */ | 630 | default: { |
631 | return; /* yield */ | ||
632 | } | ||
750 | } | 633 | } |
751 | ) | 634 | } |
752 | vmcasenb(OP_RETURN, | 635 | case OP_RETURN: { |
753 | int b = GETARG_B(i); | 636 | int b = GETARG_B(i); |
754 | if (b != 0) L->top = ra+b-1; | 637 | if (b != 0) L->top = ra+b-1; |
755 | if (cl->p->sizep > 0) luaF_close(L, base); | 638 | if (L->openupval) luaF_close(L, base); |
639 | L->savedpc = pc; | ||
756 | b = luaD_poscall(L, ra); | 640 | b = luaD_poscall(L, ra); |
757 | if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ | 641 | if (--nexeccalls == 0) /* was previous function running `here'? */ |
758 | return; /* external invocation: return */ | 642 | return; /* no: return */ |
759 | else { /* invocation via reentry: continue execution */ | 643 | else { /* yes: continue its execution */ |
760 | ci = L->ci; | 644 | if (b) L->top = L->ci->top; |
761 | if (b) L->top = ci->top; | 645 | lua_assert(isLua(L->ci)); |
762 | lua_assert(isLua(ci)); | 646 | lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); |
763 | lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); | 647 | goto reentry; |
764 | goto newframe; /* restart luaV_execute over new Lua function */ | ||
765 | } | 648 | } |
766 | ) | 649 | } |
767 | vmcase(OP_FORLOOP, | 650 | case OP_FORLOOP: { |
768 | lua_Number step = nvalue(ra+2); | 651 | lua_Number step = nvalue(ra+2); |
769 | lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */ | 652 | lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ |
770 | lua_Number limit = nvalue(ra+1); | 653 | lua_Number limit = nvalue(ra+1); |
771 | if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit) | 654 | if (luai_numlt(0, step) ? luai_numle(idx, limit) |
772 | : luai_numle(L, limit, idx)) { | 655 | : luai_numle(limit, idx)) { |
773 | ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ | 656 | dojump(L, pc, GETARG_sBx(i)); /* jump back */ |
774 | setnvalue(ra, idx); /* update internal index... */ | 657 | setnvalue(ra, idx); /* update internal index... */ |
775 | setnvalue(ra+3, idx); /* ...and external index */ | 658 | setnvalue(ra+3, idx); /* ...and external index */ |
776 | } | 659 | } |
777 | ) | 660 | continue; |
778 | vmcase(OP_FORPREP, | 661 | } |
662 | case OP_FORPREP: { | ||
779 | const TValue *init = ra; | 663 | const TValue *init = ra; |
780 | const TValue *plimit = ra+1; | 664 | const TValue *plimit = ra+1; |
781 | const TValue *pstep = ra+2; | 665 | const TValue *pstep = ra+2; |
666 | L->savedpc = pc; /* next steps may throw errors */ | ||
782 | if (!tonumber(init, ra)) | 667 | if (!tonumber(init, ra)) |
783 | luaG_runerror(L, LUA_QL("for") " initial value must be a number"); | 668 | luaG_runerror(L, LUA_QL("for") " initial value must be a number"); |
784 | else if (!tonumber(plimit, ra+1)) | 669 | else if (!tonumber(plimit, ra+1)) |
785 | luaG_runerror(L, LUA_QL("for") " limit must be a number"); | 670 | luaG_runerror(L, LUA_QL("for") " limit must be a number"); |
786 | else if (!tonumber(pstep, ra+2)) | 671 | else if (!tonumber(pstep, ra+2)) |
787 | luaG_runerror(L, LUA_QL("for") " step must be a number"); | 672 | luaG_runerror(L, LUA_QL("for") " step must be a number"); |
788 | setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep))); | 673 | setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); |
789 | ci->u.l.savedpc += GETARG_sBx(i); | 674 | dojump(L, pc, GETARG_sBx(i)); |
790 | ) | 675 | continue; |
791 | vmcasenb(OP_TFORCALL, | 676 | } |
677 | case OP_TFORLOOP: { | ||
792 | StkId cb = ra + 3; /* call base */ | 678 | StkId cb = ra + 3; /* call base */ |
793 | setobjs2s(L, cb+2, ra+2); | 679 | setobjs2s(L, cb+2, ra+2); |
794 | setobjs2s(L, cb+1, ra+1); | 680 | setobjs2s(L, cb+1, ra+1); |
795 | setobjs2s(L, cb, ra); | 681 | setobjs2s(L, cb, ra); |
796 | L->top = cb + 3; /* func. + 2 args (state and index) */ | 682 | L->top = cb+3; /* func. + 2 args (state and index) */ |
797 | Protect(luaD_call(L, cb, GETARG_C(i), 1)); | 683 | Protect(luaD_call(L, cb, GETARG_C(i))); |
798 | L->top = ci->top; | 684 | L->top = L->ci->top; |
799 | i = *(ci->u.l.savedpc++); /* go to next instruction */ | 685 | cb = RA(i) + 3; /* previous call may change the stack */ |
800 | ra = RA(i); | 686 | if (!ttisnil(cb)) { /* continue loop? */ |
801 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP); | 687 | setobjs2s(L, cb-1, cb); /* save control variable */ |
802 | goto l_tforloop; | 688 | dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ |
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 */ | ||
809 | } | 689 | } |
810 | ) | 690 | pc++; |
811 | vmcase(OP_SETLIST, | 691 | continue; |
692 | } | ||
693 | case OP_SETLIST: { | ||
812 | int n = GETARG_B(i); | 694 | int n = GETARG_B(i); |
813 | int c = GETARG_C(i); | 695 | int c = GETARG_C(i); |
814 | int last; | 696 | int last; |
815 | Table *h; | 697 | Table *h; |
816 | if (n == 0) n = cast_int(L->top - ra) - 1; | 698 | if (n == 0) { |
817 | if (c == 0) { | 699 | n = cast_int(L->top - ra) - 1; |
818 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); | 700 | L->top = L->ci->top; |
819 | c = GETARG_Ax(*ci->u.l.savedpc++); | ||
820 | } | 701 | } |
821 | luai_runtimecheck(L, ttistable(ra)); | 702 | if (c == 0) c = cast_int(*pc++); |
703 | runtime_check(L, ttistable(ra)); | ||
822 | h = hvalue(ra); | 704 | h = hvalue(ra); |
823 | last = ((c-1)*LFIELDS_PER_FLUSH) + n; | 705 | last = ((c-1)*LFIELDS_PER_FLUSH) + n; |
824 | if (last > h->sizearray) /* needs more space? */ | 706 | if (last > h->sizearray) /* needs more space? */ |
825 | luaH_resizearray(L, h, last); /* pre-allocate it at once */ | 707 | luaH_resizearray(L, h, last); /* pre-alloc it at once */ |
826 | for (; n > 0; n--) { | 708 | for (; n > 0; n--) { |
827 | TValue *val = ra+n; | 709 | TValue *val = ra+n; |
828 | luaH_setint(L, h, last--, val); | 710 | setobj2t(L, luaH_setnum(L, h, last--), val); |
829 | luaC_barrierback(L, obj2gco(h), val); | 711 | luaC_barriert(L, h, val); |
830 | } | 712 | } |
831 | L->top = ci->top; /* correct top (in case of previous open call) */ | 713 | continue; |
832 | ) | 714 | } |
833 | vmcase(OP_CLOSURE, | 715 | case OP_CLOSE: { |
834 | Proto *p = cl->p->p[GETARG_Bx(i)]; | 716 | luaF_close(L, ra); |
835 | Closure *ncl = getcached(p, cl->upvals, base); /* cached closure */ | 717 | continue; |
836 | if (ncl == NULL) /* no match? */ | 718 | } |
837 | pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ | 719 | case OP_CLOSURE: { |
838 | else | 720 | Proto *p; |
839 | setclLvalue(L, ra, ncl); /* push cashed closure */ | 721 | Closure *ncl; |
840 | checkGC(L, ra + 1); | 722 | int nup, j; |
841 | ) | 723 | p = cl->p->p[GETARG_Bx(i)]; |
842 | vmcase(OP_VARARG, | 724 | nup = p->nups; |
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: { | ||
843 | int b = GETARG_B(i) - 1; | 740 | int b = GETARG_B(i) - 1; |
844 | int j; | 741 | int j; |
845 | int n = cast_int(base - ci->func) - cl->p->numparams - 1; | 742 | CallInfo *ci = L->ci; |
846 | if (b < 0) { /* B == 0? */ | 743 | int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; |
847 | b = n; /* get all var. arguments */ | 744 | if (b == LUA_MULTRET) { |
848 | Protect(luaD_checkstack(L, n)); | 745 | Protect(luaD_checkstack(L, n)); |
849 | ra = RA(i); /* previous call may change the stack */ | 746 | ra = RA(i); /* previous call may change the stack */ |
747 | b = n; | ||
850 | L->top = ra + n; | 748 | L->top = ra + n; |
851 | } | 749 | } |
852 | for (j = 0; j < b; j++) { | 750 | for (j = 0; j < b; j++) { |
853 | if (j < n) { | 751 | if (j < n) { |
854 | setobjs2s(L, ra + j, base - n + j); | 752 | setobjs2s(L, ra + j, ci->base - n + j); |
855 | } | 753 | } |
856 | else { | 754 | else { |
857 | setnilvalue(ra + j); | 755 | setnilvalue(ra + j); |
858 | } | 756 | } |
859 | } | 757 | } |
860 | ) | 758 | continue; |
861 | vmcase(OP_EXTRAARG, | 759 | } |
862 | lua_assert(0); | ||
863 | ) | ||
864 | } | 760 | } |
865 | } | 761 | } |
866 | } | 762 | } |
diff --git a/apps/plugins/lua/lvm.h b/apps/plugins/lua/lvm.h index 5380270da6..dff2a139f7 100644 --- a/apps/plugins/lua/lvm.h +++ b/apps/plugins/lua/lvm.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.h,v 2.18.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
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,32 +13,24 @@ | |||
13 | #include "ltm.h" | 13 | #include "ltm.h" |
14 | 14 | ||
15 | 15 | ||
16 | #define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) | 16 | #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) |
17 | 17 | ||
18 | #define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) | 18 | #define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ |
19 | (((o) = luaV_tonumber(o,n)) != NULL)) | ||
19 | 20 | ||
20 | #define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2)) | 21 | #define equalobj(L,o1,o2) \ |
21 | 22 | (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) | |
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); | ||
27 | 23 | ||
28 | 24 | ||
29 | LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); | 25 | LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); |
30 | LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); | 26 | LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); |
31 | LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); | 27 | LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); |
32 | LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); | 28 | LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); |
33 | LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, | 29 | LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, |
34 | StkId val); | 30 | StkId val); |
35 | LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, | 31 | LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, |
36 | StkId val); | 32 | StkId val); |
37 | LUAI_FUNC void luaV_finishOp (lua_State *L); | 33 | LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); |
38 | LUAI_FUNC void luaV_execute (lua_State *L); | 34 | LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); |
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); | ||
43 | 35 | ||
44 | #endif | 36 | #endif |
diff --git a/apps/plugins/lua/lzio.c b/apps/plugins/lua/lzio.c index 20efea9830..293edd59b0 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.35.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ |
3 | ** Buffered streams | 3 | ** a generic input stream interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
6 | 6 | ||
@@ -25,11 +25,23 @@ 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) | 28 | if (buff == NULL || size == 0) return EOZ; |
29 | return EOZ; | 29 | z->n = size - 1; |
30 | z->n = size - 1; /* discount char being returned */ | ||
31 | z->p = buff; | 30 | z->p = buff; |
32 | return cast_uchar(*(z->p++)); | 31 | return char2int(*(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); | ||
33 | } | 45 | } |
34 | 46 | ||
35 | 47 | ||
@@ -46,14 +58,8 @@ void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { | |||
46 | size_t luaZ_read (ZIO *z, void *b, size_t n) { | 58 | size_t luaZ_read (ZIO *z, void *b, size_t n) { |
47 | while (n) { | 59 | while (n) { |
48 | size_t m; | 60 | size_t m; |
49 | if (z->n == 0) { /* no bytes in buffer? */ | 61 | if (luaZ_lookahead(z) == EOZ) |
50 | if (luaZ_fill(z) == EOZ) /* try to read more */ | 62 | return n; /* return number of missing bytes */ |
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 | } | ||
57 | m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ | 63 | m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ |
58 | memcpy(b, z->p, m); | 64 | memcpy(b, z->p, m); |
59 | z->n -= m; | 65 | z->n -= m; |
diff --git a/apps/plugins/lua/lzio.h b/apps/plugins/lua/lzio.h index 441f7479cb..9aa9e4b537 100644 --- a/apps/plugins/lua/lzio.h +++ b/apps/plugins/lua/lzio.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lzio.h,v 1.26.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id$ |
3 | ** Buffered streams | 3 | ** Buffered streams |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -17,8 +17,9 @@ | |||
17 | 17 | ||
18 | typedef struct Zio ZIO; | 18 | typedef struct Zio ZIO; |
19 | 19 | ||
20 | #define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) | 20 | #define char2int(c) cast(int, cast(unsigned char, (c))) |
21 | 21 | ||
22 | #define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) | ||
22 | 23 | ||
23 | typedef struct Mbuffer { | 24 | typedef struct Mbuffer { |
24 | char *buffer; | 25 | char *buffer; |
@@ -46,6 +47,7 @@ LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); | |||
46 | LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, | 47 | LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, |
47 | void *data); | 48 | void *data); |
48 | LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ | 49 | 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); | ||
49 | 51 | ||
50 | 52 | ||
51 | 53 | ||
@@ -54,7 +56,7 @@ LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ | |||
54 | struct Zio { | 56 | struct Zio { |
55 | size_t n; /* bytes still unread */ | 57 | size_t n; /* bytes still unread */ |
56 | const char *p; /* current position in buffer */ | 58 | const char *p; /* current position in buffer */ |
57 | lua_Reader reader; /* reader function */ | 59 | lua_Reader reader; |
58 | void* data; /* additional data */ | 60 | void* data; /* additional data */ |
59 | lua_State *L; /* Lua state (for reader) */ | 61 | lua_State *L; /* Lua state (for reader) */ |
60 | }; | 62 | }; |
diff --git a/apps/plugins/lua/rockconf.h b/apps/plugins/lua/rockconf.h index eda1e05084..a13146d7e9 100644 --- a/apps/plugins/lua/rockconf.h +++ b/apps/plugins/lua/rockconf.h | |||
@@ -25,6 +25,10 @@ | |||
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 | |||
28 | #undef LUA_PATH_DEFAULT | 32 | #undef LUA_PATH_DEFAULT |
29 | #define LUA_PATH_DEFAULT "$/?.lua;" "$/?/init.lua;" VIEWERS_DIR"/lua/?.lua;" VIEWERS_DIR"/lua/?/init.lua;" | 33 | #define LUA_PATH_DEFAULT "$/?.lua;" "$/?/init.lua;" VIEWERS_DIR"/lua/?.lua;" VIEWERS_DIR"/lua/?/init.lua;" |
30 | 34 | ||
@@ -32,11 +36,20 @@ | |||
32 | 36 | ||
33 | #include "lib/pluginlib_exit.h" | 37 | #include "lib/pluginlib_exit.h" |
34 | 38 | ||
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 | |||
35 | extern char curpath[MAX_PATH]; | 43 | extern char curpath[MAX_PATH]; |
36 | struct tm *gmtime(const time_t *timep); | 44 | struct tm *gmtime(const time_t *timep); |
37 | long strtol(const char *nptr, char **endptr, int base); | 45 | long strtol(const char *nptr, char **endptr, int base); |
38 | unsigned long strtoul(const char *str, char **endptr, int base); | 46 | unsigned long strtoul(const char *str, char **endptr, int base); |
39 | size_t strftime(char* dst, size_t max, const char* format, const struct tm* tm); | 47 | 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 | ||
40 | 53 | ||
41 | /* Simple substitutions */ | 54 | /* Simple substitutions */ |
42 | #define malloc tlsf_malloc | 55 | #define malloc tlsf_malloc |
@@ -50,17 +63,5 @@ size_t strftime(char* dst, size_t max, const char* format, const struct tm* tm); | |||
50 | #define strcpy rb->strcpy | 63 | #define strcpy rb->strcpy |
51 | #define strlen rb->strlen | 64 | #define strlen rb->strlen |
52 | 65 | ||
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 | |||
65 | #endif /* _ROCKCONF_H_ */ | 66 | #endif /* _ROCKCONF_H_ */ |
66 | 67 | ||
diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c index f214aca694..27c1177748 100644 --- a/apps/plugins/lua/rocklib.c +++ b/apps/plugins/lua/rocklib.c | |||
@@ -156,19 +156,7 @@ static int rli_tostring(lua_State *L) | |||
156 | return 1; | 156 | return 1; |
157 | } | 157 | } |
158 | 158 | ||
159 | int rli_checkboolean (lua_State *L, int narg) { | 159 | static const struct luaL_reg rli_lib [] = |
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 [] = | ||
172 | { | 160 | { |
173 | {"__tostring", rli_tostring}, | 161 | {"__tostring", rli_tostring}, |
174 | {"set", rli_set}, | 162 | {"set", rli_set}, |
@@ -484,8 +472,8 @@ RB_WRAP(read_bmp_file) | |||
484 | { | 472 | { |
485 | struct bitmap bm; | 473 | struct bitmap bm; |
486 | const char* filename = luaL_checkstring(L, 1); | 474 | const char* filename = luaL_checkstring(L, 1); |
487 | bool dither = rli_optboolean(L, 2, true); | 475 | bool dither = luaL_optboolean(L, 2, true); |
488 | bool transparent = rli_optboolean(L, 3, false); | 476 | bool transparent = luaL_optboolean(L, 3, false); |
489 | int format = FORMAT_NATIVE; | 477 | int format = FORMAT_NATIVE; |
490 | 478 | ||
491 | if(dither) | 479 | if(dither) |
@@ -528,7 +516,7 @@ static void fill_text_message(lua_State *L, struct text_message * message, | |||
528 | { | 516 | { |
529 | int i; | 517 | int i; |
530 | luaL_checktype(L, pos, LUA_TTABLE); | 518 | luaL_checktype(L, pos, LUA_TTABLE); |
531 | int n = lua_rawlen(L, pos); | 519 | int n = luaL_getn(L, pos); |
532 | const char **lines = (const char**) tlsf_malloc(n * sizeof(const char*)); | 520 | const char **lines = (const char**) tlsf_malloc(n * sizeof(const char*)); |
533 | if(lines == NULL) | 521 | if(lines == NULL) |
534 | luaL_error(L, "Can't allocate %d bytes!", n * sizeof(const char*)); | 522 | luaL_error(L, "Can't allocate %d bytes!", n * sizeof(const char*)); |
@@ -577,7 +565,7 @@ RB_WRAP(do_menu) | |||
577 | luaL_checktype(L, 2, LUA_TTABLE); | 565 | luaL_checktype(L, 2, LUA_TTABLE); |
578 | start_selected = luaL_optint(L, 3, 0); | 566 | start_selected = luaL_optint(L, 3, 0); |
579 | 567 | ||
580 | n = lua_rawlen(L, 2); | 568 | n = luaL_getn(L, 2); |
581 | items = (const char**) tlsf_malloc(n * sizeof(const char*)); | 569 | items = (const char**) tlsf_malloc(n * sizeof(const char*)); |
582 | if(items == NULL) | 570 | if(items == NULL) |
583 | luaL_error(L, "Can't allocate %d bytes!", n * sizeof(const char*)); | 571 | luaL_error(L, "Can't allocate %d bytes!", n * sizeof(const char*)); |
@@ -770,9 +758,8 @@ extern const luaL_Reg rocklib_aux[]; | |||
770 | */ | 758 | */ |
771 | LUALIB_API int luaopen_rock(lua_State *L) | 759 | LUALIB_API int luaopen_rock(lua_State *L) |
772 | { | 760 | { |
773 | rli_init(L); | 761 | luaL_register(L, LUA_ROCKLIBNAME, rocklib); |
774 | luaL_newlib(L, rocklib); | 762 | luaL_register(L, LUA_ROCKLIBNAME, rocklib_aux); |
775 | luaL_setfuncs(L, rocklib_aux, 0); | ||
776 | 763 | ||
777 | RB_CONSTANT(HZ); | 764 | RB_CONSTANT(HZ); |
778 | 765 | ||
@@ -810,6 +797,7 @@ LUALIB_API int luaopen_rock(lua_State *L) | |||
810 | RB_STRING_CONSTANT(PLUGIN_DATA_DIR); | 797 | RB_STRING_CONSTANT(PLUGIN_DATA_DIR); |
811 | RB_STRING_CONSTANT(VIEWERS_DATA_DIR); | 798 | RB_STRING_CONSTANT(VIEWERS_DATA_DIR); |
812 | 799 | ||
800 | rli_init(L); | ||
813 | 801 | ||
814 | return 1; | 802 | return 1; |
815 | } | 803 | } |
diff --git a/apps/plugins/lua/rocklib.h b/apps/plugins/lua/rocklib.h index 2b259ee53e..84b5fd2de0 100644 --- a/apps/plugins/lua/rocklib.h +++ b/apps/plugins/lua/rocklib.h | |||
@@ -25,7 +25,6 @@ | |||
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); | ||
29 | 28 | ||
30 | #endif /* _ROCKLIB_H_ */ | 29 | #endif /* _ROCKLIB_H_ */ |
31 | 30 | ||
diff --git a/apps/plugins/lua/rocklib_aux.pl b/apps/plugins/lua/rocklib_aux.pl index 61e0115bdf..9103fccbda 100755 --- a/apps/plugins/lua/rocklib_aux.pl +++ b/apps/plugins/lua/rocklib_aux.pl | |||
@@ -133,7 +133,6 @@ 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" | ||
137 | #include "lauxlib.h" | 136 | #include "lauxlib.h" |
138 | #include "plugin.h" | 137 | #include "plugin.h" |
139 | 138 | ||
@@ -208,7 +207,7 @@ sub in_string | |||
208 | sub in_bool | 207 | sub in_bool |
209 | { | 208 | { |
210 | my ($name, $type, $pos) = @_; | 209 | my ($name, $type, $pos) = @_; |
211 | return sprintf("\tbool %s = rli_checkboolean(L, %d);\n", $name, $pos) | 210 | return sprintf("\tbool %s = luaL_checkboolean(L, %d);\n", $name, $pos) |
212 | } | 211 | } |
213 | 212 | ||
214 | sub out_void | 213 | sub out_void |
diff --git a/apps/plugins/lua/rocklibc.h b/apps/plugins/lua/rocklibc.h index 430889bb70..44f916fded 100644 --- a/apps/plugins/lua/rocklibc.h +++ b/apps/plugins/lua/rocklibc.h | |||
@@ -30,7 +30,6 @@ | |||
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 | ||
34 | extern int errno; | 33 | extern int errno; |
35 | #define EINVAL 22 /* Invalid argument */ | 34 | #define EINVAL 22 /* Invalid argument */ |
36 | #define ERANGE 34 /* Math result not representable */ | 35 | #define ERANGE 34 /* Math result not representable */ |
@@ -44,8 +43,7 @@ extern int errno; | |||
44 | #define memcmp rb->memcmp | 43 | #define memcmp rb->memcmp |
45 | #define strlen rb->strlen | 44 | #define strlen rb->strlen |
46 | 45 | ||
47 | extern int PREFIX(fscanf)(void *fd, const char *fmt, ...); | 46 | extern int PREFIX(fscanf)(int fd, const char *fmt, ...); |
48 | extern int PREFIX(getc)(int fd); | ||
49 | 47 | ||
50 | #endif /* _ROCKLIBC_H_ */ | 48 | #endif /* _ROCKLIBC_H_ */ |
51 | 49 | ||
diff --git a/apps/plugins/lua/rocklua.c b/apps/plugins/lua/rocklua.c index 4f328dd84a..5539618a43 100644 --- a/apps/plugins/lua/rocklua.c +++ b/apps/plugins/lua/rocklua.c | |||
@@ -26,8 +26,7 @@ | |||
26 | #include "rocklib.h" | 26 | #include "rocklib.h" |
27 | #include "luadir.h" | 27 | #include "luadir.h" |
28 | 28 | ||
29 | #undef LUA_BITLIBNAME | 29 | |
30 | #define LUA_BITLIBNAME "bit" | ||
31 | 30 | ||
32 | static const luaL_Reg lualibs[] = { | 31 | static const luaL_Reg lualibs[] = { |
33 | {"", luaopen_base}, | 32 | {"", luaopen_base}, |
@@ -35,7 +34,7 @@ static const luaL_Reg lualibs[] = { | |||
35 | {LUA_STRLIBNAME, luaopen_string}, | 34 | {LUA_STRLIBNAME, luaopen_string}, |
36 | {LUA_OSLIBNAME, luaopen_os}, | 35 | {LUA_OSLIBNAME, luaopen_os}, |
37 | {LUA_ROCKLIBNAME, luaopen_rock}, | 36 | {LUA_ROCKLIBNAME, luaopen_rock}, |
38 | {LUA_BITLIBNAME, luaopen_bit32}, | 37 | {LUA_BITLIBNAME, luaopen_bit}, |
39 | {LUA_IOLIBNAME, luaopen_io}, | 38 | {LUA_IOLIBNAME, luaopen_io}, |
40 | {LUA_LOADLIBNAME, luaopen_package}, | 39 | {LUA_LOADLIBNAME, luaopen_package}, |
41 | {LUA_MATHLIBNAME, luaopen_math}, | 40 | {LUA_MATHLIBNAME, luaopen_math}, |
@@ -44,10 +43,11 @@ static const luaL_Reg lualibs[] = { | |||
44 | }; | 43 | }; |
45 | 44 | ||
46 | static void rocklua_openlibs(lua_State *L) { | 45 | static void rocklua_openlibs(lua_State *L) { |
47 | const luaL_Reg *lib; | 46 | const luaL_Reg *lib = lualibs; |
48 | for (lib = lualibs; lib->func; lib++) { | 47 | for (; lib->func; lib++) { |
49 | luaL_requiref(L, lib->name, lib->func, 1); | 48 | lua_pushcfunction(L, lib->func); |
50 | lua_pop(L, 1); /* remove lib */ | 49 | lua_pushstring(L, lib->name); |
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 new file mode 100644 index 0000000000..0a19eaebf2 --- /dev/null +++ b/apps/plugins/lua/strcspn.c | |||
@@ -0,0 +1,17 @@ | |||
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 deleted file mode 100644 index e95500a1dc..0000000000 --- a/apps/plugins/lua/strspn.c +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
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 | |||