|
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 |
|
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, int opt) { |
|
118 if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); |
|
119 else { |
|
120 lua_Debug ar; |
|
121 int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 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, 1); |
|
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, 0); |
|
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 if (i > e) return 0; /* empty range */ |
|
348 n = e - i + 1; /* number of elements */ |
|
349 if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ |
|
350 return luaL_error(L, "too many results to unpack"); |
|
351 lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ |
|
352 while (i++ < e) /* push arg[i + 1...e] */ |
|
353 lua_rawgeti(L, 1, i); |
|
354 return n; |
|
355 } |
|
356 |
|
357 |
|
358 static int luaB_select (lua_State *L) { |
|
359 int n = lua_gettop(L); |
|
360 if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { |
|
361 lua_pushinteger(L, n-1); |
|
362 return 1; |
|
363 } |
|
364 else { |
|
365 int i = luaL_checkint(L, 1); |
|
366 if (i < 0) i = n + i; |
|
367 else if (i > n) i = n; |
|
368 luaL_argcheck(L, 1 <= i, 1, "index out of range"); |
|
369 return n - i; |
|
370 } |
|
371 } |
|
372 |
|
373 |
|
374 static int luaB_pcall (lua_State *L) { |
|
375 int status; |
|
376 luaL_checkany(L, 1); |
|
377 status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); |
|
378 lua_pushboolean(L, (status == 0)); |
|
379 lua_insert(L, 1); |
|
380 return lua_gettop(L); /* return status + all results */ |
|
381 } |
|
382 |
|
383 |
|
384 static int luaB_xpcall (lua_State *L) { |
|
385 int status; |
|
386 luaL_checkany(L, 2); |
|
387 lua_settop(L, 2); |
|
388 lua_insert(L, 1); /* put error function under function to be called */ |
|
389 status = lua_pcall(L, 0, LUA_MULTRET, 1); |
|
390 lua_pushboolean(L, (status == 0)); |
|
391 lua_replace(L, 1); |
|
392 return lua_gettop(L); /* return status + all results */ |
|
393 } |
|
394 |
|
395 |
|
396 static int luaB_tostring (lua_State *L) { |
|
397 luaL_checkany(L, 1); |
|
398 if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ |
|
399 return 1; /* use its value */ |
|
400 switch (lua_type(L, 1)) { |
|
401 case LUA_TNUMBER: |
|
402 lua_pushstring(L, lua_tostring(L, 1)); |
|
403 break; |
|
404 case LUA_TSTRING: |
|
405 lua_pushvalue(L, 1); |
|
406 break; |
|
407 case LUA_TBOOLEAN: |
|
408 lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); |
|
409 break; |
|
410 case LUA_TNIL: |
|
411 lua_pushliteral(L, "nil"); |
|
412 break; |
|
413 default: |
|
414 lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); |
|
415 break; |
|
416 } |
|
417 return 1; |
|
418 } |
|
419 |
|
420 |
|
421 static int luaB_newproxy (lua_State *L) { |
|
422 lua_settop(L, 1); |
|
423 lua_newuserdata(L, 0); /* create proxy */ |
|
424 if (lua_toboolean(L, 1) == 0) |
|
425 return 1; /* no metatable */ |
|
426 else if (lua_isboolean(L, 1)) { |
|
427 lua_newtable(L); /* create a new metatable `m' ... */ |
|
428 lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ |
|
429 lua_pushboolean(L, 1); |
|
430 lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ |
|
431 } |
|
432 else { |
|
433 int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ |
|
434 if (lua_getmetatable(L, 1)) { |
|
435 lua_rawget(L, lua_upvalueindex(1)); |
|
436 validproxy = lua_toboolean(L, -1); |
|
437 lua_pop(L, 1); /* remove value */ |
|
438 } |
|
439 luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); |
|
440 lua_getmetatable(L, 1); /* metatable is valid; get it */ |
|
441 } |
|
442 lua_setmetatable(L, 2); |
|
443 return 1; |
|
444 } |
|
445 |
|
446 |
|
447 static const luaL_Reg base_funcs[] = { |
|
448 {"assert", luaB_assert}, |
|
449 {"collectgarbage", luaB_collectgarbage}, |
|
450 {"dofile", luaB_dofile}, |
|
451 {"error", luaB_error}, |
|
452 {"gcinfo", luaB_gcinfo}, |
|
453 {"getfenv", luaB_getfenv}, |
|
454 {"getmetatable", luaB_getmetatable}, |
|
455 {"loadfile", luaB_loadfile}, |
|
456 {"load", luaB_load}, |
|
457 {"loadstring", luaB_loadstring}, |
|
458 {"next", luaB_next}, |
|
459 {"pcall", luaB_pcall}, |
|
460 {"print", luaB_print}, |
|
461 {"rawequal", luaB_rawequal}, |
|
462 {"rawget", luaB_rawget}, |
|
463 {"rawset", luaB_rawset}, |
|
464 {"select", luaB_select}, |
|
465 {"setfenv", luaB_setfenv}, |
|
466 {"setmetatable", luaB_setmetatable}, |
|
467 {"tonumber", luaB_tonumber}, |
|
468 {"tostring", luaB_tostring}, |
|
469 {"type", luaB_type}, |
|
470 {"unpack", luaB_unpack}, |
|
471 {"xpcall", luaB_xpcall}, |
|
472 {NULL, NULL} |
|
473 }; |
|
474 |
|
475 |
|
476 /* |
|
477 ** {====================================================== |
|
478 ** Coroutine library |
|
479 ** ======================================================= |
|
480 */ |
|
481 |
|
482 #define CO_RUN 0 /* running */ |
|
483 #define CO_SUS 1 /* suspended */ |
|
484 #define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ |
|
485 #define CO_DEAD 3 |
|
486 |
|
487 static const char *const statnames[] = |
|
488 {"running", "suspended", "normal", "dead"}; |
|
489 |
|
490 static int costatus (lua_State *L, lua_State *co) { |
|
491 if (L == co) return CO_RUN; |
|
492 switch (lua_status(co)) { |
|
493 case LUA_YIELD: |
|
494 return CO_SUS; |
|
495 case 0: { |
|
496 lua_Debug ar; |
|
497 if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ |
|
498 return CO_NOR; /* it is running */ |
|
499 else if (lua_gettop(co) == 0) |
|
500 return CO_DEAD; |
|
501 else |
|
502 return CO_SUS; /* initial state */ |
|
503 } |
|
504 default: /* some error occured */ |
|
505 return CO_DEAD; |
|
506 } |
|
507 } |
|
508 |
|
509 |
|
510 static int luaB_costatus (lua_State *L) { |
|
511 lua_State *co = lua_tothread(L, 1); |
|
512 luaL_argcheck(L, co, 1, "coroutine expected"); |
|
513 lua_pushstring(L, statnames[costatus(L, co)]); |
|
514 return 1; |
|
515 } |
|
516 |
|
517 |
|
518 static int auxresume (lua_State *L, lua_State *co, int narg) { |
|
519 int status = costatus(L, co); |
|
520 if (!lua_checkstack(co, narg)) |
|
521 luaL_error(L, "too many arguments to resume"); |
|
522 if (status != CO_SUS) { |
|
523 lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); |
|
524 return -1; /* error flag */ |
|
525 } |
|
526 lua_xmove(L, co, narg); |
|
527 lua_setlevel(L, co); |
|
528 status = lua_resume(co, narg); |
|
529 if (status == 0 || status == LUA_YIELD) { |
|
530 int nres = lua_gettop(co); |
|
531 if (!lua_checkstack(L, nres + 1)) |
|
532 luaL_error(L, "too many results to resume"); |
|
533 lua_xmove(co, L, nres); /* move yielded values */ |
|
534 return nres; |
|
535 } |
|
536 else { |
|
537 lua_xmove(co, L, 1); /* move error message */ |
|
538 return -1; /* error flag */ |
|
539 } |
|
540 } |
|
541 |
|
542 |
|
543 static int luaB_coresume (lua_State *L) { |
|
544 lua_State *co = lua_tothread(L, 1); |
|
545 int r; |
|
546 luaL_argcheck(L, co, 1, "coroutine expected"); |
|
547 r = auxresume(L, co, lua_gettop(L) - 1); |
|
548 if (r < 0) { |
|
549 lua_pushboolean(L, 0); |
|
550 lua_insert(L, -2); |
|
551 return 2; /* return false + error message */ |
|
552 } |
|
553 else { |
|
554 lua_pushboolean(L, 1); |
|
555 lua_insert(L, -(r + 1)); |
|
556 return r + 1; /* return true + `resume' returns */ |
|
557 } |
|
558 } |
|
559 |
|
560 |
|
561 static int luaB_auxwrap (lua_State *L) { |
|
562 lua_State *co = lua_tothread(L, lua_upvalueindex(1)); |
|
563 int r = auxresume(L, co, lua_gettop(L)); |
|
564 if (r < 0) { |
|
565 if (lua_isstring(L, -1)) { /* error object is a string? */ |
|
566 luaL_where(L, 1); /* add extra info */ |
|
567 lua_insert(L, -2); |
|
568 lua_concat(L, 2); |
|
569 } |
|
570 lua_error(L); /* propagate error */ |
|
571 } |
|
572 return r; |
|
573 } |
|
574 |
|
575 |
|
576 static int luaB_cocreate (lua_State *L) { |
|
577 lua_State *NL = lua_newthread(L); |
|
578 luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, |
|
579 "Lua function expected"); |
|
580 lua_pushvalue(L, 1); /* move function to top */ |
|
581 lua_xmove(L, NL, 1); /* move function from L to NL */ |
|
582 return 1; |
|
583 } |
|
584 |
|
585 |
|
586 static int luaB_cowrap (lua_State *L) { |
|
587 luaB_cocreate(L); |
|
588 lua_pushcclosure(L, luaB_auxwrap, 1); |
|
589 return 1; |
|
590 } |
|
591 |
|
592 |
|
593 static int luaB_yield (lua_State *L) { |
|
594 return lua_yield(L, lua_gettop(L)); |
|
595 } |
|
596 |
|
597 |
|
598 static int luaB_corunning (lua_State *L) { |
|
599 if (lua_pushthread(L)) |
|
600 lua_pushnil(L); /* main thread is not a coroutine */ |
|
601 return 1; |
|
602 } |
|
603 |
|
604 |
|
605 static const luaL_Reg co_funcs[] = { |
|
606 {"create", luaB_cocreate}, |
|
607 {"resume", luaB_coresume}, |
|
608 {"running", luaB_corunning}, |
|
609 {"status", luaB_costatus}, |
|
610 {"wrap", luaB_cowrap}, |
|
611 {"yield", luaB_yield}, |
|
612 {NULL, NULL} |
|
613 }; |
|
614 |
|
615 /* }====================================================== */ |
|
616 |
|
617 |
|
618 static void auxopen (lua_State *L, const char *name, |
|
619 lua_CFunction f, lua_CFunction u) { |
|
620 lua_pushcfunction(L, u); |
|
621 lua_pushcclosure(L, f, 1); |
|
622 lua_setfield(L, -2, name); |
|
623 } |
|
624 |
|
625 |
|
626 static void base_open (lua_State *L) { |
|
627 /* set global _G */ |
|
628 lua_pushvalue(L, LUA_GLOBALSINDEX); |
|
629 lua_setglobal(L, "_G"); |
|
630 /* open lib into global table */ |
|
631 luaL_register(L, "_G", base_funcs); |
|
632 lua_pushliteral(L, LUA_VERSION); |
|
633 lua_setglobal(L, "_VERSION"); /* set global _VERSION */ |
|
634 /* `ipairs' and `pairs' need auxliliary functions as upvalues */ |
|
635 auxopen(L, "ipairs", luaB_ipairs, ipairsaux); |
|
636 auxopen(L, "pairs", luaB_pairs, luaB_next); |
|
637 /* `newproxy' needs a weaktable as upvalue */ |
|
638 lua_createtable(L, 0, 1); /* new table `w' */ |
|
639 lua_pushvalue(L, -1); /* `w' will be its own metatable */ |
|
640 lua_setmetatable(L, -2); |
|
641 lua_pushliteral(L, "kv"); |
|
642 lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ |
|
643 lua_pushcclosure(L, luaB_newproxy, 1); |
|
644 lua_setglobal(L, "newproxy"); /* set global `newproxy' */ |
|
645 } |
|
646 |
|
647 |
|
648 LUALIB_API int luaopen_base (lua_State *L) { |
|
649 base_open(L); |
|
650 luaL_register(L, LUA_COLIBNAME, co_funcs); |
|
651 return 2; |
|
652 } |
|
653 |