LCOV - code coverage report
Current view: top level - external/lua/src - lauxlib.c (source / functions) Hit Total Coverage
Test: rapport Lines: 202 579 34.9 %
Date: 2021-12-10 16:22:55 Functions: 30 67 44.8 %
Branches: 55 253 21.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            : ** $Id: lauxlib.c $
       3                 :            : ** Auxiliary functions for building Lua libraries
       4                 :            : ** See Copyright Notice in lua.h
       5                 :            : */
       6                 :            : 
       7                 :            : #define lauxlib_c
       8                 :            : #define LUA_LIB
       9                 :            : 
      10                 :            : #include "lprefix.h"
      11                 :            : 
      12                 :            : 
      13                 :            : #include <errno.h>
      14                 :            : #include <stdarg.h>
      15                 :            : #include <stdio.h>
      16                 :            : #include <stdlib.h>
      17                 :            : #include <string.h>
      18                 :            : 
      19                 :            : 
      20                 :            : /*
      21                 :            : ** This file uses only the official API of Lua.
      22                 :            : ** Any function declared here could be written as an application function.
      23                 :            : */
      24                 :            : 
      25                 :            : #include "lua.h"
      26                 :            : 
      27                 :            : #include "lauxlib.h"
      28                 :            : 
      29                 :            : 
      30                 :            : #if !defined(MAX_SIZET)
      31                 :            : /* maximum value for size_t */
      32                 :            : #define MAX_SIZET       ((size_t)(~(size_t)0))
      33                 :            : #endif
      34                 :            : 
      35                 :            : 
      36                 :            : /*
      37                 :            : ** {======================================================
      38                 :            : ** Traceback
      39                 :            : ** =======================================================
      40                 :            : */
      41                 :            : 
      42                 :            : 
      43                 :            : #define LEVELS1 10      /* size of the first part of the stack */
      44                 :            : #define LEVELS2 11      /* size of the second part of the stack */
      45                 :            : 
      46                 :            : 
      47                 :            : 
      48                 :            : /*
      49                 :            : ** Search for 'objidx' in table at index -1. ('objidx' must be an
      50                 :            : ** absolute index.) Return 1 + string at top if it found a good name.
      51                 :            : */
      52                 :          0 : static int findfield (lua_State *L, int objidx, int level) {
      53   [ #  #  #  # ]:          0 :   if (level == 0 || !lua_istable(L, -1))
      54                 :          0 :     return 0;  /* not found */
      55                 :          0 :   lua_pushnil(L);  /* start 'next' loop */
      56         [ #  # ]:          0 :   while (lua_next(L, -2)) {  /* for each pair in table */
      57         [ #  # ]:          0 :     if (lua_type(L, -2) == LUA_TSTRING) {  /* ignore non-string keys */
      58         [ #  # ]:          0 :       if (lua_rawequal(L, objidx, -1)) {  /* found object? */
      59                 :          0 :         lua_pop(L, 1);  /* remove value (but keep name) */
      60                 :          0 :         return 1;
      61                 :            :       }
      62         [ #  # ]:          0 :       else if (findfield(L, objidx, level - 1)) {  /* try recursively */
      63                 :            :         /* stack: lib_name, lib_table, field_name (top) */
      64                 :          0 :         lua_pushliteral(L, ".");  /* place '.' between the two names */
      65                 :          0 :         lua_replace(L, -3);  /* (in the slot occupied by table) */
      66                 :          0 :         lua_concat(L, 3);  /* lib_name.field_name */
      67                 :          0 :         return 1;
      68                 :            :       }
      69                 :          0 :     }
      70                 :          0 :     lua_pop(L, 1);  /* remove value */
      71                 :            :   }
      72                 :          0 :   return 0;  /* not found */
      73                 :          0 : }
      74                 :            : 
      75                 :            : 
      76                 :            : /*
      77                 :            : ** Search for a name for a function in all loaded modules
      78                 :            : */
      79                 :          0 : static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
      80                 :          0 :   int top = lua_gettop(L);
      81                 :          0 :   lua_getinfo(L, "f", ar);  /* push function */
      82                 :          0 :   lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
      83         [ #  # ]:          0 :   if (findfield(L, top + 1, 2)) {
      84                 :          0 :     const char *name = lua_tostring(L, -1);
      85         [ #  # ]:          0 :     if (strncmp(name, LUA_GNAME ".", 3) == 0) {  /* name start with '_G.'? */
      86                 :          0 :       lua_pushstring(L, name + 3);  /* push name without prefix */
      87                 :          0 :       lua_remove(L, -2);  /* remove original name */
      88                 :          0 :     }
      89                 :          0 :     lua_copy(L, -1, top + 1);  /* copy name to proper place */
      90                 :          0 :     lua_settop(L, top + 1);  /* remove table "loaded" and name copy */
      91                 :          0 :     return 1;
      92                 :            :   }
      93                 :            :   else {
      94                 :          0 :     lua_settop(L, top);  /* remove function and global table */
      95                 :          0 :     return 0;
      96                 :            :   }
      97                 :          0 : }
      98                 :            : 
      99                 :            : 
     100                 :          0 : static void pushfuncname (lua_State *L, lua_Debug *ar) {
     101         [ #  # ]:          0 :   if (pushglobalfuncname(L, ar)) {  /* try first a global name */
     102                 :          0 :     lua_pushfstring(L, "function '%s'", lua_tostring(L, -1));
     103                 :          0 :     lua_remove(L, -2);  /* remove name */
     104                 :          0 :   }
     105         [ #  # ]:          0 :   else if (*ar->namewhat != '\0')  /* is there a name from code? */
     106                 :          0 :     lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name);  /* use it */
     107         [ #  # ]:          0 :   else if (*ar->what == 'm')  /* main? */
     108                 :          0 :       lua_pushliteral(L, "main chunk");
     109         [ #  # ]:          0 :   else if (*ar->what != 'C')  /* for Lua functions, use <file:line> */
     110                 :          0 :     lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
     111                 :            :   else  /* nothing left... */
     112                 :          0 :     lua_pushliteral(L, "?");
     113                 :          0 : }
     114                 :            : 
     115                 :            : 
     116                 :          0 : static int lastlevel (lua_State *L) {
     117                 :            :   lua_Debug ar;
     118                 :          0 :   int li = 1, le = 1;
     119                 :            :   /* find an upper bound */
     120         [ #  # ]:          0 :   while (lua_getstack(L, le, &ar)) { li = le; le *= 2; }
     121                 :            :   /* do a binary search */
     122         [ #  # ]:          0 :   while (li < le) {
     123                 :          0 :     int m = (li + le)/2;
     124         [ #  # ]:          0 :     if (lua_getstack(L, m, &ar)) li = m + 1;
     125                 :          0 :     else le = m;
     126                 :            :   }
     127                 :          0 :   return le - 1;
     128                 :            : }
     129                 :            : 
     130                 :            : 
     131                 :          0 : LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1,
     132                 :            :                                 const char *msg, int level) {
     133                 :            :   luaL_Buffer b;
     134                 :            :   lua_Debug ar;
     135                 :          0 :   int last = lastlevel(L1);
     136                 :          0 :   int limit2show = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1;
     137                 :          0 :   luaL_buffinit(L, &b);
     138         [ #  # ]:          0 :   if (msg) {
     139                 :          0 :     luaL_addstring(&b, msg);
     140         [ #  # ]:          0 :     luaL_addchar(&b, '\n');
     141                 :          0 :   }
     142                 :          0 :   luaL_addstring(&b, "stack traceback:");
     143         [ #  # ]:          0 :   while (lua_getstack(L1, level++, &ar)) {
     144         [ #  # ]:          0 :     if (limit2show-- == 0) {  /* too many levels? */
     145                 :          0 :       int n = last - level - LEVELS2 + 1;  /* number of levels to skip */
     146                 :          0 :       lua_pushfstring(L, "\n\t...\t(skipping %d levels)", n);
     147                 :          0 :       luaL_addvalue(&b);  /* add warning about skip */
     148                 :          0 :       level += n;  /* and skip to last levels */
     149                 :          0 :     }
     150                 :            :     else {
     151                 :          0 :       lua_getinfo(L1, "Slnt", &ar);
     152         [ #  # ]:          0 :       if (ar.currentline <= 0)
     153                 :          0 :         lua_pushfstring(L, "\n\t%s: in ", ar.short_src);
     154                 :            :       else
     155                 :          0 :         lua_pushfstring(L, "\n\t%s:%d: in ", ar.short_src, ar.currentline);
     156                 :          0 :       luaL_addvalue(&b);
     157                 :          0 :       pushfuncname(L, &ar);
     158                 :          0 :       luaL_addvalue(&b);
     159         [ #  # ]:          0 :       if (ar.istailcall)
     160                 :          0 :         luaL_addstring(&b, "\n\t(...tail calls...)");
     161                 :            :     }
     162                 :            :   }
     163                 :          0 :   luaL_pushresult(&b);
     164                 :          0 : }
     165                 :            : 
     166                 :            : /* }====================================================== */
     167                 :            : 
     168                 :            : 
     169                 :            : /*
     170                 :            : ** {======================================================
     171                 :            : ** Error-report functions
     172                 :            : ** =======================================================
     173                 :            : */
     174                 :            : 
     175                 :        244 : LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) {
     176                 :            :   lua_Debug ar;
     177         [ +  - ]:        244 :   if (!lua_getstack(L, 0, &ar))  /* no stack frame? */
     178                 :          0 :     return luaL_error(L, "bad argument #%d (%s)", arg, extramsg);
     179                 :        244 :   lua_getinfo(L, "n", &ar);
     180         [ +  - ]:        244 :   if (strcmp(ar.namewhat, "method") == 0) {
     181                 :          0 :     arg--;  /* do not count 'self' */
     182         [ #  # ]:          0 :     if (arg == 0)  /* error is in the self argument itself? */
     183                 :          0 :       return luaL_error(L, "calling '%s' on bad self (%s)",
     184                 :          0 :                            ar.name, extramsg);
     185                 :          0 :   }
     186         [ +  - ]:        244 :   if (ar.name == NULL)
     187         [ #  # ]:          0 :     ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?";
     188                 :        488 :   return luaL_error(L, "bad argument #%d to '%s' (%s)",
     189                 :        244 :                         arg, ar.name, extramsg);
     190                 :        244 : }
     191                 :            : 
     192                 :            : 
     193                 :         19 : int luaL_typeerror (lua_State *L, int arg, const char *tname) {
     194                 :            :   const char *msg;
     195                 :            :   const char *typearg;  /* name for the type of the actual argument */
     196         [ -  + ]:         19 :   if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING)
     197                 :          0 :     typearg = lua_tostring(L, -1);  /* use the given type name */
     198         [ -  + ]:         19 :   else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA)
     199                 :          0 :     typearg = "light userdata";  /* special name for messages */
     200                 :            :   else
     201                 :         19 :     typearg = luaL_typename(L, arg);  /* standard name */
     202                 :         19 :   msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg);
     203                 :         19 :   return luaL_argerror(L, arg, msg);
     204                 :            : }
     205                 :            : 
     206                 :            : 
     207                 :         16 : static void tag_error (lua_State *L, int arg, int tag) {
     208                 :         16 :   luaL_typeerror(L, arg, lua_typename(L, tag));
     209                 :         16 : }
     210                 :            : 
     211                 :            : 
     212                 :            : /*
     213                 :            : ** The use of 'lua_pushfstring' ensures this function does not
     214                 :            : ** need reserved stack space when called.
     215                 :            : */
     216                 :        282 : LUALIB_API void luaL_where (lua_State *L, int level) {
     217                 :            :   lua_Debug ar;
     218         [ -  + ]:        282 :   if (lua_getstack(L, level, &ar)) {  /* check function at level */
     219                 :        282 :     lua_getinfo(L, "Sl", &ar);  /* get info about it */
     220         [ -  + ]:        282 :     if (ar.currentline > 0) {  /* is there info? */
     221                 :        282 :       lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
     222                 :        282 :       return;
     223                 :            :     }
     224                 :          0 :   }
     225                 :          0 :   lua_pushfstring(L, "");  /* else, no information available... */
     226                 :        282 : }
     227                 :            : 
     228                 :            : 
     229                 :            : /*
     230                 :            : ** Again, the use of 'lua_pushvfstring' ensures this function does
     231                 :            : ** not need reserved stack space when called. (At worst, it generates
     232                 :            : ** an error with "stack overflow" instead of the given message.)
     233                 :            : */
     234                 :        276 : LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
     235                 :            :   va_list argp;
     236                 :        276 :   va_start(argp, fmt);
     237                 :        276 :   luaL_where(L, 1);
     238                 :        276 :   lua_pushvfstring(L, fmt, argp);
     239                 :        276 :   va_end(argp);
     240                 :        276 :   lua_concat(L, 2);
     241                 :        276 :   return lua_error(L);
     242                 :            : }
     243                 :            : 
     244                 :            : 
     245                 :        130 : LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
     246                 :        130 :   int en = errno;  /* calls to Lua API may change this value */
     247         [ +  + ]:        130 :   if (stat) {
     248                 :         20 :     lua_pushboolean(L, 1);
     249                 :         20 :     return 1;
     250                 :            :   }
     251                 :            :   else {
     252                 :        110 :     luaL_pushfail(L);
     253         [ -  + ]:        110 :     if (fname)
     254                 :        110 :       lua_pushfstring(L, "%s: %s", fname, strerror(en));
     255                 :            :     else
     256                 :          0 :       lua_pushstring(L, strerror(en));
     257                 :        110 :     lua_pushinteger(L, en);
     258                 :        110 :     return 3;
     259                 :            :   }
     260                 :        130 : }
     261                 :            : 
     262                 :            : 
     263                 :            : #if !defined(l_inspectstat)     /* { */
     264                 :            : 
     265                 :            : #if defined(LUA_USE_POSIX)
     266                 :            : 
     267                 :            : #include <sys/wait.h>
     268                 :            : 
     269                 :            : /*
     270                 :            : ** use appropriate macros to interpret 'pclose' return status
     271                 :            : */
     272                 :            : #define l_inspectstat(stat,what)  \
     273                 :            :    if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \
     274                 :            :    else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; }
     275                 :            : 
     276                 :            : #else
     277                 :            : 
     278                 :            : #define l_inspectstat(stat,what)  /* no op */
     279                 :            : 
     280                 :            : #endif
     281                 :            : 
     282                 :            : #endif                          /* } */
     283                 :            : 
     284                 :            : 
     285                 :          1 : LUALIB_API int luaL_execresult (lua_State *L, int stat) {
     286   [ -  +  #  # ]:          1 :   if (stat != 0 && errno != 0)  /* error with an 'errno'? */
     287                 :          0 :     return luaL_fileresult(L, 0, NULL);
     288                 :            :   else {
     289                 :          1 :     const char *what = "exit";  /* type of termination */
     290                 :            :     l_inspectstat(stat, what);  /* interpret result */
     291   [ +  -  +  - ]:          1 :     if (*what == 'e' && stat == 0)  /* successful termination? */
     292                 :          1 :       lua_pushboolean(L, 1);
     293                 :            :     else
     294                 :          0 :       luaL_pushfail(L);
     295                 :          1 :     lua_pushstring(L, what);
     296                 :          1 :     lua_pushinteger(L, stat);
     297                 :          1 :     return 3;  /* return true/fail,what,code */
     298                 :            :   }
     299                 :          1 : }
     300                 :            : 
     301                 :            : /* }====================================================== */
     302                 :            : 
     303                 :            : 
     304                 :            : 
     305                 :            : /*
     306                 :            : ** {======================================================
     307                 :            : ** Userdata's metatable manipulation
     308                 :            : ** =======================================================
     309                 :            : */
     310                 :            : 
     311                 :        810 : LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
     312         [ -  + ]:        810 :   if (luaL_getmetatable(L, tname) != LUA_TNIL)  /* name already in use? */
     313                 :          0 :     return 0;  /* leave previous value on top, but return 0 */
     314                 :        810 :   lua_pop(L, 1);
     315                 :        810 :   lua_createtable(L, 0, 2);  /* create metatable */
     316                 :        810 :   lua_pushstring(L, tname);
     317                 :        810 :   lua_setfield(L, -2, "__name");  /* metatable.__name = tname */
     318                 :        810 :   lua_pushvalue(L, -1);
     319                 :        810 :   lua_setfield(L, LUA_REGISTRYINDEX, tname);  /* registry.name = metatable */
     320                 :        810 :   return 1;
     321                 :        810 : }
     322                 :            : 
     323                 :            : 
     324                 :       2449 : LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) {
     325                 :       2449 :   luaL_getmetatable(L, tname);
     326                 :       2449 :   lua_setmetatable(L, -2);
     327                 :       2449 : }
     328                 :            : 
     329                 :            : 
     330                 :        423 : LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) {
     331                 :        423 :   void *p = lua_touserdata(L, ud);
     332         [ +  + ]:        423 :   if (p != NULL) {  /* value is a userdata? */
     333         [ +  - ]:        420 :     if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */
     334                 :        420 :       luaL_getmetatable(L, tname);  /* get correct metatable */
     335         [ -  + ]:        420 :       if (!lua_rawequal(L, -1, -2))  /* not the same? */
     336                 :          0 :         p = NULL;  /* value is a userdata with wrong metatable */
     337                 :        420 :       lua_pop(L, 2);  /* remove both metatables */
     338                 :        420 :       return p;
     339                 :            :     }
     340                 :          0 :   }
     341                 :          3 :   return NULL;  /* value is not a userdata with a metatable */
     342                 :        423 : }
     343                 :            : 
     344                 :            : 
     345                 :        423 : LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
     346                 :        423 :   void *p = luaL_testudata(L, ud, tname);
     347         [ +  + ]:        423 :   luaL_argexpected(L, p != NULL, ud, tname);
     348                 :        423 :   return p;
     349                 :            : }
     350                 :            : 
     351                 :            : /* }====================================================== */
     352                 :            : 
     353                 :            : 
     354                 :            : /*
     355                 :            : ** {======================================================
     356                 :            : ** Argument check functions
     357                 :            : ** =======================================================
     358                 :            : */
     359                 :            : 
     360                 :          0 : LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def,
     361                 :            :                                  const char *const lst[]) {
     362         [ #  # ]:          0 :   const char *name = (def) ? luaL_optstring(L, arg, def) :
     363                 :          0 :                              luaL_checkstring(L, arg);
     364                 :            :   int i;
     365         [ #  # ]:          0 :   for (i=0; lst[i]; i++)
     366         [ #  # ]:          0 :     if (strcmp(lst[i], name) == 0)
     367                 :          0 :       return i;
     368                 :          0 :   return luaL_argerror(L, arg,
     369                 :          0 :                        lua_pushfstring(L, "invalid option '%s'", name));
     370                 :          0 : }
     371                 :            : 
     372                 :            : 
     373                 :            : /*
     374                 :            : ** Ensures the stack has at least 'space' extra slots, raising an error
     375                 :            : ** if it cannot fulfill the request. (The error handling needs a few
     376                 :            : ** extra slots to format the error message. In case of an error without
     377                 :            : ** this extra space, Lua will generate the same 'stack overflow' error,
     378                 :            : ** but without 'msg'.)
     379                 :            : */
     380                 :      12881 : LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
     381         [ +  - ]:      12881 :   if (!lua_checkstack(L, space)) {
     382         [ #  # ]:          0 :     if (msg)
     383                 :          0 :       luaL_error(L, "stack overflow (%s)", msg);
     384                 :            :     else
     385                 :          0 :       luaL_error(L, "stack overflow");
     386                 :          0 :   }
     387                 :      12881 : }
     388                 :            : 
     389                 :            : 
     390                 :         22 : LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) {
     391         [ +  + ]:         22 :   if (lua_type(L, arg) != t)
     392                 :         13 :     tag_error(L, arg, t);
     393                 :         22 : }
     394                 :            : 
     395                 :            : 
     396                 :          6 : LUALIB_API void luaL_checkany (lua_State *L, int arg) {
     397         [ -  + ]:          6 :   if (lua_type(L, arg) == LUA_TNONE)
     398                 :          0 :     luaL_argerror(L, arg, "value expected");
     399                 :          6 : }
     400                 :            : 
     401                 :            : 
     402                 :        574 : LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) {
     403                 :        574 :   const char *s = lua_tolstring(L, arg, len);
     404         [ +  + ]:        574 :   if (!s) tag_error(L, arg, LUA_TSTRING);
     405                 :        574 :   return s;
     406                 :            : }
     407                 :            : 
     408                 :            : 
     409                 :         20 : LUALIB_API const char *luaL_optlstring (lua_State *L, int arg,
     410                 :            :                                         const char *def, size_t *len) {
     411         [ -  + ]:         20 :   if (lua_isnoneornil(L, arg)) {
     412         [ #  # ]:          0 :     if (len)
     413         [ #  # ]:          0 :       *len = (def ? strlen(def) : 0);
     414                 :          0 :     return def;
     415                 :            :   }
     416                 :         20 :   else return luaL_checklstring(L, arg, len);
     417                 :         20 : }
     418                 :            : 
     419                 :            : 
     420                 :          0 : LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) {
     421                 :            :   int isnum;
     422                 :          0 :   lua_Number d = lua_tonumberx(L, arg, &isnum);
     423         [ #  # ]:          0 :   if (!isnum)
     424                 :          0 :     tag_error(L, arg, LUA_TNUMBER);
     425                 :          0 :   return d;
     426                 :            : }
     427                 :            : 
     428                 :            : 
     429                 :          0 : LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) {
     430         [ #  # ]:          0 :   return luaL_opt(L, luaL_checknumber, arg, def);
     431                 :            : }
     432                 :            : 
     433                 :            : 
     434                 :          0 : static void interror (lua_State *L, int arg) {
     435         [ #  # ]:          0 :   if (lua_isnumber(L, arg))
     436                 :          0 :     luaL_argerror(L, arg, "number has no integer representation");
     437                 :            :   else
     438                 :          0 :     tag_error(L, arg, LUA_TNUMBER);
     439                 :          0 : }
     440                 :            : 
     441                 :            : 
     442                 :          0 : LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) {
     443                 :            :   int isnum;
     444                 :          0 :   lua_Integer d = lua_tointegerx(L, arg, &isnum);
     445         [ #  # ]:          0 :   if (!isnum) {
     446                 :          0 :     interror(L, arg);
     447                 :          0 :   }
     448                 :          0 :   return d;
     449                 :            : }
     450                 :            : 
     451                 :            : 
     452                 :          6 : LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg,
     453                 :            :                                                       lua_Integer def) {
     454         [ +  - ]:          6 :   return luaL_opt(L, luaL_checkinteger, arg, def);
     455                 :            : }
     456                 :            : 
     457                 :            : /* }====================================================== */
     458                 :            : 
     459                 :            : 
     460                 :            : /*
     461                 :            : ** {======================================================
     462                 :            : ** Generic Buffer manipulation
     463                 :            : ** =======================================================
     464                 :            : */
     465                 :            : 
     466                 :            : /* userdata to box arbitrary data */
     467                 :            : typedef struct UBox {
     468                 :            :   void *box;
     469                 :            :   size_t bsize;
     470                 :            : } UBox;
     471                 :            : 
     472                 :            : 
     473                 :          0 : static void *resizebox (lua_State *L, int idx, size_t newsize) {
     474                 :            :   void *ud;
     475                 :          0 :   lua_Alloc allocf = lua_getallocf(L, &ud);
     476                 :          0 :   UBox *box = (UBox *)lua_touserdata(L, idx);
     477                 :          0 :   void *temp = allocf(ud, box->box, box->bsize, newsize);
     478   [ #  #  #  # ]:          0 :   if (temp == NULL && newsize > 0) {  /* allocation error? */
     479                 :          0 :     lua_pushliteral(L, "not enough memory");
     480                 :          0 :     lua_error(L);  /* raise a memory error */
     481                 :          0 :   }
     482                 :          0 :   box->box = temp;
     483                 :          0 :   box->bsize = newsize;
     484                 :          0 :   return temp;
     485                 :            : }
     486                 :            : 
     487                 :            : 
     488                 :          0 : static int boxgc (lua_State *L) {
     489                 :          0 :   resizebox(L, 1, 0);
     490                 :          0 :   return 0;
     491                 :            : }
     492                 :            : 
     493                 :            : 
     494                 :            : static const luaL_Reg boxmt[] = {  /* box metamethods */
     495                 :            :   {"__gc", boxgc},
     496                 :            :   {"__close", boxgc},
     497                 :            :   {NULL, NULL}
     498                 :            : };
     499                 :            : 
     500                 :            : 
     501                 :          0 : static void newbox (lua_State *L) {
     502                 :          0 :   UBox *box = (UBox *)lua_newuserdatauv(L, sizeof(UBox), 0);
     503                 :          0 :   box->box = NULL;
     504                 :          0 :   box->bsize = 0;
     505         [ #  # ]:          0 :   if (luaL_newmetatable(L, "_UBOX*"))  /* creating metatable? */
     506                 :          0 :     luaL_setfuncs(L, boxmt, 0);  /* set its metamethods */
     507                 :          0 :   lua_setmetatable(L, -2);
     508                 :          0 : }
     509                 :            : 
     510                 :            : 
     511                 :            : /*
     512                 :            : ** check whether buffer is using a userdata on the stack as a temporary
     513                 :            : ** buffer
     514                 :            : */
     515                 :            : #define buffonstack(B)  ((B)->b != (B)->init.b)
     516                 :            : 
     517                 :            : 
     518                 :            : /*
     519                 :            : ** Compute new size for buffer 'B', enough to accommodate extra 'sz'
     520                 :            : ** bytes.
     521                 :            : */
     522                 :          0 : static size_t newbuffsize (luaL_Buffer *B, size_t sz) {
     523                 :          0 :   size_t newsize = B->size * 2;  /* double buffer size */
     524         [ #  # ]:          0 :   if (MAX_SIZET - sz < B->n)  /* overflow in (B->n + sz)? */
     525                 :          0 :     return luaL_error(B->L, "buffer too large");
     526         [ #  # ]:          0 :   if (newsize < B->n + sz)  /* double is not big enough? */
     527                 :          0 :     newsize = B->n + sz;
     528                 :          0 :   return newsize;
     529                 :          0 : }
     530                 :            : 
     531                 :            : 
     532                 :            : /*
     533                 :            : ** Returns a pointer to a free area with at least 'sz' bytes in buffer
     534                 :            : ** 'B'. 'boxidx' is the relative position in the stack where the
     535                 :            : ** buffer's box is or should be.
     536                 :            : */
     537                 :          0 : static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) {
     538         [ #  # ]:          0 :   if (B->size - B->n >= sz)  /* enough space? */
     539                 :          0 :     return B->b + B->n;
     540                 :            :   else {
     541                 :          0 :     lua_State *L = B->L;
     542                 :            :     char *newbuff;
     543                 :          0 :     size_t newsize = newbuffsize(B, sz);
     544                 :            :     /* create larger buffer */
     545         [ #  # ]:          0 :     if (buffonstack(B))  /* buffer already has a box? */
     546                 :          0 :       newbuff = (char *)resizebox(L, boxidx, newsize);  /* resize it */
     547                 :            :     else {  /* no box yet */
     548                 :          0 :       lua_pushnil(L);  /* reserve slot for final result */
     549                 :          0 :       newbox(L);  /* create a new box */
     550                 :            :       /* move box (and slot) to its intended position */
     551                 :          0 :       lua_rotate(L, boxidx - 1, 2);
     552                 :          0 :       lua_toclose(L, boxidx);
     553                 :          0 :       newbuff = (char *)resizebox(L, boxidx, newsize);
     554                 :          0 :       memcpy(newbuff, B->b, B->n * sizeof(char));  /* copy original content */
     555                 :            :     }
     556                 :          0 :     B->b = newbuff;
     557                 :          0 :     B->size = newsize;
     558                 :          0 :     return newbuff + B->n;
     559                 :            :   }
     560                 :          0 : }
     561                 :            : 
     562                 :            : /*
     563                 :            : ** returns a pointer to a free area with at least 'sz' bytes
     564                 :            : */
     565                 :          0 : LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
     566                 :          0 :   return prepbuffsize(B, sz, -1);
     567                 :            : }
     568                 :            : 
     569                 :            : 
     570                 :          0 : LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
     571         [ #  # ]:          0 :   if (l > 0) {  /* avoid 'memcpy' when 's' can be NULL */
     572                 :          0 :     char *b = prepbuffsize(B, l, -1);
     573                 :          0 :     memcpy(b, s, l * sizeof(char));
     574                 :          0 :     luaL_addsize(B, l);
     575                 :          0 :   }
     576                 :          0 : }
     577                 :            : 
     578                 :            : 
     579                 :          0 : LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
     580                 :          0 :   luaL_addlstring(B, s, strlen(s));
     581                 :          0 : }
     582                 :            : 
     583                 :            : 
     584                 :          0 : LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
     585                 :          0 :   lua_State *L = B->L;
     586                 :          0 :   lua_pushlstring(L, B->b, B->n);
     587         [ #  # ]:          0 :   if (buffonstack(B)) {
     588                 :          0 :     lua_copy(L, -1, -3);  /* move string to reserved slot */
     589                 :          0 :     lua_pop(L, 2);  /* pop string and box (closing the box) */
     590                 :          0 :   }
     591                 :          0 : }
     592                 :            : 
     593                 :            : 
     594                 :          0 : LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) {
     595                 :          0 :   luaL_addsize(B, sz);
     596                 :          0 :   luaL_pushresult(B);
     597                 :          0 : }
     598                 :            : 
     599                 :            : 
     600                 :            : /*
     601                 :            : ** 'luaL_addvalue' is the only function in the Buffer system where the
     602                 :            : ** box (if existent) is not on the top of the stack. So, instead of
     603                 :            : ** calling 'luaL_addlstring', it replicates the code using -2 as the
     604                 :            : ** last argument to 'prepbuffsize', signaling that the box is (or will
     605                 :            : ** be) bellow the string being added to the buffer. (Box creation can
     606                 :            : ** trigger an emergency GC, so we should not remove the string from the
     607                 :            : ** stack before we have the space guaranteed.)
     608                 :            : */
     609                 :          0 : LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
     610                 :          0 :   lua_State *L = B->L;
     611                 :            :   size_t len;
     612                 :          0 :   const char *s = lua_tolstring(L, -1, &len);
     613                 :          0 :   char *b = prepbuffsize(B, len, -2);
     614                 :          0 :   memcpy(b, s, len * sizeof(char));
     615                 :          0 :   luaL_addsize(B, len);
     616                 :          0 :   lua_pop(L, 1);  /* pop string */
     617                 :          0 : }
     618                 :            : 
     619                 :            : 
     620                 :          0 : LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
     621                 :          0 :   B->L = L;
     622                 :          0 :   B->b = B->init.b;
     623                 :          0 :   B->n = 0;
     624                 :          0 :   B->size = LUAL_BUFFERSIZE;
     625                 :          0 : }
     626                 :            : 
     627                 :            : 
     628                 :          0 : LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) {
     629                 :          0 :   luaL_buffinit(L, B);
     630                 :          0 :   return prepbuffsize(B, sz, -1);
     631                 :            : }
     632                 :            : 
     633                 :            : /* }====================================================== */
     634                 :            : 
     635                 :            : 
     636                 :            : /*
     637                 :            : ** {======================================================
     638                 :            : ** Reference system
     639                 :            : ** =======================================================
     640                 :            : */
     641                 :            : 
     642                 :            : /* index of free-list header */
     643                 :            : #define freelist        0
     644                 :            : 
     645                 :            : 
     646                 :          0 : LUALIB_API int luaL_ref (lua_State *L, int t) {
     647                 :            :   int ref;
     648         [ #  # ]:          0 :   if (lua_isnil(L, -1)) {
     649                 :          0 :     lua_pop(L, 1);  /* remove from stack */
     650                 :          0 :     return LUA_REFNIL;  /* 'nil' has a unique fixed reference */
     651                 :            :   }
     652                 :          0 :   t = lua_absindex(L, t);
     653                 :          0 :   lua_rawgeti(L, t, freelist);  /* get first free element */
     654                 :          0 :   ref = (int)lua_tointeger(L, -1);  /* ref = t[freelist] */
     655                 :          0 :   lua_pop(L, 1);  /* remove it from stack */
     656         [ #  # ]:          0 :   if (ref != 0) {  /* any free element? */
     657                 :          0 :     lua_rawgeti(L, t, ref);  /* remove it from list */
     658                 :          0 :     lua_rawseti(L, t, freelist);  /* (t[freelist] = t[ref]) */
     659                 :          0 :   }
     660                 :            :   else  /* no free elements */
     661                 :          0 :     ref = (int)lua_rawlen(L, t) + 1;  /* get a new reference */
     662                 :          0 :   lua_rawseti(L, t, ref);
     663                 :          0 :   return ref;
     664                 :          0 : }
     665                 :            : 
     666                 :            : 
     667                 :          0 : LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
     668         [ #  # ]:          0 :   if (ref >= 0) {
     669                 :          0 :     t = lua_absindex(L, t);
     670                 :          0 :     lua_rawgeti(L, t, freelist);
     671                 :          0 :     lua_rawseti(L, t, ref);  /* t[ref] = t[freelist] */
     672                 :          0 :     lua_pushinteger(L, ref);
     673                 :          0 :     lua_rawseti(L, t, freelist);  /* t[freelist] = ref */
     674                 :          0 :   }
     675                 :          0 : }
     676                 :            : 
     677                 :            : /* }====================================================== */
     678                 :            : 
     679                 :            : 
     680                 :            : /*
     681                 :            : ** {======================================================
     682                 :            : ** Load functions
     683                 :            : ** =======================================================
     684                 :            : */
     685                 :            : 
     686                 :            : typedef struct LoadF {
     687                 :            :   int n;  /* number of pre-read characters */
     688                 :            :   FILE *f;  /* file being read */
     689                 :            :   char buff[BUFSIZ];  /* area for reading file */
     690                 :            : } LoadF;
     691                 :            : 
     692                 :            : 
     693                 :          0 : static const char *getF (lua_State *L, void *ud, size_t *size) {
     694                 :          0 :   LoadF *lf = (LoadF *)ud;
     695                 :          0 :   (void)L;  /* not used */
     696         [ #  # ]:          0 :   if (lf->n > 0) {  /* are there pre-read characters to be read? */
     697                 :          0 :     *size = lf->n;  /* return them (chars already in buffer) */
     698                 :          0 :     lf->n = 0;  /* no more pre-read characters */
     699                 :          0 :   }
     700                 :            :   else {  /* read a block from file */
     701                 :            :     /* 'fread' can return > 0 *and* set the EOF flag. If next call to
     702                 :            :        'getF' called 'fread', it might still wait for user input.
     703                 :            :        The next check avoids this problem. */
     704   [ #  #  #  # ]:          0 :     if (feof(lf->f)) return NULL;
     705                 :          0 :     *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);  /* read block */
     706                 :            :   }
     707                 :          0 :   return lf->buff;
     708                 :          0 : }
     709                 :            : 
     710                 :            : 
     711                 :          0 : static int errfile (lua_State *L, const char *what, int fnameindex) {
     712                 :          0 :   const char *serr = strerror(errno);
     713                 :          0 :   const char *filename = lua_tostring(L, fnameindex) + 1;
     714                 :          0 :   lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
     715                 :          0 :   lua_remove(L, fnameindex);
     716                 :          0 :   return LUA_ERRFILE;
     717                 :            : }
     718                 :            : 
     719                 :            : 
     720                 :          0 : static int skipBOM (LoadF *lf) {
     721                 :          0 :   const char *p = "\xEF\xBB\xBF";  /* UTF-8 BOM mark */
     722                 :            :   int c;
     723                 :          0 :   lf->n = 0;
     724                 :          0 :   do {
     725   [ #  #  #  # ]:          0 :     c = getc(lf->f);
     726   [ #  #  #  # ]:          0 :     if (c == EOF || c != *(const unsigned char *)p++) return c;
     727                 :          0 :     lf->buff[lf->n++] = c;  /* to be read by the parser */
     728         [ #  # ]:          0 :   } while (*p != '\0');
     729                 :          0 :   lf->n = 0;  /* prefix matched; discard it */
     730   [ #  #  #  # ]:          0 :   return getc(lf->f);  /* return next character */
     731                 :          0 : }
     732                 :            : 
     733                 :            : 
     734                 :            : /*
     735                 :            : ** reads the first character of file 'f' and skips an optional BOM mark
     736                 :            : ** in its beginning plus its first line if it starts with '#'. Returns
     737                 :            : ** true if it skipped the first line.  In any case, '*cp' has the
     738                 :            : ** first "valid" character of the file (after the optional BOM and
     739                 :            : ** a first-line comment).
     740                 :            : */
     741                 :          0 : static int skipcomment (LoadF *lf, int *cp) {
     742                 :          0 :   int c = *cp = skipBOM(lf);
     743         [ #  # ]:          0 :   if (c == '#') {  /* first line is a comment (Unix exec. file)? */
     744                 :          0 :     do {  /* skip first line */
     745   [ #  #  #  # ]:          0 :       c = getc(lf->f);
     746   [ #  #  #  # ]:          0 :     } while (c != EOF && c != '\n');
     747   [ #  #  #  # ]:          0 :     *cp = getc(lf->f);  /* skip end-of-line, if present */
     748                 :          0 :     return 1;  /* there was a comment */
     749                 :            :   }
     750                 :          0 :   else return 0;  /* no comment */
     751                 :          0 : }
     752                 :            : 
     753                 :            : 
     754                 :          0 : LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
     755                 :            :                                              const char *mode) {
     756                 :            :   LoadF lf;
     757                 :            :   int status, readstatus;
     758                 :            :   int c;
     759                 :          0 :   int fnameindex = lua_gettop(L) + 1;  /* index of filename on the stack */
     760         [ #  # ]:          0 :   if (filename == NULL) {
     761                 :          0 :     lua_pushliteral(L, "=stdin");
     762                 :          0 :     lf.f = stdin;
     763                 :          0 :   }
     764                 :            :   else {
     765                 :          0 :     lua_pushfstring(L, "@%s", filename);
     766                 :          0 :     lf.f = fopen(filename, "r");
     767         [ #  # ]:          0 :     if (lf.f == NULL) return errfile(L, "open", fnameindex);
     768                 :            :   }
     769         [ #  # ]:          0 :   if (skipcomment(&lf, &c))  /* read initial portion */
     770                 :          0 :     lf.buff[lf.n++] = '\n';  /* add line to correct line numbers */
     771   [ #  #  #  # ]:          0 :   if (c == LUA_SIGNATURE[0] && filename) {  /* binary file? */
     772                 :          0 :     lf.f = freopen(filename, "rb", lf.f);  /* reopen in binary mode */
     773         [ #  # ]:          0 :     if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
     774                 :          0 :     skipcomment(&lf, &c);  /* re-read initial portion */
     775                 :          0 :   }
     776         [ #  # ]:          0 :   if (c != EOF)
     777                 :          0 :     lf.buff[lf.n++] = c;  /* 'c' is the first character of the stream */
     778                 :          0 :   status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode);
     779         [ #  # ]:          0 :   readstatus = ferror(lf.f);
     780         [ #  # ]:          0 :   if (filename) fclose(lf.f);  /* close file (even in case of errors) */
     781         [ #  # ]:          0 :   if (readstatus) {
     782                 :          0 :     lua_settop(L, fnameindex);  /* ignore results from 'lua_load' */
     783                 :          0 :     return errfile(L, "read", fnameindex);
     784                 :            :   }
     785                 :          0 :   lua_remove(L, fnameindex);
     786                 :          0 :   return status;
     787                 :          0 : }
     788                 :            : 
     789                 :            : 
     790                 :            : typedef struct LoadS {
     791                 :            :   const char *s;
     792                 :            :   size_t size;
     793                 :            : } LoadS;
     794                 :            : 
     795                 :            : 
     796                 :       1312 : static const char *getS (lua_State *L, void *ud, size_t *size) {
     797                 :       1312 :   LoadS *ls = (LoadS *)ud;
     798                 :       1312 :   (void)L;  /* not used */
     799         [ +  + ]:       1312 :   if (ls->size == 0) return NULL;
     800                 :        656 :   *size = ls->size;
     801                 :        656 :   ls->size = 0;
     802                 :        656 :   return ls->s;
     803                 :       1312 : }
     804                 :            : 
     805                 :            : 
     806                 :        656 : LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size,
     807                 :            :                                  const char *name, const char *mode) {
     808                 :            :   LoadS ls;
     809                 :        656 :   ls.s = buff;
     810                 :        656 :   ls.size = size;
     811                 :        656 :   return lua_load(L, getS, &ls, name, mode);
     812                 :            : }
     813                 :            : 
     814                 :            : 
     815                 :        656 : LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
     816                 :        656 :   return luaL_loadbuffer(L, s, strlen(s), s);
     817                 :            : }
     818                 :            : 
     819                 :            : /* }====================================================== */
     820                 :            : 
     821                 :            : 
     822                 :            : 
     823                 :        123 : LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
     824         [ +  + ]:        123 :   if (!lua_getmetatable(L, obj))  /* no metatable? */
     825                 :         72 :     return LUA_TNIL;
     826                 :            :   else {
     827                 :            :     int tt;
     828                 :         51 :     lua_pushstring(L, event);
     829                 :         51 :     tt = lua_rawget(L, -2);
     830         [ +  - ]:         51 :     if (tt == LUA_TNIL)  /* is metafield nil? */
     831                 :         51 :       lua_pop(L, 2);  /* remove metatable and metafield */
     832                 :            :     else
     833                 :          0 :       lua_remove(L, -2);  /* remove only metatable */
     834                 :         51 :     return tt;  /* return metafield type */
     835                 :            :   }
     836                 :        123 : }
     837                 :            : 
     838                 :            : 
     839                 :        104 : LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
     840                 :        104 :   obj = lua_absindex(L, obj);
     841         [ +  - ]:        104 :   if (luaL_getmetafield(L, obj, event) == LUA_TNIL)  /* no metafield? */
     842                 :        104 :     return 0;
     843                 :          0 :   lua_pushvalue(L, obj);
     844                 :          0 :   lua_call(L, 1, 1);
     845                 :          0 :   return 1;
     846                 :        104 : }
     847                 :            : 
     848                 :            : 
     849                 :         40 : LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) {
     850                 :            :   lua_Integer l;
     851                 :            :   int isnum;
     852                 :         40 :   lua_len(L, idx);
     853                 :         40 :   l = lua_tointegerx(L, -1, &isnum);
     854         [ -  + ]:         40 :   if (!isnum)
     855                 :          0 :     luaL_error(L, "object length is not an integer");
     856                 :         40 :   lua_pop(L, 1);  /* remove object */
     857                 :         40 :   return l;
     858                 :            : }
     859                 :            : 
     860                 :            : 
     861                 :        104 : LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
     862         [ -  + ]:        104 :   if (luaL_callmeta(L, idx, "__tostring")) {  /* metafield? */
     863         [ #  # ]:          0 :     if (!lua_isstring(L, -1))
     864                 :          0 :       luaL_error(L, "'__tostring' must return a string");
     865                 :          0 :   }
     866                 :            :   else {
     867   [ -  +  +  -  :        104 :     switch (lua_type(L, idx)) {
                      + ]
     868                 :            :       case LUA_TNUMBER: {
     869         [ -  + ]:         44 :         if (lua_isinteger(L, idx))
     870                 :         44 :           lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx));
     871                 :            :         else
     872                 :          0 :           lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx));
     873                 :         44 :         break;
     874                 :            :       }
     875                 :            :       case LUA_TSTRING:
     876                 :         51 :         lua_pushvalue(L, idx);
     877                 :         51 :         break;
     878                 :            :       case LUA_TBOOLEAN:
     879                 :          0 :         lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false"));
     880                 :          0 :         break;
     881                 :            :       case LUA_TNIL:
     882                 :          9 :         lua_pushliteral(L, "nil");
     883                 :          9 :         break;
     884                 :            :       default: {
     885                 :          0 :         int tt = luaL_getmetafield(L, idx, "__name");  /* try name */
     886         [ #  # ]:          0 :         const char *kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) :
     887                 :          0 :                                                  luaL_typename(L, idx);
     888                 :          0 :         lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx));
     889         [ #  # ]:          0 :         if (tt != LUA_TNIL)
     890                 :          0 :           lua_remove(L, -2);  /* remove '__name' */
     891                 :          0 :         break;
     892                 :            :       }
     893                 :            :     }
     894                 :            :   }
     895                 :        104 :   return lua_tolstring(L, -1, len);
     896                 :            : }
     897                 :            : 
     898                 :            : 
     899                 :            : /*
     900                 :            : ** set functions from list 'l' into table at top - 'nup'; each
     901                 :            : ** function gets the 'nup' elements at the top as upvalues.
     902                 :            : ** Returns with only the table at the stack.
     903                 :            : */
     904                 :      12881 : LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
     905                 :      12881 :   luaL_checkstack(L, nup, "too many upvalues");
     906         [ +  + ]:     142681 :   for (; l->name != NULL; l++) {  /* fill the table with given functions */
     907         [ +  + ]:     129800 :     if (l->func == NULL)  /* place holder? */
     908                 :      12960 :       lua_pushboolean(L, 0);
     909                 :            :     else {
     910                 :            :       int i;
     911         [ +  + ]:     119270 :       for (i = 0; i < nup; i++)  /* copy upvalues to the top */
     912                 :       2430 :         lua_pushvalue(L, -nup);
     913                 :     116840 :       lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
     914                 :            :     }
     915                 :     129800 :     lua_setfield(L, -(nup + 2), l->name);
     916                 :     129800 :   }
     917                 :      12881 :   lua_pop(L, nup);  /* remove upvalues */
     918                 :      12881 : }
     919                 :            : 
     920                 :            : 
     921                 :            : /*
     922                 :            : ** ensure that stack[idx][fname] has a table and push that table
     923                 :            : ** into the stack
     924                 :            : */
     925                 :      10530 : LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) {
     926         [ +  + ]:      10530 :   if (lua_getfield(L, idx, fname) == LUA_TTABLE)
     927                 :       8100 :     return 1;  /* table already there */
     928                 :            :   else {
     929                 :       2430 :     lua_pop(L, 1);  /* remove previous result */
     930                 :       2430 :     idx = lua_absindex(L, idx);
     931                 :       2430 :     lua_newtable(L);
     932                 :       2430 :     lua_pushvalue(L, -1);  /* copy to be left at top */
     933                 :       2430 :     lua_setfield(L, idx, fname);  /* assign new table to field */
     934                 :       2430 :     return 0;  /* false, because did not find table there */
     935                 :            :   }
     936                 :      10530 : }
     937                 :            : 
     938                 :            : 
     939                 :            : /*
     940                 :            : ** Stripped-down 'require': After checking "loaded" table, calls 'openf'
     941                 :            : ** to open a module, registers the result in 'package.loaded' table and,
     942                 :            : ** if 'glb' is true, also registers the result in the global table.
     943                 :            : ** Leaves resulting module on the top.
     944                 :            : */
     945                 :       8100 : LUALIB_API void luaL_requiref (lua_State *L, const char *modname,
     946                 :            :                                lua_CFunction openf, int glb) {
     947                 :       8100 :   luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
     948                 :       8100 :   lua_getfield(L, -1, modname);  /* LOADED[modname] */
     949         [ +  - ]:       8100 :   if (!lua_toboolean(L, -1)) {  /* package not already loaded? */
     950                 :       8100 :     lua_pop(L, 1);  /* remove field */
     951                 :       8100 :     lua_pushcfunction(L, openf);
     952                 :       8100 :     lua_pushstring(L, modname);  /* argument to open function */
     953                 :       8100 :     lua_call(L, 1, 1);  /* call 'openf' to open module */
     954                 :       8100 :     lua_pushvalue(L, -1);  /* make copy of module (call result) */
     955                 :       8100 :     lua_setfield(L, -3, modname);  /* LOADED[modname] = module */
     956                 :       8100 :   }
     957                 :       8100 :   lua_remove(L, -2);  /* remove LOADED table */
     958         [ -  + ]:       8100 :   if (glb) {
     959                 :       8100 :     lua_pushvalue(L, -1);  /* copy of module */
     960                 :       8100 :     lua_setglobal(L, modname);  /* _G[modname] = module */
     961                 :       8100 :   }
     962                 :       8100 : }
     963                 :            : 
     964                 :            : 
     965                 :          0 : LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s,
     966                 :            :                                      const char *p, const char *r) {
     967                 :            :   const char *wild;
     968                 :          0 :   size_t l = strlen(p);
     969         [ #  # ]:          0 :   while ((wild = strstr(s, p)) != NULL) {
     970                 :          0 :     luaL_addlstring(b, s, wild - s);  /* push prefix */
     971                 :          0 :     luaL_addstring(b, r);  /* push replacement in place of pattern */
     972                 :          0 :     s = wild + l;  /* continue after 'p' */
     973                 :            :   }
     974                 :          0 :   luaL_addstring(b, s);  /* push last suffix */
     975                 :          0 : }
     976                 :            : 
     977                 :            : 
     978                 :          0 : LUALIB_API const char *luaL_gsub (lua_State *L, const char *s,
     979                 :            :                                   const char *p, const char *r) {
     980                 :            :   luaL_Buffer b;
     981                 :          0 :   luaL_buffinit(L, &b);
     982                 :          0 :   luaL_addgsub(&b, s, p, r);
     983                 :          0 :   luaL_pushresult(&b);
     984                 :          0 :   return lua_tostring(L, -1);
     985                 :            : }
     986                 :            : 
     987                 :            : 
     988                 :     308195 : static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
     989                 :     308195 :   (void)ud; (void)osize;  /* not used */
     990         [ +  + ]:     308195 :   if (nsize == 0) {
     991                 :      60162 :     free(ptr);
     992                 :      60162 :     return NULL;
     993                 :            :   }
     994                 :            :   else
     995                 :     248033 :     return realloc(ptr, nsize);
     996                 :     308195 : }
     997                 :            : 
     998                 :            : 
     999                 :          0 : static int panic (lua_State *L) {
    1000                 :          0 :   const char *msg = lua_tostring(L, -1);
    1001         [ #  # ]:          0 :   if (msg == NULL) msg = "error object is not a string";
    1002                 :          0 :   lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
    1003                 :            :                         msg);
    1004                 :          0 :   return 0;  /* return to Lua to abort */
    1005                 :            : }
    1006                 :            : 
    1007                 :            : 
    1008                 :            : /*
    1009                 :            : ** Warning functions:
    1010                 :            : ** warnfoff: warning system is off
    1011                 :            : ** warnfon: ready to start a new message
    1012                 :            : ** warnfcont: previous message is to be continued
    1013                 :            : */
    1014                 :            : static void warnfoff (void *ud, const char *message, int tocont);
    1015                 :            : static void warnfon (void *ud, const char *message, int tocont);
    1016                 :            : static void warnfcont (void *ud, const char *message, int tocont);
    1017                 :            : 
    1018                 :            : 
    1019                 :            : /*
    1020                 :            : ** Check whether message is a control message. If so, execute the
    1021                 :            : ** control or ignore it if unknown.
    1022                 :            : */
    1023                 :          0 : static int checkcontrol (lua_State *L, const char *message, int tocont) {
    1024   [ #  #  #  # ]:          0 :   if (tocont || *(message++) != '@')  /* not a control message? */
    1025                 :          0 :     return 0;
    1026                 :            :   else {
    1027         [ #  # ]:          0 :     if (strcmp(message, "off") == 0)
    1028                 :          0 :       lua_setwarnf(L, warnfoff, L);  /* turn warnings off */
    1029         [ #  # ]:          0 :     else if (strcmp(message, "on") == 0)
    1030                 :          0 :       lua_setwarnf(L, warnfon, L);   /* turn warnings on */
    1031                 :          0 :     return 1;  /* it was a control message */
    1032                 :            :   }
    1033                 :          0 : }
    1034                 :            : 
    1035                 :            : 
    1036                 :          0 : static void warnfoff (void *ud, const char *message, int tocont) {
    1037                 :          0 :   checkcontrol((lua_State *)ud, message, tocont);
    1038                 :          0 : }
    1039                 :            : 
    1040                 :            : 
    1041                 :            : /*
    1042                 :            : ** Writes the message and handle 'tocont', finishing the message
    1043                 :            : ** if needed and setting the next warn function.
    1044                 :            : */
    1045                 :          0 : static void warnfcont (void *ud, const char *message, int tocont) {
    1046                 :          0 :   lua_State *L = (lua_State *)ud;
    1047                 :          0 :   lua_writestringerror("%s", message);  /* write message */
    1048         [ #  # ]:          0 :   if (tocont)  /* not the last part? */
    1049                 :          0 :     lua_setwarnf(L, warnfcont, L);  /* to be continued */
    1050                 :            :   else {  /* last part */
    1051                 :          0 :     lua_writestringerror("%s", "\n");  /* finish message with end-of-line */
    1052                 :          0 :     lua_setwarnf(L, warnfon, L);  /* next call is a new message */
    1053                 :            :   }
    1054                 :          0 : }
    1055                 :            : 
    1056                 :            : 
    1057                 :          0 : static void warnfon (void *ud, const char *message, int tocont) {
    1058         [ #  # ]:          0 :   if (checkcontrol((lua_State *)ud, message, tocont))  /* control message? */
    1059                 :          0 :     return;  /* nothing else to be done */
    1060                 :          0 :   lua_writestringerror("%s", "Lua warning: ");  /* start a new warning */
    1061                 :          0 :   warnfcont(ud, message, tocont);  /* finish processing */
    1062                 :          0 : }
    1063                 :            : 
    1064                 :            : 
    1065                 :        810 : LUALIB_API lua_State *luaL_newstate (void) {
    1066                 :        810 :   lua_State *L = lua_newstate(l_alloc, NULL);
    1067         [ +  - ]:        810 :   if (L) {
    1068                 :        810 :     lua_atpanic(L, &panic);
    1069                 :        810 :     lua_setwarnf(L, warnfoff, L);  /* default is warnings off */
    1070                 :        810 :   }
    1071                 :        810 :   return L;
    1072                 :            : }
    1073                 :            : 
    1074                 :            : 
    1075                 :       8021 : LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
    1076                 :       8021 :   lua_Number v = lua_version(L);
    1077         [ -  + ]:       8021 :   if (sz != LUAL_NUMSIZES)  /* check numeric types */
    1078                 :          0 :     luaL_error(L, "core and library have incompatible numeric types");
    1079         [ -  + ]:       8021 :   else if (v != ver)
    1080                 :          0 :     luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f",
    1081                 :          0 :                   (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)v);
    1082                 :       8021 : }
    1083                 :            : 

Generated by: LCOV version 1.15