Imported from ../lua-5.0.3.tar.gz.
[lua.git] / src / lib / lbaselib.c
blobfb26a54a94001864c3fadec2187eb9ac468dc9fd
1 /*
2 ** $Id: lbaselib.c,v 1.130c 2003/04/03 13:35:34 roberto Exp $
3 ** Basic library
4 ** See Copyright Notice in lua.h
5 */
9 #include <ctype.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
14 #define lbaselib_c
16 #include "lua.h"
18 #include "lauxlib.h"
19 #include "lualib.h"
25 ** If your system does not support `stdout', you can just remove this function.
26 ** If you need, you can define your own `print' function, following this
27 ** model but changing `fputs' to put the strings at a proper place
28 ** (a console window or a log file, for instance).
30 static int luaB_print (lua_State *L) {
31 int n = lua_gettop(L); /* number of arguments */
32 int i;
33 lua_getglobal(L, "tostring");
34 for (i=1; i<=n; i++) {
35 const char *s;
36 lua_pushvalue(L, -1); /* function to be called */
37 lua_pushvalue(L, i); /* value to print */
38 lua_call(L, 1, 1);
39 s = lua_tostring(L, -1); /* get result */
40 if (s == NULL)
41 return luaL_error(L, "`tostring' must return a string to `print'");
42 if (i>1) fputs("\t", stdout);
43 fputs(s, stdout);
44 lua_pop(L, 1); /* pop result */
46 fputs("\n", stdout);
47 return 0;
51 static int luaB_tonumber (lua_State *L) {
52 int base = luaL_optint(L, 2, 10);
53 if (base == 10) { /* standard conversion */
54 luaL_checkany(L, 1);
55 if (lua_isnumber(L, 1)) {
56 lua_pushnumber(L, lua_tonumber(L, 1));
57 return 1;
60 else {
61 const char *s1 = luaL_checkstring(L, 1);
62 char *s2;
63 unsigned long n;
64 luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
65 n = strtoul(s1, &s2, base);
66 if (s1 != s2) { /* at least one valid digit? */
67 while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */
68 if (*s2 == '\0') { /* no invalid trailing characters? */
69 lua_pushnumber(L, (lua_Number)n);
70 return 1;
74 lua_pushnil(L); /* else not a number */
75 return 1;
79 static int luaB_error (lua_State *L) {
80 int level = luaL_optint(L, 2, 1);
81 luaL_checkany(L, 1);
82 if (!lua_isstring(L, 1) || level == 0)
83 lua_pushvalue(L, 1); /* propagate error message without changes */
84 else { /* add extra information */
85 luaL_where(L, level);
86 lua_pushvalue(L, 1);
87 lua_concat(L, 2);
89 return lua_error(L);
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 */
99 luaL_getmetafield(L, 1, "__metatable");
100 return 1; /* returns either __metatable field (if present) or metatable */
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;
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);
133 static int aux_getfenv (lua_State *L) {
134 lua_getfenv(L, -1);
135 lua_pushliteral(L, "__fenv");
136 lua_rawget(L, -2);
137 return !lua_isnil(L, -1);
141 static int luaB_getfenv (lua_State *L) {
142 getfunc(L);
143 if (!aux_getfenv(L)) /* __fenv not defined? */
144 lua_pop(L, 1); /* remove it, to return real environment */
145 return 1;
149 static int luaB_setfenv (lua_State *L) {
150 luaL_checktype(L, 2, LUA_TTABLE);
151 getfunc(L);
152 if (aux_getfenv(L)) /* __fenv defined? */
153 luaL_error(L, "`setfenv' cannot change a protected environment");
154 else
155 lua_pop(L, 2); /* remove __fenv and real environment table */
156 lua_pushvalue(L, 2);
157 if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0)
158 lua_replace(L, LUA_GLOBALSINDEX);
159 else if (lua_setfenv(L, -2) == 0)
160 luaL_error(L, "`setfenv' cannot change environment of given function");
161 return 0;
165 static int luaB_rawequal (lua_State *L) {
166 luaL_checkany(L, 1);
167 luaL_checkany(L, 2);
168 lua_pushboolean(L, lua_rawequal(L, 1, 2));
169 return 1;
173 static int luaB_rawget (lua_State *L) {
174 luaL_checktype(L, 1, LUA_TTABLE);
175 luaL_checkany(L, 2);
176 lua_settop(L, 2);
177 lua_rawget(L, 1);
178 return 1;
181 static int luaB_rawset (lua_State *L) {
182 luaL_checktype(L, 1, LUA_TTABLE);
183 luaL_checkany(L, 2);
184 luaL_checkany(L, 3);
185 lua_settop(L, 3);
186 lua_rawset(L, 1);
187 return 1;
191 static int luaB_gcinfo (lua_State *L) {
192 lua_pushnumber(L, (lua_Number)lua_getgccount(L));
193 lua_pushnumber(L, (lua_Number)lua_getgcthreshold(L));
194 return 2;
198 static int luaB_collectgarbage (lua_State *L) {
199 lua_setgcthreshold(L, luaL_optint(L, 1, 0));
200 return 0;
204 static int luaB_type (lua_State *L) {
205 luaL_checkany(L, 1);
206 lua_pushstring(L, lua_typename(L, lua_type(L, 1)));
207 return 1;
211 static int luaB_next (lua_State *L) {
212 luaL_checktype(L, 1, LUA_TTABLE);
213 lua_settop(L, 2); /* create a 2nd argument if there isn't one */
214 if (lua_next(L, 1))
215 return 2;
216 else {
217 lua_pushnil(L);
218 return 1;
223 static int luaB_pairs (lua_State *L) {
224 luaL_checktype(L, 1, LUA_TTABLE);
225 lua_pushliteral(L, "next");
226 lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */
227 lua_pushvalue(L, 1); /* state, */
228 lua_pushnil(L); /* and initial value */
229 return 3;
233 static int luaB_ipairs (lua_State *L) {
234 lua_Number i = lua_tonumber(L, 2);
235 luaL_checktype(L, 1, LUA_TTABLE);
236 if (i == 0 && lua_isnone(L, 2)) { /* `for' start? */
237 lua_pushliteral(L, "ipairs");
238 lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */
239 lua_pushvalue(L, 1); /* state, */
240 lua_pushnumber(L, 0); /* and initial value */
241 return 3;
243 else { /* `for' step */
244 i++; /* next value */
245 lua_pushnumber(L, i);
246 lua_rawgeti(L, 1, (int)i);
247 return (lua_isnil(L, -1)) ? 0 : 2;
252 static int load_aux (lua_State *L, int status) {
253 if (status == 0) /* OK? */
254 return 1;
255 else {
256 lua_pushnil(L);
257 lua_insert(L, -2); /* put before error message */
258 return 2; /* return nil plus error message */
263 static int luaB_loadstring (lua_State *L) {
264 size_t l;
265 const char *s = luaL_checklstring(L, 1, &l);
266 const char *chunkname = luaL_optstring(L, 2, s);
267 return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
271 static int luaB_loadfile (lua_State *L) {
272 const char *fname = luaL_optstring(L, 1, NULL);
273 return load_aux(L, luaL_loadfile(L, fname));
277 static int luaB_dofile (lua_State *L) {
278 const char *fname = luaL_optstring(L, 1, NULL);
279 int n = lua_gettop(L);
280 int status = luaL_loadfile(L, fname);
281 if (status != 0) lua_error(L);
282 lua_call(L, 0, LUA_MULTRET);
283 return lua_gettop(L) - n;
287 static int luaB_assert (lua_State *L) {
288 luaL_checkany(L, 1);
289 if (!lua_toboolean(L, 1))
290 return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
291 lua_settop(L, 1);
292 return 1;
296 static int luaB_unpack (lua_State *L) {
297 int n, i;
298 luaL_checktype(L, 1, LUA_TTABLE);
299 n = luaL_getn(L, 1);
300 luaL_checkstack(L, n, "table too big to unpack");
301 for (i=1; i<=n; i++) /* push arg[1...n] */
302 lua_rawgeti(L, 1, i);
303 return n;
307 static int luaB_pcall (lua_State *L) {
308 int status;
309 luaL_checkany(L, 1);
310 status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
311 lua_pushboolean(L, (status == 0));
312 lua_insert(L, 1);
313 return lua_gettop(L); /* return status + all results */
317 static int luaB_xpcall (lua_State *L) {
318 int status;
319 luaL_checkany(L, 2);
320 lua_settop(L, 2);
321 lua_insert(L, 1); /* put error function under function to be called */
322 status = lua_pcall(L, 0, LUA_MULTRET, 1);
323 lua_pushboolean(L, (status == 0));
324 lua_replace(L, 1);
325 return lua_gettop(L); /* return status + all results */
329 static int luaB_tostring (lua_State *L) {
330 char buff[128];
331 luaL_checkany(L, 1);
332 if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */
333 return 1; /* use its value */
334 switch (lua_type(L, 1)) {
335 case LUA_TNUMBER:
336 lua_pushstring(L, lua_tostring(L, 1));
337 return 1;
338 case LUA_TSTRING:
339 lua_pushvalue(L, 1);
340 return 1;
341 case LUA_TBOOLEAN:
342 lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
343 return 1;
344 case LUA_TTABLE:
345 sprintf(buff, "table: %p", lua_topointer(L, 1));
346 break;
347 case LUA_TFUNCTION:
348 sprintf(buff, "function: %p", lua_topointer(L, 1));
349 break;
350 case LUA_TUSERDATA:
351 case LUA_TLIGHTUSERDATA:
352 sprintf(buff, "userdata: %p", lua_touserdata(L, 1));
353 break;
354 case LUA_TTHREAD:
355 sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1));
356 break;
357 case LUA_TNIL:
358 lua_pushliteral(L, "nil");
359 return 1;
361 lua_pushstring(L, buff);
362 return 1;
366 static int luaB_newproxy (lua_State *L) {
367 lua_settop(L, 1);
368 lua_newuserdata(L, 0); /* create proxy */
369 if (lua_toboolean(L, 1) == 0)
370 return 1; /* no metatable */
371 else if (lua_isboolean(L, 1)) {
372 lua_newtable(L); /* create a new metatable `m' ... */
373 lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */
374 lua_pushboolean(L, 1);
375 lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */
377 else {
378 int validproxy = 0; /* to check if weaktable[metatable(u)] == true */
379 if (lua_getmetatable(L, 1)) {
380 lua_rawget(L, lua_upvalueindex(1));
381 validproxy = lua_toboolean(L, -1);
382 lua_pop(L, 1); /* remove value */
384 luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
385 lua_getmetatable(L, 1); /* metatable is valid; get it */
387 lua_setmetatable(L, 2);
388 return 1;
393 ** {======================================================
394 ** `require' function
395 ** =======================================================
399 /* name of global that holds table with loaded packages */
400 #define REQTAB "_LOADED"
402 /* name of global that holds the search path for packages */
403 #define LUA_PATH "LUA_PATH"
405 #ifndef LUA_PATH_SEP
406 #define LUA_PATH_SEP ';'
407 #endif
409 #ifndef LUA_PATH_MARK
410 #define LUA_PATH_MARK '?'
411 #endif
413 #ifndef LUA_PATH_DEFAULT
414 #define LUA_PATH_DEFAULT "?;?.lua"
415 #endif
418 static const char *getpath (lua_State *L) {
419 const char *path;
420 lua_getglobal(L, LUA_PATH); /* try global variable */
421 path = lua_tostring(L, -1);
422 lua_pop(L, 1);
423 if (path) return path;
424 path = getenv(LUA_PATH); /* else try environment variable */
425 if (path) return path;
426 return LUA_PATH_DEFAULT; /* else use default */
430 static const char *pushnextpath (lua_State *L, const char *path) {
431 const char *l;
432 if (*path == '\0') return NULL; /* no more paths */
433 if (*path == LUA_PATH_SEP) path++; /* skip separator */
434 l = strchr(path, LUA_PATH_SEP); /* find next separator */
435 if (l == NULL) l = path+strlen(path);
436 lua_pushlstring(L, path, l - path); /* directory name */
437 return l;
441 static void pushcomposename (lua_State *L) {
442 const char *path = lua_tostring(L, -1);
443 const char *wild;
444 int n = 1;
445 while ((wild = strchr(path, LUA_PATH_MARK)) != NULL) {
446 /* is there stack space for prefix, name, and eventual last sufix? */
447 luaL_checkstack(L, 3, "too many marks in a path component");
448 lua_pushlstring(L, path, wild - path); /* push prefix */
449 lua_pushvalue(L, 1); /* push package name (in place of MARK) */
450 path = wild + 1; /* continue after MARK */
451 n += 2;
453 lua_pushstring(L, path); /* push last sufix (`n' already includes this) */
454 lua_concat(L, n);
458 static int luaB_require (lua_State *L) {
459 const char *path;
460 int status = LUA_ERRFILE; /* not found (yet) */
461 luaL_checkstring(L, 1);
462 lua_settop(L, 1);
463 lua_getglobal(L, REQTAB);
464 if (!lua_istable(L, 2)) return luaL_error(L, "`" REQTAB "' is not a table");
465 path = getpath(L);
466 lua_pushvalue(L, 1); /* check package's name in book-keeping table */
467 lua_rawget(L, 2);
468 if (lua_toboolean(L, -1)) /* is it there? */
469 return 1; /* package is already loaded; return its result */
470 else { /* must load it */
471 while (status == LUA_ERRFILE) {
472 lua_settop(L, 3); /* reset stack position */
473 if ((path = pushnextpath(L, path)) == NULL) break;
474 pushcomposename(L);
475 status = luaL_loadfile(L, lua_tostring(L, -1)); /* try to load it */
478 switch (status) {
479 case 0: {
480 lua_getglobal(L, "_REQUIREDNAME"); /* save previous name */
481 lua_insert(L, -2); /* put it below function */
482 lua_pushvalue(L, 1);
483 lua_setglobal(L, "_REQUIREDNAME"); /* set new name */
484 lua_call(L, 0, 1); /* run loaded module */
485 lua_insert(L, -2); /* put result below previous name */
486 lua_setglobal(L, "_REQUIREDNAME"); /* reset to previous name */
487 if (lua_isnil(L, -1)) { /* no/nil return? */
488 lua_pushboolean(L, 1);
489 lua_replace(L, -2); /* replace to true */
491 lua_pushvalue(L, 1);
492 lua_pushvalue(L, -2);
493 lua_rawset(L, 2); /* mark it as loaded */
494 return 1; /* return value */
496 case LUA_ERRFILE: { /* file not found */
497 return luaL_error(L, "could not load package `%s' from path `%s'",
498 lua_tostring(L, 1), getpath(L));
500 default: {
501 return luaL_error(L, "error loading package `%s' (%s)",
502 lua_tostring(L, 1), lua_tostring(L, -1));
507 /* }====================================================== */
510 static const luaL_reg base_funcs[] = {
511 {"error", luaB_error},
512 {"getmetatable", luaB_getmetatable},
513 {"setmetatable", luaB_setmetatable},
514 {"getfenv", luaB_getfenv},
515 {"setfenv", luaB_setfenv},
516 {"next", luaB_next},
517 {"ipairs", luaB_ipairs},
518 {"pairs", luaB_pairs},
519 {"print", luaB_print},
520 {"tonumber", luaB_tonumber},
521 {"tostring", luaB_tostring},
522 {"type", luaB_type},
523 {"assert", luaB_assert},
524 {"unpack", luaB_unpack},
525 {"rawequal", luaB_rawequal},
526 {"rawget", luaB_rawget},
527 {"rawset", luaB_rawset},
528 {"pcall", luaB_pcall},
529 {"xpcall", luaB_xpcall},
530 {"collectgarbage", luaB_collectgarbage},
531 {"gcinfo", luaB_gcinfo},
532 {"loadfile", luaB_loadfile},
533 {"dofile", luaB_dofile},
534 {"loadstring", luaB_loadstring},
535 {"require", luaB_require},
536 {NULL, NULL}
541 ** {======================================================
542 ** Coroutine library
543 ** =======================================================
546 static int auxresume (lua_State *L, lua_State *co, int narg) {
547 int status;
548 if (!lua_checkstack(co, narg))
549 luaL_error(L, "too many arguments to resume");
550 lua_xmove(L, co, narg);
551 status = lua_resume(co, narg);
552 if (status == 0) {
553 int nres = lua_gettop(co);
554 if (!lua_checkstack(L, nres))
555 luaL_error(L, "too many results to resume");
556 lua_xmove(co, L, nres); /* move yielded values */
557 return nres;
559 else {
560 lua_xmove(co, L, 1); /* move error message */
561 return -1; /* error flag */
566 static int luaB_coresume (lua_State *L) {
567 lua_State *co = lua_tothread(L, 1);
568 int r;
569 luaL_argcheck(L, co, 1, "coroutine expected");
570 r = auxresume(L, co, lua_gettop(L) - 1);
571 if (r < 0) {
572 lua_pushboolean(L, 0);
573 lua_insert(L, -2);
574 return 2; /* return false + error message */
576 else {
577 lua_pushboolean(L, 1);
578 lua_insert(L, -(r + 1));
579 return r + 1; /* return true + `resume' returns */
584 static int luaB_auxwrap (lua_State *L) {
585 lua_State *co = lua_tothread(L, lua_upvalueindex(1));
586 int r = auxresume(L, co, lua_gettop(L));
587 if (r < 0) {
588 if (lua_isstring(L, -1)) { /* error object is a string? */
589 luaL_where(L, 1); /* add extra info */
590 lua_insert(L, -2);
591 lua_concat(L, 2);
593 lua_error(L); /* propagate error */
595 return r;
599 static int luaB_cocreate (lua_State *L) {
600 lua_State *NL = lua_newthread(L);
601 luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
602 "Lua function expected");
603 lua_pushvalue(L, 1); /* move function to top */
604 lua_xmove(L, NL, 1); /* move function from L to NL */
605 return 1;
609 static int luaB_cowrap (lua_State *L) {
610 luaB_cocreate(L);
611 lua_pushcclosure(L, luaB_auxwrap, 1);
612 return 1;
616 static int luaB_yield (lua_State *L) {
617 return lua_yield(L, lua_gettop(L));
621 static int luaB_costatus (lua_State *L) {
622 lua_State *co = lua_tothread(L, 1);
623 luaL_argcheck(L, co, 1, "coroutine expected");
624 if (L == co) lua_pushliteral(L, "running");
625 else {
626 lua_Debug ar;
627 if (lua_getstack(co, 0, &ar) == 0 && lua_gettop(co) == 0)
628 lua_pushliteral(L, "dead");
629 else
630 lua_pushliteral(L, "suspended");
632 return 1;
636 static const luaL_reg co_funcs[] = {
637 {"create", luaB_cocreate},
638 {"wrap", luaB_cowrap},
639 {"resume", luaB_coresume},
640 {"yield", luaB_yield},
641 {"status", luaB_costatus},
642 {NULL, NULL}
645 /* }====================================================== */
649 static void base_open (lua_State *L) {
650 lua_pushliteral(L, "_G");
651 lua_pushvalue(L, LUA_GLOBALSINDEX);
652 luaL_openlib(L, NULL, base_funcs, 0); /* open lib into global table */
653 lua_pushliteral(L, "_VERSION");
654 lua_pushliteral(L, LUA_VERSION);
655 lua_rawset(L, -3); /* set global _VERSION */
656 /* `newproxy' needs a weaktable as upvalue */
657 lua_pushliteral(L, "newproxy");
658 lua_newtable(L); /* new table `w' */
659 lua_pushvalue(L, -1); /* `w' will be its own metatable */
660 lua_setmetatable(L, -2);
661 lua_pushliteral(L, "__mode");
662 lua_pushliteral(L, "k");
663 lua_rawset(L, -3); /* metatable(w).__mode = "k" */
664 lua_pushcclosure(L, luaB_newproxy, 1);
665 lua_rawset(L, -3); /* set global `newproxy' */
666 lua_rawset(L, -1); /* set global _G */
670 LUALIB_API int luaopen_base (lua_State *L) {
671 base_open(L);
672 luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0);
673 lua_newtable(L);
674 lua_setglobal(L, REQTAB);
675 return 0;