source: trunk/src/lua/lbaselib.c @ 2540

Last change on this file since 2540 was 2540, checked in by sam, 10 years ago

core: import pristine lua 5.2.1 in the engine code.

File size: 11.9 KB
Line 
1/*
2** $Id: lbaselib.c,v 1.274 2012/04/27 14:13:19 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
23static int luaB_print (lua_State *L) {
24  int n = lua_gettop(L);  /* number of arguments */
25  int i;
26  lua_getglobal(L, "tostring");
27  for (i=1; i<=n; i++) {
28    const char *s;
29    size_t l;
30    lua_pushvalue(L, -1);  /* function to be called */
31    lua_pushvalue(L, i);   /* value to print */
32    lua_call(L, 1, 1);
33    s = lua_tolstring(L, -1, &l);  /* get result */
34    if (s == NULL)
35      return luaL_error(L,
36         LUA_QL("tostring") " must return a string to " LUA_QL("print"));
37    if (i>1) luai_writestring("\t", 1);
38    luai_writestring(s, l);
39    lua_pop(L, 1);  /* pop result */
40  }
41  luai_writeline();
42  return 0;
43}
44
45
46#define SPACECHARS      " \f\n\r\t\v"
47
48static int luaB_tonumber (lua_State *L) {
49  if (lua_isnoneornil(L, 2)) {  /* standard conversion */
50    int isnum;
51    lua_Number n = lua_tonumberx(L, 1, &isnum);
52    if (isnum) {
53      lua_pushnumber(L, n);
54      return 1;
55    }  /* else not a number; must be something */
56    luaL_checkany(L, 1);
57  }
58  else {
59    size_t l;
60    const char *s = luaL_checklstring(L, 1, &l);
61    const char *e = s + l;  /* end point for 's' */
62    int base = luaL_checkint(L, 2);
63    int neg = 0;
64    luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
65    s += strspn(s, SPACECHARS);  /* skip initial spaces */
66    if (*s == '-') { s++; neg = 1; }  /* handle signal */
67    else if (*s == '+') s++;
68    if (isalnum((unsigned char)*s)) {
69      lua_Number n = 0;
70      do {
71        int digit = (isdigit((unsigned char)*s)) ? *s - '0'
72                       : toupper((unsigned char)*s) - 'A' + 10;
73        if (digit >= base) break;  /* invalid numeral; force a fail */
74        n = n * (lua_Number)base + (lua_Number)digit;
75        s++;
76      } while (isalnum((unsigned char)*s));
77      s += strspn(s, SPACECHARS);  /* skip trailing spaces */
78      if (s == e) {  /* no invalid trailing characters? */
79        lua_pushnumber(L, (neg) ? -n : n);
80        return 1;
81      }  /* else not a number */
82    }  /* else not a number */
83  }
84  lua_pushnil(L);  /* not a number */
85  return 1;
86}
87
88
89static int luaB_error (lua_State *L) {
90  int level = luaL_optint(L, 2, 1);
91  lua_settop(L, 1);
92  if (lua_isstring(L, 1) && level > 0) {  /* add extra information? */
93    luaL_where(L, level);
94    lua_pushvalue(L, 1);
95    lua_concat(L, 2);
96  }
97  return lua_error(L);
98}
99
100
101static int luaB_getmetatable (lua_State *L) {
102  luaL_checkany(L, 1);
103  if (!lua_getmetatable(L, 1)) {
104    lua_pushnil(L);
105    return 1;  /* no metatable */
106  }
107  luaL_getmetafield(L, 1, "__metatable");
108  return 1;  /* returns either __metatable field (if present) or metatable */
109}
110
111
112static int luaB_setmetatable (lua_State *L) {
113  int t = lua_type(L, 2);
114  luaL_checktype(L, 1, LUA_TTABLE);
115  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
116                    "nil or table expected");
117  if (luaL_getmetafield(L, 1, "__metatable"))
118    return luaL_error(L, "cannot change a protected metatable");
119  lua_settop(L, 2);
120  lua_setmetatable(L, 1);
121  return 1;
122}
123
124
125static int luaB_rawequal (lua_State *L) {
126  luaL_checkany(L, 1);
127  luaL_checkany(L, 2);
128  lua_pushboolean(L, lua_rawequal(L, 1, 2));
129  return 1;
130}
131
132
133static int luaB_rawlen (lua_State *L) {
134  int t = lua_type(L, 1);
135  luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
136                   "table or string expected");
137  lua_pushinteger(L, lua_rawlen(L, 1));
138  return 1;
139}
140
141
142static int luaB_rawget (lua_State *L) {
143  luaL_checktype(L, 1, LUA_TTABLE);
144  luaL_checkany(L, 2);
145  lua_settop(L, 2);
146  lua_rawget(L, 1);
147  return 1;
148}
149
150static int luaB_rawset (lua_State *L) {
151  luaL_checktype(L, 1, LUA_TTABLE);
152  luaL_checkany(L, 2);
153  luaL_checkany(L, 3);
154  lua_settop(L, 3);
155  lua_rawset(L, 1);
156  return 1;
157}
158
159
160static int luaB_collectgarbage (lua_State *L) {
161  static const char *const opts[] = {"stop", "restart", "collect",
162    "count", "step", "setpause", "setstepmul",
163    "setmajorinc", "isrunning", "generational", "incremental", NULL};
164  static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
165    LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
166    LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC};
167  int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
168  int ex = luaL_optint(L, 2, 0);
169  int res = lua_gc(L, o, ex);
170  switch (o) {
171    case LUA_GCCOUNT: {
172      int b = lua_gc(L, LUA_GCCOUNTB, 0);
173      lua_pushnumber(L, res + ((lua_Number)b/1024));
174      lua_pushinteger(L, b);
175      return 2;
176    }
177    case LUA_GCSTEP: case LUA_GCISRUNNING: {
178      lua_pushboolean(L, res);
179      return 1;
180    }
181    default: {
182      lua_pushinteger(L, res);
183      return 1;
184    }
185  }
186}
187
188
189static int luaB_type (lua_State *L) {
190  luaL_checkany(L, 1);
191  lua_pushstring(L, luaL_typename(L, 1));
192  return 1;
193}
194
195
196static int pairsmeta (lua_State *L, const char *method, int iszero,
197                      lua_CFunction iter) {
198  if (!luaL_getmetafield(L, 1, method)) {  /* no metamethod? */
199    luaL_checktype(L, 1, LUA_TTABLE);  /* argument must be a table */
200    lua_pushcfunction(L, iter);  /* will return generator, */
201    lua_pushvalue(L, 1);  /* state, */
202    if (iszero) lua_pushinteger(L, 0);  /* and initial value */
203    else lua_pushnil(L);
204  }
205  else {
206    lua_pushvalue(L, 1);  /* argument 'self' to metamethod */
207    lua_call(L, 1, 3);  /* get 3 values from metamethod */
208  }
209  return 3;
210}
211
212
213static int luaB_next (lua_State *L) {
214  luaL_checktype(L, 1, LUA_TTABLE);
215  lua_settop(L, 2);  /* create a 2nd argument if there isn't one */
216  if (lua_next(L, 1))
217    return 2;
218  else {
219    lua_pushnil(L);
220    return 1;
221  }
222}
223
224
225static int luaB_pairs (lua_State *L) {
226  return pairsmeta(L, "__pairs", 0, luaB_next);
227}
228
229
230static int ipairsaux (lua_State *L) {
231  int i = luaL_checkint(L, 2);
232  luaL_checktype(L, 1, LUA_TTABLE);
233  i++;  /* next value */
234  lua_pushinteger(L, i);
235  lua_rawgeti(L, 1, i);
236  return (lua_isnil(L, -1)) ? 1 : 2;
237}
238
239
240static int luaB_ipairs (lua_State *L) {
241  return pairsmeta(L, "__ipairs", 1, ipairsaux);
242}
243
244
245static int load_aux (lua_State *L, int status) {
246  if (status == LUA_OK)
247    return 1;
248  else {
249    lua_pushnil(L);
250    lua_insert(L, -2);  /* put before error message */
251    return 2;  /* return nil plus error message */
252  }
253}
254
255
256static int luaB_loadfile (lua_State *L) {
257  const char *fname = luaL_optstring(L, 1, NULL);
258  const char *mode = luaL_optstring(L, 2, NULL);
259  int env = !lua_isnone(L, 3);  /* 'env' parameter? */
260  int status = luaL_loadfilex(L, fname, mode);
261  if (status == LUA_OK && env) {  /* 'env' parameter? */
262    lua_pushvalue(L, 3);
263    lua_setupvalue(L, -2, 1);  /* set it as 1st upvalue of loaded chunk */
264  }
265  return load_aux(L, status);
266}
267
268
269/*
270** {======================================================
271** Generic Read function
272** =======================================================
273*/
274
275
276/*
277** reserved slot, above all arguments, to hold a copy of the returned
278** string to avoid it being collected while parsed. 'load' has four
279** optional arguments (chunk, source name, mode, and environment).
280*/
281#define RESERVEDSLOT    5
282
283
284/*
285** Reader for generic `load' function: `lua_load' uses the
286** stack for internal stuff, so the reader cannot change the
287** stack top. Instead, it keeps its resulting string in a
288** reserved slot inside the stack.
289*/
290static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
291  (void)(ud);  /* not used */
292  luaL_checkstack(L, 2, "too many nested functions");
293  lua_pushvalue(L, 1);  /* get function */
294  lua_call(L, 0, 1);  /* call it */
295  if (lua_isnil(L, -1)) {
296    lua_pop(L, 1);  /* pop result */
297    *size = 0;
298    return NULL;
299  }
300  else if (!lua_isstring(L, -1))
301    luaL_error(L, "reader function must return a string");
302  lua_replace(L, RESERVEDSLOT);  /* save string in reserved slot */
303  return lua_tolstring(L, RESERVEDSLOT, size);
304}
305
306
307static int luaB_load (lua_State *L) {
308  int status;
309  size_t l;
310  int top = lua_gettop(L);
311  const char *s = lua_tolstring(L, 1, &l);
312  const char *mode = luaL_optstring(L, 3, "bt");
313  if (s != NULL) {  /* loading a string? */
314    const char *chunkname = luaL_optstring(L, 2, s);
315    status = luaL_loadbufferx(L, s, l, chunkname, mode);
316  }
317  else {  /* loading from a reader function */
318    const char *chunkname = luaL_optstring(L, 2, "=(load)");
319    luaL_checktype(L, 1, LUA_TFUNCTION);
320    lua_settop(L, RESERVEDSLOT);  /* create reserved slot */
321    status = lua_load(L, generic_reader, NULL, chunkname, mode);
322  }
323  if (status == LUA_OK && top >= 4) {  /* is there an 'env' argument */
324    lua_pushvalue(L, 4);  /* environment for loaded function */
325    lua_setupvalue(L, -2, 1);  /* set it as 1st upvalue */
326  }
327  return load_aux(L, status);
328}
329
330/* }====================================================== */
331
332
333static int dofilecont (lua_State *L) {
334  return lua_gettop(L) - 1;
335}
336
337
338static int luaB_dofile (lua_State *L) {
339  const char *fname = luaL_optstring(L, 1, NULL);
340  lua_settop(L, 1);
341  if (luaL_loadfile(L, fname) != LUA_OK) lua_error(L);
342  lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
343  return dofilecont(L);
344}
345
346
347static int luaB_assert (lua_State *L) {
348  if (!lua_toboolean(L, 1))
349    return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
350  return lua_gettop(L);
351}
352
353
354static int luaB_select (lua_State *L) {
355  int n = lua_gettop(L);
356  if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
357    lua_pushinteger(L, n-1);
358    return 1;
359  }
360  else {
361    int i = luaL_checkint(L, 1);
362    if (i < 0) i = n + i;
363    else if (i > n) i = n;
364    luaL_argcheck(L, 1 <= i, 1, "index out of range");
365    return n - i;
366  }
367}
368
369
370static int finishpcall (lua_State *L, int status) {
371  if (!lua_checkstack(L, 1)) {  /* no space for extra boolean? */
372    lua_settop(L, 0);  /* create space for return values */
373    lua_pushboolean(L, 0);
374    lua_pushstring(L, "stack overflow");
375    return 2;  /* return false, msg */
376  }
377  lua_pushboolean(L, status);  /* first result (status) */
378  lua_replace(L, 1);  /* put first result in first slot */
379  return lua_gettop(L);
380}
381
382
383static int pcallcont (lua_State *L) {
384  int status = lua_getctx(L, NULL);
385  return finishpcall(L, (status == LUA_YIELD));
386}
387
388
389static int luaB_pcall (lua_State *L) {
390  int status;
391  luaL_checkany(L, 1);
392  lua_pushnil(L);
393  lua_insert(L, 1);  /* create space for status result */
394  status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont);
395  return finishpcall(L, (status == LUA_OK));
396}
397
398
399static int luaB_xpcall (lua_State *L) {
400  int status;
401  int n = lua_gettop(L);
402  luaL_argcheck(L, n >= 2, 2, "value expected");
403  lua_pushvalue(L, 1);  /* exchange function... */
404  lua_copy(L, 2, 1);  /* ...and error handler */
405  lua_replace(L, 2);
406  status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont);
407  return finishpcall(L, (status == LUA_OK));
408}
409
410
411static int luaB_tostring (lua_State *L) {
412  luaL_checkany(L, 1);
413  luaL_tolstring(L, 1, NULL);
414  return 1;
415}
416
417
418static const luaL_Reg base_funcs[] = {
419  {"assert", luaB_assert},
420  {"collectgarbage", luaB_collectgarbage},
421  {"dofile", luaB_dofile},
422  {"error", luaB_error},
423  {"getmetatable", luaB_getmetatable},
424  {"ipairs", luaB_ipairs},
425  {"loadfile", luaB_loadfile},
426  {"load", luaB_load},
427#if defined(LUA_COMPAT_LOADSTRING)
428  {"loadstring", luaB_load},
429#endif
430  {"next", luaB_next},
431  {"pairs", luaB_pairs},
432  {"pcall", luaB_pcall},
433  {"print", luaB_print},
434  {"rawequal", luaB_rawequal},
435  {"rawlen", luaB_rawlen},
436  {"rawget", luaB_rawget},
437  {"rawset", luaB_rawset},
438  {"select", luaB_select},
439  {"setmetatable", luaB_setmetatable},
440  {"tonumber", luaB_tonumber},
441  {"tostring", luaB_tostring},
442  {"type", luaB_type},
443  {"xpcall", luaB_xpcall},
444  {NULL, NULL}
445};
446
447
448LUAMOD_API int luaopen_base (lua_State *L) {
449  /* set global _G */
450  lua_pushglobaltable(L);
451  lua_pushglobaltable(L);
452  lua_setfield(L, -2, "_G");
453  /* open lib into global table */
454  luaL_setfuncs(L, base_funcs, 0);
455  lua_pushliteral(L, LUA_VERSION);
456  lua_setfield(L, -2, "_VERSION");  /* set global _VERSION */
457  return 1;
458}
459
Note: See TracBrowser for help on using the repository browser.