Embed luaposix and bitlib into Lua core library
authorSteven Barth <cyrus@openwrt.org>
Thu, 25 Sep 2008 12:15:32 +0000 (12:15 +0000)
committerSteven Barth <cyrus@openwrt.org>
Thu, 25 Sep 2008 12:15:32 +0000 (12:15 +0000)
SVN-Revision: 12696

package/lua/Makefile
package/lua/patches/400-luaposix_5.1.4-embedded.patch [new file with mode: 0644]
package/lua/patches/410-bitlib_25-embedded.patch [new file with mode: 0644]

index bae83402baae2bde4a9c6b81715531c65410dd58..4523ff14b4fef7393badc9ef1a94acb314ce3d8f 100644 (file)
@@ -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 (file)
index 0000000..73d8eb0
--- /dev/null
@@ -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 <lhf@tecgraf.puc-rio.br>
++* 07 Apr 2006 23:17:49
++* Clean up and bug fixes by Leo Razoumov <slonik.az@gmail.com> 2006-10-11 <!LR> 
++* Based on original by Claudio Terra for Lua 3.x.
++* With contributions by Roberto Ierusalimschy.
++*/
++
++#include <sys/stat.h>
++#include <sys/times.h>
++#include <sys/types.h>
++#include <sys/utsname.h>
++#include <sys/wait.h>
++
++#include <dirent.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <glob.h>
++#include <grp.h>
++#include <libgen.h>
++#include <limits.h>
++#include <poll.h>
++#include <pwd.h>
++#include <signal.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <syslog.h>
++#include <time.h>
++#include <unistd.h>
++#include <utime.h>
++
++#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<n; i++) argv[i] = (char*)luaL_checkstring(L, i+1);
++      argv[n] = NULL;
++      if (use_shell) {
++              execvp(path, argv);
++      } else {
++              execv(path, argv);
++      }
++      return pusherror(L, path);
++}
++
++
++static int Pexec(lua_State *L)                        /** exec(path,[args]) */
++{
++      return runexec(L, 0);
++}
++
++
++static int Pexecp(lua_State *L)                       /** execp(path,[args]) */
++{
++      return runexec(L, 1);
++}
++
++
++static int Pfork(lua_State *L)                        /** fork() */
++{
++      return pushresult(L, fork(), NULL);
++}
++
++/* from http://lua-users.org/lists/lua-l/2007-11/msg00346.html */
++static int Ppoll(lua_State *L)   /** poll(filehandle, timeout) */
++{
++      struct pollfd fds;
++      FILE* file = *(FILE**)luaL_checkudata(L,1,LUA_FILEHANDLE);
++      int timeout = luaL_checkint(L,2);
++      fds.fd = fileno(file);
++      fds.events = POLLIN;
++      return pushresult(L, poll(&fds,1,timeout), NULL);
++}
++
++static int Pwait(lua_State *L)                        /** wait([pid]) */
++{
++      int status;
++      pid_t pid = luaL_optint(L, 1, -1);
++      pid = waitpid(pid, &status, 0);
++      if (pid == -1) return pusherror(L, NULL);
++      lua_pushinteger(L, pid);
++      if (WIFEXITED(status))
++      {
++              lua_pushliteral(L,"exited");
++              lua_pushinteger(L, WEXITSTATUS(status));
++              return 3;
++      }
++      else if (WIFSIGNALED(status))
++      {
++              lua_pushliteral(L,"killed");
++              lua_pushinteger(L, WTERMSIG(status));
++              return 3;
++      }
++      else if (WIFSTOPPED(status))
++      {
++              lua_pushliteral(L,"stopped");
++              lua_pushinteger(L, WSTOPSIG(status));
++              return 3;
++      }
++      return 1;
++}
++
++
++static int Pkill(lua_State *L)                        /** kill(pid,[sig]) */
++{
++      pid_t pid = luaL_checkint(L, 1);
++      int sig = luaL_optint(L, 2, SIGTERM);
++      return pushresult(L, kill(pid, sig), NULL);
++}
++
++static int Psetpid(lua_State *L)              /** setpid(option,...) */
++{
++      const char *what=luaL_checkstring(L, 1);
++      switch (*what)
++      {
++              case 'U':
++                      return pushresult(L, seteuid(mygetuid(L, 2)), NULL);
++              case 'u':
++                      return pushresult(L, setuid(mygetuid(L, 2)), NULL);
++              case 'G':
++                      return pushresult(L, setegid(mygetgid(L, 2)), NULL);
++              case 'g':
++                      return pushresult(L, setgid(mygetgid(L, 2)), NULL);
++              case 's':
++                      return pushresult(L, setsid(), NULL);
++              case 'p':
++              {
++                      pid_t pid  = luaL_checkint(L, 2);
++                      pid_t pgid = luaL_checkint(L, 3);
++                      return pushresult(L, setpgid(pid,pgid), NULL);
++              }
++              default:
++                      badoption(L, 2, "id", *what);
++                      return 0;
++      }
++}
++
++
++static int Psleep(lua_State *L)                       /** sleep(seconds) */
++{
++      unsigned int seconds = luaL_checkint(L, 1);
++      lua_pushinteger(L, sleep(seconds));
++      return 1;
++}
++
++
++static int Psetenv(lua_State *L)              /** setenv(name,value,[over]) */
++{
++      const char *name=luaL_checkstring(L, 1);
++      const char *value=luaL_optstring(L, 2, NULL);
++      if (value==NULL)
++      {
++      unsetenv(name);
++              return pushresult(L, 0, NULL);
++      }
++      else
++      {
++              int overwrite=lua_isnoneornil(L, 3) || lua_toboolean(L, 3);
++              return pushresult(L, setenv(name,value,overwrite), NULL);
++      }
++}
++
++
++static int Pgetenv(lua_State *L)              /** getenv([name]) */
++{
++      if (lua_isnone(L, 1))
++      {
++              extern char **environ;
++              char **e;
++              lua_newtable(L);
++              for (e=environ; *e!=NULL; e++)
++              {
++                      char *s=*e;
++                      char *eq=strchr(s, '=');
++                      if (eq==NULL)           /* will this ever happen? */
++                      {
++                              lua_pushstring(L,s);
++                              lua_pushboolean(L,1);
++                      }
++                      else
++                      {
++                              lua_pushlstring(L,s,eq-s);
++                              lua_pushstring(L,eq+1);
++                      }
++                      lua_settable(L,-3);
++              }
++      }
++      else
++              lua_pushstring(L, getenv(luaL_checkstring(L, 1)));
++      return 1;
++}
++
++static int Pumask(lua_State *L)                       /** umask([mode]) */
++{/* <!LR> from old lposix-5.0 version */
++      char m[10];
++      mode_t mode;
++      umask(mode=umask(0));
++      mode=(~mode)&0777;
++      if (!lua_isnone(L, 1))
++      {
++              if (mode_munch(&mode, luaL_checkstring(L, 1)))
++              {
++                      lua_pushnil(L);
++                      return 1;
++              }
++              mode&=0777;
++              umask(~mode);
++      }
++      modechopper(mode, m);
++      lua_pushstring(L, m);
++      return 1;
++}
++
++
++static int Pchmod(lua_State *L)                       /** chmod(path,mode) */
++{
++      mode_t mode;
++      struct stat s;
++      const char *path = luaL_checkstring(L, 1);
++      const char *modestr = luaL_checkstring(L, 2);
++      if (stat(path, &s)) return pusherror(L, path);
++      mode = s.st_mode;
++      if (mode_munch(&mode, modestr)) luaL_argerror(L, 2, "bad mode");
++      return pushresult(L, chmod(path, mode), path);
++}
++
++
++static int Pchown(lua_State *L)                       /** chown(path,uid,gid) */
++{
++      const char *path = luaL_checkstring(L, 1);
++      uid_t uid = mygetuid(L, 2);
++      gid_t gid = mygetgid(L, 3);
++      return pushresult(L, chown(path, uid, gid), path);
++}
++
++
++static int Putime(lua_State *L)                       /** utime(path,[mtime,atime]) */
++{
++      struct utimbuf times;
++      time_t currtime = time(NULL);
++      const char *path = luaL_checkstring(L, 1);
++      times.modtime = luaL_optnumber(L, 2, currtime);
++      times.actime  = luaL_optnumber(L, 3, currtime);
++      return pushresult(L, utime(path, &times), path);
++}
++
++
++static void FgetID(lua_State *L, int i, const void *data)
++{
++      switch (i)
++      {
++              case 0: lua_pushinteger(L, getegid());  break;
++              case 1: lua_pushinteger(L, geteuid());  break;
++              case 2: lua_pushinteger(L, getgid());   break;
++              case 3: lua_pushinteger(L, getuid());   break;
++              case 4: lua_pushinteger(L, getpgrp());  break;
++              case 5: lua_pushinteger(L, getpid());   break;
++              case 6: lua_pushinteger(L, getppid());  break;
++      }
++}
++
++static const char *const SgetID[] =
++{
++      "egid", "euid", "gid", "uid", "pgrp", "pid", "ppid", NULL
++};
++
++static int Pgetpid(lua_State *L)              /** getpid([options]) */
++{
++      return doselection(L, 1, SgetID, FgetID, NULL);
++}
++
++
++static int Phostid(lua_State *L)              /** hostid() */
++{
++      char b[32];
++      sprintf(b,"%ld",gethostid());
++      lua_pushstring(L, b);
++      return 1;
++}
++
++
++static int Pttyname(lua_State *L)             /** ttyname([fd]) */
++{
++      int fd=luaL_optint(L, 1, 0);
++      lua_pushstring(L, ttyname(fd));
++      return 1;
++}
++
++
++static int Pctermid(lua_State *L)             /** ctermid() */
++{
++      char b[L_ctermid];
++      lua_pushstring(L, ctermid(b));
++      return 1;
++}
++
++
++static int Pgetlogin(lua_State *L)            /** getlogin() */
++{
++      lua_pushstring(L, getlogin());
++      return 1;
++}
++
++
++static void Fgetpasswd(lua_State *L, int i, const void *data)
++{
++      const struct passwd *p=data;
++      switch (i)
++      {
++              case 0: lua_pushstring(L, p->pw_name); break;
++              case 1: lua_pushinteger(L, p->pw_uid); break;
++              case 2: lua_pushinteger(L, p->pw_gid); break;
++              case 3: lua_pushstring(L, p->pw_dir); break;
++              case 4: lua_pushstring(L, p->pw_shell); break;
++/* not strictly POSIX */
++              case 5: lua_pushstring(L, p->pw_gecos); break;
++              case 6: lua_pushstring(L, p->pw_passwd); break;
++      }
++}
++
++static const char *const Sgetpasswd[] =
++{
++      "name", "uid", "gid", "dir", "shell", "gecos", "passwd", NULL
++};
++
++
++static int Pgetpasswd(lua_State *L)           /** getpasswd(name|id,[sel]) */
++{
++      struct passwd *p=NULL;
++      if (lua_isnoneornil(L, 1))
++              p = getpwuid(geteuid());
++      else if (lua_isnumber(L, 1))
++              p = getpwuid((uid_t)lua_tonumber(L, 1));
++      else if (lua_isstring(L, 1))
++              p = getpwnam(lua_tostring(L, 1));
++      else
++              luaL_typerror(L, 1, "string or number");
++      if (p==NULL)
++              lua_pushnil(L);
++      else
++              return doselection(L, 2, Sgetpasswd, Fgetpasswd, p);
++      return 1;
++}
++
++
++static int Pgetgroup(lua_State *L)            /** getgroup(name|id) */
++{
++      struct group *g=NULL;
++      if (lua_isnumber(L, 1))
++              g = getgrgid((gid_t)lua_tonumber(L, 1));
++      else if (lua_isstring(L, 1))
++              g = getgrnam(lua_tostring(L, 1));
++      else
++              luaL_typerror(L, 1, "string or number");
++      if (g==NULL)
++              lua_pushnil(L);
++      else
++      {
++              int i;
++              lua_newtable(L);
++              lua_pushliteral(L, "name");
++              lua_pushstring(L, g->gr_name);
++              lua_settable(L, -3);
++              lua_pushliteral(L, "gid");
++              lua_pushinteger(L, g->gr_gid);
++              lua_settable(L, -3);
++              for (i=0; g->gr_mem[i]!=NULL; i++)
++              {
++                      lua_pushstring(L, g->gr_mem[i]);
++                      lua_rawseti(L, -2, i);
++              }
++      }
++      return 1;
++}
++
++
++struct mytimes
++{
++ struct tms t;
++ clock_t elapsed;
++};
++
++/* #define pushtime(L,x)      lua_pushnumber(L,((lua_Number)x)/CLOCKS_PER_SEC) */
++#define pushtime(L,x) lua_pushnumber(L, ((lua_Number)x)/clk_tck)
++
++static void Ftimes(lua_State *L, int i, const void *data)
++{
++    static long clk_tck = 0; 
++      const struct mytimes *t=data;
++
++    if( !clk_tck){ clk_tck= sysconf(_SC_CLK_TCK);}
++      switch (i)
++      {
++              case 0: pushtime(L, t->t.tms_utime); break;
++              case 1: pushtime(L, t->t.tms_stime); break;
++              case 2: pushtime(L, t->t.tms_cutime); break;
++              case 3: pushtime(L, t->t.tms_cstime); break;
++              case 4: pushtime(L, t->elapsed); break;
++      }
++}
++
++static const char *const Stimes[] =
++{
++      "utime", "stime", "cutime", "cstime", "elapsed", NULL
++};
++
++static int Ptimes(lua_State *L)                       /** times([options]) */
++{
++      struct mytimes t;
++      t.elapsed = times(&t.t);
++      return doselection(L, 1, Stimes, Ftimes, &t);
++}
++
++
++static const char *filetype(mode_t m)
++{
++      if (S_ISREG(m))         return "regular";
++      else if (S_ISLNK(m))    return "link";
++      else if (S_ISDIR(m))    return "directory";
++      else if (S_ISCHR(m))    return "character device";
++      else if (S_ISBLK(m))    return "block device";
++      else if (S_ISFIFO(m))   return "fifo";
++      else if (S_ISSOCK(m))   return "socket";
++      else                    return "?";
++}
++
++static void Fstat(lua_State *L, int i, const void *data)
++{
++      const struct stat *s=data;
++      switch (i)
++      {
++              case 0: pushmode(L, s->st_mode); break;
++              case 1: lua_pushinteger(L, s->st_ino); break;
++              case 2: lua_pushinteger(L, s->st_dev); break;
++              case 3: lua_pushinteger(L, s->st_nlink); break;
++              case 4: lua_pushinteger(L, s->st_uid); break;
++              case 5: lua_pushinteger(L, s->st_gid); break;
++              case 6: lua_pushinteger(L, s->st_size); break;
++              case 7: lua_pushinteger(L, s->st_atime); break;
++              case 8: lua_pushinteger(L, s->st_mtime); break;
++              case 9: lua_pushinteger(L, s->st_ctime); break;
++              case 10:lua_pushstring(L, filetype(s->st_mode)); break;
++      }
++}
++
++static const char *const Sstat[] =
++{
++      "mode", "ino", "dev", "nlink", "uid", "gid",
++      "size", "atime", "mtime", "ctime", "type",
++      NULL
++};
++
++static int Pstat(lua_State *L)                        /** stat(path,[options]) */
++{
++      struct stat s;
++      const char *path=luaL_checkstring(L, 1);
++      if (lstat(path,&s)==-1) return pusherror(L, path);
++      return doselection(L, 2, Sstat, Fstat, &s);
++}
++
++
++static int Puname(lua_State *L)                       /** uname([string]) */
++{
++      struct utsname u;
++      luaL_Buffer b;
++      const char *s;
++      if (uname(&u)==-1) return pusherror(L, NULL);
++      luaL_buffinit(L, &b);
++      for (s=luaL_optstring(L, 1, "%s %n %r %v %m"); *s; s++)
++              if (*s!='%')
++                      luaL_putchar(&b, *s);
++              else switch (*++s)
++              {
++                      case '%': luaL_putchar(&b, *s); break;
++                      case 'm': luaL_addstring(&b,u.machine); break;
++                      case 'n': luaL_addstring(&b,u.nodename); break;
++                      case 'r': luaL_addstring(&b,u.release); break;
++                      case 's': luaL_addstring(&b,u.sysname); break;
++                      case 'v': luaL_addstring(&b,u.version); break;
++                      default: badoption(L, 2, "format", *s); break;
++              }
++      luaL_pushresult(&b);
++      return 1;
++}
++
++
++static const int Kpathconf[] =
++{
++      _PC_LINK_MAX, _PC_MAX_CANON, _PC_MAX_INPUT, _PC_NAME_MAX, _PC_PATH_MAX,
++      _PC_PIPE_BUF, _PC_CHOWN_RESTRICTED, _PC_NO_TRUNC, _PC_VDISABLE,
++      -1
++};
++
++static void Fpathconf(lua_State *L, int i, const void *data)
++{
++      const char *path=data;
++      lua_pushinteger(L, pathconf(path, Kpathconf[i]));
++}
++
++static const char *const Spathconf[] =
++{
++      "link_max", "max_canon", "max_input", "name_max", "path_max",
++      "pipe_buf", "chown_restricted", "no_trunc", "vdisable",
++      NULL
++};
++
++static int Ppathconf(lua_State *L)            /** pathconf([path,options]) */
++{
++      const char *path = luaL_optstring(L, 1, ".");
++      return doselection(L, 2, Spathconf, Fpathconf, path);
++}
++
++
++static const int Ksysconf[] =
++{
++      _SC_ARG_MAX, _SC_CHILD_MAX, _SC_CLK_TCK, _SC_NGROUPS_MAX, _SC_STREAM_MAX,
++      _SC_TZNAME_MAX, _SC_OPEN_MAX, _SC_JOB_CONTROL, _SC_SAVED_IDS, _SC_VERSION,
++      -1
++};
++
++static void Fsysconf(lua_State *L, int i, const void *data)
++{
++      lua_pushinteger(L, sysconf(Ksysconf[i]));
++}
++
++static const char *const Ssysconf[] =
++{
++      "arg_max", "child_max", "clk_tck", "ngroups_max", "stream_max",
++      "tzname_max", "open_max", "job_control", "saved_ids", "version",
++      NULL
++};
++
++static int Psysconf(lua_State *L)             /** sysconf([options]) */
++{
++      return doselection(L, 1, Ssysconf, Fsysconf, NULL);
++}
++
++#if ENABLE_SYSLOG
++/* syslog funcs */
++static int Popenlog(lua_State *L)     /** openlog(ident, [option], [facility]) */
++{
++      const char *ident = luaL_checkstring(L, 1);
++      int option = 0;
++      int facility = luaL_optint(L, 3, LOG_USER);
++      const char *s = luaL_optstring(L, 2, "");
++      while (*s) {
++              switch (*s) {
++                      case ' ': break;
++                      case 'c': option |= LOG_CONS; break;
++                      case 'n': option |= LOG_NDELAY; break;
++                      case 'e': option |= LOG_PERROR; break;
++                      case 'p': option |= LOG_PID; break;
++                      default: badoption(L, 2, "option", *s); break;
++              }
++              s++;
++      }
++      openlog(ident, option, facility);
++      return 0;
++}
++
++
++static int Psyslog(lua_State *L)              /** syslog(priority, message) */
++{
++      int priority = luaL_checkint(L, 1);
++      const char *msg = luaL_checkstring(L, 2);
++      syslog(priority, "%s", msg);
++      return 0;
++}
++
++
++static int Pcloselog(lua_State *L)            /** closelog() */
++{
++      closelog();
++      return 0;
++}
++#endif
++
++/*
++ * XXX: GNU and BSD handle the forward declaration of crypt() in different
++ * and annoying ways (especially GNU). Declare it here just to make sure
++ * that it's there
++ */
++char *crypt(const char *, const char *);
++
++static int Pcrypt(lua_State *L)
++{
++      const char *str, *salt;
++      char *res;
++
++      str = luaL_checkstring(L, 1);
++      salt = luaL_checkstring(L, 2);
++      if (strlen(salt) < 2)
++              luaL_error(L, "not enough salt");
++
++      res = crypt(str, salt);
++      lua_pushstring(L, res);
++
++      return 1;
++}
++
++static const luaL_reg R[] =
++{
++      {"access",              Paccess},
++      {"basename",            Pbasename},
++      {"chdir",               Pchdir},
++      {"chmod",               Pchmod},
++      {"chown",               Pchown},
++      {"crypt",               Pcrypt},
++      {"ctermid",             Pctermid},
++      {"dirname",             Pdirname},
++      {"dir",                 Pdir},
++      {"dup",                 Pdup},
++      {"errno",               Perrno},
++      {"exec",                Pexec},
++      {"execp",               Pexecp},
++      {"fdopen",              Pfdopen},
++      {"fileno",              Pfileno},
++      {"files",               Pfiles},
++      {"fork",                Pfork},
++      {"getcwd",              Pgetcwd},
++      {"getenv",              Pgetenv},
++      {"getgroup",            Pgetgroup},
++      {"getlogin",            Pgetlogin},
++      {"getpasswd",           Pgetpasswd},
++      {"getpid",              Pgetpid},
++      {"glob",                Pglob},
++      {"hostid",              Phostid},
++      {"kill",                Pkill},
++      {"link",                Plink},
++      {"mkdir",               Pmkdir},
++      {"mkfifo",              Pmkfifo},
++      {"pathconf",            Ppathconf},
++      {"pipe",                Ppipe},
++      {"readlink",            Preadlink},
++      {"rmdir",               Prmdir},
++      {"rpoll",               Ppoll},
++      {"setenv",              Psetenv},
++      {"setpid",              Psetpid},
++      {"sleep",               Psleep},
++      {"stat",                Pstat},
++      {"sysconf",             Psysconf},
++      {"times",               Ptimes},
++      {"ttyname",             Pttyname},
++      {"unlink",              Punlink},
++      {"umask",               Pumask},
++      {"uname",               Puname},
++      {"utime",               Putime},
++      {"wait",                Pwait},
++
++#if ENABLE_SYSLOG
++      {"openlog",             Popenlog},
++      {"syslog",              Psyslog},
++      {"closelog",            Pcloselog},
++#endif
++
++      {NULL,                  NULL}
++};
++
++#define set_const(key, value)         \
++      lua_pushliteral(L, key);        \
++      lua_pushnumber(L, value);       \
++      lua_settable(L, -3)
++
++LUALIB_API int luaopen_posix (lua_State *L)
++{
++      luaL_register(L,MYNAME,R);
++      lua_pushliteral(L,"version");           /** version */
++      lua_pushliteral(L,MYVERSION);
++      lua_settable(L,-3);
++
++#if ENABLE_SYSLOG
++      set_const("LOG_AUTH", LOG_AUTH);
++      set_const("LOG_AUTHPRIV", LOG_AUTHPRIV);
++      set_const("LOG_CRON", LOG_CRON);
++      set_const("LOG_DAEMON", LOG_DAEMON);
++      set_const("LOG_FTP", LOG_FTP);
++      set_const("LOG_KERN", LOG_KERN);
++      set_const("LOG_LOCAL0", LOG_LOCAL0);
++      set_const("LOG_LOCAL1", LOG_LOCAL1);
++      set_const("LOG_LOCAL2", LOG_LOCAL2);
++      set_const("LOG_LOCAL3", LOG_LOCAL3);
++      set_const("LOG_LOCAL4", LOG_LOCAL4);
++      set_const("LOG_LOCAL5", LOG_LOCAL5);
++      set_const("LOG_LOCAL6", LOG_LOCAL6);
++      set_const("LOG_LOCAL7", LOG_LOCAL7);
++      set_const("LOG_LPR", LOG_LPR);
++      set_const("LOG_MAIL", LOG_MAIL);
++      set_const("LOG_NEWS", LOG_NEWS);
++      set_const("LOG_SYSLOG", LOG_SYSLOG);
++      set_const("LOG_USER", LOG_USER);
++      set_const("LOG_UUCP", LOG_UUCP);
++
++      set_const("LOG_EMERG", LOG_EMERG);
++      set_const("LOG_ALERT", LOG_ALERT);
++      set_const("LOG_CRIT", LOG_CRIT);
++      set_const("LOG_ERR", LOG_ERR);
++      set_const("LOG_WARNING", LOG_WARNING);
++      set_const("LOG_NOTICE", LOG_NOTICE);
++      set_const("LOG_INFO", LOG_INFO);
++      set_const("LOG_DEBUG", LOG_DEBUG);
++#endif
++
++
++      return 1;
++}
++
++/*EOF*/
+Index: lua-5.1.4/src/lualib.h
+===================================================================
+--- lua-5.1.4.orig/src/lualib.h        2008-09-25 12:18:14.000000000 +0200
++++ lua-5.1.4/src/lualib.h     2008-09-25 12:18:53.000000000 +0200
+@@ -39,6 +39,9 @@
+ #define LUA_LOADLIBNAME       "package"
+ LUALIB_API int (luaopen_package) (lua_State *L);
++#define LUA_POSIXLIBNAME "posix"
++LUALIB_API int (luaopen_posix) (lua_State *L);
++
+ /* open all previous libraries */
+ LUALIB_API void (luaL_openlibs) (lua_State *L); 
+Index: lua-5.1.4/src/modemuncher.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ lua-5.1.4/src/modemuncher.c        2008-09-25 12:16:29.000000000 +0200
+@@ -0,0 +1,261 @@
++/* 
++      Mode Muncher -- modemuncher.c
++      961110 Claudio Terra
++
++      munch vb
++      [ME monchen, perh. influenced by MF mangier to eat --more at MANGER]
++      :to chew with a crunching sound: eat with relish
++      :to chew food with a crunching sound: eat food with relish
++      --munch-er n
++              
++      The NeXT Digital Edition of Webster's Ninth New Collegiate Dictionary
++      and Webster's Collegiate Thesaurus
++*/
++
++/* struct for rwx <-> 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 (file)
index 0000000..91de064
--- /dev/null
@@ -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 <stdint.h>
++#include <math.h>
++
++/* 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);