Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ceguilua/src/lua-5.0.3/lua/lbaselib.c @ 1808

Last change on this file since 1808 was 1803, checked in by rgrieder, 16 years ago

added files for lua 5.1.3, lua 5.0.3, CEGUILua-0.6.1 and CEGUILua-0.5.0b

  • Property svn:eol-style set to native
File size: 17.5 KB
Line 
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*/
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
16#include "lua.h"
17
18#include "lauxlib.h"
19#include "lualib.h"
20
21
22
23
24/*
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).
29*/
30static 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 */
45  }
46  fputs("\n", stdout);
47  return 0;
48}
49
50
51static 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;
58    }
59  }
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;
71      }
72    }
73  }
74  lua_pushnil(L);  /* else not a number */
75  return 1;
76}
77
78
79static 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);
88  }
89  return lua_error(L);
90}
91
92
93static 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
104static 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
117static 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
133static 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);
138}
139
140
141static 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;
146}
147
148
149static 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;
162}
163
164
165static 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;
170}
171
172
173static 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;
179}
180
181static 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;
188}
189
190
191static 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;
195}
196
197
198static int luaB_collectgarbage (lua_State *L) {
199  lua_setgcthreshold(L, luaL_optint(L, 1, 0));
200  return 0;
201}
202
203
204static 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;
208}
209
210
211static 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;
219  }
220}
221
222
223static 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;
230}
231
232
233static 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;
242  }
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;
248  }
249}
250
251
252static 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 */
259  }
260}
261
262
263static 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));
268}
269
270
271static int luaB_loadfile (lua_State *L) {
272  const char *fname = luaL_optstring(L, 1, NULL);
273  return load_aux(L, luaL_loadfile(L, fname));
274}
275
276
277static 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;
284}
285
286
287static 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;
293}
294
295
296static 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;
304}
305
306
307static 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 */
314}
315
316
317static 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 */
326}
327
328
329static 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;
360  }
361  lua_pushstring(L, buff);
362  return 1;
363}
364
365
366static 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 */
376  }
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 */
383    }
384    luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
385    lua_getmetatable(L, 1);  /* metatable is valid; get it */
386  }
387  lua_setmetatable(L, 2);
388  return 1;
389}
390
391
392/*
393** {======================================================
394** `require' function
395** =======================================================
396*/
397
398
399/* name of global that holds table with loaded packages */
400#define REQTAB          "_LOADED"
401
402/* name of global that holds the search path for packages */
403#define LUA_PATH        "LUA_PATH"
404
405#ifndef LUA_PATH_SEP
406#define LUA_PATH_SEP    ';'
407#endif
408
409#ifndef LUA_PATH_MARK
410#define LUA_PATH_MARK   '?'
411#endif
412
413#ifndef LUA_PATH_DEFAULT
414#define LUA_PATH_DEFAULT        "?;?.lua"
415#endif
416
417
418static 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 */
427}
428
429
430static 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;
438}
439
440
441static 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;
452  }
453  lua_pushstring(L, path);  /* push last sufix (`n' already includes this) */
454  lua_concat(L, n);
455}
456
457
458static 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 */
476    }
477  }
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 */
490      }
491      lua_pushvalue(L, 1);
492      lua_pushvalue(L, -2);
493      lua_rawset(L, 2);  /* mark it as loaded */
494      return 1;  /* return value */
495    }
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));
499    }
500    default: {
501      return luaL_error(L, "error loading package `%s' (%s)",
502                           lua_tostring(L, 1), lua_tostring(L, -1));
503    }
504  }
505}
506
507/* }====================================================== */
508
509
510static 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}
537};
538
539
540/*
541** {======================================================
542** Coroutine library
543** =======================================================
544*/
545
546static 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;
558  }
559  else {
560    lua_xmove(co, L, 1);  /* move error message */
561    return -1;  /* error flag */
562  }
563}
564
565
566static 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 */
575  }
576  else {
577    lua_pushboolean(L, 1);
578    lua_insert(L, -(r + 1));
579    return r + 1;  /* return true + `resume' returns */
580  }
581}
582
583
584static 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);
592    }
593    lua_error(L);  /* propagate error */
594  }
595  return r;
596}
597
598
599static 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;
606}
607
608
609static int luaB_cowrap (lua_State *L) {
610  luaB_cocreate(L);
611  lua_pushcclosure(L, luaB_auxwrap, 1);
612  return 1;
613}
614
615
616static int luaB_yield (lua_State *L) {
617  return lua_yield(L, lua_gettop(L));
618}
619
620
621static 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");
631  }
632  return 1;
633}
634
635
636static 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}
643};
644
645/* }====================================================== */
646
647
648
649static 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 */
667}
668
669
670LUALIB_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;
676}
677
Note: See TracBrowser for help on using the repository browser.