From ae2779e504ca5ae11a87e047b4536a5f428cce4d Mon Sep 17 00:00:00 2001 From: pixel Date: Sat, 27 Nov 2004 21:46:02 +0000 Subject: Large dos2unix commit... --- lib/lua/src/LuaLib/lauxlib.c | 1182 +++++++++++++++---------------- lib/lua/src/LuaLib/lbaselib.c | 1348 ++++++++++++++++++------------------ lib/lua/src/LuaLib/ldblib.c | 598 ++++++++-------- lib/lua/src/LuaLib/ldirlib.c | 192 ++--- lib/lua/src/LuaLib/liolib.c | 1500 +++++++++++++++++++-------------------- lib/lua/src/LuaLib/lmathlib.c | 492 ++++++------- lib/lua/src/LuaLib/loadlib.c | 410 +++++------ lib/lua/src/LuaLib/lstrlib.c | 1540 ++++++++++++++++++++--------------------- lib/lua/src/LuaLib/ltablib.c | 500 ++++++------- 9 files changed, 3881 insertions(+), 3881 deletions(-) (limited to 'lib/lua/src/LuaLib') diff --git a/lib/lua/src/LuaLib/lauxlib.c b/lib/lua/src/LuaLib/lauxlib.c index c4b24a7..2088b9e 100644 --- a/lib/lua/src/LuaLib/lauxlib.c +++ b/lib/lua/src/LuaLib/lauxlib.c @@ -1,591 +1,591 @@ -/* -** $Id: lauxlib.c,v 1.3 2004-11-27 21:35:21 pixel Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include - - -/* This file uses only the official API of Lua. -** Any function declared here could be written as an application function. -*/ - -#define lauxlib_c - -#include "lua.h" - -#include "lauxlib.h" - - -/* number of prereserved references (for internal use) */ -#define RESERVED_REFS 2 - -/* reserved references */ -#define FREELIST_REF 1 /* free list of references */ -#define ARRAYSIZE_REF 2 /* array sizes */ - - -/* convert a stack index to positive */ -#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ - lua_gettop(L) + (i) + 1) - - -/* -** {====================================================== -** Error-report functions -** ======================================================= -*/ - - -LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { - lua_Debug ar; - lua_getstack(L, 0, &ar); - lua_getinfo(L, "n", &ar); - if (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 `%s' on bad self (%s)", ar.name, extramsg); - } - if (ar.name == NULL) - ar.name = "?"; - return luaL_error(L, "bad argument #%d to `%s' (%s)", - narg, ar.name, extramsg); -} - - -LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { - const char *msg = lua_pushfstring(L, "%s expected, got %s", - tname, lua_typename(L, lua_type(L,narg))); - return luaL_argerror(L, narg, msg); -} - - -static void tag_error (lua_State *L, int narg, int tag) { - luaL_typerror(L, narg, lua_typename(L, tag)); -} - - -LUALIB_API void luaL_where (lua_State *L, int level) { - lua_Debug ar; - if (lua_getstack(L, level, &ar)) { /* check function at level */ - lua_getinfo(L, "Snl", &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... */ -} - - -LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { - 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); -} - -/* }====================================================== */ - - -LUALIB_API int luaL_findstring (const char *name, const char *const list[]) { - int i; - for (i=0; list[i]; i++) - if (strcmp(list[i], name) == 0) - return i; - return -1; /* name not found */ -} - - -LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { - lua_pushstring(L, tname); - lua_rawget(L, LUA_REGISTRYINDEX); /* 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_pushstring(L, tname); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_REGISTRYINDEX); /* registry.name = metatable */ - lua_pushvalue(L, -1); - lua_pushstring(L, tname); - lua_rawset(L, LUA_REGISTRYINDEX); /* registry[metatable] = name */ - return 1; -} - - -LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname) { - lua_pushstring(L, tname); - lua_rawget(L, LUA_REGISTRYINDEX); -} - - -LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { - const char *tn; - if (!lua_getmetatable(L, ud)) return NULL; /* no metatable? */ - lua_rawget(L, LUA_REGISTRYINDEX); /* get registry[metatable] */ - tn = lua_tostring(L, -1); - if (tn && (strcmp(tn, tname) == 0)) { - lua_pop(L, 1); - return lua_touserdata(L, ud); - } - else { - lua_pop(L, 1); - return NULL; - } -} - - -LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { - if (!lua_checkstack(L, space)) - luaL_error(L, "stack overflow (%s)", mes); -} - - -LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { - if (lua_type(L, narg) != t) - tag_error(L, narg, t); -} - - -LUALIB_API void luaL_checkany (lua_State *L, int narg) { - if (lua_type(L, narg) == LUA_TNONE) - luaL_argerror(L, narg, "value expected"); -} - - -LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { - const char *s = lua_tostring(L, narg); - if (!s) tag_error(L, narg, LUA_TSTRING); - if (len) *len = lua_strlen(L, narg); - return s; -} - - -LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, - const char *def, size_t *len) { - if (lua_isnoneornil(L, narg)) { - if (len) - *len = (def ? strlen(def) : 0); - return def; - } - else return luaL_checklstring(L, narg, len); -} - - -LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { - 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; -} - - -LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { - if (lua_isnoneornil(L, narg)) return def; - else return luaL_checknumber(L, narg); -} - - -LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { - 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; - } -} - - -LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { - 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; -} - - -LUALIB_API void luaL_openlib (lua_State *L, const char *libname, - const luaL_reg *l, int nup) { - if (libname) { - lua_pushstring(L, libname); - lua_gettable(L, LUA_GLOBALSINDEX); /* check whether lib already exists */ - if (lua_isnil(L, -1)) { /* no? */ - lua_pop(L, 1); - lua_newtable(L); /* create it */ - lua_pushstring(L, libname); - lua_pushvalue(L, -2); - lua_settable(L, LUA_GLOBALSINDEX); /* register it with given name */ - } - lua_insert(L, -(nup+1)); /* move library table to below upvalues */ - } - for (; l->name; l++) { - int i; - lua_pushstring(L, l->name); - for (i=0; ifunc, nup); - lua_settable(L, -(nup+3)); - } - lua_pop(L, nup); /* remove upvalues */ -} - - - -/* -** {====================================================== -** getn-setn: size for arrays -** ======================================================= -*/ - -static int checkint (lua_State *L, int topop) { - int n = (int)lua_tonumber(L, -1); - if (n == 0 && !lua_isnumber(L, -1)) n = -1; - lua_pop(L, topop); - return n; -} - - -static void getsizes (lua_State *L) { - lua_rawgeti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); - 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, "__mode"); - lua_pushliteral(L, "k"); - lua_rawset(L, -3); /* metatable(N).__mode = "k" */ - lua_pushvalue(L, -1); - lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); /* store in register */ - } -} - - -void luaL_setn (lua_State *L, int t, int n) { - 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_pushnumber(L, (lua_Number)n); - lua_rawset(L, t); - } - else { /* use `sizes' */ - getsizes(L); - lua_pushvalue(L, t); - lua_pushnumber(L, (lua_Number)n); - lua_rawset(L, -3); /* sizes[t] = n */ - lua_pop(L, 1); /* remove `sizes' */ - } -} - - -int luaL_getn (lua_State *L, int t) { - 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; - for (n = 1; ; n++) { /* else must count elements */ - lua_rawgeti(L, t, n); - if (lua_isnil(L, -1)) break; - lua_pop(L, 1); - } - lua_pop(L, 1); - return n - 1; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - - -#define bufflen(B) ((B)->p - (B)->buffer) -#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) - -#define LIMIT (LUA_MINSTACK/2) - - -static int emptybuffer (luaL_Buffer *B) { - 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; - } -} - - -static void adjuststack (luaL_Buffer *B) { - 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; - } -} - - -LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { - if (emptybuffer(B)) - adjuststack(B); - return B->buffer; -} - - -LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { - while (l--) - luaL_putchar(B, *s++); -} - - -LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { - luaL_addlstring(B, s, strlen(s)); -} - - -LUALIB_API void luaL_pushresult (luaL_Buffer *B) { - emptybuffer(B); - lua_concat(B->L, B->lvl); - B->lvl = 1; -} - - -LUALIB_API void luaL_addvalue (luaL_Buffer *B) { - lua_State *L = B->L; - size_t vl = lua_strlen(L, -1); - if (vl <= bufffree(B)) { /* fit into buffer? */ - memcpy(B->p, lua_tostring(L, -1), 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); - } -} - - -LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { - B->L = L; - B->p = B->buffer; - B->lvl = 0; -} - -/* }====================================================== */ - - -LUALIB_API int luaL_ref (lua_State *L, int t) { - 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_tonumber(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 = luaL_getn(L, t); - if (ref < RESERVED_REFS) - ref = RESERVED_REFS; /* skip reserved references */ - ref++; /* create new reference */ - luaL_setn(L, t, ref); - } - lua_rawseti(L, t, ref); - return ref; -} - - -LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { - 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_pushnumber(L, (lua_Number)ref); - lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ - } -} - - - -/* -** {====================================================== -** Load functions -** ======================================================= -*/ - -typedef struct LoadF { - FILE *f; - char buff[LUAL_BUFFERSIZE]; -} LoadF; - - -static const char *getF (lua_State *L, void *ud, size_t *size) { - LoadF *lf = (LoadF *)ud; - (void)L; - if (feof(lf->f)) return NULL; - *size = fread(lf->buff, 1, LUAL_BUFFERSIZE, lf->f); - return (*size > 0) ? lf->buff : NULL; -} - - -static int errfile (lua_State *L, int fnameindex) { - const char *filename = lua_tostring(L, fnameindex) + 1; - lua_pushfstring(L, "cannot read %s: %s", filename, strerror(errno)); - lua_remove(L, fnameindex); - return LUA_ERRFILE; -} - - -LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { - LoadF lf; - int status, readstatus; - int c; - int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ - if (filename == NULL) { - lua_pushliteral(L, "=stdin"); - lf.f = stdin; - } - else { - lua_pushfstring(L, "@%s", filename); - lf.f = fopen(filename, "r"); - } - if (lf.f == NULL) return errfile(L, fnameindex); /* unable to open file */ - c = ungetc(getc(lf.f), lf.f); - if (!(isspace(c) || isprint(c)) && lf.f != stdin) { /* binary file? */ - fclose(lf.f); - lf.f = fopen(filename, "rb"); /* reopen in binary mode */ - if (lf.f == NULL) return errfile(L, fnameindex); /* unable to reopen file */ - } - status = lua_load(L, getF, &lf, lua_tostring(L, -1)); - readstatus = ferror(lf.f); - if (lf.f != stdin) fclose(lf.f); /* close file (even in case of errors) */ - if (readstatus) { - lua_settop(L, fnameindex); /* ignore results from `lua_load' */ - return errfile(L, fnameindex); - } - lua_remove(L, fnameindex); - return status; -} - - -typedef struct LoadS { - const char *s; - size_t size; -} LoadS; - - -static const char *getS (lua_State *L, void *ud, size_t *size) { - LoadS *ls = (LoadS *)ud; - (void)L; - if (ls->size == 0) return NULL; - *size = ls->size; - ls->size = 0; - return ls->s; -} - - -LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, - const char *name) { - LoadS ls; - ls.s = buff; - ls.size = size; - return lua_load(L, getS, &ls, name); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** compatibility code -** ======================================================= -*/ - - -static void callalert (lua_State *L, int status) { - if (status != 0) { - lua_getglobal(L, "_ALERT"); - if (lua_isfunction(L, -1)) { - lua_insert(L, -2); - lua_call(L, 1, 0); - } - else { /* no _ALERT function; print it on stderr */ - fprintf(stderr, "%s\n", lua_tostring(L, -2)); - lua_pop(L, 2); /* remove error message and _ALERT */ - } - } -} - - -static int aux_do (lua_State *L, int status) { - if (status == 0) { /* parse OK? */ - status = lua_pcall(L, 0, LUA_MULTRET, 0); /* call main */ - } - callalert(L, status); - return status; -} - - -LUALIB_API int lua_dofile (lua_State *L, const char *filename) { - return aux_do(L, luaL_loadfile(L, filename)); -} - - -LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, - const char *name) { - return aux_do(L, luaL_loadbuffer(L, buff, size, name)); -} - - -LUALIB_API int lua_dostring (lua_State *L, const char *str) { - return lua_dobuffer(L, str, strlen(str), str); -} - -/* }====================================================== */ +/* +** $Id: lauxlib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + + +/* This file uses only the official API of Lua. +** Any function declared here could be written as an application function. +*/ + +#define lauxlib_c + +#include "lua.h" + +#include "lauxlib.h" + + +/* number of prereserved references (for internal use) */ +#define RESERVED_REFS 2 + +/* reserved references */ +#define FREELIST_REF 1 /* free list of references */ +#define ARRAYSIZE_REF 2 /* array sizes */ + + +/* convert a stack index to positive */ +#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ + lua_gettop(L) + (i) + 1) + + +/* +** {====================================================== +** Error-report functions +** ======================================================= +*/ + + +LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { + lua_Debug ar; + lua_getstack(L, 0, &ar); + lua_getinfo(L, "n", &ar); + if (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 `%s' on bad self (%s)", ar.name, extramsg); + } + if (ar.name == NULL) + ar.name = "?"; + return luaL_error(L, "bad argument #%d to `%s' (%s)", + narg, ar.name, extramsg); +} + + +LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { + const char *msg = lua_pushfstring(L, "%s expected, got %s", + tname, lua_typename(L, lua_type(L,narg))); + return luaL_argerror(L, narg, msg); +} + + +static void tag_error (lua_State *L, int narg, int tag) { + luaL_typerror(L, narg, lua_typename(L, tag)); +} + + +LUALIB_API void luaL_where (lua_State *L, int level) { + lua_Debug ar; + if (lua_getstack(L, level, &ar)) { /* check function at level */ + lua_getinfo(L, "Snl", &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... */ +} + + +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { + 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); +} + +/* }====================================================== */ + + +LUALIB_API int luaL_findstring (const char *name, const char *const list[]) { + int i; + for (i=0; list[i]; i++) + if (strcmp(list[i], name) == 0) + return i; + return -1; /* name not found */ +} + + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { + lua_pushstring(L, tname); + lua_rawget(L, LUA_REGISTRYINDEX); /* 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_pushstring(L, tname); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); /* registry.name = metatable */ + lua_pushvalue(L, -1); + lua_pushstring(L, tname); + lua_rawset(L, LUA_REGISTRYINDEX); /* registry[metatable] = name */ + return 1; +} + + +LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname) { + lua_pushstring(L, tname); + lua_rawget(L, LUA_REGISTRYINDEX); +} + + +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + const char *tn; + if (!lua_getmetatable(L, ud)) return NULL; /* no metatable? */ + lua_rawget(L, LUA_REGISTRYINDEX); /* get registry[metatable] */ + tn = lua_tostring(L, -1); + if (tn && (strcmp(tn, tname) == 0)) { + lua_pop(L, 1); + return lua_touserdata(L, ud); + } + else { + lua_pop(L, 1); + return NULL; + } +} + + +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { + if (!lua_checkstack(L, space)) + luaL_error(L, "stack overflow (%s)", mes); +} + + +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { + if (lua_type(L, narg) != t) + tag_error(L, narg, t); +} + + +LUALIB_API void luaL_checkany (lua_State *L, int narg) { + if (lua_type(L, narg) == LUA_TNONE) + luaL_argerror(L, narg, "value expected"); +} + + +LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { + const char *s = lua_tostring(L, narg); + if (!s) tag_error(L, narg, LUA_TSTRING); + if (len) *len = lua_strlen(L, narg); + return s; +} + + +LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, + const char *def, size_t *len) { + if (lua_isnoneornil(L, narg)) { + if (len) + *len = (def ? strlen(def) : 0); + return def; + } + else return luaL_checklstring(L, narg, len); +} + + +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { + 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; +} + + +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { + if (lua_isnoneornil(L, narg)) return def; + else return luaL_checknumber(L, narg); +} + + +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + 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; + } +} + + +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { + 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; +} + + +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, + const luaL_reg *l, int nup) { + if (libname) { + lua_pushstring(L, libname); + lua_gettable(L, LUA_GLOBALSINDEX); /* check whether lib already exists */ + if (lua_isnil(L, -1)) { /* no? */ + lua_pop(L, 1); + lua_newtable(L); /* create it */ + lua_pushstring(L, libname); + lua_pushvalue(L, -2); + lua_settable(L, LUA_GLOBALSINDEX); /* register it with given name */ + } + lua_insert(L, -(nup+1)); /* move library table to below upvalues */ + } + for (; l->name; l++) { + int i; + lua_pushstring(L, l->name); + for (i=0; ifunc, nup); + lua_settable(L, -(nup+3)); + } + lua_pop(L, nup); /* remove upvalues */ +} + + + +/* +** {====================================================== +** getn-setn: size for arrays +** ======================================================= +*/ + +static int checkint (lua_State *L, int topop) { + int n = (int)lua_tonumber(L, -1); + if (n == 0 && !lua_isnumber(L, -1)) n = -1; + lua_pop(L, topop); + return n; +} + + +static void getsizes (lua_State *L) { + lua_rawgeti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); + 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, "__mode"); + lua_pushliteral(L, "k"); + lua_rawset(L, -3); /* metatable(N).__mode = "k" */ + lua_pushvalue(L, -1); + lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); /* store in register */ + } +} + + +void luaL_setn (lua_State *L, int t, int n) { + 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_pushnumber(L, (lua_Number)n); + lua_rawset(L, t); + } + else { /* use `sizes' */ + getsizes(L); + lua_pushvalue(L, t); + lua_pushnumber(L, (lua_Number)n); + lua_rawset(L, -3); /* sizes[t] = n */ + lua_pop(L, 1); /* remove `sizes' */ + } +} + + +int luaL_getn (lua_State *L, int t) { + 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; + for (n = 1; ; n++) { /* else must count elements */ + lua_rawgeti(L, t, n); + if (lua_isnil(L, -1)) break; + lua_pop(L, 1); + } + lua_pop(L, 1); + return n - 1; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + +#define bufflen(B) ((B)->p - (B)->buffer) +#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) + +#define LIMIT (LUA_MINSTACK/2) + + +static int emptybuffer (luaL_Buffer *B) { + 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; + } +} + + +static void adjuststack (luaL_Buffer *B) { + 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; + } +} + + +LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { + if (emptybuffer(B)) + adjuststack(B); + return B->buffer; +} + + +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { + while (l--) + luaL_putchar(B, *s++); +} + + +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { + luaL_addlstring(B, s, strlen(s)); +} + + +LUALIB_API void luaL_pushresult (luaL_Buffer *B) { + emptybuffer(B); + lua_concat(B->L, B->lvl); + B->lvl = 1; +} + + +LUALIB_API void luaL_addvalue (luaL_Buffer *B) { + lua_State *L = B->L; + size_t vl = lua_strlen(L, -1); + if (vl <= bufffree(B)) { /* fit into buffer? */ + memcpy(B->p, lua_tostring(L, -1), 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); + } +} + + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { + B->L = L; + B->p = B->buffer; + B->lvl = 0; +} + +/* }====================================================== */ + + +LUALIB_API int luaL_ref (lua_State *L, int t) { + 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_tonumber(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 = luaL_getn(L, t); + if (ref < RESERVED_REFS) + ref = RESERVED_REFS; /* skip reserved references */ + ref++; /* create new reference */ + luaL_setn(L, t, ref); + } + lua_rawseti(L, t, ref); + return ref; +} + + +LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { + 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_pushnumber(L, (lua_Number)ref); + lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ + } +} + + + +/* +** {====================================================== +** Load functions +** ======================================================= +*/ + +typedef struct LoadF { + FILE *f; + char buff[LUAL_BUFFERSIZE]; +} LoadF; + + +static const char *getF (lua_State *L, void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + (void)L; + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, LUAL_BUFFERSIZE, lf->f); + return (*size > 0) ? lf->buff : NULL; +} + + +static int errfile (lua_State *L, int fnameindex) { + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot read %s: %s", filename, strerror(errno)); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + + +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { + LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + if (filename == NULL) { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else { + lua_pushfstring(L, "@%s", filename); + lf.f = fopen(filename, "r"); + } + if (lf.f == NULL) return errfile(L, fnameindex); /* unable to open file */ + c = ungetc(getc(lf.f), lf.f); + if (!(isspace(c) || isprint(c)) && lf.f != stdin) { /* binary file? */ + fclose(lf.f); + lf.f = fopen(filename, "rb"); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, fnameindex); /* unable to reopen file */ + } + status = lua_load(L, getF, &lf, lua_tostring(L, -1)); + readstatus = ferror(lf.f); + if (lf.f != stdin) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from `lua_load' */ + return errfile(L, fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + + +typedef struct LoadS { + const char *s; + size_t size; +} LoadS; + + +static const char *getS (lua_State *L, void *ud, size_t *size) { + LoadS *ls = (LoadS *)ud; + (void)L; + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + + +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, + const char *name) { + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** compatibility code +** ======================================================= +*/ + + +static void callalert (lua_State *L, int status) { + if (status != 0) { + lua_getglobal(L, "_ALERT"); + if (lua_isfunction(L, -1)) { + lua_insert(L, -2); + lua_call(L, 1, 0); + } + else { /* no _ALERT function; print it on stderr */ + fprintf(stderr, "%s\n", lua_tostring(L, -2)); + lua_pop(L, 2); /* remove error message and _ALERT */ + } + } +} + + +static int aux_do (lua_State *L, int status) { + if (status == 0) { /* parse OK? */ + status = lua_pcall(L, 0, LUA_MULTRET, 0); /* call main */ + } + callalert(L, status); + return status; +} + + +LUALIB_API int lua_dofile (lua_State *L, const char *filename) { + return aux_do(L, luaL_loadfile(L, filename)); +} + + +LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, + const char *name) { + return aux_do(L, luaL_loadbuffer(L, buff, size, name)); +} + + +LUALIB_API int lua_dostring (lua_State *L, const char *str) { + return lua_dobuffer(L, str, strlen(str), str); +} + +/* }====================================================== */ diff --git a/lib/lua/src/LuaLib/lbaselib.c b/lib/lua/src/LuaLib/lbaselib.c index 6c928b5..11e5504 100644 --- a/lib/lua/src/LuaLib/lbaselib.c +++ b/lib/lua/src/LuaLib/lbaselib.c @@ -1,674 +1,674 @@ -/* -** $Id: lbaselib.c,v 1.3 2004-11-27 21:35:21 pixel Exp $ -** Basic library -** See Copyright Notice in lua.h -*/ - - - -#include -#include -#include -#include - -#define lbaselib_c - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - - -/* -** If your system does not support `stdout', you can just remove this function. -** If you need, you can define your own `print' function, following this -** model but changing `fputs' to put the strings at a proper place -** (a console window or a log file, for instance). -*/ -static int luaB_print (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int i; - lua_getglobal(L, "tostring"); - for (i=1; i<=n; i++) { - const char *s; - lua_pushvalue(L, -1); /* function to be called */ - lua_pushvalue(L, i); /* value to print */ - lua_call(L, 1, 1); - s = lua_tostring(L, -1); /* get result */ - if (s == NULL) - return luaL_error(L, "`tostring' must return a string to `print'"); - if (i>1) fputs("\t", stdout); - fputs(s, stdout); - lua_pop(L, 1); /* pop result */ - } - fputs("\n", stdout); - return 0; -} - - -static int luaB_tonumber (lua_State *L) { - int base = luaL_optint(L, 2, 10); - if (base == 10) { /* standard conversion */ - luaL_checkany(L, 1); - if (lua_isnumber(L, 1)) { - lua_pushnumber(L, lua_tonumber(L, 1)); - return 1; - } - } - else { - const char *s1 = luaL_checkstring(L, 1); - char *s2; - unsigned long n; - luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - n = strtoul(s1, &s2, base); - if (s1 != s2) { /* at least one valid digit? */ - while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ - if (*s2 == '\0') { /* no invalid trailing characters? */ - lua_pushnumber(L, (lua_Number)n); - return 1; - } - } - } - lua_pushnil(L); /* else not a number */ - return 1; -} - - -static int luaB_error (lua_State *L) { - int level = luaL_optint(L, 2, 1); - luaL_checkany(L, 1); - if (!lua_isstring(L, 1) || level == 0) - lua_pushvalue(L, 1); /* propagate error message without changes */ - else { /* add extra information */ - luaL_where(L, level); - lua_pushvalue(L, 1); - lua_concat(L, 2); - } - return lua_error(L); -} - - -static int luaB_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); - return 1; /* no metatable */ - } - luaL_getmetafield(L, 1, "__metatable"); - return 1; /* returns either __metatable field (if present) or metatable */ -} - - -static int luaB_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - if (luaL_getmetafield(L, 1, "__metatable")) - luaL_error(L, "cannot change a protected metatable"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; -} - - -static void getfunc (lua_State *L) { - if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); - else { - lua_Debug ar; - int level = luaL_optint(L, 1, 1); - luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); - if (lua_getstack(L, level, &ar) == 0) - luaL_argerror(L, 1, "invalid level"); - lua_getinfo(L, "f", &ar); - if (lua_isnil(L, -1)) - luaL_error(L, "no function environment for tail call at level %d", - level); - } -} - - -static int aux_getfenv (lua_State *L) { - lua_getfenv(L, -1); - lua_pushliteral(L, "__fenv"); - lua_rawget(L, -2); - return !lua_isnil(L, -1); -} - - -static int luaB_getfenv (lua_State *L) { - getfunc(L); - if (!aux_getfenv(L)) /* __fenv not defined? */ - lua_pop(L, 1); /* remove it, to return real environment */ - return 1; -} - - -static int luaB_setfenv (lua_State *L) { - luaL_checktype(L, 2, LUA_TTABLE); - getfunc(L); - if (aux_getfenv(L)) /* __fenv defined? */ - luaL_error(L, "`setfenv' cannot change a protected environment"); - else - lua_pop(L, 2); /* remove __fenv and real environment table */ - lua_pushvalue(L, 2); - if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) - lua_replace(L, LUA_GLOBALSINDEX); - else if (lua_setfenv(L, -2) == 0) - luaL_error(L, "`setfenv' cannot change environment of given function"); - return 0; -} - - -static int luaB_rawequal (lua_State *L) { - luaL_checkany(L, 1); - luaL_checkany(L, 2); - lua_pushboolean(L, lua_rawequal(L, 1, 2)); - return 1; -} - - -static int luaB_rawget (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - lua_rawget(L, 1); - return 1; -} - -static int luaB_rawset (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - luaL_checkany(L, 3); - lua_rawset(L, 1); - return 1; -} - - -static int luaB_gcinfo (lua_State *L) { - lua_pushnumber(L, (lua_Number)lua_getgccount(L)); - lua_pushnumber(L, (lua_Number)lua_getgcthreshold(L)); - return 2; -} - - -static int luaB_collectgarbage (lua_State *L) { - lua_setgcthreshold(L, luaL_optint(L, 1, 0)); - return 0; -} - - -static int luaB_type (lua_State *L) { - luaL_checkany(L, 1); - lua_pushstring(L, lua_typename(L, lua_type(L, 1))); - return 1; -} - - -static int luaB_next (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 2); /* create a 2nd argument if there isn't one */ - if (lua_next(L, 1)) - return 2; - else { - lua_pushnil(L); - return 1; - } -} - - -static int luaB_pairs (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushliteral(L, "next"); - lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */ - lua_pushvalue(L, 1); /* state, */ - lua_pushnil(L); /* and initial value */ - return 3; -} - - -static int luaB_ipairs (lua_State *L) { - lua_Number i = lua_tonumber(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - if (i == 0 && lua_isnone(L, 2)) { /* `for' start? */ - lua_pushliteral(L, "ipairs"); - lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */ - lua_pushvalue(L, 1); /* state, */ - lua_pushnumber(L, 0); /* and initial value */ - return 3; - } - else { /* `for' step */ - i++; /* next value */ - lua_pushnumber(L, i); - lua_rawgeti(L, 1, (int)i); - return (lua_isnil(L, -1)) ? 0 : 2; - } -} - - -static int load_aux (lua_State *L, int status) { - if (status == 0) /* OK? */ - return 1; - else { - lua_pushnil(L); - lua_insert(L, -2); /* put before error message */ - return 2; /* return nil plus error message */ - } -} - - -static int luaB_loadstring (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - const char *chunkname = luaL_optstring(L, 2, s); - return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); -} - - -static int luaB_loadfile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - return load_aux(L, luaL_loadfile(L, fname)); -} - - -static int luaB_dofile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - int status = luaL_loadfile(L, fname); - if (status != 0) lua_error(L); - lua_call(L, 0, LUA_MULTRET); - return lua_gettop(L) - 1; -} - - -static int luaB_assert (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_toboolean(L, 1)) - return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); - lua_settop(L, 1); - return 1; -} - - -static int luaB_unpack (lua_State *L) { - int n, i; - luaL_checktype(L, 1, LUA_TTABLE); - n = luaL_getn(L, 1); - luaL_checkstack(L, n, "table too big to unpack"); - for (i=1; i<=n; i++) /* push arg[1...n] */ - lua_rawgeti(L, 1, i); - return n; -} - - -static int luaB_pcall (lua_State *L) { - int status; - luaL_checkany(L, 1); - status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); - lua_pushboolean(L, (status == 0)); - lua_insert(L, 1); - return lua_gettop(L); /* return status + all results */ -} - - -static int luaB_xpcall (lua_State *L) { - int status; - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_insert(L, 1); /* put error function under function to be called */ - status = lua_pcall(L, 0, LUA_MULTRET, 1); - lua_pushboolean(L, (status == 0)); - lua_replace(L, 1); - return lua_gettop(L); /* return status + all results */ -} - - -static int luaB_tostring (lua_State *L) { - char buff[64]; - luaL_checkany(L, 1); - if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ - return 1; /* use its value */ - switch (lua_type(L, 1)) { - case LUA_TNUMBER: - lua_pushstring(L, lua_tostring(L, 1)); - return 1; - case LUA_TSTRING: - lua_pushvalue(L, 1); - return 1; - case LUA_TBOOLEAN: - lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); - return 1; - case LUA_TTABLE: - sprintf(buff, "table: %p", lua_topointer(L, 1)); - break; - case LUA_TFUNCTION: - sprintf(buff, "function: %p", lua_topointer(L, 1)); - break; - case LUA_TUSERDATA: - case LUA_TLIGHTUSERDATA: - sprintf(buff, "userdata: %p", lua_touserdata(L, 1)); - break; - case LUA_TTHREAD: - sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1)); - break; - case LUA_TNIL: - lua_pushliteral(L, "nil"); - return 1; - } - lua_pushstring(L, buff); - return 1; -} - - -static int luaB_newproxy (lua_State *L) { - lua_settop(L, 1); - lua_newuserdata(L, 0); /* create proxy */ - if (lua_toboolean(L, 1) == 0) - return 1; /* no metatable */ - else if (lua_isboolean(L, 1)) { - lua_newtable(L); /* create a new metatable `m' ... */ - lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ - lua_pushboolean(L, 1); - lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ - } - else { - int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ - if (lua_getmetatable(L, 1)) { - lua_rawget(L, lua_upvalueindex(1)); - validproxy = lua_toboolean(L, -1); - lua_pop(L, 1); /* remove value */ - } - luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); - lua_getmetatable(L, 1); /* metatable is valid; get it */ - } - lua_setmetatable(L, 2); - return 1; -} - - -/* -** {====================================================== -** `require' function -** ======================================================= -*/ - - -/* name of global that holds table with loaded packages */ -#define REQTAB "_LOADED" - -/* name of global that holds the search path for packages */ -#define LUA_PATH "LUA_PATH" - -#ifndef LUA_PATH_SEP -#define LUA_PATH_SEP ';' -#endif - -#ifndef LUA_PATH_MARK -#define LUA_PATH_MARK '?' -#endif - -#ifndef LUA_PATH_DEFAULT -#define LUA_PATH_DEFAULT "?;?.lua" -#endif - - -static const char *getpath (lua_State *L) { - const char *path; - lua_getglobal(L, LUA_PATH); /* try global variable */ - path = lua_tostring(L, -1); - lua_pop(L, 1); - if (path) return path; - path = getenv(LUA_PATH); /* else try environment variable */ - if (path) return path; - return LUA_PATH_DEFAULT; /* else use default */ -} - - -static const char *pushnextpath (lua_State *L, const char *path) { - const char *l; - if (*path == '\0') return NULL; /* no more paths */ - if (*path == LUA_PATH_SEP) path++; /* skip separator */ - l = strchr(path, LUA_PATH_SEP); /* find next separator */ - if (l == NULL) l = path+strlen(path); - lua_pushlstring(L, path, l - path); /* directory name */ - return l; -} - - -static void pushcomposename (lua_State *L) { - const char *path = lua_tostring(L, -1); - const char *wild; - int n = 1; - while ((wild = strchr(path, LUA_PATH_MARK)) != NULL) { - /* is there stack space for prefix, name, and eventual last sufix? */ - luaL_checkstack(L, 3, "too many marks in a path component"); - lua_pushlstring(L, path, wild - path); /* push prefix */ - lua_pushvalue(L, 1); /* push package name (in place of MARK) */ - path = wild + 1; /* continue after MARK */ - n += 2; - } - lua_pushstring(L, path); /* push last sufix (`n' already includes this) */ - lua_concat(L, n); -} - - -static int luaB_require (lua_State *L) { - const char *path; - int status = LUA_ERRFILE; /* not found (yet) */ - luaL_checkstring(L, 1); - lua_settop(L, 1); - lua_getglobal(L, REQTAB); - if (!lua_istable(L, 2)) return luaL_error(L, "`" REQTAB "' is not a table"); - path = getpath(L); - lua_pushvalue(L, 1); /* check package's name in book-keeping table */ - lua_rawget(L, 2); - if (lua_toboolean(L, -1)) /* is it there? */ - return 1; /* package is already loaded; return its result */ - else { /* must load it */ - while (status == LUA_ERRFILE) { - lua_settop(L, 3); /* reset stack position */ - if ((path = pushnextpath(L, path)) == NULL) break; - pushcomposename(L); - status = luaL_loadfile(L, lua_tostring(L, -1)); /* try to load it */ - } - } - switch (status) { - case 0: { - lua_getglobal(L, "_REQUIREDNAME"); /* save previous name */ - lua_insert(L, -2); /* put it below function */ - lua_pushvalue(L, 1); - lua_setglobal(L, "_REQUIREDNAME"); /* set new name */ - lua_call(L, 0, 1); /* run loaded module */ - lua_insert(L, -2); /* put result below previous name */ - lua_setglobal(L, "_REQUIREDNAME"); /* reset to previous name */ - if (lua_isnil(L, -1)) { /* no/nil return? */ - lua_pushboolean(L, 1); - lua_replace(L, -2); /* replace to true */ - } - lua_pushvalue(L, 1); - lua_pushvalue(L, -2); - lua_rawset(L, 2); /* mark it as loaded */ - return 1; /* return value */ - } - case LUA_ERRFILE: { /* file not found */ - return luaL_error(L, "could not load package `%s' from path `%s'", - lua_tostring(L, 1), getpath(L)); - } - default: { - return luaL_error(L, "error loading package `%s' (%s)", - lua_tostring(L, 1), lua_tostring(L, -1)); - } - } -} - -/* }====================================================== */ - - -static const luaL_reg base_funcs[] = { - {"error", luaB_error}, - {"getmetatable", luaB_getmetatable}, - {"setmetatable", luaB_setmetatable}, - {"getfenv", luaB_getfenv}, - {"setfenv", luaB_setfenv}, - {"next", luaB_next}, - {"ipairs", luaB_ipairs}, - {"pairs", luaB_pairs}, - {"print", luaB_print}, - {"tonumber", luaB_tonumber}, - {"tostring", luaB_tostring}, - {"type", luaB_type}, - {"assert", luaB_assert}, - {"unpack", luaB_unpack}, - {"rawequal", luaB_rawequal}, - {"rawget", luaB_rawget}, - {"rawset", luaB_rawset}, - {"pcall", luaB_pcall}, - {"xpcall", luaB_xpcall}, - {"collectgarbage", luaB_collectgarbage}, - {"gcinfo", luaB_gcinfo}, - {"loadfile", luaB_loadfile}, - {"dofile", luaB_dofile}, - {"loadstring", luaB_loadstring}, - {"require", luaB_require}, - {NULL, NULL} -}; - - -/* -** {====================================================== -** Coroutine library -** ======================================================= -*/ - -static int auxresume (lua_State *L, lua_State *co, int narg) { - int status; - if (!lua_checkstack(co, narg)) - luaL_error(L, "too many arguments to resume"); - lua_xmove(L, co, narg); - status = lua_resume(co, narg); - if (status == 0) { - int nres = lua_gettop(co); - if (!lua_checkstack(L, nres)) - luaL_error(L, "too many results to resume"); - lua_xmove(co, L, nres); /* move yielded values */ - return nres; - } - else { - lua_xmove(co, L, 1); /* move error message */ - return -1; /* error flag */ - } -} - - -static int luaB_coresume (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - int r; - luaL_argcheck(L, co, 1, "coroutine expected"); - r = auxresume(L, co, lua_gettop(L) - 1); - if (r < 0) { - lua_pushboolean(L, 0); - lua_insert(L, -2); - return 2; /* return false + error message */ - } - else { - lua_pushboolean(L, 1); - lua_insert(L, -(r + 1)); - return r + 1; /* return true + `resume' returns */ - } -} - - -static int luaB_auxwrap (lua_State *L) { - lua_State *co = lua_tothread(L, lua_upvalueindex(1)); - int r = auxresume(L, co, lua_gettop(L)); - if (r < 0) { - if (lua_isstring(L, -1)) { /* error object is a string? */ - luaL_where(L, 1); /* add extra info */ - lua_insert(L, -2); - lua_concat(L, 2); - } - lua_error(L); /* propagate error */ - } - return r; -} - - -static int luaB_cocreate (lua_State *L) { - lua_State *NL = lua_newthread(L); - luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, - "Lua function expected"); - lua_pushvalue(L, 1); /* move function to top */ - lua_xmove(L, NL, 1); /* move function from L to NL */ - return 1; -} - - -static int luaB_cowrap (lua_State *L) { - luaB_cocreate(L); - lua_pushcclosure(L, luaB_auxwrap, 1); - return 1; -} - - -static int luaB_yield (lua_State *L) { - return lua_yield(L, lua_gettop(L)); -} - - -static int luaB_costatus (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - luaL_argcheck(L, co, 1, "coroutine expected"); - if (L == co) lua_pushliteral(L, "running"); - else { - lua_Debug ar; - if (lua_getstack(co, 0, &ar) == 0 && lua_gettop(co) == 0) - lua_pushliteral(L, "dead"); - else - lua_pushliteral(L, "suspended"); - } - return 1; -} - - -static const luaL_reg co_funcs[] = { - {"create", luaB_cocreate}, - {"wrap", luaB_cowrap}, - {"resume", luaB_coresume}, - {"yield", luaB_yield}, - {"status", luaB_costatus}, - {NULL, NULL} -}; - -/* }====================================================== */ - - - -static void base_open (lua_State *L) { - lua_pushliteral(L, "_G"); - lua_pushvalue(L, LUA_GLOBALSINDEX); - luaL_openlib(L, NULL, base_funcs, 0); /* open lib into global table */ - lua_pushliteral(L, "_VERSION"); - lua_pushliteral(L, LUA_VERSION); - lua_rawset(L, -3); /* set global _VERSION */ - /* `newproxy' needs a weaktable as upvalue */ - lua_pushliteral(L, "newproxy"); - lua_newtable(L); /* new table `w' */ - lua_pushvalue(L, -1); /* `w' will be its own metatable */ - lua_setmetatable(L, -2); - lua_pushliteral(L, "__mode"); - lua_pushliteral(L, "k"); - lua_rawset(L, -3); /* metatable(w).__mode = "k" */ - lua_pushcclosure(L, luaB_newproxy, 1); - lua_rawset(L, -3); /* set global `newproxy' */ - lua_rawset(L, -1); /* set global _G */ -} - - -LUALIB_API int luaopen_base (lua_State *L) { - base_open(L); - luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0); - lua_newtable(L); - lua_setglobal(L, REQTAB); - return 0; -} - +/* +** $Id: lbaselib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $ +** Basic library +** See Copyright Notice in lua.h +*/ + + + +#include +#include +#include +#include + +#define lbaselib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + + +/* +** If your system does not support `stdout', you can just remove this function. +** If you need, you can define your own `print' function, following this +** model but changing `fputs' to put the strings at a proper place +** (a console window or a log file, for instance). +*/ +static int luaB_print (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + lua_getglobal(L, "tostring"); + for (i=1; i<=n; i++) { + const char *s; + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + s = lua_tostring(L, -1); /* get result */ + if (s == NULL) + return luaL_error(L, "`tostring' must return a string to `print'"); + if (i>1) fputs("\t", stdout); + fputs(s, stdout); + lua_pop(L, 1); /* pop result */ + } + fputs("\n", stdout); + return 0; +} + + +static int luaB_tonumber (lua_State *L) { + int base = luaL_optint(L, 2, 10); + if (base == 10) { /* standard conversion */ + luaL_checkany(L, 1); + if (lua_isnumber(L, 1)) { + lua_pushnumber(L, lua_tonumber(L, 1)); + return 1; + } + } + else { + const char *s1 = luaL_checkstring(L, 1); + char *s2; + unsigned long n; + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + n = strtoul(s1, &s2, base); + if (s1 != s2) { /* at least one valid digit? */ + while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ + if (*s2 == '\0') { /* no invalid trailing characters? */ + lua_pushnumber(L, (lua_Number)n); + return 1; + } + } + } + lua_pushnil(L); /* else not a number */ + return 1; +} + + +static int luaB_error (lua_State *L) { + int level = luaL_optint(L, 2, 1); + luaL_checkany(L, 1); + if (!lua_isstring(L, 1) || level == 0) + lua_pushvalue(L, 1); /* propagate error message without changes */ + else { /* add extra information */ + luaL_where(L, level); + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + return lua_error(L); +} + + +static int luaB_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); + return 1; /* no metatable */ + } + luaL_getmetafield(L, 1, "__metatable"); + return 1; /* returns either __metatable field (if present) or metatable */ +} + + +static int luaB_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + if (luaL_getmetafield(L, 1, "__metatable")) + luaL_error(L, "cannot change a protected metatable"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; +} + + +static void getfunc (lua_State *L) { + if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); + else { + lua_Debug ar; + int level = luaL_optint(L, 1, 1); + luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); + if (lua_getstack(L, level, &ar) == 0) + luaL_argerror(L, 1, "invalid level"); + lua_getinfo(L, "f", &ar); + if (lua_isnil(L, -1)) + luaL_error(L, "no function environment for tail call at level %d", + level); + } +} + + +static int aux_getfenv (lua_State *L) { + lua_getfenv(L, -1); + lua_pushliteral(L, "__fenv"); + lua_rawget(L, -2); + return !lua_isnil(L, -1); +} + + +static int luaB_getfenv (lua_State *L) { + getfunc(L); + if (!aux_getfenv(L)) /* __fenv not defined? */ + lua_pop(L, 1); /* remove it, to return real environment */ + return 1; +} + + +static int luaB_setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + getfunc(L); + if (aux_getfenv(L)) /* __fenv defined? */ + luaL_error(L, "`setfenv' cannot change a protected environment"); + else + lua_pop(L, 2); /* remove __fenv and real environment table */ + lua_pushvalue(L, 2); + if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) + lua_replace(L, LUA_GLOBALSINDEX); + else if (lua_setfenv(L, -2) == 0) + luaL_error(L, "`setfenv' cannot change environment of given function"); + return 0; +} + + +static int luaB_rawequal (lua_State *L) { + luaL_checkany(L, 1); + luaL_checkany(L, 2); + lua_pushboolean(L, lua_rawequal(L, 1, 2)); + return 1; +} + + +static int luaB_rawget (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_rawget(L, 1); + return 1; +} + +static int luaB_rawset (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + luaL_checkany(L, 3); + lua_rawset(L, 1); + return 1; +} + + +static int luaB_gcinfo (lua_State *L) { + lua_pushnumber(L, (lua_Number)lua_getgccount(L)); + lua_pushnumber(L, (lua_Number)lua_getgcthreshold(L)); + return 2; +} + + +static int luaB_collectgarbage (lua_State *L) { + lua_setgcthreshold(L, luaL_optint(L, 1, 0)); + return 0; +} + + +static int luaB_type (lua_State *L) { + luaL_checkany(L, 1); + lua_pushstring(L, lua_typename(L, lua_type(L, 1))); + return 1; +} + + +static int luaB_next (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + + +static int luaB_pairs (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushliteral(L, "next"); + lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushnil(L); /* and initial value */ + return 3; +} + + +static int luaB_ipairs (lua_State *L) { + lua_Number i = lua_tonumber(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + if (i == 0 && lua_isnone(L, 2)) { /* `for' start? */ + lua_pushliteral(L, "ipairs"); + lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushnumber(L, 0); /* and initial value */ + return 3; + } + else { /* `for' step */ + i++; /* next value */ + lua_pushnumber(L, i); + lua_rawgeti(L, 1, (int)i); + return (lua_isnil(L, -1)) ? 0 : 2; + } +} + + +static int load_aux (lua_State *L, int status) { + if (status == 0) /* OK? */ + return 1; + else { + lua_pushnil(L); + lua_insert(L, -2); /* put before error message */ + return 2; /* return nil plus error message */ + } +} + + +static int luaB_loadstring (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + const char *chunkname = luaL_optstring(L, 2, s); + return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); +} + + +static int luaB_loadfile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + return load_aux(L, luaL_loadfile(L, fname)); +} + + +static int luaB_dofile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + int status = luaL_loadfile(L, fname); + if (status != 0) lua_error(L); + lua_call(L, 0, LUA_MULTRET); + return lua_gettop(L) - 1; +} + + +static int luaB_assert (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_toboolean(L, 1)) + return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); + lua_settop(L, 1); + return 1; +} + + +static int luaB_unpack (lua_State *L) { + int n, i; + luaL_checktype(L, 1, LUA_TTABLE); + n = luaL_getn(L, 1); + luaL_checkstack(L, n, "table too big to unpack"); + for (i=1; i<=n; i++) /* push arg[1...n] */ + lua_rawgeti(L, 1, i); + return n; +} + + +static int luaB_pcall (lua_State *L) { + int status; + luaL_checkany(L, 1); + status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); + lua_pushboolean(L, (status == 0)); + lua_insert(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_xpcall (lua_State *L) { + int status; + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_insert(L, 1); /* put error function under function to be called */ + status = lua_pcall(L, 0, LUA_MULTRET, 1); + lua_pushboolean(L, (status == 0)); + lua_replace(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_tostring (lua_State *L) { + char buff[64]; + luaL_checkany(L, 1); + if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ + return 1; /* use its value */ + switch (lua_type(L, 1)) { + case LUA_TNUMBER: + lua_pushstring(L, lua_tostring(L, 1)); + return 1; + case LUA_TSTRING: + lua_pushvalue(L, 1); + return 1; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); + return 1; + case LUA_TTABLE: + sprintf(buff, "table: %p", lua_topointer(L, 1)); + break; + case LUA_TFUNCTION: + sprintf(buff, "function: %p", lua_topointer(L, 1)); + break; + case LUA_TUSERDATA: + case LUA_TLIGHTUSERDATA: + sprintf(buff, "userdata: %p", lua_touserdata(L, 1)); + break; + case LUA_TTHREAD: + sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1)); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + return 1; + } + lua_pushstring(L, buff); + return 1; +} + + +static int luaB_newproxy (lua_State *L) { + lua_settop(L, 1); + lua_newuserdata(L, 0); /* create proxy */ + if (lua_toboolean(L, 1) == 0) + return 1; /* no metatable */ + else if (lua_isboolean(L, 1)) { + lua_newtable(L); /* create a new metatable `m' ... */ + lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ + lua_pushboolean(L, 1); + lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ + } + else { + int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ + if (lua_getmetatable(L, 1)) { + lua_rawget(L, lua_upvalueindex(1)); + validproxy = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + } + luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); + lua_getmetatable(L, 1); /* metatable is valid; get it */ + } + lua_setmetatable(L, 2); + return 1; +} + + +/* +** {====================================================== +** `require' function +** ======================================================= +*/ + + +/* name of global that holds table with loaded packages */ +#define REQTAB "_LOADED" + +/* name of global that holds the search path for packages */ +#define LUA_PATH "LUA_PATH" + +#ifndef LUA_PATH_SEP +#define LUA_PATH_SEP ';' +#endif + +#ifndef LUA_PATH_MARK +#define LUA_PATH_MARK '?' +#endif + +#ifndef LUA_PATH_DEFAULT +#define LUA_PATH_DEFAULT "?;?.lua" +#endif + + +static const char *getpath (lua_State *L) { + const char *path; + lua_getglobal(L, LUA_PATH); /* try global variable */ + path = lua_tostring(L, -1); + lua_pop(L, 1); + if (path) return path; + path = getenv(LUA_PATH); /* else try environment variable */ + if (path) return path; + return LUA_PATH_DEFAULT; /* else use default */ +} + + +static const char *pushnextpath (lua_State *L, const char *path) { + const char *l; + if (*path == '\0') return NULL; /* no more paths */ + if (*path == LUA_PATH_SEP) path++; /* skip separator */ + l = strchr(path, LUA_PATH_SEP); /* find next separator */ + if (l == NULL) l = path+strlen(path); + lua_pushlstring(L, path, l - path); /* directory name */ + return l; +} + + +static void pushcomposename (lua_State *L) { + const char *path = lua_tostring(L, -1); + const char *wild; + int n = 1; + while ((wild = strchr(path, LUA_PATH_MARK)) != NULL) { + /* is there stack space for prefix, name, and eventual last sufix? */ + luaL_checkstack(L, 3, "too many marks in a path component"); + lua_pushlstring(L, path, wild - path); /* push prefix */ + lua_pushvalue(L, 1); /* push package name (in place of MARK) */ + path = wild + 1; /* continue after MARK */ + n += 2; + } + lua_pushstring(L, path); /* push last sufix (`n' already includes this) */ + lua_concat(L, n); +} + + +static int luaB_require (lua_State *L) { + const char *path; + int status = LUA_ERRFILE; /* not found (yet) */ + luaL_checkstring(L, 1); + lua_settop(L, 1); + lua_getglobal(L, REQTAB); + if (!lua_istable(L, 2)) return luaL_error(L, "`" REQTAB "' is not a table"); + path = getpath(L); + lua_pushvalue(L, 1); /* check package's name in book-keeping table */ + lua_rawget(L, 2); + if (lua_toboolean(L, -1)) /* is it there? */ + return 1; /* package is already loaded; return its result */ + else { /* must load it */ + while (status == LUA_ERRFILE) { + lua_settop(L, 3); /* reset stack position */ + if ((path = pushnextpath(L, path)) == NULL) break; + pushcomposename(L); + status = luaL_loadfile(L, lua_tostring(L, -1)); /* try to load it */ + } + } + switch (status) { + case 0: { + lua_getglobal(L, "_REQUIREDNAME"); /* save previous name */ + lua_insert(L, -2); /* put it below function */ + lua_pushvalue(L, 1); + lua_setglobal(L, "_REQUIREDNAME"); /* set new name */ + lua_call(L, 0, 1); /* run loaded module */ + lua_insert(L, -2); /* put result below previous name */ + lua_setglobal(L, "_REQUIREDNAME"); /* reset to previous name */ + if (lua_isnil(L, -1)) { /* no/nil return? */ + lua_pushboolean(L, 1); + lua_replace(L, -2); /* replace to true */ + } + lua_pushvalue(L, 1); + lua_pushvalue(L, -2); + lua_rawset(L, 2); /* mark it as loaded */ + return 1; /* return value */ + } + case LUA_ERRFILE: { /* file not found */ + return luaL_error(L, "could not load package `%s' from path `%s'", + lua_tostring(L, 1), getpath(L)); + } + default: { + return luaL_error(L, "error loading package `%s' (%s)", + lua_tostring(L, 1), lua_tostring(L, -1)); + } + } +} + +/* }====================================================== */ + + +static const luaL_reg base_funcs[] = { + {"error", luaB_error}, + {"getmetatable", luaB_getmetatable}, + {"setmetatable", luaB_setmetatable}, + {"getfenv", luaB_getfenv}, + {"setfenv", luaB_setfenv}, + {"next", luaB_next}, + {"ipairs", luaB_ipairs}, + {"pairs", luaB_pairs}, + {"print", luaB_print}, + {"tonumber", luaB_tonumber}, + {"tostring", luaB_tostring}, + {"type", luaB_type}, + {"assert", luaB_assert}, + {"unpack", luaB_unpack}, + {"rawequal", luaB_rawequal}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"pcall", luaB_pcall}, + {"xpcall", luaB_xpcall}, + {"collectgarbage", luaB_collectgarbage}, + {"gcinfo", luaB_gcinfo}, + {"loadfile", luaB_loadfile}, + {"dofile", luaB_dofile}, + {"loadstring", luaB_loadstring}, + {"require", luaB_require}, + {NULL, NULL} +}; + + +/* +** {====================================================== +** Coroutine library +** ======================================================= +*/ + +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status; + if (!lua_checkstack(co, narg)) + luaL_error(L, "too many arguments to resume"); + lua_xmove(L, co, narg); + status = lua_resume(co, narg); + if (status == 0) { + int nres = lua_gettop(co); + if (!lua_checkstack(L, nres)) + luaL_error(L, "too many results to resume"); + lua_xmove(co, L, nres); /* move yielded values */ + return nres; + } + else { + lua_xmove(co, L, 1); /* move error message */ + return -1; /* error flag */ + } +} + + +static int luaB_coresume (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + int r; + luaL_argcheck(L, co, 1, "coroutine expected"); + r = auxresume(L, co, lua_gettop(L) - 1); + if (r < 0) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + lua_insert(L, -(r + 1)); + return r + 1; /* return true + `resume' returns */ + } +} + + +static int luaB_auxwrap (lua_State *L) { + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); + int r = auxresume(L, co, lua_gettop(L)); + if (r < 0) { + if (lua_isstring(L, -1)) { /* error object is a string? */ + luaL_where(L, 1); /* add extra info */ + lua_insert(L, -2); + lua_concat(L, 2); + } + lua_error(L); /* propagate error */ + } + return r; +} + + +static int luaB_cocreate (lua_State *L) { + lua_State *NL = lua_newthread(L); + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, + "Lua function expected"); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + return 1; +} + + +static int luaB_cowrap (lua_State *L) { + luaB_cocreate(L); + lua_pushcclosure(L, luaB_auxwrap, 1); + return 1; +} + + +static int luaB_yield (lua_State *L) { + return lua_yield(L, lua_gettop(L)); +} + + +static int luaB_costatus (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "coroutine expected"); + if (L == co) lua_pushliteral(L, "running"); + else { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) == 0 && lua_gettop(co) == 0) + lua_pushliteral(L, "dead"); + else + lua_pushliteral(L, "suspended"); + } + return 1; +} + + +static const luaL_reg co_funcs[] = { + {"create", luaB_cocreate}, + {"wrap", luaB_cowrap}, + {"resume", luaB_coresume}, + {"yield", luaB_yield}, + {"status", luaB_costatus}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +static void base_open (lua_State *L) { + lua_pushliteral(L, "_G"); + lua_pushvalue(L, LUA_GLOBALSINDEX); + luaL_openlib(L, NULL, base_funcs, 0); /* open lib into global table */ + lua_pushliteral(L, "_VERSION"); + lua_pushliteral(L, LUA_VERSION); + lua_rawset(L, -3); /* set global _VERSION */ + /* `newproxy' needs a weaktable as upvalue */ + lua_pushliteral(L, "newproxy"); + lua_newtable(L); /* new table `w' */ + lua_pushvalue(L, -1); /* `w' will be its own metatable */ + lua_setmetatable(L, -2); + lua_pushliteral(L, "__mode"); + lua_pushliteral(L, "k"); + lua_rawset(L, -3); /* metatable(w).__mode = "k" */ + lua_pushcclosure(L, luaB_newproxy, 1); + lua_rawset(L, -3); /* set global `newproxy' */ + lua_rawset(L, -1); /* set global _G */ +} + + +LUALIB_API int luaopen_base (lua_State *L) { + base_open(L); + luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0); + lua_newtable(L); + lua_setglobal(L, REQTAB); + return 0; +} + diff --git a/lib/lua/src/LuaLib/ldblib.c b/lib/lua/src/LuaLib/ldblib.c index 455b89f..2449b90 100644 --- a/lib/lua/src/LuaLib/ldblib.c +++ b/lib/lua/src/LuaLib/ldblib.c @@ -1,299 +1,299 @@ -/* -** $Id: ldblib.c,v 1.3 2004-11-27 21:35:21 pixel Exp $ -** Interface from Lua to its debug API -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#define ldblib_c - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - -static void settabss (lua_State *L, const char *i, const char *v) { - lua_pushstring(L, i); - lua_pushstring(L, v); - lua_rawset(L, -3); -} - - -static void settabsi (lua_State *L, const char *i, int v) { - lua_pushstring(L, i); - lua_pushnumber(L, (lua_Number)v); - lua_rawset(L, -3); -} - - -static int getinfo (lua_State *L) { - lua_Debug ar; - const char *options = luaL_optstring(L, 2, "flnSu"); - if (lua_isnumber(L, 1)) { - if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) { - lua_pushnil(L); /* level out of range */ - return 1; - } - } - else if (lua_isfunction(L, 1)) { - lua_pushfstring(L, ">%s", options); - options = lua_tostring(L, -1); - lua_pushvalue(L, 1); - } - else - return luaL_argerror(L, 1, "function or level expected"); - if (!lua_getinfo(L, options, &ar)) - return luaL_argerror(L, 2, "invalid option"); - lua_newtable(L); - for (; *options; options++) { - switch (*options) { - case 'S': - settabss(L, "source", ar.source); - settabss(L, "short_src", ar.short_src); - settabsi(L, "linedefined", ar.linedefined); - settabss(L, "what", ar.what); - break; - case 'l': - settabsi(L, "currentline", ar.currentline); - break; - case 'u': - settabsi(L, "nups", ar.nups); - break; - case 'n': - settabss(L, "name", ar.name); - settabss(L, "namewhat", ar.namewhat); - break; - case 'f': - lua_pushliteral(L, "func"); - lua_pushvalue(L, -3); - lua_rawset(L, -3); - break; - } - } - return 1; /* return table */ -} - - -static int getlocal (lua_State *L) { - lua_Debug ar; - const char *name; - if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */ - return luaL_argerror(L, 1, "level out of range"); - name = lua_getlocal(L, &ar, luaL_checkint(L, 2)); - if (name) { - lua_pushstring(L, name); - lua_pushvalue(L, -2); - return 2; - } - else { - lua_pushnil(L); - return 1; - } -} - - -static int setlocal (lua_State *L) { - lua_Debug ar; - if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */ - return luaL_argerror(L, 1, "level out of range"); - luaL_checkany(L, 3); - lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2))); - return 1; -} - - -static int auxupvalue (lua_State *L, int get) { - const char *name; - int n = luaL_checkint(L, 2); - luaL_checktype(L, 1, LUA_TFUNCTION); - if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ - name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); - if (name == NULL) return 0; - lua_pushstring(L, name); - lua_insert(L, -(get+1)); - return get + 1; -} - - -static int getupvalue (lua_State *L) { - return auxupvalue(L, 1); -} - - -static int setupvalue (lua_State *L) { - luaL_checkany(L, 3); - return auxupvalue(L, 0); -} - - - -static const char KEY_HOOK = 'h'; - - -static void hookf (lua_State *L, lua_Debug *ar) { - static const char *const hooknames[] = - {"call", "return", "line", "count", "tail return"}; - lua_pushlightuserdata(L, (void *)&KEY_HOOK); - lua_rawget(L, LUA_REGISTRYINDEX); - if (lua_isfunction(L, -1)) { - lua_pushstring(L, hooknames[(int)ar->event]); - if (ar->currentline >= 0) - lua_pushnumber(L, (lua_Number)ar->currentline); - else lua_pushnil(L); - lua_assert(lua_getinfo(L, "lS", ar)); - lua_call(L, 2, 0); - } - else - lua_pop(L, 1); /* pop result from gettable */ -} - - -static int makemask (const char *smask, int count) { - int mask = 0; - if (strchr(smask, 'c')) mask |= LUA_MASKCALL; - if (strchr(smask, 'r')) mask |= LUA_MASKRET; - if (strchr(smask, 'l')) mask |= LUA_MASKLINE; - if (count > 0) mask |= LUA_MASKCOUNT; - return mask; -} - - -static char *unmakemask (int mask, char *smask) { - int i = 0; - if (mask & LUA_MASKCALL) smask[i++] = 'c'; - if (mask & LUA_MASKRET) smask[i++] = 'r'; - if (mask & LUA_MASKLINE) smask[i++] = 'l'; - smask[i] = '\0'; - return smask; -} - - -static int sethook (lua_State *L) { - if (lua_isnoneornil(L, 1)) { - lua_settop(L, 1); - lua_sethook(L, NULL, 0, 0); /* turn off hooks */ - } - else { - const char *smask = luaL_checkstring(L, 2); - int count = luaL_optint(L, 3, 0); - luaL_checktype(L, 1, LUA_TFUNCTION); - lua_sethook(L, hookf, makemask(smask, count), count); - } - lua_pushlightuserdata(L, (void *)&KEY_HOOK); - lua_pushvalue(L, 1); - lua_rawset(L, LUA_REGISTRYINDEX); /* set new hook */ - return 0; -} - - -static int gethook (lua_State *L) { - char buff[5]; - int mask = lua_gethookmask(L); - lua_Hook hook = lua_gethook(L); - if (hook != NULL && hook != hookf) /* external hook? */ - lua_pushliteral(L, "external hook"); - else { - lua_pushlightuserdata(L, (void *)&KEY_HOOK); - lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */ - } - lua_pushstring(L, unmakemask(mask, buff)); - lua_pushnumber(L, (lua_Number)lua_gethookcount(L)); - return 3; -} - - -static int debug (lua_State *L) { - for (;;) { - char buffer[250]; - fputs("lua_debug> ", stderr); - if (fgets(buffer, sizeof(buffer), stdin) == 0 || - strcmp(buffer, "cont\n") == 0) - return 0; - lua_dostring(L, buffer); - lua_settop(L, 0); /* remove eventual returns */ - } -} - - -#define LEVELS1 12 /* size of the first part of the stack */ -#define LEVELS2 10 /* size of the second part of the stack */ - -static int errorfb (lua_State *L) { - int level = 1; /* skip level 0 (it's this function) */ - int firstpart = 1; /* still before eventual `...' */ - lua_Debug ar; - if (lua_gettop(L) == 0) - lua_pushliteral(L, ""); - else if (!lua_isstring(L, 1)) return 1; /* no string message */ - else lua_pushliteral(L, "\n"); - lua_pushliteral(L, "stack traceback:"); - while (lua_getstack(L, level++, &ar)) { - if (level > LEVELS1 && firstpart) { - /* no more than `LEVELS2' more levels? */ - if (!lua_getstack(L, level+LEVELS2, &ar)) - level--; /* keep going */ - else { - lua_pushliteral(L, "\n\t..."); /* too many levels */ - while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */ - level++; - } - firstpart = 0; - continue; - } - lua_pushliteral(L, "\n\t"); - lua_getinfo(L, "Snl", &ar); - lua_pushfstring(L, "%s:", ar.short_src); - if (ar.currentline > 0) - lua_pushfstring(L, "%d:", ar.currentline); - switch (*ar.namewhat) { - case 'g': /* global */ - case 'l': /* local */ - case 'f': /* field */ - case 'm': /* method */ - lua_pushfstring(L, " in function `%s'", ar.name); - break; - default: { - if (*ar.what == 'm') /* main? */ - lua_pushfstring(L, " in main chunk"); - else if (*ar.what == 'C' || *ar.what == 't') - lua_pushliteral(L, " ?"); /* C function or tail call */ - else - lua_pushfstring(L, " in function <%s:%d>", - ar.short_src, ar.linedefined); - } - } - lua_concat(L, lua_gettop(L)); - } - lua_concat(L, lua_gettop(L)); - return 1; -} - - -static const luaL_reg dblib[] = { - {"getlocal", getlocal}, - {"getinfo", getinfo}, - {"gethook", gethook}, - {"getupvalue", getupvalue}, - {"sethook", sethook}, - {"setlocal", setlocal}, - {"setupvalue", setupvalue}, - {"debug", debug}, - {"traceback", errorfb}, - {NULL, NULL} -}; - - -LUALIB_API int luaopen_debug (lua_State *L) { - luaL_openlib(L, LUA_DBLIBNAME, dblib, 0); - lua_pushliteral(L, "_TRACEBACK"); - lua_pushcfunction(L, errorfb); - lua_settable(L, LUA_GLOBALSINDEX); - return 1; -} - +/* +** $Id: ldblib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $ +** Interface from Lua to its debug API +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define ldblib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +static void settabss (lua_State *L, const char *i, const char *v) { + lua_pushstring(L, i); + lua_pushstring(L, v); + lua_rawset(L, -3); +} + + +static void settabsi (lua_State *L, const char *i, int v) { + lua_pushstring(L, i); + lua_pushnumber(L, (lua_Number)v); + lua_rawset(L, -3); +} + + +static int getinfo (lua_State *L) { + lua_Debug ar; + const char *options = luaL_optstring(L, 2, "flnSu"); + if (lua_isnumber(L, 1)) { + if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) { + lua_pushnil(L); /* level out of range */ + return 1; + } + } + else if (lua_isfunction(L, 1)) { + lua_pushfstring(L, ">%s", options); + options = lua_tostring(L, -1); + lua_pushvalue(L, 1); + } + else + return luaL_argerror(L, 1, "function or level expected"); + if (!lua_getinfo(L, options, &ar)) + return luaL_argerror(L, 2, "invalid option"); + lua_newtable(L); + for (; *options; options++) { + switch (*options) { + case 'S': + settabss(L, "source", ar.source); + settabss(L, "short_src", ar.short_src); + settabsi(L, "linedefined", ar.linedefined); + settabss(L, "what", ar.what); + break; + case 'l': + settabsi(L, "currentline", ar.currentline); + break; + case 'u': + settabsi(L, "nups", ar.nups); + break; + case 'n': + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + break; + case 'f': + lua_pushliteral(L, "func"); + lua_pushvalue(L, -3); + lua_rawset(L, -3); + break; + } + } + return 1; /* return table */ +} + + +static int getlocal (lua_State *L) { + lua_Debug ar; + const char *name; + if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */ + return luaL_argerror(L, 1, "level out of range"); + name = lua_getlocal(L, &ar, luaL_checkint(L, 2)); + if (name) { + lua_pushstring(L, name); + lua_pushvalue(L, -2); + return 2; + } + else { + lua_pushnil(L); + return 1; + } +} + + +static int setlocal (lua_State *L) { + lua_Debug ar; + if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */ + return luaL_argerror(L, 1, "level out of range"); + luaL_checkany(L, 3); + lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2))); + return 1; +} + + +static int auxupvalue (lua_State *L, int get) { + const char *name; + int n = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + lua_insert(L, -(get+1)); + return get + 1; +} + + +static int getupvalue (lua_State *L) { + return auxupvalue(L, 1); +} + + +static int setupvalue (lua_State *L) { + luaL_checkany(L, 3); + return auxupvalue(L, 0); +} + + + +static const char KEY_HOOK = 'h'; + + +static void hookf (lua_State *L, lua_Debug *ar) { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail return"}; + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); + if (lua_isfunction(L, -1)) { + lua_pushstring(L, hooknames[(int)ar->event]); + if (ar->currentline >= 0) + lua_pushnumber(L, (lua_Number)ar->currentline); + else lua_pushnil(L); + lua_assert(lua_getinfo(L, "lS", ar)); + lua_call(L, 2, 0); + } + else + lua_pop(L, 1); /* pop result from gettable */ +} + + +static int makemask (const char *smask, int count) { + int mask = 0; + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; + if (strchr(smask, 'r')) mask |= LUA_MASKRET; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + return mask; +} + + +static char *unmakemask (int mask, char *smask) { + int i = 0; + if (mask & LUA_MASKCALL) smask[i++] = 'c'; + if (mask & LUA_MASKRET) smask[i++] = 'r'; + if (mask & LUA_MASKLINE) smask[i++] = 'l'; + smask[i] = '\0'; + return smask; +} + + +static int sethook (lua_State *L) { + if (lua_isnoneornil(L, 1)) { + lua_settop(L, 1); + lua_sethook(L, NULL, 0, 0); /* turn off hooks */ + } + else { + const char *smask = luaL_checkstring(L, 2); + int count = luaL_optint(L, 3, 0); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_sethook(L, hookf, makemask(smask, count), count); + } + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_pushvalue(L, 1); + lua_rawset(L, LUA_REGISTRYINDEX); /* set new hook */ + return 0; +} + + +static int gethook (lua_State *L) { + char buff[5]; + int mask = lua_gethookmask(L); + lua_Hook hook = lua_gethook(L); + if (hook != NULL && hook != hookf) /* external hook? */ + lua_pushliteral(L, "external hook"); + else { + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */ + } + lua_pushstring(L, unmakemask(mask, buff)); + lua_pushnumber(L, (lua_Number)lua_gethookcount(L)); + return 3; +} + + +static int debug (lua_State *L) { + for (;;) { + char buffer[250]; + fputs("lua_debug> ", stderr); + if (fgets(buffer, sizeof(buffer), stdin) == 0 || + strcmp(buffer, "cont\n") == 0) + return 0; + lua_dostring(L, buffer); + lua_settop(L, 0); /* remove eventual returns */ + } +} + + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + +static int errorfb (lua_State *L) { + int level = 1; /* skip level 0 (it's this function) */ + int firstpart = 1; /* still before eventual `...' */ + lua_Debug ar; + if (lua_gettop(L) == 0) + lua_pushliteral(L, ""); + else if (!lua_isstring(L, 1)) return 1; /* no string message */ + else lua_pushliteral(L, "\n"); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L, level++, &ar)) { + if (level > LEVELS1 && firstpart) { + /* no more than `LEVELS2' more levels? */ + if (!lua_getstack(L, level+LEVELS2, &ar)) + level--; /* keep going */ + else { + lua_pushliteral(L, "\n\t..."); /* too many levels */ + while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */ + level++; + } + firstpart = 0; + continue; + } + lua_pushliteral(L, "\n\t"); + lua_getinfo(L, "Snl", &ar); + lua_pushfstring(L, "%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + switch (*ar.namewhat) { + case 'g': /* global */ + case 'l': /* local */ + case 'f': /* field */ + case 'm': /* method */ + lua_pushfstring(L, " in function `%s'", ar.name); + break; + default: { + if (*ar.what == 'm') /* main? */ + lua_pushfstring(L, " in main chunk"); + else if (*ar.what == 'C' || *ar.what == 't') + lua_pushliteral(L, " ?"); /* C function or tail call */ + else + lua_pushfstring(L, " in function <%s:%d>", + ar.short_src, ar.linedefined); + } + } + lua_concat(L, lua_gettop(L)); + } + lua_concat(L, lua_gettop(L)); + return 1; +} + + +static const luaL_reg dblib[] = { + {"getlocal", getlocal}, + {"getinfo", getinfo}, + {"gethook", gethook}, + {"getupvalue", getupvalue}, + {"sethook", sethook}, + {"setlocal", setlocal}, + {"setupvalue", setupvalue}, + {"debug", debug}, + {"traceback", errorfb}, + {NULL, NULL} +}; + + +LUALIB_API int luaopen_debug (lua_State *L) { + luaL_openlib(L, LUA_DBLIBNAME, dblib, 0); + lua_pushliteral(L, "_TRACEBACK"); + lua_pushcfunction(L, errorfb); + lua_settable(L, LUA_GLOBALSINDEX); + return 1; +} + diff --git a/lib/lua/src/LuaLib/ldirlib.c b/lib/lua/src/LuaLib/ldirlib.c index 4e221b4..9bf2090 100644 --- a/lib/lua/src/LuaLib/ldirlib.c +++ b/lib/lua/src/LuaLib/ldirlib.c @@ -1,96 +1,96 @@ -#include -#include -#include -#include - -#define ldirlib_c - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - -/* forward declaration for the iterator function */ -static int dir_iter (lua_State *L); - -static int l_dir (lua_State *L) { - const char *path = luaL_checkstring(L, 1); - - /* create a userdatum to store a DIR address */ - DIR **d = (DIR **)lua_newuserdata(L, sizeof(DIR *)); - - /* set its metatable */ - luaL_getmetatable(L, "LuaBook.dir"); - lua_setmetatable(L, -2); - - /* try to open the given directory */ - *d = opendir(path); - if (*d == NULL) /* error opening the directory? */ - luaL_error(L, "cannot open %s: %s", path, - strerror(errno)); - - /* creates and returns the iterator function - (its sole upvalue, the directory userdatum, - is already on the stack top */ - lua_pushcclosure(L, dir_iter, 1); - return 1; -} - -static int dir_iter (lua_State *L) { - DIR *d = *(DIR **)lua_touserdata(L, lua_upvalueindex(1)); - struct dirent *entry; -#ifdef _WIN32 - struct _stat file_stat; -#else - struct stat file_stat; -#endif - if ((entry = readdir(d)) != NULL) { - lua_newtable(L); - lua_pushstring(L, "name"); - lua_pushstring(L, entry->d_name); - lua_settable(L, -3); -#ifdef _WIN32 - _stat(entry->d_name, &file_stat); -#else - stat(entry->d_name, &file_stat); -#endif - lua_pushstring(L, "type"); - lua_pushnumber(L, (S_IFREG & file_stat.st_mode) ? 2 : ((S_IFDIR & file_stat.st_mode) ? 1 : 0)); - lua_settable(L, -3); - - return 1; - } - else return 0; /* no more values to return */ -} - -static int dir_gc (lua_State *L) { - DIR *d = *(DIR **)lua_touserdata(L, 1); - if (d) closedir(d); - return 0; -} - -static const luaL_reg dirlib[] = { - {NULL, NULL} -}; - -int luaopen_dir (lua_State *L) { - luaL_openlib(L, LUA_DIRLIBNAME, dirlib, 0); - luaL_newmetatable(L, "LuaBook.dir"); - - /* set its __gc field */ - lua_pushstring(L, "__gc"); - lua_pushcfunction(L, dir_gc); - lua_settable(L, -3); - - /* register the `dir' function */ - lua_pushcfunction(L, l_dir); - lua_setglobal(L, "dir"); - - lua_pushnumber(L, 1); - lua_setglobal(L, "FLAG_DIR"); - - lua_pushnumber(L, 2); - lua_setglobal(L, "FLAG_FILE"); - - return 0; -} +#include +#include +#include +#include + +#define ldirlib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + +/* forward declaration for the iterator function */ +static int dir_iter (lua_State *L); + +static int l_dir (lua_State *L) { + const char *path = luaL_checkstring(L, 1); + + /* create a userdatum to store a DIR address */ + DIR **d = (DIR **)lua_newuserdata(L, sizeof(DIR *)); + + /* set its metatable */ + luaL_getmetatable(L, "LuaBook.dir"); + lua_setmetatable(L, -2); + + /* try to open the given directory */ + *d = opendir(path); + if (*d == NULL) /* error opening the directory? */ + luaL_error(L, "cannot open %s: %s", path, + strerror(errno)); + + /* creates and returns the iterator function + (its sole upvalue, the directory userdatum, + is already on the stack top */ + lua_pushcclosure(L, dir_iter, 1); + return 1; +} + +static int dir_iter (lua_State *L) { + DIR *d = *(DIR **)lua_touserdata(L, lua_upvalueindex(1)); + struct dirent *entry; +#ifdef _WIN32 + struct _stat file_stat; +#else + struct stat file_stat; +#endif + if ((entry = readdir(d)) != NULL) { + lua_newtable(L); + lua_pushstring(L, "name"); + lua_pushstring(L, entry->d_name); + lua_settable(L, -3); +#ifdef _WIN32 + _stat(entry->d_name, &file_stat); +#else + stat(entry->d_name, &file_stat); +#endif + lua_pushstring(L, "type"); + lua_pushnumber(L, (S_IFREG & file_stat.st_mode) ? 2 : ((S_IFDIR & file_stat.st_mode) ? 1 : 0)); + lua_settable(L, -3); + + return 1; + } + else return 0; /* no more values to return */ +} + +static int dir_gc (lua_State *L) { + DIR *d = *(DIR **)lua_touserdata(L, 1); + if (d) closedir(d); + return 0; +} + +static const luaL_reg dirlib[] = { + {NULL, NULL} +}; + +int luaopen_dir (lua_State *L) { + luaL_openlib(L, LUA_DIRLIBNAME, dirlib, 0); + luaL_newmetatable(L, "LuaBook.dir"); + + /* set its __gc field */ + lua_pushstring(L, "__gc"); + lua_pushcfunction(L, dir_gc); + lua_settable(L, -3); + + /* register the `dir' function */ + lua_pushcfunction(L, l_dir); + lua_setglobal(L, "dir"); + + lua_pushnumber(L, 1); + lua_setglobal(L, "FLAG_DIR"); + + lua_pushnumber(L, 2); + lua_setglobal(L, "FLAG_FILE"); + + return 0; +} diff --git a/lib/lua/src/LuaLib/liolib.c b/lib/lua/src/LuaLib/liolib.c index 3eeb05f..69e0a19 100644 --- a/lib/lua/src/LuaLib/liolib.c +++ b/lib/lua/src/LuaLib/liolib.c @@ -1,750 +1,750 @@ -/* -** $Id: liolib.c,v 1.3 2004-11-27 21:35:21 pixel Exp $ -** Standard I/O (and system) library -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include -#include - -#define liolib_c - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - -/* -** by default, gcc does not get `tmpname' -*/ -#ifndef USE_TMPNAME -#ifdef __GNUC__ -#define USE_TMPNAME 0 -#else -#define USE_TMPNAME 1 -#endif -#endif - - -/* -** by default, posix systems get `popen' -*/ -#ifndef USE_POPEN -#ifdef _POSIX_C_SOURCE -#if _POSIX_C_SOURCE >= 2 -#define USE_POPEN 1 -#endif -#endif -#endif - -#ifndef USE_POPEN -#define USE_POPEN 0 -#endif - - - - -/* -** {====================================================== -** FILE Operations -** ======================================================= -*/ - - -#if !USE_POPEN -#define pclose(f) (-1) -#endif - - -#define FILEHANDLE "FILE*" - -#define IO_INPUT "_input" -#define IO_OUTPUT "_output" - - -static int pushresult (lua_State *L, int i, const char *filename) { - if (i) { - lua_pushboolean(L, 1); - return 1; - } - else { - lua_pushnil(L); - if (filename) - lua_pushfstring(L, "%s: %s", filename, strerror(errno)); - else - lua_pushfstring(L, "%s", strerror(errno)); - lua_pushnumber(L, errno); - return 3; - } -} - - -static FILE **topfile (lua_State *L, int findex) { - FILE **f = (FILE **)luaL_checkudata(L, findex, FILEHANDLE); - if (f == NULL) luaL_argerror(L, findex, "bad file"); - return f; -} - - -static int io_type (lua_State *L) { - FILE **f = (FILE **)luaL_checkudata(L, 1, FILEHANDLE); - if (f == NULL) lua_pushnil(L); - else if (*f == NULL) - lua_pushliteral(L, "closed file"); - else - lua_pushliteral(L, "file"); - return 1; -} - - -static FILE *tofile (lua_State *L, int findex) { - FILE **f = topfile(L, findex); - if (*f == NULL) - luaL_error(L, "attempt to use a closed file"); - return *f; -} - - - -/* -** When creating file handles, always creates a `closed' file handle -** before opening the actual file; so, if there is a memory error, the -** file is not left opened. -*/ -static FILE **newfile (lua_State *L) { - FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); - *pf = NULL; /* file handle is currently `closed' */ - luaL_getmetatable(L, FILEHANDLE); - lua_setmetatable(L, -2); - return pf; -} - - -/* -** assumes that top of the stack is the `io' library, and next is -** the `io' metatable -*/ -static void registerfile (lua_State *L, FILE *f, const char *name, - const char *impname) { - lua_pushstring(L, name); - *newfile(L) = f; - if (impname) { - lua_pushstring(L, impname); - lua_pushvalue(L, -2); - lua_settable(L, -6); /* metatable[impname] = file */ - } - lua_settable(L, -3); /* io[name] = file */ -} - - -static int aux_close (lua_State *L) { - FILE *f = tofile(L, 1); - if (f == stdin || f == stdout || f == stderr) - return 0; /* file cannot be closed */ - else { - int ok = (pclose(f) != -1) || (fclose(f) == 0); - if (ok) - *(FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */ - return ok; - } -} - - -static int io_close (lua_State *L) { - if (lua_isnone(L, 1)) { - lua_pushstring(L, IO_OUTPUT); - lua_rawget(L, lua_upvalueindex(1)); - } - return pushresult(L, aux_close(L), NULL); -} - - -static int io_gc (lua_State *L) { - FILE **f = topfile(L, 1); - if (*f != NULL) /* ignore closed files */ - aux_close(L); - return 0; -} - - -static int io_tostring (lua_State *L) { - char buff[32]; - FILE **f = topfile(L, 1); - if (*f == NULL) - strcpy(buff, "closed"); - else - sprintf(buff, "%p", lua_touserdata(L, 1)); - lua_pushfstring(L, "file (%s)", buff); - return 1; -} - - -static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); - *pf = fopen(filename, mode); - return (*pf == NULL) ? pushresult(L, 0, filename) : 1; -} - - -static int io_popen (lua_State *L) { -#if !USE_POPEN - luaL_error(L, "`popen' not supported"); - return 0; -#else - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); - *pf = popen(filename, mode); - return (*pf == NULL) ? pushresult(L, 0, filename) : 1; -#endif -} - - -static int io_tmpfile (lua_State *L) { - FILE **pf = newfile(L); - *pf = tmpfile(); - return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; -} - - -static FILE *getiofile (lua_State *L, const char *name) { - lua_pushstring(L, name); - lua_rawget(L, lua_upvalueindex(1)); - return tofile(L, -1); -} - - -static int g_iofile (lua_State *L, const char *name, const char *mode) { - if (!lua_isnoneornil(L, 1)) { - const char *filename = lua_tostring(L, 1); - lua_pushstring(L, name); - if (filename) { - FILE **pf = newfile(L); - *pf = fopen(filename, mode); - if (*pf == NULL) { - lua_pushfstring(L, "%s: %s", filename, strerror(errno)); - luaL_argerror(L, 1, lua_tostring(L, -1)); - } - } - else { - tofile(L, 1); /* check that it's a valid file handle */ - lua_pushvalue(L, 1); - } - lua_rawset(L, lua_upvalueindex(1)); - } - /* return current value */ - lua_pushstring(L, name); - lua_rawget(L, lua_upvalueindex(1)); - return 1; -} - - -static int io_input (lua_State *L) { - return g_iofile(L, IO_INPUT, "r"); -} - - -static int io_output (lua_State *L) { - return g_iofile(L, IO_OUTPUT, "w"); -} - - -static int io_readline (lua_State *L); - - -static void aux_lines (lua_State *L, int idx, int close) { - lua_pushliteral(L, FILEHANDLE); - lua_rawget(L, LUA_REGISTRYINDEX); - lua_pushvalue(L, idx); - lua_pushboolean(L, close); /* close/not close file when finished */ - lua_pushcclosure(L, io_readline, 3); -} - - -static int f_lines (lua_State *L) { - tofile(L, 1); /* check that it's a valid file handle */ - aux_lines(L, 1, 0); - return 1; -} - - -static int io_lines (lua_State *L) { - if (lua_isnoneornil(L, 1)) { /* no arguments? */ - lua_pushstring(L, IO_INPUT); - lua_rawget(L, lua_upvalueindex(1)); /* will iterate over default input */ - return f_lines(L); - } - else { - const char *filename = luaL_checkstring(L, 1); - FILE **pf = newfile(L); - *pf = fopen(filename, "r"); - luaL_argcheck(L, *pf, 1, strerror(errno)); - aux_lines(L, lua_gettop(L), 1); - return 1; - } -} - - -/* -** {====================================================== -** READ -** ======================================================= -*/ - - -static int read_number (lua_State *L, FILE *f) { - lua_Number d; - if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { - lua_pushnumber(L, d); - return 1; - } - else return 0; /* read fails */ -} - - -static int test_eof (lua_State *L, FILE *f) { - int c = getc(f); - ungetc(c, f); - lua_pushlstring(L, NULL, 0); - return (c != EOF); -} - - -static int read_line (lua_State *L, FILE *f) { - luaL_Buffer b; - luaL_buffinit(L, &b); - for (;;) { - size_t l; - char *p = luaL_prepbuffer(&b); - if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ - luaL_pushresult(&b); /* close buffer */ - return (lua_strlen(L, -1) > 0); /* check whether read something */ - } - l = strlen(p); - if (p[l-1] != '\n') - luaL_addsize(&b, l); - else { - luaL_addsize(&b, l - 1); /* do not include `eol' */ - luaL_pushresult(&b); /* close buffer */ - return 1; /* read at least an `eol' */ - } - } -} - - -static int read_chars (lua_State *L, FILE *f, size_t n) { - size_t rlen; /* how much to read */ - size_t nr; /* number of chars actually read */ - luaL_Buffer b; - luaL_buffinit(L, &b); - rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ - do { - char *p = luaL_prepbuffer(&b); - if (rlen > n) rlen = n; /* cannot read more than asked */ - nr = fread(p, sizeof(char), rlen, f); - luaL_addsize(&b, nr); - n -= nr; /* still have to read `n' chars */ - } while (n > 0 && nr == rlen); /* until end of count or eof */ - luaL_pushresult(&b); /* close buffer */ - return (n == 0 || lua_strlen(L, -1) > 0); -} - - -static int g_read (lua_State *L, FILE *f, int first) { - int nargs = lua_gettop(L) - 1; - int success; - int n; - if (nargs == 0) { /* no arguments? */ - success = read_line(L, f); - n = first+1; /* to return 1 result */ - } - else { /* ensure stack space for all results and for auxlib's buffer */ - luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); - success = 1; - for (n = first; nargs-- && success; n++) { - if (lua_type(L, n) == LUA_TNUMBER) { - size_t l = (size_t)lua_tonumber(L, n); - success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); - } - else { - const char *p = lua_tostring(L, n); - luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); - switch (p[1]) { - case 'n': /* number */ - success = read_number(L, f); - break; - case 'l': /* line */ - success = read_line(L, f); - break; - case 'a': /* file */ - read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ - success = 1; /* always success */ - break; - case 'w': /* word */ - return luaL_error(L, "obsolete option `*w' to `read'"); - default: - return luaL_argerror(L, n, "invalid format"); - } - } - } - } - if (!success) { - lua_pop(L, 1); /* remove last result */ - lua_pushnil(L); /* push nil instead */ - } - return n - first; -} - - -static int io_read (lua_State *L) { - return g_read(L, getiofile(L, IO_INPUT), 1); -} - - -static int f_read (lua_State *L) { - return g_read(L, tofile(L, 1), 2); -} - - -static int io_readline (lua_State *L) { - FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(2)); - if (f == NULL) /* file is already closed? */ - luaL_error(L, "file is already closed"); - if (read_line(L, f)) return 1; - else { /* EOF */ - if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ - lua_settop(L, 0); - lua_pushvalue(L, lua_upvalueindex(2)); - aux_close(L); /* close it */ - } - return 0; - } -} - -/* }====================================================== */ - - -static int g_write (lua_State *L, FILE *f, int arg) { - int nargs = lua_gettop(L) - 1; - int status = 1; - for (; nargs--; arg++) { - if (lua_type(L, arg) == LUA_TNUMBER) { - /* optimization: could be done exactly as for strings */ - status = status && - fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; - } - else { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - status = status && (fwrite(s, sizeof(char), l, f) == l); - } - } - return pushresult(L, status, NULL); -} - - -static int io_write (lua_State *L) { - return g_write(L, getiofile(L, IO_OUTPUT), 1); -} - - -static int f_write (lua_State *L) { - return g_write(L, tofile(L, 1), 2); -} - - -static int f_seek (lua_State *L) { - static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; - static const char *const modenames[] = {"set", "cur", "end", NULL}; - FILE *f = tofile(L, 1); - int op = luaL_findstring(luaL_optstring(L, 2, "cur"), modenames); - long offset = luaL_optlong(L, 3, 0); - luaL_argcheck(L, op != -1, 2, "invalid mode"); - op = fseek(f, offset, mode[op]); - if (op) - return pushresult(L, 0, NULL); /* error */ - else { - lua_pushnumber(L, ftell(f)); - return 1; - } -} - - -static int io_flush (lua_State *L) { - return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); -} - - -static int f_flush (lua_State *L) { - return pushresult(L, fflush(tofile(L, 1)) == 0, NULL); -} - - -static const luaL_reg iolib[] = { - {"input", io_input}, - {"output", io_output}, - {"lines", io_lines}, - {"close", io_close}, - {"flush", io_flush}, - {"open", io_open}, - {"popen", io_popen}, - {"read", io_read}, - {"tmpfile", io_tmpfile}, - {"type", io_type}, - {"write", io_write}, - {NULL, NULL} -}; - - -static const luaL_reg flib[] = { - {"flush", f_flush}, - {"read", f_read}, - {"lines", f_lines}, - {"seek", f_seek}, - {"write", f_write}, - {"close", io_close}, - {"__gc", io_gc}, - {"__tostring", io_tostring}, - {NULL, NULL} -}; - - -static void createmeta (lua_State *L) { - luaL_newmetatable(L, FILEHANDLE); /* create new metatable for file handles */ - /* file methods */ - lua_pushliteral(L, "__index"); - lua_pushvalue(L, -2); /* push metatable */ - lua_rawset(L, -3); /* metatable.__index = metatable */ - luaL_openlib(L, NULL, flib, 0); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Other O.S. Operations -** ======================================================= -*/ - -static int io_execute (lua_State *L) { - lua_pushnumber(L, system(luaL_checkstring(L, 1))); - return 1; -} - - -static int io_remove (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - return pushresult(L, remove(filename) == 0, filename); -} - - -static int io_rename (lua_State *L) { - const char *fromname = luaL_checkstring(L, 1); - const char *toname = luaL_checkstring(L, 2); - return pushresult(L, rename(fromname, toname) == 0, fromname); -} - - -static int io_tmpname (lua_State *L) { -#if !USE_TMPNAME - luaL_error(L, "`tmpname' not supported"); - return 0; -#else - char buff[L_tmpnam]; - if (tmpnam(buff) != buff) - return luaL_error(L, "unable to generate a unique filename in `tmpname'"); - lua_pushstring(L, buff); - return 1; -#endif -} - - -static int io_getenv (lua_State *L) { - lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ - return 1; -} - - -static int io_clock (lua_State *L) { - lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); - return 1; -} - - -/* -** {====================================================== -** Time/Date operations -** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, -** wday=%w+1, yday=%j, isdst=? } -** ======================================================= -*/ - -static void setfield (lua_State *L, const char *key, int value) { - lua_pushstring(L, key); - lua_pushnumber(L, value); - lua_rawset(L, -3); -} - -static void setboolfield (lua_State *L, const char *key, int value) { - lua_pushstring(L, key); - lua_pushboolean(L, value); - lua_rawset(L, -3); -} - -static int getboolfield (lua_State *L, const char *key) { - int res; - lua_pushstring(L, key); - lua_gettable(L, -2); - res = lua_toboolean(L, -1); - lua_pop(L, 1); - return res; -} - - -static int getfield (lua_State *L, const char *key, int d) { - int res; - lua_pushstring(L, key); - lua_gettable(L, -2); - if (lua_isnumber(L, -1)) - res = (int)(lua_tonumber(L, -1)); - else { - if (d == -2) - return luaL_error(L, "field `%s' missing in date table", key); - res = d; - } - lua_pop(L, 1); - return res; -} - - -static int io_date (lua_State *L) { - const char *s = luaL_optstring(L, 1, "%c"); - time_t t = (time_t)(luaL_optnumber(L, 2, -1)); - struct tm *stm; - if (t == (time_t)(-1)) /* no time given? */ - t = time(NULL); /* use current time */ - if (*s == '!') { /* UTC? */ - stm = gmtime(&t); - s++; /* skip `!' */ - } - else - stm = localtime(&t); - if (stm == NULL) /* invalid date? */ - lua_pushnil(L); - else if (strcmp(s, "*t") == 0) { - lua_newtable(L); - setfield(L, "sec", stm->tm_sec); - setfield(L, "min", stm->tm_min); - setfield(L, "hour", stm->tm_hour); - setfield(L, "day", stm->tm_mday); - setfield(L, "month", stm->tm_mon+1); - setfield(L, "year", stm->tm_year+1900); - setfield(L, "wday", stm->tm_wday+1); - setfield(L, "yday", stm->tm_yday+1); - setboolfield(L, "isdst", stm->tm_isdst); - } - else { - char b[256]; - if (strftime(b, sizeof(b), s, stm)) - lua_pushstring(L, b); - else - return luaL_error(L, "`date' format too long"); - } - return 1; -} - - -static int io_time (lua_State *L) { - if (lua_isnoneornil(L, 1)) /* called without args? */ - lua_pushnumber(L, time(NULL)); /* return current time */ - else { - time_t t; - struct tm ts; - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 1); /* make sure table is at the top */ - ts.tm_sec = getfield(L, "sec", 0); - ts.tm_min = getfield(L, "min", 0); - ts.tm_hour = getfield(L, "hour", 12); - ts.tm_mday = getfield(L, "day", -2); - ts.tm_mon = getfield(L, "month", -2) - 1; - ts.tm_year = getfield(L, "year", -2) - 1900; - ts.tm_isdst = getboolfield(L, "isdst"); - t = mktime(&ts); - if (t == (time_t)(-1)) - lua_pushnil(L); - else - lua_pushnumber(L, t); - } - return 1; -} - - -static int io_difftime (lua_State *L) { - lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), - (time_t)(luaL_optnumber(L, 2, 0)))); - return 1; -} - -/* }====================================================== */ - - -static int io_setloc (lua_State *L) { - static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, - LC_NUMERIC, LC_TIME}; - static const char *const catnames[] = {"all", "collate", "ctype", "monetary", - "numeric", "time", NULL}; - const char *l = lua_tostring(L, 1); - int op = luaL_findstring(luaL_optstring(L, 2, "all"), catnames); - luaL_argcheck(L, l || lua_isnoneornil(L, 1), 1, "string expected"); - luaL_argcheck(L, op != -1, 2, "invalid option"); - lua_pushstring(L, setlocale(cat[op], l)); - return 1; -} - - -static int io_exit (lua_State *L) { - exit(luaL_optint(L, 1, EXIT_SUCCESS)); - return 0; /* to avoid warnings */ -} - -static const luaL_reg syslib[] = { - {"clock", io_clock}, - {"date", io_date}, - {"difftime", io_difftime}, - {"execute", io_execute}, - {"exit", io_exit}, - {"getenv", io_getenv}, - {"remove", io_remove}, - {"rename", io_rename}, - {"setlocale", io_setloc}, - {"time", io_time}, - {"tmpname", io_tmpname}, - {NULL, NULL} -}; - -/* }====================================================== */ - - - -LUALIB_API int luaopen_io (lua_State *L) { - luaL_openlib(L, LUA_OSLIBNAME, syslib, 0); - createmeta(L); - lua_pushvalue(L, -1); - luaL_openlib(L, LUA_IOLIBNAME, iolib, 1); - /* put predefined file handles into `io' table */ - registerfile(L, stdin, "stdin", IO_INPUT); - registerfile(L, stdout, "stdout", IO_OUTPUT); - registerfile(L, stderr, "stderr", NULL); - return 1; -} - +/* +** $Id: liolib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include +#include + +#define liolib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +/* +** by default, gcc does not get `tmpname' +*/ +#ifndef USE_TMPNAME +#ifdef __GNUC__ +#define USE_TMPNAME 0 +#else +#define USE_TMPNAME 1 +#endif +#endif + + +/* +** by default, posix systems get `popen' +*/ +#ifndef USE_POPEN +#ifdef _POSIX_C_SOURCE +#if _POSIX_C_SOURCE >= 2 +#define USE_POPEN 1 +#endif +#endif +#endif + +#ifndef USE_POPEN +#define USE_POPEN 0 +#endif + + + + +/* +** {====================================================== +** FILE Operations +** ======================================================= +*/ + + +#if !USE_POPEN +#define pclose(f) (-1) +#endif + + +#define FILEHANDLE "FILE*" + +#define IO_INPUT "_input" +#define IO_OUTPUT "_output" + + +static int pushresult (lua_State *L, int i, const char *filename) { + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (filename) + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); + else + lua_pushfstring(L, "%s", strerror(errno)); + lua_pushnumber(L, errno); + return 3; + } +} + + +static FILE **topfile (lua_State *L, int findex) { + FILE **f = (FILE **)luaL_checkudata(L, findex, FILEHANDLE); + if (f == NULL) luaL_argerror(L, findex, "bad file"); + return f; +} + + +static int io_type (lua_State *L) { + FILE **f = (FILE **)luaL_checkudata(L, 1, FILEHANDLE); + if (f == NULL) lua_pushnil(L); + else if (*f == NULL) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static FILE *tofile (lua_State *L, int findex) { + FILE **f = topfile(L, findex); + if (*f == NULL) + luaL_error(L, "attempt to use a closed file"); + return *f; +} + + + +/* +** When creating file handles, always creates a `closed' file handle +** before opening the actual file; so, if there is a memory error, the +** file is not left opened. +*/ +static FILE **newfile (lua_State *L) { + FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); + *pf = NULL; /* file handle is currently `closed' */ + luaL_getmetatable(L, FILEHANDLE); + lua_setmetatable(L, -2); + return pf; +} + + +/* +** assumes that top of the stack is the `io' library, and next is +** the `io' metatable +*/ +static void registerfile (lua_State *L, FILE *f, const char *name, + const char *impname) { + lua_pushstring(L, name); + *newfile(L) = f; + if (impname) { + lua_pushstring(L, impname); + lua_pushvalue(L, -2); + lua_settable(L, -6); /* metatable[impname] = file */ + } + lua_settable(L, -3); /* io[name] = file */ +} + + +static int aux_close (lua_State *L) { + FILE *f = tofile(L, 1); + if (f == stdin || f == stdout || f == stderr) + return 0; /* file cannot be closed */ + else { + int ok = (pclose(f) != -1) || (fclose(f) == 0); + if (ok) + *(FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */ + return ok; + } +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) { + lua_pushstring(L, IO_OUTPUT); + lua_rawget(L, lua_upvalueindex(1)); + } + return pushresult(L, aux_close(L), NULL); +} + + +static int io_gc (lua_State *L) { + FILE **f = topfile(L, 1); + if (*f != NULL) /* ignore closed files */ + aux_close(L); + return 0; +} + + +static int io_tostring (lua_State *L) { + char buff[32]; + FILE **f = topfile(L, 1); + if (*f == NULL) + strcpy(buff, "closed"); + else + sprintf(buff, "%p", lua_touserdata(L, 1)); + lua_pushfstring(L, "file (%s)", buff); + return 1; +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +static int io_popen (lua_State *L) { +#if !USE_POPEN + luaL_error(L, "`popen' not supported"); + return 0; +#else + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = popen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +#endif +} + + +static int io_tmpfile (lua_State *L) { + FILE **pf = newfile(L); + *pf = tmpfile(); + return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; +} + + +static FILE *getiofile (lua_State *L, const char *name) { + lua_pushstring(L, name); + lua_rawget(L, lua_upvalueindex(1)); + return tofile(L, -1); +} + + +static int g_iofile (lua_State *L, const char *name, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + lua_pushstring(L, name); + if (filename) { + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + if (*pf == NULL) { + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); + luaL_argerror(L, 1, lua_tostring(L, -1)); + } + } + else { + tofile(L, 1); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_rawset(L, lua_upvalueindex(1)); + } + /* return current value */ + lua_pushstring(L, name); + lua_rawget(L, lua_upvalueindex(1)); + return 1; +} + + +static int io_input (lua_State *L) { + return g_iofile(L, IO_INPUT, "r"); +} + + +static int io_output (lua_State *L) { + return g_iofile(L, IO_OUTPUT, "w"); +} + + +static int io_readline (lua_State *L); + + +static void aux_lines (lua_State *L, int idx, int close) { + lua_pushliteral(L, FILEHANDLE); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, idx); + lua_pushboolean(L, close); /* close/not close file when finished */ + lua_pushcclosure(L, io_readline, 3); +} + + +static int f_lines (lua_State *L) { + tofile(L, 1); /* check that it's a valid file handle */ + aux_lines(L, 1, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + if (lua_isnoneornil(L, 1)) { /* no arguments? */ + lua_pushstring(L, IO_INPUT); + lua_rawget(L, lua_upvalueindex(1)); /* will iterate over default input */ + return f_lines(L); + } + else { + const char *filename = luaL_checkstring(L, 1); + FILE **pf = newfile(L); + *pf = fopen(filename, "r"); + luaL_argcheck(L, *pf, 1, strerror(errno)); + aux_lines(L, lua_gettop(L), 1); + return 1; + } +} + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + + +static int read_number (lua_State *L, FILE *f) { + lua_Number d; + if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { + lua_pushnumber(L, d); + return 1; + } + else return 0; /* read fails */ +} + + +static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); + ungetc(c, f); + lua_pushlstring(L, NULL, 0); + return (c != EOF); +} + + +static int read_line (lua_State *L, FILE *f) { + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + size_t l; + char *p = luaL_prepbuffer(&b); + if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ + luaL_pushresult(&b); /* close buffer */ + return (lua_strlen(L, -1) > 0); /* check whether read something */ + } + l = strlen(p); + if (p[l-1] != '\n') + luaL_addsize(&b, l); + else { + luaL_addsize(&b, l - 1); /* do not include `eol' */ + luaL_pushresult(&b); /* close buffer */ + return 1; /* read at least an `eol' */ + } + } +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t rlen; /* how much to read */ + size_t nr; /* number of chars actually read */ + luaL_Buffer b; + luaL_buffinit(L, &b); + rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ + do { + char *p = luaL_prepbuffer(&b); + if (rlen > n) rlen = n; /* cannot read more than asked */ + nr = fread(p, sizeof(char), rlen, f); + luaL_addsize(&b, nr); + n -= nr; /* still have to read `n' chars */ + } while (n > 0 && nr == rlen); /* until end of count or eof */ + luaL_pushresult(&b); /* close buffer */ + return (n == 0 || lua_strlen(L, -1) > 0); +} + + +static int g_read (lua_State *L, FILE *f, int first) { + int nargs = lua_gettop(L) - 1; + int success; + int n; + if (nargs == 0) { /* no arguments? */ + success = read_line(L, f); + n = first+1; /* to return 1 result */ + } + else { /* ensure stack space for all results and for auxlib's buffer */ + luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); + success = 1; + for (n = first; nargs-- && success; n++) { + if (lua_type(L, n) == LUA_TNUMBER) { + size_t l = (size_t)lua_tonumber(L, n); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + } + else { + const char *p = lua_tostring(L, n); + luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); + switch (p[1]) { + case 'n': /* number */ + success = read_number(L, f); + break; + case 'l': /* line */ + success = read_line(L, f); + break; + case 'a': /* file */ + read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ + success = 1; /* always success */ + break; + case 'w': /* word */ + return luaL_error(L, "obsolete option `*w' to `read'"); + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (!success) { + lua_pop(L, 1); /* remove last result */ + lua_pushnil(L); /* push nil instead */ + } + return n - first; +} + + +static int io_read (lua_State *L) { + return g_read(L, getiofile(L, IO_INPUT), 1); +} + + +static int f_read (lua_State *L) { + return g_read(L, tofile(L, 1), 2); +} + + +static int io_readline (lua_State *L) { + FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(2)); + if (f == NULL) /* file is already closed? */ + luaL_error(L, "file is already closed"); + if (read_line(L, f)) return 1; + else { /* EOF */ + if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ + lua_settop(L, 0); + lua_pushvalue(L, lua_upvalueindex(2)); + aux_close(L); /* close it */ + } + return 0; + } +} + +/* }====================================================== */ + + +static int g_write (lua_State *L, FILE *f, int arg) { + int nargs = lua_gettop(L) - 1; + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { + /* optimization: could be done exactly as for strings */ + status = status && + fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + } + else { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + return pushresult(L, status, NULL); +} + + +static int io_write (lua_State *L) { + return g_write(L, getiofile(L, IO_OUTPUT), 1); +} + + +static int f_write (lua_State *L) { + return g_write(L, tofile(L, 1), 2); +} + + +static int f_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + FILE *f = tofile(L, 1); + int op = luaL_findstring(luaL_optstring(L, 2, "cur"), modenames); + long offset = luaL_optlong(L, 3, 0); + luaL_argcheck(L, op != -1, 2, "invalid mode"); + op = fseek(f, offset, mode[op]); + if (op) + return pushresult(L, 0, NULL); /* error */ + else { + lua_pushnumber(L, ftell(f)); + return 1; + } +} + + +static int io_flush (lua_State *L) { + return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return pushresult(L, fflush(tofile(L, 1)) == 0, NULL); +} + + +static const luaL_reg iolib[] = { + {"input", io_input}, + {"output", io_output}, + {"lines", io_lines}, + {"close", io_close}, + {"flush", io_flush}, + {"open", io_open}, + {"popen", io_popen}, + {"read", io_read}, + {"tmpfile", io_tmpfile}, + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} +}; + + +static const luaL_reg flib[] = { + {"flush", f_flush}, + {"read", f_read}, + {"lines", f_lines}, + {"seek", f_seek}, + {"write", f_write}, + {"close", io_close}, + {"__gc", io_gc}, + {"__tostring", io_tostring}, + {NULL, NULL} +}; + + +static void createmeta (lua_State *L) { + luaL_newmetatable(L, FILEHANDLE); /* create new metatable for file handles */ + /* file methods */ + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -2); /* push metatable */ + lua_rawset(L, -3); /* metatable.__index = metatable */ + luaL_openlib(L, NULL, flib, 0); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Other O.S. Operations +** ======================================================= +*/ + +static int io_execute (lua_State *L) { + lua_pushnumber(L, system(luaL_checkstring(L, 1))); + return 1; +} + + +static int io_remove (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + return pushresult(L, remove(filename) == 0, filename); +} + + +static int io_rename (lua_State *L) { + const char *fromname = luaL_checkstring(L, 1); + const char *toname = luaL_checkstring(L, 2); + return pushresult(L, rename(fromname, toname) == 0, fromname); +} + + +static int io_tmpname (lua_State *L) { +#if !USE_TMPNAME + luaL_error(L, "`tmpname' not supported"); + return 0; +#else + char buff[L_tmpnam]; + if (tmpnam(buff) != buff) + return luaL_error(L, "unable to generate a unique filename in `tmpname'"); + lua_pushstring(L, buff); + return 1; +#endif +} + + +static int io_getenv (lua_State *L) { + lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ + return 1; +} + + +static int io_clock (lua_State *L) { + lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); + return 1; +} + + +/* +** {====================================================== +** Time/Date operations +** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, +** wday=%w+1, yday=%j, isdst=? } +** ======================================================= +*/ + +static void setfield (lua_State *L, const char *key, int value) { + lua_pushstring(L, key); + lua_pushnumber(L, value); + lua_rawset(L, -3); +} + +static void setboolfield (lua_State *L, const char *key, int value) { + lua_pushstring(L, key); + lua_pushboolean(L, value); + lua_rawset(L, -3); +} + +static int getboolfield (lua_State *L, const char *key) { + int res; + lua_pushstring(L, key); + lua_gettable(L, -2); + res = lua_toboolean(L, -1); + lua_pop(L, 1); + return res; +} + + +static int getfield (lua_State *L, const char *key, int d) { + int res; + lua_pushstring(L, key); + lua_gettable(L, -2); + if (lua_isnumber(L, -1)) + res = (int)(lua_tonumber(L, -1)); + else { + if (d == -2) + return luaL_error(L, "field `%s' missing in date table", key); + res = d; + } + lua_pop(L, 1); + return res; +} + + +static int io_date (lua_State *L) { + const char *s = luaL_optstring(L, 1, "%c"); + time_t t = (time_t)(luaL_optnumber(L, 2, -1)); + struct tm *stm; + if (t == (time_t)(-1)) /* no time given? */ + t = time(NULL); /* use current time */ + if (*s == '!') { /* UTC? */ + stm = gmtime(&t); + s++; /* skip `!' */ + } + else + stm = localtime(&t); + if (stm == NULL) /* invalid date? */ + lua_pushnil(L); + else if (strcmp(s, "*t") == 0) { + lua_newtable(L); + setfield(L, "sec", stm->tm_sec); + setfield(L, "min", stm->tm_min); + setfield(L, "hour", stm->tm_hour); + setfield(L, "day", stm->tm_mday); + setfield(L, "month", stm->tm_mon+1); + setfield(L, "year", stm->tm_year+1900); + setfield(L, "wday", stm->tm_wday+1); + setfield(L, "yday", stm->tm_yday+1); + setboolfield(L, "isdst", stm->tm_isdst); + } + else { + char b[256]; + if (strftime(b, sizeof(b), s, stm)) + lua_pushstring(L, b); + else + return luaL_error(L, "`date' format too long"); + } + return 1; +} + + +static int io_time (lua_State *L) { + if (lua_isnoneornil(L, 1)) /* called without args? */ + lua_pushnumber(L, time(NULL)); /* return current time */ + else { + time_t t; + struct tm ts; + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); /* make sure table is at the top */ + ts.tm_sec = getfield(L, "sec", 0); + ts.tm_min = getfield(L, "min", 0); + ts.tm_hour = getfield(L, "hour", 12); + ts.tm_mday = getfield(L, "day", -2); + ts.tm_mon = getfield(L, "month", -2) - 1; + ts.tm_year = getfield(L, "year", -2) - 1900; + ts.tm_isdst = getboolfield(L, "isdst"); + t = mktime(&ts); + if (t == (time_t)(-1)) + lua_pushnil(L); + else + lua_pushnumber(L, t); + } + return 1; +} + + +static int io_difftime (lua_State *L) { + lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), + (time_t)(luaL_optnumber(L, 2, 0)))); + return 1; +} + +/* }====================================================== */ + + +static int io_setloc (lua_State *L) { + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME}; + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", + "numeric", "time", NULL}; + const char *l = lua_tostring(L, 1); + int op = luaL_findstring(luaL_optstring(L, 2, "all"), catnames); + luaL_argcheck(L, l || lua_isnoneornil(L, 1), 1, "string expected"); + luaL_argcheck(L, op != -1, 2, "invalid option"); + lua_pushstring(L, setlocale(cat[op], l)); + return 1; +} + + +static int io_exit (lua_State *L) { + exit(luaL_optint(L, 1, EXIT_SUCCESS)); + return 0; /* to avoid warnings */ +} + +static const luaL_reg syslib[] = { + {"clock", io_clock}, + {"date", io_date}, + {"difftime", io_difftime}, + {"execute", io_execute}, + {"exit", io_exit}, + {"getenv", io_getenv}, + {"remove", io_remove}, + {"rename", io_rename}, + {"setlocale", io_setloc}, + {"time", io_time}, + {"tmpname", io_tmpname}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +LUALIB_API int luaopen_io (lua_State *L) { + luaL_openlib(L, LUA_OSLIBNAME, syslib, 0); + createmeta(L); + lua_pushvalue(L, -1); + luaL_openlib(L, LUA_IOLIBNAME, iolib, 1); + /* put predefined file handles into `io' table */ + registerfile(L, stdin, "stdin", IO_INPUT); + registerfile(L, stdout, "stdout", IO_OUTPUT); + registerfile(L, stderr, "stderr", NULL); + return 1; +} + diff --git a/lib/lua/src/LuaLib/lmathlib.c b/lib/lua/src/LuaLib/lmathlib.c index 2352fca..998c46c 100644 --- a/lib/lua/src/LuaLib/lmathlib.c +++ b/lib/lua/src/LuaLib/lmathlib.c @@ -1,246 +1,246 @@ -/* -** $Id: lmathlib.c,v 1.3 2004-11-27 21:35:21 pixel Exp $ -** Standard mathematical library -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#define lmathlib_c - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#undef PI -#define PI (3.14159265358979323846) -#define RADIANS_PER_DEGREE (PI/180.0) - - - -/* -** If you want Lua to operate in degrees (instead of radians), -** define USE_DEGREES -*/ -#ifdef USE_DEGREES -#define FROMRAD(a) ((a)/RADIANS_PER_DEGREE) -#define TORAD(a) ((a)*RADIANS_PER_DEGREE) -#else -#define FROMRAD(a) (a) -#define TORAD(a) (a) -#endif - - -static int math_abs (lua_State *L) { - lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sin (lua_State *L) { - lua_pushnumber(L, sin(TORAD(luaL_checknumber(L, 1)))); - return 1; -} - -static int math_cos (lua_State *L) { - lua_pushnumber(L, cos(TORAD(luaL_checknumber(L, 1)))); - return 1; -} - -static int math_tan (lua_State *L) { - lua_pushnumber(L, tan(TORAD(luaL_checknumber(L, 1)))); - return 1; -} - -static int math_asin (lua_State *L) { - lua_pushnumber(L, FROMRAD(asin(luaL_checknumber(L, 1)))); - return 1; -} - -static int math_acos (lua_State *L) { - lua_pushnumber(L, FROMRAD(acos(luaL_checknumber(L, 1)))); - return 1; -} - -static int math_atan (lua_State *L) { - lua_pushnumber(L, FROMRAD(atan(luaL_checknumber(L, 1)))); - return 1; -} - -static int math_atan2 (lua_State *L) { - lua_pushnumber(L, FROMRAD(atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)))); - return 1; -} - -static int math_ceil (lua_State *L) { - lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); - return 1; -} - -static int math_floor (lua_State *L) { - lua_pushnumber(L, floor(luaL_checknumber(L, 1))); - return 1; -} - -static int math_mod (lua_State *L) { - lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); - return 1; -} - -static int math_sqrt (lua_State *L) { - lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); - return 1; -} - -static int math_pow (lua_State *L) { - lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); - return 1; -} - -static int math_log (lua_State *L) { - lua_pushnumber(L, log(luaL_checknumber(L, 1))); - return 1; -} - -static int math_log10 (lua_State *L) { - lua_pushnumber(L, log10(luaL_checknumber(L, 1))); - return 1; -} - -static int math_exp (lua_State *L) { - lua_pushnumber(L, exp(luaL_checknumber(L, 1))); - return 1; -} - -static int math_deg (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); - return 1; -} - -static int math_rad (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); - return 1; -} - -static int math_frexp (lua_State *L) { - int e; - lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); - lua_pushnumber(L, e); - return 2; -} - -static int math_ldexp (lua_State *L) { - lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); - return 1; -} - - - -static int math_min (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - lua_Number dmin = luaL_checknumber(L, 1); - int i; - for (i=2; i<=n; i++) { - lua_Number d = luaL_checknumber(L, i); - if (d < dmin) - dmin = d; - } - lua_pushnumber(L, dmin); - return 1; -} - - -static int math_max (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - lua_Number dmax = luaL_checknumber(L, 1); - int i; - for (i=2; i<=n; i++) { - lua_Number d = luaL_checknumber(L, i); - if (d > dmax) - dmax = d; - } - lua_pushnumber(L, dmax); - return 1; -} - - -static int math_random (lua_State *L) { - /* the `%' avoids the (rare) case of r==1, and is needed also because on - some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ - lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; - switch (lua_gettop(L)) { /* check number of arguments */ - case 0: { /* no arguments */ - lua_pushnumber(L, r); /* Number between 0 and 1 */ - break; - } - case 1: { /* only upper limit */ - int u = luaL_checkint(L, 1); - luaL_argcheck(L, 1<=u, 1, "interval is empty"); - lua_pushnumber(L, (int)floor(r*u)+1); /* int between 1 and `u' */ - break; - } - case 2: { /* lower and upper limits */ - int l = luaL_checkint(L, 1); - int u = luaL_checkint(L, 2); - luaL_argcheck(L, l<=u, 2, "interval is empty"); - lua_pushnumber(L, (int)floor(r*(u-l+1))+l); /* int between `l' and `u' */ - break; - } - default: return luaL_error(L, "wrong number of arguments"); - } - return 1; -} - - -static int math_randomseed (lua_State *L) { - srand(luaL_checkint(L, 1)); - return 0; -} - - -static const luaL_reg mathlib[] = { - {"abs", math_abs}, - {"sin", math_sin}, - {"cos", math_cos}, - {"tan", math_tan}, - {"asin", math_asin}, - {"acos", math_acos}, - {"atan", math_atan}, - {"atan2", math_atan2}, - {"ceil", math_ceil}, - {"floor", math_floor}, - {"mod", math_mod}, - {"frexp", math_frexp}, - {"ldexp", math_ldexp}, - {"sqrt", math_sqrt}, - {"min", math_min}, - {"max", math_max}, - {"log", math_log}, - {"log10", math_log10}, - {"exp", math_exp}, - {"deg", math_deg}, - {"pow", math_pow}, - {"rad", math_rad}, - {"random", math_random}, - {"randomseed", math_randomseed}, - {NULL, NULL} -}; - - -/* -** Open math library -*/ -LUALIB_API int luaopen_math (lua_State *L) { - luaL_openlib(L, LUA_MATHLIBNAME, mathlib, 0); - lua_pushliteral(L, "pi"); - lua_pushnumber(L, PI); - lua_settable(L, -3); - lua_pushliteral(L, "__pow"); - lua_pushcfunction(L, math_pow); - lua_settable(L, LUA_GLOBALSINDEX); - return 1; -} - +/* +** $Id: lmathlib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $ +** Standard mathematical library +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define lmathlib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#undef PI +#define PI (3.14159265358979323846) +#define RADIANS_PER_DEGREE (PI/180.0) + + + +/* +** If you want Lua to operate in degrees (instead of radians), +** define USE_DEGREES +*/ +#ifdef USE_DEGREES +#define FROMRAD(a) ((a)/RADIANS_PER_DEGREE) +#define TORAD(a) ((a)*RADIANS_PER_DEGREE) +#else +#define FROMRAD(a) (a) +#define TORAD(a) (a) +#endif + + +static int math_abs (lua_State *L) { + lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sin (lua_State *L) { + lua_pushnumber(L, sin(TORAD(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_cos (lua_State *L) { + lua_pushnumber(L, cos(TORAD(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_tan (lua_State *L) { + lua_pushnumber(L, tan(TORAD(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_asin (lua_State *L) { + lua_pushnumber(L, FROMRAD(asin(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_acos (lua_State *L) { + lua_pushnumber(L, FROMRAD(acos(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_atan (lua_State *L) { + lua_pushnumber(L, FROMRAD(atan(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_atan2 (lua_State *L) { + lua_pushnumber(L, FROMRAD(atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)))); + return 1; +} + +static int math_ceil (lua_State *L) { + lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); + return 1; +} + +static int math_floor (lua_State *L) { + lua_pushnumber(L, floor(luaL_checknumber(L, 1))); + return 1; +} + +static int math_mod (lua_State *L) { + lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_sqrt (lua_State *L) { + lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); + return 1; +} + +static int math_pow (lua_State *L) { + lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_log (lua_State *L) { + lua_pushnumber(L, log(luaL_checknumber(L, 1))); + return 1; +} + +static int math_log10 (lua_State *L) { + lua_pushnumber(L, log10(luaL_checknumber(L, 1))); + return 1; +} + +static int math_exp (lua_State *L) { + lua_pushnumber(L, exp(luaL_checknumber(L, 1))); + return 1; +} + +static int math_deg (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); + return 1; +} + +static int math_rad (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); + return 1; +} + +static int math_frexp (lua_State *L) { + int e; + lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); + lua_pushnumber(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); + return 1; +} + + + +static int math_min (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmin = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d < dmin) + dmin = d; + } + lua_pushnumber(L, dmin); + return 1; +} + + +static int math_max (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmax = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d > dmax) + dmax = d; + } + lua_pushnumber(L, dmax); + return 1; +} + + +static int math_random (lua_State *L) { + /* the `%' avoids the (rare) case of r==1, and is needed also because on + some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ + lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; + switch (lua_gettop(L)) { /* check number of arguments */ + case 0: { /* no arguments */ + lua_pushnumber(L, r); /* Number between 0 and 1 */ + break; + } + case 1: { /* only upper limit */ + int u = luaL_checkint(L, 1); + luaL_argcheck(L, 1<=u, 1, "interval is empty"); + lua_pushnumber(L, (int)floor(r*u)+1); /* int between 1 and `u' */ + break; + } + case 2: { /* lower and upper limits */ + int l = luaL_checkint(L, 1); + int u = luaL_checkint(L, 2); + luaL_argcheck(L, l<=u, 2, "interval is empty"); + lua_pushnumber(L, (int)floor(r*(u-l+1))+l); /* int between `l' and `u' */ + break; + } + default: return luaL_error(L, "wrong number of arguments"); + } + return 1; +} + + +static int math_randomseed (lua_State *L) { + srand(luaL_checkint(L, 1)); + return 0; +} + + +static const luaL_reg mathlib[] = { + {"abs", math_abs}, + {"sin", math_sin}, + {"cos", math_cos}, + {"tan", math_tan}, + {"asin", math_asin}, + {"acos", math_acos}, + {"atan", math_atan}, + {"atan2", math_atan2}, + {"ceil", math_ceil}, + {"floor", math_floor}, + {"mod", math_mod}, + {"frexp", math_frexp}, + {"ldexp", math_ldexp}, + {"sqrt", math_sqrt}, + {"min", math_min}, + {"max", math_max}, + {"log", math_log}, + {"log10", math_log10}, + {"exp", math_exp}, + {"deg", math_deg}, + {"pow", math_pow}, + {"rad", math_rad}, + {"random", math_random}, + {"randomseed", math_randomseed}, + {NULL, NULL} +}; + + +/* +** Open math library +*/ +LUALIB_API int luaopen_math (lua_State *L) { + luaL_openlib(L, LUA_MATHLIBNAME, mathlib, 0); + lua_pushliteral(L, "pi"); + lua_pushnumber(L, PI); + lua_settable(L, -3); + lua_pushliteral(L, "__pow"); + lua_pushcfunction(L, math_pow); + lua_settable(L, LUA_GLOBALSINDEX); + return 1; +} + diff --git a/lib/lua/src/LuaLib/loadlib.c b/lib/lua/src/LuaLib/loadlib.c index dc83283..8756205 100644 --- a/lib/lua/src/LuaLib/loadlib.c +++ b/lib/lua/src/LuaLib/loadlib.c @@ -1,205 +1,205 @@ -/* -** $Id: loadlib.c,v 1.3 2004-11-27 21:35:21 pixel Exp $ -** Dynamic library loader for Lua -** See Copyright Notice in lua.h -* -* This Lua library exports a single function, called loadlib, which is -* called from Lua as loadlib(lib,init), where lib is the full name of the -* library to be loaded (including the complete path) and init is the name -* of a function to be called after the library is loaded. Typically, this -* function will register other functions, thus making the complete library -* available to Lua. The init function is *not* automatically called by -* loadlib. Instead, loadlib returns the init function as a Lua function -* that the client can call when it thinks is appropriate. In the case of -* errors, loadlib returns nil and two strings describing the error. -* The first string is supplied by the operating system; it should be -* informative and useful for error messages. The second string is "open", -* "init", or "absent" to identify the error and is meant to be used for -* making decisions without having to look into the first string (whose -* format is system-dependent). -* -* This module contains an implementation of loadlib for Unix systems that -* have dlfcn, an implementation for Windows, and a stub for other systems. -* See the list at the end of this file for some links to available -* implementations of dlfcn and interfaces to other native dynamic loaders -* on top of which loadlib could be implemented. -* -*/ - -#include "lua.h" -#include "lauxlib.h" -#include "lualib.h" - - -#undef LOADLIB - - -#ifdef USE_DLOPEN -#define LOADLIB -/* -* This is an implementation of loadlib based on the dlfcn interface. -* The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, -* NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least -* as an emulation layer on top of native functions. -*/ - -#include - -static int loadlib(lua_State *L) -{ - const char *path=luaL_checkstring(L,1); - const char *init=luaL_checkstring(L,2); - void *lib=dlopen(path,RTLD_NOW); - if (lib!=NULL) - { - lua_CFunction f=(lua_CFunction) dlsym(lib,init); - if (f!=NULL) - { - lua_pushlightuserdata(L,lib); - lua_pushcclosure(L,f,1); - return 1; - } - } - /* else return appropriate error messages */ - lua_pushnil(L); - lua_pushstring(L,dlerror()); - lua_pushstring(L,(lib!=NULL) ? "init" : "open"); - if (lib!=NULL) dlclose(lib); - return 3; -} - -#endif - - - -/* -** In Windows, default is to use dll; otherwise, default is not to use dll -*/ -#ifndef USE_DLL -#ifdef _WIN32 -#define USE_DLL 1 -#else -#define USE_DLL 0 -#endif -#endif - - -#if USE_DLL -#define LOADLIB -/* -* This is an implementation of loadlib for Windows using native functions. -*/ - -#include - -static void pusherror(lua_State *L) -{ - int error=GetLastError(); - char buffer[128]; - if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, - 0, error, 0, buffer, sizeof(buffer), 0)) - lua_pushstring(L,buffer); - else - lua_pushfstring(L,"system error %d\n",error); -} - -static int loadlib(lua_State *L) -{ - const char *path=luaL_checkstring(L,1); - const char *init=luaL_checkstring(L,2); - HINSTANCE lib=LoadLibrary(path); - if (lib!=NULL) - { - lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init); - if (f!=NULL) - { - lua_pushlightuserdata(L,lib); - lua_pushcclosure(L,f,1); - return 1; - } - } - lua_pushnil(L); - pusherror(L); - lua_pushstring(L,(lib!=NULL) ? "init" : "open"); - if (lib!=NULL) FreeLibrary(lib); - return 3; -} - -#endif - - - -#ifndef LOADLIB -/* Fallback for other systems */ - -/* -** Those systems support dlopen, so they should have defined USE_DLOPEN. -** The default (no)implementation gives them a special error message. -*/ -#ifdef linux -#define LOADLIB -#endif - -#ifdef sun -#define LOADLIB -#endif - -#ifdef sgi -#define LOADLIB -#endif - -#ifdef BSD -#define LOADLIB -#endif - -#ifdef _WIN32 -#define LOADLIB -#endif - -#ifdef LOADLIB -#undef LOADLIB -#define LOADLIB "`loadlib' not installed (check your Lua configuration)" -#else -#define LOADLIB "`loadlib' not supported" -#endif - -static int loadlib(lua_State *L) -{ - lua_pushnil(L); - lua_pushliteral(L,LOADLIB); - lua_pushliteral(L,"absent"); - return 3; -} -#endif - -LUALIB_API int luaopen_loadlib (lua_State *L) -{ - lua_register(L,"loadlib",loadlib); - return 0; -} - -/* -* Here are some links to available implementations of dlfcn and -* interfaces to other native dynamic loaders on top of which loadlib -* could be implemented. Please send contributions and corrections to us. -* -* AIX -* Starting with AIX 4.2, dlfcn is included in the base OS. -* There is also an emulation package available. -* http://www.faqs.org/faqs/aix-faq/part4/section-21.html -* -* HPUX -* HPUX 11 has dlfcn. For HPUX 10 use shl_*. -* http://www.geda.seul.org/mailinglist/geda-dev37/msg00094.html -* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html -* -* Macintosh, Windows -* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html -* -* Mac OS X/Darwin -* http://www.opendarwin.org/projects/dlcompat/ -* -* GLIB has wrapper code for BeOS, OS2, Unix and Windows -* http://cvs.gnome.org/lxr/source/glib/gmodule/ -* -*/ +/* +** $Id: loadlib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $ +** Dynamic library loader for Lua +** See Copyright Notice in lua.h +* +* This Lua library exports a single function, called loadlib, which is +* called from Lua as loadlib(lib,init), where lib is the full name of the +* library to be loaded (including the complete path) and init is the name +* of a function to be called after the library is loaded. Typically, this +* function will register other functions, thus making the complete library +* available to Lua. The init function is *not* automatically called by +* loadlib. Instead, loadlib returns the init function as a Lua function +* that the client can call when it thinks is appropriate. In the case of +* errors, loadlib returns nil and two strings describing the error. +* The first string is supplied by the operating system; it should be +* informative and useful for error messages. The second string is "open", +* "init", or "absent" to identify the error and is meant to be used for +* making decisions without having to look into the first string (whose +* format is system-dependent). +* +* This module contains an implementation of loadlib for Unix systems that +* have dlfcn, an implementation for Windows, and a stub for other systems. +* See the list at the end of this file for some links to available +* implementations of dlfcn and interfaces to other native dynamic loaders +* on top of which loadlib could be implemented. +* +*/ + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" + + +#undef LOADLIB + + +#ifdef USE_DLOPEN +#define LOADLIB +/* +* This is an implementation of loadlib based on the dlfcn interface. +* The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, +* NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least +* as an emulation layer on top of native functions. +*/ + +#include + +static int loadlib(lua_State *L) +{ + const char *path=luaL_checkstring(L,1); + const char *init=luaL_checkstring(L,2); + void *lib=dlopen(path,RTLD_NOW); + if (lib!=NULL) + { + lua_CFunction f=(lua_CFunction) dlsym(lib,init); + if (f!=NULL) + { + lua_pushlightuserdata(L,lib); + lua_pushcclosure(L,f,1); + return 1; + } + } + /* else return appropriate error messages */ + lua_pushnil(L); + lua_pushstring(L,dlerror()); + lua_pushstring(L,(lib!=NULL) ? "init" : "open"); + if (lib!=NULL) dlclose(lib); + return 3; +} + +#endif + + + +/* +** In Windows, default is to use dll; otherwise, default is not to use dll +*/ +#ifndef USE_DLL +#ifdef _WIN32 +#define USE_DLL 1 +#else +#define USE_DLL 0 +#endif +#endif + + +#if USE_DLL +#define LOADLIB +/* +* This is an implementation of loadlib for Windows using native functions. +*/ + +#include + +static void pusherror(lua_State *L) +{ + int error=GetLastError(); + char buffer[128]; + if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + 0, error, 0, buffer, sizeof(buffer), 0)) + lua_pushstring(L,buffer); + else + lua_pushfstring(L,"system error %d\n",error); +} + +static int loadlib(lua_State *L) +{ + const char *path=luaL_checkstring(L,1); + const char *init=luaL_checkstring(L,2); + HINSTANCE lib=LoadLibrary(path); + if (lib!=NULL) + { + lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init); + if (f!=NULL) + { + lua_pushlightuserdata(L,lib); + lua_pushcclosure(L,f,1); + return 1; + } + } + lua_pushnil(L); + pusherror(L); + lua_pushstring(L,(lib!=NULL) ? "init" : "open"); + if (lib!=NULL) FreeLibrary(lib); + return 3; +} + +#endif + + + +#ifndef LOADLIB +/* Fallback for other systems */ + +/* +** Those systems support dlopen, so they should have defined USE_DLOPEN. +** The default (no)implementation gives them a special error message. +*/ +#ifdef linux +#define LOADLIB +#endif + +#ifdef sun +#define LOADLIB +#endif + +#ifdef sgi +#define LOADLIB +#endif + +#ifdef BSD +#define LOADLIB +#endif + +#ifdef _WIN32 +#define LOADLIB +#endif + +#ifdef LOADLIB +#undef LOADLIB +#define LOADLIB "`loadlib' not installed (check your Lua configuration)" +#else +#define LOADLIB "`loadlib' not supported" +#endif + +static int loadlib(lua_State *L) +{ + lua_pushnil(L); + lua_pushliteral(L,LOADLIB); + lua_pushliteral(L,"absent"); + return 3; +} +#endif + +LUALIB_API int luaopen_loadlib (lua_State *L) +{ + lua_register(L,"loadlib",loadlib); + return 0; +} + +/* +* Here are some links to available implementations of dlfcn and +* interfaces to other native dynamic loaders on top of which loadlib +* could be implemented. Please send contributions and corrections to us. +* +* AIX +* Starting with AIX 4.2, dlfcn is included in the base OS. +* There is also an emulation package available. +* http://www.faqs.org/faqs/aix-faq/part4/section-21.html +* +* HPUX +* HPUX 11 has dlfcn. For HPUX 10 use shl_*. +* http://www.geda.seul.org/mailinglist/geda-dev37/msg00094.html +* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html +* +* Macintosh, Windows +* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html +* +* Mac OS X/Darwin +* http://www.opendarwin.org/projects/dlcompat/ +* +* GLIB has wrapper code for BeOS, OS2, Unix and Windows +* http://cvs.gnome.org/lxr/source/glib/gmodule/ +* +*/ diff --git a/lib/lua/src/LuaLib/lstrlib.c b/lib/lua/src/LuaLib/lstrlib.c index 9b5fe8a..2e5f26e 100644 --- a/lib/lua/src/LuaLib/lstrlib.c +++ b/lib/lua/src/LuaLib/lstrlib.c @@ -1,770 +1,770 @@ -/* -** $Id: lstrlib.c,v 1.3 2004-11-27 21:35:21 pixel Exp $ -** Standard library for string operations and pattern-matching -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include - -#define lstrlib_c - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* macro to `unsign' a character */ -#ifndef uchar -#define uchar(c) ((unsigned char)(c)) -#endif - - -typedef long sint32; /* a signed version for size_t */ - - -static int str_len (lua_State *L) { - size_t l; - luaL_checklstring(L, 1, &l); - lua_pushnumber(L, (lua_Number)l); - return 1; -} - - -static sint32 posrelat (sint32 pos, size_t len) { - /* relative string position: negative means back from end */ - return (pos>=0) ? pos : (sint32)len+pos+1; -} - - -static int str_sub (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - sint32 start = posrelat(luaL_checklong(L, 2), l); - sint32 end = posrelat(luaL_optlong(L, 3, -1), l); - if (start < 1) start = 1; - if (end > (sint32)l) end = (sint32)l; - if (start <= end) - lua_pushlstring(L, s+start-1, end-start+1); - else lua_pushliteral(L, ""); - return 1; -} - - -static int str_lower (lua_State *L) { - size_t l; - size_t i; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - luaL_buffinit(L, &b); - for (i=0; i 0) - luaL_addlstring(&b, s, l); - luaL_pushresult(&b); - return 1; -} - - -static int str_byte (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - sint32 pos = posrelat(luaL_optlong(L, 2, 1), l); - if (pos <= 0 || (size_t)(pos) > l) /* index out of range? */ - return 0; /* no answer */ - lua_pushnumber(L, uchar(s[pos-1])); - return 1; -} - - -static int str_char (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int i; - luaL_Buffer b; - luaL_buffinit(L, &b); - for (i=1; i<=n; i++) { - int c = luaL_checkint(L, i); - luaL_argcheck(L, uchar(c) == c, i, "invalid value"); - luaL_putchar(&b, uchar(c)); - } - luaL_pushresult(&b); - return 1; -} - - -static int writer (lua_State *L, const void* b, size_t size, void* B) { - (void)L; - luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); - return 1; -} - - -static int str_dump (lua_State *L) { - luaL_Buffer b; - luaL_checktype(L, 1, LUA_TFUNCTION); - luaL_buffinit(L,&b); - if (!lua_dump(L, writer, &b)) - luaL_error(L, "unable to dump given function"); - luaL_pushresult(&b); - return 1; -} - - - -/* -** {====================================================== -** PATTERN MATCHING -** ======================================================= -*/ - -#ifndef MAX_CAPTURES -#define MAX_CAPTURES 32 /* arbitrary limit */ -#endif - - -#define CAP_UNFINISHED (-1) -#define CAP_POSITION (-2) - -typedef struct MatchState { - const char *src_init; /* init of source string */ - const char *src_end; /* end (`\0') of source string */ - lua_State *L; - int level; /* total number of captures (finished or unfinished) */ - struct { - const char *init; - sint32 len; - } capture[MAX_CAPTURES]; -} MatchState; - - -#define ESC '%' -#define SPECIALS "^$*+?.([%-" - - -static int check_capture (MatchState *ms, int l) { - l -= '1'; - if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) - return luaL_error(ms->L, "invalid capture index"); - return l; -} - - -static int capture_to_close (MatchState *ms) { - int level = ms->level; - for (level--; level>=0; level--) - if (ms->capture[level].len == CAP_UNFINISHED) return level; - return luaL_error(ms->L, "invalid pattern capture"); -} - - -static const char *luaI_classend (MatchState *ms, const char *p) { - switch (*p++) { - case ESC: { - if (*p == '\0') - luaL_error(ms->L, "malformed pattern (ends with `%')"); - return p+1; - } - case '[': { - if (*p == '^') p++; - do { /* look for a `]' */ - if (*p == '\0') - luaL_error(ms->L, "malformed pattern (missing `]')"); - if (*(p++) == ESC && *p != '\0') - p++; /* skip escapes (e.g. `%]') */ - } while (*p != ']'); - return p+1; - } - default: { - return p; - } - } -} - - -static int match_class (int c, int cl) { - int res; - switch (tolower(cl)) { - case 'a' : res = isalpha(c); break; - case 'c' : res = iscntrl(c); break; - case 'd' : res = isdigit(c); break; - case 'l' : res = islower(c); break; - case 'p' : res = ispunct(c); break; - case 's' : res = isspace(c); break; - case 'u' : res = isupper(c); break; - case 'w' : res = isalnum(c); break; - case 'x' : res = isxdigit(c); break; - case 'z' : res = (c == 0); break; - default: return (cl == c); - } - return (islower(cl) ? res : !res); -} - - -static int matchbracketclass (int c, const char *p, const char *ec) { - int sig = 1; - if (*(p+1) == '^') { - sig = 0; - p++; /* skip the `^' */ - } - while (++p < ec) { - if (*p == ESC) { - p++; - if (match_class(c, *p)) - return sig; - } - else if ((*(p+1) == '-') && (p+2 < ec)) { - p+=2; - if (uchar(*(p-2)) <= c && c <= uchar(*p)) - return sig; - } - else if (uchar(*p) == c) return sig; - } - return !sig; -} - - -static int luaI_singlematch (int c, const char *p, const char *ep) { - switch (*p) { - case '.': return 1; /* matches any char */ - case ESC: return match_class(c, *(p+1)); - case '[': return matchbracketclass(c, p, ep-1); - default: return (uchar(*p) == c); - } -} - - -static const char *match (MatchState *ms, const char *s, const char *p); - - -static const char *matchbalance (MatchState *ms, const char *s, - const char *p) { - if (*p == 0 || *(p+1) == 0) - luaL_error(ms->L, "unbalanced pattern"); - if (*s != *p) return NULL; - else { - int b = *p; - int e = *(p+1); - int cont = 1; - while (++s < ms->src_end) { - if (*s == e) { - if (--cont == 0) return s+1; - } - else if (*s == b) cont++; - } - } - return NULL; /* string ends out of balance */ -} - - -static const char *max_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - sint32 i = 0; /* counts maximum expand for item */ - while ((s+i)src_end && luaI_singlematch(uchar(*(s+i)), p, ep)) - i++; - /* keeps trying to match with the maximum repetitions */ - while (i>=0) { - const char *res = match(ms, (s+i), ep+1); - if (res) return res; - i--; /* else didn't match; reduce 1 repetition to try again */ - } - return NULL; -} - - -static const char *min_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - for (;;) { - const char *res = match(ms, s, ep+1); - if (res != NULL) - return res; - else if (ssrc_end && luaI_singlematch(uchar(*s), p, ep)) - s++; /* try with one more repetition */ - else return NULL; - } -} - - -static const char *start_capture (MatchState *ms, const char *s, - const char *p, int what) { - const char *res; - int level = ms->level; - if (level >= MAX_CAPTURES) luaL_error(ms->L, "too many captures"); - ms->capture[level].init = s; - ms->capture[level].len = what; - ms->level = level+1; - if ((res=match(ms, s, p)) == NULL) /* match failed? */ - ms->level--; /* undo capture */ - return res; -} - - -static const char *end_capture (MatchState *ms, const char *s, - const char *p) { - int l = capture_to_close(ms); - const char *res; - ms->capture[l].len = s - ms->capture[l].init; /* close capture */ - if ((res = match(ms, s, p)) == NULL) /* match failed? */ - ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ - return res; -} - - -static const char *match_capture (MatchState *ms, const char *s, int l) { - size_t len; - l = check_capture(ms, l); - len = ms->capture[l].len; - if ((size_t)(ms->src_end-s) >= len && - memcmp(ms->capture[l].init, s, len) == 0) - return s+len; - else return NULL; -} - - -static const char *match (MatchState *ms, const char *s, const char *p) { - init: /* using goto's to optimize tail recursion */ - switch (*p) { - case '(': { /* start capture */ - if (*(p+1) == ')') /* position capture? */ - return start_capture(ms, s, p+2, CAP_POSITION); - else - return start_capture(ms, s, p+1, CAP_UNFINISHED); - } - case ')': { /* end capture */ - return end_capture(ms, s, p+1); - } - case ESC: { - switch (*(p+1)) { - case 'b': { /* balanced string? */ - s = matchbalance(ms, s, p+2); - if (s == NULL) return NULL; - p+=4; goto init; /* else return match(ms, s, p+4); */ - } - case 'f': { /* frontier? */ - const char *ep; char previous; - p += 2; - if (*p != '[') - luaL_error(ms->L, "missing `[' after `%%f' in pattern"); - ep = luaI_classend(ms, p); /* points to what is next */ - previous = (s == ms->src_init) ? '\0' : *(s-1); - if (matchbracketclass(uchar(previous), p, ep-1) || - !matchbracketclass(uchar(*s), p, ep-1)) return NULL; - p=ep; goto init; /* else return match(ms, s, ep); */ - } - default: { - if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ - s = match_capture(ms, s, *(p+1)); - if (s == NULL) return NULL; - p+=2; goto init; /* else return match(ms, s, p+2) */ - } - goto dflt; /* case default */ - } - } - } - case '\0': { /* end of pattern */ - return s; /* match succeeded */ - } - case '$': { - if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ - return (s == ms->src_end) ? s : NULL; /* check end of string */ - else goto dflt; - } - default: dflt: { /* it is a pattern item */ - const char *ep = luaI_classend(ms, p); /* points to what is next */ - int m = ssrc_end && luaI_singlematch(uchar(*s), p, ep); - switch (*ep) { - case '?': { /* optional */ - const char *res; - if (m && ((res=match(ms, s+1, ep+1)) != NULL)) - return res; - p=ep+1; goto init; /* else return match(ms, s, ep+1); */ - } - case '*': { /* 0 or more repetitions */ - return max_expand(ms, s, p, ep); - } - case '+': { /* 1 or more repetitions */ - return (m ? max_expand(ms, s+1, p, ep) : NULL); - } - case '-': { /* 0 or more repetitions (minimum) */ - return min_expand(ms, s, p, ep); - } - default: { - if (!m) return NULL; - s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ - } - } - } - } -} - - - -static const char *lmemfind (const char *s1, size_t l1, - const char *s2, size_t l2) { - if (l2 == 0) return s1; /* empty strings are everywhere */ - else if (l2 > l1) return NULL; /* avoids a negative `l1' */ - else { - const char *init; /* to search for a `*s2' inside `s1' */ - l2--; /* 1st char will be checked by `memchr' */ - l1 = l1-l2; /* `s2' cannot be found after that */ - while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { - init++; /* 1st char is already checked */ - if (memcmp(init, s2+1, l2) == 0) - return init-1; - else { /* correct `l1' and `s1' to try again */ - l1 -= init-s1; - s1 = init; - } - } - return NULL; /* not found */ - } -} - - -static void push_onecapture (MatchState *ms, int i) { - int l = ms->capture[i].len; - if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); - if (l == CAP_POSITION) - lua_pushnumber(ms->L, (lua_Number)(ms->capture[i].init - ms->src_init + 1)); - else - lua_pushlstring(ms->L, ms->capture[i].init, l); -} - - -static int push_captures (MatchState *ms, const char *s, const char *e) { - int i; - luaL_checkstack(ms->L, ms->level, "too many captures"); - if (ms->level == 0 && s) { /* no explicit captures? */ - lua_pushlstring(ms->L, s, e-s); /* return whole match */ - return 1; - } - else { /* return all captures */ - for (i=0; ilevel; i++) - push_onecapture(ms, i); - return ms->level; /* number of strings pushed */ - } -} - - -static int str_find (lua_State *L) { - size_t l1, l2; - const char *s = luaL_checklstring(L, 1, &l1); - const char *p = luaL_checklstring(L, 2, &l2); - sint32 init = posrelat(luaL_optlong(L, 3, 1), l1) - 1; - if (init < 0) init = 0; - else if ((size_t)(init) > l1) init = (sint32)l1; - if (lua_toboolean(L, 4) || /* explicit request? */ - strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */ - /* do a plain search */ - const char *s2 = lmemfind(s+init, l1-init, p, l2); - if (s2) { - lua_pushnumber(L, (lua_Number)(s2-s+1)); - lua_pushnumber(L, (lua_Number)(s2-s+l2)); - return 2; - } - } - else { - MatchState ms; - int anchor = (*p == '^') ? (p++, 1) : 0; - const char *s1=s+init; - ms.L = L; - ms.src_init = s; - ms.src_end = s+l1; - do { - const char *res; - ms.level = 0; - if ((res=match(&ms, s1, p)) != NULL) { - lua_pushnumber(L, (lua_Number)(s1-s+1)); /* start */ - lua_pushnumber(L, (lua_Number)(res-s)); /* end */ - return push_captures(&ms, NULL, 0) + 2; - } - } while (s1++L; - if (lua_isstring(L, 3)) { - const char *news = lua_tostring(L, 3); - size_t l = lua_strlen(L, 3); - size_t i; - for (i=0; i= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)), - 3, "string or function expected"); - luaL_buffinit(L, &b); - ms.L = L; - ms.src_init = src; - ms.src_end = src+srcl; - while (n < max_s) { - const char *e; - ms.level = 0; - e = match(&ms, src, p); - if (e) { - n++; - add_s(&ms, &b, src, e); - } - if (e && e>src) /* non empty match? */ - src = e; /* skip it */ - else if (src < ms.src_end) - luaL_putchar(&b, *src++); - else break; - if (anchor) break; - } - luaL_addlstring(&b, src, ms.src_end-src); - luaL_pushresult(&b); - lua_pushnumber(L, (lua_Number)n); /* number of substitutions */ - return 2; -} - -/* }====================================================== */ - - -/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ -#define MAX_ITEM 512 -/* maximum size of each format specification (such as '%-099.99d') */ -#define MAX_FORMAT 20 - - -static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - luaL_putchar(b, '"'); - while (l--) { - switch (*s) { - case '"': case '\\': case '\n': { - luaL_putchar(b, '\\'); - luaL_putchar(b, *s); - break; - } - case '\0': { - luaL_addlstring(b, "\\000", 4); - break; - } - default: { - luaL_putchar(b, *s); - break; - } - } - s++; - } - luaL_putchar(b, '"'); -} - - -static const char *scanformat (lua_State *L, const char *strfrmt, - char *form, int *hasprecision) { - const char *p = strfrmt; - while (strchr("-+ #0", *p)) p++; /* skip flags */ - if (isdigit(uchar(*p))) p++; /* skip width */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - if (*p == '.') { - p++; - *hasprecision = 1; - if (isdigit(uchar(*p))) p++; /* skip precision */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - } - if (isdigit(uchar(*p))) - luaL_error(L, "invalid format (width or precision too long)"); - if (p-strfrmt+2 > MAX_FORMAT) /* +2 to include `%' and the specifier */ - luaL_error(L, "invalid format (too long)"); - form[0] = '%'; - strncpy(form+1, strfrmt, p-strfrmt+1); - form[p-strfrmt+2] = 0; - return p; -} - - -static int str_format (lua_State *L) { - int arg = 1; - size_t sfl; - const char *strfrmt = luaL_checklstring(L, arg, &sfl); - const char *strfrmt_end = strfrmt+sfl; - luaL_Buffer b; - luaL_buffinit(L, &b); - while (strfrmt < strfrmt_end) { - if (*strfrmt != '%') - luaL_putchar(&b, *strfrmt++); - else if (*++strfrmt == '%') - luaL_putchar(&b, *strfrmt++); /* %% */ - else { /* format item */ - char form[MAX_FORMAT]; /* to store the format (`%...') */ - char buff[MAX_ITEM]; /* to store the formatted item */ - int hasprecision = 0; - if (isdigit(uchar(*strfrmt)) && *(strfrmt+1) == '$') - return luaL_error(L, "obsolete option (d$) to `format'"); - arg++; - strfrmt = scanformat(L, strfrmt, form, &hasprecision); - switch (*strfrmt++) { - case 'c': case 'd': case 'i': { - sprintf(buff, form, luaL_checkint(L, arg)); - break; - } - case 'o': case 'u': case 'x': case 'X': { - sprintf(buff, form, (unsigned int)(luaL_checknumber(L, arg))); - break; - } - case 'e': case 'E': case 'f': - case 'g': case 'G': { - sprintf(buff, form, luaL_checknumber(L, arg)); - break; - } - case 'q': { - luaI_addquoted(L, &b, arg); - continue; /* skip the `addsize' at the end */ - } - case 's': { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - if (!hasprecision && l >= 100) { - /* no precision and string is too long to be formatted; - keep original string */ - lua_pushvalue(L, arg); - luaL_addvalue(&b); - continue; /* skip the `addsize' at the end */ - } - else { - sprintf(buff, form, s); - break; - } - } - default: { /* also treat cases `pnLlh' */ - return luaL_error(L, "invalid option to `format'"); - } - } - luaL_addlstring(&b, buff, strlen(buff)); - } - } - luaL_pushresult(&b); - return 1; -} - - -static const luaL_reg strlib[] = { - {"len", str_len}, - {"sub", str_sub}, - {"lower", str_lower}, - {"upper", str_upper}, - {"char", str_char}, - {"rep", str_rep}, - {"byte", str_byte}, - {"format", str_format}, - {"dump", str_dump}, - {"find", str_find}, - {"gfind", gfind}, - {"gsub", str_gsub}, - {NULL, NULL} -}; - - -/* -** Open string library -*/ -LUALIB_API int luaopen_string (lua_State *L) { - luaL_openlib(L, LUA_STRLIBNAME, strlib, 0); - return 1; -} - +/* +** $Id: lstrlib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $ +** Standard library for string operations and pattern-matching +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + +#define lstrlib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* macro to `unsign' a character */ +#ifndef uchar +#define uchar(c) ((unsigned char)(c)) +#endif + + +typedef long sint32; /* a signed version for size_t */ + + +static int str_len (lua_State *L) { + size_t l; + luaL_checklstring(L, 1, &l); + lua_pushnumber(L, (lua_Number)l); + return 1; +} + + +static sint32 posrelat (sint32 pos, size_t len) { + /* relative string position: negative means back from end */ + return (pos>=0) ? pos : (sint32)len+pos+1; +} + + +static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + sint32 start = posrelat(luaL_checklong(L, 2), l); + sint32 end = posrelat(luaL_optlong(L, 3, -1), l); + if (start < 1) start = 1; + if (end > (sint32)l) end = (sint32)l; + if (start <= end) + lua_pushlstring(L, s+start-1, end-start+1); + else lua_pushliteral(L, ""); + return 1; +} + + +static int str_lower (lua_State *L) { + size_t l; + size_t i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + luaL_buffinit(L, &b); + for (i=0; i 0) + luaL_addlstring(&b, s, l); + luaL_pushresult(&b); + return 1; +} + + +static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + sint32 pos = posrelat(luaL_optlong(L, 2, 1), l); + if (pos <= 0 || (size_t)(pos) > l) /* index out of range? */ + return 0; /* no answer */ + lua_pushnumber(L, uchar(s[pos-1])); + return 1; +} + + +static int str_char (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + luaL_Buffer b; + luaL_buffinit(L, &b); + for (i=1; i<=n; i++) { + int c = luaL_checkint(L, i); + luaL_argcheck(L, uchar(c) == c, i, "invalid value"); + luaL_putchar(&b, uchar(c)); + } + luaL_pushresult(&b); + return 1; +} + + +static int writer (lua_State *L, const void* b, size_t size, void* B) { + (void)L; + luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); + return 1; +} + + +static int str_dump (lua_State *L) { + luaL_Buffer b; + luaL_checktype(L, 1, LUA_TFUNCTION); + luaL_buffinit(L,&b); + if (!lua_dump(L, writer, &b)) + luaL_error(L, "unable to dump given function"); + luaL_pushresult(&b); + return 1; +} + + + +/* +** {====================================================== +** PATTERN MATCHING +** ======================================================= +*/ + +#ifndef MAX_CAPTURES +#define MAX_CAPTURES 32 /* arbitrary limit */ +#endif + + +#define CAP_UNFINISHED (-1) +#define CAP_POSITION (-2) + +typedef struct MatchState { + const char *src_init; /* init of source string */ + const char *src_end; /* end (`\0') of source string */ + lua_State *L; + int level; /* total number of captures (finished or unfinished) */ + struct { + const char *init; + sint32 len; + } capture[MAX_CAPTURES]; +} MatchState; + + +#define ESC '%' +#define SPECIALS "^$*+?.([%-" + + +static int check_capture (MatchState *ms, int l) { + l -= '1'; + if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) + return luaL_error(ms->L, "invalid capture index"); + return l; +} + + +static int capture_to_close (MatchState *ms) { + int level = ms->level; + for (level--; level>=0; level--) + if (ms->capture[level].len == CAP_UNFINISHED) return level; + return luaL_error(ms->L, "invalid pattern capture"); +} + + +static const char *luaI_classend (MatchState *ms, const char *p) { + switch (*p++) { + case ESC: { + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (ends with `%')"); + return p+1; + } + case '[': { + if (*p == '^') p++; + do { /* look for a `]' */ + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (missing `]')"); + if (*(p++) == ESC && *p != '\0') + p++; /* skip escapes (e.g. `%]') */ + } while (*p != ']'); + return p+1; + } + default: { + return p; + } + } +} + + +static int match_class (int c, int cl) { + int res; + switch (tolower(cl)) { + case 'a' : res = isalpha(c); break; + case 'c' : res = iscntrl(c); break; + case 'd' : res = isdigit(c); break; + case 'l' : res = islower(c); break; + case 'p' : res = ispunct(c); break; + case 's' : res = isspace(c); break; + case 'u' : res = isupper(c); break; + case 'w' : res = isalnum(c); break; + case 'x' : res = isxdigit(c); break; + case 'z' : res = (c == 0); break; + default: return (cl == c); + } + return (islower(cl) ? res : !res); +} + + +static int matchbracketclass (int c, const char *p, const char *ec) { + int sig = 1; + if (*(p+1) == '^') { + sig = 0; + p++; /* skip the `^' */ + } + while (++p < ec) { + if (*p == ESC) { + p++; + if (match_class(c, *p)) + return sig; + } + else if ((*(p+1) == '-') && (p+2 < ec)) { + p+=2; + if (uchar(*(p-2)) <= c && c <= uchar(*p)) + return sig; + } + else if (uchar(*p) == c) return sig; + } + return !sig; +} + + +static int luaI_singlematch (int c, const char *p, const char *ep) { + switch (*p) { + case '.': return 1; /* matches any char */ + case ESC: return match_class(c, *(p+1)); + case '[': return matchbracketclass(c, p, ep-1); + default: return (uchar(*p) == c); + } +} + + +static const char *match (MatchState *ms, const char *s, const char *p); + + +static const char *matchbalance (MatchState *ms, const char *s, + const char *p) { + if (*p == 0 || *(p+1) == 0) + luaL_error(ms->L, "unbalanced pattern"); + if (*s != *p) return NULL; + else { + int b = *p; + int e = *(p+1); + int cont = 1; + while (++s < ms->src_end) { + if (*s == e) { + if (--cont == 0) return s+1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ +} + + +static const char *max_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + sint32 i = 0; /* counts maximum expand for item */ + while ((s+i)src_end && luaI_singlematch(uchar(*(s+i)), p, ep)) + i++; + /* keeps trying to match with the maximum repetitions */ + while (i>=0) { + const char *res = match(ms, (s+i), ep+1); + if (res) return res; + i--; /* else didn't match; reduce 1 repetition to try again */ + } + return NULL; +} + + +static const char *min_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + for (;;) { + const char *res = match(ms, s, ep+1); + if (res != NULL) + return res; + else if (ssrc_end && luaI_singlematch(uchar(*s), p, ep)) + s++; /* try with one more repetition */ + else return NULL; + } +} + + +static const char *start_capture (MatchState *ms, const char *s, + const char *p, int what) { + const char *res; + int level = ms->level; + if (level >= MAX_CAPTURES) luaL_error(ms->L, "too many captures"); + ms->capture[level].init = s; + ms->capture[level].len = what; + ms->level = level+1; + if ((res=match(ms, s, p)) == NULL) /* match failed? */ + ms->level--; /* undo capture */ + return res; +} + + +static const char *end_capture (MatchState *ms, const char *s, + const char *p) { + int l = capture_to_close(ms); + const char *res; + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ + if ((res = match(ms, s, p)) == NULL) /* match failed? */ + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ + return res; +} + + +static const char *match_capture (MatchState *ms, const char *s, int l) { + size_t len; + l = check_capture(ms, l); + len = ms->capture[l].len; + if ((size_t)(ms->src_end-s) >= len && + memcmp(ms->capture[l].init, s, len) == 0) + return s+len; + else return NULL; +} + + +static const char *match (MatchState *ms, const char *s, const char *p) { + init: /* using goto's to optimize tail recursion */ + switch (*p) { + case '(': { /* start capture */ + if (*(p+1) == ')') /* position capture? */ + return start_capture(ms, s, p+2, CAP_POSITION); + else + return start_capture(ms, s, p+1, CAP_UNFINISHED); + } + case ')': { /* end capture */ + return end_capture(ms, s, p+1); + } + case ESC: { + switch (*(p+1)) { + case 'b': { /* balanced string? */ + s = matchbalance(ms, s, p+2); + if (s == NULL) return NULL; + p+=4; goto init; /* else return match(ms, s, p+4); */ + } + case 'f': { /* frontier? */ + const char *ep; char previous; + p += 2; + if (*p != '[') + luaL_error(ms->L, "missing `[' after `%%f' in pattern"); + ep = luaI_classend(ms, p); /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s-1); + if (matchbracketclass(uchar(previous), p, ep-1) || + !matchbracketclass(uchar(*s), p, ep-1)) return NULL; + p=ep; goto init; /* else return match(ms, s, ep); */ + } + default: { + if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ + s = match_capture(ms, s, *(p+1)); + if (s == NULL) return NULL; + p+=2; goto init; /* else return match(ms, s, p+2) */ + } + goto dflt; /* case default */ + } + } + } + case '\0': { /* end of pattern */ + return s; /* match succeeded */ + } + case '$': { + if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ + return (s == ms->src_end) ? s : NULL; /* check end of string */ + else goto dflt; + } + default: dflt: { /* it is a pattern item */ + const char *ep = luaI_classend(ms, p); /* points to what is next */ + int m = ssrc_end && luaI_singlematch(uchar(*s), p, ep); + switch (*ep) { + case '?': { /* optional */ + const char *res; + if (m && ((res=match(ms, s+1, ep+1)) != NULL)) + return res; + p=ep+1; goto init; /* else return match(ms, s, ep+1); */ + } + case '*': { /* 0 or more repetitions */ + return max_expand(ms, s, p, ep); + } + case '+': { /* 1 or more repetitions */ + return (m ? max_expand(ms, s+1, p, ep) : NULL); + } + case '-': { /* 0 or more repetitions (minimum) */ + return min_expand(ms, s, p, ep); + } + default: { + if (!m) return NULL; + s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ + } + } + } + } +} + + + +static const char *lmemfind (const char *s1, size_t l1, + const char *s2, size_t l2) { + if (l2 == 0) return s1; /* empty strings are everywhere */ + else if (l2 > l1) return NULL; /* avoids a negative `l1' */ + else { + const char *init; /* to search for a `*s2' inside `s1' */ + l2--; /* 1st char will be checked by `memchr' */ + l1 = l1-l2; /* `s2' cannot be found after that */ + while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { + init++; /* 1st char is already checked */ + if (memcmp(init, s2+1, l2) == 0) + return init-1; + else { /* correct `l1' and `s1' to try again */ + l1 -= init-s1; + s1 = init; + } + } + return NULL; /* not found */ + } +} + + +static void push_onecapture (MatchState *ms, int i) { + int l = ms->capture[i].len; + if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); + if (l == CAP_POSITION) + lua_pushnumber(ms->L, (lua_Number)(ms->capture[i].init - ms->src_init + 1)); + else + lua_pushlstring(ms->L, ms->capture[i].init, l); +} + + +static int push_captures (MatchState *ms, const char *s, const char *e) { + int i; + luaL_checkstack(ms->L, ms->level, "too many captures"); + if (ms->level == 0 && s) { /* no explicit captures? */ + lua_pushlstring(ms->L, s, e-s); /* return whole match */ + return 1; + } + else { /* return all captures */ + for (i=0; ilevel; i++) + push_onecapture(ms, i); + return ms->level; /* number of strings pushed */ + } +} + + +static int str_find (lua_State *L) { + size_t l1, l2; + const char *s = luaL_checklstring(L, 1, &l1); + const char *p = luaL_checklstring(L, 2, &l2); + sint32 init = posrelat(luaL_optlong(L, 3, 1), l1) - 1; + if (init < 0) init = 0; + else if ((size_t)(init) > l1) init = (sint32)l1; + if (lua_toboolean(L, 4) || /* explicit request? */ + strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */ + /* do a plain search */ + const char *s2 = lmemfind(s+init, l1-init, p, l2); + if (s2) { + lua_pushnumber(L, (lua_Number)(s2-s+1)); + lua_pushnumber(L, (lua_Number)(s2-s+l2)); + return 2; + } + } + else { + MatchState ms; + int anchor = (*p == '^') ? (p++, 1) : 0; + const char *s1=s+init; + ms.L = L; + ms.src_init = s; + ms.src_end = s+l1; + do { + const char *res; + ms.level = 0; + if ((res=match(&ms, s1, p)) != NULL) { + lua_pushnumber(L, (lua_Number)(s1-s+1)); /* start */ + lua_pushnumber(L, (lua_Number)(res-s)); /* end */ + return push_captures(&ms, NULL, 0) + 2; + } + } while (s1++L; + if (lua_isstring(L, 3)) { + const char *news = lua_tostring(L, 3); + size_t l = lua_strlen(L, 3); + size_t i; + for (i=0; i= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)), + 3, "string or function expected"); + luaL_buffinit(L, &b); + ms.L = L; + ms.src_init = src; + ms.src_end = src+srcl; + while (n < max_s) { + const char *e; + ms.level = 0; + e = match(&ms, src, p); + if (e) { + n++; + add_s(&ms, &b, src, e); + } + if (e && e>src) /* non empty match? */ + src = e; /* skip it */ + else if (src < ms.src_end) + luaL_putchar(&b, *src++); + else break; + if (anchor) break; + } + luaL_addlstring(&b, src, ms.src_end-src); + luaL_pushresult(&b); + lua_pushnumber(L, (lua_Number)n); /* number of substitutions */ + return 2; +} + +/* }====================================================== */ + + +/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ +#define MAX_ITEM 512 +/* maximum size of each format specification (such as '%-099.99d') */ +#define MAX_FORMAT 20 + + +static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + luaL_putchar(b, '"'); + while (l--) { + switch (*s) { + case '"': case '\\': case '\n': { + luaL_putchar(b, '\\'); + luaL_putchar(b, *s); + break; + } + case '\0': { + luaL_addlstring(b, "\\000", 4); + break; + } + default: { + luaL_putchar(b, *s); + break; + } + } + s++; + } + luaL_putchar(b, '"'); +} + + +static const char *scanformat (lua_State *L, const char *strfrmt, + char *form, int *hasprecision) { + const char *p = strfrmt; + while (strchr("-+ #0", *p)) p++; /* skip flags */ + if (isdigit(uchar(*p))) p++; /* skip width */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + if (*p == '.') { + p++; + *hasprecision = 1; + if (isdigit(uchar(*p))) p++; /* skip precision */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + } + if (isdigit(uchar(*p))) + luaL_error(L, "invalid format (width or precision too long)"); + if (p-strfrmt+2 > MAX_FORMAT) /* +2 to include `%' and the specifier */ + luaL_error(L, "invalid format (too long)"); + form[0] = '%'; + strncpy(form+1, strfrmt, p-strfrmt+1); + form[p-strfrmt+2] = 0; + return p; +} + + +static int str_format (lua_State *L) { + int arg = 1; + size_t sfl; + const char *strfrmt = luaL_checklstring(L, arg, &sfl); + const char *strfrmt_end = strfrmt+sfl; + luaL_Buffer b; + luaL_buffinit(L, &b); + while (strfrmt < strfrmt_end) { + if (*strfrmt != '%') + luaL_putchar(&b, *strfrmt++); + else if (*++strfrmt == '%') + luaL_putchar(&b, *strfrmt++); /* %% */ + else { /* format item */ + char form[MAX_FORMAT]; /* to store the format (`%...') */ + char buff[MAX_ITEM]; /* to store the formatted item */ + int hasprecision = 0; + if (isdigit(uchar(*strfrmt)) && *(strfrmt+1) == '$') + return luaL_error(L, "obsolete option (d$) to `format'"); + arg++; + strfrmt = scanformat(L, strfrmt, form, &hasprecision); + switch (*strfrmt++) { + case 'c': case 'd': case 'i': { + sprintf(buff, form, luaL_checkint(L, arg)); + break; + } + case 'o': case 'u': case 'x': case 'X': { + sprintf(buff, form, (unsigned int)(luaL_checknumber(L, arg))); + break; + } + case 'e': case 'E': case 'f': + case 'g': case 'G': { + sprintf(buff, form, luaL_checknumber(L, arg)); + break; + } + case 'q': { + luaI_addquoted(L, &b, arg); + continue; /* skip the `addsize' at the end */ + } + case 's': { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + if (!hasprecision && l >= 100) { + /* no precision and string is too long to be formatted; + keep original string */ + lua_pushvalue(L, arg); + luaL_addvalue(&b); + continue; /* skip the `addsize' at the end */ + } + else { + sprintf(buff, form, s); + break; + } + } + default: { /* also treat cases `pnLlh' */ + return luaL_error(L, "invalid option to `format'"); + } + } + luaL_addlstring(&b, buff, strlen(buff)); + } + } + luaL_pushresult(&b); + return 1; +} + + +static const luaL_reg strlib[] = { + {"len", str_len}, + {"sub", str_sub}, + {"lower", str_lower}, + {"upper", str_upper}, + {"char", str_char}, + {"rep", str_rep}, + {"byte", str_byte}, + {"format", str_format}, + {"dump", str_dump}, + {"find", str_find}, + {"gfind", gfind}, + {"gsub", str_gsub}, + {NULL, NULL} +}; + + +/* +** Open string library +*/ +LUALIB_API int luaopen_string (lua_State *L) { + luaL_openlib(L, LUA_STRLIBNAME, strlib, 0); + return 1; +} + diff --git a/lib/lua/src/LuaLib/ltablib.c b/lib/lua/src/LuaLib/ltablib.c index fc6c380..71f3afa 100644 --- a/lib/lua/src/LuaLib/ltablib.c +++ b/lib/lua/src/LuaLib/ltablib.c @@ -1,250 +1,250 @@ -/* -** $Id: ltablib.c,v 1.3 2004-11-27 21:35:21 pixel Exp $ -** Library for Table Manipulation -** See Copyright Notice in lua.h -*/ - - -#include - -#define ltablib_c - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) - - -static int luaB_foreachi (lua_State *L) { - int i; - int n = aux_getn(L, 1); - luaL_checktype(L, 2, LUA_TFUNCTION); - for (i=1; i<=n; i++) { - lua_pushvalue(L, 2); /* function */ - lua_pushnumber(L, (lua_Number)i); /* 1st argument */ - lua_rawgeti(L, 1, i); /* 2nd argument */ - lua_call(L, 2, 1); - if (!lua_isnil(L, -1)) - return 1; - lua_pop(L, 1); /* remove nil result */ - } - return 0; -} - - -static int luaB_foreach (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checktype(L, 2, LUA_TFUNCTION); - lua_pushnil(L); /* first key */ - for (;;) { - if (lua_next(L, 1) == 0) - return 0; - lua_pushvalue(L, 2); /* function */ - lua_pushvalue(L, -3); /* key */ - lua_pushvalue(L, -3); /* value */ - lua_call(L, 2, 1); - if (!lua_isnil(L, -1)) - return 1; - lua_pop(L, 2); /* remove value and result */ - } -} - - -static int luaB_getn (lua_State *L) { - lua_pushnumber(L, (lua_Number)aux_getn(L, 1)); - return 1; -} - - -static int luaB_setn (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_setn(L, 1, luaL_checkint(L, 2)); - return 0; -} - - -static int luaB_tinsert (lua_State *L) { - int v = lua_gettop(L); /* number of arguments */ - int n = aux_getn(L, 1) + 1; - int pos; /* where to insert new element */ - if (v == 2) /* called with only 2 arguments */ - pos = n; /* insert new element at the end */ - else { - pos = luaL_checkint(L, 2); /* 2nd argument is the position */ - if (pos > n) n = pos; /* `grow' array if necessary */ - v = 3; /* function may be called with more than 3 args */ - } - luaL_setn(L, 1, n); /* new size */ - while (--n >= pos) { /* move up elements */ - lua_rawgeti(L, 1, n); - lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */ - } - lua_pushvalue(L, v); - lua_rawseti(L, 1, pos); /* t[pos] = v */ - return 0; -} - - -static int luaB_tremove (lua_State *L) { - int n = aux_getn(L, 1); - int pos = luaL_optint(L, 2, n); - if (n <= 0) return 0; /* table is `empty' */ - luaL_setn(L, 1, n-1); /* t.n = n-1 */ - lua_rawgeti(L, 1, pos); /* result = t[pos] */ - for ( ;pos= P */ - while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { - if (i>u) luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[i] */ - } - /* repeat --j until a[j] <= P */ - while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { - if (j + +#define ltablib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) + + +static int luaB_foreachi (lua_State *L) { + int i; + int n = aux_getn(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + for (i=1; i<=n; i++) { + lua_pushvalue(L, 2); /* function */ + lua_pushnumber(L, (lua_Number)i); /* 1st argument */ + lua_rawgeti(L, 1, i); /* 2nd argument */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 1); /* remove nil result */ + } + return 0; +} + + +static int luaB_foreach (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checktype(L, 2, LUA_TFUNCTION); + lua_pushnil(L); /* first key */ + for (;;) { + if (lua_next(L, 1) == 0) + return 0; + lua_pushvalue(L, 2); /* function */ + lua_pushvalue(L, -3); /* key */ + lua_pushvalue(L, -3); /* value */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 2); /* remove value and result */ + } +} + + +static int luaB_getn (lua_State *L) { + lua_pushnumber(L, (lua_Number)aux_getn(L, 1)); + return 1; +} + + +static int luaB_setn (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_setn(L, 1, luaL_checkint(L, 2)); + return 0; +} + + +static int luaB_tinsert (lua_State *L) { + int v = lua_gettop(L); /* number of arguments */ + int n = aux_getn(L, 1) + 1; + int pos; /* where to insert new element */ + if (v == 2) /* called with only 2 arguments */ + pos = n; /* insert new element at the end */ + else { + pos = luaL_checkint(L, 2); /* 2nd argument is the position */ + if (pos > n) n = pos; /* `grow' array if necessary */ + v = 3; /* function may be called with more than 3 args */ + } + luaL_setn(L, 1, n); /* new size */ + while (--n >= pos) { /* move up elements */ + lua_rawgeti(L, 1, n); + lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */ + } + lua_pushvalue(L, v); + lua_rawseti(L, 1, pos); /* t[pos] = v */ + return 0; +} + + +static int luaB_tremove (lua_State *L) { + int n = aux_getn(L, 1); + int pos = luaL_optint(L, 2, n); + if (n <= 0) return 0; /* table is `empty' */ + luaL_setn(L, 1, n-1); /* t.n = n-1 */ + lua_rawgeti(L, 1, pos); /* result = t[pos] */ + for ( ;pos= P */ + while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (i>u) luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* repeat --j until a[j] <= P */ + while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { + if (j