diff options
author | David Walter Seikel | 2012-01-23 23:36:30 +1000 |
---|---|---|
committer | David Walter Seikel | 2012-01-23 23:36:30 +1000 |
commit | 6523585c66c04cea54df50013df8886b589847d8 (patch) | |
tree | 0b22aee7064166d88595eda260ca2d17c0773da5 /libraries/luajit-2.0/src/lib_base.c | |
parent | Update the EFL to what I'm actually using, coz I'm using some stuff not yet r... (diff) | |
download | SledjHamr-6523585c66c04cea54df50013df8886b589847d8.zip SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.gz SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.bz2 SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.xz |
Add luaproc and LuaJIT libraries.
Two versions of LuaJIT, the stable release, and the dev version. Try the dev version first, until ih fails badly.
Diffstat (limited to '')
-rw-r--r-- | libraries/luajit-2.0/src/lib_base.c | 650 |
1 files changed, 650 insertions, 0 deletions
diff --git a/libraries/luajit-2.0/src/lib_base.c b/libraries/luajit-2.0/src/lib_base.c new file mode 100644 index 0000000..f897598 --- /dev/null +++ b/libraries/luajit-2.0/src/lib_base.c | |||
@@ -0,0 +1,650 @@ | |||
1 | /* | ||
2 | ** Base and coroutine library. | ||
3 | ** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h | ||
4 | ** | ||
5 | ** Major portions taken verbatim or adapted from the Lua interpreter. | ||
6 | ** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h | ||
7 | */ | ||
8 | |||
9 | #include <stdio.h> | ||
10 | |||
11 | #define lib_base_c | ||
12 | #define LUA_LIB | ||
13 | |||
14 | #include "lua.h" | ||
15 | #include "lauxlib.h" | ||
16 | #include "lualib.h" | ||
17 | |||
18 | #include "lj_obj.h" | ||
19 | #include "lj_gc.h" | ||
20 | #include "lj_err.h" | ||
21 | #include "lj_debug.h" | ||
22 | #include "lj_str.h" | ||
23 | #include "lj_tab.h" | ||
24 | #include "lj_meta.h" | ||
25 | #include "lj_state.h" | ||
26 | #if LJ_HASFFI | ||
27 | #include "lj_ctype.h" | ||
28 | #include "lj_cconv.h" | ||
29 | #endif | ||
30 | #include "lj_bc.h" | ||
31 | #include "lj_ff.h" | ||
32 | #include "lj_dispatch.h" | ||
33 | #include "lj_char.h" | ||
34 | #include "lj_lib.h" | ||
35 | |||
36 | /* -- Base library: checks ------------------------------------------------ */ | ||
37 | |||
38 | #define LJLIB_MODULE_base | ||
39 | |||
40 | LJLIB_ASM(assert) LJLIB_REC(.) | ||
41 | { | ||
42 | GCstr *s; | ||
43 | lj_lib_checkany(L, 1); | ||
44 | s = lj_lib_optstr(L, 2); | ||
45 | if (s) | ||
46 | lj_err_callermsg(L, strdata(s)); | ||
47 | else | ||
48 | lj_err_caller(L, LJ_ERR_ASSERT); | ||
49 | return FFH_UNREACHABLE; | ||
50 | } | ||
51 | |||
52 | /* ORDER LJ_T */ | ||
53 | LJLIB_PUSH("nil") | ||
54 | LJLIB_PUSH("boolean") | ||
55 | LJLIB_PUSH(top-1) /* boolean */ | ||
56 | LJLIB_PUSH("userdata") | ||
57 | LJLIB_PUSH("string") | ||
58 | LJLIB_PUSH("upval") | ||
59 | LJLIB_PUSH("thread") | ||
60 | LJLIB_PUSH("proto") | ||
61 | LJLIB_PUSH("function") | ||
62 | LJLIB_PUSH("trace") | ||
63 | LJLIB_PUSH("cdata") | ||
64 | LJLIB_PUSH("table") | ||
65 | LJLIB_PUSH(top-9) /* userdata */ | ||
66 | LJLIB_PUSH("number") | ||
67 | LJLIB_ASM_(type) LJLIB_REC(.) | ||
68 | /* Recycle the lj_lib_checkany(L, 1) from assert. */ | ||
69 | |||
70 | /* -- Base library: getters and setters ----------------------------------- */ | ||
71 | |||
72 | LJLIB_ASM_(getmetatable) LJLIB_REC(.) | ||
73 | /* Recycle the lj_lib_checkany(L, 1) from assert. */ | ||
74 | |||
75 | LJLIB_ASM(setmetatable) LJLIB_REC(.) | ||
76 | { | ||
77 | GCtab *t = lj_lib_checktab(L, 1); | ||
78 | GCtab *mt = lj_lib_checktabornil(L, 2); | ||
79 | if (!tvisnil(lj_meta_lookup(L, L->base, MM_metatable))) | ||
80 | lj_err_caller(L, LJ_ERR_PROTMT); | ||
81 | setgcref(t->metatable, obj2gco(mt)); | ||
82 | if (mt) { lj_gc_objbarriert(L, t, mt); } | ||
83 | settabV(L, L->base-1, t); | ||
84 | return FFH_RES(1); | ||
85 | } | ||
86 | |||
87 | LJLIB_CF(getfenv) | ||
88 | { | ||
89 | GCfunc *fn; | ||
90 | cTValue *o = L->base; | ||
91 | if (!(o < L->top && tvisfunc(o))) { | ||
92 | int level = lj_lib_optint(L, 1, 1); | ||
93 | o = lj_debug_frame(L, level, &level); | ||
94 | if (o == NULL) | ||
95 | lj_err_arg(L, 1, LJ_ERR_INVLVL); | ||
96 | } | ||
97 | fn = &gcval(o)->fn; | ||
98 | settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env)); | ||
99 | return 1; | ||
100 | } | ||
101 | |||
102 | LJLIB_CF(setfenv) | ||
103 | { | ||
104 | GCfunc *fn; | ||
105 | GCtab *t = lj_lib_checktab(L, 2); | ||
106 | cTValue *o = L->base; | ||
107 | if (!(o < L->top && tvisfunc(o))) { | ||
108 | int level = lj_lib_checkint(L, 1); | ||
109 | if (level == 0) { | ||
110 | /* NOBARRIER: A thread (i.e. L) is never black. */ | ||
111 | setgcref(L->env, obj2gco(t)); | ||
112 | return 0; | ||
113 | } | ||
114 | o = lj_debug_frame(L, level, &level); | ||
115 | if (o == NULL) | ||
116 | lj_err_arg(L, 1, LJ_ERR_INVLVL); | ||
117 | } | ||
118 | fn = &gcval(o)->fn; | ||
119 | if (!isluafunc(fn)) | ||
120 | lj_err_caller(L, LJ_ERR_SETFENV); | ||
121 | setgcref(fn->l.env, obj2gco(t)); | ||
122 | lj_gc_objbarrier(L, obj2gco(fn), t); | ||
123 | setfuncV(L, L->top++, fn); | ||
124 | return 1; | ||
125 | } | ||
126 | |||
127 | LJLIB_ASM(rawget) LJLIB_REC(.) | ||
128 | { | ||
129 | lj_lib_checktab(L, 1); | ||
130 | lj_lib_checkany(L, 2); | ||
131 | return FFH_UNREACHABLE; | ||
132 | } | ||
133 | |||
134 | LJLIB_CF(rawset) LJLIB_REC(.) | ||
135 | { | ||
136 | lj_lib_checktab(L, 1); | ||
137 | lj_lib_checkany(L, 2); | ||
138 | L->top = 1+lj_lib_checkany(L, 3); | ||
139 | lua_rawset(L, 1); | ||
140 | return 1; | ||
141 | } | ||
142 | |||
143 | LJLIB_CF(rawequal) LJLIB_REC(.) | ||
144 | { | ||
145 | cTValue *o1 = lj_lib_checkany(L, 1); | ||
146 | cTValue *o2 = lj_lib_checkany(L, 2); | ||
147 | setboolV(L->top-1, lj_obj_equal(o1, o2)); | ||
148 | return 1; | ||
149 | } | ||
150 | |||
151 | LJLIB_CF(unpack) | ||
152 | { | ||
153 | GCtab *t = lj_lib_checktab(L, 1); | ||
154 | int32_t n, i = lj_lib_optint(L, 2, 1); | ||
155 | int32_t e = (L->base+3-1 < L->top && !tvisnil(L->base+3-1)) ? | ||
156 | lj_lib_checkint(L, 3) : (int32_t)lj_tab_len(t); | ||
157 | if (i > e) return 0; | ||
158 | n = e - i + 1; | ||
159 | if (n <= 0 || !lua_checkstack(L, n)) | ||
160 | lj_err_caller(L, LJ_ERR_UNPACK); | ||
161 | do { | ||
162 | cTValue *tv = lj_tab_getint(t, i); | ||
163 | if (tv) { | ||
164 | copyTV(L, L->top++, tv); | ||
165 | } else { | ||
166 | setnilV(L->top++); | ||
167 | } | ||
168 | } while (i++ < e); | ||
169 | return n; | ||
170 | } | ||
171 | |||
172 | LJLIB_CF(select) LJLIB_REC(.) | ||
173 | { | ||
174 | int32_t n = (int32_t)(L->top - L->base); | ||
175 | if (n >= 1 && tvisstr(L->base) && *strVdata(L->base) == '#') { | ||
176 | setintV(L->top-1, n-1); | ||
177 | return 1; | ||
178 | } else { | ||
179 | int32_t i = lj_lib_checkint(L, 1); | ||
180 | if (i < 0) i = n + i; else if (i > n) i = n; | ||
181 | if (i < 1) | ||
182 | lj_err_arg(L, 1, LJ_ERR_IDXRNG); | ||
183 | return n - i; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | /* -- Base library: conversions ------------------------------------------- */ | ||
188 | |||
189 | LJLIB_ASM(tonumber) LJLIB_REC(.) | ||
190 | { | ||
191 | int32_t base = lj_lib_optint(L, 2, 10); | ||
192 | if (base == 10) { | ||
193 | TValue *o = lj_lib_checkany(L, 1); | ||
194 | if (tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o))) { | ||
195 | copyTV(L, L->base-1, o); | ||
196 | return FFH_RES(1); | ||
197 | } | ||
198 | #if LJ_HASFFI | ||
199 | if (tviscdata(o)) { | ||
200 | CTState *cts = ctype_cts(L); | ||
201 | CType *ct = lj_ctype_rawref(cts, cdataV(o)->typeid); | ||
202 | if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); | ||
203 | if (ctype_isnum(ct->info) || ctype_iscomplex(ct->info)) { | ||
204 | if (LJ_DUALNUM && ctype_isinteger_or_bool(ct->info) && | ||
205 | ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) { | ||
206 | int32_t i; | ||
207 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0); | ||
208 | setintV(L->base-1, i); | ||
209 | return FFH_RES(1); | ||
210 | } | ||
211 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE), | ||
212 | (uint8_t *)&(L->base-1)->n, o, 0); | ||
213 | return FFH_RES(1); | ||
214 | } | ||
215 | } | ||
216 | #endif | ||
217 | } else { | ||
218 | const char *p = strdata(lj_lib_checkstr(L, 1)); | ||
219 | char *ep; | ||
220 | unsigned long ul; | ||
221 | if (base < 2 || base > 36) | ||
222 | lj_err_arg(L, 2, LJ_ERR_BASERNG); | ||
223 | ul = strtoul(p, &ep, base); | ||
224 | if (p != ep) { | ||
225 | while (lj_char_isspace((unsigned char)(*ep))) ep++; | ||
226 | if (*ep == '\0') { | ||
227 | if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u)) | ||
228 | setintV(L->base-1, (int32_t)ul); | ||
229 | else | ||
230 | setnumV(L->base-1, (lua_Number)ul); | ||
231 | return FFH_RES(1); | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | setnilV(L->base-1); | ||
236 | return FFH_RES(1); | ||
237 | } | ||
238 | |||
239 | LJLIB_PUSH("nil") | ||
240 | LJLIB_PUSH("false") | ||
241 | LJLIB_PUSH("true") | ||
242 | LJLIB_ASM(tostring) LJLIB_REC(.) | ||
243 | { | ||
244 | TValue *o = lj_lib_checkany(L, 1); | ||
245 | cTValue *mo; | ||
246 | L->top = o+1; /* Only keep one argument. */ | ||
247 | if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { | ||
248 | copyTV(L, L->base-1, mo); /* Replace callable. */ | ||
249 | return FFH_TAILCALL; | ||
250 | } else { | ||
251 | GCstr *s; | ||
252 | if (tvisnumber(o)) { | ||
253 | s = lj_str_fromnumber(L, o); | ||
254 | } else if (tvispri(o)) { | ||
255 | s = strV(lj_lib_upvalue(L, -(int32_t)itype(o))); | ||
256 | } else { | ||
257 | if (tvisfunc(o) && isffunc(funcV(o))) | ||
258 | lua_pushfstring(L, "function: fast#%d", funcV(o)->c.ffid); | ||
259 | else | ||
260 | lua_pushfstring(L, "%s: %p", typename(o), lua_topointer(L, 1)); | ||
261 | /* Note: lua_pushfstring calls the GC which may invalidate o. */ | ||
262 | s = strV(L->top-1); | ||
263 | } | ||
264 | setstrV(L, L->base-1, s); | ||
265 | return FFH_RES(1); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | /* -- Base library: iterators --------------------------------------------- */ | ||
270 | |||
271 | /* This solves a circular dependency problem -- change FF_next_N as needed. */ | ||
272 | LJ_STATIC_ASSERT((int)FF_next == FF_next_N); | ||
273 | |||
274 | LJLIB_ASM(next) | ||
275 | { | ||
276 | lj_lib_checktab(L, 1); | ||
277 | return FFH_UNREACHABLE; | ||
278 | } | ||
279 | |||
280 | #ifdef LUAJIT_ENABLE_LUA52COMPAT | ||
281 | static int ffh_pairs(lua_State *L, MMS mm) | ||
282 | { | ||
283 | TValue *o = lj_lib_checkany(L, 1); | ||
284 | cTValue *mo = lj_meta_lookup(L, o, mm); | ||
285 | if (!tvisnil(mo)) { | ||
286 | L->top = o+1; /* Only keep one argument. */ | ||
287 | copyTV(L, L->base-1, mo); /* Replace callable. */ | ||
288 | return FFH_TAILCALL; | ||
289 | } else { | ||
290 | if (!tvistab(o)) lj_err_argt(L, 1, LUA_TTABLE); | ||
291 | setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1))); | ||
292 | if (mm == MM_pairs) setnilV(o+1); else setintV(o+1, 0); | ||
293 | return FFH_RES(3); | ||
294 | } | ||
295 | } | ||
296 | #else | ||
297 | #define ffh_pairs(L, mm) (lj_lib_checktab(L, 1), FFH_UNREACHABLE) | ||
298 | #endif | ||
299 | |||
300 | LJLIB_PUSH(lastcl) | ||
301 | LJLIB_ASM(pairs) | ||
302 | { | ||
303 | return ffh_pairs(L, MM_pairs); | ||
304 | } | ||
305 | |||
306 | LJLIB_NOREGUV LJLIB_ASM(ipairs_aux) LJLIB_REC(.) | ||
307 | { | ||
308 | lj_lib_checktab(L, 1); | ||
309 | lj_lib_checkint(L, 2); | ||
310 | return FFH_UNREACHABLE; | ||
311 | } | ||
312 | |||
313 | LJLIB_PUSH(lastcl) | ||
314 | LJLIB_ASM(ipairs) LJLIB_REC(.) | ||
315 | { | ||
316 | return ffh_pairs(L, MM_ipairs); | ||
317 | } | ||
318 | |||
319 | /* -- Base library: throw and catch errors -------------------------------- */ | ||
320 | |||
321 | LJLIB_CF(error) | ||
322 | { | ||
323 | int32_t level = lj_lib_optint(L, 2, 1); | ||
324 | lua_settop(L, 1); | ||
325 | if (lua_isstring(L, 1) && level > 0) { | ||
326 | luaL_where(L, level); | ||
327 | lua_pushvalue(L, 1); | ||
328 | lua_concat(L, 2); | ||
329 | } | ||
330 | return lua_error(L); | ||
331 | } | ||
332 | |||
333 | LJLIB_ASM(pcall) LJLIB_REC(.) | ||
334 | { | ||
335 | lj_lib_checkany(L, 1); | ||
336 | lj_lib_checkfunc(L, 2); /* For xpcall only. */ | ||
337 | return FFH_UNREACHABLE; | ||
338 | } | ||
339 | LJLIB_ASM_(xpcall) LJLIB_REC(.) | ||
340 | |||
341 | /* -- Base library: load Lua code ----------------------------------------- */ | ||
342 | |||
343 | static int load_aux(lua_State *L, int status) | ||
344 | { | ||
345 | if (status == 0) | ||
346 | return 1; | ||
347 | copyTV(L, L->top, L->top-1); | ||
348 | setnilV(L->top-1); | ||
349 | L->top++; | ||
350 | return 2; | ||
351 | } | ||
352 | |||
353 | LJLIB_CF(loadstring) | ||
354 | { | ||
355 | GCstr *s = lj_lib_checkstr(L, 1); | ||
356 | GCstr *name = lj_lib_optstr(L, 2); | ||
357 | return load_aux(L, | ||
358 | luaL_loadbuffer(L, strdata(s), s->len, strdata(name ? name : s))); | ||
359 | } | ||
360 | |||
361 | LJLIB_CF(loadfile) | ||
362 | { | ||
363 | GCstr *fname = lj_lib_optstr(L, 1); | ||
364 | return load_aux(L, luaL_loadfile(L, fname ? strdata(fname) : NULL)); | ||
365 | } | ||
366 | |||
367 | static const char *reader_func(lua_State *L, void *ud, size_t *size) | ||
368 | { | ||
369 | UNUSED(ud); | ||
370 | luaL_checkstack(L, 2, "too many nested functions"); | ||
371 | copyTV(L, L->top++, L->base); | ||
372 | lua_call(L, 0, 1); /* Call user-supplied function. */ | ||
373 | L->top--; | ||
374 | if (tvisnil(L->top)) { | ||
375 | *size = 0; | ||
376 | return NULL; | ||
377 | } else if (tvisstr(L->top) || tvisnumber(L->top)) { | ||
378 | copyTV(L, L->base+2, L->top); /* Anchor string in reserved stack slot. */ | ||
379 | return lua_tolstring(L, 3, size); | ||
380 | } else { | ||
381 | lj_err_caller(L, LJ_ERR_RDRSTR); | ||
382 | return NULL; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | LJLIB_CF(load) | ||
387 | { | ||
388 | GCstr *name; | ||
389 | if (L->base < L->top && (tvisstr(L->base) || tvisnumber(L->base))) | ||
390 | return lj_cf_loadstring(L); | ||
391 | lj_lib_checkfunc(L, 1); | ||
392 | name = lj_lib_optstr(L, 2); | ||
393 | lua_settop(L, 3); /* Reserve a slot for the string from the reader. */ | ||
394 | return load_aux(L, | ||
395 | lua_load(L, reader_func, NULL, name ? strdata(name) : "=(load)")); | ||
396 | } | ||
397 | |||
398 | LJLIB_CF(dofile) | ||
399 | { | ||
400 | GCstr *fname = lj_lib_optstr(L, 1); | ||
401 | setnilV(L->top); | ||
402 | L->top = L->base+1; | ||
403 | if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != 0) | ||
404 | lua_error(L); | ||
405 | lua_call(L, 0, LUA_MULTRET); | ||
406 | return (int)(L->top - L->base) - 1; | ||
407 | } | ||
408 | |||
409 | /* -- Base library: GC control -------------------------------------------- */ | ||
410 | |||
411 | LJLIB_CF(gcinfo) | ||
412 | { | ||
413 | setintV(L->top++, (G(L)->gc.total >> 10)); | ||
414 | return 1; | ||
415 | } | ||
416 | |||
417 | LJLIB_CF(collectgarbage) | ||
418 | { | ||
419 | int opt = lj_lib_checkopt(L, 1, LUA_GCCOLLECT, /* ORDER LUA_GC* */ | ||
420 | "\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul"); | ||
421 | int32_t data = lj_lib_optint(L, 2, 0); | ||
422 | if (opt == LUA_GCCOUNT) { | ||
423 | setnumV(L->top, (lua_Number)G(L)->gc.total/1024.0); | ||
424 | } else { | ||
425 | int res = lua_gc(L, opt, data); | ||
426 | if (opt == LUA_GCSTEP) | ||
427 | setboolV(L->top, res); | ||
428 | else | ||
429 | setintV(L->top, res); | ||
430 | } | ||
431 | L->top++; | ||
432 | return 1; | ||
433 | } | ||
434 | |||
435 | /* -- Base library: miscellaneous functions ------------------------------- */ | ||
436 | |||
437 | LJLIB_PUSH(top-2) /* Upvalue holds weak table. */ | ||
438 | LJLIB_CF(newproxy) | ||
439 | { | ||
440 | lua_settop(L, 1); | ||
441 | lua_newuserdata(L, 0); | ||
442 | if (lua_toboolean(L, 1) == 0) { /* newproxy(): without metatable. */ | ||
443 | return 1; | ||
444 | } else if (lua_isboolean(L, 1)) { /* newproxy(true): with metatable. */ | ||
445 | lua_newtable(L); | ||
446 | lua_pushvalue(L, -1); | ||
447 | lua_pushboolean(L, 1); | ||
448 | lua_rawset(L, lua_upvalueindex(1)); /* Remember mt in weak table. */ | ||
449 | } else { /* newproxy(proxy): inherit metatable. */ | ||
450 | int validproxy = 0; | ||
451 | if (lua_getmetatable(L, 1)) { | ||
452 | lua_rawget(L, lua_upvalueindex(1)); | ||
453 | validproxy = lua_toboolean(L, -1); | ||
454 | lua_pop(L, 1); | ||
455 | } | ||
456 | if (!validproxy) | ||
457 | lj_err_arg(L, 1, LJ_ERR_NOPROXY); | ||
458 | lua_getmetatable(L, 1); | ||
459 | } | ||
460 | lua_setmetatable(L, 2); | ||
461 | return 1; | ||
462 | } | ||
463 | |||
464 | LJLIB_PUSH("tostring") | ||
465 | LJLIB_CF(print) | ||
466 | { | ||
467 | ptrdiff_t i, nargs = L->top - L->base; | ||
468 | cTValue *tv = lj_tab_getstr(tabref(L->env), strV(lj_lib_upvalue(L, 1))); | ||
469 | int shortcut; | ||
470 | if (tv && !tvisnil(tv)) { | ||
471 | copyTV(L, L->top++, tv); | ||
472 | } else { | ||
473 | setstrV(L, L->top++, strV(lj_lib_upvalue(L, 1))); | ||
474 | lua_gettable(L, LUA_GLOBALSINDEX); | ||
475 | tv = L->top-1; | ||
476 | } | ||
477 | shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring); | ||
478 | for (i = 0; i < nargs; i++) { | ||
479 | const char *str; | ||
480 | size_t size; | ||
481 | cTValue *o = &L->base[i]; | ||
482 | if (shortcut && tvisstr(o)) { | ||
483 | str = strVdata(o); | ||
484 | size = strV(o)->len; | ||
485 | } else if (shortcut && tvisint(o)) { | ||
486 | char buf[LJ_STR_INTBUF]; | ||
487 | char *p = lj_str_bufint(buf, intV(o)); | ||
488 | size = (size_t)(buf+LJ_STR_INTBUF-p); | ||
489 | str = p; | ||
490 | } else if (shortcut && tvisnum(o)) { | ||
491 | char buf[LJ_STR_NUMBUF]; | ||
492 | size = lj_str_bufnum(buf, o); | ||
493 | str = buf; | ||
494 | } else { | ||
495 | copyTV(L, L->top+1, o); | ||
496 | copyTV(L, L->top, L->top-1); | ||
497 | L->top += 2; | ||
498 | lua_call(L, 1, 1); | ||
499 | str = lua_tolstring(L, -1, &size); | ||
500 | if (!str) | ||
501 | lj_err_caller(L, LJ_ERR_PRTOSTR); | ||
502 | L->top--; | ||
503 | } | ||
504 | if (i) | ||
505 | putchar('\t'); | ||
506 | fwrite(str, 1, size, stdout); | ||
507 | } | ||
508 | putchar('\n'); | ||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | LJLIB_PUSH(top-3) | ||
513 | LJLIB_SET(_VERSION) | ||
514 | |||
515 | #include "lj_libdef.h" | ||
516 | |||
517 | /* -- Coroutine library --------------------------------------------------- */ | ||
518 | |||
519 | #define LJLIB_MODULE_coroutine | ||
520 | |||
521 | LJLIB_CF(coroutine_status) | ||
522 | { | ||
523 | const char *s; | ||
524 | lua_State *co; | ||
525 | if (!(L->top > L->base && tvisthread(L->base))) | ||
526 | lj_err_arg(L, 1, LJ_ERR_NOCORO); | ||
527 | co = threadV(L->base); | ||
528 | if (co == L) s = "running"; | ||
529 | else if (co->status == LUA_YIELD) s = "suspended"; | ||
530 | else if (co->status != 0) s = "dead"; | ||
531 | else if (co->base > tvref(co->stack)+1) s = "normal"; | ||
532 | else if (co->top == co->base) s = "dead"; | ||
533 | else s = "suspended"; | ||
534 | lua_pushstring(L, s); | ||
535 | return 1; | ||
536 | } | ||
537 | |||
538 | LJLIB_CF(coroutine_running) | ||
539 | { | ||
540 | #ifdef LUAJIT_ENABLE_LUA52COMPAT | ||
541 | int ismain = lua_pushthread(L); | ||
542 | setboolV(L->top++, ismain); | ||
543 | return 2; | ||
544 | #else | ||
545 | if (lua_pushthread(L)) | ||
546 | setnilV(L->top++); | ||
547 | return 1; | ||
548 | #endif | ||
549 | } | ||
550 | |||
551 | LJLIB_CF(coroutine_create) | ||
552 | { | ||
553 | lua_State *L1 = lua_newthread(L); | ||
554 | if (!(L->base < L->top && tvisfunc(L->base))) | ||
555 | lj_err_argt(L, 1, LUA_TFUNCTION); | ||
556 | setfuncV(L, L1->top++, funcV(L->base)); | ||
557 | return 1; | ||
558 | } | ||
559 | |||
560 | LJLIB_ASM(coroutine_yield) | ||
561 | { | ||
562 | lj_err_caller(L, LJ_ERR_CYIELD); | ||
563 | return FFH_UNREACHABLE; | ||
564 | } | ||
565 | |||
566 | static int ffh_resume(lua_State *L, lua_State *co, int wrap) | ||
567 | { | ||
568 | if (co->cframe != NULL || co->status > LUA_YIELD || | ||
569 | (co->status == 0 && co->top == co->base)) { | ||
570 | ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD; | ||
571 | if (wrap) lj_err_caller(L, em); | ||
572 | setboolV(L->base-1, 0); | ||
573 | setstrV(L, L->base, lj_err_str(L, em)); | ||
574 | return FFH_RES(2); | ||
575 | } | ||
576 | lj_state_growstack(co, (MSize)(L->top - L->base)); | ||
577 | return FFH_RETRY; | ||
578 | } | ||
579 | |||
580 | LJLIB_ASM(coroutine_resume) | ||
581 | { | ||
582 | if (!(L->top > L->base && tvisthread(L->base))) | ||
583 | lj_err_arg(L, 1, LJ_ERR_NOCORO); | ||
584 | return ffh_resume(L, threadV(L->base), 0); | ||
585 | } | ||
586 | |||
587 | LJLIB_NOREG LJLIB_ASM(coroutine_wrap_aux) | ||
588 | { | ||
589 | return ffh_resume(L, threadV(lj_lib_upvalue(L, 1)), 1); | ||
590 | } | ||
591 | |||
592 | /* Inline declarations. */ | ||
593 | LJ_ASMF void lj_ff_coroutine_wrap_aux(void); | ||
594 | LJ_FUNCA_NORET void LJ_FASTCALL lj_ffh_coroutine_wrap_err(lua_State *L, | ||
595 | lua_State *co); | ||
596 | |||
597 | /* Error handler, called from assembler VM. */ | ||
598 | void LJ_FASTCALL lj_ffh_coroutine_wrap_err(lua_State *L, lua_State *co) | ||
599 | { | ||
600 | co->top--; copyTV(L, L->top, co->top); L->top++; | ||
601 | if (tvisstr(L->top-1)) | ||
602 | lj_err_callermsg(L, strVdata(L->top-1)); | ||
603 | else | ||
604 | lj_err_run(L); | ||
605 | } | ||
606 | |||
607 | /* Forward declaration. */ | ||
608 | static void setpc_wrap_aux(lua_State *L, GCfunc *fn); | ||
609 | |||
610 | LJLIB_CF(coroutine_wrap) | ||
611 | { | ||
612 | lj_cf_coroutine_create(L); | ||
613 | lj_lib_pushcc(L, lj_ffh_coroutine_wrap_aux, FF_coroutine_wrap_aux, 1); | ||
614 | setpc_wrap_aux(L, funcV(L->top-1)); | ||
615 | return 1; | ||
616 | } | ||
617 | |||
618 | #include "lj_libdef.h" | ||
619 | |||
620 | /* Fix the PC of wrap_aux. Really ugly workaround. */ | ||
621 | static void setpc_wrap_aux(lua_State *L, GCfunc *fn) | ||
622 | { | ||
623 | setmref(fn->c.pc, &L2GG(L)->bcff[lj_lib_init_coroutine[1]+2]); | ||
624 | } | ||
625 | |||
626 | /* ------------------------------------------------------------------------ */ | ||
627 | |||
628 | static void newproxy_weaktable(lua_State *L) | ||
629 | { | ||
630 | /* NOBARRIER: The table is new (marked white). */ | ||
631 | GCtab *t = lj_tab_new(L, 0, 1); | ||
632 | settabV(L, L->top++, t); | ||
633 | setgcref(t->metatable, obj2gco(t)); | ||
634 | setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")), | ||
635 | lj_str_newlit(L, "kv")); | ||
636 | t->nomm = (uint8_t)(~(1u<<MM_mode)); | ||
637 | } | ||
638 | |||
639 | LUALIB_API int luaopen_base(lua_State *L) | ||
640 | { | ||
641 | /* NOBARRIER: Table and value are the same. */ | ||
642 | GCtab *env = tabref(L->env); | ||
643 | settabV(L, lj_tab_setstr(L, env, lj_str_newlit(L, "_G")), env); | ||
644 | lua_pushliteral(L, LUA_VERSION); /* top-3. */ | ||
645 | newproxy_weaktable(L); /* top-2. */ | ||
646 | LJ_LIB_REG(L, "_G", base); | ||
647 | LJ_LIB_REG(L, LUA_COLIBNAME, coroutine); | ||
648 | return 2; | ||
649 | } | ||
650 | |||