zombiezen.com/go/lua@v0.0.0-20231013005828-290725fb9140/internal/lua54/lauxlib.c (about)

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