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-1.1.7/src/lbaselib.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-1.1.7/src/lbaselib.c | 679 |
1 files changed, 679 insertions, 0 deletions
diff --git a/libraries/LuaJIT-1.1.7/src/lbaselib.c b/libraries/LuaJIT-1.1.7/src/lbaselib.c new file mode 100644 index 0000000..2366a02 --- /dev/null +++ b/libraries/LuaJIT-1.1.7/src/lbaselib.c | |||
@@ -0,0 +1,679 @@ | |||
1 | /* | ||
2 | ** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ | ||
3 | ** Basic library | ||
4 | ** See Copyright Notice in lua.h | ||
5 | */ | ||
6 | |||
7 | |||
8 | |||
9 | #include <ctype.h> | ||
10 | #include <stdio.h> | ||
11 | #include <stdlib.h> | ||
12 | #include <string.h> | ||
13 | |||
14 | #define lbaselib_c | ||
15 | #define LUA_LIB | ||
16 | |||
17 | #include "lua.h" | ||
18 | |||
19 | #include "lauxlib.h" | ||
20 | #include "lualib.h" | ||
21 | #ifndef COCO_DISABLE | ||
22 | #include "lcoco.h" | ||
23 | #endif | ||
24 | |||
25 | |||
26 | |||
27 | |||
28 | /* | ||
29 | ** If your system does not support `stdout', you can just remove this function. | ||
30 | ** If you need, you can define your own `print' function, following this | ||
31 | ** model but changing `fputs' to put the strings at a proper place | ||
32 | ** (a console window or a log file, for instance). | ||
33 | */ | ||
34 | static int luaB_print (lua_State *L) { | ||
35 | int n = lua_gettop(L); /* number of arguments */ | ||
36 | int i; | ||
37 | lua_getglobal(L, "tostring"); | ||
38 | for (i=1; i<=n; i++) { | ||
39 | const char *s; | ||
40 | lua_pushvalue(L, -1); /* function to be called */ | ||
41 | lua_pushvalue(L, i); /* value to print */ | ||
42 | lua_call(L, 1, 1); | ||
43 | s = lua_tostring(L, -1); /* get result */ | ||
44 | if (s == NULL) | ||
45 | return luaL_error(L, LUA_QL("tostring") " must return a string to " | ||
46 | LUA_QL("print")); | ||
47 | if (i>1) fputs("\t", stdout); | ||
48 | fputs(s, stdout); | ||
49 | lua_pop(L, 1); /* pop result */ | ||
50 | } | ||
51 | fputs("\n", stdout); | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | |||
56 | static int luaB_tonumber (lua_State *L) { | ||
57 | int base = luaL_optint(L, 2, 10); | ||
58 | if (base == 10) { /* standard conversion */ | ||
59 | luaL_checkany(L, 1); | ||
60 | if (lua_isnumber(L, 1)) { | ||
61 | lua_pushnumber(L, lua_tonumber(L, 1)); | ||
62 | return 1; | ||
63 | } | ||
64 | } | ||
65 | else { | ||
66 | const char *s1 = luaL_checkstring(L, 1); | ||
67 | char *s2; | ||
68 | unsigned long n; | ||
69 | luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); | ||
70 | n = strtoul(s1, &s2, base); | ||
71 | if (s1 != s2) { /* at least one valid digit? */ | ||
72 | while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ | ||
73 | if (*s2 == '\0') { /* no invalid trailing characters? */ | ||
74 | lua_pushnumber(L, (lua_Number)n); | ||
75 | return 1; | ||
76 | } | ||
77 | } | ||
78 | } | ||
79 | lua_pushnil(L); /* else not a number */ | ||
80 | return 1; | ||
81 | } | ||
82 | |||
83 | |||
84 | static int luaB_error (lua_State *L) { | ||
85 | int level = luaL_optint(L, 2, 1); | ||
86 | lua_settop(L, 1); | ||
87 | if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ | ||
88 | luaL_where(L, level); | ||
89 | lua_pushvalue(L, 1); | ||
90 | lua_concat(L, 2); | ||
91 | } | ||
92 | return lua_error(L); | ||
93 | } | ||
94 | |||
95 | |||
96 | static int luaB_getmetatable (lua_State *L) { | ||
97 | luaL_checkany(L, 1); | ||
98 | if (!lua_getmetatable(L, 1)) { | ||
99 | lua_pushnil(L); | ||
100 | return 1; /* no metatable */ | ||
101 | } | ||
102 | luaL_getmetafield(L, 1, "__metatable"); | ||
103 | return 1; /* returns either __metatable field (if present) or metatable */ | ||
104 | } | ||
105 | |||
106 | |||
107 | static int luaB_setmetatable (lua_State *L) { | ||
108 | int t = lua_type(L, 2); | ||
109 | luaL_checktype(L, 1, LUA_TTABLE); | ||
110 | luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, | ||
111 | "nil or table expected"); | ||
112 | if (luaL_getmetafield(L, 1, "__metatable")) | ||
113 | luaL_error(L, "cannot change a protected metatable"); | ||
114 | lua_settop(L, 2); | ||
115 | lua_setmetatable(L, 1); | ||
116 | return 1; | ||
117 | } | ||
118 | |||
119 | |||
120 | static void getfunc (lua_State *L, int opt) { | ||
121 | if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); | ||
122 | else { | ||
123 | lua_Debug ar; | ||
124 | int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); | ||
125 | luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); | ||
126 | if (lua_getstack(L, level, &ar) == 0) | ||
127 | luaL_argerror(L, 1, "invalid level"); | ||
128 | lua_getinfo(L, "f", &ar); | ||
129 | if (lua_isnil(L, -1)) | ||
130 | luaL_error(L, "no function environment for tail call at level %d", | ||
131 | level); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | |||
136 | static int luaB_getfenv (lua_State *L) { | ||
137 | getfunc(L, 1); | ||
138 | if (lua_iscfunction(L, -1)) /* is a C function? */ | ||
139 | lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ | ||
140 | else | ||
141 | lua_getfenv(L, -1); | ||
142 | return 1; | ||
143 | } | ||
144 | |||
145 | |||
146 | static int luaB_setfenv (lua_State *L) { | ||
147 | luaL_checktype(L, 2, LUA_TTABLE); | ||
148 | getfunc(L, 0); | ||
149 | lua_pushvalue(L, 2); | ||
150 | if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { | ||
151 | /* change environment of current thread */ | ||
152 | lua_pushthread(L); | ||
153 | lua_insert(L, -2); | ||
154 | lua_setfenv(L, -2); | ||
155 | return 0; | ||
156 | } | ||
157 | else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) | ||
158 | luaL_error(L, | ||
159 | LUA_QL("setfenv") " cannot change environment of given object"); | ||
160 | return 1; | ||
161 | } | ||
162 | |||
163 | |||
164 | static int luaB_rawequal (lua_State *L) { | ||
165 | luaL_checkany(L, 1); | ||
166 | luaL_checkany(L, 2); | ||
167 | lua_pushboolean(L, lua_rawequal(L, 1, 2)); | ||
168 | return 1; | ||
169 | } | ||
170 | |||
171 | |||
172 | static int luaB_rawget (lua_State *L) { | ||
173 | luaL_checktype(L, 1, LUA_TTABLE); | ||
174 | luaL_checkany(L, 2); | ||
175 | lua_settop(L, 2); | ||
176 | lua_rawget(L, 1); | ||
177 | return 1; | ||
178 | } | ||
179 | |||
180 | static int luaB_rawset (lua_State *L) { | ||
181 | luaL_checktype(L, 1, LUA_TTABLE); | ||
182 | luaL_checkany(L, 2); | ||
183 | luaL_checkany(L, 3); | ||
184 | lua_settop(L, 3); | ||
185 | lua_rawset(L, 1); | ||
186 | return 1; | ||
187 | } | ||
188 | |||
189 | |||
190 | static int luaB_gcinfo (lua_State *L) { | ||
191 | lua_pushinteger(L, lua_getgccount(L)); | ||
192 | return 1; | ||
193 | } | ||
194 | |||
195 | |||
196 | static int luaB_collectgarbage (lua_State *L) { | ||
197 | static const char *const opts[] = {"stop", "restart", "collect", | ||
198 | "count", "step", "setpause", "setstepmul", NULL}; | ||
199 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, | ||
200 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; | ||
201 | int o = luaL_checkoption(L, 1, "collect", opts); | ||
202 | int ex = luaL_optint(L, 2, 0); | ||
203 | int res = lua_gc(L, optsnum[o], ex); | ||
204 | switch (optsnum[o]) { | ||
205 | case LUA_GCCOUNT: { | ||
206 | int b = lua_gc(L, LUA_GCCOUNTB, 0); | ||
207 | lua_pushnumber(L, res + ((lua_Number)b/1024)); | ||
208 | return 1; | ||
209 | } | ||
210 | case LUA_GCSTEP: { | ||
211 | lua_pushboolean(L, res); | ||
212 | return 1; | ||
213 | } | ||
214 | default: { | ||
215 | lua_pushnumber(L, res); | ||
216 | return 1; | ||
217 | } | ||
218 | } | ||
219 | } | ||
220 | |||
221 | |||
222 | static int luaB_type (lua_State *L) { | ||
223 | luaL_checkany(L, 1); | ||
224 | lua_pushstring(L, luaL_typename(L, 1)); | ||
225 | return 1; | ||
226 | } | ||
227 | |||
228 | |||
229 | static int luaB_next (lua_State *L) { | ||
230 | luaL_checktype(L, 1, LUA_TTABLE); | ||
231 | lua_settop(L, 2); /* create a 2nd argument if there isn't one */ | ||
232 | if (lua_next(L, 1)) | ||
233 | return 2; | ||
234 | else { | ||
235 | lua_pushnil(L); | ||
236 | return 1; | ||
237 | } | ||
238 | } | ||
239 | |||
240 | |||
241 | static int luaB_pairs (lua_State *L) { | ||
242 | luaL_checktype(L, 1, LUA_TTABLE); | ||
243 | lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ | ||
244 | lua_pushvalue(L, 1); /* state, */ | ||
245 | lua_pushnil(L); /* and initial value */ | ||
246 | return 3; | ||
247 | } | ||
248 | |||
249 | |||
250 | static int ipairsaux (lua_State *L) { | ||
251 | int i = luaL_checkint(L, 2); | ||
252 | luaL_checktype(L, 1, LUA_TTABLE); | ||
253 | i++; /* next value */ | ||
254 | lua_pushinteger(L, i); | ||
255 | lua_rawgeti(L, 1, i); | ||
256 | return (lua_isnil(L, -1)) ? 0 : 2; | ||
257 | } | ||
258 | |||
259 | |||
260 | static int luaB_ipairs (lua_State *L) { | ||
261 | luaL_checktype(L, 1, LUA_TTABLE); | ||
262 | lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ | ||
263 | lua_pushvalue(L, 1); /* state, */ | ||
264 | lua_pushinteger(L, 0); /* and initial value */ | ||
265 | return 3; | ||
266 | } | ||
267 | |||
268 | |||
269 | static int load_aux (lua_State *L, int status) { | ||
270 | if (status == 0) /* OK? */ | ||
271 | return 1; | ||
272 | else { | ||
273 | lua_pushnil(L); | ||
274 | lua_insert(L, -2); /* put before error message */ | ||
275 | return 2; /* return nil plus error message */ | ||
276 | } | ||
277 | } | ||
278 | |||
279 | |||
280 | static int luaB_loadstring (lua_State *L) { | ||
281 | size_t l; | ||
282 | const char *s = luaL_checklstring(L, 1, &l); | ||
283 | const char *chunkname = luaL_optstring(L, 2, s); | ||
284 | return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); | ||
285 | } | ||
286 | |||
287 | |||
288 | static int luaB_loadfile (lua_State *L) { | ||
289 | const char *fname = luaL_optstring(L, 1, NULL); | ||
290 | return load_aux(L, luaL_loadfile(L, fname)); | ||
291 | } | ||
292 | |||
293 | |||
294 | /* | ||
295 | ** Reader for generic `load' function: `lua_load' uses the | ||
296 | ** stack for internal stuff, so the reader cannot change the | ||
297 | ** stack top. Instead, it keeps its resulting string in a | ||
298 | ** reserved slot inside the stack. | ||
299 | */ | ||
300 | static const char *generic_reader (lua_State *L, void *ud, size_t *size) { | ||
301 | (void)ud; /* to avoid warnings */ | ||
302 | luaL_checkstack(L, 2, "too many nested functions"); | ||
303 | lua_pushvalue(L, 1); /* get function */ | ||
304 | lua_call(L, 0, 1); /* call it */ | ||
305 | if (lua_isnil(L, -1)) { | ||
306 | *size = 0; | ||
307 | return NULL; | ||
308 | } | ||
309 | else if (lua_isstring(L, -1)) { | ||
310 | lua_replace(L, 3); /* save string in a reserved stack slot */ | ||
311 | return lua_tolstring(L, 3, size); | ||
312 | } | ||
313 | else luaL_error(L, "reader function must return a string"); | ||
314 | return NULL; /* to avoid warnings */ | ||
315 | } | ||
316 | |||
317 | |||
318 | static int luaB_load (lua_State *L) { | ||
319 | int status; | ||
320 | const char *cname = luaL_optstring(L, 2, "=(load)"); | ||
321 | luaL_checktype(L, 1, LUA_TFUNCTION); | ||
322 | lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ | ||
323 | status = lua_load(L, generic_reader, NULL, cname); | ||
324 | return load_aux(L, status); | ||
325 | } | ||
326 | |||
327 | |||
328 | static int luaB_dofile (lua_State *L) { | ||
329 | const char *fname = luaL_optstring(L, 1, NULL); | ||
330 | int n = lua_gettop(L); | ||
331 | if (luaL_loadfile(L, fname) != 0) lua_error(L); | ||
332 | lua_call(L, 0, LUA_MULTRET); | ||
333 | return lua_gettop(L) - n; | ||
334 | } | ||
335 | |||
336 | |||
337 | static int luaB_assert (lua_State *L) { | ||
338 | luaL_checkany(L, 1); | ||
339 | if (!lua_toboolean(L, 1)) | ||
340 | return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); | ||
341 | return lua_gettop(L); | ||
342 | } | ||
343 | |||
344 | |||
345 | static int luaB_unpack (lua_State *L) { | ||
346 | int i, e, n; | ||
347 | luaL_checktype(L, 1, LUA_TTABLE); | ||
348 | i = luaL_optint(L, 2, 1); | ||
349 | e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); | ||
350 | if (i > e) return 0; /* empty range */ | ||
351 | n = e - i + 1; /* number of elements */ | ||
352 | if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ | ||
353 | return luaL_error(L, "too many results to unpack"); | ||
354 | lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ | ||
355 | while (i++ < e) /* push arg[i + 1...e] */ | ||
356 | lua_rawgeti(L, 1, i); | ||
357 | return n; | ||
358 | } | ||
359 | |||
360 | |||
361 | static int luaB_select (lua_State *L) { | ||
362 | int n = lua_gettop(L); | ||
363 | if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { | ||
364 | lua_pushinteger(L, n-1); | ||
365 | return 1; | ||
366 | } | ||
367 | else { | ||
368 | int i = luaL_checkint(L, 1); | ||
369 | if (i < 0) i = n + i; | ||
370 | else if (i > n) i = n; | ||
371 | luaL_argcheck(L, 1 <= i, 1, "index out of range"); | ||
372 | return n - i; | ||
373 | } | ||
374 | } | ||
375 | |||
376 | |||
377 | static int luaB_pcall (lua_State *L) { | ||
378 | int status; | ||
379 | luaL_checkany(L, 1); | ||
380 | status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); | ||
381 | lua_pushboolean(L, (status == 0)); | ||
382 | lua_insert(L, 1); | ||
383 | return lua_gettop(L); /* return status + all results */ | ||
384 | } | ||
385 | |||
386 | |||
387 | static int luaB_xpcall (lua_State *L) { | ||
388 | int status; | ||
389 | luaL_checkany(L, 2); | ||
390 | lua_settop(L, 2); | ||
391 | lua_insert(L, 1); /* put error function under function to be called */ | ||
392 | status = lua_pcall(L, 0, LUA_MULTRET, 1); | ||
393 | lua_pushboolean(L, (status == 0)); | ||
394 | lua_replace(L, 1); | ||
395 | return lua_gettop(L); /* return status + all results */ | ||
396 | } | ||
397 | |||
398 | |||
399 | static int luaB_tostring (lua_State *L) { | ||
400 | luaL_checkany(L, 1); | ||
401 | if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ | ||
402 | return 1; /* use its value */ | ||
403 | switch (lua_type(L, 1)) { | ||
404 | case LUA_TNUMBER: | ||
405 | lua_pushstring(L, lua_tostring(L, 1)); | ||
406 | break; | ||
407 | case LUA_TSTRING: | ||
408 | lua_pushvalue(L, 1); | ||
409 | break; | ||
410 | case LUA_TBOOLEAN: | ||
411 | lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); | ||
412 | break; | ||
413 | case LUA_TNIL: | ||
414 | lua_pushliteral(L, "nil"); | ||
415 | break; | ||
416 | default: | ||
417 | lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); | ||
418 | break; | ||
419 | } | ||
420 | return 1; | ||
421 | } | ||
422 | |||
423 | |||
424 | static int luaB_newproxy (lua_State *L) { | ||
425 | lua_settop(L, 1); | ||
426 | lua_newuserdata(L, 0); /* create proxy */ | ||
427 | if (lua_toboolean(L, 1) == 0) | ||
428 | return 1; /* no metatable */ | ||
429 | else if (lua_isboolean(L, 1)) { | ||
430 | lua_newtable(L); /* create a new metatable `m' ... */ | ||
431 | lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ | ||
432 | lua_pushboolean(L, 1); | ||
433 | lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ | ||
434 | } | ||
435 | else { | ||
436 | int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ | ||
437 | if (lua_getmetatable(L, 1)) { | ||
438 | lua_rawget(L, lua_upvalueindex(1)); | ||
439 | validproxy = lua_toboolean(L, -1); | ||
440 | lua_pop(L, 1); /* remove value */ | ||
441 | } | ||
442 | luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); | ||
443 | lua_getmetatable(L, 1); /* metatable is valid; get it */ | ||
444 | } | ||
445 | lua_setmetatable(L, 2); | ||
446 | return 1; | ||
447 | } | ||
448 | |||
449 | |||
450 | static const luaL_Reg base_funcs[] = { | ||
451 | {"assert", luaB_assert}, | ||
452 | {"collectgarbage", luaB_collectgarbage}, | ||
453 | {"dofile", luaB_dofile}, | ||
454 | {"error", luaB_error}, | ||
455 | {"gcinfo", luaB_gcinfo}, | ||
456 | {"getfenv", luaB_getfenv}, | ||
457 | {"getmetatable", luaB_getmetatable}, | ||
458 | {"loadfile", luaB_loadfile}, | ||
459 | {"load", luaB_load}, | ||
460 | {"loadstring", luaB_loadstring}, | ||
461 | {"next", luaB_next}, | ||
462 | {"pcall", luaB_pcall}, | ||
463 | {"print", luaB_print}, | ||
464 | {"rawequal", luaB_rawequal}, | ||
465 | {"rawget", luaB_rawget}, | ||
466 | {"rawset", luaB_rawset}, | ||
467 | {"select", luaB_select}, | ||
468 | {"setfenv", luaB_setfenv}, | ||
469 | {"setmetatable", luaB_setmetatable}, | ||
470 | {"tonumber", luaB_tonumber}, | ||
471 | {"tostring", luaB_tostring}, | ||
472 | {"type", luaB_type}, | ||
473 | {"unpack", luaB_unpack}, | ||
474 | {"xpcall", luaB_xpcall}, | ||
475 | {NULL, NULL} | ||
476 | }; | ||
477 | |||
478 | |||
479 | /* | ||
480 | ** {====================================================== | ||
481 | ** Coroutine library | ||
482 | ** ======================================================= | ||
483 | */ | ||
484 | |||
485 | #define CO_RUN 0 /* running */ | ||
486 | #define CO_SUS 1 /* suspended */ | ||
487 | #define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ | ||
488 | #define CO_DEAD 3 | ||
489 | |||
490 | static const char *const statnames[] = | ||
491 | {"running", "suspended", "normal", "dead"}; | ||
492 | |||
493 | static int costatus (lua_State *L, lua_State *co) { | ||
494 | if (L == co) return CO_RUN; | ||
495 | switch (lua_status(co)) { | ||
496 | case LUA_YIELD: | ||
497 | return CO_SUS; | ||
498 | case 0: { | ||
499 | lua_Debug ar; | ||
500 | if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ | ||
501 | return CO_NOR; /* it is running */ | ||
502 | else if (lua_gettop(co) == 0) | ||
503 | return CO_DEAD; | ||
504 | else | ||
505 | return CO_SUS; /* initial state */ | ||
506 | } | ||
507 | default: /* some error occured */ | ||
508 | return CO_DEAD; | ||
509 | } | ||
510 | } | ||
511 | |||
512 | |||
513 | static int luaB_costatus (lua_State *L) { | ||
514 | lua_State *co = lua_tothread(L, 1); | ||
515 | luaL_argcheck(L, co, 1, "coroutine expected"); | ||
516 | lua_pushstring(L, statnames[costatus(L, co)]); | ||
517 | return 1; | ||
518 | } | ||
519 | |||
520 | |||
521 | static int auxresume (lua_State *L, lua_State *co, int narg) { | ||
522 | int status = costatus(L, co); | ||
523 | if (!lua_checkstack(co, narg)) | ||
524 | luaL_error(L, "too many arguments to resume"); | ||
525 | if (status != CO_SUS) { | ||
526 | lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); | ||
527 | return -1; /* error flag */ | ||
528 | } | ||
529 | lua_xmove(L, co, narg); | ||
530 | status = lua_resume(co, narg); | ||
531 | if (status == 0 || status == LUA_YIELD) { | ||
532 | int nres = lua_gettop(co); | ||
533 | if (!lua_checkstack(L, nres + 1)) | ||
534 | luaL_error(L, "too many results to resume"); | ||
535 | lua_xmove(co, L, nres); /* move yielded values */ | ||
536 | return nres; | ||
537 | } | ||
538 | else { | ||
539 | lua_xmove(co, L, 1); /* move error message */ | ||
540 | return -1; /* error flag */ | ||
541 | } | ||
542 | } | ||
543 | |||
544 | |||
545 | static int luaB_coresume (lua_State *L) { | ||
546 | lua_State *co = lua_tothread(L, 1); | ||
547 | int r; | ||
548 | luaL_argcheck(L, co, 1, "coroutine expected"); | ||
549 | r = auxresume(L, co, lua_gettop(L) - 1); | ||
550 | if (r < 0) { | ||
551 | lua_pushboolean(L, 0); | ||
552 | lua_insert(L, -2); | ||
553 | return 2; /* return false + error message */ | ||
554 | } | ||
555 | else { | ||
556 | lua_pushboolean(L, 1); | ||
557 | lua_insert(L, -(r + 1)); | ||
558 | return r + 1; /* return true + `resume' returns */ | ||
559 | } | ||
560 | } | ||
561 | |||
562 | |||
563 | static int luaB_auxwrap (lua_State *L) { | ||
564 | lua_State *co = lua_tothread(L, lua_upvalueindex(1)); | ||
565 | int r = auxresume(L, co, lua_gettop(L)); | ||
566 | if (r < 0) { | ||
567 | if (lua_isstring(L, -1)) { /* error object is a string? */ | ||
568 | luaL_where(L, 1); /* add extra info */ | ||
569 | lua_insert(L, -2); | ||
570 | lua_concat(L, 2); | ||
571 | } | ||
572 | lua_error(L); /* propagate error */ | ||
573 | } | ||
574 | return r; | ||
575 | } | ||
576 | |||
577 | |||
578 | #ifndef COCO_DISABLE | ||
579 | static int luaB_cstacksize (lua_State *L) | ||
580 | { | ||
581 | lua_pushinteger(L, luaCOCO_cstacksize(luaL_optint(L, 1, -1))); | ||
582 | return 1; | ||
583 | } | ||
584 | #endif | ||
585 | |||
586 | |||
587 | static int luaB_cocreate (lua_State *L) { | ||
588 | #ifdef COCO_DISABLE | ||
589 | lua_State *NL = lua_newthread(L); | ||
590 | luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, | ||
591 | "Lua function expected"); | ||
592 | #else | ||
593 | int cstacksize = luaL_optint(L, 2, 0); | ||
594 | lua_State *NL = lua_newcthread(L, cstacksize); | ||
595 | luaL_argcheck(L, lua_isfunction(L, 1) && | ||
596 | (cstacksize >= 0 ? 1 : !lua_iscfunction(L, 1)), | ||
597 | 1, "Lua function expected"); | ||
598 | #endif | ||
599 | lua_pushvalue(L, 1); /* move function to top */ | ||
600 | lua_xmove(L, NL, 1); /* move function from L to NL */ | ||
601 | return 1; | ||
602 | } | ||
603 | |||
604 | |||
605 | static int luaB_cowrap (lua_State *L) { | ||
606 | luaB_cocreate(L); | ||
607 | lua_pushcclosure(L, luaB_auxwrap, 1); | ||
608 | return 1; | ||
609 | } | ||
610 | |||
611 | |||
612 | static int luaB_yield (lua_State *L) { | ||
613 | return lua_yield(L, lua_gettop(L)); | ||
614 | } | ||
615 | |||
616 | |||
617 | static int luaB_corunning (lua_State *L) { | ||
618 | if (lua_pushthread(L)) | ||
619 | lua_pushnil(L); /* main thread is not a coroutine */ | ||
620 | return 1; | ||
621 | } | ||
622 | |||
623 | |||
624 | static const luaL_Reg co_funcs[] = { | ||
625 | {"create", luaB_cocreate}, | ||
626 | {"resume", luaB_coresume}, | ||
627 | {"running", luaB_corunning}, | ||
628 | {"status", luaB_costatus}, | ||
629 | {"wrap", luaB_cowrap}, | ||
630 | {"yield", luaB_yield}, | ||
631 | #ifndef COCO_DISABLE | ||
632 | {"cstacksize", luaB_cstacksize}, | ||
633 | #endif | ||
634 | {NULL, NULL} | ||
635 | }; | ||
636 | |||
637 | /* }====================================================== */ | ||
638 | |||
639 | |||
640 | static void auxopen (lua_State *L, const char *name, | ||
641 | lua_CFunction f, lua_CFunction u) { | ||
642 | lua_pushcfunction(L, u); | ||
643 | lua_pushcclosure(L, f, 1); | ||
644 | lua_setfield(L, -2, name); | ||
645 | } | ||
646 | |||
647 | |||
648 | static void base_open (lua_State *L) { | ||
649 | /* set global _G */ | ||
650 | lua_pushvalue(L, LUA_GLOBALSINDEX); | ||
651 | lua_setglobal(L, "_G"); | ||
652 | /* open lib into global table */ | ||
653 | luaL_register(L, "_G", base_funcs); | ||
654 | lua_pushliteral(L, LUA_VERSION); | ||
655 | lua_setglobal(L, "_VERSION"); /* set global _VERSION */ | ||
656 | /* `ipairs' and `pairs' need auxliliary functions as upvalues */ | ||
657 | auxopen(L, "ipairs", luaB_ipairs, ipairsaux); | ||
658 | auxopen(L, "pairs", luaB_pairs, luaB_next); | ||
659 | /* `newproxy' needs a weaktable as upvalue */ | ||
660 | lua_createtable(L, 0, 1); /* new table `w' */ | ||
661 | lua_pushvalue(L, -1); /* `w' will be its own metatable */ | ||
662 | lua_setmetatable(L, -2); | ||
663 | lua_pushliteral(L, "kv"); | ||
664 | lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ | ||
665 | lua_pushcclosure(L, luaB_newproxy, 1); | ||
666 | lua_setglobal(L, "newproxy"); /* set global `newproxy' */ | ||
667 | } | ||
668 | |||
669 | |||
670 | LUALIB_API int luaopen_base (lua_State *L) { | ||
671 | base_open(L); | ||
672 | luaL_register(L, LUA_COLIBNAME, co_funcs); | ||
673 | #ifndef COCO_DISABLE | ||
674 | lua_pushboolean(L, 1); | ||
675 | lua_setfield(L, -2, "coco"); | ||
676 | #endif | ||
677 | return 2; | ||
678 | } | ||
679 | |||