From: Steven Barth Date: Thu, 25 Sep 2008 12:15:32 +0000 (+0000) Subject: Embed luaposix and bitlib into Lua core library X-Git-Tag: reboot~25526 X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=c1ef612776742b585dce6079685b9cf4f12fef01;p=openwrt%2Fstaging%2Fpepe2k.git Embed luaposix and bitlib into Lua core library SVN-Revision: 12696 --- diff --git a/package/lua/Makefile b/package/lua/Makefile index bae83402ba..4523ff14b4 100644 --- a/package/lua/Makefile +++ b/package/lua/Makefile @@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=lua PKG_VERSION:=5.1.4 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=http://www.lua.org/ftp/ \ diff --git a/package/lua/patches/400-luaposix_5.1.4-embedded.patch b/package/lua/patches/400-luaposix_5.1.4-embedded.patch new file mode 100644 index 0000000000..73d8eb03ba --- /dev/null +++ b/package/lua/patches/400-luaposix_5.1.4-embedded.patch @@ -0,0 +1,1458 @@ +Index: lua-5.1.4/src/Makefile +=================================================================== +--- lua-5.1.4.orig/src/Makefile 2008-09-25 12:19:44.000000000 +0200 ++++ lua-5.1.4/src/Makefile 2008-09-25 12:20:03.000000000 +0200 +@@ -12,7 +12,7 @@ + AR= ar rcu + RANLIB= ranlib + RM= rm -f +-LIBS= -lm $(MYLIBS) ++LIBS= -lm -lcrypt $(MYLIBS) + + MYCFLAGS= + MYLDFLAGS= +@@ -29,7 +29,7 @@ + lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \ + lundump.o lvm.o lzio.o lnum.o + LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ +- lstrlib.o loadlib.o linit.o ++ lstrlib.o loadlib.o linit.o lposix.o + + LUA_T= lua + LUA_O= lua.o +Index: lua-5.1.4/src/linit.c +=================================================================== +--- lua-5.1.4.orig/src/linit.c 2008-09-25 12:19:02.000000000 +0200 ++++ lua-5.1.4/src/linit.c 2008-09-25 12:19:32.000000000 +0200 +@@ -23,6 +23,7 @@ + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_DBLIBNAME, luaopen_debug}, ++ {LUA_POSIXLIBNAME, luaopen_posix}, + {NULL, NULL} + }; + +Index: lua-5.1.4/src/lposix.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ lua-5.1.4/src/lposix.c 2008-09-25 12:16:29.000000000 +0200 +@@ -0,0 +1,1139 @@ ++/* ++* lposix.c ++* POSIX library for Lua 5.1. ++* Luiz Henrique de Figueiredo ++* 07 Apr 2006 23:17:49 ++* Clean up and bug fixes by Leo Razoumov 2006-10-11 ++* Based on original by Claudio Terra for Lua 3.x. ++* With contributions by Roberto Ierusalimschy. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MYNAME "posix" ++#define MYVERSION MYNAME " library for " LUA_VERSION " / Jan 2008" ++ ++#ifndef ENABLE_SYSLOG ++#define ENABLE_SYSLOG 1 ++#endif ++ ++#include "lua.h" ++#include "lualib.h" ++#include "lauxlib.h" ++ ++#include "modemuncher.c" ++ ++/* compatibility with Lua 5.0 */ ++#ifndef LUA_VERSION_NUM ++static int luaL_checkoption (lua_State *L, int narg, const char *def, ++ const char *const lst[]) { ++ const char *name = (def) ? luaL_optstring(L, narg, def) : ++ luaL_checkstring(L, narg); ++ int i = luaL_findstring(name, lst); ++ if (i == -1) ++ luaL_argerror(L, narg, lua_pushfstring(L, "invalid option '%s'", name)); ++ return i; ++} ++#define lua_pushinteger lua_pushnumber ++#define lua_createtable(L,a,r) lua_newtable(L) ++#define LUA_FILEHANDLE "FILE*" ++ ++#define lua_setfield(l,i,k) ++#define lua_getfield(l,i,k) ++ ++#endif ++ ++static const struct { char c; mode_t b; } M[] = ++{ ++ {'r', S_IRUSR}, {'w', S_IWUSR}, {'x', S_IXUSR}, ++ {'r', S_IRGRP}, {'w', S_IWGRP}, {'x', S_IXGRP}, ++ {'r', S_IROTH}, {'w', S_IWOTH}, {'x', S_IXOTH}, ++}; ++ ++ ++static void pushmode(lua_State *L, mode_t mode) ++{ ++ char m[9]; ++ int i; ++ for (i=0; i<9; i++) m[i]= (mode & M[i].b) ? M[i].c : '-'; ++ if (mode & S_ISUID) m[2]= (mode & S_IXUSR) ? 's' : 'S'; ++ if (mode & S_ISGID) m[5]= (mode & S_IXGRP) ? 's' : 'S'; ++ lua_pushlstring(L, m, 9); ++} ++ ++typedef void (*Selector)(lua_State *L, int i, const void *data); ++ ++static int doselection(lua_State *L, int i, int n, ++ const char *const S[], ++ Selector F, ++ const void *data) ++{ ++ if (lua_isnone(L, i) || lua_istable(L, i)) ++ { ++ int j; ++ if (lua_isnone(L, i)) lua_createtable(L,0,n); else lua_settop(L, i); ++ for (j=0; S[j]!=NULL; j++) ++ { ++ lua_pushstring(L, S[j]); ++ F(L, j, data); ++ lua_settable(L, -3); ++ } ++ return 1; ++ } ++ else ++ { ++ int k,n=lua_gettop(L); ++ for (k=i; k<=n; k++) ++ { ++ int j=luaL_checkoption(L, k, NULL, S); ++ F(L, j, data); ++ lua_replace(L, k); ++ } ++ return n-i+1; ++ } ++} ++#define doselection(L,i,S,F,d) (doselection)(L,i,sizeof(S)/sizeof(*S)-1,S,F,d) ++ ++static int pusherror(lua_State *L, const char *info) ++{ ++ lua_pushnil(L); ++ if (info==NULL) ++ lua_pushstring(L, strerror(errno)); ++ else ++ lua_pushfstring(L, "%s: %s", info, strerror(errno)); ++ lua_pushinteger(L, errno); ++ return 3; ++} ++ ++static int pushresult(lua_State *L, int i, const char *info) ++{ ++ if (i==-1) return pusherror(L, info); ++ lua_pushinteger(L, i); ++ return 1; ++} ++ ++static void badoption(lua_State *L, int i, const char *what, int option) ++{ ++ luaL_argerror(L, 2, ++ lua_pushfstring(L, "unknown %s option '%c'", what, option)); ++} ++ ++static uid_t mygetuid(lua_State *L, int i) ++{ ++ if (lua_isnone(L, i)) ++ return -1; ++ else if (lua_isnumber(L, i)) ++ return (uid_t) lua_tonumber(L, i); ++ else if (lua_isstring(L, i)) ++ { ++ struct passwd *p=getpwnam(lua_tostring(L, i)); ++ return (p==NULL) ? -1 : p->pw_uid; ++ } ++ else ++ return luaL_typerror(L, i, "string or number"); ++} ++ ++static gid_t mygetgid(lua_State *L, int i) ++{ ++ if (lua_isnone(L, i)) ++ return -1; ++ else if (lua_isnumber(L, i)) ++ return (gid_t) lua_tonumber(L, i); ++ else if (lua_isstring(L, i)) ++ { ++ struct group *g=getgrnam(lua_tostring(L, i)); ++ return (g==NULL) ? -1 : g->gr_gid; ++ } ++ else ++ return luaL_typerror(L, i, "string or number"); ++} ++ ++ ++static int Perrno(lua_State *L) /** errno([n]) */ ++{ ++ int n = luaL_optint(L, 1, errno); ++ lua_pushstring(L, strerror(n)); ++ lua_pushinteger(L, n); ++ return 2; ++} ++ ++ ++static int Pbasename(lua_State *L) /** basename(path) */ ++{ ++ char b[PATH_MAX]; ++ size_t len; ++ const char *path = luaL_checklstring(L, 1, &len); ++ if (len>=sizeof(b)) luaL_argerror(L, 1, "too long"); ++ lua_pushstring(L, basename(strcpy(b,path))); ++ return 1; ++} ++ ++ ++static int Pdirname(lua_State *L) /** dirname(path) */ ++{ ++ char b[PATH_MAX]; ++ size_t len; ++ const char *path = luaL_checklstring(L, 1, &len); ++ if (len>=sizeof(b)) luaL_argerror(L, 1, "too long"); ++ lua_pushstring(L, dirname(strcpy(b,path))); ++ return 1; ++} ++ ++ ++static int Pdir(lua_State *L) /** dir([path]) */ ++{ ++ const char *path = luaL_optstring(L, 1, "."); ++ DIR *d = opendir(path); ++ if (d == NULL) ++ return pusherror(L, path); ++ else ++ { ++ int i; ++ struct dirent *entry; ++ lua_newtable(L); ++ for (i=1; (entry = readdir(d)) != NULL; i++) ++ { ++ lua_pushstring(L, entry->d_name); ++ lua_rawseti(L, -2, i); ++ } ++ closedir(d); ++ lua_pushinteger(L, i-1); ++ return 2; ++ } ++} ++ ++static int Pglob(lua_State *L) /** glob(pattern) */ ++{ ++ const char *pattern = luaL_optstring(L, 1, "*"); ++ glob_t globres; ++ ++ if (glob(pattern, 0, NULL, &globres)) ++ return pusherror(L, pattern); ++ else ++ { ++ int i; ++ lua_newtable(L); ++ for (i=1; i<=globres.gl_pathc; i++) { ++ lua_pushstring(L, globres.gl_pathv[i-1]); ++ lua_rawseti(L, -2, i); ++ } ++ globfree(&globres); ++ return 1; ++ } ++} ++ ++static int aux_files(lua_State *L) ++{ ++ DIR **p = (DIR **)lua_touserdata(L, lua_upvalueindex(1)); ++ DIR *d = *p; ++ struct dirent *entry; ++ if (d == NULL) return 0; ++ entry = readdir(d); ++ if (entry == NULL) ++ { ++ closedir(d); ++ *p=NULL; ++ return 0; ++ } ++ else ++ { ++ lua_pushstring(L, entry->d_name); ++ return 1; ++ } ++} ++ ++static int dir_gc (lua_State *L) ++{ ++ DIR *d = *(DIR **)lua_touserdata(L, 1); ++ if (d!=NULL) closedir(d); ++ return 0; ++} ++ ++static int Pfiles(lua_State *L) /** files([path]) */ ++{ ++ const char *path = luaL_optstring(L, 1, "."); ++ DIR **d = (DIR **)lua_newuserdata(L, sizeof(DIR *)); ++ if (luaL_newmetatable(L, MYNAME " dir handle")) ++ { ++ lua_pushliteral(L, "__gc"); ++ lua_pushcfunction(L, dir_gc); ++ lua_settable(L, -3); ++ } ++ lua_setmetatable(L, -2); ++ *d = opendir(path); ++ if (*d == NULL) return pusherror(L, path); ++ lua_pushcclosure(L, aux_files, 1); ++ return 1; ++} ++ ++ ++static int Pgetcwd(lua_State *L) /** getcwd() */ ++{ ++ char b[PATH_MAX]; ++ if (getcwd(b, sizeof(b)) == NULL) return pusherror(L, "."); ++ lua_pushstring(L, b); ++ return 1; ++} ++ ++ ++static int Pmkdir(lua_State *L) /** mkdir(path) */ ++{ ++ const char *path = luaL_checkstring(L, 1); ++ return pushresult(L, mkdir(path, 0777), path); ++} ++ ++ ++static int Pchdir(lua_State *L) /** chdir(path) */ ++{ ++ const char *path = luaL_checkstring(L, 1); ++ return pushresult(L, chdir(path), path); ++} ++ ++static int Prmdir(lua_State *L) /** rmdir(path) */ ++{ ++ const char *path = luaL_checkstring(L, 1); ++ return pushresult(L, rmdir(path), path); ++} ++ ++ ++static int Punlink(lua_State *L) /** unlink(path) */ ++{ ++ const char *path = luaL_checkstring(L, 1); ++ return pushresult(L, unlink(path), path); ++} ++ ++static int Plink(lua_State *L) /** link(old,new,[symbolic]) */ ++{ ++ const char *oldpath = luaL_checkstring(L, 1); ++ const char *newpath = luaL_checkstring(L, 2); ++ return pushresult(L, ++ (lua_toboolean(L,3) ? symlink : link)(oldpath, newpath), NULL); ++} ++ ++ ++static int Preadlink(lua_State *L) /** readlink(path) */ ++{ ++ char b[PATH_MAX]; ++ const char *path = luaL_checkstring(L, 1); ++ int n = readlink(path, b, sizeof(b)); ++ if (n==-1) return pusherror(L, path); ++ lua_pushlstring(L, b, n); ++ return 1; ++} ++ ++ ++static int Paccess(lua_State *L) /** access(path,[mode]) */ ++{ ++ int mode=F_OK; ++ const char *path=luaL_checkstring(L, 1); ++ const char *s; ++ for (s=luaL_optstring(L, 2, "f"); *s!=0 ; s++) ++ switch (*s) ++ { ++ case ' ': break; ++ case 'r': mode |= R_OK; break; ++ case 'w': mode |= W_OK; break; ++ case 'x': mode |= X_OK; break; ++ case 'f': mode |= F_OK; break; ++ default: badoption(L, 2, "mode", *s); break; ++ } ++ return pushresult(L, access(path, mode), path); ++} ++ ++ ++static int myfclose (lua_State *L) { ++ FILE **p = (FILE **)lua_touserdata(L, 1); ++ int rc = fclose(*p); ++ if (rc == 0) *p = NULL; ++ return pushresult(L, rc, NULL); ++} ++ ++static int pushfile (lua_State *L, int id, const char *mode) { ++ FILE **f = (FILE **)lua_newuserdata(L, sizeof(FILE *)); ++ *f = NULL; ++ luaL_getmetatable(L, LUA_FILEHANDLE); ++ lua_setmetatable(L, -2); ++ lua_getfield(L, LUA_REGISTRYINDEX, "POSIX_PIPEFILE"); ++ if (lua_isnil(L, -1)) { ++ lua_pop(L, 1); ++ lua_newtable(L); ++ lua_pushvalue(L, -1); ++ lua_pushcfunction(L, myfclose); ++ lua_setfield(L, -2, "__close"); ++ lua_setfield(L, LUA_REGISTRYINDEX, "POSIX_PIPEFILE"); ++ } ++ lua_setfenv(L, -2); ++ *f = fdopen(id, mode); ++ return (*f != NULL); ++} ++ ++static int Ppipe(lua_State *L) /** pipe() */ ++{ ++ int fd[2]; ++ if (pipe(fd)==-1) return pusherror(L, NULL); ++ if (!pushfile(L, fd[0], "r") || !pushfile(L, fd[1], "w")) ++ return pusherror(L, "pipe"); ++ return 2; ++} ++ ++ ++static int Pfileno(lua_State *L) /** fileno(filehandle) */ ++{ ++ FILE *f = *(FILE**) luaL_checkudata(L, 1, LUA_FILEHANDLE); ++ return pushresult(L, fileno(f), NULL); ++} ++ ++ ++static int Pfdopen(lua_State *L) /** fdopen(fd, mode) */ ++{ ++ int fd = luaL_checkint(L, 1); ++ const char *mode = luaL_checkstring(L, 2); ++ if (!pushfile(L, fd, mode)) ++ return pusherror(L, "fdpoen"); ++ return 1; ++} ++ ++ ++/* helper func for Pdup */ ++static const char *filemode(int fd) ++{ ++ const char *m; ++ int mode = fcntl(fd, F_GETFL); ++ if (mode < 0) ++ return NULL; ++ switch (mode & O_ACCMODE) { ++ case O_RDONLY: m = "r"; break; ++ case O_WRONLY: m = "w"; break; ++ default: m = "rw"; break; ++ } ++ return m; ++} ++ ++static int Pdup(lua_State *L) /** dup(old,[new]) */ ++{ ++ FILE **oldf = (FILE**)luaL_checkudata(L, 1, LUA_FILEHANDLE); ++ FILE **newf = (FILE **)lua_touserdata(L, 2); ++ int fd; ++ const char *msg = "dup2"; ++ fflush(*newf); ++ if (newf == NULL) { ++ fd = dup(fileno(*oldf)); ++ msg = "dup"; ++ } else { ++ fflush(*newf); ++ fd = dup2(fileno(*oldf), fileno(*newf)); ++ } ++ ++ if ((fd < 0) || !pushfile(L, fd, filemode(fd))) ++ return pusherror(L, msg); ++ return 1; ++} ++ ++ ++static int Pmkfifo(lua_State *L) /** mkfifo(path) */ ++{ ++ const char *path = luaL_checkstring(L, 1); ++ return pushresult(L, mkfifo(path, 0777), path); ++} ++ ++ ++static int runexec(lua_State *L, int use_shell) ++{ ++ const char *path = luaL_checkstring(L, 1); ++ int i,n=lua_gettop(L); ++ char **argv = lua_newuserdata(L,(n+1)*sizeof(char*)); ++ argv[0] = (char*)path; ++ for (i=1; i POSIX constant lookup tables */ ++struct modeLookup ++{ ++ char rwx; ++ mode_t bits; ++}; ++ ++typedef struct modeLookup modeLookup; ++ ++static modeLookup modesel[] = ++{ ++ /* RWX char Posix Constant */ ++ {'r', S_IRUSR}, ++ {'w', S_IWUSR}, ++ {'x', S_IXUSR}, ++ ++ {'r', S_IRGRP}, ++ {'w', S_IWGRP}, ++ {'x', S_IXGRP}, ++ ++ {'r', S_IROTH}, ++ {'w', S_IWOTH}, ++ {'x', S_IXOTH}, ++ {0, (mode_t)-1} /* do not delete this line */ ++}; ++ ++ ++ ++static int rwxrwxrwx(mode_t *mode, const char *p) ++{ ++ int count; ++ mode_t tmp_mode = *mode; ++ ++ tmp_mode &= ~(S_ISUID | S_ISGID); /* turn off suid and sgid flags */ ++ for (count=0; count<9; count ++) ++ { ++ if (*p == modesel[count].rwx) tmp_mode |= modesel[count].bits; /* set a bit */ ++ else if (*p == '-') tmp_mode &= ~modesel[count].bits; /* clear a bit */ ++ else if (*p=='s') switch(count) ++ { ++ case 2: /* turn on suid flag */ ++ tmp_mode |= S_ISUID | S_IXUSR; ++ break; ++ ++ case 5: /* turn on sgid flag */ ++ tmp_mode |= S_ISGID | S_IXGRP; ++ break; ++ ++ default: ++ return -4; /* failed! -- bad rwxrwxrwx mode change */ ++ break; ++ } ++ p++; ++ } ++ *mode = tmp_mode; ++ return 0; ++} ++ ++static void modechopper(mode_t mode, char *p) ++{ ++ /* requires char p[10] */ ++ int count; ++ char *pp; ++ ++ pp=p; ++ ++ for (count=0; count<9; count ++) ++ { ++ if (mode & modesel[count].bits) *p = modesel[count].rwx; ++ else *p='-'; ++ ++ p++; ++ } ++ *p=0; /* to finish the string */ ++ ++ /* dealing with suid and sgid flags */ ++ if (mode & S_ISUID) pp[2] = (mode & S_IXUSR) ? 's' : 'S'; ++ if (mode & S_ISGID) pp[5] = (mode & S_IXGRP) ? 's' : 'S'; ++ ++} ++ ++static int mode_munch(mode_t *mode, const char* p) ++{ ++ ++ char op=0; ++ mode_t affected_bits, ch_mode; ++ int doneFlag = 0; ++#ifdef DEBUG ++char tmp[10]; ++#endif ++ ++#ifdef DEBUG ++modechopper(*mode, tmp); ++printf("modemuncher: got base mode = %s\n", tmp); ++#endif ++ ++ while (!doneFlag) ++ { ++ /* step 0 -- clear temporary variables */ ++ affected_bits=0; ++ ch_mode=0; ++ ++ /* step 1 -- who's affected? */ ++ ++#ifdef DEBUG ++printf("modemuncher step 1\n"); ++#endif ++ ++ /* mode string given in rwxrwxrwx format */ ++ if (*p== 'r' || *p == '-') return rwxrwxrwx(mode, p); ++ ++ /* mode string given in ugoa+-=rwx format */ ++ for ( ; ; p++) ++ switch (*p) ++ { ++ case 'u': ++ affected_bits |= 04700; ++ break; ++ ++ case 'g': ++ affected_bits |= 02070; ++ break; ++ ++ case 'o': ++ affected_bits |= 01007; ++ break; ++ ++ case 'a': ++ affected_bits |= 07777; ++ break; ++ ++ /* ignore spaces */ ++ case ' ': ++ break; ++ ++ ++ default: ++ goto no_more_affected; ++ } ++ ++ no_more_affected: ++ /* If none specified, affect all bits. */ ++ if (affected_bits == 0) affected_bits = 07777; ++ ++ /* step 2 -- how is it changed? */ ++ ++#ifdef DEBUG ++printf("modemuncher step 2 (*p='%c')\n", *p); ++#endif ++ ++ switch (*p) ++ { ++ case '+': ++ case '-': ++ case '=': ++ op = *p; ++ break; ++ ++ /* ignore spaces */ ++ case ' ': ++ break; ++ ++ default: ++ return -1; /* failed! -- bad operator */ ++ } ++ ++ ++ /* step 3 -- what are the changes? */ ++ ++#ifdef DEBUG ++printf("modemuncher step 3\n"); ++#endif ++ ++ for (p++ ; *p!=0 ; p++) ++ switch (*p) ++ { ++ case 'r': ++ ch_mode |= 00444; ++ break; ++ ++ case 'w': ++ ch_mode |= 00222; ++ break; ++ ++ case 'x': ++ ch_mode |= 00111; ++ break; ++ ++ case 's': ++ /* Set the setuid/gid bits if `u' or `g' is selected. */ ++ ch_mode |= 06000; ++ break; ++ ++ /* ignore spaces */ ++ case ' ': ++ break; ++ ++ default: ++ goto specs_done; ++ } ++ ++ specs_done: ++ /* step 4 -- apply the changes */ ++ ++#ifdef DEBUG ++ printf("modemuncher step 4\n"); ++#endif ++ if (*p != ',') doneFlag = 1; ++ if (*p != 0 && *p != ' ' && *p != ',') ++ { ++ ++#ifdef DEBUG ++printf("modemuncher: comma error!\n"); ++printf("modemuncher: doneflag = %u\n", doneFlag); ++#endif ++ return -2; /* failed! -- bad mode change */ ++ ++ } ++ p++; ++ /*if (!ch_mode) return -2;*/ /* failed! -- bad mode change */ ++ if (ch_mode) switch (op) ++ { ++ case '+': ++ *mode = *mode |= ch_mode & affected_bits; ++ break; ++ ++ case '-': ++ *mode = *mode &= ~(ch_mode & affected_bits); ++ break; ++ ++ case '=': ++ *mode = ch_mode & affected_bits; ++ break; ++ ++ default: ++ return -3; /* failed! -- unknown error */ ++ } ++ } ++#ifdef DEBUG ++modechopper(*mode, tmp); ++printf("modemuncher: returning mode = %s\n", tmp); ++#endif ++ ++ return 0; /* successful call */ ++} ++ ++ diff --git a/package/lua/patches/410-bitlib_25-embedded.patch b/package/lua/patches/410-bitlib_25-embedded.patch new file mode 100644 index 0000000000..91de0647f5 --- /dev/null +++ b/package/lua/patches/410-bitlib_25-embedded.patch @@ -0,0 +1,186 @@ +Index: lua-5.1.4/src/Makefile +=================================================================== +--- lua-5.1.4.orig/src/Makefile 2008-09-25 13:08:31.000000000 +0200 ++++ lua-5.1.4/src/Makefile 2008-09-25 13:08:43.000000000 +0200 +@@ -29,7 +29,7 @@ + lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \ + lundump.o lvm.o lzio.o lnum.o + LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ +- lstrlib.o loadlib.o linit.o lposix.o ++ lstrlib.o loadlib.o linit.o lposix.o lbitlib.o + + LUA_T= lua + LUA_O= lua.o +Index: lua-5.1.4/src/bit_limits.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ lua-5.1.4/src/bit_limits.h 2008-09-25 13:09:16.000000000 +0200 +@@ -0,0 +1,4 @@ ++#define BITLIB_FLOAT_BITS 53 ++#define BITLIB_FLOAT_MAX 0xfffffffffffffL ++#define BITLIB_FLOAT_MIN (-0x10000000000000L) ++#define BITLIB_FLOAT_UMAX 0x1fffffffffffffUL +Index: lua-5.1.4/src/lbitlib.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ lua-5.1.4/src/lbitlib.c 2008-09-25 13:05:15.000000000 +0200 +@@ -0,0 +1,133 @@ ++/* Bitwise operations library */ ++/* (c) Reuben Thomas 2000-2008 */ ++/* See README for license */ ++ ++#include "lua.h" ++#include "lauxlib.h" ++#include "limits.h" ++ ++#include "bit_limits.h" ++ ++ ++/* FIXME: Assume lua_Integer is int */ ++#define LUA_INTEGER_MAX INT_MAX ++#define LUA_INTEGER_MIN INT_MIN ++ ++/* FIXME: Assume uint is an unsigned lua_Integer */ ++typedef unsigned int lua_UInteger; ++#define LUA_UINTEGER_MAX UINT_MAX ++ ++ ++/* Bit type size and limits */ ++ ++#define BIT_BITS \ ++ (CHAR_BIT * sizeof(lua_Integer) > BITLIB_FLOAT_BITS ? \ ++ BITLIB_FLOAT_BITS : (CHAR_BIT * sizeof(lua_Integer))) ++ ++/* This code may give warnings if BITLIB_FLOAT_* are too big to fit in ++ long, but that doesn't matter since in that case they won't be ++ used. */ ++#define BIT_MAX \ ++ (CHAR_BIT * sizeof(lua_Integer) > BITLIB_FLOAT_BITS ? BITLIB_FLOAT_MAX : LUA_INTEGER_MAX) ++ ++#define BIT_MIN \ ++ (CHAR_BIT * sizeof(lua_Integer) > BITLIB_FLOAT_BITS ? BITLIB_FLOAT_MIN : LUA_INTEGER_MIN) ++ ++#define BIT_UMAX \ ++ (CHAR_BIT * sizeof(lua_Integer) > BITLIB_FLOAT_BITS ? BITLIB_FLOAT_UMAX : LUA_UINTEGER_MAX) ++ ++ ++/* Define TOBIT to get a bit value */ ++#ifdef BUILTIN_CAST ++#define ++#define TOBIT(L, n, res) \ ++ ((void)(res), luaL_checkinteger((L), (n))) ++#else ++#include ++#include ++ ++/* FIXME: Assume lua_Number fits in a double (use of fmod). */ ++#define TOBIT(L, n, res) \ ++ ((lua_Integer)(((res) = fmod(luaL_checknumber(L, (n)), (double)BIT_UMAX + 1.0)), \ ++ (res) > BIT_MAX ? ((res) -= (double)BIT_UMAX, (res) -= 1) : \ ++ ((res) < BIT_MIN ? ((res) += (double)BIT_UMAX, (res) += 1) : (res)))) ++#endif ++ ++ ++#define BIT_TRUNCATE(i) \ ++ ((i) & BIT_UMAX) ++ ++ ++/* Operations ++ ++ The macros MONADIC and VARIADIC only deal with bitwise operations. ++ ++ LOGICAL_SHIFT truncates its left-hand operand before shifting so ++ that any extra bits at the most-significant end are not shifted ++ into the result. ++ ++ ARITHMETIC_SHIFT does not truncate its left-hand operand, so that ++ the sign bits are not removed and right shift work properly. ++ */ ++ ++#define MONADIC(name, op) \ ++ static int bit_ ## name(lua_State *L) { \ ++ lua_Number f; \ ++ lua_pushinteger(L, BIT_TRUNCATE(op TOBIT(L, 1, f))); \ ++ return 1; \ ++ } ++ ++#define VARIADIC(name, op) \ ++ static int bit_ ## name(lua_State *L) { \ ++ lua_Number f; \ ++ int n = lua_gettop(L), i; \ ++ lua_Integer w = TOBIT(L, 1, f); \ ++ for (i = 2; i <= n; i++) \ ++ w op TOBIT(L, i, f); \ ++ lua_pushinteger(L, BIT_TRUNCATE(w)); \ ++ return 1; \ ++ } ++ ++#define LOGICAL_SHIFT(name, op) \ ++ static int bit_ ## name(lua_State *L) { \ ++ lua_Number f; \ ++ lua_pushinteger(L, BIT_TRUNCATE(BIT_TRUNCATE((lua_UInteger)TOBIT(L, 1, f)) op \ ++ (unsigned)luaL_checknumber(L, 2))); \ ++ return 1; \ ++ } ++ ++#define ARITHMETIC_SHIFT(name, op) \ ++ static int bit_ ## name(lua_State *L) { \ ++ lua_Number f; \ ++ lua_pushinteger(L, BIT_TRUNCATE((lua_Integer)TOBIT(L, 1, f) op \ ++ (unsigned)luaL_checknumber(L, 2))); \ ++ return 1; \ ++ } ++ ++MONADIC(cast, +) ++MONADIC(bnot, ~) ++VARIADIC(band, &=) ++VARIADIC(bor, |=) ++VARIADIC(bxor, ^=) ++ARITHMETIC_SHIFT(lshift, <<) ++LOGICAL_SHIFT(rshift, >>) ++ARITHMETIC_SHIFT(arshift, >>) ++ ++static const struct luaL_reg bitlib[] = { ++ {"cast", bit_cast}, ++ {"bnot", bit_bnot}, ++ {"band", bit_band}, ++ {"bor", bit_bor}, ++ {"bxor", bit_bxor}, ++ {"lshift", bit_lshift}, ++ {"rshift", bit_rshift}, ++ {"arshift", bit_arshift}, ++ {NULL, NULL} ++}; ++ ++LUALIB_API int luaopen_bit (lua_State *L) { ++ luaL_register(L, "bit", bitlib); ++ lua_pushnumber(L, BIT_BITS); ++ lua_setfield(L, -2, "bits"); ++ return 1; ++} +Index: lua-5.1.4/src/linit.c +=================================================================== +--- lua-5.1.4.orig/src/linit.c 2008-09-25 13:08:11.000000000 +0200 ++++ lua-5.1.4/src/linit.c 2008-09-25 13:08:27.000000000 +0200 +@@ -24,6 +24,7 @@ + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_DBLIBNAME, luaopen_debug}, + {LUA_POSIXLIBNAME, luaopen_posix}, ++ {LUA_BITLIBNAME, luaopen_bit}, + {NULL, NULL} + }; + +Index: lua-5.1.4/src/lualib.h +=================================================================== +--- lua-5.1.4.orig/src/lualib.h 2008-09-25 13:07:29.000000000 +0200 ++++ lua-5.1.4/src/lualib.h 2008-09-25 13:08:06.000000000 +0200 +@@ -42,6 +42,9 @@ + #define LUA_POSIXLIBNAME "posix" + LUALIB_API int (luaopen_posix) (lua_State *L); + ++#define LUA_BITLIBNAME "bit" ++LUALIB_API int (luaopen_bit) (lua_State *L); ++ + + /* open all previous libraries */ + LUALIB_API void (luaL_openlibs) (lua_State *L);