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