2014-12-22 12:35:05 +01:00
|
|
|
/*
|
|
|
|
** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $
|
|
|
|
** Auxiliary functions for building Lua libraries
|
|
|
|
** See Copyright Notice in lua.h
|
|
|
|
*/
|
|
|
|
|
2015-09-01 07:11:36 +02:00
|
|
|
#define LUAC_CROSS_FILE
|
2014-12-22 12:35:05 +01:00
|
|
|
|
2015-09-01 07:11:36 +02:00
|
|
|
#include "lua.h"
|
|
|
|
#include C_HEADER_CTYPE
|
|
|
|
#include C_HEADER_ERRNO
|
|
|
|
#include C_HEADER_STDIO
|
|
|
|
#include C_HEADER_STDLIB
|
|
|
|
#include C_HEADER_STRING
|
|
|
|
#ifndef LUA_CROSS_COMPILER
|
2016-09-05 20:17:13 +02:00
|
|
|
#include "vfs.h"
|
2015-09-01 07:11:36 +02:00
|
|
|
#else
|
|
|
|
#endif
|
2014-12-22 12:35:05 +01:00
|
|
|
|
|
|
|
/* This file uses only the official API of Lua.
|
|
|
|
** Any function declared here could be written as an application function.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define lauxlib_c
|
|
|
|
#define LUA_LIB
|
|
|
|
|
|
|
|
#include "lrotable.h"
|
|
|
|
|
|
|
|
#include "lauxlib.h"
|
|
|
|
#include "lgc.h"
|
|
|
|
#include "ldo.h"
|
|
|
|
#include "lobject.h"
|
|
|
|
#include "lstate.h"
|
|
|
|
#include "legc.h"
|
|
|
|
|
|
|
|
#define FREELIST_REF 0 /* free list of references */
|
|
|
|
|
|
|
|
|
|
|
|
/* convert a stack index to positive */
|
|
|
|
#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
|
|
|
|
lua_gettop(L) + (i) + 1)
|
|
|
|
|
|
|
|
// Parameters for luaI_openlib
|
|
|
|
#define LUA_USECCLOSURES 0
|
|
|
|
#define LUA_USELIGHTFUNCTIONS 1
|
|
|
|
|
|
|
|
/*
|
|
|
|
** {======================================================
|
|
|
|
** Error-report functions
|
|
|
|
** =======================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
|
2014-12-22 12:35:05 +01:00
|
|
|
lua_Debug ar;
|
|
|
|
if (!lua_getstack(L, 0, &ar)) /* no stack frame? */
|
|
|
|
return luaL_error(L, "bad argument #%d (%s)", narg, extramsg);
|
|
|
|
lua_getinfo(L, "n", &ar);
|
|
|
|
if (c_strcmp(ar.namewhat, "method") == 0) {
|
|
|
|
narg--; /* do not count `self' */
|
|
|
|
if (narg == 0) /* error is in the self argument itself? */
|
|
|
|
return luaL_error(L, "calling " LUA_QS " on bad self (%s)",
|
|
|
|
ar.name, extramsg);
|
|
|
|
}
|
|
|
|
if (ar.name == NULL)
|
|
|
|
ar.name = "?";
|
|
|
|
return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
|
|
|
|
narg, ar.name, extramsg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {
|
2014-12-22 12:35:05 +01:00
|
|
|
const char *msg = lua_pushfstring(L, "%s expected, got %s",
|
|
|
|
tname, luaL_typename(L, narg));
|
|
|
|
return luaL_argerror(L, narg, msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static void tag_error (lua_State *L, int narg, int tag) {
|
2014-12-22 12:35:05 +01:00
|
|
|
luaL_typerror(L, narg, lua_typename(L, tag));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaL_where (lua_State *L, int level) {
|
2014-12-22 12:35:05 +01:00
|
|
|
lua_Debug ar;
|
|
|
|
if (lua_getstack(L, level, &ar)) { /* check function at level */
|
|
|
|
lua_getinfo(L, "Sl", &ar); /* get info about it */
|
|
|
|
if (ar.currentline > 0) { /* is there info? */
|
|
|
|
lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lua_pushliteral(L, ""); /* else, no information available... */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
|
2014-12-22 12:35:05 +01:00
|
|
|
va_list argp;
|
|
|
|
va_start(argp, fmt);
|
|
|
|
luaL_where(L, 1);
|
|
|
|
lua_pushvfstring(L, fmt, argp);
|
|
|
|
va_end(argp);
|
|
|
|
lua_concat(L, 2);
|
|
|
|
return lua_error(L);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* }====================================================== */
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
|
2014-12-22 12:35:05 +01:00
|
|
|
const char *const lst[]) {
|
|
|
|
const char *name = (def) ? luaL_optstring(L, narg, def) :
|
|
|
|
luaL_checkstring(L, narg);
|
|
|
|
int i;
|
|
|
|
for (i=0; lst[i]; i++)
|
|
|
|
if (c_strcmp(lst[i], name) == 0)
|
|
|
|
return i;
|
|
|
|
return luaL_argerror(L, narg,
|
|
|
|
lua_pushfstring(L, "invalid option " LUA_QS, name));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
|
2014-12-22 12:35:05 +01:00
|
|
|
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */
|
|
|
|
if (!lua_isnil(L, -1)) /* name already in use? */
|
|
|
|
return 0; /* leave previous value on top, but return 0 */
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_newtable(L); /* create metatable */
|
|
|
|
lua_pushvalue(L, -1);
|
|
|
|
lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int luaL_rometatable (lua_State *L, const char* tname, void *p) {
|
2014-12-22 12:35:05 +01:00
|
|
|
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */
|
|
|
|
if (!lua_isnil(L, -1)) /* name already in use? */
|
|
|
|
return 0; /* leave previous value on top, but return 0 */
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_pushrotable(L, p);
|
|
|
|
lua_pushvalue(L, -1);
|
|
|
|
lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
|
2014-12-22 12:35:05 +01:00
|
|
|
void *p = lua_touserdata(L, ud);
|
|
|
|
if (p != NULL) { /* value is a userdata? */
|
|
|
|
if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
|
|
|
|
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
|
|
|
|
if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
|
|
|
|
lua_pop(L, 2); /* remove both metatables */
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
luaL_typerror(L, ud, tname); /* else error */
|
|
|
|
return NULL; /* to avoid warnings */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
|
2014-12-22 12:35:05 +01:00
|
|
|
if (!lua_checkstack(L, space))
|
|
|
|
luaL_error(L, "stack overflow (%s)", mes);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
|
2014-12-22 12:35:05 +01:00
|
|
|
if (lua_type(L, narg) != t)
|
|
|
|
tag_error(L, narg, t);
|
|
|
|
}
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaL_checkanyfunction (lua_State *L, int narg) {
|
2014-12-22 12:35:05 +01:00
|
|
|
if (lua_type(L, narg) != LUA_TFUNCTION && lua_type(L, narg) != LUA_TLIGHTFUNCTION) {
|
|
|
|
const char *msg = lua_pushfstring(L, "function or lightfunction expected, got %s",
|
|
|
|
luaL_typename(L, narg));
|
|
|
|
luaL_argerror(L, narg, msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaL_checkanytable (lua_State *L, int narg) {
|
2014-12-22 12:35:05 +01:00
|
|
|
if (lua_type(L, narg) != LUA_TTABLE && lua_type(L, narg) != LUA_TROTABLE) {
|
|
|
|
const char *msg = lua_pushfstring(L, "table or rotable expected, got %s",
|
|
|
|
luaL_typename(L, narg));
|
|
|
|
luaL_argerror(L, narg, msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaL_checkany (lua_State *L, int narg) {
|
2014-12-22 12:35:05 +01:00
|
|
|
if (lua_type(L, narg) == LUA_TNONE)
|
|
|
|
luaL_argerror(L, narg, "value expected");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
|
2014-12-22 12:35:05 +01:00
|
|
|
const char *s = lua_tolstring(L, narg, len);
|
|
|
|
if (!s) tag_error(L, narg, LUA_TSTRING);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API const char *luaL_optlstring (lua_State *L, int narg,
|
2014-12-22 12:35:05 +01:00
|
|
|
const char *def, size_t *len) {
|
|
|
|
if (lua_isnoneornil(L, narg)) {
|
|
|
|
if (len)
|
|
|
|
*len = (def ? c_strlen(def) : 0);
|
|
|
|
return def;
|
|
|
|
}
|
|
|
|
else return luaL_checklstring(L, narg, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
|
2014-12-22 12:35:05 +01:00
|
|
|
lua_Number d = lua_tonumber(L, narg);
|
|
|
|
if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
|
|
|
|
tag_error(L, narg, LUA_TNUMBER);
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
|
2014-12-22 12:35:05 +01:00
|
|
|
return luaL_opt(L, luaL_checknumber, narg, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
|
2014-12-22 12:35:05 +01:00
|
|
|
lua_Integer d = lua_tointeger(L, narg);
|
|
|
|
if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
|
|
|
|
tag_error(L, narg, LUA_TNUMBER);
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
|
2014-12-22 12:35:05 +01:00
|
|
|
lua_Integer def) {
|
|
|
|
return luaL_opt(L, luaL_checkinteger, narg, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
|
2014-12-22 12:35:05 +01:00
|
|
|
if (!lua_getmetatable(L, obj)) /* no metatable? */
|
|
|
|
return 0;
|
|
|
|
lua_pushstring(L, event);
|
|
|
|
lua_rawget(L, -2);
|
|
|
|
if (lua_isnil(L, -1)) {
|
|
|
|
lua_pop(L, 2); /* remove metatable and metafield */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
lua_remove(L, -2); /* remove only metatable */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
|
2014-12-22 12:35:05 +01:00
|
|
|
obj = abs_index(L, obj);
|
|
|
|
if (!luaL_getmetafield(L, obj, event)) /* no metafield? */
|
|
|
|
return 0;
|
|
|
|
lua_pushvalue(L, obj);
|
|
|
|
lua_call(L, 1, 1);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
|
2014-12-22 12:35:05 +01:00
|
|
|
const luaL_Reg *l) {
|
|
|
|
luaI_openlib(L, libname, l, 0, LUA_USECCLOSURES);
|
|
|
|
}
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void (luaL_register_light) (lua_State *L, const char *libname,
|
2014-12-22 12:35:05 +01:00
|
|
|
const luaL_Reg *l) {
|
|
|
|
#if LUA_OPTIMIZE_MEMORY > 0
|
|
|
|
luaI_openlib(L, libname, l, 0, LUA_USELIGHTFUNCTIONS);
|
|
|
|
#else
|
|
|
|
luaI_openlib(L, libname, l, 0, LUA_USECCLOSURES);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static int libsize (const luaL_Reg *l) {
|
2014-12-22 12:35:05 +01:00
|
|
|
int size = 0;
|
|
|
|
for (; l->name; l++) size++;
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
|
2014-12-22 12:35:05 +01:00
|
|
|
const luaL_Reg *l, int nup, int ftype) {
|
|
|
|
if (libname) {
|
|
|
|
int size = libsize(l);
|
|
|
|
/* check whether lib already exists */
|
|
|
|
luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);
|
|
|
|
lua_getfield(L, -1, libname); /* get _LOADED[libname] */
|
|
|
|
if (!lua_istable(L, -1)) { /* not found? */
|
|
|
|
lua_pop(L, 1); /* remove previous result */
|
|
|
|
/* try global variable (and create one if it does not exist) */
|
|
|
|
if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
|
|
|
|
luaL_error(L, "name conflict for module " LUA_QS, libname);
|
|
|
|
lua_pushvalue(L, -1);
|
|
|
|
lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
|
|
|
|
}
|
|
|
|
lua_remove(L, -2); /* remove _LOADED table */
|
|
|
|
lua_insert(L, -(nup+1)); /* move library table to below upvalues */
|
|
|
|
}
|
|
|
|
for (; l->name; l++) {
|
|
|
|
int i;
|
|
|
|
for (i=0; i<nup; i++) /* copy upvalues to the top */
|
|
|
|
lua_pushvalue(L, -nup);
|
|
|
|
if (ftype == LUA_USELIGHTFUNCTIONS)
|
|
|
|
lua_pushlightfunction(L, l->func);
|
|
|
|
else
|
|
|
|
lua_pushcclosure(L, l->func, nup);
|
|
|
|
lua_setfield(L, -(nup+2), l->name);
|
|
|
|
}
|
|
|
|
lua_pop(L, nup); /* remove upvalues */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** {======================================================
|
|
|
|
** getn-setn: size for arrays
|
|
|
|
** =======================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if defined(LUA_COMPAT_GETN)
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static int checkint (lua_State *L, int topop) {
|
2014-12-22 12:35:05 +01:00
|
|
|
int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;
|
|
|
|
lua_pop(L, topop);
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static void getsizes (lua_State *L) {
|
2014-12-22 12:35:05 +01:00
|
|
|
lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES");
|
|
|
|
if (lua_isnil(L, -1)) { /* no `size' table? */
|
|
|
|
lua_pop(L, 1); /* remove nil */
|
|
|
|
lua_newtable(L); /* create it */
|
|
|
|
lua_pushvalue(L, -1); /* `size' will be its own metatable */
|
|
|
|
lua_setmetatable(L, -2);
|
|
|
|
lua_pushliteral(L, "kv");
|
|
|
|
lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */
|
|
|
|
lua_pushvalue(L, -1);
|
|
|
|
lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaL_setn (lua_State *L, int t, int n) {
|
2014-12-22 12:35:05 +01:00
|
|
|
t = abs_index(L, t);
|
|
|
|
lua_pushliteral(L, "n");
|
|
|
|
lua_rawget(L, t);
|
|
|
|
if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */
|
|
|
|
lua_pushliteral(L, "n"); /* use it */
|
|
|
|
lua_pushinteger(L, n);
|
|
|
|
lua_rawset(L, t);
|
|
|
|
}
|
|
|
|
else { /* use `sizes' */
|
|
|
|
getsizes(L);
|
|
|
|
lua_pushvalue(L, t);
|
|
|
|
lua_pushinteger(L, n);
|
|
|
|
lua_rawset(L, -3); /* sizes[t] = n */
|
|
|
|
lua_pop(L, 1); /* remove `sizes' */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int luaL_getn (lua_State *L, int t) {
|
2014-12-22 12:35:05 +01:00
|
|
|
int n;
|
|
|
|
t = abs_index(L, t);
|
|
|
|
lua_pushliteral(L, "n"); /* try t.n */
|
|
|
|
lua_rawget(L, t);
|
|
|
|
if ((n = checkint(L, 1)) >= 0) return n;
|
|
|
|
getsizes(L); /* else try sizes[t] */
|
|
|
|
lua_pushvalue(L, t);
|
|
|
|
lua_rawget(L, -2);
|
|
|
|
if ((n = checkint(L, 2)) >= 0) return n;
|
|
|
|
return (int)lua_objlen(L, t);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* }====================================================== */
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
|
2014-12-22 12:35:05 +01:00
|
|
|
const char *r) {
|
|
|
|
const char *wild;
|
|
|
|
size_t l = c_strlen(p);
|
|
|
|
luaL_Buffer b;
|
|
|
|
luaL_buffinit(L, &b);
|
|
|
|
while ((wild = c_strstr(s, p)) != NULL) {
|
|
|
|
luaL_addlstring(&b, s, wild - s); /* push prefix */
|
|
|
|
luaL_addstring(&b, r); /* push replacement in place of pattern */
|
|
|
|
s = wild + l; /* continue after `p' */
|
|
|
|
}
|
|
|
|
luaL_addstring(&b, s); /* push last suffix */
|
|
|
|
luaL_pushresult(&b);
|
|
|
|
return lua_tostring(L, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
|
2014-12-22 12:35:05 +01:00
|
|
|
const char *fname, int szhint) {
|
|
|
|
const char *e;
|
|
|
|
lua_pushvalue(L, idx);
|
|
|
|
do {
|
|
|
|
e = c_strchr(fname, '.');
|
|
|
|
if (e == NULL) e = fname + c_strlen(fname);
|
|
|
|
lua_pushlstring(L, fname, e - fname);
|
|
|
|
lua_rawget(L, -2);
|
|
|
|
if (lua_isnil(L, -1)) {
|
|
|
|
/* If looking for a global variable, check the rotables too */
|
|
|
|
void *ptable = luaR_findglobal(fname, e - fname);
|
|
|
|
if (ptable) {
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_pushrotable(L, ptable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lua_isnil(L, -1)) { /* no such field? */
|
|
|
|
lua_pop(L, 1); /* remove this nil */
|
|
|
|
lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
|
|
|
|
lua_pushlstring(L, fname, e - fname);
|
|
|
|
lua_pushvalue(L, -2);
|
|
|
|
lua_settable(L, -4); /* set new table into field */
|
|
|
|
}
|
|
|
|
else if (!lua_istable(L, -1) && !lua_isrotable(L, -1)) { /* field has a non-table value? */
|
|
|
|
lua_pop(L, 2); /* remove table and value */
|
|
|
|
return fname; /* return problematic part of the name */
|
|
|
|
}
|
|
|
|
lua_remove(L, -2); /* remove previous table */
|
|
|
|
fname = e + 1;
|
|
|
|
} while (*e == '.');
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** {======================================================
|
|
|
|
** Generic Buffer manipulation
|
|
|
|
** =======================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#define bufflen(B) ((B)->p - (B)->buffer)
|
|
|
|
#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
|
|
|
|
|
|
|
|
#define LIMIT (LUA_MINSTACK/2)
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static int emptybuffer (luaL_Buffer *B) {
|
2014-12-22 12:35:05 +01:00
|
|
|
size_t l = bufflen(B);
|
|
|
|
if (l == 0) return 0; /* put nothing on stack */
|
|
|
|
else {
|
|
|
|
lua_pushlstring(B->L, B->buffer, l);
|
|
|
|
B->p = B->buffer;
|
|
|
|
B->lvl++;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static void adjuststack (luaL_Buffer *B) {
|
2014-12-22 12:35:05 +01:00
|
|
|
if (B->lvl > 1) {
|
|
|
|
lua_State *L = B->L;
|
|
|
|
int toget = 1; /* number of levels to concat */
|
|
|
|
size_t toplen = lua_strlen(L, -1);
|
|
|
|
do {
|
|
|
|
size_t l = lua_strlen(L, -(toget+1));
|
|
|
|
if (B->lvl - toget + 1 >= LIMIT || toplen > l) {
|
|
|
|
toplen += l;
|
|
|
|
toget++;
|
|
|
|
}
|
|
|
|
else break;
|
|
|
|
} while (toget < B->lvl);
|
|
|
|
lua_concat(L, toget);
|
|
|
|
B->lvl = B->lvl - toget + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {
|
2014-12-22 12:35:05 +01:00
|
|
|
if (emptybuffer(B))
|
|
|
|
adjuststack(B);
|
|
|
|
return B->buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
|
2014-12-22 12:35:05 +01:00
|
|
|
while (l--)
|
|
|
|
luaL_addchar(B, *s++);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
|
2014-12-22 12:35:05 +01:00
|
|
|
luaL_addlstring(B, s, c_strlen(s));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
|
2014-12-22 12:35:05 +01:00
|
|
|
emptybuffer(B);
|
|
|
|
lua_concat(B->L, B->lvl);
|
|
|
|
B->lvl = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
|
2014-12-22 12:35:05 +01:00
|
|
|
lua_State *L = B->L;
|
|
|
|
size_t vl;
|
|
|
|
const char *s = lua_tolstring(L, -1, &vl);
|
|
|
|
if (vl <= bufffree(B)) { /* fit into buffer? */
|
|
|
|
c_memcpy(B->p, s, vl); /* put it there */
|
|
|
|
B->p += vl;
|
|
|
|
lua_pop(L, 1); /* remove from stack */
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (emptybuffer(B))
|
|
|
|
lua_insert(L, -2); /* put buffer before new value */
|
|
|
|
B->lvl++; /* add new value into B stack */
|
|
|
|
adjuststack(B);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
|
2014-12-22 12:35:05 +01:00
|
|
|
B->L = L;
|
|
|
|
B->p = B->buffer;
|
|
|
|
B->lvl = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* }====================================================== */
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int luaL_ref (lua_State *L, int t) {
|
2014-12-22 12:35:05 +01:00
|
|
|
int ref;
|
|
|
|
t = abs_index(L, t);
|
|
|
|
if (lua_isnil(L, -1)) {
|
|
|
|
lua_pop(L, 1); /* remove from stack */
|
|
|
|
return LUA_REFNIL; /* `nil' has a unique fixed reference */
|
|
|
|
}
|
|
|
|
lua_rawgeti(L, t, FREELIST_REF); /* get first free element */
|
|
|
|
ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */
|
|
|
|
lua_pop(L, 1); /* remove it from stack */
|
|
|
|
if (ref != 0) { /* any free element? */
|
|
|
|
lua_rawgeti(L, t, ref); /* remove it from list */
|
|
|
|
lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */
|
|
|
|
}
|
|
|
|
else { /* no free elements */
|
|
|
|
ref = (int)lua_objlen(L, t);
|
|
|
|
ref++; /* create new reference */
|
|
|
|
}
|
|
|
|
lua_rawseti(L, t, ref);
|
|
|
|
return ref;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
|
2014-12-22 12:35:05 +01:00
|
|
|
if (ref >= 0) {
|
|
|
|
t = abs_index(L, t);
|
|
|
|
lua_rawgeti(L, t, FREELIST_REF);
|
|
|
|
lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */
|
|
|
|
lua_pushinteger(L, ref);
|
|
|
|
lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** {======================================================
|
|
|
|
** Load functions
|
|
|
|
** =======================================================
|
|
|
|
*/
|
|
|
|
|
2015-09-01 07:11:36 +02:00
|
|
|
#ifdef LUA_CROSS_COMPILER
|
2014-12-22 12:35:05 +01:00
|
|
|
|
|
|
|
typedef struct LoadF {
|
|
|
|
int extraline;
|
|
|
|
FILE *f;
|
|
|
|
char buff[LUAL_BUFFERSIZE];
|
|
|
|
} LoadF;
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static const char *getF (lua_State *L, void *ud, size_t *size) {
|
2014-12-22 12:35:05 +01:00
|
|
|
LoadF *lf = (LoadF *)ud;
|
|
|
|
(void)L;
|
|
|
|
if (lf->extraline) {
|
|
|
|
lf->extraline = 0;
|
|
|
|
*size = 1;
|
|
|
|
return "\n";
|
|
|
|
}
|
|
|
|
if (c_feof(lf->f)) return NULL;
|
|
|
|
*size = c_fread(lf->buff, 1, sizeof(lf->buff), lf->f);
|
|
|
|
return (*size > 0) ? lf->buff : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static int errfile (lua_State *L, const char *what, int fnameindex) {
|
2014-12-22 12:35:05 +01:00
|
|
|
const char *serr = c_strerror(errno);
|
|
|
|
const char *filename = lua_tostring(L, fnameindex) + 1;
|
|
|
|
lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
|
|
|
|
lua_remove(L, fnameindex);
|
|
|
|
return LUA_ERRFILE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
|
2014-12-22 12:35:05 +01:00
|
|
|
LoadF lf;
|
|
|
|
int status, readstatus;
|
|
|
|
int c;
|
|
|
|
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
|
|
|
|
lf.extraline = 0;
|
|
|
|
if (filename == NULL) {
|
|
|
|
lua_pushliteral(L, "=stdin");
|
|
|
|
lf.f = c_stdin;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
lua_pushfstring(L, "@%s", filename);
|
|
|
|
lf.f = c_fopen(filename, "r");
|
|
|
|
if (lf.f == NULL) return errfile(L, "open", fnameindex);
|
|
|
|
}
|
|
|
|
c = c_getc(lf.f);
|
|
|
|
if (c == '#') { /* Unix exec. file? */
|
|
|
|
lf.extraline = 1;
|
|
|
|
while ((c = c_getc(lf.f)) != EOF && c != '\n') ; /* skip first line */
|
|
|
|
if (c == '\n') c = c_getc(lf.f);
|
|
|
|
}
|
|
|
|
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
|
|
|
|
lf.f = c_freopen(filename, "rb", lf.f); /* reopen in binary mode */
|
|
|
|
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
|
|
|
|
/* skip eventual `#!...' */
|
|
|
|
while ((c = c_getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
|
|
|
|
lf.extraline = 0;
|
|
|
|
}
|
|
|
|
c_ungetc(c, lf.f);
|
|
|
|
status = lua_load(L, getF, &lf, lua_tostring(L, -1));
|
|
|
|
readstatus = c_ferror(lf.f);
|
|
|
|
if (filename) c_fclose(lf.f); /* close file (even in case of errors) */
|
|
|
|
if (readstatus) {
|
|
|
|
lua_settop(L, fnameindex); /* ignore results from `lua_load' */
|
|
|
|
return errfile(L, "read", fnameindex);
|
|
|
|
}
|
|
|
|
lua_remove(L, fnameindex);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2015-09-01 07:11:36 +02:00
|
|
|
#include C_HEADER_FCNTL
|
2014-12-22 12:35:05 +01:00
|
|
|
|
|
|
|
typedef struct LoadFSF {
|
|
|
|
int extraline;
|
|
|
|
int f;
|
2015-02-14 09:59:45 +01:00
|
|
|
char buff[LUAL_BUFFERSIZE];
|
2014-12-22 12:35:05 +01:00
|
|
|
} LoadFSF;
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static const char *getFSF (lua_State *L, void *ud, size_t *size) {
|
2014-12-22 12:35:05 +01:00
|
|
|
LoadFSF *lf = (LoadFSF *)ud;
|
|
|
|
(void)L;
|
2015-03-14 17:00:25 +01:00
|
|
|
|
|
|
|
if (L == NULL && size == NULL) // Direct mode check
|
|
|
|
return NULL;
|
|
|
|
|
2014-12-22 12:35:05 +01:00
|
|
|
if (lf->extraline) {
|
|
|
|
lf->extraline = 0;
|
|
|
|
*size = 1;
|
|
|
|
return "\n";
|
|
|
|
}
|
2015-03-14 17:00:25 +01:00
|
|
|
|
2016-09-05 20:17:13 +02:00
|
|
|
if (vfs_eof(lf->f)) return NULL;
|
|
|
|
*size = vfs_read(lf->f, lf->buff, sizeof(lf->buff));
|
2015-03-14 17:00:25 +01:00
|
|
|
|
2014-12-22 12:35:05 +01:00
|
|
|
return (*size > 0) ? lf->buff : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static int errfsfile (lua_State *L, const char *what, int fnameindex) {
|
2014-12-22 12:35:05 +01:00
|
|
|
const char *filename = lua_tostring(L, fnameindex) + 1;
|
|
|
|
lua_pushfstring(L, "cannot %s %s", what, filename);
|
|
|
|
lua_remove(L, fnameindex);
|
|
|
|
return LUA_ERRFILE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) {
|
2014-12-22 12:35:05 +01:00
|
|
|
LoadFSF lf;
|
|
|
|
int status, readstatus;
|
|
|
|
int c;
|
|
|
|
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
|
|
|
|
lf.extraline = 0;
|
|
|
|
if (filename == NULL) {
|
|
|
|
return luaL_error(L, "filename is NULL");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
lua_pushfstring(L, "@%s", filename);
|
2016-09-05 20:17:13 +02:00
|
|
|
lf.f = vfs_open(filename, "r");
|
|
|
|
if (!lf.f) return errfsfile(L, "open", fnameindex);
|
2014-12-22 12:35:05 +01:00
|
|
|
}
|
2015-02-14 09:59:45 +01:00
|
|
|
// if(fs_size(lf.f)>LUAL_BUFFERSIZE)
|
|
|
|
// return luaL_error(L, "file is too big");
|
2016-09-05 20:17:13 +02:00
|
|
|
c = vfs_getc(lf.f);
|
2014-12-22 12:35:05 +01:00
|
|
|
if (c == '#') { /* Unix exec. file? */
|
|
|
|
lf.extraline = 1;
|
2016-09-05 20:17:13 +02:00
|
|
|
while ((c = vfs_getc(lf.f)) != VFS_EOF && c != '\n') ; /* skip first line */
|
|
|
|
if (c == '\n') c = vfs_getc(lf.f);
|
2014-12-22 12:35:05 +01:00
|
|
|
}
|
|
|
|
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
|
2016-09-05 20:17:13 +02:00
|
|
|
vfs_close(lf.f);
|
|
|
|
lf.f = vfs_open(filename, "r"); /* reopen in binary mode */
|
|
|
|
if (!lf.f) return errfsfile(L, "reopen", fnameindex);
|
2014-12-22 12:35:05 +01:00
|
|
|
/* skip eventual `#!...' */
|
2016-09-05 20:17:13 +02:00
|
|
|
while ((c = vfs_getc(lf.f)) != VFS_EOF && c != LUA_SIGNATURE[0]) ;
|
2014-12-22 12:35:05 +01:00
|
|
|
lf.extraline = 0;
|
|
|
|
}
|
2016-09-05 20:17:13 +02:00
|
|
|
vfs_ungetc(c, lf.f);
|
2014-12-22 12:35:05 +01:00
|
|
|
status = lua_load(L, getFSF, &lf, lua_tostring(L, -1));
|
|
|
|
|
2016-09-05 20:17:13 +02:00
|
|
|
if (filename) vfs_close(lf.f); /* close file (even in case of errors) */
|
2014-12-22 12:35:05 +01:00
|
|
|
lua_remove(L, fnameindex);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef struct LoadS {
|
|
|
|
const char *s;
|
|
|
|
size_t size;
|
|
|
|
} LoadS;
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static const char *getS (lua_State *L, void *ud, size_t *size) {
|
2014-12-22 12:35:05 +01:00
|
|
|
LoadS *ls = (LoadS *)ud;
|
|
|
|
(void)L;
|
|
|
|
if (L == NULL && size == NULL) // direct mode check
|
|
|
|
return NULL;
|
|
|
|
if (ls->size == 0) return NULL;
|
|
|
|
*size = ls->size;
|
|
|
|
ls->size = 0;
|
|
|
|
return ls->s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
|
2014-12-22 12:35:05 +01:00
|
|
|
const char *name) {
|
|
|
|
LoadS ls;
|
|
|
|
ls.s = buff;
|
|
|
|
ls.size = size;
|
|
|
|
return lua_load(L, getS, &ls, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) {
|
2014-12-22 12:35:05 +01:00
|
|
|
return luaL_loadbuffer(L, s, c_strlen(s), s);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* }====================================================== */
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static int l_check_memlimit(lua_State *L, size_t needbytes) {
|
2014-12-22 12:35:05 +01:00
|
|
|
global_State *g = G(L);
|
|
|
|
int cycle_count = 0;
|
|
|
|
lu_mem limit = g->memlimit - needbytes;
|
|
|
|
/* don't allow allocation if it requires more memory then the total limit. */
|
|
|
|
if (needbytes > g->memlimit) return 1;
|
|
|
|
/* make sure the GC is not disabled. */
|
|
|
|
if (!is_block_gc(L)) {
|
|
|
|
while (g->totalbytes >= limit) {
|
|
|
|
/* only allow the GC to finished atleast 1 full cycle. */
|
|
|
|
if (g->gcstate == GCSpause && ++cycle_count > 1) break;
|
|
|
|
luaC_step(L);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (g->totalbytes >= limit) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
|
2014-12-22 12:35:05 +01:00
|
|
|
lua_State *L = (lua_State *)ud;
|
|
|
|
int mode = L == NULL ? 0 : G(L)->egcmode;
|
|
|
|
void *nptr;
|
|
|
|
|
|
|
|
if (nsize == 0) {
|
|
|
|
c_free(ptr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (L != NULL && (mode & EGC_ALWAYS)) /* always collect memory if requested */
|
|
|
|
luaC_fullgc(L);
|
|
|
|
if(nsize > osize && L != NULL) {
|
|
|
|
#if defined(LUA_STRESS_EMERGENCY_GC)
|
|
|
|
luaC_fullgc(L);
|
|
|
|
#endif
|
|
|
|
if(G(L)->memlimit > 0 && (mode & EGC_ON_MEM_LIMIT) && l_check_memlimit(L, nsize - osize))
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
nptr = (void *)c_realloc(ptr, nsize);
|
|
|
|
if (nptr == NULL && L != NULL && (mode & EGC_ON_ALLOC_FAILURE)) {
|
|
|
|
luaC_fullgc(L); /* emergency full collection. */
|
|
|
|
nptr = (void *)c_realloc(ptr, nsize); /* try allocation again */
|
|
|
|
}
|
|
|
|
return nptr;
|
|
|
|
}
|
|
|
|
|
2016-03-20 17:54:16 +01:00
|
|
|
LUALIB_API void luaL_assertfail(const char *file, int line, const char *message) {
|
Next 1.5.4.1 master drop (#1627)
* add u8g.fb_rle display
* move comm drivers to u8g_glue.c
* disable fb_rle per default
* implement file.size for spiffs (#1516)
Another bug squashed!
* Fix start-up race between UART & start_lua. (#1522)
Input during startup (especially while doing initial filesystem format)
ran the risk of filling up the task queue, preventing the start_lua task
from being queued, and hence NodeMCU would not start up that time.
* Reimplemented esp_init_data_default.
To work around the pesky "rf_cal[0] !=0x05" hang when booting on a chip
which doesn't have esp_init_data written to it.
It is no longer possible to do the writing of the esp_init_data_default
from within nodemcu_init(), as the SDK now hangs long before it gets
there. As such, I've had to reimplement this in our user_start_trampoline
and get it all done before the SDK has a chance to look for the init data.
It's unfortunate that we have to spend IRAM on this, but I see no better
alternative at this point.
* Replace hardcoded init data with generated data from SDK
The esp_init_data_default.bin is now extracted from the SDK (and its
patch file, if present), and the contents are automatically embedded
into user_main.o.
* Rework flashing instructions
Clarifies issues around SDK init data and hopefully clears up some
confusion, when paired with the esp_init_data_default changes in
NodeMCU.
* Fix typo
* Fixes the gpio.serout problem from #1534 (#1535)
* Fix some issues in gpio.serout
* Minor cleanup
* fix dereferencing NULL pointer in vfs_errno() (#1539)
* add map ids for flash sizes 32m-c2, 64m, 128m in user_rf_cal_sector_set() (#1529)
* Somfy/TELIS driver (#1521)
* Reduced LUAL_BUFFERSIZE to 256. Should free up some stack (#1530)
* avoid task queue overrun for serial input (#1540)
Thank you.
* Increase irom0_0_seg size for PR build
* Improve reliability of FS detection. (#1528)
* Version to make filesystem detection more reliable
* Improve bad fs detection
* Version of printf that doesn't suffer from buffer overflows (#1564)
* Small improvement to http client (#1558)
* Remove luaL_buffer from file_g_read() (#1541)
* remove luaL_buffer from file_g_read()
- avoid memory leak when function gets terminated by lua_error
- skip scanning for end_char when reading until EOF
* attempt to free memory in any case
* Change HTTP failures from debug to error messages (#1568)
* Change HTTP failures from debug to error messages
* Add tag to HTTP error messages
* Create macro for error msg and improve dbg msg
* Add ssd1306_128x32 for U8G (#1571)
* Update CONTRIBUTING.md
* Add support to mix ws2812.buffer objects. (#1575)
* Add load/dump/mix/power operations on the buffer object
* Calculate the pixel value in mix and then clip to the range.
* Fixed the two wrong userdata types
* Added a couple more useful methods
* Add support for shifting a piece of the buffer.
* Fix a minor bug with offset shifts
* Update to the wifi module (#1497)
* Removed inline documentation for several functions and update comments
Since documentation is now part of the repository, the inline
documentation just adds to the already huge wifi.c
* Wifi module: add new functionality, update documentation
Functions Added:
wifi.getdefaultmode(): returns default wifi opmode
wifi.sta.apchange(): select alternate cached AP
wifi.sta.apinfo(): get cached AP list
wifi.sta.aplimit(): set cached AP limit
wifi.sta.getapindex(): get index of currently configured AP
wifi.sta.getdefaultconfig(): get default station configuration
wifi.ap.getdefaultconfig(): get default AP configuration
functions modified:
wifi.setmode: saving mode to flash is now optional
wifi.sta.config: now accepts table as an argument and save config to
flash is now optional
wifi.sta.getconfig: added option to return table
wifi.ap.config: save config to flash is now optional
wifi.ap.getconfig: added option to return table
Documentation changes:
- Modified documentation to reflect above changes
- Removed unnecessary inline documentation from `wifi.c`
- Updated documentation for `wifi.sta.disconnect`to address issue #1480
- Fixed inaccurate documentation for function `wifi.sleeptype`
- Added more details to `wifi.nullmodesleep()`
* Move function `wifi.sleeptype()` to `wifi.sta.sleeptype()`
* Fixed problem where wifi.x.getconfig() returned invalid strings when
ssid or password were set to maximum length.
* fix error in documentation for `wifi.sta.getapindex`
* Renamed some wifi functions
wifi.sta.apinfo -> getapinfo
wifi.sta.aplimit -> setaplimit
wifi.sta.apchange -> changeap
also organized the wifi_station_map array
* Make the MQTT PING functionality work better. (#1557)
Deal with flow control stopped case
* Implement object model for files (#1532)
* Eus channelfix (#1583)
Squashed commits included:
Bug fixes and final implementation
- Added Content-Length: 0 to all headers
- Endpoint name checks not using trailing space so cache-busting techniques can be used (i.e., append a nonce to the URL)
- Track when connecting so APList scan doesn't take place during (which changes the channel)
- More debugging output added to assist in tracking down some issues
Added /status.json endpoint for phone apps/XHR to get JSON response
Station Status caching for wifi channel workaround + AJAX/CORS
- During checkstation poll, cache the last station status
- Shut down the station if status = 2,3,4 and channel is different than SoftAP
- Add Access-Control-Allow-Origin: * to endpoint responses used by a service
- Add a /setwifi GET endpoint for phone apps/XHR to use (same parameters as /update endpoint). Returns a JSON response containing chip id and status code.
- Add handler for OPTIONS verb (needed for CORS support)
Wi-Fi Channel Issue Workaround
- Do a site survey upon startup, set SoftAP channel to the strongest rssi's channel
- Compare successful station connect channel to SoftAP's. If different, then defer the Lua success callback to the end. Shut down Station and start the SoftAP back up with original channel.
- After the 10 second shutdown timer fires, check to see if success callback was already called. If not, then call it while starting the Station back up.
HTTP Response and DNS enhancements
- If DNS's UDP buffer fills up, keep going as non-fatal. It's UDP and not guaranteed anyways. I've seen this occur when connecting a PC to the SoftAP and every open program tries to phone home at the same time, overwhelming the EUS DNS server.
- Support for detecting/handling pre-gzipped `enduser_setup.html` (and `http_html_backup`) payload. Nice for keeping the size of the `state->http_payload_data` as small as possible (also makes minimization not as critical)
- Corrected misuse of HTTP 401 response status (changed one occurrence to 400/Bad Request, and changed another to 405/Method Not Allowed)
* Normalized formatting (tabs-to-spaces)
* Added documentation
* Corrected misuse of strlen for binary (gzip) data.
* Added NULL check after malloc
* fix vfs_lseek() result checking in enduser_setup and clarify SPIFFS_lseek() return value (#1570)
* Fix link
* Overhaul flashing docs once again (#1587)
* Add chapter about determine flash size plus small fixes
* Rewrite esptool.py chapter, move flash size chapter to end
* i2c - allow slave stretching SCL (just loop and check) (#1589)
* Add note on dev board usage of SPI bus 0 (#1591)
* Turn SPI busses note to admonition note
* support for custom websocket headers (#1573)
Looks good to me. Thank you.
Also:
- allow for '\0's in received messages
* add client:config for setting websocket headers
Also:
- headers are case-insensitive now
* fix docs
* fix typo
* remove unnecessary luaL_argcheck calls
* replace os_sprintf with simple string copy
* Handle error condition in file.read() (#1599)
* handle error condition in file.read()
* simplify loop initialization
* Fix macro as suggested in #1548
* Extract and hoist net receive callbacks
This is done to avoid the accidental upval binding
* Fix typo at rtctime.md
rtctime.dsleep -> rtctime.dsleep_aligned
2016-12-01 21:37:24 +01:00
|
|
|
dbg_printf("ASSERT@%s(%d): %s\n", file, line, message);
|
2016-03-20 17:54:16 +01:00
|
|
|
}
|
2014-12-22 12:35:05 +01:00
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
static int panic (lua_State *L) {
|
2014-12-22 12:35:05 +01:00
|
|
|
(void)L; /* to avoid warnings */
|
|
|
|
#if defined(LUA_USE_STDIO)
|
|
|
|
c_fprintf(c_stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
|
|
|
|
lua_tostring(L, -1));
|
|
|
|
#else
|
|
|
|
luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
|
|
|
|
lua_tostring(L, -1));
|
|
|
|
#endif
|
2015-07-14 03:37:12 +02:00
|
|
|
while (1) {}
|
2014-12-22 12:35:05 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-05 03:09:51 +01:00
|
|
|
LUALIB_API lua_State *luaL_newstate (void) {
|
2014-12-22 12:35:05 +01:00
|
|
|
lua_State *L = lua_newstate(l_alloc, NULL);
|
|
|
|
lua_setallocf(L, l_alloc, L); /* allocator need lua_State. */
|
|
|
|
if (L) lua_atpanic(L, &panic);
|
|
|
|
return L;
|
|
|
|
}
|
|
|
|
|