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