LCOV - code coverage report
Current view: top level - AP_Scripting/lua/src - lbaselib.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 111 249 44.6 %
Date: 2026-09-09 11:02:08 Functions: 16 31 51.6 %

          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             : }

Generated by: LCOV version 1.14