Line data Source code
1 : /*
2 : ** $Id: lbaselib.c,v 1.314.1.1 2017/04/19 17:39:34 roberto Exp $
3 : ** Basic library
4 : ** See Copyright Notice in lua.h
5 : */
6 :
7 : #define lbaselib_c
8 : #define LUA_LIB
9 :
10 : #include "lprefix.h"
11 :
12 :
13 : #include <ctype.h>
14 : #include <stdio.h>
15 : #include <stdlib.h>
16 : #include <string.h>
17 :
18 : #include "lua.h"
19 :
20 : #include "lauxlib.h"
21 : #include "lualib.h"
22 :
23 :
24 2204 : static int luaB_print (lua_State *L) {
25 2204 : int n = lua_gettop(L); /* number of arguments */
26 : int i;
27 2204 : lua_getglobal(L, "tostring");
28 4411 : for (i=1; i<=n; i++) {
29 : const char *s;
30 : size_t l;
31 2208 : lua_pushvalue(L, -1); /* function to be called */
32 2208 : lua_pushvalue(L, i); /* value to print */
33 2208 : lua_call(L, 1, 1);
34 2207 : s = lua_tolstring(L, -1, &l); /* get result */
35 2207 : if (s == NULL)
36 0 : return luaL_error(L, "'tostring' must return a string to 'print'");
37 2207 : if (i>1) lua_writestring("\t", 1);
38 2207 : lua_writestring(s, l);
39 2207 : lua_pop(L, 1); /* pop result */
40 : }
41 2203 : lua_writeline();
42 2203 : return 0;
43 : }
44 :
45 :
46 : #define SPACECHARS " \f\n\r\t\v"
47 :
48 3 : static const char *b_str2int (const char *s, int base, lua_Integer *pn) {
49 3 : lua_Unsigned n = 0;
50 3 : int neg = 0;
51 3 : s += strspn(s, SPACECHARS); /* skip initial spaces */
52 3 : if (*s == '-') { s++; neg = 1; } /* handle signal */
53 3 : else if (*s == '+') s++;
54 3 : if (!isalnum((unsigned char)*s)) /* no digit? */
55 0 : return NULL;
56 : do {
57 27 : int digit = (isdigit((unsigned char)*s)) ? *s - '0'
58 9 : : (toupper((unsigned char)*s) - 'A') + 10;
59 9 : if (digit >= base) return NULL; /* invalid numeral */
60 9 : n = n * base + digit;
61 9 : s++;
62 9 : } while (isalnum((unsigned char)*s));
63 3 : s += strspn(s, SPACECHARS); /* skip trailing spaces */
64 3 : *pn = (lua_Integer)((neg) ? (0u - n) : n);
65 3 : return s;
66 : }
67 :
68 :
69 123 : static int luaB_tonumber (lua_State *L) {
70 123 : if (lua_isnoneornil(L, 2)) { /* standard conversion? */
71 119 : luaL_checkany(L, 1);
72 118 : if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */
73 103 : lua_settop(L, 1); /* yes; return it */
74 103 : return 1;
75 : }
76 : else {
77 : size_t l;
78 15 : const char *s = lua_tolstring(L, 1, &l);
79 15 : if (s != NULL && lua_stringtonumber(L, s) == l + 1)
80 12 : return 1; /* successful conversion to number */
81 : /* else not a number */
82 : }
83 : }
84 : else {
85 : size_t l;
86 : const char *s;
87 4 : lua_Integer n = 0; /* to avoid warnings */
88 4 : lua_Integer base = luaL_checkinteger(L, 2);
89 4 : luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */
90 4 : s = lua_tolstring(L, 1, &l);
91 4 : luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
92 3 : if (b_str2int(s, (int)base, &n) == s + l) {
93 3 : lua_pushinteger(L, n);
94 3 : return 1;
95 : } /* else not a number */
96 : } /* else not a number */
97 3 : lua_pushnil(L); /* not a number */
98 3 : return 1;
99 : }
100 :
101 :
102 22 : static int luaB_error (lua_State *L) {
103 22 : int level = (int)luaL_optinteger(L, 2, 1);
104 22 : lua_settop(L, 1);
105 22 : if (lua_type(L, 1) == LUA_TSTRING && level > 0) {
106 14 : luaL_where(L, level); /* add extra information */
107 14 : lua_pushvalue(L, 1);
108 14 : lua_concat(L, 2);
109 : }
110 22 : return lua_error(L);
111 : }
112 :
113 :
114 25 : static int luaB_getmetatable (lua_State *L) {
115 25 : luaL_checkany(L, 1);
116 25 : if (!lua_getmetatable(L, 1)) {
117 12 : lua_pushnil(L);
118 12 : return 1; /* no metatable */
119 : }
120 13 : luaL_getmetafield(L, 1, "__metatable");
121 13 : return 1; /* returns either __metatable field (if present) or metatable */
122 : }
123 :
124 :
125 100 : static int luaB_setmetatable (lua_State *L) {
126 100 : int t = lua_type(L, 2);
127 100 : luaL_checktype(L, 1, LUA_TTABLE);
128 99 : luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
129 : "nil or table expected");
130 97 : if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL)
131 1 : return luaL_error(L, "cannot change a protected metatable");
132 96 : lua_settop(L, 2);
133 96 : lua_setmetatable(L, 1);
134 96 : return 1;
135 : }
136 :
137 :
138 17 : static int luaB_rawequal (lua_State *L) {
139 17 : luaL_checkany(L, 1);
140 17 : luaL_checkany(L, 2);
141 17 : lua_pushboolean(L, lua_rawequal(L, 1, 2));
142 17 : return 1;
143 : }
144 :
145 :
146 3 : static int luaB_rawlen (lua_State *L) {
147 3 : int t = lua_type(L, 1);
148 3 : luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
149 : "table or string expected");
150 2 : lua_pushinteger(L, lua_rawlen(L, 1));
151 2 : return 1;
152 : }
153 :
154 :
155 5 : static int luaB_rawget (lua_State *L) {
156 5 : luaL_checktype(L, 1, LUA_TTABLE);
157 5 : luaL_checkany(L, 2);
158 5 : lua_settop(L, 2);
159 5 : lua_rawget(L, 1);
160 5 : return 1;
161 : }
162 :
163 3 : static int luaB_rawset (lua_State *L) {
164 3 : luaL_checktype(L, 1, LUA_TTABLE);
165 3 : luaL_checkany(L, 2);
166 3 : luaL_checkany(L, 3);
167 3 : lua_settop(L, 3);
168 3 : lua_rawset(L, 1);
169 2 : return 1;
170 : }
171 :
172 :
173 13 : static int luaB_collectgarbage (lua_State *L) {
174 : static const char *const opts[] = {"stop", "restart", "collect",
175 : "count", "step", "setpause", "setstepmul",
176 : "isrunning", NULL};
177 : static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
178 : LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
179 : LUA_GCISRUNNING};
180 13 : int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
181 12 : int ex = (int)luaL_optinteger(L, 2, 0);
182 12 : int res = lua_gc(L, o, ex);
183 12 : switch (o) {
184 1 : case LUA_GCCOUNT: {
185 1 : int b = lua_gc(L, LUA_GCCOUNTB, 0);
186 1 : lua_pushnumber(L, (lua_Number)res + ((lua_Number)b/1024));
187 1 : return 1;
188 : }
189 5 : case LUA_GCSTEP: case LUA_GCISRUNNING: {
190 5 : lua_pushboolean(L, res);
191 5 : return 1;
192 : }
193 6 : default: {
194 6 : lua_pushinteger(L, res);
195 6 : return 1;
196 : }
197 : }
198 : }
199 :
200 :
201 153 : static int luaB_type (lua_State *L) {
202 153 : int t = lua_type(L, 1);
203 153 : luaL_argcheck(L, t != LUA_TNONE, 1, "value expected");
204 152 : lua_pushstring(L, lua_typename(L, t));
205 152 : return 1;
206 : }
207 :
208 :
209 5934 : static int pairsmeta (lua_State *L, const char *method, int iszero,
210 : lua_CFunction iter) {
211 5934 : luaL_checkany(L, 1);
212 5934 : if (luaL_getmetafield(L, 1, method) == LUA_TNIL) { /* no metamethod? */
213 5932 : lua_pushcfunction(L, iter); /* will return generator, */
214 5932 : lua_pushvalue(L, 1); /* state, */
215 5932 : if (iszero) lua_pushinteger(L, 0); /* and initial value */
216 6 : else lua_pushnil(L);
217 : }
218 : else {
219 2 : lua_pushvalue(L, 1); /* argument 'self' to metamethod */
220 2 : lua_call(L, 1, 3); /* get 3 values from metamethod */
221 : }
222 5934 : return 3;
223 : }
224 :
225 :
226 45 : static int luaB_next (lua_State *L) {
227 45 : luaL_checktype(L, 1, LUA_TTABLE);
228 44 : lua_settop(L, 2); /* create a 2nd argument if there isn't one */
229 44 : if (lua_next(L, 1))
230 31 : return 2;
231 : else {
232 12 : lua_pushnil(L);
233 12 : return 1;
234 : }
235 : }
236 :
237 :
238 7 : static int luaB_pairs (lua_State *L) {
239 7 : return pairsmeta(L, "__pairs", 0, luaB_next);
240 : }
241 :
242 :
243 : /*
244 : ** Traversal function for 'ipairs'
245 : */
246 46287 : static int ipairsaux (lua_State *L) {
247 46287 : lua_Integer i = luaL_checkinteger(L, 2) + 1;
248 46287 : lua_pushinteger(L, i);
249 46287 : return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
250 : }
251 :
252 :
253 : /*
254 : ** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
255 : ** (The given "table" may not be a table.)
256 : */
257 5927 : static int luaB_ipairs (lua_State *L) {
258 : #if defined(LUA_COMPAT_IPAIRS)
259 5927 : return pairsmeta(L, "__ipairs", 1, ipairsaux);
260 : #else
261 : luaL_checkany(L, 1);
262 : lua_pushcfunction(L, ipairsaux); /* iteration function */
263 : lua_pushvalue(L, 1); /* state */
264 : lua_pushinteger(L, 0); /* initial value */
265 : return 3;
266 : #endif
267 : }
268 :
269 :
270 223 : static int load_aux (lua_State *L, int status, int envidx) {
271 223 : if (status == LUA_OK) {
272 180 : if (envidx != 0) { /* 'env' parameter? */
273 2 : lua_pushvalue(L, envidx); /* environment for loaded function */
274 2 : if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
275 0 : lua_pop(L, 1); /* remove 'env' if not used by previous call */
276 : }
277 180 : return 1;
278 : }
279 : else { /* error (message is on top of the stack) */
280 43 : lua_pushnil(L);
281 43 : lua_insert(L, -2); /* put before error message */
282 43 : return 2; /* return nil plus error message */
283 : }
284 : }
285 :
286 :
287 6 : static int luaB_loadfile (lua_State *L) {
288 6 : const char *fname = luaL_optstring(L, 1, NULL);
289 6 : const char *mode = luaL_optstring(L, 2, NULL);
290 6 : int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */
291 6 : int status = luaL_loadfilex(L, fname, mode);
292 6 : return load_aux(L, status, env);
293 : }
294 :
295 :
296 : /*
297 : ** {======================================================
298 : ** Generic Read function
299 : ** =======================================================
300 : */
301 :
302 :
303 : /*
304 : ** reserved slot, above all arguments, to hold a copy of the returned
305 : ** string to avoid it being collected while parsed. 'load' has four
306 : ** optional arguments (chunk, source name, mode, and environment).
307 : */
308 : #define RESERVEDSLOT 5
309 :
310 :
311 : /*
312 : ** Reader for generic 'load' function: 'lua_load' uses the
313 : ** stack for internal stuff, so the reader cannot change the
314 : ** stack top. Instead, it keeps its resulting string in a
315 : ** reserved slot inside the stack.
316 : */
317 6 : static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
318 : (void)(ud); /* not used */
319 6 : luaL_checkstack(L, 2, "too many nested functions");
320 6 : lua_pushvalue(L, 1); /* get function */
321 6 : lua_call(L, 0, 1); /* call it */
322 6 : if (lua_isnil(L, -1)) {
323 3 : lua_pop(L, 1); /* pop result */
324 3 : *size = 0;
325 3 : return NULL;
326 : }
327 3 : else if (!lua_isstring(L, -1))
328 1 : luaL_error(L, "reader function must return a string");
329 2 : lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
330 2 : return lua_tolstring(L, RESERVEDSLOT, size);
331 : }
332 :
333 :
334 217 : static int luaB_load (lua_State *L) {
335 : int status;
336 : size_t l;
337 217 : const char *s = lua_tolstring(L, 1, &l);
338 217 : const char *mode = luaL_optstring(L, 3, "bt");
339 217 : int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
340 217 : if (s != NULL) { /* loading a string? */
341 212 : const char *chunkname = luaL_optstring(L, 2, s);
342 212 : status = luaL_loadbufferx(L, s, l, chunkname, mode);
343 : }
344 : else { /* loading from a reader function */
345 5 : const char *chunkname = luaL_optstring(L, 2, "=(load)");
346 5 : luaL_checktype(L, 1, LUA_TFUNCTION);
347 5 : lua_settop(L, RESERVEDSLOT); /* create reserved slot */
348 5 : status = lua_load(L, generic_reader, NULL, chunkname, mode);
349 : }
350 217 : return load_aux(L, status, env);
351 : }
352 :
353 : /* }====================================================== */
354 :
355 :
356 13 : static int dofilecont (lua_State *L, int d1, lua_KContext d2) {
357 : (void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */
358 13 : return lua_gettop(L) - 1;
359 : }
360 :
361 :
362 15 : static int luaB_dofile (lua_State *L) {
363 15 : const char *fname = luaL_optstring(L, 1, NULL);
364 15 : lua_settop(L, 1);
365 15 : if (luaL_loadfile(L, fname) != LUA_OK)
366 2 : return lua_error(L);
367 13 : lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
368 13 : return dofilecont(L, 0, 0);
369 : }
370 :
371 :
372 5929 : static int luaB_assert (lua_State *L) {
373 5929 : if (lua_toboolean(L, 1)) /* condition is true? */
374 5919 : return lua_gettop(L); /* return all arguments */
375 : else { /* error */
376 10 : luaL_checkany(L, 1); /* there must be a condition */
377 9 : lua_remove(L, 1); /* remove it */
378 9 : lua_pushliteral(L, "assertion failed!"); /* default message */
379 9 : lua_settop(L, 1); /* leave only message (default if no other one) */
380 9 : return luaB_error(L); /* call 'error' */
381 : }
382 : }
383 :
384 :
385 12 : static int luaB_select (lua_State *L) {
386 12 : int n = lua_gettop(L);
387 12 : if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
388 2 : lua_pushinteger(L, n-1);
389 2 : return 1;
390 : }
391 : else {
392 10 : lua_Integer i = luaL_checkinteger(L, 1);
393 10 : if (i < 0) i = n + i;
394 6 : else if (i > n) i = n;
395 10 : luaL_argcheck(L, 1 <= i, 1, "index out of range");
396 8 : return n - (int)i;
397 : }
398 : }
399 :
400 :
401 : /*
402 : ** Continuation function for 'pcall' and 'xpcall'. Both functions
403 : ** already pushed a 'true' before doing the call, so in case of success
404 : ** 'finishpcall' only has to return everything in the stack minus
405 : ** 'extra' values (where 'extra' is exactly the number of items to be
406 : ** ignored).
407 : */
408 632 : static int finishpcall (lua_State *L, int status, lua_KContext extra) {
409 632 : if (status != LUA_OK && status != LUA_YIELD) { /* error? */
410 459 : lua_pushboolean(L, 0); /* first result (false) */
411 459 : lua_pushvalue(L, -2); /* error message */
412 459 : return 2; /* return false, msg */
413 : }
414 : else
415 173 : return lua_gettop(L) - (int)extra; /* return all results */
416 : }
417 :
418 :
419 625 : static int luaB_pcall (lua_State *L) {
420 : int status;
421 625 : luaL_checkany(L, 1);
422 625 : lua_pushboolean(L, 1); /* first result if no errors */
423 625 : lua_insert(L, 1); /* put it in place */
424 625 : status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall);
425 624 : return finishpcall(L, status, 0);
426 : }
427 :
428 :
429 : /*
430 : ** Do a protected call with error handling. After 'lua_rotate', the
431 : ** stack will have <f, err, true, f, [args...]>; so, the function passes
432 : ** 2 to 'finishpcall' to skip the 2 first values when returning results.
433 : */
434 9 : static int luaB_xpcall (lua_State *L) {
435 : int status;
436 9 : int n = lua_gettop(L);
437 9 : luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */
438 7 : lua_pushboolean(L, 1); /* first result */
439 7 : lua_pushvalue(L, 1); /* function */
440 7 : lua_rotate(L, 3, 2); /* move them below function's arguments */
441 7 : status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall);
442 6 : return finishpcall(L, status, 2);
443 : }
444 :
445 :
446 5053 : static int luaB_tostring (lua_State *L) {
447 5053 : luaL_checkany(L, 1);
448 5052 : luaL_tolstring(L, 1, NULL);
449 5049 : return 1;
450 : }
451 :
452 :
453 : static const luaL_Reg base_funcs[] = {
454 : {"assert", luaB_assert},
455 : {"collectgarbage", luaB_collectgarbage},
456 : {"dofile", luaB_dofile},
457 : {"error", luaB_error},
458 : {"getmetatable", luaB_getmetatable},
459 : {"ipairs", luaB_ipairs},
460 : {"loadfile", luaB_loadfile},
461 : {"load", luaB_load},
462 : #if defined(LUA_COMPAT_LOADSTRING)
463 : {"loadstring", luaB_load},
464 : #endif
465 : {"next", luaB_next},
466 : {"pairs", luaB_pairs},
467 : {"pcall", luaB_pcall},
468 : {"print", luaB_print},
469 : {"rawequal", luaB_rawequal},
470 : {"rawlen", luaB_rawlen},
471 : {"rawget", luaB_rawget},
472 : {"rawset", luaB_rawset},
473 : {"select", luaB_select},
474 : {"setmetatable", luaB_setmetatable},
475 : {"tonumber", luaB_tonumber},
476 : {"tostring", luaB_tostring},
477 : {"type", luaB_type},
478 : {"xpcall", luaB_xpcall},
479 : /* placeholders */
480 : {"_G", NULL},
481 : {"_VERSION", NULL},
482 : {NULL, NULL}
483 : };
484 :
485 :
486 86 : LUAMOD_API int luaopen_base (lua_State *L) {
487 : /* open lib into global table */
488 86 : lua_pushglobaltable(L);
489 86 : luaL_setfuncs(L, base_funcs, 0);
490 : /* set global _G */
491 86 : lua_pushvalue(L, -1);
492 86 : lua_setfield(L, -2, "_G");
493 : /* set global _VERSION */
494 86 : lua_pushliteral(L, LUA_VERSION);
495 86 : lua_setfield(L, -2, "_VERSION");
496 86 : return 1;
497 : }
498 :
|