11d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
21d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** $Id: lauxlib.c,v 1.248 2013/03/21 13:54:57 roberto Exp $
31d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Auxiliary functions for building Lua libraries
41d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** See Copyright Notice in lua.h
51d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
61d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
71d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
81d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#include <errno.h>
91d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#include <stdarg.h>
101d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#include <stdio.h>
111d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#include <stdlib.h>
121d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#include <string.h>
131d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
141d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
151d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/* This file uses only the official API of Lua.
161d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Any function declared here could be written as an application function.
171d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
181d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
191d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#define lauxlib_c
201d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#define LUA_LIB
211d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
221d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#include "lua.h"
231d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
241d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#include "lauxlib.h"
251d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
261d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
271d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
281d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** {======================================================
291d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Traceback
301d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** =======================================================
311d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
321d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
331d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
341d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#define LEVELS1	12	/* size of the first part of the stack */
351d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#define LEVELS2	10	/* size of the second part of the stack */
361d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
371d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
381d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
391d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
401d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** search for 'objidx' in table at index -1.
411d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** return 1 + string at top if find a good name.
421d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
431d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic int findfield (lua_State *L, int objidx, int level) {
441d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (level == 0 || !lua_istable(L, -1))
451d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return 0;  /* not found */
461d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushnil(L);  /* start 'next' loop */
471d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  while (lua_next(L, -2)) {  /* for each pair in table */
481d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (lua_type(L, -2) == LUA_TSTRING) {  /* ignore non-string keys */
491d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      if (lua_rawequal(L, objidx, -1)) {  /* found object? */
501d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        lua_pop(L, 1);  /* remove value (but keep name) */
511d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        return 1;
521d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      }
531d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      else if (findfield(L, objidx, level - 1)) {  /* try recursively */
541d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        lua_remove(L, -2);  /* remove table (but keep name) */
551d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        lua_pushliteral(L, ".");
561d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        lua_insert(L, -2);  /* place '.' between the two names */
571d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        lua_concat(L, 3);
581d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        return 1;
591d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      }
601d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    }
611d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pop(L, 1);  /* remove value */
621d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
631d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return 0;  /* not found */
641d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
651d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
661d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
671d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
681d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int top = lua_gettop(L);
691d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_getinfo(L, "f", ar);  /* push function */
701d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushglobaltable(L);
711d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (findfield(L, top + 1, 2)) {
721d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_copy(L, -1, top + 1);  /* move name to proper place */
731d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pop(L, 2);  /* remove pushed values */
741d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return 1;
751d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
761d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else {
771d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_settop(L, top);  /* remove function and global table */
781d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return 0;
791d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
801d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
811d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
821d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
831d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic void pushfuncname (lua_State *L, lua_Debug *ar) {
841d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (*ar->namewhat != '\0')  /* is there a name? */
851d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushfstring(L, "function " LUA_QS, ar->name);
861d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else if (*ar->what == 'm')  /* main? */
871d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushliteral(L, "main chunk");
881d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else if (*ar->what == 'C') {
891d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (pushglobalfuncname(L, ar)) {
901d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1));
911d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_remove(L, -2);  /* remove name */
921d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    }
931d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    else
941d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushliteral(L, "?");
951d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
961d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else
971d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
981d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
991d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1001d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1011d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic int countlevels (lua_State *L) {
1021d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_Debug ar;
1031d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int li = 1, le = 1;
1041d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  /* find an upper bound */
1051d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  while (lua_getstack(L, le, &ar)) { li = le; le *= 2; }
1061d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  /* do a binary search */
1071d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  while (li < le) {
1081d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    int m = (li + le)/2;
1091d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (lua_getstack(L, m, &ar)) li = m + 1;
1101d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    else le = m;
1111d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
1121d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return le - 1;
1131d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
1141d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1151d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1161d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_traceback (lua_State *L, lua_State *L1,
1171d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                                const char *msg, int level) {
1181d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_Debug ar;
1191d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int top = lua_gettop(L);
1201d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int numlevels = countlevels(L1);
1211d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0;
1221d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (msg) lua_pushfstring(L, "%s\n", msg);
1231d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushliteral(L, "stack traceback:");
1241d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  while (lua_getstack(L1, level++, &ar)) {
1251d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (level == mark) {  /* too many levels? */
1261d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushliteral(L, "\n\t...");  /* add a '...' */
1271d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      level = numlevels - LEVELS2;  /* and skip to last ones */
1281d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    }
1291d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    else {
1301d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_getinfo(L1, "Slnt", &ar);
1311d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushfstring(L, "\n\t%s:", ar.short_src);
1321d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      if (ar.currentline > 0)
1331d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        lua_pushfstring(L, "%d:", ar.currentline);
1341d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushliteral(L, " in ");
1351d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      pushfuncname(L, &ar);
1361d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      if (ar.istailcall)
1371d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        lua_pushliteral(L, "\n\t(...tail calls...)");
1381d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_concat(L, lua_gettop(L) - top);
1391d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    }
1401d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
1411d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_concat(L, lua_gettop(L) - top);
1421d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
1431d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1441d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/* }====================================================== */
1451d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1461d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1471d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
1481d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** {======================================================
1491d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Error-report functions
1501d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** =======================================================
1511d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
1521d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1531d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
1541d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_Debug ar;
1551d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (!lua_getstack(L, 0, &ar))  /* no stack frame? */
1561d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return luaL_error(L, "bad argument #%d (%s)", narg, extramsg);
1571d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_getinfo(L, "n", &ar);
1581d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (strcmp(ar.namewhat, "method") == 0) {
1591d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    narg--;  /* do not count `self' */
1601d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (narg == 0)  /* error is in the self argument itself? */
1611d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      return luaL_error(L, "calling " LUA_QS " on bad self (%s)",
1621d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                           ar.name, extramsg);
1631d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
1641d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (ar.name == NULL)
1651d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?";
1661d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
1671d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                        narg, ar.name, extramsg);
1681d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
1691d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1701d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1711d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic int typeerror (lua_State *L, int narg, const char *tname) {
1721d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  const char *msg = lua_pushfstring(L, "%s expected, got %s",
1731d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                                    tname, luaL_typename(L, narg));
1741d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return luaL_argerror(L, narg, msg);
1751d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
1761d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1771d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1781d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic void tag_error (lua_State *L, int narg, int tag) {
1791d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  typeerror(L, narg, lua_typename(L, tag));
1801d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
1811d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1821d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1831d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_where (lua_State *L, int level) {
1841d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_Debug ar;
1851d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (lua_getstack(L, level, &ar)) {  /* check function at level */
1861d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_getinfo(L, "Sl", &ar);  /* get info about it */
1871d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (ar.currentline > 0) {  /* is there info? */
1881d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
1891d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      return;
1901d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    }
1911d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
1921d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushliteral(L, "");  /* else, no information available... */
1931d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
1941d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1951d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
1961d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
1971d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  va_list argp;
1981d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  va_start(argp, fmt);
1991d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_where(L, 1);
2001d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushvfstring(L, fmt, argp);
2011d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  va_end(argp);
2021d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_concat(L, 2);
2031d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return lua_error(L);
2041d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
2051d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2061d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2071d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
2081d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int en = errno;  /* calls to Lua API may change this value */
2091d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (stat) {
2101d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushboolean(L, 1);
2111d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return 1;
2121d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
2131d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else {
2141d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushnil(L);
2151d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (fname)
2161d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushfstring(L, "%s: %s", fname, strerror(en));
2171d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    else
2181d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushstring(L, strerror(en));
2191d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushinteger(L, en);
2201d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return 3;
2211d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
2221d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
2231d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2241d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2251d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#if !defined(inspectstat)	/* { */
2261d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2271d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#if defined(LUA_USE_POSIX)
2281d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2291d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#include <sys/wait.h>
2301d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2311d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
2321d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** use appropriate macros to interpret 'pclose' return status
2331d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
2341d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#define inspectstat(stat,what)  \
2351d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III   if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \
2361d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III   else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; }
2371d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2381d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#else
2391d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2401d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#define inspectstat(stat,what)  /* no op */
2411d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2421d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#endif
2431d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2441d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#endif				/* } */
2451d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2461d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2471d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_execresult (lua_State *L, int stat) {
2481d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  const char *what = "exit";  /* type of termination */
2491d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (stat == -1)  /* error? */
2501d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return luaL_fileresult(L, 0, NULL);
2511d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else {
2521d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    inspectstat(stat, what);  /* interpret result */
2531d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (*what == 'e' && stat == 0)  /* successful termination? */
2541d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushboolean(L, 1);
2551d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    else
2561d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushnil(L);
2571d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushstring(L, what);
2581d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushinteger(L, stat);
2591d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return 3;  /* return true/nil,what,code */
2601d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
2611d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
2621d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2631d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/* }====================================================== */
2641d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2651d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2661d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
2671d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** {======================================================
2681d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Userdata's metatable manipulation
2691d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** =======================================================
2701d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
2711d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2721d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
2731d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_getmetatable(L, tname);  /* try to get metatable */
2741d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (!lua_isnil(L, -1))  /* name already in use? */
2751d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return 0;  /* leave previous value on top, but return 0 */
2761d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pop(L, 1);
2771d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_newtable(L);  /* create metatable */
2781d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushvalue(L, -1);
2791d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_setfield(L, LUA_REGISTRYINDEX, tname);  /* registry.name = metatable */
2801d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return 1;
2811d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
2821d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2831d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2841d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) {
2851d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_getmetatable(L, tname);
2861d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_setmetatable(L, -2);
2871d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
2881d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2891d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
2901d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) {
2911d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  void *p = lua_touserdata(L, ud);
2921d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (p != NULL) {  /* value is a userdata? */
2931d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */
2941d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      luaL_getmetatable(L, tname);  /* get correct metatable */
2951d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      if (!lua_rawequal(L, -1, -2))  /* not the same? */
2961d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        p = NULL;  /* value is a userdata with wrong metatable */
2971d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pop(L, 2);  /* remove both metatables */
2981d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      return p;
2991d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    }
3001d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
3011d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return NULL;  /* value is not a userdata with a metatable */
3021d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
3031d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3041d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3051d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
3061d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  void *p = luaL_testudata(L, ud, tname);
3071d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (p == NULL) typeerror(L, ud, tname);
3081d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return p;
3091d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
3101d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3111d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/* }====================================================== */
3121d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3131d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3141d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
3151d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** {======================================================
3161d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Argument check functions
3171d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** =======================================================
3181d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
3191d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3201d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
3211d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                                 const char *const lst[]) {
3221d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  const char *name = (def) ? luaL_optstring(L, narg, def) :
3231d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                             luaL_checkstring(L, narg);
3241d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int i;
3251d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  for (i=0; lst[i]; i++)
3261d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (strcmp(lst[i], name) == 0)
3271d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      return i;
3281d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return luaL_argerror(L, narg,
3291d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                       lua_pushfstring(L, "invalid option " LUA_QS, name));
3301d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
3311d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3321d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3331d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
3341d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  /* keep some extra space to run error routines, if needed */
3351d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  const int extra = LUA_MINSTACK;
3361d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (!lua_checkstack(L, space + extra)) {
3371d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (msg)
3381d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      luaL_error(L, "stack overflow (%s)", msg);
3391d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    else
3401d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      luaL_error(L, "stack overflow");
3411d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
3421d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
3431d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3441d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3451d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
3461d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (lua_type(L, narg) != t)
3471d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    tag_error(L, narg, t);
3481d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
3491d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3501d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3511d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_checkany (lua_State *L, int narg) {
3521d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (lua_type(L, narg) == LUA_TNONE)
3531d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    luaL_argerror(L, narg, "value expected");
3541d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
3551d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3561d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3571d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
3581d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  const char *s = lua_tolstring(L, narg, len);
3591d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (!s) tag_error(L, narg, LUA_TSTRING);
3601d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return s;
3611d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
3621d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3631d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3641d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API const char *luaL_optlstring (lua_State *L, int narg,
3651d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                                        const char *def, size_t *len) {
3661d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (lua_isnoneornil(L, narg)) {
3671d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (len)
3681d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      *len = (def ? strlen(def) : 0);
3691d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return def;
3701d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
3711d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else return luaL_checklstring(L, narg, len);
3721d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
3731d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3741d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3751d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
3761d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int isnum;
3771d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_Number d = lua_tonumberx(L, narg, &isnum);
3781d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (!isnum)
3791d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    tag_error(L, narg, LUA_TNUMBER);
3801d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return d;
3811d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
3821d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3831d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3841d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
3851d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return luaL_opt(L, luaL_checknumber, narg, def);
3861d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
3871d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3881d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3891d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
3901d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int isnum;
3911d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_Integer d = lua_tointegerx(L, narg, &isnum);
3921d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (!isnum)
3931d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    tag_error(L, narg, LUA_TNUMBER);
3941d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return d;
3951d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
3961d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3971d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
3981d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) {
3991d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int isnum;
4001d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_Unsigned d = lua_tounsignedx(L, narg, &isnum);
4011d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (!isnum)
4021d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    tag_error(L, narg, LUA_TNUMBER);
4031d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return d;
4041d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
4051d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4061d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4071d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
4081d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                                                      lua_Integer def) {
4091d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return luaL_opt(L, luaL_checkinteger, narg, def);
4101d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
4111d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4121d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4131d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg,
4141d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                                                        lua_Unsigned def) {
4151d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return luaL_opt(L, luaL_checkunsigned, narg, def);
4161d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
4171d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4181d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/* }====================================================== */
4191d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4201d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4211d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
4221d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** {======================================================
4231d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Generic Buffer manipulation
4241d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** =======================================================
4251d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
4261d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4271d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
4281d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** check whether buffer is using a userdata on the stack as a temporary
4291d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** buffer
4301d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
4311d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#define buffonstack(B)	((B)->b != (B)->initb)
4321d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4331d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4341d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
4351d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** returns a pointer to a free area with at least 'sz' bytes
4361d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
4371d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
4381d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_State *L = B->L;
4391d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (B->size - B->n < sz) {  /* not enough space? */
4401d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    char *newbuff;
4411d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    size_t newsize = B->size * 2;  /* double buffer size */
4421d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (newsize - B->n < sz)  /* not big enough? */
4431d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      newsize = B->n + sz;
4441d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (newsize < B->n || newsize - B->n < sz)
4451d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      luaL_error(L, "buffer too large");
4461d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    /* create larger buffer */
4471d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char));
4481d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    /* move content to new buffer */
4491d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    memcpy(newbuff, B->b, B->n * sizeof(char));
4501d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (buffonstack(B))
4511d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_remove(L, -2);  /* remove old buffer */
4521d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    B->b = newbuff;
4531d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    B->size = newsize;
4541d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
4551d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return &B->b[B->n];
4561d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
4571d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4581d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4591d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
4601d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  char *b = luaL_prepbuffsize(B, l);
4611d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  memcpy(b, s, l * sizeof(char));
4621d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_addsize(B, l);
4631d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
4641d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4651d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4661d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
4671d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_addlstring(B, s, strlen(s));
4681d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
4691d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4701d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4711d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_pushresult (luaL_Buffer *B) {
4721d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_State *L = B->L;
4731d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushlstring(L, B->b, B->n);
4741d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (buffonstack(B))
4751d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_remove(L, -2);  /* remove old buffer */
4761d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
4771d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4781d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4791d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) {
4801d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_addsize(B, sz);
4811d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_pushresult(B);
4821d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
4831d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4841d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4851d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_addvalue (luaL_Buffer *B) {
4861d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_State *L = B->L;
4871d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  size_t l;
4881d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  const char *s = lua_tolstring(L, -1, &l);
4891d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (buffonstack(B))
4901d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_insert(L, -2);  /* put value below buffer */
4911d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_addlstring(B, s, l);
4921d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_remove(L, (buffonstack(B)) ? -2 : -1);  /* remove value */
4931d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
4941d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4951d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
4961d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
4971d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  B->L = L;
4981d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  B->b = B->initb;
4991d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  B->n = 0;
5001d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  B->size = LUAL_BUFFERSIZE;
5011d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
5021d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5031d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5041d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) {
5051d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_buffinit(L, B);
5061d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return luaL_prepbuffsize(B, sz);
5071d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
5081d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5091d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/* }====================================================== */
5101d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5111d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5121d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
5131d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** {======================================================
5141d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Reference system
5151d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** =======================================================
5161d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
5171d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5181d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/* index of free-list header */
5191d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#define freelist	0
5201d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5211d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5221d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_ref (lua_State *L, int t) {
5231d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int ref;
5241d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (lua_isnil(L, -1)) {
5251d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pop(L, 1);  /* remove from stack */
5261d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return LUA_REFNIL;  /* `nil' has a unique fixed reference */
5271d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
5281d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  t = lua_absindex(L, t);
5291d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_rawgeti(L, t, freelist);  /* get first free element */
5301d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  ref = (int)lua_tointeger(L, -1);  /* ref = t[freelist] */
5311d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pop(L, 1);  /* remove it from stack */
5321d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (ref != 0) {  /* any free element? */
5331d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_rawgeti(L, t, ref);  /* remove it from list */
5341d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_rawseti(L, t, freelist);  /* (t[freelist] = t[ref]) */
5351d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
5361d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else  /* no free elements */
5371d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    ref = (int)lua_rawlen(L, t) + 1;  /* get a new reference */
5381d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_rawseti(L, t, ref);
5391d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return ref;
5401d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
5411d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5421d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5431d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
5441d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (ref >= 0) {
5451d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    t = lua_absindex(L, t);
5461d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_rawgeti(L, t, freelist);
5471d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_rawseti(L, t, ref);  /* t[ref] = t[freelist] */
5481d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushinteger(L, ref);
5491d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_rawseti(L, t, freelist);  /* t[freelist] = ref */
5501d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
5511d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
5521d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5531d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/* }====================================================== */
5541d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5551d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5561d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
5571d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** {======================================================
5581d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Load functions
5591d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** =======================================================
5601d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
5611d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5621d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIItypedef struct LoadF {
5631d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int n;  /* number of pre-read characters */
5641d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  FILE *f;  /* file being read */
5651d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  char buff[LUAL_BUFFERSIZE];  /* area for reading file */
5661d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III} LoadF;
5671d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5681d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5691d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic const char *getF (lua_State *L, void *ud, size_t *size) {
5701d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  LoadF *lf = (LoadF *)ud;
5711d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  (void)L;  /* not used */
5721d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (lf->n > 0) {  /* are there pre-read characters to be read? */
5731d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    *size = lf->n;  /* return them (chars already in buffer) */
5741d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lf->n = 0;  /* no more pre-read characters */
5751d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
5761d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else {  /* read a block from file */
5771d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    /* 'fread' can return > 0 *and* set the EOF flag. If next call to
5781d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III       'getF' called 'fread', it might still wait for user input.
5791d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III       The next check avoids this problem. */
5801d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (feof(lf->f)) return NULL;
5811d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);  /* read block */
5821d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
5831d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return lf->buff;
5841d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
5851d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5861d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5871d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic int errfile (lua_State *L, const char *what, int fnameindex) {
5881d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  const char *serr = strerror(errno);
5891d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  const char *filename = lua_tostring(L, fnameindex) + 1;
5901d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
5911d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_remove(L, fnameindex);
5921d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return LUA_ERRFILE;
5931d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
5941d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5951d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
5961d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic int skipBOM (LoadF *lf) {
5971d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  const char *p = "\xEF\xBB\xBF";  /* Utf8 BOM mark */
5981d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int c;
5991d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lf->n = 0;
6001d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  do {
6011d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    c = getc(lf->f);
6021d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (c == EOF || c != *(const unsigned char *)p++) return c;
6031d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lf->buff[lf->n++] = c;  /* to be read by the parser */
6041d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  } while (*p != '\0');
6051d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lf->n = 0;  /* prefix matched; discard it */
6061d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return getc(lf->f);  /* return next character */
6071d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
6081d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6091d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6101d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
6111d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** reads the first character of file 'f' and skips an optional BOM mark
6121d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** in its beginning plus its first line if it starts with '#'. Returns
6131d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** true if it skipped the first line.  In any case, '*cp' has the
6141d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** first "valid" character of the file (after the optional BOM and
6151d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** a first-line comment).
6161d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
6171d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic int skipcomment (LoadF *lf, int *cp) {
6181d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int c = *cp = skipBOM(lf);
6191d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (c == '#') {  /* first line is a comment (Unix exec. file)? */
6201d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    do {  /* skip first line */
6211d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      c = getc(lf->f);
6221d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    } while (c != EOF && c != '\n') ;
6231d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    *cp = getc(lf->f);  /* skip end-of-line, if present */
6241d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return 1;  /* there was a comment */
6251d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
6261d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else return 0;  /* no comment */
6271d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
6281d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6291d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6301d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
6311d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                                             const char *mode) {
6321d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  LoadF lf;
6331d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int status, readstatus;
6341d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int c;
6351d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int fnameindex = lua_gettop(L) + 1;  /* index of filename on the stack */
6361d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (filename == NULL) {
6371d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushliteral(L, "=stdin");
6381d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lf.f = stdin;
6391d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
6401d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else {
6411d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushfstring(L, "@%s", filename);
6421d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lf.f = fopen(filename, "r");
6431d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (lf.f == NULL) return errfile(L, "open", fnameindex);
6441d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
6451d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (skipcomment(&lf, &c))  /* read initial portion */
6461d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lf.buff[lf.n++] = '\n';  /* add line to correct line numbers */
6471d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (c == LUA_SIGNATURE[0] && filename) {  /* binary file? */
6481d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lf.f = freopen(filename, "rb", lf.f);  /* reopen in binary mode */
6491d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
6501d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    skipcomment(&lf, &c);  /* re-read initial portion */
6511d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
6521d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (c != EOF)
6531d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lf.buff[lf.n++] = c;  /* 'c' is the first character of the stream */
6541d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode);
6551d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  readstatus = ferror(lf.f);
6561d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (filename) fclose(lf.f);  /* close file (even in case of errors) */
6571d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (readstatus) {
6581d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_settop(L, fnameindex);  /* ignore results from `lua_load' */
6591d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return errfile(L, "read", fnameindex);
6601d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
6611d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_remove(L, fnameindex);
6621d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return status;
6631d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
6641d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6651d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6661d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIItypedef struct LoadS {
6671d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  const char *s;
6681d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  size_t size;
6691d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III} LoadS;
6701d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6711d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6721d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic const char *getS (lua_State *L, void *ud, size_t *size) {
6731d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  LoadS *ls = (LoadS *)ud;
6741d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  (void)L;  /* not used */
6751d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (ls->size == 0) return NULL;
6761d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  *size = ls->size;
6771d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  ls->size = 0;
6781d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return ls->s;
6791d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
6801d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6811d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6821d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size,
6831d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                                 const char *name, const char *mode) {
6841d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  LoadS ls;
6851d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  ls.s = buff;
6861d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  ls.size = size;
6871d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return lua_load(L, getS, &ls, name, mode);
6881d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
6891d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6901d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6911d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
6921d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return luaL_loadbuffer(L, s, strlen(s), s);
6931d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
6941d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6951d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/* }====================================================== */
6961d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6971d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6981d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
6991d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
7001d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (!lua_getmetatable(L, obj))  /* no metatable? */
7011d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return 0;
7021d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushstring(L, event);
7031d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_rawget(L, -2);
7041d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (lua_isnil(L, -1)) {
7051d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pop(L, 2);  /* remove metatable and metafield */
7061d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return 0;
7071d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
7081d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else {
7091d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_remove(L, -2);  /* remove only metatable */
7101d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return 1;
7111d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
7121d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
7131d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
7141d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
7151d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
7161d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  obj = lua_absindex(L, obj);
7171d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (!luaL_getmetafield(L, obj, event))  /* no metafield? */
7181d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return 0;
7191d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushvalue(L, obj);
7201d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_call(L, 1, 1);
7211d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return 1;
7221d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
7231d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
7241d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
7251d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_len (lua_State *L, int idx) {
7261d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int l;
7271d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int isnum;
7281d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_len(L, idx);
7291d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  l = (int)lua_tointegerx(L, -1, &isnum);
7301d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (!isnum)
7311d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    luaL_error(L, "object length is not a number");
7321d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pop(L, 1);  /* remove object */
7331d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return l;
7341d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
7351d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
7361d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
7371d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
7381d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (!luaL_callmeta(L, idx, "__tostring")) {  /* no metafield? */
7391d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    switch (lua_type(L, idx)) {
7401d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      case LUA_TNUMBER:
7411d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      case LUA_TSTRING:
7421d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        lua_pushvalue(L, idx);
7431d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        break;
7441d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      case LUA_TBOOLEAN:
7451d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false"));
7461d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        break;
7471d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      case LUA_TNIL:
7481d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        lua_pushliteral(L, "nil");
7491d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        break;
7501d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      default:
7511d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        lua_pushfstring(L, "%s: %p", luaL_typename(L, idx),
7521d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                                            lua_topointer(L, idx));
7531d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III        break;
7541d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    }
7551d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
7561d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return lua_tolstring(L, -1, len);
7571d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
7581d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
7591d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
7601d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
7611d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** {======================================================
7621d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Compatibility with 5.1 module functions
7631d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** =======================================================
7641d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
7651d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#if defined(LUA_COMPAT_MODULE)
7661d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
7671d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic const char *luaL_findtable (lua_State *L, int idx,
7681d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                                   const char *fname, int szhint) {
7691d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  const char *e;
7701d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (idx) lua_pushvalue(L, idx);
7711d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  do {
7721d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    e = strchr(fname, '.');
7731d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (e == NULL) e = fname + strlen(fname);
7741d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushlstring(L, fname, e - fname);
7751d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_rawget(L, -2);
7761d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (lua_isnil(L, -1)) {  /* no such field? */
7771d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pop(L, 1);  /* remove this nil */
7781d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
7791d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushlstring(L, fname, e - fname);
7801d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushvalue(L, -2);
7811d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_settable(L, -4);  /* set new table into field */
7821d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    }
7831d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    else if (!lua_istable(L, -1)) {  /* field has a non-table value? */
7841d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pop(L, 2);  /* remove table and value */
7851d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      return fname;  /* return problematic part of the name */
7861d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    }
7871d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_remove(L, -2);  /* remove previous table */
7881d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    fname = e + 1;
7891d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  } while (*e == '.');
7901d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return NULL;
7911d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
7921d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
7931d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
7941d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
7951d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Count number of elements in a luaL_Reg list.
7961d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
7971d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic int libsize (const luaL_Reg *l) {
7981d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  int size = 0;
7991d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  for (; l && l->name; l++) size++;
8001d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return size;
8011d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
8021d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
8031d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
8041d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
8051d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Find or create a module table with a given name. The function
8061d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** first looks at the _LOADED table and, if that fails, try a
8071d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** global variable with that name. In any case, leaves on the stack
8081d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** the module table.
8091d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
8101d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_pushmodule (lua_State *L, const char *modname,
8111d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                                 int sizehint) {
8121d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);  /* get _LOADED table */
8131d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_getfield(L, -1, modname);  /* get _LOADED[modname] */
8141d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (!lua_istable(L, -1)) {  /* not found? */
8151d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pop(L, 1);  /* remove previous result */
8161d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    /* try global variable (and create one if it does not exist) */
8171d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushglobaltable(L);
8181d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    if (luaL_findtable(L, 0, modname, sizehint) != NULL)
8191d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      luaL_error(L, "name conflict for module " LUA_QS, modname);
8201d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushvalue(L, -1);
8211d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_setfield(L, -3, modname);  /* _LOADED[modname] = new table */
8221d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
8231d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_remove(L, -2);  /* remove _LOADED table */
8241d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
8251d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
8261d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
8271d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_openlib (lua_State *L, const char *libname,
8281d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                               const luaL_Reg *l, int nup) {
8291d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_checkversion(L);
8301d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (libname) {
8311d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    luaL_pushmodule(L, libname, libsize(l));  /* get/create library table */
8321d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_insert(L, -(nup + 1));  /* move library table to below upvalues */
8331d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
8341d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (l)
8351d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    luaL_setfuncs(L, l, nup);
8361d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else
8371d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pop(L, nup);  /* remove upvalues */
8381d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
8391d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
8401d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III#endif
8411d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/* }====================================================== */
8421d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
8431d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
8441d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** set functions from list 'l' into table at top - 'nup'; each
8451d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** function gets the 'nup' elements at the top as upvalues.
8461d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Returns with only the table at the stack.
8471d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
8481d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
8491d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_checkversion(L);
8501d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_checkstack(L, nup, "too many upvalues");
8511d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  for (; l->name != NULL; l++) {  /* fill the table with given functions */
8521d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    int i;
8531d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    for (i = 0; i < nup; i++)  /* copy upvalues to the top */
8541d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_pushvalue(L, -nup);
8551d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
8561d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_setfield(L, -(nup + 2), l->name);
8571d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
8581d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pop(L, nup);  /* remove upvalues */
8591d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
8601d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
8611d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
8621d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
8631d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** ensure that stack[idx][fname] has a table and push that table
8641d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** into the stack
8651d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
8661d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) {
8671d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_getfield(L, idx, fname);
8681d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (lua_istable(L, -1)) return 1;  /* table already there */
8691d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else {
8701d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pop(L, 1);  /* remove previous result */
8711d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    idx = lua_absindex(L, idx);
8721d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_newtable(L);
8731d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushvalue(L, -1);  /* copy to be left at top */
8741d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_setfield(L, idx, fname);  /* assign new table to field */
8751d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return 0;  /* false, because did not find table there */
8761d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
8771d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
8781d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
8791d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
8801d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III/*
8811d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** stripped-down 'require'. Calls 'openf' to open a module,
8821d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** registers the result in 'package.loaded' table and, if 'glb'
8831d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** is true, also registers the result in the global table.
8841d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III** Leaves resulting module on the top.
8851d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III*/
8861d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_requiref (lua_State *L, const char *modname,
8871d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                               lua_CFunction openf, int glb) {
8881d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushcfunction(L, openf);
8891d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushstring(L, modname);  /* argument to open function */
8901d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_call(L, 1, 1);  /* open module */
8911d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
8921d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushvalue(L, -2);  /* make copy of module (call result) */
8931d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_setfield(L, -2, modname);  /* _LOADED[modname] = module */
8941d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pop(L, 1);  /* remove _LOADED table */
8951d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (glb) {
8961d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_pushvalue(L, -1);  /* copy of 'mod' */
8971d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    lua_setglobal(L, modname);  /* _G[modname] = module */
8981d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
8991d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
9001d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
9011d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
9021d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
9031d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                                                               const char *r) {
9041d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  const char *wild;
9051d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  size_t l = strlen(p);
9061d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_Buffer b;
9071d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_buffinit(L, &b);
9081d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  while ((wild = strstr(s, p)) != NULL) {
9091d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    luaL_addlstring(&b, s, wild - s);  /* push prefix */
9101d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    luaL_addstring(&b, r);  /* push replacement in place of pattern */
9111d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    s = wild + l;  /* continue after `p' */
9121d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
9131d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_addstring(&b, s);  /* push last suffix */
9141d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luaL_pushresult(&b);
9151d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return lua_tostring(L, -1);
9161d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
9171d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
9181d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
9191d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
9201d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  (void)ud; (void)osize;  /* not used */
9211d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (nsize == 0) {
9221d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    free(ptr);
9231d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return NULL;
9241d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  }
9251d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else
9261d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    return realloc(ptr, nsize);
9271d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
9281d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
9291d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
9301d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIIstatic int panic (lua_State *L) {
9311d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
9321d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                   lua_tostring(L, -1));
9331d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return 0;  /* return to Lua to abort */
9341d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
9351d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
9361d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
9371d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API lua_State *luaL_newstate (void) {
9381d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_State *L = lua_newstate(l_alloc, NULL);
9391d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (L) lua_atpanic(L, &panic);
9401d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  return L;
9411d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
9421d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
9431d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
9441d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins IIILUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) {
9451d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  const lua_Number *v = lua_version(L);
9461d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (v != lua_version(NULL))
9471d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    luaL_error(L, "multiple Lua VMs detected");
9481d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  else if (*v != ver)
9491d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f",
9501d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                  ver, *v);
9511d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  /* check conversions number -> integer types */
9521d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pushnumber(L, -(lua_Number)0x1234);
9531d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  if (lua_tointeger(L, -1) != -0x1234 ||
9541d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III      lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234)
9551d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III    luaL_error(L, "bad conversion number->int;"
9561d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III                  " must recompile Lua with proper settings");
9571d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III  lua_pop(L, 1);
9581d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III}
9591d9a26b35628ec99e6b03380bdedec2a0135d5f9Leon Scroggins III
960