LCOV - code coverage report
Current view: top level - src - lauxlib.c Coverage Total Hit
Test: Lua 5.2.4 Lines: 83.6 % 489 409
Test Date: 2024-04-28 10:23:12
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              : ** $Id: lauxlib.c,v 1.248.1.1 2013/04/12 18:48:47 roberto Exp $
       3              : ** Auxiliary functions for building Lua libraries
       4              : ** See Copyright Notice in lua.h
       5              : */
       6              : 
       7              : 
       8              : #include <errno.h>
       9              : #include <stdarg.h>
      10              : #include <stdio.h>
      11              : #include <stdlib.h>
      12              : #include <string.h>
      13              : 
      14              : 
      15              : /* This file uses only the official API of Lua.
      16              : ** Any function declared here could be written as an application function.
      17              : */
      18              : 
      19              : #define lauxlib_c
      20              : #define LUA_LIB
      21              : 
      22              : #include "lua.h"
      23              : 
      24              : #include "lauxlib.h"
      25              : 
      26              : 
      27              : /*
      28              : ** {======================================================
      29              : ** Traceback
      30              : ** =======================================================
      31              : */
      32              : 
      33              : 
      34              : #define LEVELS1 12      /* size of the first part of the stack */
      35              : #define LEVELS2 10      /* size of the second part of the stack */
      36              : 
      37              : 
      38              : 
      39              : /*
      40              : ** search for 'objidx' in table at index -1.
      41              : ** return 1 + string at top if find a good name.
      42              : */
      43         1000 : static int findfield (lua_State *L, int objidx, int level) {
      44         1000 :   if (level == 0 || !lua_istable(L, -1))
      45          950 :     return 0;  /* not found */
      46           50 :   lua_pushnil(L);  /* start 'next' loop */
      47         1058 :   while (lua_next(L, -2)) {  /* for each pair in table */
      48         1008 :     if (lua_type(L, -2) == LUA_TSTRING) {  /* ignore non-string keys */
      49          996 :       if (lua_rawequal(L, objidx, -1)) {  /* found object? */
      50            0 :         lua_pop(L, 1);  /* remove value (but keep name) */
      51            0 :         return 1;
      52              :       }
      53          996 :       else if (findfield(L, objidx, level - 1)) {  /* try recursively */
      54            0 :         lua_remove(L, -2);  /* remove table (but keep name) */
      55            0 :         lua_pushliteral(L, ".");
      56            0 :         lua_insert(L, -2);  /* place '.' between the two names */
      57            0 :         lua_concat(L, 3);
      58            0 :         return 1;
      59              :       }
      60              :     }
      61         1008 :     lua_pop(L, 1);  /* remove value */
      62              :   }
      63           50 :   return 0;  /* not found */
      64              : }
      65              : 
      66              : 
      67            4 : static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
      68            4 :   int top = lua_gettop(L);
      69            4 :   lua_getinfo(L, "f", ar);  /* push function */
      70            4 :   lua_pushglobaltable(L);
      71            4 :   if (findfield(L, top + 1, 2)) {
      72            0 :     lua_copy(L, -1, top + 1);  /* move name to proper place */
      73            0 :     lua_pop(L, 2);  /* remove pushed values */
      74            0 :     return 1;
      75              :   }
      76              :   else {
      77            4 :     lua_settop(L, top);  /* remove function and global table */
      78            4 :     return 0;
      79              :   }
      80              : }
      81              : 
      82              : 
      83           10 : static void pushfuncname (lua_State *L, lua_Debug *ar) {
      84           10 :   if (*ar->namewhat != '\0')  /* is there a name? */
      85            2 :     lua_pushfstring(L, "function " LUA_QS, ar->name);
      86            8 :   else if (*ar->what == 'm')  /* main? */
      87            4 :       lua_pushliteral(L, "main chunk");
      88            4 :   else if (*ar->what == 'C') {
      89            4 :     if (pushglobalfuncname(L, ar)) {
      90            0 :       lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1));
      91            0 :       lua_remove(L, -2);  /* remove name */
      92              :     }
      93              :     else
      94            4 :       lua_pushliteral(L, "?");
      95              :   }
      96              :   else
      97            0 :     lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
      98           10 : }
      99              : 
     100              : 
     101            4 : static int countlevels (lua_State *L) {
     102              :   lua_Debug ar;
     103            4 :   int li = 1, le = 1;
     104              :   /* find an upper bound */
     105           12 :   while (lua_getstack(L, le, &ar)) { li = le; le *= 2; }
     106              :   /* do a binary search */
     107           10 :   while (li < le) {
     108            6 :     int m = (li + le)/2;
     109            6 :     if (lua_getstack(L, m, &ar)) li = m + 1;
     110            2 :     else le = m;
     111              :   }
     112            4 :   return le - 1;
     113              : }
     114              : 
     115              : 
     116            4 : LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1,
     117              :                                 const char *msg, int level) {
     118              :   lua_Debug ar;
     119            4 :   int top = lua_gettop(L);
     120            4 :   int numlevels = countlevels(L1);
     121            4 :   int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0;
     122            4 :   if (msg) lua_pushfstring(L, "%s\n", msg);
     123            4 :   lua_pushliteral(L, "stack traceback:");
     124           14 :   while (lua_getstack(L1, level++, &ar)) {
     125           10 :     if (level == mark) {  /* too many levels? */
     126            0 :       lua_pushliteral(L, "\n\t...");  /* add a '...' */
     127            0 :       level = numlevels - LEVELS2;  /* and skip to last ones */
     128              :     }
     129              :     else {
     130           10 :       lua_getinfo(L1, "Slnt", &ar);
     131           10 :       lua_pushfstring(L, "\n\t%s:", ar.short_src);
     132           10 :       if (ar.currentline > 0)
     133            4 :         lua_pushfstring(L, "%d:", ar.currentline);
     134           10 :       lua_pushliteral(L, " in ");
     135           10 :       pushfuncname(L, &ar);
     136           10 :       if (ar.istailcall)
     137            0 :         lua_pushliteral(L, "\n\t(...tail calls...)");
     138           10 :       lua_concat(L, lua_gettop(L) - top);
     139              :     }
     140              :   }
     141            4 :   lua_concat(L, lua_gettop(L) - top);
     142            4 : }
     143              : 
     144              : /* }====================================================== */
     145              : 
     146              : 
     147              : /*
     148              : ** {======================================================
     149              : ** Error-report functions
     150              : ** =======================================================
     151              : */
     152              : 
     153           48 : LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
     154              :   lua_Debug ar;
     155           48 :   if (!lua_getstack(L, 0, &ar))  /* no stack frame? */
     156            0 :     return luaL_error(L, "bad argument #%d (%s)", narg, extramsg);
     157           48 :   lua_getinfo(L, "n", &ar);
     158           48 :   if (strcmp(ar.namewhat, "method") == 0) {
     159            2 :     narg--;  /* do not count `self' */
     160            2 :     if (narg == 0)  /* error is in the self argument itself? */
     161            0 :       return luaL_error(L, "calling " LUA_QS " on bad self (%s)",
     162              :                            ar.name, extramsg);
     163              :   }
     164           48 :   if (ar.name == NULL)
     165            0 :     ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?";
     166           48 :   return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
     167              :                         narg, ar.name, extramsg);
     168              : }
     169              : 
     170              : 
     171           13 : static int typeerror (lua_State *L, int narg, const char *tname) {
     172           13 :   const char *msg = lua_pushfstring(L, "%s expected, got %s",
     173              :                                     tname, luaL_typename(L, narg));
     174           13 :   return luaL_argerror(L, narg, msg);
     175              : }
     176              : 
     177              : 
     178           13 : static void tag_error (lua_State *L, int narg, int tag) {
     179           13 :   typeerror(L, narg, lua_typename(L, tag));
     180            0 : }
     181              : 
     182              : 
     183          150 : LUALIB_API void luaL_where (lua_State *L, int level) {
     184              :   lua_Debug ar;
     185          150 :   if (lua_getstack(L, level, &ar)) {  /* check function at level */
     186          150 :     lua_getinfo(L, "Sl", &ar);  /* get info about it */
     187          150 :     if (ar.currentline > 0) {  /* is there info? */
     188          100 :       lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
     189          100 :       return;
     190              :     }
     191              :   }
     192           50 :   lua_pushliteral(L, "");  /* else, no information available... */
     193              : }
     194              : 
     195              : 
     196          141 : LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
     197              :   va_list argp;
     198          141 :   va_start(argp, fmt);
     199          141 :   luaL_where(L, 1);
     200          141 :   lua_pushvfstring(L, fmt, argp);
     201          141 :   va_end(argp);
     202          141 :   lua_concat(L, 2);
     203          141 :   return lua_error(L);
     204              : }
     205              : 
     206              : 
     207          102 : LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
     208          102 :   int en = errno;  /* calls to Lua API may change this value */
     209          102 :   if (stat) {
     210           96 :     lua_pushboolean(L, 1);
     211           96 :     return 1;
     212              :   }
     213              :   else {
     214            6 :     lua_pushnil(L);
     215            6 :     if (fname)
     216            5 :       lua_pushfstring(L, "%s: %s", fname, strerror(en));
     217              :     else
     218            1 :       lua_pushstring(L, strerror(en));
     219            6 :     lua_pushinteger(L, en);
     220            6 :     return 3;
     221              :   }
     222              : }
     223              : 
     224              : 
     225              : #if !defined(inspectstat)       /* { */
     226              : 
     227              : #if defined(LUA_USE_POSIX)
     228              : 
     229              : #include <sys/wait.h>
     230              : 
     231              : /*
     232              : ** use appropriate macros to interpret 'pclose' return status
     233              : */
     234              : #define inspectstat(stat,what)  \
     235              :    if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \
     236              :    else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; }
     237              : 
     238              : #else
     239              : 
     240              : #define inspectstat(stat,what)  /* no op */
     241              : 
     242              : #endif
     243              : 
     244              : #endif                          /* } */
     245              : 
     246              : 
     247           67 : LUALIB_API int luaL_execresult (lua_State *L, int stat) {
     248           67 :   const char *what = "exit";  /* type of termination */
     249           67 :   if (stat == -1)  /* error? */
     250            0 :     return luaL_fileresult(L, 0, NULL);
     251              :   else {
     252           67 :     inspectstat(stat, what);  /* interpret result */
     253           67 :     if (*what == 'e' && stat == 0)  /* successful termination? */
     254           41 :       lua_pushboolean(L, 1);
     255              :     else
     256           26 :       lua_pushnil(L);
     257           67 :     lua_pushstring(L, what);
     258           67 :     lua_pushinteger(L, stat);
     259           67 :     return 3;  /* return true/nil,what,code */
     260              :   }
     261              : }
     262              : 
     263              : /* }====================================================== */
     264              : 
     265              : 
     266              : /*
     267              : ** {======================================================
     268              : ** Userdata's metatable manipulation
     269              : ** =======================================================
     270              : */
     271              : 
     272           86 : LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
     273           86 :   luaL_getmetatable(L, tname);  /* try to get metatable */
     274           86 :   if (!lua_isnil(L, -1))  /* name already in use? */
     275            0 :     return 0;  /* leave previous value on top, but return 0 */
     276           86 :   lua_pop(L, 1);
     277           86 :   lua_newtable(L);  /* create metatable */
     278           86 :   lua_pushvalue(L, -1);
     279           86 :   lua_setfield(L, LUA_REGISTRYINDEX, tname);  /* registry.name = metatable */
     280           86 :   return 1;
     281              : }
     282              : 
     283              : 
     284          384 : LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) {
     285          384 :   luaL_getmetatable(L, tname);
     286          384 :   lua_setmetatable(L, -2);
     287          384 : }
     288              : 
     289              : 
     290         1357 : LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) {
     291         1357 :   void *p = lua_touserdata(L, ud);
     292         1357 :   if (p != NULL) {  /* value is a userdata? */
     293         1356 :     if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */
     294         1356 :       luaL_getmetatable(L, tname);  /* get correct metatable */
     295         1356 :       if (!lua_rawequal(L, -1, -2))  /* not the same? */
     296            0 :         p = NULL;  /* value is a userdata with wrong metatable */
     297         1356 :       lua_pop(L, 2);  /* remove both metatables */
     298         1356 :       return p;
     299              :     }
     300              :   }
     301            1 :   return NULL;  /* value is not a userdata with a metatable */
     302              : }
     303              : 
     304              : 
     305         1348 : LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
     306         1348 :   void *p = luaL_testudata(L, ud, tname);
     307         1348 :   if (p == NULL) typeerror(L, ud, tname);
     308         1348 :   return p;
     309              : }
     310              : 
     311              : /* }====================================================== */
     312              : 
     313              : 
     314              : /*
     315              : ** {======================================================
     316              : ** Argument check functions
     317              : ** =======================================================
     318              : */
     319              : 
     320           24 : LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
     321              :                                  const char *const lst[]) {
     322           24 :   const char *name = (def) ? luaL_optstring(L, narg, def) :
     323            3 :                              luaL_checkstring(L, narg);
     324              :   int i;
     325          116 :   for (i=0; lst[i]; i++)
     326          114 :     if (strcmp(lst[i], name) == 0)
     327           22 :       return i;
     328            2 :   return luaL_argerror(L, narg,
     329              :                        lua_pushfstring(L, "invalid option " LUA_QS, name));
     330              : }
     331              : 
     332              : 
     333         7657 : LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
     334              :   /* keep some extra space to run error routines, if needed */
     335         7657 :   const int extra = LUA_MINSTACK;
     336         7657 :   if (!lua_checkstack(L, space + extra)) {
     337            0 :     if (msg)
     338            0 :       luaL_error(L, "stack overflow (%s)", msg);
     339              :     else
     340            0 :       luaL_error(L, "stack overflow");
     341              :   }
     342         7657 : }
     343              : 
     344              : 
     345        70401 : LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
     346        70401 :   if (lua_type(L, narg) != t)
     347            7 :     tag_error(L, narg, t);
     348        70394 : }
     349              : 
     350              : 
     351         5100 : LUALIB_API void luaL_checkany (lua_State *L, int narg) {
     352         5100 :   if (lua_type(L, narg) == LUA_TNONE)
     353            3 :     luaL_argerror(L, narg, "value expected");
     354         5097 : }
     355              : 
     356              : 
     357        20676 : LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
     358        20676 :   const char *s = lua_tolstring(L, narg, len);
     359        20676 :   if (!s) tag_error(L, narg, LUA_TSTRING);
     360        20674 :   return s;
     361              : }
     362              : 
     363              : 
     364        12610 : LUALIB_API const char *luaL_optlstring (lua_State *L, int narg,
     365              :                                         const char *def, size_t *len) {
     366        12610 :   if (lua_isnoneornil(L, narg)) {
     367          531 :     if (len)
     368           11 :       *len = (def ? strlen(def) : 0);
     369          531 :     return def;
     370              :   }
     371        12079 :   else return luaL_checklstring(L, narg, len);
     372              : }
     373              : 
     374              : 
     375          149 : LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
     376              :   int isnum;
     377          149 :   lua_Number d = lua_tonumberx(L, narg, &isnum);
     378          149 :   if (!isnum)
     379            3 :     tag_error(L, narg, LUA_TNUMBER);
     380          146 :   return d;
     381              : }
     382              : 
     383              : 
     384            2 : LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
     385            2 :   return luaL_opt(L, luaL_checknumber, narg, def);
     386              : }
     387              : 
     388              : 
     389        59103 : LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
     390              :   int isnum;
     391        59103 :   lua_Integer d = lua_tointegerx(L, narg, &isnum);
     392        59103 :   if (!isnum)
     393            1 :     tag_error(L, narg, LUA_TNUMBER);
     394        59102 :   return d;
     395              : }
     396              : 
     397              : 
     398           33 : LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) {
     399              :   int isnum;
     400           33 :   lua_Unsigned d = lua_tounsignedx(L, narg, &isnum);
     401           33 :   if (!isnum)
     402            0 :     tag_error(L, narg, LUA_TNUMBER);
     403           33 :   return d;
     404              : }
     405              : 
     406              : 
     407        19035 : LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
     408              :                                                       lua_Integer def) {
     409        19035 :   return luaL_opt(L, luaL_checkinteger, narg, def);
     410              : }
     411              : 
     412              : 
     413            0 : LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg,
     414              :                                                         lua_Unsigned def) {
     415            0 :   return luaL_opt(L, luaL_checkunsigned, narg, def);
     416              : }
     417              : 
     418              : /* }====================================================== */
     419              : 
     420              : 
     421              : /*
     422              : ** {======================================================
     423              : ** Generic Buffer manipulation
     424              : ** =======================================================
     425              : */
     426              : 
     427              : /*
     428              : ** check whether buffer is using a userdata on the stack as a temporary
     429              : ** buffer
     430              : */
     431              : #define buffonstack(B)  ((B)->b != (B)->initb)
     432              : 
     433              : 
     434              : /*
     435              : ** returns a pointer to a free area with at least 'sz' bytes
     436              : */
     437       156642 : LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
     438       156642 :   lua_State *L = B->L;
     439       156642 :   if (B->size - B->n < sz) {  /* not enough space? */
     440              :     char *newbuff;
     441            5 :     size_t newsize = B->size * 2;  /* double buffer size */
     442            5 :     if (newsize - B->n < sz)  /* not big enough? */
     443            5 :       newsize = B->n + sz;
     444            5 :     if (newsize < B->n || newsize - B->n < sz)
     445            0 :       luaL_error(L, "buffer too large");
     446              :     /* create larger buffer */
     447            5 :     newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char));
     448              :     /* move content to new buffer */
     449            5 :     memcpy(newbuff, B->b, B->n * sizeof(char));
     450            5 :     if (buffonstack(B))
     451            0 :       lua_remove(L, -2);  /* remove old buffer */
     452            5 :     B->b = newbuff;
     453            5 :     B->size = newsize;
     454              :   }
     455       156642 :   return &B->b[B->n];
     456              : }
     457              : 
     458              : 
     459       156318 : LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
     460       156318 :   char *b = luaL_prepbuffsize(B, l);
     461       156318 :   memcpy(b, s, l * sizeof(char));
     462       156318 :   luaL_addsize(B, l);
     463       156318 : }
     464              : 
     465              : 
     466         3379 : LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
     467         3379 :   luaL_addlstring(B, s, strlen(s));
     468         3379 : }
     469              : 
     470              : 
     471        14302 : LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
     472        14302 :   lua_State *L = B->L;
     473        14302 :   lua_pushlstring(L, B->b, B->n);
     474        14302 :   if (buffonstack(B))
     475            5 :     lua_remove(L, -2);  /* remove old buffer */
     476        14302 : }
     477              : 
     478              : 
     479           26 : LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) {
     480           26 :   luaL_addsize(B, sz);
     481           26 :   luaL_pushresult(B);
     482           26 : }
     483              : 
     484              : 
     485        82339 : LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
     486        82339 :   lua_State *L = B->L;
     487              :   size_t l;
     488        82339 :   const char *s = lua_tolstring(L, -1, &l);
     489        82339 :   if (buffonstack(B))
     490            0 :     lua_insert(L, -2);  /* put value below buffer */
     491        82339 :   luaL_addlstring(B, s, l);
     492        82339 :   lua_remove(L, (buffonstack(B)) ? -2 : -1);  /* remove value */
     493        82339 : }
     494              : 
     495              : 
     496        14521 : LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
     497        14521 :   B->L = L;
     498        14521 :   B->b = B->initb;
     499        14521 :   B->n = 0;
     500        14521 :   B->size = LUAL_BUFFERSIZE;
     501        14521 : }
     502              : 
     503              : 
     504           28 : LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) {
     505           28 :   luaL_buffinit(L, B);
     506           28 :   return luaL_prepbuffsize(B, sz);
     507              : }
     508              : 
     509              : /* }====================================================== */
     510              : 
     511              : 
     512              : /*
     513              : ** {======================================================
     514              : ** Reference system
     515              : ** =======================================================
     516              : */
     517              : 
     518              : /* index of free-list header */
     519              : #define freelist        0
     520              : 
     521              : 
     522            0 : LUALIB_API int luaL_ref (lua_State *L, int t) {
     523              :   int ref;
     524            0 :   if (lua_isnil(L, -1)) {
     525            0 :     lua_pop(L, 1);  /* remove from stack */
     526            0 :     return LUA_REFNIL;  /* `nil' has a unique fixed reference */
     527              :   }
     528            0 :   t = lua_absindex(L, t);
     529            0 :   lua_rawgeti(L, t, freelist);  /* get first free element */
     530            0 :   ref = (int)lua_tointeger(L, -1);  /* ref = t[freelist] */
     531            0 :   lua_pop(L, 1);  /* remove it from stack */
     532            0 :   if (ref != 0) {  /* any free element? */
     533            0 :     lua_rawgeti(L, t, ref);  /* remove it from list */
     534            0 :     lua_rawseti(L, t, freelist);  /* (t[freelist] = t[ref]) */
     535              :   }
     536              :   else  /* no free elements */
     537            0 :     ref = (int)lua_rawlen(L, t) + 1;  /* get a new reference */
     538            0 :   lua_rawseti(L, t, ref);
     539            0 :   return ref;
     540              : }
     541              : 
     542              : 
     543            0 : LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
     544            0 :   if (ref >= 0) {
     545            0 :     t = lua_absindex(L, t);
     546            0 :     lua_rawgeti(L, t, freelist);
     547            0 :     lua_rawseti(L, t, ref);  /* t[ref] = t[freelist] */
     548            0 :     lua_pushinteger(L, ref);
     549            0 :     lua_rawseti(L, t, freelist);  /* t[freelist] = ref */
     550              :   }
     551            0 : }
     552              : 
     553              : /* }====================================================== */
     554              : 
     555              : 
     556              : /*
     557              : ** {======================================================
     558              : ** Load functions
     559              : ** =======================================================
     560              : */
     561              : 
     562              : typedef struct LoadF {
     563              :   int n;  /* number of pre-read characters */
     564              :   FILE *f;  /* file being read */
     565              :   char buff[LUAL_BUFFERSIZE];  /* area for reading file */
     566              : } LoadF;
     567              : 
     568              : 
     569          549 : static const char *getF (lua_State *L, void *ud, size_t *size) {
     570          549 :   LoadF *lf = (LoadF *)ud;
     571              :   (void)L;  /* not used */
     572          549 :   if (lf->n > 0) {  /* are there pre-read characters to be read? */
     573          185 :     *size = lf->n;  /* return them (chars already in buffer) */
     574          185 :     lf->n = 0;  /* no more pre-read characters */
     575              :   }
     576              :   else {  /* read a block from file */
     577              :     /* 'fread' can return > 0 *and* set the EOF flag. If next call to
     578              :        'getF' called 'fread', it might still wait for user input.
     579              :        The next check avoids this problem. */
     580          364 :     if (feof(lf->f)) return NULL;
     581          195 :     *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);  /* read block */
     582              :   }
     583          380 :   return lf->buff;
     584              : }
     585              : 
     586              : 
     587            4 : static int errfile (lua_State *L, const char *what, int fnameindex) {
     588            4 :   const char *serr = strerror(errno);
     589            4 :   const char *filename = lua_tostring(L, fnameindex) + 1;
     590            4 :   lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
     591            4 :   lua_remove(L, fnameindex);
     592            4 :   return LUA_ERRFILE;
     593              : }
     594              : 
     595              : 
     596          197 : static int skipBOM (LoadF *lf) {
     597          197 :   const char *p = "\xEF\xBB\xBF";  /* Utf8 BOM mark */
     598              :   int c;
     599          197 :   lf->n = 0;
     600              :   do {
     601          203 :     c = getc(lf->f);
     602          203 :     if (c == EOF || c != *(const unsigned char *)p++) return c;
     603            9 :     lf->buff[lf->n++] = c;  /* to be read by the parser */
     604            9 :   } while (*p != '\0');
     605            3 :   lf->n = 0;  /* prefix matched; discard it */
     606            3 :   return getc(lf->f);  /* return next character */
     607              : }
     608              : 
     609              : 
     610              : /*
     611              : ** reads the first character of file 'f' and skips an optional BOM mark
     612              : ** in its beginning plus its first line if it starts with '#'. Returns
     613              : ** true if it skipped the first line.  In any case, '*cp' has the
     614              : ** first "valid" character of the file (after the optional BOM and
     615              : ** a first-line comment).
     616              : */
     617          197 : static int skipcomment (LoadF *lf, int *cp) {
     618          197 :   int c = *cp = skipBOM(lf);
     619          197 :   if (c == '#') {  /* first line is a comment (Unix exec. file)? */
     620              :     do {  /* skip first line */
     621          750 :       c = getc(lf->f);
     622          750 :     } while (c != EOF && c != '\n') ;
     623           50 :     *cp = getc(lf->f);  /* skip end-of-line, if present */
     624           50 :     return 1;  /* there was a comment */
     625              :   }
     626          147 :   else return 0;  /* no comment */
     627              : }
     628              : 
     629              : 
     630          189 : LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
     631              :                                              const char *mode) {
     632              :   LoadF lf;
     633              :   int status, readstatus;
     634              :   int c;
     635          189 :   int fnameindex = lua_gettop(L) + 1;  /* index of filename on the stack */
     636          189 :   if (filename == NULL) {
     637            6 :     lua_pushliteral(L, "=stdin");
     638            6 :     lf.f = stdin;
     639              :   }
     640              :   else {
     641          183 :     lua_pushfstring(L, "@%s", filename);
     642          183 :     lf.f = fopen(filename, "r");
     643          183 :     if (lf.f == NULL) return errfile(L, "open", fnameindex);
     644              :   }
     645          185 :   if (skipcomment(&lf, &c))  /* read initial portion */
     646           50 :     lf.buff[lf.n++] = '\n';  /* add line to correct line numbers */
     647          185 :   if (c == LUA_SIGNATURE[0] && filename) {  /* binary file? */
     648           12 :     lf.f = freopen(filename, "rb", lf.f);  /* reopen in binary mode */
     649           12 :     if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
     650           12 :     skipcomment(&lf, &c);  /* re-read initial portion */
     651              :   }
     652          185 :   if (c != EOF)
     653          185 :     lf.buff[lf.n++] = c;  /* 'c' is the first character of the stream */
     654          185 :   status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode);
     655          185 :   readstatus = ferror(lf.f);
     656          185 :   if (filename) fclose(lf.f);  /* close file (even in case of errors) */
     657          185 :   if (readstatus) {
     658            0 :     lua_settop(L, fnameindex);  /* ignore results from `lua_load' */
     659            0 :     return errfile(L, "read", fnameindex);
     660              :   }
     661          185 :   lua_remove(L, fnameindex);
     662          185 :   return status;
     663              : }
     664              : 
     665              : 
     666              : typedef struct LoadS {
     667              :   const char *s;
     668              :   size_t size;
     669              : } LoadS;
     670              : 
     671              : 
     672          624 : static const char *getS (lua_State *L, void *ud, size_t *size) {
     673          624 :   LoadS *ls = (LoadS *)ud;
     674              :   (void)L;  /* not used */
     675          624 :   if (ls->size == 0) return NULL;
     676          322 :   *size = ls->size;
     677          322 :   ls->size = 0;
     678          322 :   return ls->s;
     679              : }
     680              : 
     681              : 
     682          322 : LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size,
     683              :                                  const char *name, const char *mode) {
     684              :   LoadS ls;
     685          322 :   ls.s = buff;
     686          322 :   ls.size = size;
     687          322 :   return lua_load(L, getS, &ls, name, mode);
     688              : }
     689              : 
     690              : 
     691            0 : LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
     692            0 :   return luaL_loadbuffer(L, s, strlen(s), s);
     693              : }
     694              : 
     695              : /* }====================================================== */
     696              : 
     697              : 
     698              : 
     699        10400 : LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
     700        10400 :   if (!lua_getmetatable(L, obj))  /* no metatable? */
     701         7890 :     return 0;
     702         2510 :   lua_pushstring(L, event);
     703         2510 :   lua_rawget(L, -2);
     704         2510 :   if (lua_isnil(L, -1)) {
     705         2460 :     lua_pop(L, 2);  /* remove metatable and metafield */
     706         2460 :     return 0;
     707              :   }
     708              :   else {
     709           50 :     lua_remove(L, -2);  /* remove only metatable */
     710           50 :     return 1;
     711              :   }
     712              : }
     713              : 
     714              : 
     715         4357 : LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
     716         4357 :   obj = lua_absindex(L, obj);
     717         4357 :   if (!luaL_getmetafield(L, obj, event))  /* no metafield? */
     718         4311 :     return 0;
     719           46 :   lua_pushvalue(L, obj);
     720           46 :   lua_call(L, 1, 1);
     721           45 :   return 1;
     722              : }
     723              : 
     724              : 
     725        18039 : LUALIB_API int luaL_len (lua_State *L, int idx) {
     726              :   int l;
     727              :   int isnum;
     728        18039 :   lua_len(L, idx);
     729        18039 :   l = (int)lua_tointegerx(L, -1, &isnum);
     730        18039 :   if (!isnum)
     731            1 :     luaL_error(L, "object length is not a number");
     732        18038 :   lua_pop(L, 1);  /* remove object */
     733        18038 :   return l;
     734              : }
     735              : 
     736              : 
     737         4355 : LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
     738         4355 :   if (!luaL_callmeta(L, idx, "__tostring")) {  /* no metafield? */
     739         4310 :     switch (lua_type(L, idx)) {
     740         4298 :       case LUA_TNUMBER:
     741              :       case LUA_TSTRING:
     742         4298 :         lua_pushvalue(L, idx);
     743         4298 :         break;
     744            3 :       case LUA_TBOOLEAN:
     745            3 :         lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false"));
     746            3 :         break;
     747            4 :       case LUA_TNIL:
     748            4 :         lua_pushliteral(L, "nil");
     749            4 :         break;
     750            5 :       default:
     751            5 :         lua_pushfstring(L, "%s: %p", luaL_typename(L, idx),
     752              :                                             lua_topointer(L, idx));
     753            5 :         break;
     754              :     }
     755              :   }
     756         4354 :   return lua_tolstring(L, -1, len);
     757              : }
     758              : 
     759              : 
     760              : /*
     761              : ** {======================================================
     762              : ** Compatibility with 5.1 module functions
     763              : ** =======================================================
     764              : */
     765              : #if defined(LUA_COMPAT_MODULE)
     766              : 
     767            4 : static const char *luaL_findtable (lua_State *L, int idx,
     768              :                                    const char *fname, int szhint) {
     769              :   const char *e;
     770            4 :   if (idx) lua_pushvalue(L, idx);
     771              :   do {
     772            4 :     e = strchr(fname, '.');
     773            4 :     if (e == NULL) e = fname + strlen(fname);
     774            4 :     lua_pushlstring(L, fname, e - fname);
     775            4 :     lua_rawget(L, -2);
     776            4 :     if (lua_isnil(L, -1)) {  /* no such field? */
     777            2 :       lua_pop(L, 1);  /* remove this nil */
     778            2 :       lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
     779            2 :       lua_pushlstring(L, fname, e - fname);
     780            2 :       lua_pushvalue(L, -2);
     781            2 :       lua_settable(L, -4);  /* set new table into field */
     782              :     }
     783            2 :     else if (!lua_istable(L, -1)) {  /* field has a non-table value? */
     784            0 :       lua_pop(L, 2);  /* remove table and value */
     785            0 :       return fname;  /* return problematic part of the name */
     786              :     }
     787            4 :     lua_remove(L, -2);  /* remove previous table */
     788            4 :     fname = e + 1;
     789            4 :   } while (*e == '.');
     790            4 :   return NULL;
     791              : }
     792              : 
     793              : 
     794              : /*
     795              : ** Count number of elements in a luaL_Reg list.
     796              : */
     797            0 : static int libsize (const luaL_Reg *l) {
     798            0 :   int size = 0;
     799            0 :   for (; l && l->name; l++) size++;
     800            0 :   return size;
     801              : }
     802              : 
     803              : 
     804              : /*
     805              : ** Find or create a module table with a given name. The function
     806              : ** first looks at the _LOADED table and, if that fails, try a
     807              : ** global variable with that name. In any case, leaves on the stack
     808              : ** the module table.
     809              : */
     810            2 : LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname,
     811              :                                  int sizehint) {
     812            2 :   luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);  /* get _LOADED table */
     813            2 :   lua_getfield(L, -1, modname);  /* get _LOADED[modname] */
     814            2 :   if (!lua_istable(L, -1)) {  /* not found? */
     815            2 :     lua_pop(L, 1);  /* remove previous result */
     816              :     /* try global variable (and create one if it does not exist) */
     817            2 :     lua_pushglobaltable(L);
     818            2 :     if (luaL_findtable(L, 0, modname, sizehint) != NULL)
     819            0 :       luaL_error(L, "name conflict for module " LUA_QS, modname);
     820            2 :     lua_pushvalue(L, -1);
     821            2 :     lua_setfield(L, -3, modname);  /* _LOADED[modname] = new table */
     822              :   }
     823            2 :   lua_remove(L, -2);  /* remove _LOADED table */
     824            2 : }
     825              : 
     826              : 
     827            0 : LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
     828              :                                const luaL_Reg *l, int nup) {
     829            0 :   luaL_checkversion(L);
     830            0 :   if (libname) {
     831            0 :     luaL_pushmodule(L, libname, libsize(l));  /* get/create library table */
     832            0 :     lua_insert(L, -(nup + 1));  /* move library table to below upvalues */
     833              :   }
     834            0 :   if (l)
     835            0 :     luaL_setfuncs(L, l, nup);
     836              :   else
     837            0 :     lua_pop(L, nup);  /* remove upvalues */
     838            0 : }
     839              : 
     840              : #endif
     841              : /* }====================================================== */
     842              : 
     843              : /*
     844              : ** set functions from list 'l' into table at top - 'nup'; each
     845              : ** function gets the 'nup' elements at the top as upvalues.
     846              : ** Returns with only the table at the stack.
     847              : */
     848         1032 : LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
     849         1032 :   luaL_checkversion(L);
     850         1032 :   luaL_checkstack(L, nup, "too many upvalues");
     851        13244 :   for (; l->name != NULL; l++) {  /* fill the table with given functions */
     852              :     int i;
     853        12384 :     for (i = 0; i < nup; i++)  /* copy upvalues to the top */
     854          172 :       lua_pushvalue(L, -nup);
     855        12212 :     lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
     856        12212 :     lua_setfield(L, -(nup + 2), l->name);
     857              :   }
     858         1032 :   lua_pop(L, nup);  /* remove upvalues */
     859         1032 : }
     860              : 
     861              : 
     862              : /*
     863              : ** ensure that stack[idx][fname] has a table and push that table
     864              : ** into the stack
     865              : */
     866         1436 : LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) {
     867         1436 :   lua_getfield(L, idx, fname);
     868         1436 :   if (lua_istable(L, -1)) return 1;  /* table already there */
     869              :   else {
     870          259 :     lua_pop(L, 1);  /* remove previous result */
     871          259 :     idx = lua_absindex(L, idx);
     872          259 :     lua_newtable(L);
     873          259 :     lua_pushvalue(L, -1);  /* copy to be left at top */
     874          259 :     lua_setfield(L, idx, fname);  /* assign new table to field */
     875          259 :     return 0;  /* false, because did not find table there */
     876              :   }
     877              : }
     878              : 
     879              : 
     880              : /*
     881              : ** stripped-down 'require'. Calls 'openf' to open a module,
     882              : ** registers the result in 'package.loaded' table and, if 'glb'
     883              : ** is true, also registers the result in the global table.
     884              : ** Leaves resulting module on the top.
     885              : */
     886          860 : LUALIB_API void luaL_requiref (lua_State *L, const char *modname,
     887              :                                lua_CFunction openf, int glb) {
     888          860 :   lua_pushcfunction(L, openf);
     889          860 :   lua_pushstring(L, modname);  /* argument to open function */
     890          860 :   lua_call(L, 1, 1);  /* open module */
     891          860 :   luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
     892          860 :   lua_pushvalue(L, -2);  /* make copy of module (call result) */
     893          860 :   lua_setfield(L, -2, modname);  /* _LOADED[modname] = module */
     894          860 :   lua_pop(L, 1);  /* remove _LOADED table */
     895          860 :   if (glb) {
     896          860 :     lua_pushvalue(L, -1);  /* copy of 'mod' */
     897          860 :     lua_setglobal(L, modname);  /* _G[modname] = module */
     898              :   }
     899          860 : }
     900              : 
     901              : 
     902         1807 : LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
     903              :                                                                const char *r) {
     904              :   const char *wild;
     905         1807 :   size_t l = strlen(p);
     906              :   luaL_Buffer b;
     907         1807 :   luaL_buffinit(L, &b);
     908         3375 :   while ((wild = strstr(s, p)) != NULL) {
     909         1568 :     luaL_addlstring(&b, s, wild - s);  /* push prefix */
     910         1568 :     luaL_addstring(&b, r);  /* push replacement in place of pattern */
     911         1568 :     s = wild + l;  /* continue after `p' */
     912              :   }
     913         1807 :   luaL_addstring(&b, s);  /* push last suffix */
     914         1807 :   luaL_pushresult(&b);
     915         1807 :   return lua_tostring(L, -1);
     916              : }
     917              : 
     918              : 
     919       249823 : static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
     920              :   (void)ud; (void)osize;  /* not used */
     921       249823 :   if (nsize == 0) {
     922       107714 :     free(ptr);
     923       107714 :     return NULL;
     924              :   }
     925              :   else
     926       142109 :     return realloc(ptr, nsize);
     927              : }
     928              : 
     929              : 
     930            0 : static int panic (lua_State *L) {
     931            0 :   luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
     932              :                    lua_tostring(L, -1));
     933            0 :   return 0;  /* return to Lua to abort */
     934              : }
     935              : 
     936              : 
     937          104 : LUALIB_API lua_State *luaL_newstate (void) {
     938          104 :   lua_State *L = lua_newstate(l_alloc, NULL);
     939          104 :   if (L) lua_atpanic(L, &panic);
     940          104 :   return L;
     941              : }
     942              : 
     943              : 
     944         1118 : LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) {
     945         1118 :   const lua_Number *v = lua_version(L);
     946         1118 :   if (v != lua_version(NULL))
     947            0 :     luaL_error(L, "multiple Lua VMs detected");
     948         1118 :   else if (*v != ver)
     949            0 :     luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f",
     950              :                   ver, *v);
     951              :   /* check conversions number -> integer types */
     952         1118 :   lua_pushnumber(L, -(lua_Number)0x1234);
     953         2236 :   if (lua_tointeger(L, -1) != -0x1234 ||
     954         1118 :       lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234)
     955            0 :     luaL_error(L, "bad conversion number->int;"
     956              :                   " must recompile Lua with proper settings");
     957         1118 :   lua_pop(L, 1);
     958         1118 : }
     959              : 
        

Generated by: LCOV version 2.0-1