RPM Community Forums

Mailing List Message of <rpm-cvs>

[CVS] RPM: lua/ .cvsignore COPYRIGHT HISTORY Makefile.am README bin2c....

From: Ralf S. Engelschall <rse@rpm5.org>
Date: Sun 15 Jul 2007 - 19:56:20 CEST
Message-Id: <20070715175620.10F6A3484F1@rpm5.org>
  RPM Package Manager, CVS Repository
  http://rpm5.org/cvs/
  ____________________________________________________________________________

  Server: rpm5.org                         Name:   Ralf S. Engelschall
  Root:   /v/rpm/cvs                       Email:  rse@rpm5.org
  Module: rpm lua                          Date:   15-Jul-2007 19:56:19
  Branch: HEAD                             Handle: 2007071518561009

  Added files:
    lua                     bin2c.c lauxlib.c lauxlib.h lbaselib.c ldblib.c
                            linit.c liolib.c lmathlib.c loadlib.c loslib.c
                            lstrlib.c ltablib.c lua.c lua.h luac.c luaconf.h
                            lualib.h print.c
    lua/local               .cvsignore llocal.c llocal.h llocal.lua
  Modified files:
    lua                     .cvsignore COPYRIGHT HISTORY Makefile.am README
                            lapi.c lapi.h lcode.c lcode.h ldebug.c ldebug.h
                            ldo.c ldo.h ldump.c lfunc.c lfunc.h lgc.c lgc.h
                            llex.c llex.h llimits.h lmem.c lmem.h lobject.c
                            lobject.h lopcodes.c lopcodes.h lparser.c
                            lparser.h lstate.c lstate.h lstring.c lstring.h
                            ltable.c ltable.h ltm.c ltm.h lundump.c lundump.h
                            lvm.c lvm.h lzio.c lzio.h
    lua/local               lposix.c lrexlib.c
    rpm                     CHANGES configure.ac
    rpm/rpmio               rpmlua.c
  Removed files:
    lua/include             lauxlib.h lua.h lualib.h
    lua/lib                 lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c
                            loadlib.c lstrlib.c ltablib.c
    lua/local               linit.c linit.lch linit.lua modemuncher.c
                            userconfig.c
    lua/lua                 lua.c
    lua/luac                luac.c print.c

  Log:
    upgrade the local Lua copy from version 5.0.2 to 5.1.2

  Summary:
    Revision    Changes     Path
    1.2         +1  -0      lua/.cvsignore
    1.3         +1  -1      lua/COPYRIGHT
    1.2         +25 -1      lua/HISTORY
    1.12        +30 -94     lua/Makefile.am
    1.2         +10 -17     lua/README
    1.1         +69 -0      lua/bin2c.c
    1.4         +0  -188    lua/include/lauxlib.h
    1.4         +0  -479    lua/include/lua.h
    1.4         +0  -63     lua/include/lualib.h
    1.3         +407 -273   lua/lapi.c
    1.3         +2  -3      lua/lapi.h
    1.1         +653 -0     lua/lauxlib.c
    1.1         +174 -0     lua/lauxlib.h
    1.1         +643 -0     lua/lbaselib.c
    1.3         +311 -226   lua/lcode.c
    1.3         +35 -61     lua/lcode.h
    1.1         +397 -0     lua/ldblib.c
    1.3         +190 -202   lua/ldebug.c
    1.3         +12 -18     lua/ldebug.h
    1.4         +215 -196   lua/ldo.c
    1.3         +25 -42     lua/ldo.h
    1.3         +80 -99     lua/ldump.c
    1.2         +76 -37     lua/lfunc.c
    1.3         +19 -23     lua/lfunc.h
    1.4         +494 -332   lua/lgc.c
    1.4         +93 -13     lua/lgc.h
    1.3         +0  -616    lua/lib/lauxlib.c
    1.4         +0  -766    lua/lib/lbaselib.c
    1.3         +0  -335    lua/lib/ldblib.c
    1.4         +0  -898    lua/lib/liolib.c
    1.3         +0  -299    lua/lib/lmathlib.c
    1.3         +0  -209    lua/lib/loadlib.c
    1.2         +0  -770    lua/lib/lstrlib.c
    1.3         +0  -275    lua/lib/ltablib.c
    1.1         +38 -0      lua/linit.c
    1.1         +532 -0     lua/liolib.c
    1.3         +288 -259   lua/llex.c
    1.3         +17 -20     lua/llex.h
    1.2         +41 -98     lua/llimits.h
    1.1         +263 -0     lua/lmathlib.c
    1.2         +46 -51     lua/lmem.c
    1.3         +24 -23     lua/lmem.h
    1.1         +664 -0     lua/loadlib.c
    1.3         +74 -57     lua/lobject.c
    1.3         +123 -101   lua/lobject.h
    1.1         +2  -0      lua/local/.cvsignore
    1.4         +0  -10     lua/local/linit.c
    1.3         +0  -46     lua/local/linit.lch
    1.3         +0  -41     lua/local/linit.lua
    1.1         +10 -0      lua/local/llocal.c
    1.1         +7  -0      lua/local/llocal.h
    1.1         +41 -0      lua/local/llocal.lua
    1.5         +277 -2     lua/local/lposix.c
    1.5         +4  -0      lua/local/lrexlib.c
    1.4         +0  -276    lua/local/modemuncher.c
    1.4         +0  -58     lua/local/userconfig.c
    1.2         +51 -51     lua/lopcodes.c
    1.3         +78 -49     lua/lopcodes.h
    1.1         +244 -0     lua/loslib.c
    1.4         +368 -508   lua/lparser.c
    1.3         +20 -14     lua/lparser.h
    1.3         +104 -130   lua/lstate.c
    1.3         +51 -101    lua/lstate.h
    1.3         +36 -30     lua/lstring.c
    1.3         +8  -16     lua/lstring.h
    1.1         +868 -0     lua/lstrlib.c
    1.3         +290 -240   lua/ltable.c
    1.3         +22 -26     lua/ltable.h
    1.1         +278 -0     lua/ltablib.c
    1.3         +17 -15     lua/ltm.c
    1.3         +10 -13     lua/ltm.h
    1.1         +390 -0     lua/lua.c
    1.1         +385 -0     lua/lua.h
    1.3         +0  -506    lua/lua/lua.c
    1.1         +200 -0     lua/luac.c
    1.3         +0  -193    lua/luac/luac.c
    1.2         +0  -217    lua/luac/print.c
    1.1         +762 -0     lua/luaconf.h
    1.1         +53 -0      lua/lualib.h
    1.3         +112 -199   lua/lundump.c
    1.3         +19 -23     lua/lundump.h
    1.4         +404 -449   lua/lvm.c
    1.3         +11 -21     lua/lvm.h
    1.2         +19 -18     lua/lzio.c
    1.3         +20 -24     lua/lzio.h
    1.1         +227 -0     lua/print.c
    1.1467      +1  -0      rpm/CHANGES
    2.173       +1  -1      rpm/configure.ac
    2.15        +15 -8      rpm/rpmio/rpmlua.c
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: lua/.cvsignore
  ============================================================================
  $ cvs diff -u -r1.1 -r1.2 .cvsignore
  --- lua/.cvsignore	23 Mar 2004 05:09:13 -0000	1.1
  +++ lua/.cvsignore	15 Jul 2007 17:56:10 -0000	1.2
  @@ -5,3 +5,4 @@
   *.la
   *.lcd
   *.lo
  +bin2c
  @@ .
  patch -p0 <<'@@ .'
  Index: lua/COPYRIGHT
  ============================================================================
  $ cvs diff -u -r1.2 -r1.3 COPYRIGHT
  --- lua/COPYRIGHT	19 Mar 2004 21:14:32 -0000	1.2
  +++ lua/COPYRIGHT	15 Jul 2007 17:56:10 -0000	1.3
  @@ -9,7 +9,7 @@
   
   ===============================================================================
   
  -Copyright (C) 2003-2004 Tecgraf, PUC-Rio.
  +Copyright (C) 1994-2007 Lua.org, PUC-Rio.
   
   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
  @@ .
  patch -p0 <<'@@ .'
  Index: lua/HISTORY
  ============================================================================
  $ cvs diff -u -r1.1 -r1.2 HISTORY
  --- lua/HISTORY	16 Mar 2004 21:58:30 -0000	1.1
  +++ lua/HISTORY	15 Jul 2007 17:56:10 -0000	1.2
  @@ -1,4 +1,28 @@
  -This is Lua 5.0.
  +HISTORY for Lua 5.1
  +
  +* Changes from version 5.0 to 5.1
  +  -------------------------------
  +  Language:
  +  + new module system.
  +  + new semantics for control variables of fors.
  +  + new semantics for setn/getn.
  +  + new syntax/semantics for varargs.
  +  + new long strings and comments.
  +  + new `mod' operator (`%')
  +  + new length operator #t
  +  + metatables for all types
  +  API:
  +  + new functions: lua_createtable, lua_get(set)field, lua_push(to)integer.
  +  + user supplies memory allocator (lua_open becomes lua_newstate).
  +  + luaopen_* functions must be called through Lua.
  +  Implementation:
  +  + new configuration scheme via luaconf.h.
  +  + incremental garbage collection.
  +  + better handling of end-of-line in the lexer.
  +  + fully reentrant parser (new Lua function `load')
  +  + better support for 64-bit machines.
  +  + native loadlib support for Mac OS X.
  +  + standard distribution in only one library (lualib.a merged into lua.a)
   
   * Changes from version 4.0 to 5.0
     -------------------------------
  @@ .
  patch -p0 <<'@@ .'
  Index: lua/Makefile.am
  ============================================================================
  $ cvs diff -u -r1.11 -r1.12 Makefile.am
  --- lua/Makefile.am	27 Jun 2007 20:20:26 -0000	1.11
  +++ lua/Makefile.am	15 Jul 2007 17:56:10 -0000	1.12
  @@ -1,8 +1,6 @@
   
  -LINT = splint
  -
   noinst_LTLIBRARIES = liblua.la
  -noinst_PROGRAMS = lua/lua luac/luac
  +noinst_PROGRAMS = lua/lua luac/luac bin2c
   
   EXTRA_DIST = \
   	COPYRIGHT \
  @@ -12,37 +10,42 @@
   	local/linit.lua
   
   AM_CPPFLAGS = \
  -	-I$(srcdir)/include \
   	-I$(srcdir)/local \
   	-I$(srcdir)
   
  -lua_lua_SOURCES = lua/lua.c
  -lua_lua_CFLAGS = -DLUA_USERCONFIG='"$(srcdir)/local/userconfig.c"'
  +lua_lua_SOURCES = lua.c
  +lua_lua_CFLAGS =
   lua_lua_LDADD = liblua.la
  -luac_luac_SOURCES = luac/luac.c luac/print.c lopcodes.c
  -luac_luac_CFLAGS = -DLUA_OPNAMES
  +luac_luac_SOURCES = luac.c print.c
  +luac_luac_CFLAGS =
   luac_luac_LDADD = liblua.la
  +bin2c_SOURCES = bin2c.c
  +bin2c_CFLAGS =
  +bin2c_LDADD =
   
  -liblua_la_CFLAGS = @WITH_LUA_SUBDIR_DEF@ -DWITH_POSIX
  +liblua_la_CFLAGS = @WITH_LUA_SUBDIR_DEF@ -DLUA_USE_POSIX
   liblua_la_LIBADD = @WITH_LUA_SUBDIR_LIB@ -lm
   liblua_la_SOURCES = \
  -		local/linit.c \
  -		local/linit.lch \
  +		local/llocal.c \
  +		local/llocal.h \
   		local/lposix.h \
   		local/lposix.c \
   		local/lrexlib.h \
   		local/lrexlib.c \
  -		include/lauxlib.h \
  -		include/lua.h \
  -		include/lualib.h \
  -		lib/lauxlib.c \
  -		lib/lbaselib.c \
  -		lib/ldblib.c \
  -		lib/liolib.c \
  -		lib/lmathlib.c \
  -		lib/loadlib.c \
  -		lib/lstrlib.c \
  -		lib/ltablib.c \
  +		linit.c \
  +		lauxlib.h \
  +		lauxlib.c \
  +		lua.h \
  +		luaconf.h \
  +		lualib.h \
  +		lbaselib.c \
  +		ldblib.c \
  +		liolib.c \
  +		loslib.c \
  +		lmathlib.c \
  +		loadlib.c \
  +		lstrlib.c \
  +		ltablib.c \
   		lapi.c \
   		lapi.h \
   		lcode.c \
  @@ -85,77 +88,10 @@
   liblua.la: $(liblua_la_OBJECTS) $(liblua_la_DEPENDENCIES) 
   	$(liblua_la_LINK) $(liblua_la_OBJECTS) $(liblua_la_LIBADD)
   
  -local/linit.lch: local/linit.lua
  -	bin2c local/linit.lua > local/linit.lch
  -
  -# XXX to avoid local/linit.lch syntax problem.
  -#
  -#		local/linit.c \
  -#		lib/lstrlib.c \
  -#
  -LUA_SPLINT_SRCS = \
  -		lua/lua.c \
  -		include/lauxlib.h \
  -		include/lua.h \
  -		include/lualib.h \
  -		lib/lauxlib.c \
  -		lib/lbaselib.c \
  -		lib/ldblib.c \
  -		lib/liolib.c \
  -		lib/loadlib.c \
  -		lib/lmathlib.c \
  -		lib/ltablib.c \
  -		local/lposix.h \
  -		local/lposix.c \
  -		local/lrexlib.h \
  -		local/lrexlib.c \
  -		local/lsyck.h \
  -		local/lsyck.c \
  -		lapi.c \
  -		lapi.h \
  -		lcode.c \
  -		lcode.h \
  -		ldebug.c \
  -		ldebug.h \
  -		ldo.c \
  -		ldo.h \
  -		ldump.c \
  -		lfunc.c \
  -		lfunc.h \
  -		lgc.c \
  -		lgc.h \
  -		llex.c \
  -		llex.h \
  -		llimits.h \
  -		lmem.c \
  -		lmem.h \
  -		lobject.c \
  -		lobject.h \
  -		lopcodes.c \
  -		lopcodes.h \
  -		lparser.c \
  -		lparser.h \
  -		lstate.c \
  -		lstate.h \
  -		lstring.c \
  -		lstring.h \
  -		ltable.c \
  -		ltable.h \
  -		ltests.c \
  -		ltm.c \
  -		ltm.h \
  -		lundump.c \
  -		lundump.h \
  -		lvm.c \
  -		lvm.h \
  -		lzio.c \
  -		lzio.h
  +$(builddir)/local/llocal.c: $(builddir)/local/llocal_lua.c
  +$(builddir)/local/llocal_lua.c: $(builddir)/bin2c $(srcdir)/local/llocal.lua
  +	$(builddir)/bin2c $(srcdir)/local/llocal.lua >$(builddir)/local/llocal_lua.c
   
  -.PHONY:	sources
  -sources:
  -	@echo $(LUA_SPLINT_SRCS:%=lua/%)
  -
  -.PHONY:	lint
  -lint:
  -	$(LINT) $(DEFS) $(INCLUDES) $(LUA_SPLINT_SRCS)
  +clean-local:
  +	-rm -f $(builddir)/local/llocal_lua.c
   
  @@ .
  patch -p0 <<'@@ .'
  Index: lua/README
  ============================================================================
  $ cvs diff -u -r1.1 -r1.2 README
  --- lua/README	16 Mar 2004 21:58:30 -0000	1.1
  +++ lua/README	15 Jul 2007 17:56:10 -0000	1.2
  @@ -1,4 +1,6 @@
  -This is Lua 5.0.
  +README for Lua 5.1
  +
  +See INSTALL for installation instructions.
   See HISTORY for a summary of changes since the last released version.
   
   * What is Lua?
  @@ -17,28 +19,19 @@
     ------------
     Lua is freely available for both academic and commercial purposes.
     See COPYRIGHT and http://www.lua.org/license.html for details.
  -  Lua can be downloaded from its official site http://www.lua.org/ and
  -  several other sites aroung the world. For a complete list of mirror sites,
  -  see http://www.lua.org/mirrors.html .
  +  Lua can be downloaded at http://www.lua.org/download.html .
   
   * Installation
     ------------
     Lua is implemented in pure ANSI C, and compiles unmodified in all known
  -  platforms that have an ANSI C compiler. Under Unix, simply typing "make"
  -  should work. See INSTALL for detailed instructions.
  -
  -* Contacting the authors
  -  ----------------------
  -  Send your comments, questions, and bug reports to lua@tecgraf.puc-rio.br.
  -  For more information about the authors, see http://www.lua.org/authors.html .
  -  For reporting bugs, try also the mailing list: lua-l@tecgraf.puc-rio.br.
  -  For more information about this list, including instructions on how to
  -  subscribe and access the archives, see http://www.lua.org/lua-l.html .
  +  platforms that have an ANSI C compiler. In most Unix-like platforms, simply
  +  do "make" with a suitable target. See INSTALL for detailed instructions.
   
   * Origin
     ------
  -  Lua is developed at Tecgraf, the Computer Graphics Technology Group
  -  of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro in Brazil).
  -  Tecgraf is a laboratory of the Department of Computer Science.
  +  Lua is developed at Lua.org, a laboratory of the Department of Computer
  +  Science of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro
  +  in Brazil).
  +  For more information about the authors, see http://www.lua.org/authors.html .
   
   (end of README)
  @@ .
  patch -p0 <<'@@ .'
  Index: lua/bin2c.c
  ============================================================================
  $ cvs diff -u -r0 -r1.1 bin2c.c
  --- /dev/null	2007-07-15 19:55:00 +0200
  +++ bin2c.c	2007-07-15 19:56:11 +0200
  @@ -0,0 +1,69 @@
  +/*
  +* bin2c.c
  +* convert files to byte arrays for automatic loading
  +* Luiz Henrique de Figueiredo (lhf@tecgraf.puc-rio.br)
  +* Fixed to Lua 5.1. Antonio Scuri (scuri@tecgraf.puc-rio.br)
  +* Generated files will work also for Lua 5.0
  +* 08 Dec 2005
  +*/
  +
  +#include <ctype.h>
  +#include <stdio.h>
  +#include <stdlib.h>
  +
  +static void dump(FILE* f, int n)
  +{
  +  printf("static const unsigned char B%d[]={\n",n);
  +  for (n=1;;n++)
  +  {
  +    int c=getc(f); 
  +    if (c==EOF) break;
  +    printf("%3u,",c);
  +    if (n==20) { putchar('\n'); n=0; }
  +  }
  +  printf("\n};\n\n");
  +}
  +
  +static void fdump(const char* fn, int n)
  +{
  +  FILE* f= fopen(fn,"rb");		/* must open in binary mode */
  +  if (f==NULL)
  +  {
  +    fprintf(stderr,"bin2c: cannot open ");
  +    perror(fn);
  +    exit(1);
  +  }
  +  else
  +  {
  +    printf("/* %s */\n",fn);
  +    dump(f,n);
  +    fclose(f);
  +  }
  +}
  +
  +static void emit(const char* fn, int n)
  +{
  +  printf(" if (luaL_loadbuffer(L,(const char*)B%d,sizeof(B%d),\"%s\")==0) lua_pcall(L, 0, 0, 0);\n",n,n,fn);
  +}
  +
  +int main(int argc, char* argv[])
  +{
  +  printf("/* code automatically generated by bin2c -- DO NOT EDIT */\n");
  +  printf("{\n");
  +  if (argc<2)
  +  {
  +    dump(stdin,0);
  +    emit("=stdin",0);
  +  }
  +  else
  +  {
  +    int i;
  +    printf("/* #include'ing this file in a C program is equivalent to calling\n");
  +    for (i=1; i<argc; i++) printf("  if (luaL_loadfile(L,\"%s\")==0) lua_pcall(L, 0, 0, 0); \n",argv[i]);
  +    printf("*/\n");
  +    for (i=1; i<argc; i++) fdump(argv[i],i);
  +    for (i=1; i<argc; i++) emit(argv[i],i);
  +  }
  +  printf("}\n");
  +  return 0;
  +}
  @@ .
  rm -f lua/include/lauxlib.h <<'@@ .'
  Index: lua/include/lauxlib.h
  ============================================================================
  [NO CHANGE SUMMARY BECAUSE FILE AS A WHOLE IS JUST REMOVED]
  @@ .
  rm -f lua/include/lua.h <<'@@ .'
  Index: lua/include/lua.h
  ============================================================================
  [NO CHANGE SUMMARY BECAUSE FILE AS A WHOLE IS JUST REMOVED]
  @@ .
  rm -f lua/include/lualib.h <<'@@ .'
  Index: lua/include/lualib.h
  ============================================================================
  [NO CHANGE SUMMARY BECAUSE FILE AS A WHOLE IS JUST REMOVED]
  @@ .
  patch -p0 <<'@@ .'
  Index: lua/lapi.c
  ============================================================================
  $ cvs diff -u -r1.2 -r1.3 lapi.c
  --- lua/lapi.c	23 Mar 2004 05:09:14 -0000	1.2
  +++ lua/lapi.c	15 Jul 2007 17:56:10 -0000	1.3
  @@ -1,14 +1,17 @@
   /*
  -** $Id: lapi.c,v 1.2 2004/03/23 05:09:14 jbj Exp $
  +** $Id: lapi.c,v 1.3 2007/07/15 17:56:10 rse Exp $
   ** Lua API
   ** See Copyright Notice in lua.h
   */
   
   
   #include <assert.h>
  +#include <math.h>
  +#include <stdarg.h>
   #include <string.h>
   
   #define lapi_c
  +#define LUA_CORE
   
   #include "lua.h"
   
  @@ -27,89 +30,72 @@
   #include "lvm.h"
   
   
  -/*@unused@*/
  +
   const char lua_ident[] =
  -  "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n"
  +  "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n"
     "$Authors: " LUA_AUTHORS " $\n"
     "$URL: www.lua.org $\n";
   
   
   
  -#ifndef api_check
  -#define api_check(L, o)		/*{ assert(o); }*/
  -#endif
  -
   #define api_checknelems(L, n)	api_check(L, (n) <= (L->top - L->base))
   
  -#define api_incr_top(L)   {api_check(L, L->top < L->ci->top); L->top++;}
  +#define api_checkvalidindex(L, i)	api_check(L, (i) != luaO_nilobject)
   
  +#define api_incr_top(L)   {api_check(L, L->top < L->ci->top); L->top++;}
   
   
   
  -/*@dependent@*/ /*@null@*/
  -static TObject *negindex (lua_State *L, int idx)
  -	/*@*/
  -{
  -  if (idx > LUA_REGISTRYINDEX) {
  +static TValue *index2adr (lua_State *L, int idx) {
  +  if (idx > 0) {
  +    TValue *o = L->base + (idx - 1);
  +    api_check(L, idx <= L->ci->top - L->base);
  +    if (o >= L->top) return cast(TValue *, luaO_nilobject);
  +    else return o;
  +  }
  +  else if (idx > LUA_REGISTRYINDEX) {
       api_check(L, idx != 0 && -idx <= L->top - L->base);
  -    return L->top+idx;
  +    return L->top + idx;
     }
     else switch (idx) {  /* pseudo-indices */
       case LUA_REGISTRYINDEX: return registry(L);
  +    case LUA_ENVIRONINDEX: {
  +      Closure *func = curr_func(L);
  +      sethvalue(L, &L->env, func->c.env);
  +      return &L->env;
  +    }
       case LUA_GLOBALSINDEX: return gt(L);
       default: {
  -      TObject *func = (L->base - 1);
  +      Closure *func = curr_func(L);
         idx = LUA_GLOBALSINDEX - idx;
  -      lua_assert(iscfunction(func));
  -      return (idx <= clvalue(func)->c.nupvalues)
  -                ? &clvalue(func)->c.upvalue[idx-1]
  -                : NULL;
  +      return (idx <= func->c.nupvalues)
  +                ? &func->c.upvalue[idx-1]
  +                : cast(TValue *, luaO_nilobject);
       }
     }
   }
   
   
  -/*@dependent@*/ /*@relnull@*/
  -static TObject *luaA_index (lua_State *L, int idx)
  -	/*@*/
  -{
  -  if (idx > 0) {
  -    api_check(L, idx <= L->top - L->base);
  -    return L->base + idx - 1;
  -  }
  +static Table *getcurrenv (lua_State *L) {
  +  if (L->ci == L->base_ci)  /* no enclosing function? */
  +    return hvalue(gt(L));  /* use global table as environment */
     else {
  -    TObject *o = negindex(L, idx);
  -    api_check(L, o != NULL);
  -    return o;
  +    Closure *func = curr_func(L);
  +    return func->c.env;
     }
   }
   
   
  -/*@dependent@*/ /*@null@*/
  -static TObject *luaA_indexAcceptable (lua_State *L, int idx)
  -	/*@*/
  -{
  -  if (idx > 0) {
  -    TObject *o = L->base+(idx-1);
  -    api_check(L, idx <= L->stack_last - L->base);
  -    if (o >= L->top) return NULL;
  -    else return o;
  -  }
  -  else
  -    return negindex(L, idx);
  -}
  -
  -
  -void luaA_pushobject (lua_State *L, const TObject *o) {
  -  setobj2s(L->top, o);
  -  incr_top(L);
  +void luaA_pushobject (lua_State *L, const TValue *o) {
  +  setobj2s(L, L->top, o);
  +  api_incr_top(L);
   }
   
   
   LUA_API int lua_checkstack (lua_State *L, int size) {
     int res;
     lua_lock(L);
  -  if ((L->top - L->base + size) > LUA_MAXCSTACK)
  +  if ((L->top - L->base + size) > LUAI_MAXCSTACK)
       res = 0;  /* stack overflow */
     else {
       luaD_checkstack(L, size);
  @@ -124,12 +110,14 @@
   
   LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
     int i;
  +  if (from == to) return;
     lua_lock(to);
     api_checknelems(from, n);
  +  api_check(from, G(from) == G(to));
  +  api_check(from, to->ci->top - to->top >= n);
     from->top -= n;
     for (i = 0; i < n; i++) {
  -    setobj2s(to->top, from->top + i);
  -    api_incr_top(to);
  +    setobj2s(to, to->top++, from->top + i);
     }
     lua_unlock(to);
   }
  @@ -150,13 +138,11 @@
     lua_lock(L);
     luaC_checkGC(L);
     L1 = luaE_newthread(L);
  -  setthvalue(L->top, L1);
  +  setthvalue(L, L->top, L1);
     api_incr_top(L);
     lua_unlock(L);
  -  lua_userstateopen(L1);
  -/*@-kepttrans@*/
  +  luai_userstatethread(L, L1);
     return L1;
  -/*@=kepttrans@*/
   }
   
   
  @@ -167,7 +153,7 @@
   
   
   LUA_API int lua_gettop (lua_State *L) {
  -  return (L->top - L->base);
  +  return cast_int(L->top - L->base);
   }
   
   
  @@ -190,8 +176,9 @@
   LUA_API void lua_remove (lua_State *L, int idx) {
     StkId p;
     lua_lock(L);
  -  p = luaA_index(L, idx);
  -  while (++p < L->top) setobjs2s(p-1, p);
  +  p = index2adr(L, idx);
  +  api_checkvalidindex(L, p);
  +  while (++p < L->top) setobjs2s(L, p-1, p);
     L->top--;
     lua_unlock(L);
   }
  @@ -201,17 +188,34 @@
     StkId p;
     StkId q;
     lua_lock(L);
  -  p = luaA_index(L, idx);
  -  for (q = L->top; q>p; q--) setobjs2s(q, q-1);
  -  setobjs2s(p, L->top);
  +  p = index2adr(L, idx);
  +  api_checkvalidindex(L, p);
  +  for (q = L->top; q>p; q--) setobjs2s(L, q, q-1);
  +  setobjs2s(L, p, L->top);
     lua_unlock(L);
   }
   
   
   LUA_API void lua_replace (lua_State *L, int idx) {
  +  StkId o;
     lua_lock(L);
  +  /* explicit test for incompatible code */
  +  if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci)
  +    luaG_runerror(L, "no calling environment");
     api_checknelems(L, 1);
  -  setobj(luaA_index(L, idx), L->top - 1);  /* write barrier */
  +  o = index2adr(L, idx);
  +  api_checkvalidindex(L, o);
  +  if (idx == LUA_ENVIRONINDEX) {
  +    Closure *func = curr_func(L);
  +    api_check(L, ttistable(L->top - 1)); 
  +    func->c.env = hvalue(L->top - 1);
  +    luaC_barrier(L, func, L->top - 1);
  +  }
  +  else {
  +    setobj(L, o, L->top - 1);
  +    if (idx < LUA_GLOBALSINDEX)  /* function upvalue? */
  +      luaC_barrier(L, curr_func(L), L->top - 1);
  +  }
     L->top--;
     lua_unlock(L);
   }
  @@ -219,7 +223,7 @@
   
   LUA_API void lua_pushvalue (lua_State *L, int idx) {
     lua_lock(L);
  -  setobj2s(L->top, luaA_index(L, idx));
  +  setobj2s(L, L->top, index2adr(L, idx));
     api_incr_top(L);
     lua_unlock(L);
   }
  @@ -232,8 +236,8 @@
   
   
   LUA_API int lua_type (lua_State *L, int idx) {
  -  StkId o = luaA_indexAcceptable(L, idx);
  -  return (o == NULL) ? LUA_TNONE : ttype(o);
  +  StkId o = index2adr(L, idx);
  +  return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
   }
   
   
  @@ -244,15 +248,15 @@
   
   
   LUA_API int lua_iscfunction (lua_State *L, int idx) {
  -  StkId o = luaA_indexAcceptable(L, idx);
  -  return (o == NULL) ? 0 : iscfunction(o);
  +  StkId o = index2adr(L, idx);
  +  return iscfunction(o);
   }
   
   
   LUA_API int lua_isnumber (lua_State *L, int idx) {
  -  TObject n;
  -  const TObject *o = luaA_indexAcceptable(L, idx);
  -  return (o != NULL && tonumber(o, &n));
  +  TValue n;
  +  const TValue *o = index2adr(L, idx);
  +  return tonumber(o, &n);
   }
   
   
  @@ -263,16 +267,16 @@
   
   
   LUA_API int lua_isuserdata (lua_State *L, int idx) {
  -  const TObject *o = luaA_indexAcceptable(L, idx);
  -  return (o != NULL && (ttisuserdata(o) || ttislightuserdata(o)));
  +  const TValue *o = index2adr(L, idx);
  +  return (ttisuserdata(o) || ttislightuserdata(o));
   }
   
   
   LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
  -  StkId o1 = luaA_indexAcceptable(L, index1);
  -  StkId o2 = luaA_indexAcceptable(L, index2);
  -  return (o1 == NULL || o2 == NULL) ? 0  /* index out of range */
  -                                    : luaO_rawequalObj(o1, o2);
  +  StkId o1 = index2adr(L, index1);
  +  StkId o2 = index2adr(L, index2);
  +  return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
  +         : luaO_rawequalObj(o1, o2);
   }
   
   
  @@ -280,10 +284,9 @@
     StkId o1, o2;
     int i;
     lua_lock(L);  /* may call tag method */
  -  o1 = luaA_indexAcceptable(L, index1);
  -  o2 = luaA_indexAcceptable(L, index2);
  -  i = (o1 == NULL || o2 == NULL) ? 0  /* index out of range */
  -                                 : equalobj(L, o1, o2);
  +  o1 = index2adr(L, index1);
  +  o2 = index2adr(L, index2);
  +  i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2);
     lua_unlock(L);
     return i;
   }
  @@ -293,10 +296,10 @@
     StkId o1, o2;
     int i;
     lua_lock(L);  /* may call tag method */
  -  o1 = luaA_indexAcceptable(L, index1);
  -  o2 = luaA_indexAcceptable(L, index2);
  -  i = (o1 == NULL || o2 == NULL) ? 0  /* index out-of-range */
  -                                 : luaV_lessthan(L, o1, o2);
  +  o1 = index2adr(L, index1);
  +  o2 = index2adr(L, index2);
  +  i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
  +       : luaV_lessthan(L, o1, o2);
     lua_unlock(L);
     return i;
   }
  @@ -304,65 +307,81 @@
   
   
   LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
  -  TObject n;
  -  const TObject *o = luaA_indexAcceptable(L, idx);
  -  if (o != NULL && tonumber(o, &n))
  +  TValue n;
  +  const TValue *o = index2adr(L, idx);
  +  if (tonumber(o, &n))
       return nvalue(o);
     else
       return 0;
   }
   
   
  +LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
  +  TValue n;
  +  const TValue *o = index2adr(L, idx);
  +  if (tonumber(o, &n)) {
  +    lua_Integer res;
  +    lua_Number num = nvalue(o);
  +    lua_number2integer(res, num);
  +    return res;
  +  }
  +  else
  +    return 0;
  +}
  +
  +
   LUA_API int lua_toboolean (lua_State *L, int idx) {
  -  const TObject *o = luaA_indexAcceptable(L, idx);
  -  return (o != NULL) && !l_isfalse(o);
  +  const TValue *o = index2adr(L, idx);
  +  return !l_isfalse(o);
   }
   
   
  -LUA_API const char *lua_tostring (lua_State *L, int idx) {
  -  StkId o = luaA_indexAcceptable(L, idx);
  -  if (o == NULL)
  -    return NULL;
  -  else if (ttisstring(o))
  -    return svalue(o);
  -  else {
  -    const char *s;
  +LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
  +  StkId o = index2adr(L, idx);
  +  if (!ttisstring(o)) {
       lua_lock(L);  /* `luaV_tostring' may create a new string */
  -    s = (luaV_tostring(L, o) ? svalue(o) : NULL);
  +    if (!luaV_tostring(L, o)) {  /* conversion failed? */
  +      if (len != NULL) *len = 0;
  +      lua_unlock(L);
  +      return NULL;
  +    }
       luaC_checkGC(L);
  +    o = index2adr(L, idx);  /* previous call may reallocate the stack */
       lua_unlock(L);
  -    return s;
     }
  +  if (len != NULL) *len = tsvalue(o)->len;
  +  return svalue(o);
   }
   
   
  -LUA_API size_t lua_strlen (lua_State *L, int idx) {
  -  StkId o = luaA_indexAcceptable(L, idx);
  -  if (o == NULL)
  -    return 0;
  -  else if (ttisstring(o))
  -    return tsvalue(o)->tsv.len;
  -  else {
  -    size_t l;
  -    lua_lock(L);  /* `luaV_tostring' may create a new string */
  -    l = (luaV_tostring(L, o) ? tsvalue(o)->tsv.len : 0);
  -    lua_unlock(L);
  -    return l;
  +LUA_API size_t lua_objlen (lua_State *L, int idx) {
  +  StkId o = index2adr(L, idx);
  +  switch (ttype(o)) {
  +    case LUA_TSTRING: return tsvalue(o)->len;
  +    case LUA_TUSERDATA: return uvalue(o)->len;
  +    case LUA_TTABLE: return luaH_getn(hvalue(o));
  +    case LUA_TNUMBER: {
  +      size_t l;
  +      lua_lock(L);  /* `luaV_tostring' may create a new string */
  +      l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0);
  +      lua_unlock(L);
  +      return l;
  +    }
  +    default: return 0;
     }
   }
   
   
   LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
  -  StkId o = luaA_indexAcceptable(L, idx);
  -  return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->c.f;
  +  StkId o = index2adr(L, idx);
  +  return (!iscfunction(o)) ? NULL : clvalue(o)->c.f;
   }
   
   
   LUA_API void *lua_touserdata (lua_State *L, int idx) {
  -  StkId o = luaA_indexAcceptable(L, idx);
  -  if (o == NULL) return NULL;
  +  StkId o = index2adr(L, idx);
     switch (ttype(o)) {
  -    case LUA_TUSERDATA: return (uvalue(o) + 1);
  +    case LUA_TUSERDATA: return (rawuvalue(o) + 1);
       case LUA_TLIGHTUSERDATA: return pvalue(o);
       default: return NULL;
     }
  @@ -370,24 +389,21 @@
   
   
   LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
  -  StkId o = luaA_indexAcceptable(L, idx);
  -  return (o == NULL || !ttisthread(o)) ? NULL : thvalue(o);
  +  StkId o = index2adr(L, idx);
  +  return (!ttisthread(o)) ? NULL : thvalue(o);
   }
   
   
   LUA_API const void *lua_topointer (lua_State *L, int idx) {
  -  StkId o = luaA_indexAcceptable(L, idx);
  -  if (o == NULL) return NULL;
  -  else {
  -    switch (ttype(o)) {
  -      case LUA_TTABLE: return hvalue(o);
  -      case LUA_TFUNCTION: return clvalue(o);
  -      case LUA_TTHREAD: return thvalue(o);
  -      case LUA_TUSERDATA:
  -      case LUA_TLIGHTUSERDATA:
  -        return lua_touserdata(L, idx);
  -      default: return NULL;
  -    }
  +  StkId o = index2adr(L, idx);
  +  switch (ttype(o)) {
  +    case LUA_TTABLE: return hvalue(o);
  +    case LUA_TFUNCTION: return clvalue(o);
  +    case LUA_TTHREAD: return thvalue(o);
  +    case LUA_TUSERDATA:
  +    case LUA_TLIGHTUSERDATA:
  +      return lua_touserdata(L, idx);
  +    default: return NULL;
     }
   }
   
  @@ -414,10 +430,18 @@
   }
   
   
  +LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
  +  lua_lock(L);
  +  setnvalue(L->top, cast_num(n));
  +  api_incr_top(L);
  +  lua_unlock(L);
  +}
  +
  +
   LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
     lua_lock(L);
     luaC_checkGC(L);
  -  setsvalue2s(L->top, luaS_newlstr(L, s, len));
  +  setsvalue2s(L, L->top, luaS_newlstr(L, s, len));
     api_incr_top(L);
     lua_unlock(L);
   }
  @@ -460,12 +484,13 @@
     lua_lock(L);
     luaC_checkGC(L);
     api_checknelems(L, n);
  -  cl = luaF_newCclosure(L, n);
  +  cl = luaF_newCclosure(L, n, getcurrenv(L));
     cl->c.f = fn;
     L->top -= n;
     while (n--)
  -    setobj2n(&cl->c.upvalue[n], L->top+n);
  -  setclvalue(L->top, cl);
  +    setobj2n(L, &cl->c.upvalue[n], L->top+n);
  +  setclvalue(L, L->top, cl);
  +  lua_assert(iswhite(obj2gco(cl)));
     api_incr_top(L);
     lua_unlock(L);
   }
  @@ -487,6 +512,15 @@
   }
   
   
  +LUA_API int lua_pushthread (lua_State *L) {
  +  lua_lock(L);
  +  setthvalue(L, L->top, L);
  +  api_incr_top(L);
  +  lua_unlock(L);
  +  return (G(L)->mainthread == L);
  +}
  +
  +
   
   /*
   ** get functions (Lua -> stack)
  @@ -496,8 +530,22 @@
   LUA_API void lua_gettable (lua_State *L, int idx) {
     StkId t;
     lua_lock(L);
  -  t = luaA_index(L, idx);
  -  setobj2s(L->top - 1, luaV_gettable(L, t, L->top - 1, 0));
  +  t = index2adr(L, idx);
  +  api_checkvalidindex(L, t);
  +  luaV_gettable(L, t, L->top - 1, L->top - 1);
  +  lua_unlock(L);
  +}
  +
  +
  +LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
  +  StkId t;
  +  TValue key;
  +  lua_lock(L);
  +  t = index2adr(L, idx);
  +  api_checkvalidindex(L, t);
  +  setsvalue(L, &key, luaS_new(L, k));
  +  luaV_gettable(L, t, &key, L->top);
  +  api_incr_top(L);
     lua_unlock(L);
   }
   
  @@ -505,9 +553,9 @@
   LUA_API void lua_rawget (lua_State *L, int idx) {
     StkId t;
     lua_lock(L);
  -  t = luaA_index(L, idx);
  +  t = index2adr(L, idx);
     api_check(L, ttistable(t));
  -  setobj2s(L->top - 1, luaH_get(hvalue(t), L->top - 1));
  +  setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
     lua_unlock(L);
   }
   
  @@ -515,43 +563,44 @@
   LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
     StkId o;
     lua_lock(L);
  -  o = luaA_index(L, idx);
  +  o = index2adr(L, idx);
     api_check(L, ttistable(o));
  -  setobj2s(L->top, luaH_getnum(hvalue(o), n));
  +  setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
     api_incr_top(L);
     lua_unlock(L);
   }
   
   
  -LUA_API void lua_newtable (lua_State *L) {
  +LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
     lua_lock(L);
     luaC_checkGC(L);
  -  sethvalue(L->top, luaH_new(L, 0, 0));
  +  sethvalue(L, L->top, luaH_new(L, narray, nrec));
     api_incr_top(L);
     lua_unlock(L);
   }
   
   
   LUA_API int lua_getmetatable (lua_State *L, int objindex) {
  -  const TObject *obj;
  +  const TValue *obj;
     Table *mt = NULL;
     int res;
     lua_lock(L);
  -  obj = luaA_indexAcceptable(L, objindex);
  -  if (obj != NULL) {
  -    switch (ttype(obj)) {
  -      case LUA_TTABLE:
  -        mt = hvalue(obj)->metatable;
  -        break;
  -      case LUA_TUSERDATA:
  -        mt = uvalue(obj)->uv.metatable;
  -        break;
  -    }
  +  obj = index2adr(L, objindex);
  +  switch (ttype(obj)) {
  +    case LUA_TTABLE:
  +      mt = hvalue(obj)->metatable;
  +      break;
  +    case LUA_TUSERDATA:
  +      mt = uvalue(obj)->metatable;
  +      break;
  +    default:
  +      mt = G(L)->mt[ttype(obj)];
  +      break;
     }
  -  if (mt == NULL || mt == hvalue(defaultmeta(L)))
  +  if (mt == NULL)
       res = 0;
     else {
  -    sethvalue(L->top, mt);
  +    sethvalue(L, L->top, mt);
       api_incr_top(L);
       res = 1;
     }
  @@ -563,8 +612,22 @@
   LUA_API void lua_getfenv (lua_State *L, int idx) {
     StkId o;
     lua_lock(L);
  -  o = luaA_index(L, idx);
  -  setobj2s(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L));
  +  o = index2adr(L, idx);
  +  api_checkvalidindex(L, o);
  +  switch (ttype(o)) {
  +    case LUA_TFUNCTION:
  +      sethvalue(L, L->top, clvalue(o)->c.env);
  +      break;
  +    case LUA_TUSERDATA:
  +      sethvalue(L, L->top, uvalue(o)->env);
  +      break;
  +    case LUA_TTHREAD:
  +      setobj2s(L, L->top,  gt(thvalue(o)));
  +      break;
  +    default:
  +      setnilvalue(L->top);
  +      break;
  +  }
     api_incr_top(L);
     lua_unlock(L);
   }
  @@ -579,20 +642,36 @@
     StkId t;
     lua_lock(L);
     api_checknelems(L, 2);
  -  t = luaA_index(L, idx);
  +  t = index2adr(L, idx);
  +  api_checkvalidindex(L, t);
     luaV_settable(L, t, L->top - 2, L->top - 1);
     L->top -= 2;  /* pop index and value */
     lua_unlock(L);
   }
   
   
  +LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
  +  StkId t;
  +  TValue key;
  +  lua_lock(L);
  +  api_checknelems(L, 1);
  +  t = index2adr(L, idx);
  +  api_checkvalidindex(L, t);
  +  setsvalue(L, &key, luaS_new(L, k));
  +  luaV_settable(L, t, &key, L->top - 1);
  +  L->top--;  /* pop value */
  +  lua_unlock(L);
  +}
  +
  +
   LUA_API void lua_rawset (lua_State *L, int idx) {
     StkId t;
     lua_lock(L);
     api_checknelems(L, 2);
  -  t = luaA_index(L, idx);
  +  t = index2adr(L, idx);
     api_check(L, ttistable(t));
  -  setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1);  /* write barrier */
  +  setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);
  +  luaC_barriert(L, hvalue(t), L->top-1);
     L->top -= 2;
     lua_unlock(L);
   }
  @@ -602,54 +681,76 @@
     StkId o;
     lua_lock(L);
     api_checknelems(L, 1);
  -  o = luaA_index(L, idx);
  +  o = index2adr(L, idx);
     api_check(L, ttistable(o));
  -  setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1);  /* write barrier */
  +  setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
  +  luaC_barriert(L, hvalue(o), L->top-1);
     L->top--;
     lua_unlock(L);
   }
   
   
   LUA_API int lua_setmetatable (lua_State *L, int objindex) {
  -  TObject *obj, *mt;
  -  int res = 1;
  +  TValue *obj;
  +  Table *mt;
     lua_lock(L);
     api_checknelems(L, 1);
  -  obj = luaA_index(L, objindex);
  -  mt = (!ttisnil(L->top - 1)) ? L->top - 1 : defaultmeta(L);
  -  api_check(L, ttistable(mt));
  +  obj = index2adr(L, objindex);
  +  api_checkvalidindex(L, obj);
  +  if (ttisnil(L->top - 1))
  +    mt = NULL;
  +  else {
  +    api_check(L, ttistable(L->top - 1));
  +    mt = hvalue(L->top - 1);
  +  }
     switch (ttype(obj)) {
       case LUA_TTABLE: {
  -      hvalue(obj)->metatable = hvalue(mt);  /* write barrier */
  +      hvalue(obj)->metatable = mt;
  +      if (mt)
  +        luaC_objbarriert(L, hvalue(obj), mt);
         break;
       }
       case LUA_TUSERDATA: {
  -      uvalue(obj)->uv.metatable = hvalue(mt);  /* write barrier */
  +      uvalue(obj)->metatable = mt;
  +      if (mt)
  +        luaC_objbarrier(L, rawuvalue(obj), mt);
         break;
       }
       default: {
  -      res = 0;  /* cannot set */
  +      G(L)->mt[ttype(obj)] = mt;
         break;
       }
     }
     L->top--;
     lua_unlock(L);
  -  return res;
  +  return 1;
   }
   
   
   LUA_API int lua_setfenv (lua_State *L, int idx) {
     StkId o;
  -  int res = 0;
  +  int res = 1;
     lua_lock(L);
     api_checknelems(L, 1);
  -  o = luaA_index(L, idx);
  -  L->top--;
  -  api_check(L, ttistable(L->top));
  -  if (isLfunction(o)) {
  -    res = 1;
  -    clvalue(o)->l.g = *(L->top);
  +  o = index2adr(L, idx);
  +  api_checkvalidindex(L, o);
  +  api_check(L, ttistable(L->top - 1));
  +  switch (ttype(o)) {
  +    case LUA_TFUNCTION:
  +      clvalue(o)->c.env = hvalue(L->top - 1);
  +      break;
  +    case LUA_TUSERDATA:
  +      uvalue(o)->env = hvalue(L->top - 1);
  +      break;
  +    case LUA_TTHREAD:
  +      sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1));
  +      break;
  +    default:
  +      res = 0;
  +      break;
     }
  +  luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));
  +  L->top--;
     lua_unlock(L);
     return res;
   }
  @@ -659,12 +760,23 @@
   ** `load' and `call' functions (run Lua code)
   */
   
  +
  +#define adjustresults(L,nres) \
  +    { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; }
  +
  +
  +#define checkresults(L,na,nr) \
  +     api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)))
  +	
  +
   LUA_API void lua_call (lua_State *L, int nargs, int nresults) {
     StkId func;
     lua_lock(L);
     api_checknelems(L, nargs+1);
  +  checkresults(L, nargs, nresults);
     func = L->top - (nargs+1);
     luaD_call(L, func, nresults);
  +  adjustresults(L, nresults);
     lua_unlock(L);
   }
   
  @@ -674,15 +786,12 @@
   ** Execute a protected call.
   */
   struct CallS {  /* data to `f_call' */
  -/*@dependent@*/
     StkId func;
     int nresults;
   };
   
   
  -static void f_call (lua_State *L, void *ud)
  -	/*@modifies L @*/
  -{
  +static void f_call (lua_State *L, void *ud) {
     struct CallS *c = cast(struct CallS *, ud);
     luaD_call(L, c->func, c->nresults);
   }
  @@ -694,10 +803,19 @@
     int status;
     ptrdiff_t func;
     lua_lock(L);
  -  func = (errfunc == 0) ? 0 : savestack(L, luaA_index(L, errfunc));
  +  api_checknelems(L, nargs+1);
  +  checkresults(L, nargs, nresults);
  +  if (errfunc == 0)
  +    func = 0;
  +  else {
  +    StkId o = index2adr(L, errfunc);
  +    api_checkvalidindex(L, o);
  +    func = savestack(L, o);
  +  }
     c.func = L->top - (nargs+1);  /* function to be called */
     c.nresults = nresults;
     status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
  +  adjustresults(L, nresults);
     lua_unlock(L);
     return status;
   }
  @@ -712,17 +830,15 @@
   };
   
   
  -static void f_Ccall (lua_State *L, void *ud)
  -	/*@modifies L @*/
  -{
  +static void f_Ccall (lua_State *L, void *ud) {
     struct CCallS *c = cast(struct CCallS *, ud);
     Closure *cl;
  -  cl = luaF_newCclosure(L, 0);
  +  cl = luaF_newCclosure(L, 0, getcurrenv(L));
     cl->c.f = c->func;
  -  setclvalue(L->top, cl);  /* push function */
  -  incr_top(L);
  +  setclvalue(L, L->top, cl);  /* push function */
  +  api_incr_top(L);
     setpvalue(L->top, c->ud);  /* push only argument */
  -  incr_top(L);
  +  api_incr_top(L);
     luaD_call(L, L->top - 2, 0);
   }
   
  @@ -739,72 +855,98 @@
   }
   
   
  -LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
  +LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
                         const char *chunkname) {
     ZIO z;
     int status;
  -  int c;
     lua_lock(L);
     if (!chunkname) chunkname = "?";
  -  luaZ_init(&z, reader, data, chunkname);
  -  c = luaZ_lookahead(&z);
  -  status = luaD_protectedparser(L, &z, (c == LUA_SIGNATURE[0]));
  +  luaZ_init(L, &z, reader, data);
  +  status = luaD_protectedparser(L, &z, chunkname);
     lua_unlock(L);
     return status;
   }
   
   
  -LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) {
  +LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {
     int status;
  -  TObject *o;
  +  TValue *o;
     lua_lock(L);
     api_checknelems(L, 1);
     o = L->top - 1;
  -  if (isLfunction(o) && clvalue(o)->l.nupvalues == 0) {
  -    luaU_dump(L, clvalue(o)->l.p, writer, data);
  -    status = 1;
  -  }
  +  if (isLfunction(o))
  +    status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0);
     else
  -    status = 0;
  +    status = 1;
     lua_unlock(L);
     return status;
   }
   
   
  -/*
  -** Garbage-collection functions
  -*/
  +LUA_API int  lua_status (lua_State *L) {
  +  return L->status;
  +}
   
  -/* GC values are expressed in Kbytes: #bytes/2^10 */
  -#define GCscalel(x)		((x)>>10)
  -#define GCscale(x)		(cast(int, GCscalel(x)))
  -#define GCunscale(x)		(cast(lu_mem, x)<<10)
   
  -LUA_API int lua_getgcthreshold (lua_State *L) {
  -  int threshold;
  -  lua_lock(L);
  -  threshold = GCscale(G(L)->GCthreshold);
  -  lua_unlock(L);
  -  return threshold;
  -}
  +/*
  +** Garbage-collection function
  +*/
   
  -LUA_API int lua_getgccount (lua_State *L) {
  -  int count;
  +LUA_API int lua_gc (lua_State *L, int what, int data) {
  +  int res = 0;
  +  global_State *g;
     lua_lock(L);
  -  count = GCscale(G(L)->nblocks);
  +  g = G(L);
  +  switch (what) {
  +    case LUA_GCSTOP: {
  +      g->GCthreshold = MAX_LUMEM;
  +      break;
  +    }
  +    case LUA_GCRESTART: {
  +      g->GCthreshold = g->totalbytes;
  +      break;
  +    }
  +    case LUA_GCCOLLECT: {
  +      luaC_fullgc(L);
  +      break;
  +    }
  +    case LUA_GCCOUNT: {
  +      /* GC values are expressed in Kbytes: #bytes/2^10 */
  +      res = cast_int(g->totalbytes >> 10);
  +      break;
  +    }
  +    case LUA_GCCOUNTB: {
  +      res = cast_int(g->totalbytes & 0x3ff);
  +      break;
  +    }
  +    case LUA_GCSTEP: {
  +      lu_mem a = (cast(lu_mem, data) << 10);
  +      if (a <= g->totalbytes)
  +        g->GCthreshold = g->totalbytes - a;
  +      else
  +        g->GCthreshold = 0;
  +      while (g->GCthreshold <= g->totalbytes)
  +        luaC_step(L);
  +      if (g->gcstate == GCSpause)  /* end of cycle? */
  +        res = 1;  /* signal it */
  +      break;
  +    }
  +    case LUA_GCSETPAUSE: {
  +      res = g->gcpause;
  +      g->gcpause = data;
  +      break;
  +    }
  +    case LUA_GCSETSTEPMUL: {
  +      res = g->gcstepmul;
  +      g->gcstepmul = data;
  +      break;
  +    }
  +    default: res = -1;  /* invalid option */
  +  }
     lua_unlock(L);
  -  return count;
  +  return res;
   }
   
  -LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
  -  lua_lock(L);
  -  if (cast(lu_mem, newthreshold) > GCscalel(MAX_LUMEM))
  -    G(L)->GCthreshold = MAX_LUMEM;
  -  else
  -    G(L)->GCthreshold = GCunscale(newthreshold);
  -  luaC_checkGC(L);
  -  lua_unlock(L);
  -}
   
   
   /*
  @@ -812,11 +954,6 @@
   */
   
   
  -LUA_API const char *lua_version (void) {
  -  return LUA_VERSION;
  -}
  -
  -
   LUA_API int lua_error (lua_State *L) {
     lua_lock(L);
     api_checknelems(L, 1);
  @@ -830,7 +967,7 @@
     StkId t;
     int more;
     lua_lock(L);
  -  t = luaA_index(L, idx);
  +  t = index2adr(L, idx);
     api_check(L, ttistable(t));
     more = luaH_next(L, hvalue(t), L->top - 1);
     if (more) {
  @@ -845,14 +982,14 @@
   
   LUA_API void lua_concat (lua_State *L, int n) {
     lua_lock(L);
  -  luaC_checkGC(L);
     api_checknelems(L, n);
     if (n >= 2) {
  -    luaV_concat(L, n, L->top - L->base - 1);
  +    luaC_checkGC(L);
  +    luaV_concat(L, n, cast_int(L->top - L->base) - 1);
       L->top -= (n-1);
     }
     else if (n == 0) {  /* push empty string */
  -    setsvalue2s(L->top, luaS_newlstr(L, NULL, 0));
  +    setsvalue2s(L, L->top, luaS_newlstr(L, "", 0));
       api_incr_top(L);
     }
     /* else n == 1; nothing to do */
  @@ -860,57 +997,51 @@
   }
   
   
  +LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {
  +  lua_Alloc f;
  +  lua_lock(L);
  +  if (ud) *ud = G(L)->ud;
  +  f = G(L)->frealloc;
  +  lua_unlock(L);
  +  return f;
  +}
  +
  +
  +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
  +  lua_lock(L);
  +  G(L)->ud = ud;
  +  G(L)->frealloc = f;
  +  lua_unlock(L);
  +}
  +
  +
   LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
     Udata *u;
     lua_lock(L);
     luaC_checkGC(L);
  -  u = luaS_newudata(L, size);
  -  setuvalue(L->top, u);
  +  u = luaS_newudata(L, size, getcurrenv(L));
  +  setuvalue(L, L->top, u);
     api_incr_top(L);
     lua_unlock(L);
  -/*@-kepttrans@*/
     return u + 1;
  -/*@=kepttrans@*/
   }
   
   
  -LUA_API int lua_pushupvalues (lua_State *L) {
  -  Closure *func;
  -  int n, i;
  -  lua_lock(L);
  -  api_check(L, iscfunction(L->base - 1));
  -  func = clvalue(L->base - 1);
  -  n = func->c.nupvalues;
  -  luaD_checkstack(L, n + LUA_MINSTACK);
  -  for (i=0; i<n; i++) {
  -    setobj2s(L->top, &func->c.upvalue[i]);
  -    L->top++;
  -  }
  -  lua_unlock(L);
  -  return n;
  -}
   
   
  -/*@observer@*/ /*@null@*/
  -static const char *aux_upvalue (lua_State *L, int funcindex, int n,
  -                                TObject **val)
  -	/*@modifies *val @*/
  -{
  +static const char *aux_upvalue (StkId fi, int n, TValue **val) {
     Closure *f;
  -  StkId fi = luaA_index(L, funcindex);
     if (!ttisfunction(fi)) return NULL;
     f = clvalue(fi);
     if (f->c.isC) {
  -    if (n > f->c.nupvalues) return NULL;
  +    if (!(1 <= n && n <= f->c.nupvalues)) return NULL;
       *val = &f->c.upvalue[n-1];
       return "";
     }
     else {
       Proto *p = f->l.p;
  -    if (n > p->sizeupvalues) return NULL;
  -/*@-onlytrans@*/
  +    if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
       *val = f->l.upvals[n-1]->v;
  -/*@=onlytrans@*/
       return getstr(p->upvalues[n-1]);
     }
   }
  @@ -918,11 +1049,11 @@
   
   LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
     const char *name;
  -  TObject *val;
  +  TValue *val;
     lua_lock(L);
  -  name = aux_upvalue(L, funcindex, n, &val);
  +  name = aux_upvalue(index2adr(L, funcindex), n, &val);
     if (name) {
  -    setobj2s(L->top, val);
  +    setobj2s(L, L->top, val);
       api_incr_top(L);
     }
     lua_unlock(L);
  @@ -932,13 +1063,16 @@
   
   LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
     const char *name;
  -  TObject *val;
  +  TValue *val;
  +  StkId fi;
     lua_lock(L);
  +  fi = index2adr(L, funcindex);
     api_checknelems(L, 1);
  -  name = aux_upvalue(L, funcindex, n, &val);
  +  name = aux_upvalue(fi, n, &val);
     if (name) {
       L->top--;
  -    setobj(val, L->top);  /* write barrier */
  +    setobj(L, val, L->top);
  +    luaC_barrier(L, clvalue(fi), L->top);
     }
     lua_unlock(L);
     return name;
  @@ .
  patch -p0 <<'@@ .'
  Index: lua/lapi.h
  ============================================================================
  $ cvs diff -u -r1.2 -r1.3 lapi.h
  --- lua/lapi.h	23 Mar 2004 05:09:14 -0000	1.2
  +++ lua/lapi.h	15 Jul 2007 17:56:10 -0000	1.3
  @@ -1,5 +1,5 @@
   /*
  -** $Id: lapi.h,v 1.2 2004/03/23 05:09:14 jbj Exp $
  +** $Id: lapi.h,v 1.3 2007/07/15 17:56:10 rse Exp $
   ** Auxiliary functions from Lua API
   ** See Copyright Notice in lua.h
   */
  @@ -11,7 +11,6 @@
   #include "lobject.h"
   
   
  -void luaA_pushobject (lua_State *L, const TObject *o)
  -	/*@modifies L @*/;
  +LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
   
   #endif
  @@ .
  patch -p0 <<'@@ .'
  Index: lua/lauxlib.c
  ============================================================================
  $ cvs diff -u -r0 -r1.1 lauxlib.c
  --- /dev/null	2007-07-15 19:55:00 +0200
  +++ lauxlib.c	2007-07-15 19:56:11 +0200
  @@ -0,0 +1,653 @@
  +/*
  +** $Id: lauxlib.c,v 1.1 2007/07/15 17:56:10 rse Exp $
  +** Auxiliary functions for building Lua libraries
  +** See Copyright Notice in lua.h
  +*/
  +
  +
  +#include <ctype.h>
  +#include <errno.h>
  +#include <stdarg.h>
  +#include <stdio.h>
  +#include <stdlib.h>
  +#include <string.h>
  +
  +
  +/* This file uses only the official API of Lua.
  +** Any function declared here could be written as an application function.
  +*/
  +
  +#define lauxlib_c
  +#define LUA_LIB
  +
  +#include "lua.h"
  +
  +#include "lauxlib.h"
  +
  +
  +#define FREELIST_REF	0	/* free list of references */
  +
  +
  +/* convert a stack index to positive */
  +#define abs_index(L, i)		((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
  +					lua_gettop(L) + (i) + 1)
  +
  +
  +/*
  +** {======================================================
  +** Error-report functions
  +** =======================================================
  +*/
  +
  +
  +LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
  +  lua_Debug ar;
  +  if (!lua_getstack(L, 0, &ar))  /* no stack frame? */
  +    return luaL_error(L, "bad argument #%d (%s)", narg, extramsg);
  +  lua_getinfo(L, "n", &ar);
  +  if (strcmp(ar.namewhat, "method") == 0) {
  +    narg--;  /* do not count `self' */
  +    if (narg == 0)  /* error is in the self argument itself? */
  +      return luaL_error(L, "calling " LUA_QS " on bad self (%s)",
  +                           ar.name, extramsg);
  +  }
  +  if (ar.name == NULL)
  +    ar.name = "?";
  +  return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
  +                        narg, ar.name, extramsg);
  +}
  +
  +
  +LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {
  +  const char *msg = lua_pushfstring(L, "%s expected, got %s",
  +                                    tname, luaL_typename(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, "Sl", &ar);  /* get info about it */
  +    if (ar.currentline > 0) {  /* is there info? */
  +      lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
  +      return;
  +    }
  +  }
  +  lua_pushliteral(L, "");  /* else, no information available... */
  +}
  +
  +
  +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_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;
  +  for (i=0; lst[i]; i++)
  +    if (strcmp(lst[i], name) == 0)
  +      return i;
  +  return luaL_argerror(L, narg,
  +                       lua_pushfstring(L, "invalid option " LUA_QS, name));
  +}
  +
  +
  +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
  +  lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get registry.name */
  +  if (!lua_isnil(L, -1))  /* name already in use? */
  +    return 0;  /* leave previous value on top, but return 0 */
  +  lua_pop(L, 1);
  +  lua_newtable(L);  /* create metatable */
  +  lua_pushvalue(L, -1);
  +  lua_setfield(L, LUA_REGISTRYINDEX, tname);  /* registry.name = metatable */
  +  return 1;
  +}
  +
  +
  +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
  +  void *p = lua_touserdata(L, ud);
  +  if (p != NULL) {  /* value is a userdata? */
  +    if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */
  +      lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get correct metatable */
  +      if (lua_rawequal(L, -1, -2)) {  /* does it have the correct mt? */
  +        lua_pop(L, 2);  /* remove both metatables */
  +        return p;
  +      }
  +    }
  +  }
  +  luaL_typerror(L, ud, tname);  /* else error */
  +  return NULL;  /* to avoid warnings */
  +}
  +
  +
  +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_tolstring(L, narg, len);
  +  if (!s) tag_error(L, narg, LUA_TSTRING);
  +  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) {
  +  return luaL_opt(L, luaL_checknumber, narg, def);
  +}
  +
  +
  +LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
  +  lua_Integer d = lua_tointeger(L, narg);
  +  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */
  +    tag_error(L, narg, LUA_TNUMBER);
  +  return d;
  +}
  +
  +
  +LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
  +                                                      lua_Integer def) {
  +  return luaL_opt(L, luaL_checkinteger, narg, def);
  +}
  +
  +
  +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_register) (lua_State *L, const char *libname,
  +                                const luaL_Reg *l) {
  +  luaI_openlib(L, libname, l, 0);
  +}
  +
  +
  +static int libsize (const luaL_Reg *l) {
  +  int size = 0;
  +  for (; l->name; l++) size++;
  +  return size;
  +}
  +
  +
  +LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
  +                              const luaL_Reg *l, int nup) {
  +  if (libname) {
  +    int size = libsize(l);
  +    /* check whether lib already exists */
  +    luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", size);
  +    lua_getfield(L, -1, libname);  /* get _LOADED[libname] */
  +    if (!lua_istable(L, -1)) {  /* not found? */
  +      lua_pop(L, 1);  /* remove previous result */
  +      /* try global variable (and create one if it does not exist) */
  +      if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
  +        luaL_error(L, "name conflict for module " LUA_QS, libname);
  +      lua_pushvalue(L, -1);
  +      lua_setfield(L, -3, libname);  /* _LOADED[libname] = new table */
  +    }
  +    lua_remove(L, -2);  /* remove _LOADED table */
  +    lua_insert(L, -(nup+1));  /* move library table to below upvalues */
  +  }
  +  for (; l->name; l++) {
  +    int i;
  +    for (i=0; i<nup; i++)  /* copy upvalues to the top */
  +      lua_pushvalue(L, -nup);
  +    lua_pushcclosure(L, l->func, nup);
  +    lua_setfield(L, -(nup+2), l->name);
  +  }
  +  lua_pop(L, nup);  /* remove upvalues */
  +}
  +
  +
  +
  +/*
  +** {======================================================
  +** getn-setn: size for arrays
  +** =======================================================
  +*/
  +
  +#if defined(LUA_COMPAT_GETN)
  +
  +static int checkint (lua_State *L, int topop) {
  +  int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;
  +  lua_pop(L, topop);
  +  return n;
  +}
  +
  +
  +static void getsizes (lua_State *L) {
  +  lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES");
  +  if (lua_isnil(L, -1)) {  /* no `size' table? */
  +    lua_pop(L, 1);  /* remove nil */
  +    lua_newtable(L);  /* create it */
  +    lua_pushvalue(L, -1);  /* `size' will be its own metatable */
  +    lua_setmetatable(L, -2);
  +    lua_pushliteral(L, "kv");
  +    lua_setfield(L, -2, "__mode");  /* metatable(N).__mode = "kv" */
  +    lua_pushvalue(L, -1);
  +    lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES");  /* store in register */
  +  }
  +}
  +
  +
  +LUALIB_API 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_pushinteger(L, n);
  +    lua_rawset(L, t);
  +  }
  +  else {  /* use `sizes' */
  +    getsizes(L);
  +    lua_pushvalue(L, t);
  +    lua_pushinteger(L, n);
  +    lua_rawset(L, -3);  /* sizes[t] = n */
  +    lua_pop(L, 1);  /* remove `sizes' */
  +  }
  +}
  +
  +
  +LUALIB_API 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;
  +  return (int)lua_objlen(L, t);
  +}
  +
  +#endif
  +
  +/* }====================================================== */
  +
  +
  +
  +LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
  +                                                               const char *r) {
  +  const char *wild;
  +  size_t l = strlen(p);
  +  luaL_Buffer b;
  +  luaL_buffinit(L, &b);
  +  while ((wild = strstr(s, p)) != NULL) {
  +    luaL_addlstring(&b, s, wild - s);  /* push prefix */
  +    luaL_addstring(&b, r);  /* push replacement in place of pattern */
  +    s = wild + l;  /* continue after `p' */
  +  }
  +  luaL_addstring(&b, s);  /* push last suffix */
  +  luaL_pushresult(&b);
  +  return lua_tostring(L, -1);
  +}
  +
  +
  +LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
  +                                       const char *fname, int szhint) {
  +  const char *e;
  +  lua_pushvalue(L, idx);
  +  do {
  +    e = strchr(fname, '.');
  +    if (e == NULL) e = fname + strlen(fname);
  +    lua_pushlstring(L, fname, e - fname);
  +    lua_rawget(L, -2);
  +    if (lua_isnil(L, -1)) {  /* no such field? */
  +      lua_pop(L, 1);  /* remove this nil */
  +      lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
  +      lua_pushlstring(L, fname, e - fname);
  +      lua_pushvalue(L, -2);
  +      lua_settable(L, -4);  /* set new table into field */
  +    }
  +    else if (!lua_istable(L, -1)) {  /* field has a non-table value? */
  +      lua_pop(L, 2);  /* remove table and value */
  +      return fname;  /* return problematic part of the name */
  +    }
  +    lua_remove(L, -2);  /* remove previous table */
  +    fname = e + 1;
  +  } while (*e == '.');
  +  return NULL;
  +}
  +
  +
  +
  +/*
  +** {======================================================
  +** Generic Buffer manipulation
  +** =======================================================
  +*/
  +
  +
  +#define bufflen(B)	((B)->p - (B)->buffer)
  +#define bufffree(B)	((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
  +
  +#define LIMIT	(LUA_MINSTACK/2)
  +
  +
  +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_addchar(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;
  +  const char *s = lua_tolstring(L, -1, &vl);
  +  if (vl <= bufffree(B)) {  /* fit into buffer? */
  +    memcpy(B->p, s, vl);  /* put it there */
  +    B->p += vl;
  +    lua_pop(L, 1);  /* remove from stack */
  +  }
  +  else {
  +    if (emptybuffer(B))
  +      lua_insert(L, -2);  /* put buffer before new value */
  +    B->lvl++;  /* add new value into B stack */
  +    adjuststack(B);
  +  }
  +}
  +
  +
  +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_tointeger(L, -1);  /* ref = t[FREELIST_REF] */
  +  lua_pop(L, 1);  /* remove it from stack */
  +  if (ref != 0) {  /* any free element? */
  +    lua_rawgeti(L, t, ref);  /* remove it from list */
  +    lua_rawseti(L, t, FREELIST_REF);  /* (t[FREELIST_REF] = t[ref]) */
  +  }
  +  else {  /* no free elements */
  +    ref = (int)lua_objlen(L, t);
  +    ref++;  /* create new reference */
  +  }
  +  lua_rawseti(L, t, ref);
  +  return ref;
  +}
  +
  +
  +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_pushinteger(L, ref);
  +    lua_rawseti(L, t, FREELIST_REF);  /* t[FREELIST_REF] = ref */
  +  }
  +}
  +
  +
  +
  +/*
  +** {======================================================
  +** Load functions
  +** =======================================================
  +*/
  +
  +typedef struct LoadF {
  +  int extraline;
  +  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 (lf->extraline) {
  +    lf->extraline = 0;
  +    *size = 1;
  +    return "\n";
  +  }
  +  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, const char *what, int fnameindex) {
  +  const char *serr = strerror(errno);
  +  const char *filename = lua_tostring(L, fnameindex) + 1;
  +  lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
  +  lua_remove(L, fnameindex);
  +  return LUA_ERRFILE;
  +}
  +
  +
  +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 */
  +  lf.extraline = 0;
  +  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, "open", fnameindex);
  +  }
  +  c = getc(lf.f);
  +  if (c == '#') {  /* Unix exec. file? */
  +    lf.extraline = 1;
  +    while ((c = getc(lf.f)) != EOF && c != '\n') ;  /* skip first line */
  +    if (c == '\n') c = getc(lf.f);
  +  }
  +  if (c == LUA_SIGNATURE[0] && lf.f != stdin) {  /* binary file? */
  +    fclose(lf.f);
  +    lf.f = fopen(filename, "rb");  /* reopen in binary mode */
  +    if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
  +    /* skip eventual `#!...' */
  +   while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
  +    lf.extraline = 0;
  +  }
  +  ungetc(c, lf.f);
  +  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, "read", 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);
  +}
  +
  +
  +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) {
  +  return luaL_loadbuffer(L, s, strlen(s), s);
  +}
  +
  +
  +
  +/* }====================================================== */
  +
  +
  +static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
  +  (void)ud;
  +  (void)osize;
  +  if (nsize == 0) {
  +    free(ptr);
  +    return NULL;
  +  }
  +  else
  +    return realloc(ptr, nsize);
  +}
  +
  +
  +static int panic (lua_State *L) {
  +  (void)L;  /* to avoid warnings */
  +  fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
  +                   lua_tostring(L, -1));
  +  return 0;
  +}
  +
  +
  +LUALIB_API lua_State *luaL_newstate (void) {
  +  lua_State *L = lua_newstate(l_alloc, NULL);
  +  if (L) lua_atpanic(L, &panic);
  +  return L;
  +}
  +
  @@ .
  patch -p0 <<'@@ .'
  Index: lua/lauxlib.h
  ============================================================================
  $ cvs diff -u -r0 -r1.1 lauxlib.h
  --- /dev/null	2007-07-15 19:55:00 +0200
  +++ lauxlib.h	2007-07-15 19:56:11 +0200
  @@ -0,0 +1,174 @@
  +/*
  +** $Id: lauxlib.h,v 1.1 2007/07/15 17:56:10 rse Exp $
  +** Auxiliary functions for building Lua libraries
  +** See Copyright Notice in lua.h
  +*/
  +
  +
  +#ifndef lauxlib_h
  +#define lauxlib_h
  +
  +
  +#include <stddef.h>
  +#include <stdio.h>
  +
  +#include "lua.h"
  +
  +
  +#if defined(LUA_COMPAT_GETN)
  +LUALIB_API int (luaL_getn) (lua_State *L, int t);
  +LUALIB_API void (luaL_setn) (lua_State *L, int t, int n);
  +#else
  +#define luaL_getn(L,i)          ((int)lua_objlen(L, i))
  +#define luaL_setn(L,i,j)        ((void)0)  /* no op! */
  +#endif
  +
  +#if defined(LUA_COMPAT_OPENLIB)
  +#define luaI_openlib	luaL_openlib
  +#endif
  +
  +
  +/* extra error code for `luaL_load' */
  +#define LUA_ERRFILE     (LUA_ERRERR+1)
  +
  +
  +typedef struct luaL_Reg {
  +  const char *name;
  +  lua_CFunction func;
  +} luaL_Reg;
  +
  +
  +
  +LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,
  +                                const luaL_Reg *l, int nup);
  +LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
  +                                const luaL_Reg *l);
  +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
  +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
  +LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
  +LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
  +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
  +                                                          size_t *l);
  +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
  +                                          const char *def, size_t *l);
  +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
  +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
  +
  +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
  +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
  +                                          lua_Integer def);
  +
  +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
  +LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
  +LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
  +
  +LUALIB_API int   (luaL_newmetatable) (lua_State *L, const char *tname);
  +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
  +
  +LUALIB_API void (luaL_where) (lua_State *L, int lvl);
  +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
  +
  +LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
  +                                   const char *const lst[]);
  +
  +LUALIB_API int (luaL_ref) (lua_State *L, int t);
  +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
  +
  +LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
  +LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
  +                                  const char *name);
  +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
  +
  +LUALIB_API lua_State *(luaL_newstate) (void);
  +
  +
  +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
  +                                                  const char *r);
  +
  +LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
  +                                         const char *fname, int szhint);
  +
  +
  +
  +
  +/*
  +** ===============================================================
  +** some useful macros
  +** ===============================================================
  +*/
  +
  +#define luaL_argcheck(L, cond,numarg,extramsg)	\
  +		((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
  +#define luaL_checkstring(L,n)	(luaL_checklstring(L, (n), NULL))
  +#define luaL_optstring(L,n,d)	(luaL_optlstring(L, (n), (d), NULL))
  +#define luaL_checkint(L,n)	((int)luaL_checkinteger(L, (n)))
  +#define luaL_optint(L,n,d)	((int)luaL_optinteger(L, (n), (d)))
  +#define luaL_checklong(L,n)	((long)luaL_checkinteger(L, (n)))
  +#define luaL_optlong(L,n,d)	((long)luaL_optinteger(L, (n), (d)))
  +
  +#define luaL_typename(L,i)	lua_typename(L, lua_type(L,(i)))
  +
  +#define luaL_dofile(L, fn) \
  +	(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
  +
  +#define luaL_dostring(L, s) \
  +	(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
  +
  +#define luaL_getmetatable(L,n)	(lua_getfield(L, LUA_REGISTRYINDEX, (n)))
  +
  +#define luaL_opt(L,f,n,d)	(lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
  +
  +/*
  +** {======================================================
  +** Generic Buffer manipulation
  +** =======================================================
  +*/
  +
  +
  +
  +typedef struct luaL_Buffer {
  +  char *p;			/* current position in buffer */
  +  int lvl;  /* number of strings in the stack (level) */
  +  lua_State *L;
  +  char buffer[LUAL_BUFFERSIZE];
  +} luaL_Buffer;
  +
  +#define luaL_addchar(B,c) \
  +  ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
  +   (*(B)->p++ = (char)(c)))
  +
  +/* compatibility only */
  +#define luaL_putchar(B,c)	luaL_addchar(B,c)
  +
  +#define luaL_addsize(B,n)	((B)->p += (n))
  +
  +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
  +LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);
  +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
  +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
  +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
  +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
  +
  +
  +/* }====================================================== */
  +
  +
  +/* compatibility with ref system */
  +
  +/* pre-defined references */
  +#define LUA_NOREF       (-2)
  +#define LUA_REFNIL      (-1)
  +
  +#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
  +      (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
  +
  +#define lua_unref(L,ref)        luaL_unref(L, LUA_REGISTRYINDEX, (ref))
  +
  +#define lua_getref(L,ref)       lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))
  +
  +
  +#define luaL_reg	luaL_Reg
  +
  +#endif
  +
  +
  @@ .
  patch -p0 <<'@@ .'
  Index: lua/lbaselib.c
  ============================================================================
  $ cvs diff -u -r0 -r1.1 lbaselib.c
  --- /dev/null	2007-07-15 19:55:00 +0200
  +++ lbaselib.c	2007-07-15 19:56:11 +0200
  @@ -0,0 +1,643 @@
  +/*
  +** $Id: lbaselib.c,v 1.1 2007/07/15 17:56:10 rse Exp $
  +** Basic library
  +** See Copyright Notice in lua.h
  +*/
  +
  +
  +
  +#include <ctype.h>
  +#include <stdio.h>
  +#include <stdlib.h>
  +#include <string.h>
  +
  +#define lbaselib_c
  +#define LUA_LIB
  +
  +#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, LUA_QL("tostring") " must return a string to "
  +                           LUA_QL("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);
  +  lua_settop(L, 1);
  +  if (lua_isstring(L, 1) && level > 0) {  /* 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, int opt) {
  +  if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
  +  else {
  +    lua_Debug ar;
  +    int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 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 luaB_getfenv (lua_State *L) {
  +  getfunc(L, 1);
  +  if (lua_iscfunction(L, -1))  /* is a C function? */
  +    lua_pushvalue(L, LUA_GLOBALSINDEX);  /* return the thread's global env. */
  +  else
  +    lua_getfenv(L, -1);
  +  return 1;
  +}
  +
  +
  +static int luaB_setfenv (lua_State *L) {
  +  luaL_checktype(L, 2, LUA_TTABLE);
  +  getfunc(L, 0);
  +  lua_pushvalue(L, 2);
  +  if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
  +    /* change environment of current thread */
  +    lua_pushthread(L);
  +    lua_insert(L, -2);
  +    lua_setfenv(L, -2);
  +    return 0;
  +  }
  +  else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
  +    luaL_error(L,
  +          LUA_QL("setfenv") " cannot change environment of given object");
  +  return 1;
  +}
  +
  +
  +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_settop(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_settop(L, 3);
  +  lua_rawset(L, 1);
  +  return 1;
  +}
  +
  +
  +static int luaB_gcinfo (lua_State *L) {
  +  lua_pushinteger(L, lua_getgccount(L));
  +  return 1;
  +}
  +
  +
  +static int luaB_collectgarbage (lua_State *L) {
  +  static const char *const opts[] = {"stop", "restart", "collect",
  +    "count", "step", "setpause", "setstepmul", NULL};
  +  static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
  +    LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
  +  int o = luaL_checkoption(L, 1, "collect", opts);
  +  int ex = luaL_optint(L, 2, 0);
  +  int res = lua_gc(L, optsnum[o], ex);
  +  switch (optsnum[o]) {
  +    case LUA_GCCOUNT: {
  +      int b = lua_gc(L, LUA_GCCOUNTB, 0);
  +      lua_pushnumber(L, res + ((lua_Number)b/1024));
  +      return 1;
  +    }
  +    case LUA_GCSTEP: {
  +      lua_pushboolean(L, res);
  +      return 1;
  +    }
  +    default: {
  +      lua_pushnumber(L, res);
  +      return 1;
  +    }
  +  }
  +}
  +
  +
  +static int luaB_type (lua_State *L) {
  +  luaL_checkany(L, 1);
  +  lua_pushstring(L, luaL_typename(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_pushvalue(L, lua_upvalueindex(1));  /* return generator, */
  +  lua_pushvalue(L, 1);  /* state, */
  +  lua_pushnil(L);  /* and initial value */
  +  return 3;
  +}
  +
  +
  +static int ipairsaux (lua_State *L) {
  +  int i = luaL_checkint(L, 2);
  +  luaL_checktype(L, 1, LUA_TTABLE);
  +  i++;  /* next value */
  +  lua_pushinteger(L, i);
  +  lua_rawgeti(L, 1, i);
  +  return (lua_isnil(L, -1)) ? 0 : 2;
  +}
  +
  +
  +static int luaB_ipairs (lua_State *L) {
  +  luaL_checktype(L, 1, LUA_TTABLE);
  +  lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */
  +  lua_pushvalue(L, 1);  /* state, */
  +  lua_pushinteger(L, 0);  /* and initial value */
  +  return 3;
  +}
  +
  +
  +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));
  +}
  +
  +
  +/*
  +** Reader for generic `load' function: `lua_load' uses the
  +** stack for internal stuff, so the reader cannot change the
  +** stack top. Instead, it keeps its resulting string in a
  +** reserved slot inside the stack.
  +*/
  +static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
  +  (void)ud;  /* to avoid warnings */
  +  luaL_checkstack(L, 2, "too many nested functions");
  +  lua_pushvalue(L, 1);  /* get function */
  +  lua_call(L, 0, 1);  /* call it */
  +  if (lua_isnil(L, -1)) {
  +    *size = 0;
  +    return NULL;
  +  }
  +  else if (lua_isstring(L, -1)) {
  +    lua_replace(L, 3);  /* save string in a reserved stack slot */
  +    return lua_tolstring(L, 3, size);
  +  }
  +  else luaL_error(L, "reader function must return a string");
  +  return NULL;  /* to avoid warnings */
  +}
  +
  +
  +static int luaB_load (lua_State *L) {
  +  int status;
  +  const char *cname = luaL_optstring(L, 2, "=(load)");
  +  luaL_checktype(L, 1, LUA_TFUNCTION);
  +  lua_settop(L, 3);  /* function, eventual name, plus one reserved slot */
  +  status = lua_load(L, generic_reader, NULL, cname);
  +  return load_aux(L, status);
  +}
  +
  +
  +static int luaB_dofile (lua_State *L) {
  +  const char *fname = luaL_optstring(L, 1, NULL);
  +  int n = lua_gettop(L);
  +  if (luaL_loadfile(L, fname) != 0) lua_error(L);
  +  lua_call(L, 0, LUA_MULTRET);
  +  return lua_gettop(L) - n;
  +}
  +
  +
  +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!"));
  +  return lua_gettop(L);
  +}
  +
  +
  +static int luaB_unpack (lua_State *L) {
  +  int i, e, n;
  +  luaL_checktype(L, 1, LUA_TTABLE);
  +  i = luaL_optint(L, 2, 1);
  +  e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
  +  n = e - i + 1;  /* number of elements */
  +  if (n <= 0) return 0;  /* empty range */
  +  luaL_checkstack(L, n, "table too big to unpack");
  +  for (; i<=e; i++)  /* push arg[i...e] */
  +    lua_rawgeti(L, 1, i);
  +  return n;
  +}
  +
  +
  +static int luaB_select (lua_State *L) {
  +  int n = lua_gettop(L);
  +  if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
  +    lua_pushinteger(L, n-1);
  +    return 1;
  +  }
  +  else {
  +    int i = luaL_checkint(L, 1);
  +    if (i < 0) i = n + i;
  +    else if (i > n) i = n;
  +    luaL_argcheck(L, 1 <= i, 1, "index out of range");
  +    return n - i;
  +  }
  +}
  +
  +
  +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) {
  +  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));
  +      break;
  +    case LUA_TSTRING:
  +      lua_pushvalue(L, 1);
  +      break;
  +    case LUA_TBOOLEAN:
  +      lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
  +      break;
  +    case LUA_TNIL:
  +      lua_pushliteral(L, "nil");
  +      break;
  +    default:
  +      lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
  +      break;
  +  }
  +  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;
  +}
  +
  +
  +static const luaL_Reg base_funcs[] = {
  +  {"assert", luaB_assert},
  +  {"collectgarbage", luaB_collectgarbage},
  +  {"dofile", luaB_dofile},
  +  {"error", luaB_error},
  +  {"gcinfo", luaB_gcinfo},
  +  {"getfenv", luaB_getfenv},
  +  {"getmetatable", luaB_getmetatable},
  +  {"loadfile", luaB_loadfile},
  +  {"load", luaB_load},
  +  {"loadstring", luaB_loadstring},
  +  {"next", luaB_next},
  +  {"pcall", luaB_pcall},
  +  {"print", luaB_print},
  +  {"rawequal", luaB_rawequal},
  +  {"rawget", luaB_rawget},
  +  {"rawset", luaB_rawset},
  +  {"select", luaB_select},
  +  {"setfenv", luaB_setfenv},
  +  {"setmetatable", luaB_setmetatable},
  +  {"tonumber", luaB_tonumber},
  +  {"tostring", luaB_tostring},
  +  {"type", luaB_type},
  +  {"unpack", luaB_unpack},
  +  {"xpcall", luaB_xpcall},
  +  {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");
  +  if (lua_status(co) == 0 && lua_gettop(co) == 0) {
  +    lua_pushliteral(L, "cannot resume dead coroutine");
  +    return -1;  /* error flag */
  +  }
  +  lua_xmove(L, co, narg);
  +  status = lua_resume(co, narg);
  +  if (status == 0 || status == LUA_YIELD) {
  +    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 {
  +    switch (lua_status(co)) {
  +      case LUA_YIELD:
  +        lua_pushliteral(L, "suspended");
  +        break;
  +      case 0: {
  +        lua_Debug ar;
  +        if (lua_getstack(co, 0, &ar) > 0)  /* does it have frames? */
  +          lua_pushliteral(L, "normal");  /* it is running */
  +        else if (lua_gettop(co) == 0)
  +            lua_pushliteral(L, "dead");
  +        else
  +          lua_pushliteral(L, "suspended");  /* initial state */
  +        break;
  +      }
  +      default:  /* some error occured */
  +        lua_pushliteral(L, "dead");
  +        break;
  +    }
  +  }
  +  return 1;
  +}
  +
  +
  +static int luaB_corunning (lua_State *L) {
  +  if (lua_pushthread(L))
  +    return 0;  /* main thread is not a coroutine */
  +  else
  +    return 1;
  +}
  +
  +
  +static const luaL_Reg co_funcs[] = {
  +  {"create", luaB_cocreate},
  +  {"resume", luaB_coresume},
  +  {"running", luaB_corunning},
  +  {"status", luaB_costatus},
  +  {"wrap", luaB_cowrap},
  +  {"yield", luaB_yield},
  +  {NULL, NULL}
  +};
  +
  +/* }====================================================== */
  +
  +
  +static void auxopen (lua_State *L, const char *name,
  +                     lua_CFunction f, lua_CFunction u) {
  +  lua_pushcfunction(L, u);
  +  lua_pushcclosure(L, f, 1);
  +  lua_setfield(L, -2, name);
  +}
  +
  +
  +static void base_open (lua_State *L) {
  +  /* set global _G */
  +  lua_pushvalue(L, LUA_GLOBALSINDEX);
  +  lua_setglobal(L, "_G");
  +  /* open lib into global table */
  +  luaL_register(L, "_G", base_funcs);
  +  lua_pushliteral(L, LUA_VERSION);
  +  lua_setglobal(L, "_VERSION");  /* set global _VERSION */
  +  /* `ipairs' and `pairs' need auxliliary functions as upvalues */
  +  auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
  +  auxopen(L, "pairs", luaB_pairs, luaB_next);
  +  /* `newproxy' needs a weaktable as upvalue */
  +  lua_createtable(L, 0, 1);  /* new table `w' */
  +  lua_pushvalue(L, -1);  /* `w' will be its own metatable */
  +  lua_setmetatable(L, -2);
  +  lua_pushliteral(L, "kv");
  +  lua_setfield(L, -2, "__mode");  /* metatable(w).__mode = "kv" */
  +  lua_pushcclosure(L, luaB_newproxy, 1);
  +  lua_setglobal(L, "newproxy");  /* set global `newproxy' */
  +}
  +
  +
  +LUALIB_API int luaopen_base (lua_State *L) {
  +  base_open(L);
  +  luaL_register(L, LUA_COLIBNAME, co_funcs);
  +  return 2;
  +}
  +
  @@ .
  patch -p0 <<'@@ .'
  Index: lua/lcode.c
  ============================================================================
  $ cvs diff -u -r1.2 -r1.3 lcode.c
  --- lua/lcode.c	23 Mar 2004 05:09:14 -0000	1.2
  +++ lua/lcode.c	15 Jul 2007 17:56:10 -0000	1.3
  @@ -1,5 +1,5 @@
   /*
  -** $Id: lcode.c,v 1.2 2004/03/23 05:09:14 jbj Exp $
  +** $Id: lcode.c,v 1.3 2007/07/15 17:56:10 rse Exp $
   ** Code generator for Lua
   ** See Copyright Notice in lua.h
   */
  @@ -8,12 +8,14 @@
   #include <stdlib.h>
   
   #define lcode_c
  +#define LUA_CORE
   
   #include "lua.h"
   
   #include "lcode.h"
   #include "ldebug.h"
   #include "ldo.h"
  +#include "lgc.h"
   #include "llex.h"
   #include "lmem.h"
   #include "lobject.h"
  @@ -25,16 +27,29 @@
   #define hasjumps(e)	((e)->t != (e)->f)
   
   
  +static int isnumeral(expdesc *e) {
  +  return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
  +}
  +
  +
   void luaK_nil (FuncState *fs, int from, int n) {
     Instruction *previous;
  -  if (fs->pc > fs->lasttarget &&  /* no jumps to current position? */
  -      GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == OP_LOADNIL) {
  -    int pfrom = GETARG_A(*previous);
  -    int pto = GETARG_B(*previous);
  -    if (pfrom <= from && from <= pto+1) {  /* can connect both? */
  -      if (from+n-1 > pto)
  -        SETARG_B(*previous, from+n-1);
  -      return;
  +  if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */
  +    if (fs->pc == 0) {  /* function start? */
  +      if (from >= fs->nactvar)
  +        return;  /* positions are already clean */
  +    }
  +    else {
  +      previous = &fs->f->code[fs->pc-1];
  +      if (GET_OPCODE(*previous) == OP_LOADNIL) {
  +        int pfrom = GETARG_A(*previous);
  +        int pto = GETARG_B(*previous);
  +        if (pfrom <= from && from <= pto+1) {  /* can connect both? */
  +          if (from+n-1 > pto)
  +            SETARG_B(*previous, from+n-1);
  +          return;
  +        }
  +      }
       }
     }
     luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0);  /* else no optimization */
  @@ -51,17 +66,18 @@
   }
   
   
  -static int luaK_condjump (FuncState *fs, OpCode op, int A, int B, int C)
  -	/*@modifies fs @*/
  -{
  +void luaK_ret (FuncState *fs, int first, int nret) {
  +  luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
  +}
  +
  +
  +static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
     luaK_codeABC(fs, op, A, B, C);
     return luaK_jump(fs);
   }
   
   
  -static void luaK_fixjump (FuncState *fs, int pc, int dest)
  -	/*@modifies fs @*/
  -{
  +static void fixjump (FuncState *fs, int pc, int dest) {
     Instruction *jmp = &fs->f->code[pc];
     int offset = dest-(pc+1);
     lua_assert(dest != NO_JUMP);
  @@ -81,9 +97,7 @@
   }
   
   
  -static int luaK_getjump (FuncState *fs, int pc)
  -	/*@*/
  -{
  +static int getjump (FuncState *fs, int pc) {
     int offset = GETARG_sBx(fs->f->code[pc]);
     if (offset == NO_JUMP)  /* point to itself represents end of list */
       return NO_JUMP;  /* end of list */
  @@ -92,11 +106,9 @@
   }
   
   
  -static Instruction *getjumpcontrol (FuncState *fs, int pc)
  -	/*@*/
  -{
  +static Instruction *getjumpcontrol (FuncState *fs, int pc) {
     Instruction *pi = &fs->f->code[pc];
  -  if (pc >= 1 && testOpMode(GET_OPCODE(*(pi-1)), OpModeT))
  +  if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
       return pi-1;
     else
       return pi;
  @@ -107,57 +119,49 @@
   ** check whether list has any jump that do not produce a value
   ** (or produce an inverted value)
   */
  -static int need_value (FuncState *fs, int list, int cond)
  -	/*@*/
  -{
  -  for (; list != NO_JUMP; list = luaK_getjump(fs, list)) {
  +static int need_value (FuncState *fs, int list) {
  +  for (; list != NO_JUMP; list = getjump(fs, list)) {
       Instruction i = *getjumpcontrol(fs, list);
  -    if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1;
  +    if (GET_OPCODE(i) != OP_TESTSET) return 1;
     }
     return 0;  /* not found */
   }
   
   
  -static void patchtestreg (Instruction *i, int reg)
  -	/*@modifies *i @*/
  -{
  -  if (reg == NO_REG) reg = GETARG_B(*i);
  -  SETARG_A(*i, reg);
  +static int patchtestreg (FuncState *fs, int node, int reg) {
  +  Instruction *i = getjumpcontrol(fs, node);
  +  if (GET_OPCODE(*i) != OP_TESTSET)
  +    return 0;  /* cannot patch other instructions */
  +  if (reg != NO_REG && reg != GETARG_B(*i))
  +    SETARG_A(*i, reg);
  +  else  /* no register to put value or register already has the value */
  +    *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
  +
  +  return 1;
   }
   
   
  -static void luaK_patchlistaux (FuncState *fs, int list,
  -          int ttarget, int treg, int ftarget, int freg, int dtarget)
  -	/*@modifies fs @*/
  -{
  +static void removevalues (FuncState *fs, int list) {
  +  for (; list != NO_JUMP; list = getjump(fs, list))
  +      patchtestreg(fs, list, NO_REG);
  +}
  +
  +
  +static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
  +                          int dtarget) {
     while (list != NO_JUMP) {
  -    int next = luaK_getjump(fs, list);
  -    Instruction *i = getjumpcontrol(fs, list);
  -    if (GET_OPCODE(*i) != OP_TEST) {
  -      lua_assert(dtarget != NO_JUMP);
  -      luaK_fixjump(fs, list, dtarget);  /* jump to default target */
  -    }
  -    else {
  -      if (GETARG_C(*i)) {
  -        lua_assert(ttarget != NO_JUMP);
  -        patchtestreg(i, treg);
  -        luaK_fixjump(fs, list, ttarget);
  -      }
  -      else {
  -        lua_assert(ftarget != NO_JUMP);
  -        patchtestreg(i, freg);
  -        luaK_fixjump(fs, list, ftarget);
  -      }
  -    }
  +    int next = getjump(fs, list);
  +    if (patchtestreg(fs, list, reg))
  +      fixjump(fs, list, vtarget);
  +    else
  +      fixjump(fs, list, dtarget);  /* jump to default target */
       list = next;
     }
   }
   
   
  -static void luaK_dischargejpc (FuncState *fs)
  -	/*@modifies fs @*/
  -{
  -  luaK_patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc, NO_REG, fs->pc);
  +static void dischargejpc (FuncState *fs) {
  +  patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
     fs->jpc = NO_JUMP;
   }
   
  @@ -167,7 +171,7 @@
       luaK_patchtohere(fs, list);
     else {
       lua_assert(target < fs->pc);
  -    luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target);
  +    patchlistaux(fs, list, target, NO_REG, target);
     }
   }
   
  @@ -185,9 +189,9 @@
     else {
       int list = *l1;
       int next;
  -    while ((next = luaK_getjump(fs, list)) != NO_JUMP)  /* find last element */
  +    while ((next = getjump(fs, list)) != NO_JUMP)  /* find last element */
         list = next;
  -    luaK_fixjump(fs, list, l2);
  +    fixjump(fs, list, l2);
     }
   }
   
  @@ -197,7 +201,7 @@
     if (newstack > fs->f->maxstacksize) {
       if (newstack >= MAXSTACK)
         luaX_syntaxerror(fs->ls, "function or expression too complex");
  -    fs->f->maxstacksize = cast(lu_byte, newstack);
  +    fs->f->maxstacksize = cast_byte(newstack);
     }
   }
   
  @@ -208,74 +212,91 @@
   }
   
   
  -static void freereg (FuncState *fs, int reg)
  -	/*@modifies fs @*/
  -{
  -  if (reg >= fs->nactvar && reg < MAXSTACK) {
  +static void freereg (FuncState *fs, int reg) {
  +  if (!ISK(reg) && reg >= fs->nactvar) {
       fs->freereg--;
       lua_assert(reg == fs->freereg);
     }
   }
   
   
  -static void freeexp (FuncState *fs, expdesc *e)
  -	/*@modifies fs @*/
  -{
  +static void freeexp (FuncState *fs, expdesc *e) {
     if (e->k == VNONRELOC)
  -    freereg(fs, e->info);
  +    freereg(fs, e->u.s.info);
   }
   
   
  -static int addk (FuncState *fs, TObject *k, TObject *v)
  -	/*@modifies fs @*/
  -{
  -  const TObject *idx = luaH_get(fs->h, k);
  +static int addk (FuncState *fs, TValue *k, TValue *v) {
  +  lua_State *L = fs->L;
  +  TValue *idx = luaH_set(L, fs->h, k);
  +  Proto *f = fs->f;
  +  int oldsize = f->sizek;
     if (ttisnumber(idx)) {
  -    lua_assert(luaO_rawequalObj(&fs->f->k[cast(int, nvalue(idx))], v));
  -    return cast(int, nvalue(idx));
  +    lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
  +    return cast_int(nvalue(idx));
     }
     else {  /* constant not found; create a new entry */
  -    Proto *f = fs->f;
  -    luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject,
  +    setnvalue(idx, cast_num(fs->nk));
  +    luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
                       MAXARG_Bx, "constant table overflow");
  -    setobj2n(&f->k[fs->nk], v);
  -    setnvalue(luaH_set(fs->L, fs->h, k), cast(lua_Number, fs->nk));
  +    while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
  +    setobj(L, &f->k[fs->nk], v);
  +    luaC_barrier(L, f, v);
       return fs->nk++;
     }
   }
   
   
   int luaK_stringK (FuncState *fs, TString *s) {
  -  TObject o;
  -  setsvalue(&o, s);
  +  TValue o;
  +  setsvalue(fs->L, &o, s);
     return addk(fs, &o, &o);
   }
   
   
   int luaK_numberK (FuncState *fs, lua_Number r) {
  -  TObject o;
  +  TValue o;
     setnvalue(&o, r);
     return addk(fs, &o, &o);
   }
   
   
  -static int nil_constant (FuncState *fs)
  -	/*@modifies fs @*/
  -{
  -  TObject k, v;
  +static int boolK (FuncState *fs, int b) {
  +  TValue o;
  +  setbvalue(&o, b);
  +  return addk(fs, &o, &o);
  +}
  +
  +
  +static int nilK (FuncState *fs) {
  +  TValue k, v;
     setnilvalue(&v);
  -  sethvalue(&k, fs->h);  /* cannot use nil as key; instead use table itself */
  +  /* cannot use nil as key; instead use table itself to represent nil */
  +  sethvalue(fs->L, &k, fs->h);
     return addk(fs, &k, &v);
   }
   
   
  -void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) {
  +void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
     if (e->k == VCALL) {  /* expression is an open function call? */
       SETARG_C(getcode(fs, e), nresults+1);
  -    if (nresults == 1) {  /* `regular' expression? */
  -      e->k = VNONRELOC;
  -      e->info = GETARG_A(getcode(fs, e));
  -    }
  +  }
  +  else if (e->k == VVARARG) {
  +    SETARG_B(getcode(fs, e), nresults+1);
  +    SETARG_A(getcode(fs, e), fs->freereg);
  +    luaK_reserveregs(fs, 1);
  +  }
  +}
  +
  +
  +void luaK_setoneret (FuncState *fs, expdesc *e) {
  +  if (e->k == VCALL) {  /* expression is an open function call? */
  +    e->k = VNONRELOC;
  +    e->u.s.info = GETARG_A(getcode(fs, e));
  +  }
  +  else if (e->k == VVARARG) {
  +    SETARG_B(getcode(fs, e), 2);
  +    e->k = VRELOCABLE;  /* can relocate its simple result */
     }
   }
   
  @@ -287,24 +308,25 @@
         break;
       }
       case VUPVAL: {
  -      e->info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->info, 0);
  +      e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);
         e->k = VRELOCABLE;
         break;
       }
       case VGLOBAL: {
  -      e->info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->info);
  +      e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
         e->k = VRELOCABLE;
         break;
       }
       case VINDEXED: {
  -      freereg(fs, e->aux);
  -      freereg(fs, e->info);
  -      e->info = luaK_codeABC(fs, OP_GETTABLE, 0, e->info, e->aux);
  +      freereg(fs, e->u.s.aux);
  +      freereg(fs, e->u.s.info);
  +      e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);
         e->k = VRELOCABLE;
         break;
       }
  +    case VVARARG:
       case VCALL: {
  -      luaK_setcallreturns(fs, e, 1);
  +      luaK_setoneret(fs, e);
         break;
       }
       default: break;  /* there is one value available (somewhere) */
  @@ -312,17 +334,13 @@
   }
   
   
  -static int code_label (FuncState *fs, int A, int b, int jump)
  -	/*@modifies fs @*/
  -{
  +static int code_label (FuncState *fs, int A, int b, int jump) {
     luaK_getlabel(fs);  /* those instructions may be jump targets */
     return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
   }
   
   
  -static void discharge2reg (FuncState *fs, expdesc *e, int reg)
  -	/*@modifies fs, e @*/
  -{
  +static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
     luaK_dischargevars(fs, e);
     switch (e->k) {
       case VNIL: {
  @@ -334,7 +352,11 @@
         break;
       }
       case VK: {
  -      luaK_codeABx(fs, OP_LOADK, reg, e->info);
  +      luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);
  +      break;
  +    }
  +    case VKNUM: {
  +      luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
         break;
       }
       case VRELOCABLE: {
  @@ -343,8 +365,8 @@
         break;
       }
       case VNONRELOC: {
  -      if (reg != e->info)
  -        luaK_codeABC(fs, OP_MOVE, reg, e->info, 0);
  +      if (reg != e->u.s.info)
  +        luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);
         break;
       }
       default: {
  @@ -352,14 +374,12 @@
         return;  /* nothing to do... */
       }
     }
  -  e->info = reg;
  +  e->u.s.info = reg;
     e->k = VNONRELOC;
   }
   
   
  -static void discharge2anyreg (FuncState *fs, expdesc *e)
  -	/*@modifies fs, e @*/
  -{
  +static void discharge2anyreg (FuncState *fs, expdesc *e) {
     if (e->k != VNONRELOC) {
       luaK_reserveregs(fs, 1);
       discharge2reg(fs, e, fs->freereg-1);
  @@ -367,30 +387,26 @@
   }
   
   
  -static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg)
  -	/*@modifies fs, e @*/
  -{
  +static void exp2reg (FuncState *fs, expdesc *e, int reg) {
     discharge2reg(fs, e, reg);
     if (e->k == VJMP)
  -    luaK_concat(fs, &e->t, e->info);  /* put this jump in `t' list */
  +    luaK_concat(fs, &e->t, e->u.s.info);  /* put this jump in `t' list */
     if (hasjumps(e)) {
       int final;  /* position after whole expression */
       int p_f = NO_JUMP;  /* position of an eventual LOAD false */
       int p_t = NO_JUMP;  /* position of an eventual LOAD true */
  -    if (need_value(fs, e->t, 1) || need_value(fs, e->f, 0)) {
  -      int fj = NO_JUMP;  /* first jump (over LOAD ops.) */
  -      if (e->k != VJMP)
  -        fj = luaK_jump(fs);
  +    if (need_value(fs, e->t) || need_value(fs, e->f)) {
  +      int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
         p_f = code_label(fs, reg, 0, 1);
         p_t = code_label(fs, reg, 1, 0);
         luaK_patchtohere(fs, fj);
       }
       final = luaK_getlabel(fs);
  -    luaK_patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f);
  -    luaK_patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t);
  +    patchlistaux(fs, e->f, final, reg, p_f);
  +    patchlistaux(fs, e->t, final, reg, p_t);
     }
     e->f = e->t = NO_JUMP;
  -  e->info = reg;
  +  e->u.s.info = reg;
     e->k = VNONRELOC;
   }
   
  @@ -399,21 +415,21 @@
     luaK_dischargevars(fs, e);
     freeexp(fs, e);
     luaK_reserveregs(fs, 1);
  -  luaK_exp2reg(fs, e, fs->freereg - 1);
  +  exp2reg(fs, e, fs->freereg - 1);
   }
   
   
   int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
     luaK_dischargevars(fs, e);
     if (e->k == VNONRELOC) {
  -    if (!hasjumps(e)) return e->info;  /* exp is already in a register */ 
  -    if (e->info >= fs->nactvar) {  /* reg. is not a local? */
  -      luaK_exp2reg(fs, e, e->info);  /* put value on it */
  -      return e->info;
  +    if (!hasjumps(e)) return e->u.s.info;  /* exp is already in a register */
  +    if (e->u.s.info >= fs->nactvar) {  /* reg. is not a local? */
  +      exp2reg(fs, e, e->u.s.info);  /* put value on it */
  +      return e->u.s.info;
       }
     }
     luaK_exp2nextreg(fs, e);  /* default */
  -  return e->info;
  +  return e->u.s.info;
   }
   
   
  @@ -428,17 +444,22 @@
   int luaK_exp2RK (FuncState *fs, expdesc *e) {
     luaK_exp2val(fs, e);
     switch (e->k) {
  +    case VKNUM:
  +    case VTRUE:
  +    case VFALSE:
       case VNIL: {
  -      if (fs->nk + MAXSTACK <= MAXARG_C) {  /* constant fit in argC? */
  -        e->info = nil_constant(fs);
  +      if (fs->nk <= MAXINDEXRK) {  /* constant fit in RK operand? */
  +        e->u.s.info = (e->k == VNIL)  ? nilK(fs) :
  +                      (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
  +                                        boolK(fs, (e->k == VTRUE));
           e->k = VK;
  -        return e->info + MAXSTACK;
  +        return RKASK(e->u.s.info);
         }
         else break;
       }
       case VK: {
  -      if (e->info + MAXSTACK <= MAXARG_C)  /* constant fit in argC? */
  -        return e->info + MAXSTACK;
  +      if (e->u.s.info <= MAXINDEXRK)  /* constant fit in argC? */
  +        return RKASK(e->u.s.info);
         else break;
       }
       default: break;
  @@ -448,26 +469,26 @@
   }
   
   
  -void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) {
  +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
     switch (var->k) {
       case VLOCAL: {
  -      freeexp(fs, exp);
  -      luaK_exp2reg(fs, exp, var->info);
  +      freeexp(fs, ex);
  +      exp2reg(fs, ex, var->u.s.info);
         return;
       }
       case VUPVAL: {
  -      int e = luaK_exp2anyreg(fs, exp);
  -      luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0);
  +      int e = luaK_exp2anyreg(fs, ex);
  +      luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);
         break;
       }
       case VGLOBAL: {
  -      int e = luaK_exp2anyreg(fs, exp);
  -      luaK_codeABx(fs, OP_SETGLOBAL, e, var->info);
  +      int e = luaK_exp2anyreg(fs, ex);
  +      luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
         break;
       }
       case VINDEXED: {
  -      int e = luaK_exp2RK(fs, exp);
  -      luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e);
  +      int e = luaK_exp2RK(fs, ex);
  +      luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
         break;
       }
       default: {
  @@ -475,7 +496,7 @@
         break;
       }
     }
  -  freeexp(fs, exp);
  +  freeexp(fs, ex);
   }
   
   
  @@ -485,37 +506,33 @@
     freeexp(fs, e);
     func = fs->freereg;
     luaK_reserveregs(fs, 2);
  -  luaK_codeABC(fs, OP_SELF, func, e->info, luaK_exp2RK(fs, key));
  +  luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
     freeexp(fs, key);
  -  e->info = func;
  +  e->u.s.info = func;
     e->k = VNONRELOC;
   }
   
   
  -static void invertjump (FuncState *fs, expdesc *e)
  -	/*@*/
  -{
  -  Instruction *pc = getjumpcontrol(fs, e->info);
  -  lua_assert(testOpMode(GET_OPCODE(*pc), OpModeT) &&
  -             GET_OPCODE(*pc) != OP_TEST);
  +static void invertjump (FuncState *fs, expdesc *e) {
  +  Instruction *pc = getjumpcontrol(fs, e->u.s.info);
  +  lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
  +                                           GET_OPCODE(*pc) != OP_TEST);
     SETARG_A(*pc, !(GETARG_A(*pc)));
   }
   
   
  -static int jumponcond (FuncState *fs, expdesc *e, int cond)
  -	/*@modifies fs, e @*/
  -{
  +static int jumponcond (FuncState *fs, expdesc *e, int cond) {
     if (e->k == VRELOCABLE) {
       Instruction ie = getcode(fs, e);
       if (GET_OPCODE(ie) == OP_NOT) {
         fs->pc--;  /* remove previous OP_NOT */
  -      return luaK_condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond);
  +      return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
       }
       /* else go through */
     }
     discharge2anyreg(fs, e);
     freeexp(fs, e);
  -  return luaK_condjump(fs, OP_TEST, NO_REG, e->info, cond);
  +  return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);
   }
   
   
  @@ -523,7 +540,7 @@
     int pc;  /* pc of last jump */
     luaK_dischargevars(fs, e);
     switch (e->k) {
  -    case VK: case VTRUE: {
  +    case VK: case VKNUM: case VTRUE: {
         pc = NO_JUMP;  /* always true; do nothing */
         break;
       }
  @@ -533,7 +550,7 @@
       }
       case VJMP: {
         invertjump(fs, e);
  -      pc = e->info;
  +      pc = e->u.s.info;
         break;
       }
       default: {
  @@ -542,10 +559,12 @@
       }
     }
     luaK_concat(fs, &e->f, pc);  /* insert last jump in `f' list */
  +  luaK_patchtohere(fs, e->t);
  +  e->t = NO_JUMP;
   }
   
   
  -void luaK_goiffalse (FuncState *fs, expdesc *e) {
  +static void luaK_goiffalse (FuncState *fs, expdesc *e) {
     int pc;  /* pc of last jump */
     luaK_dischargevars(fs, e);
     switch (e->k) {
  @@ -558,7 +577,7 @@
         break;
       }
       case VJMP: {
  -      pc = e->info;
  +      pc = e->u.s.info;
         break;
       }
       default: {
  @@ -567,19 +586,19 @@
       }
     }
     luaK_concat(fs, &e->t, pc);  /* insert last jump in `t' list */
  +  luaK_patchtohere(fs, e->f);
  +  e->f = NO_JUMP;
   }
   
   
  -static void codenot (FuncState *fs, expdesc *e)
  -	/*@modifies fs, e @*/
  -{
  +static void codenot (FuncState *fs, expdesc *e) {
     luaK_dischargevars(fs, e);
     switch (e->k) {
       case VNIL: case VFALSE: {
         e->k = VTRUE;
         break;
       }
  -    case VK: case VTRUE: {
  +    case VK: case VKNUM: case VTRUE: {
         e->k = VFALSE;
         break;
       }
  @@ -591,7 +610,7 @@
       case VNONRELOC: {
         discharge2anyreg(fs, e);
         freeexp(fs, e);
  -      e->info = luaK_codeABC(fs, OP_NOT, 0, e->info, 0);
  +      e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);
         e->k = VRELOCABLE;
         break;
       }
  @@ -602,29 +621,97 @@
     }
     /* interchange true and false lists */
     { int temp = e->f; e->f = e->t; e->t = temp; }
  +  removevalues(fs, e->f);
  +  removevalues(fs, e->t);
   }
   
   
   void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
  -  t->aux = luaK_exp2RK(fs, k);
  +  t->u.s.aux = luaK_exp2RK(fs, k);
     t->k = VINDEXED;
   }
   
   
  -void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
  -  if (op == OPR_MINUS) {
  -    luaK_exp2val(fs, e);
  -    if (e->k == VK && ttisnumber(&fs->f->k[e->info]))
  -      e->info = luaK_numberK(fs, -nvalue(&fs->f->k[e->info]));
  +static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
  +  lua_Number v1, v2, r;
  +  if (!isnumeral(e1) || !isnumeral(e2)) return 0;
  +  v1 = e1->u.nval;
  +  v2 = e2->u.nval;
  +  switch (op) {
  +    case OP_ADD: r = luai_numadd(v1, v2); break;
  +    case OP_SUB: r = luai_numsub(v1, v2); break;
  +    case OP_MUL: r = luai_nummul(v1, v2); break;
  +    case OP_DIV:
  +      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */
  +      r = luai_numdiv(v1, v2); break;
  +    case OP_MOD:
  +      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */
  +      r = luai_nummod(v1, v2); break;
  +    case OP_POW: r = luai_numpow(v1, v2); break;
  +    case OP_UNM: r = luai_numunm(v1); break;
  +    case OP_LEN: return 0;  /* no constant folding for 'len' */
  +    default: lua_assert(0); r = 0; break;
  +  }
  +  if (luai_numisnan(r)) return 0;  /* do not attempt to produce NaN */
  +  e1->u.nval = r;
  +  return 1;
  +}
  +
  +
  +static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
  +  if (constfolding(op, e1, e2))
  +    return;
  +  else {
  +    int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
  +    int o1 = luaK_exp2RK(fs, e1);
  +    if (o1 > o2) {
  +      freeexp(fs, e1);
  +      freeexp(fs, e2);
  +    }
       else {
  -      luaK_exp2anyreg(fs, e);
  -      freeexp(fs, e);
  -      e->info = luaK_codeABC(fs, OP_UNM, 0, e->info, 0);
  -      e->k = VRELOCABLE;
  +      freeexp(fs, e2);
  +      freeexp(fs, e1);
  +    }
  +    e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
  +    e1->k = VRELOCABLE;
  +  }
  +}
  +
  +
  +static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
  +                                                          expdesc *e2) {
  +  int o1 = luaK_exp2RK(fs, e1);
  +  int o2 = luaK_exp2RK(fs, e2);
  +  freeexp(fs, e2);
  +  freeexp(fs, e1);
  +  if (cond == 0 && op != OP_EQ) {
  +    int temp;  /* exchange args to replace by `<' or `<=' */
  +    temp = o1; o1 = o2; o2 = temp;  /* o1 <==> o2 */
  +    cond = 1;
  +  }
  +  e1->u.s.info = condjump(fs, op, cond, o1, o2);
  +  e1->k = VJMP;
  +}
  +
  +
  +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
  +  expdesc e2;
  +  e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
  +  switch (op) {
  +    case OPR_MINUS: {
  +      if (e->k == VK)
  +        luaK_exp2anyreg(fs, e);  /* cannot operate on non-numeric constants */
  +      codearith(fs, OP_UNM, e, &e2);
  +      break;
       }
  +    case OPR_NOT: codenot(fs, e); break;
  +    case OPR_LEN: {
  +      luaK_exp2anyreg(fs, e);  /* cannot operate on constants */
  +      codearith(fs, OP_LEN, e, &e2);
  +      break;
  +    }
  +    default: lua_assert(0);
     }
  -  else  /* op == NOT */
  -    codenot(fs, e);
   }
   
   
  @@ -632,20 +719,21 @@
     switch (op) {
       case OPR_AND: {
         luaK_goiftrue(fs, v);
  -      luaK_patchtohere(fs, v->t);
  -      v->t = NO_JUMP;
         break;
       }
       case OPR_OR: {
         luaK_goiffalse(fs, v);
  -      luaK_patchtohere(fs, v->f);
  -      v->f = NO_JUMP;
         break;
       }
       case OPR_