summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLua Team <team@lua.org>2004-09-02 12:00:00 +0000
committerrepogen <>2004-09-02 12:00:00 +0000
commit5d480731503a315eab9d6ab9426e3d4cfd5e52f8 (patch)
tree5606bf4c36fda4395d2bc1ea226227bcb80114b4
parentced7bbbe7a257ce6de94069d5dbf6672aeafd4d9 (diff)
downloadlua-github-5d480731503a315eab9d6ab9426e3d4cfd5e52f8.tar.gz
Lua 5.1-work15.1-work1
-rw-r--r--HISTORY2
-rw-r--r--INSTALL22
-rw-r--r--MANIFEST114
l---------RCS1
-rw-r--r--README2
-rwxr-xr-xbuild9
-rw-r--r--config53
-rwxr-xr-xconfigure9
-rw-r--r--etc/Makefile19
l---------etc/RCS1
-rw-r--r--etc/README4
-rw-r--r--etc/all.c41
-rw-r--r--etc/min.c46
-rw-r--r--etc/noparser.c3
-rw-r--r--include/Makefile2
l---------include/RCS1
-rw-r--r--include/lauxlib.h33
-rw-r--r--include/lua.h69
-rw-r--r--include/luaconf.h312
-rw-r--r--include/lualib.h25
l---------src/RCS1
-rw-r--r--src/README4
-rw-r--r--src/lapi.c88
-rw-r--r--src/lcode.c41
-rw-r--r--src/lcode.h7
-rw-r--r--src/ldebug.c39
-rw-r--r--src/ldebug.h4
-rw-r--r--src/ldo.c124
-rw-r--r--src/ldo.h10
-rw-r--r--src/ldump.c30
-rw-r--r--src/lfunc.c3
-rw-r--r--src/lgc.c310
-rw-r--r--src/lgc.h32
-rw-r--r--src/lib/Makefile4
l---------src/lib/RCS1
-rw-r--r--src/lib/lauxlib.c159
-rw-r--r--src/lib/lbaselib.c296
-rw-r--r--src/lib/ldblib.c33
-rw-r--r--src/lib/linit.c38
-rw-r--r--src/lib/liolib.c378
-rw-r--r--src/lib/lmathlib.c30
-rw-r--r--src/lib/loadlib.c5
-rw-r--r--src/lib/loslib.c241
-rw-r--r--src/lib/lstrlib.c30
-rw-r--r--src/lib/ltablib.c47
-rw-r--r--src/llex.c3
-rw-r--r--src/llimits.h97
-rw-r--r--src/lmem.c6
-rw-r--r--src/lobject.c30
-rw-r--r--src/lobject.h6
-rw-r--r--src/lopcodes.c10
-rw-r--r--src/lopcodes.h58
-rw-r--r--src/lparser.c68
-rw-r--r--src/lparser.h5
-rw-r--r--src/lstate.c32
-rw-r--r--src/lstate.h56
-rw-r--r--src/lstring.c12
-rw-r--r--src/lstring.h3
-rw-r--r--src/ltable.c63
-rw-r--r--src/ltable.h3
-rw-r--r--src/ltests.c852
-rw-r--r--src/ltm.c3
l---------src/lua/RCS1
-rw-r--r--src/lua/README4
-rw-r--r--src/lua/lua.c247
-rw-r--r--src/luac/Makefile6
l---------src/luac/RCS1
-rw-r--r--src/luac/README2
-rw-r--r--src/luac/luac.c75
-rw-r--r--src/luac/print.c52
-rw-r--r--src/lundump.c13
-rw-r--r--src/lundump.h6
-rw-r--r--src/lvm.c304
-rw-r--r--src/lvm.h8
-rw-r--r--src/lzio.c3
75 files changed, 2140 insertions, 2612 deletions
diff --git a/HISTORY b/HISTORY
index cf6e1c01..dd29bc7c 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,4 +1,4 @@
-This is Lua 5.0.
+This is Lua 5.1 (work).
* Changes from version 4.0 to 5.0
-------------------------------
diff --git a/INSTALL b/INSTALL
index 6828f23c..9d489301 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,4 +1,4 @@
-This is Lua 5.0.
+This is Lua 5.1 (work).
* Installation
------------
@@ -7,8 +7,9 @@ This is Lua 5.0.
1. Read "config" and edit it to suit your platform and needs.
We strongly recommend that you enable support for dynamic loading,
if your platform allows it.
- 2. Do "make".
- 3. If you want to install Lua in an "official" place in your system,
+ 2. Do the same for include/luaconf.h.
+ 3. Do "make".
+ 4. If you want to install Lua in an "official" place in your system,
then do "make install". The official place and the way to install
files are defined in "config". You may have to be root to do this.
@@ -53,27 +54,26 @@ This is Lua 5.0.
/usr/local/lib may not be a place that is checked for shared libraries.
In Linux, the places checked are in /etc/ld.so.conf. Try also "man ld.so".
- Building shared libraries in other systems is similar but details differ;
+ Building shared libraries on other systems is similar but details differ;
you may need to fix a few details in the top-level Makefile.
* Installation on Windows and other systems
-----------------------------------------
- The instructions for building Lua on other systems machine depend on the
- particular compiler you are using. The simplest way is to create a folder
- with all .c and .h files, and then create projects for the core library,
- the standard library, the interpreter, and the compiler, as follows:
+ The instructions for building Lua on other systems depend on the particular
+ compiler you are using. The simplest way is to create a folder with all .c
+ and .h files, and then create projects for the core library, the standard
+ library, the interpreter, and the compiler, as follows:
core lib: lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c
lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c
ltable.c ltm.c lundump.c lvm.c lzio.c
- standard lib: lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c ltablib.c
- lstrlib.c loadlib.c
+ standard lib: lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c
+ ltablib.c lstrlib.c loadlib.c
interpreter: core lib, standard lib, lua.c
compiler: core lib, lauxlib.c luac.c print.c
- and also lopcodes.c (with LUA_OPNAMES defined) from core.
Of course, to use Lua as a library, you'll have to know how to create
and use libraries with your compiler.
diff --git a/MANIFEST b/MANIFEST
new file mode 100644
index 00000000..fdb5d2a2
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,114 @@
+MANIFEST contents of Lua 5.1 (work1) distribution on Wed Sep 1 22:19:31 BRT 2004
+lua-5.1-work1
+lua-5.1-work1/COPYRIGHT
+lua-5.1-work1/HISTORY
+lua-5.1-work1/INSTALL
+lua-5.1-work1/MANIFEST
+lua-5.1-work1/Makefile
+lua-5.1-work1/README
+lua-5.1-work1/bin
+lua-5.1-work1/build
+lua-5.1-work1/config
+lua-5.1-work1/etc
+lua-5.1-work1/etc/Makefile
+lua-5.1-work1/etc/README
+lua-5.1-work1/etc/all.c
+lua-5.1-work1/etc/lua.ico
+lua-5.1-work1/etc/min.c
+lua-5.1-work1/etc/noparser.c
+lua-5.1-work1/etc/saconfig.c
+lua-5.1-work1/include
+lua-5.1-work1/include/Makefile
+lua-5.1-work1/include/lauxlib.h
+lua-5.1-work1/include/lua.h
+lua-5.1-work1/include/luaconf.h
+lua-5.1-work1/include/lualib.h
+lua-5.1-work1/lib
+lua-5.1-work1/src
+lua-5.1-work1/src/Makefile
+lua-5.1-work1/src/README
+lua-5.1-work1/src/lapi.c
+lua-5.1-work1/src/lapi.h
+lua-5.1-work1/src/lcode.c
+lua-5.1-work1/src/lcode.h
+lua-5.1-work1/src/ldebug.c
+lua-5.1-work1/src/ldebug.h
+lua-5.1-work1/src/ldo.c
+lua-5.1-work1/src/ldo.h
+lua-5.1-work1/src/ldump.c
+lua-5.1-work1/src/lfunc.c
+lua-5.1-work1/src/lfunc.h
+lua-5.1-work1/src/lgc.c
+lua-5.1-work1/src/lgc.h
+lua-5.1-work1/src/lib
+lua-5.1-work1/src/lib/Makefile
+lua-5.1-work1/src/lib/README
+lua-5.1-work1/src/lib/lauxlib.c
+lua-5.1-work1/src/lib/lbaselib.c
+lua-5.1-work1/src/lib/ldblib.c
+lua-5.1-work1/src/lib/linit.c
+lua-5.1-work1/src/lib/liolib.c
+lua-5.1-work1/src/lib/lmathlib.c
+lua-5.1-work1/src/lib/loadlib.c
+lua-5.1-work1/src/lib/loslib.c
+lua-5.1-work1/src/lib/lstrlib.c
+lua-5.1-work1/src/lib/ltablib.c
+lua-5.1-work1/src/llex.c
+lua-5.1-work1/src/llex.h
+lua-5.1-work1/src/llimits.h
+lua-5.1-work1/src/lmem.c
+lua-5.1-work1/src/lmem.h
+lua-5.1-work1/src/lobject.c
+lua-5.1-work1/src/lobject.h
+lua-5.1-work1/src/lopcodes.c
+lua-5.1-work1/src/lopcodes.h
+lua-5.1-work1/src/lparser.c
+lua-5.1-work1/src/lparser.h
+lua-5.1-work1/src/lstate.c
+lua-5.1-work1/src/lstate.h
+lua-5.1-work1/src/lstring.c
+lua-5.1-work1/src/lstring.h
+lua-5.1-work1/src/ltable.c
+lua-5.1-work1/src/ltable.h
+lua-5.1-work1/src/ltm.c
+lua-5.1-work1/src/ltm.h
+lua-5.1-work1/src/lua
+lua-5.1-work1/src/lua/Makefile
+lua-5.1-work1/src/lua/README
+lua-5.1-work1/src/lua/lua.c
+lua-5.1-work1/src/luac
+lua-5.1-work1/src/luac/Makefile
+lua-5.1-work1/src/luac/README
+lua-5.1-work1/src/luac/luac.c
+lua-5.1-work1/src/luac/print.c
+lua-5.1-work1/src/lundump.c
+lua-5.1-work1/src/lundump.h
+lua-5.1-work1/src/lvm.c
+lua-5.1-work1/src/lvm.h
+lua-5.1-work1/src/lzio.c
+lua-5.1-work1/src/lzio.h
+lua-5.1-work1/test
+lua-5.1-work1/test/README
+lua-5.1-work1/test/bisect.lua
+lua-5.1-work1/test/cf.lua
+lua-5.1-work1/test/echo.lua
+lua-5.1-work1/test/env.lua
+lua-5.1-work1/test/factorial.lua
+lua-5.1-work1/test/fib.lua
+lua-5.1-work1/test/fibfor.lua
+lua-5.1-work1/test/globals.lua
+lua-5.1-work1/test/hello.lua
+lua-5.1-work1/test/life.lua
+lua-5.1-work1/test/lua
+lua-5.1-work1/test/luac
+lua-5.1-work1/test/luac.lua
+lua-5.1-work1/test/printf.lua
+lua-5.1-work1/test/readonly.lua
+lua-5.1-work1/test/sieve.lua
+lua-5.1-work1/test/sort.lua
+lua-5.1-work1/test/table.lua
+lua-5.1-work1/test/trace-calls.lua
+lua-5.1-work1/test/trace-globals.lua
+lua-5.1-work1/test/undefined.lua
+lua-5.1-work1/test/xd.lua
+END OF MANIFEST
diff --git a/RCS b/RCS
deleted file mode 120000
index 1ae38936..00000000
--- a/RCS
+++ /dev/null
@@ -1 +0,0 @@
-../RCS \ No newline at end of file
diff --git a/README b/README
index 4aaaba52..8f4aa49a 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-This is Lua 5.0.
+This is Lua 5.1 (work).
See HISTORY for a summary of changes since the last released version.
* What is Lua?
diff --git a/build b/build
index 6faed371..a0e3fb3f 100755
--- a/build
+++ b/build
@@ -1,9 +1,12 @@
-# If you don't want to use make, run this script.
-# But make sure you read config to see what can be customized.
+#!/bin/sh
+#
+# If you don't want to use make, run this script to build Lua.
+# Read config and include/luaconf.h to see what can be customized.
# Easiest way to build bin/lua:
# cc -O2 -o bin/lua -Iinclude -Isrc src/*.c src/lib/*.c src/lua/*.c -lm -ldl
+# bin/lua test/hello.lua
# Easiest way to build Lua libraries and executables:
@@ -25,7 +28,7 @@ cc -O2 -o ../../bin/lua -I../../include *.c ../../lib/*.a -lm -ldl
echo -n 'luac... '
cd ../luac
-cc -O2 -o ../../bin/luac -I../../include -I.. *.c -DLUA_OPNAMES ../lopcodes.c ../../lib/*.a
+cc -O2 -o ../../bin/luac -I../../include -I.. *.c ../../lib/*.a
echo 'done'
diff --git a/config b/config
index 2700e6d9..fe39c134 100644
--- a/config
+++ b/config
@@ -1,14 +1,10 @@
-# configuration file for making Lua 5.0
+# configuration file for making Lua 5.1 (work)
# see INSTALL for installation instructions
# These are default values. Skip this section and see the explanations below.
LOADLIB=
DLLIB=
-NUMBER=
-POPEN=
-TMPNAM=
-DEGREES=
USERCONF=
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
@@ -42,50 +38,11 @@ USERCONF=
# --------------------------------------------------------------- Lua libraries
-# The Lua IO library (src/lib/liolib.c) has support for pipes using popen and
-# pclose. This support is enabled by default on POSIX systems.
-# If your system is not POSIX but has popen and pclose, define USE_POPEN=1.
-# If you don't want to support pipes, define USE_POPEN=0.
-#
-#POPEN= -DUSE_POPEN=1
-#POPEN= -DUSE_POPEN=0
-#
-# The form below will probably work on (some) Windows systems.
-#
-#POPEN= -DUSE_POPEN=1 -Dpopen=_popen -Dpclose=_pclose
-
-# The Lua OS library (src/lib/liolib.c) exports an interface to the C function
-# tmpnam, which gcc now thinks is `dangerous'. So, support for tmpnam is
-# disabled by default when compiling with gcc.
-# If you still want to use tmpnam, define USE_TMPNAME=1. If you don't want to
-# use tmpnam even if you're not compiling with gcc, define USE_TMPNAME=0.
-#
-#TMPNAM= -DUSE_TMPNAME=1
-#TMPNAM= -DUSE_TMPNAME=0
-
-# The Lua math library (src/lib/lmathlib.c) now operates in radians, unlike
-# previous versions of Lua, which used degrees. To use degrees instead of
-# radians, define USE_DEGREES.
-#
-#DEGREES= -DUSE_DEGREES
+# See include/luaconf.h.
# ------------------------------------------------------------------ Lua core
-# Lua uses double for numbers. To change this, uncomment and edit the following
-# line, changing USE_XXX to one of USE_DOUBLE, USE_FLOAT, USE_LONG, USE_INT.
-#
-#NUMBER= -DLUA_USER_H='"../etc/luser_number.h"' -DUSE_XXX
-
-# When compiling Lua with gcc on a Pentium machine, using a fast rounding
-# method for the conversion of doubles to ints can give around 20% speed
-# improvement. To use this rounding method, uncomment the following line.
-#NUMBER= -DLUA_USER_H='"../etc/luser_number.h"' -DUSE_FASTROUND
-
-# For partial compatibility with old upvalue syntax, define LUA_COMPATUPSYNTAX.
-# For partial compatibility with old upvalue behavior in C functions, define
-# LUA_COMPATUPVALUES. Add these definitions to MYCFLAGS.
-#
-# -DLUA_COMPATUPSYNTAX -DLUA_COMPATUPVALUES
+# See include/luaconf.h.
# ------------------------------------------------------------- Lua interpreter
@@ -165,14 +122,14 @@ INSTALL_DATA= cp
# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
-V= 5.0
+V= 5.1
BIN= $(LUA)/bin
INC= $(LUA)/include
LIB= $(LUA)/lib
INCS= -I$(INC) $(EXTRA_INCS)
-DEFS= $(NUMBER) $(EXTRA_DEFS)
+DEFS= $(EXTRA_DEFS)
CFLAGS= $(MYCFLAGS) $(WARN) $(INCS) $(DEFS)
diff --git a/configure b/configure
deleted file mode 100755
index 0aa89712..00000000
--- a/configure
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-# Lua does not use GNU autoconf; just edit ./config if needed to suit your
-# platform and then run make.
-
-# This shows the parameters currently set in ./config:
-make echo
-
-# If you want config as a Lua program, run "make lecho".
diff --git a/etc/Makefile b/etc/Makefile
index 0fc318cd..805df1d2 100644
--- a/etc/Makefile
+++ b/etc/Makefile
@@ -4,32 +4,29 @@ LUA= ..
include $(LUA)/config
-LIBLUA=$(LIB)/liblua.a
-ALL= bin2c min noparser luab
+ALL= min noparser luab 1
all:
@echo 'choose a target:' $(ALL)
-bin2c: bin2c.c
- $(CC) $(CFLAGS) -o $@ $@.c
-
min: min.c $(LIBLUA)
- $(CC) $(CFLAGS) -o $@ $@.c -L$(LIB) -llua
+ $(CC) $(CFLAGS) -o $@ $@.c -L$(LIB) -llua -llualib
noparser: noparser.c
$(CC) $(CFLAGS) -I$(LUA)/src -o $@.o -c $@.c
-luab: noparser $(LIBLUA)
- $(CC) -o $@ noparser.o $(LUA)/src/lua/lua.o -L$(LIB) -llua -llualib $(EXTRA_LIBS)
+luab: noparser
+ $(CC) -o $@ noparser.o $(LUA)/src/lua/lua.o -L$(LIB) -llua -llualib $(EXTRA_LIBS) $(DLLIB)
$(BIN)/luac $(LUA)/test/hello.lua
$@ luac.out
-$@ -e'a=1'
+1:
+ $(CC) $(CFLAGS) -I../src -I../src/lib -I../src/lua all.c $(EXTRA_LIBS) $(DLLIB)
+ ./a.out $(LUA)/test/hello.lua
+
flat:
cd ..; mkdir flat; mv include/*.h src/*.[ch] src/*/*.[ch] flat
-$(LIBLUA):
- cd ../src; $(MAKE)
-
clean:
rm -f $(ALL) a.out core *.o luac.out
diff --git a/etc/RCS b/etc/RCS
deleted file mode 120000
index 1ae38936..00000000
--- a/etc/RCS
+++ /dev/null
@@ -1 +0,0 @@
-../RCS \ No newline at end of file
diff --git a/etc/README b/etc/README
index 6a383ef8..01df94c4 100644
--- a/etc/README
+++ b/etc/README
@@ -1,6 +1,10 @@
This directory contains some useful files and code.
Unlike the code in ../src, everything here is in the public domain.
+all.c
+ Full Lua interpreter in a single file.
+ Do "make 1".
+
lua.ico
A Lua icon for Windows (and web sites, as favicon.ico).
Drawn by hand by Markus Gritsch <gritsch@iue.tuwien.ac.at>.
diff --git a/etc/all.c b/etc/all.c
new file mode 100644
index 00000000..fc4b045a
--- /dev/null
+++ b/etc/all.c
@@ -0,0 +1,41 @@
+/*
+* all.c -- Lua core, libraries and interpreter in a single file
+*/
+
+#define LUA_CORE
+#define LUA_LIB
+#define lua_c
+
+#include "lapi.c"
+#include "lcode.c"
+#include "ldebug.c"
+#include "ldo.c"
+#include "ldump.c"
+#include "lfunc.c"
+#include "lgc.c"
+#include "llex.c"
+#include "lmem.c"
+#include "lobject.c"
+#include "lopcodes.c"
+#include "lparser.c"
+#include "lstate.c"
+#include "lstring.c"
+#include "ltable.c"
+#include "ltm.c"
+#include "lundump.c"
+#include "lvm.c"
+#include "lzio.c"
+
+#include "lauxlib.c"
+#include "lbaselib.c"
+#include "ldblib.c"
+#include "liolib.c"
+#include "linit.c"
+#include "lmathlib.c"
+#include "loadlib.c"
+#define pushresult pushresult2
+#include "loslib.c"
+#include "lstrlib.c"
+#include "ltablib.c"
+
+#include "lua.c"
diff --git a/etc/min.c b/etc/min.c
index bc1c6821..dfcc805a 100644
--- a/etc/min.c
+++ b/etc/min.c
@@ -1,37 +1,47 @@
/*
* min.c -- a minimal Lua interpreter
-* only dynamic loading is enabled -- all libraries must be dynamically loaded
-* no interaction, only batch execution
+* loads stdin only with minimal error handling.
+* no interaction, and no standard library, only a "print" function.
*/
#include <stdio.h>
#include "lua.h"
-#include "lualib.h"
#include "lauxlib.h"
-static int run(lua_State *L)
+static int print(lua_State *L)
{
- char **argv=lua_touserdata(L,1);
- lua_register(L,"error",lua_error);
- luaopen_loadlib(L);
- while (*++argv)
+ int n=lua_gettop(L);
+ int i;
+ for (i=1; i<=n; i++)
{
- if (luaL_loadfile(L,*argv)) lua_error(L); else lua_call(L,0,0);
+ if (i>1) printf("\t");
+ if (lua_isstring(L,i))
+ printf("%s",lua_tostring(L,i));
+ else if (lua_isnil(L,i))
+ printf("%s","nil");
+ else if (lua_isboolean(L,i))
+ printf("%s",lua_toboolean(L,i) ? "true" : "false");
+ else
+ printf("%s:%p",lua_typename(L,lua_type(L,i)),lua_topointer(L,i));
}
+ printf("\n");
return 0;
}
-#define report(s) fprintf(stderr,"%s\n",s)
+static const char *getF(lua_State *L, void *ud, size_t *size)
+{
+ FILE *f=(FILE *)ud;
+ static char buff[512];
+ if (feof(f)) return NULL;
+ *size=fread(buff,1,sizeof(buff),f);
+ return (*size>0) ? buff : NULL;
+}
-int main(int argc, char *argv[])
+int main(void)
{
lua_State *L=lua_open();
- if (L==NULL)
- {
- report("not enough memory for state");
- return 1;
- }
- if (lua_cpcall(L,run,argv)) report(lua_tostring(L,-1));
- lua_close(L);
+ lua_register(L,"print",print);
+ if (lua_load(L,getF,stdin,"=stdin") || lua_pcall(L,0,0,0))
+ fprintf(stderr,"%s\n",lua_tostring(L,-1));
return 0;
}
diff --git a/etc/noparser.c b/etc/noparser.c
index 9d52f7c0..dc58faff 100644
--- a/etc/noparser.c
+++ b/etc/noparser.c
@@ -9,6 +9,8 @@
* load the parsing modules. To try it, do "make luab".
*/
+#define LUA_CORE
+
#include "llex.h"
#include "lparser.h"
#include "lzio.h"
@@ -28,6 +30,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
/*
* If you also want to avoid the dump module, ldump.o, enable the code below.
*/
+#define NODUMP
#ifdef NODUMP
#include "lundump.h"
diff --git a/include/Makefile b/include/Makefile
index d75997d9..687cf383 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -4,7 +4,7 @@ LUA= ..
include $(LUA)/config
-SRCS= lua.h lualib.h lauxlib.h
+SRCS= lua.h lualib.h lauxlib.h luaconf.h
all:
diff --git a/include/RCS b/include/RCS
deleted file mode 120000
index 1ae38936..00000000
--- a/include/RCS
+++ /dev/null
@@ -1 +0,0 @@
-../RCS \ No newline at end of file
diff --git a/include/lauxlib.h b/include/lauxlib.h
index 58f25005..22afc245 100644
--- a/include/lauxlib.h
+++ b/include/lauxlib.h
@@ -1,5 +1,5 @@
/*
-** $Id: lauxlib.h,v 1.63 2004/03/13 13:32:09 roberto Exp $
+** $Id: lauxlib.h,v 1.70 2004/07/09 18:23:17 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -15,10 +15,8 @@
#include "lua.h"
-#ifndef LUALIB_API
-#define LUALIB_API LUA_API
-#endif
-
+/* extra error code for `luaL_load' */
+#define LUA_ERRFILE (LUA_ERRERR+1)
typedef struct luaL_reg {
@@ -56,6 +54,9 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...);
LUALIB_API int luaL_findstring (const char *st, const char *const lst[]);
+LUALIB_API const char *luaL_searchpath (lua_State *L, const char *name,
+ const char *path);
+
LUALIB_API int luaL_ref (lua_State *L, int t);
LUALIB_API void luaL_unref (lua_State *L, int t, int ref);
@@ -85,6 +86,7 @@ LUALIB_API lua_State *(luaL_newstate) (void);
#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)))
/*
** {======================================================
@@ -93,10 +95,6 @@ LUALIB_API lua_State *(luaL_newstate) (void);
*/
-#ifndef LUAL_BUFFERSIZE
-#define LUAL_BUFFERSIZE BUFSIZ
-#endif
-
typedef struct luaL_Buffer {
char *p; /* current position in buffer */
@@ -122,15 +120,18 @@ LUALIB_API void luaL_pushresult (luaL_Buffer *B);
/* }====================================================== */
+/* compatibility with ref system */
-/*
-** Compatibility macros and functions
-*/
+/* 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))
-LUALIB_API int lua_dofile (lua_State *L, const char *filename);
-LUALIB_API int lua_dostring (lua_State *L, const char *str);
-LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t sz,
- const char *n);
+#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, ref)
#endif
diff --git a/include/lua.h b/include/lua.h
index bcb37a06..e513dc3c 100644
--- a/include/lua.h
+++ b/include/lua.h
@@ -1,5 +1,5 @@
/*
-** $Id: lua.h,v 1.187 2004/03/09 17:34:35 roberto Exp $
+** $Id: lua.h,v 1.192 2004/06/04 15:30:53 roberto Exp $
** Lua - An Extensible Extension Language
** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
** http://www.lua.org mailto:info@lua.org
@@ -14,7 +14,10 @@
#include <stddef.h>
-#define LUA_VERSION "Lua 5.1 (work)"
+#include "luaconf.h"
+
+
+#define LUA_VERSION "Lua 5.1 (work1)"
#define LUA_COPYRIGHT "Copyright (C) 1994-2004 Tecgraf, PUC-Rio"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
@@ -34,12 +37,11 @@
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
-/* error codes for `lua_load' and `lua_pcall' */
+/* error codes for `lua_pcall' */
#define LUA_ERRRUN 1
-#define LUA_ERRFILE 2
-#define LUA_ERRSYNTAX 3
-#define LUA_ERRMEM 4
-#define LUA_ERRERR 5
+#define LUA_ERRSYNTAX 2
+#define LUA_ERRMEM 3
+#define LUA_ERRERR 4
typedef struct lua_State lua_State;
@@ -91,26 +93,13 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
/* type of numbers in Lua */
-#ifndef LUA_NUMBER
-typedef double lua_Number;
-#else
typedef LUA_NUMBER lua_Number;
-#endif
/* type for integer functions */
-#ifndef LUA_INTEGER
-typedef long lua_Integer;
-#else
typedef LUA_INTEGER lua_Integer;
-#endif
-/* mark for all API functions */
-#ifndef LUA_API
-#define LUA_API extern
-#endif
-
/*
** state manipulation
@@ -155,7 +144,7 @@ LUA_API lua_Number lua_tonumber (lua_State *L, int idx);
LUA_API lua_Integer lua_tointeger (lua_State *L, int idx);
LUA_API int lua_toboolean (lua_State *L, int idx);
LUA_API const char *lua_tostring (lua_State *L, int idx);
-LUA_API size_t lua_strlen (lua_State *L, int idx);
+LUA_API size_t lua_objsize (lua_State *L, int idx);
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx);
LUA_API void *lua_touserdata (lua_State *L, int idx);
LUA_API lua_State *lua_tothread (lua_State *L, int idx);
@@ -228,6 +217,7 @@ LUA_API int lua_resume (lua_State *L, int narg);
#define LUA_GCRESTART 1
#define LUA_GCCOLLECT 2
#define LUA_GCCOUNT 3
+#define LUA_GCSTEP 4
LUA_API int lua_gc (lua_State *L, int what, int data);
@@ -254,11 +244,6 @@ LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud);
** ===============================================================
*/
-#define lua_boxpointer(L,u) \
- (*(void **)(lua_newuserdata(L, sizeof(void *))) = (u))
-
-#define lua_unboxpointer(L,i) (*(void **)(lua_touserdata(L, i)))
-
#define lua_pop(L,n) lua_settop(L, -(n)-1)
#define lua_newtable(L) lua_createtable(L, 0, 0)
@@ -267,6 +252,8 @@ LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud);
#define lua_pushcfunction(L,f) lua_pushcclosure(L, f, 0)
+#define lua_strlen(L,i) lua_objsize(L,i)
+
#define lua_isfunction(L,n) (lua_type(L,n) == LUA_TFUNCTION)
#define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE)
#define lua_islightuserdata(L,n) (lua_type(L,n) == LUA_TLIGHTUSERDATA)
@@ -295,41 +282,11 @@ LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud);
#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
-/* 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)
/*
** {======================================================================
-** useful definitions for Lua kernel and libraries
-** =======================================================================
-*/
-
-/* formats for Lua numbers */
-#ifndef LUA_NUMBER_SCAN
-#define LUA_NUMBER_SCAN "%lf"
-#endif
-
-#ifndef LUA_NUMBER_FMT
-#define LUA_NUMBER_FMT "%.14g"
-#endif
-
-/* }====================================================================== */
-
-
-/*
-** {======================================================================
** Debug API
** =======================================================================
*/
diff --git a/include/luaconf.h b/include/luaconf.h
new file mode 100644
index 00000000..56567c00
--- /dev/null
+++ b/include/luaconf.h
@@ -0,0 +1,312 @@
+/*
+** $Id: luaconf.h,v 1.11 2004/08/30 18:35:14 roberto Exp $
+** Configuration file for Lua
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lconfig_h
+#define lconfig_h
+
+#include <limits.h>
+#include <stddef.h>
+
+
+/*
+** {======================================================
+** Index (search for keyword to find corresponding entry)
+** =======================================================
+*/
+
+
+/* }====================================================== */
+
+
+
+
+/*
+** {======================================================
+** Generic configuration
+** =======================================================
+*/
+
+/* default path */
+#define LUA_PATH_DEFAULT "?;?.lua"
+
+
+/* type of numbers in Lua */
+#define LUA_NUMBER double
+
+/* formats for Lua numbers */
+#define LUA_NUMBER_SCAN "%lf"
+#define LUA_NUMBER_FMT "%.14g"
+
+
+/* type for integer functions */
+#define LUA_INTEGER long
+
+
+/* mark for all API functions */
+#define LUA_API extern
+
+/* mark for auxlib functions */
+#define LUALIB_API extern
+
+/* buffer size used by lauxlib buffer system */
+#define LUAL_BUFFERSIZE BUFSIZ
+
+
+/* first index for arrays */
+#define LUA_FIRSTINDEX 1
+
+/* assertions in Lua (mainly for internal debugging) */
+#define lua_assert(c) /* empty */
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** Stand-alone configuration
+** =======================================================
+*/
+
+#ifdef lua_c
+
+/* definition of `isatty' */
+#ifdef _POSIX_C_SOURCE
+#include <unistd.h>
+#define stdin_is_tty() isatty(0)
+#else
+#define stdin_is_tty() 1 /* assume stdin is a tty */
+#endif
+
+
+#define PROMPT "> "
+#define PROMPT2 ">> "
+#define PROGNAME "lua"
+
+
+/*
+** this macro allows you to open other libraries when starting the
+** stand-alone interpreter
+*/
+#define lua_userinit(L) luaopen_stdlibs(L)
+/*
+** #define lua_userinit(L) { int luaopen_mylibs(lua_State *L); \
+** luaopen_stdlibs(L); luaopen_mylibs(L); }
+*/
+
+
+
+/*
+** this macro can be used by some `history' system to save lines
+** read in manual input
+*/
+#define lua_saveline(L,line) /* empty */
+
+
+
+#endif
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** Core configuration
+** =======================================================
+*/
+
+#ifdef LUA_CORE
+
+/* LUA-C API assertions */
+#define api_check(L, o) /* empty */
+
+
+/* an unsigned integer with at least 32 bits */
+#define LUA_UINT32 unsigned long
+
+/* a signed integer with at least 32 bits */
+#define LUA_INT32 long
+#define LUA_MAXINT32 LONG_MAX
+
+
+/* maximum depth for calls (unsigned short) */
+#define LUA_MAXCALLS 4096
+
+/*
+** maximum depth for C calls (unsigned short): Not too big, or may
+** overflow the C stack...
+*/
+#define LUA_MAXCCALLS 200
+
+
+/* maximum size for the virtual stack of a C function */
+#define MAXCSTACK 2048
+
+
+/*
+** maximum number of syntactical nested non-terminals: Not too big,
+** or may overflow the C stack...
+*/
+#define LUA_MAXPARSERLEVEL 200
+
+
+/* maximum number of variables declared in a function */
+#define MAXVARS 200 /* <MAXSTACK */
+
+
+/* maximum number of upvalues per function */
+#define MAXUPVALUES 32 /* <MAXSTACK */
+
+
+/* maximum size of expressions for optimizing `while' code */
+#define MAXEXPWHILE 100
+
+
+/* function to convert a lua_Number to int (with any rounding method) */
+#if defined(__GNUC__) && defined(__i386)
+#define lua_number2int(i,d) __asm__ ("fistpl %0":"=m"(i):"t"(d):"st")
+#elif 0
+/* on machines compliant with C99, you can try `lrint' */
+#include <math.h>
+#define lua_number2int(i,d) ((i)=lrint(d))
+#else
+#define lua_number2int(i,d) ((i)=(int)(d))
+#endif
+
+/* function to convert a lua_Number to lua_Integer (with any rounding method) */
+#define lua_number2integer(i,n) lua_number2int(i,n)
+
+
+/* function to convert a lua_Number to a string */
+#include <stdio.h>
+#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
+
+/* function to convert a string to a lua_Number */
+#define lua_str2number(s,p) strtod((s), (p))
+
+
+
+/* result of a `usual argument conversion' over lua_Number */
+#define LUA_UACNUMBER double
+
+
+/* number of bits in an `int' */
+/* avoid overflows in comparison */
+#if INT_MAX-20 < 32760
+#define LUA_BITSINT 16
+#elif INT_MAX > 2147483640L
+/* machine has at least 32 bits */
+#define LUA_BITSINT 32
+#else
+#error "you must define LUA_BITSINT with number of bits in an integer"
+#endif
+
+
+/* type to ensure maximum alignment */
+#define LUSER_ALIGNMENT_T union { double u; void *s; long l; }
+
+
+/* exception handling */
+#ifndef __cplusplus
+/* default handling with long jumps */
+#include <setjmp.h>
+#define L_THROW(c) longjmp((c)->b, 1)
+#define L_TRY(c,a) if (setjmp((c)->b) == 0) { a }
+#define l_jmpbuf jmp_buf
+
+#else
+/* C++ exceptions */
+#define L_THROW(c) throw(c)
+#define L_TRY(c,a) try { a } catch(...) \
+ { if ((c)->status == 0) (c)->status = -1; }
+#define l_jmpbuf int /* dummy variable */
+#endif
+
+
+
+/*
+** macros for thread synchronization inside Lua core machine:
+** all accesses to the global state and to global objects are synchronized.
+** Because threads can read the stack of other threads
+** (when running garbage collection),
+** a thread must also synchronize any write-access to its own stack.
+** Unsynchronized accesses are allowed only when reading its own stack,
+** or when reading immutable fields from global objects
+** (such as string values and udata values).
+*/
+#define lua_lock(L) ((void) 0)
+#define lua_unlock(L) ((void) 0)
+
+/*
+** this macro allows a thread switch in appropriate places in the Lua
+** core
+*/
+#define lua_threadyield(L) {lua_unlock(L); lua_lock(L);}
+
+
+
+/* allows user-specific initialization on new threads */
+#define lua_userstateopen(l) /* empty */
+
+
+#endif
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** Library configuration
+** =======================================================
+*/
+
+#ifdef LUA_LIB
+
+
+
+/* `assert' options */
+
+/* environment variable that holds the search path for packages */
+#define LUA_PATH "LUA_PATH"
+
+/* separator of templates in a path */
+#define LUA_PATH_SEP ';'
+
+/* wild char in each template */
+#define LUA_PATH_MARK "?"
+
+
+/* maximum number of captures in pattern-matching */
+#define MAX_CAPTURES 32 /* arbitrary limit */
+
+
+/*
+** by default, gcc does not get `tmpname'
+*/
+#ifdef __GNUC__
+#define USE_TMPNAME 0
+#else
+#define USE_TMPNAME 1
+#endif
+
+
+
+#endif
+
+/* }====================================================== */
+
+
+
+
+/* Local configuration */
+
+#undef USE_TMPNAME
+#define USE_TMPNAME 1
+
+#endif
diff --git a/include/lualib.h b/include/lualib.h
index e22c4c30..c8114ed2 100644
--- a/include/lualib.h
+++ b/include/lualib.h
@@ -1,5 +1,5 @@
/*
-** $Id: lualib.h,v 1.28 2003/03/18 12:24:26 roberto Exp $
+** $Id: lualib.h,v 1.32 2004/07/09 15:47:48 roberto Exp $
** Lua standard libraries
** See Copyright Notice in lua.h
*/
@@ -11,9 +11,8 @@
#include "lua.h"
-#ifndef LUALIB_API
-#define LUALIB_API LUA_API
-#endif
+/* Key to file-handle type */
+#define LUA_FILEHANDLE "FILE*"
#define LUA_COLIBNAME "coroutine"
@@ -23,9 +22,11 @@ LUALIB_API int luaopen_base (lua_State *L);
LUALIB_API int luaopen_table (lua_State *L);
#define LUA_IOLIBNAME "io"
-#define LUA_OSLIBNAME "os"
LUALIB_API int luaopen_io (lua_State *L);
+#define LUA_OSLIBNAME "os"
+LUALIB_API int luaopen_os (lua_State *L);
+
#define LUA_STRLIBNAME "string"
LUALIB_API int luaopen_string (lua_State *L);
@@ -39,18 +40,8 @@ LUALIB_API int luaopen_debug (lua_State *L);
LUALIB_API int luaopen_loadlib (lua_State *L);
-/* to help testing the libraries */
-#ifndef lua_assert
-#define lua_assert(c) /* empty */
-#endif
-
+/* open all previous libraries */
+LUALIB_API int luaopen_stdlibs (lua_State *L);
-/* compatibility code */
-#define lua_baselibopen luaopen_base
-#define lua_tablibopen luaopen_table
-#define lua_iolibopen luaopen_io
-#define lua_strlibopen luaopen_string
-#define lua_mathlibopen luaopen_math
-#define lua_dblibopen luaopen_debug
#endif
diff --git a/src/RCS b/src/RCS
deleted file mode 120000
index 1ae38936..00000000
--- a/src/RCS
+++ /dev/null
@@ -1 +0,0 @@
-../RCS \ No newline at end of file
diff --git a/src/README b/src/README
index e5375981..915f30b4 100644
--- a/src/README
+++ b/src/README
@@ -1,5 +1,5 @@
This is the Lua core.
The standard Lua library are in lib/.
-A sample interpreter is in lua/.
-A standalone compiler is in luac/.
+The standalone interpreter is in lua/.
+The standalone compiler is in luac/.
diff --git a/src/lapi.c b/src/lapi.c
index 1b086a0b..eb2c266e 100644
--- a/src/lapi.c
+++ b/src/lapi.c
@@ -1,5 +1,5 @@
/*
-** $Id: lapi.c,v 2.5 2004/03/23 17:07:34 roberto Exp $
+** $Id: lapi.c,v 2.18 2004/08/30 13:44:44 roberto Exp $
** Lua API
** See Copyright Notice in lua.h
*/
@@ -10,6 +10,7 @@
#include <string.h>
#define lapi_c
+#define LUA_CORE
#include "lua.h"
@@ -28,11 +29,6 @@
#include "lvm.h"
-/* function to convert a lua_Number to lua_Integer (with any rounding method) */
-#ifndef lua_number2integer
-#define lua_number2integer(i,n) ((i)=(lua_Integer)(n))
-#endif
-
const char lua_ident[] =
"$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n"
@@ -41,10 +37,6 @@ const char lua_ident[] =
-#ifndef api_check
-#define api_check(L, o) lua_assert(o)
-#endif
-
#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
#define api_checkvalidindex(L, i) api_check(L, (i) != &luaO_nilobject)
@@ -56,7 +48,7 @@ const char lua_ident[] =
static TValue *luaA_index (lua_State *L, int idx) {
if (idx > 0) {
TValue *o = L->base + (idx - 1);
- api_check(L, idx <= L->stack_last - L->base);
+ api_check(L, idx <= L->ci->top - L->base);
if (o >= L->top) return cast(TValue *, &luaO_nilobject);
else return o;
}
@@ -87,7 +79,7 @@ void luaA_pushobject (lua_State *L, const TValue *o) {
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) > MAXCSTACK)
res = 0; /* stack overflow */
else {
luaD_checkstack(L, size);
@@ -331,10 +323,12 @@ LUA_API const char *lua_tostring (lua_State *L, int idx) {
}
-LUA_API size_t lua_strlen (lua_State *L, int idx) {
+LUA_API size_t lua_objsize (lua_State *L, int idx) {
StkId o = luaA_index(L, idx);
if (ttisstring(o))
return tsvalue(o)->len;
+ else if (ttisuserdata(o))
+ return uvalue(o)->len;
else {
size_t l;
lua_lock(L); /* `luaV_tostring' may create a new string */
@@ -496,7 +490,7 @@ LUA_API void lua_gettable (lua_State *L, int idx) {
lua_lock(L);
t = luaA_index(L, idx);
api_checkvalidindex(L, t);
- luaV_gettable(L, t, L->top - 1, L->top - 1);
+ luaV_gettable(L, t, L->top - 1, L->top - 1, NULL);
lua_unlock(L);
}
@@ -508,7 +502,7 @@ LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
t = luaA_index(L, idx);
api_checkvalidindex(L, t);
setsvalue(L, &key, luaS_new(L, k));
- luaV_gettable(L, t, &key, L->top);
+ luaV_gettable(L, t, &key, L->top, NULL);
api_incr_top(L);
lua_unlock(L);
}
@@ -592,7 +586,7 @@ LUA_API void lua_settable (lua_State *L, int idx) {
api_checknelems(L, 2);
t = luaA_index(L, idx);
api_checkvalidindex(L, t);
- luaV_settable(L, t, L->top - 2, L->top - 1);
+ luaV_settable(L, t, L->top - 2, L->top - 1, NULL);
L->top -= 2; /* pop index and value */
lua_unlock(L);
}
@@ -606,7 +600,7 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
t = luaA_index(L, idx);
api_checkvalidindex(L, t);
setsvalue(L, &key, luaS_new(L, k));
- luaV_settable(L, t, &key, L->top - 1);
+ luaV_settable(L, t, &key, L->top - 1, NULL);
L->top--; /* pop value */
lua_unlock(L);
}
@@ -619,7 +613,7 @@ LUA_API void lua_rawset (lua_State *L, int idx) {
t = luaA_index(L, idx);
api_check(L, ttistable(t));
setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);
- luaC_barrier(L, hvalue(t), L->top-1);
+ luaC_barriert(L, hvalue(t), L->top-1);
L->top -= 2;
lua_unlock(L);
}
@@ -632,7 +626,7 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
o = luaA_index(L, idx);
api_check(L, ttistable(o));
setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
- luaC_barrier(L, hvalue(o), L->top-1);
+ luaC_barriert(L, hvalue(o), L->top-1);
L->top--;
lua_unlock(L);
}
@@ -683,12 +677,13 @@ LUA_API int lua_setfenv (lua_State *L, int idx) {
api_checknelems(L, 1);
o = luaA_index(L, idx);
api_checkvalidindex(L, o);
- L->top--;
- api_check(L, ttistable(L->top));
+ api_check(L, ttistable(L->top - 1));
if (isLfunction(o)) {
res = 1;
- clvalue(o)->l.g = *(L->top);
+ clvalue(o)->l.g = *(L->top - 1);
+ luaC_objbarrier(L, clvalue(o), hvalue(L->top - 1));
}
+ L->top--;
lua_unlock(L);
return res;
}
@@ -698,12 +693,23 @@ LUA_API int lua_setfenv (lua_State *L, int idx) {
** `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);
}
@@ -730,6 +736,8 @@ LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
int status;
ptrdiff_t func;
lua_lock(L);
+ api_checknelems(L, nargs+1);
+ checkresults(L, nargs, nresults);
if (errfunc == 0)
func = 0;
else {
@@ -740,6 +748,7 @@ LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
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;
}
@@ -812,28 +821,41 @@ LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) {
*/
LUA_API int lua_gc (lua_State *L, int what, int data) {
- global_State *g = G(L);
+ int res = 0;
+ global_State *g;
+ lua_lock(L);
+ g = G(L);
switch (what) {
case LUA_GCSTOP: {
g->GCthreshold = MAXLMEM;
- return 0;
+ break;
}
case LUA_GCRESTART: {
- g->GCthreshold = g->nblocks;
- return 0;
+ g->GCthreshold = g->totalbytes;
+ break;
}
case LUA_GCCOLLECT: {
- lua_lock(L);
luaC_fullgc(L);
- lua_unlock(L);
- return 0;
+ break;
}
case LUA_GCCOUNT: {
/* GC values are expressed in Kbytes: #bytes/2^10 */
- return cast(int, g->nblocks >> 10);
+ res = cast(int, g->totalbytes >> 10);
+ 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;
+ luaC_step(L);
+ break;
}
- default: return -1; /* invalid option */
+ default: res = -1; /* invalid option */
}
+ lua_unlock(L);
+ return res;
}
@@ -916,13 +938,13 @@ static const char *aux_upvalue (lua_State *L, StkId fi, int n, TValue **val) {
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;
+ if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
*val = f->l.upvals[n-1]->v;
return getstr(p->upvalues[n-1]);
}
diff --git a/src/lcode.c b/src/lcode.c
index de6939bb..54ef0581 100644
--- a/src/lcode.c
+++ b/src/lcode.c
@@ -1,5 +1,5 @@
/*
-** $Id: lcode.c,v 2.1 2003/12/10 12:13:36 roberto Exp $
+** $Id: lcode.c,v 2.6 2004/08/24 20:09:11 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,7 @@
#include <stdlib.h>
#define lcode_c
+#define LUA_CORE
#include "lua.h"
@@ -194,7 +195,7 @@ void luaK_reserveregs (FuncState *fs, int n) {
static void freereg (FuncState *fs, int reg) {
- if (reg >= fs->nactvar && reg < MAXSTACK) {
+ if (!ISK(reg) && reg >= fs->nactvar) {
fs->freereg--;
lua_assert(reg == fs->freereg);
}
@@ -222,7 +223,7 @@ static int addk (FuncState *fs, TValue *k, TValue *v) {
MAXARG_Bx, "constant table overflow");
while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
setobj(L, &f->k[fs->nk], v);
- luaC_barrier(L, f, v);
+ luaC_barriert(L, f, v);
return fs->nk++;
}
}
@@ -251,13 +252,26 @@ static int nil_constant (FuncState *fs) {
}
-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->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 */
}
}
@@ -285,8 +299,9 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
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) */
@@ -403,16 +418,16 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
luaK_exp2val(fs, e);
switch (e->k) {
case VNIL: {
- if (fs->nk + MAXSTACK <= MAXARG_C) { /* constant fit in argC? */
+ if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */
e->info = nil_constant(fs);
e->k = VK;
- return e->info + MAXSTACK;
+ return RKASK(e->info);
}
else break;
}
case VK: {
- if (e->info + MAXSTACK <= MAXARG_C) /* constant fit in argC? */
- return e->info + MAXSTACK;
+ if (e->info <= MAXINDEXRK) /* constant fit in argC? */
+ return RKASK(e->info);
else break;
}
default: break;
diff --git a/src/lcode.h b/src/lcode.h
index 74908c65..b854d5cd 100644
--- a/src/lcode.h
+++ b/src/lcode.h
@@ -1,5 +1,5 @@
/*
-** $Id: lcode.h,v 1.38 2002/12/11 12:34:22 roberto Exp $
+** $Id: lcode.h,v 1.39 2004/05/31 18:51:50 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -41,6 +41,8 @@ typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr;
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
+#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
+
int luaK_code (FuncState *fs, Instruction i, int line);
int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
@@ -60,7 +62,8 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
void luaK_goiftrue (FuncState *fs, expdesc *e);
void luaK_goiffalse (FuncState *fs, expdesc *e);
void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
-void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults);
+void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
+void luaK_setoneret (FuncState *fs, expdesc *e);
int luaK_jump (FuncState *fs);
void luaK_patchlist (FuncState *fs, int list, int target);
void luaK_patchtohere (FuncState *fs, int list);
diff --git a/src/ldebug.c b/src/ldebug.c
index 42080ccd..139e4cdb 100644
--- a/src/ldebug.c
+++ b/src/ldebug.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldebug.c,v 2.3 2004/03/23 13:10:16 roberto Exp $
+** $Id: ldebug.c,v 2.8 2004/09/01 13:47:31 roberto Exp $
** Debug Interface
** See Copyright Notice in lua.h
*/
@@ -11,6 +11,7 @@
#define ldebug_c
+#define LUA_CORE
#include "lua.h"
@@ -34,7 +35,7 @@ static const char *getfuncname (CallInfo *ci, const char **name);
static int currentpc (CallInfo *ci) {
if (!isLua(ci)) return -1; /* function is not a Lua function? */
- return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p);
+ return pcRel(ci->savedpc, ci_func(ci)->l.p);
}
@@ -85,7 +86,7 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
level--;
if (f_isLua(ci)) /* Lua function? */
- level -= ci->u.l.tailcalls; /* skip lost tail calls */
+ level -= ci->tailcalls; /* skip lost tail calls */
}
if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */
else if (level < 0) { /* level is of a lost tail call */
@@ -220,8 +221,8 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
}
else if (ar->i_ci != 0) { /* no tail call? */
CallInfo *ci = L->base_ci + ar->i_ci;
- lua_assert(ttisfunction(ci->base - 1));
- status = auxgetinfo(L, what, ar, ci->base - 1, ci);
+ lua_assert(ttisfunction(ci->func));
+ status = auxgetinfo(L, what, ar, ci->func, ci);
}
else
info_tailcall(L, ar);
@@ -254,8 +255,9 @@ static int precheck (const Proto *pt) {
}
-static int checkopenop (const Proto *pt, int pc) {
- Instruction i = pt->code[pc+1];
+#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1])
+
+int luaG_checkopenop (Instruction i) {
switch (GET_OPCODE(i)) {
case OP_CALL:
case OP_TAILCALL:
@@ -274,8 +276,8 @@ static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {
case OpArgN: check(r == 0); break;
case OpArgU: break;
case OpArgR: checkreg(pt, r); break;
- case OpArgK:
- check(r < pt->maxstacksize || (r >= MAXSTACK && r-MAXSTACK < pt->sizek));
+ case OpArgK:
+ check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);
break;
}
return 1;
@@ -355,7 +357,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
}
case OP_TFORLOOP: {
checkreg(pt, a+5); /* space for control variables */
- if (reg >= a) last = pc; /* affect all registers above base */
+ if (reg >= a+3) last = pc; /* affect all regs above its call base */
break;
}
case OP_TFORPREP:
@@ -404,6 +406,13 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
}
break;
}
+ case OP_VARARG: {
+ check(pt->is_vararg & NEWSTYLEVARARG);
+ b--;
+ if (b == LUA_MULTRET) check(checkopenop(pt, pc));
+ checkreg(pt, a+b-1);
+ break;
+ }
default: break;
}
}
@@ -423,9 +432,8 @@ int luaG_checkcode (const Proto *pt) {
static const char *kname (Proto *p, int c) {
- c = c - MAXSTACK;
- if (c >= 0 && ttisstring(&p->k[c]))
- return svalue(&p->k[c]);
+ if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))
+ return svalue(&p->k[INDEXK(c)]);
else
return "?";
}
@@ -479,11 +487,12 @@ static const char *getobjname (CallInfo *ci, int stackpos, const char **name) {
static const char *getfuncname (CallInfo *ci, const char **name) {
Instruction i;
- if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci - 1))
+ if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1))
return NULL; /* calling function is not Lua (or is unknown) */
ci--; /* calling function */
i = ci_func(ci)->l.p->code[currentpc(ci)];
- if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL)
+ if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
+ GET_OPCODE(i) == OP_TFORLOOP)
return getobjname(ci, GETARG_A(i), name);
else
return NULL; /* no useful name can be found */
diff --git a/src/ldebug.h b/src/ldebug.h
index d7163f2d..5d8d2c2e 100644
--- a/src/ldebug.h
+++ b/src/ldebug.h
@@ -1,5 +1,5 @@
/*
-** $Id: ldebug.h,v 2.1 2003/12/10 12:13:36 roberto Exp $
+** $Id: ldebug.h,v 2.2 2004/06/02 19:07:55 roberto Exp $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/
@@ -25,6 +25,6 @@ int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2);
void luaG_runerror (lua_State *L, const char *fmt, ...);
void luaG_errormsg (lua_State *L);
int luaG_checkcode (const Proto *pt);
-
+int luaG_checkopenop (Instruction i);
#endif
diff --git a/src/ldo.c b/src/ldo.c
index b65c5610..46ad459a 100644
--- a/src/ldo.c
+++ b/src/ldo.c
@@ -1,15 +1,15 @@
/*
-** $Id: ldo.c,v 2.2 2004/03/23 17:02:58 roberto Exp $
+** $Id: ldo.c,v 2.7 2004/06/02 19:07:55 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
-#include <setjmp.h>
#include <stdlib.h>
#include <string.h>
#define ldo_c
+#define LUA_CORE
#include "lua.h"
@@ -34,29 +34,15 @@
/*
** {======================================================
-** Error-recovery functions (based on long jumps)
+** Error-recovery functions
** =======================================================
*/
-#ifndef LUA_USEEXCEPTIONS
-
-#define L_THROW(c) longjmp((c)->b, 1)
-#define L_TRY(c,a) if (setjmp((c)->b) == 0) { a }
-
-#else
-
-#define L_THROW(c) throw(c)
-#define L_TRY(c,a) try { a } catch(...) \
- { if ((c)->status == 0) (c)->status = -1; }
-
-#endif
-
-
/* chain list of long jump buffers */
struct lua_longjmp {
struct lua_longjmp *previous;
- jmp_buf b;
+ l_jmpbuf b;
volatile int status; /* error code */
};
@@ -127,6 +113,7 @@ static void correctstack (lua_State *L, TValue *oldstack) {
for (ci = L->base_ci; ci <= L->ci; ci++) {
ci->top = (ci->top - oldstack) + L->stack;
ci->base = (ci->base - oldstack) + L->stack;
+ ci->func = (ci->func - oldstack) + L->stack;
}
L->base = L->ci->base;
}
@@ -195,26 +182,37 @@ void luaD_callhook (lua_State *L, int event, int line) {
}
-static void adjust_varargs (lua_State *L, int nfixargs, StkId base) {
+static StkId adjust_varargs (lua_State *L, int nfixargs, int actual,
+ int style) {
int i;
- Table *htab;
- int actual = L->top - base; /* actual number of arguments */
+ Table *htab = NULL;
+ StkId base, fixed;
if (actual < nfixargs) {
- luaD_checkstack(L, nfixargs - actual);
for (; actual < nfixargs; ++actual)
setnilvalue(L->top++);
}
- actual -= nfixargs; /* number of extra arguments */
- htab = luaH_new(L, actual, 1); /* create `arg' table */
- for (i=0; i<actual; i++) /* put extra arguments into `arg' table */
- setobj2n(L, luaH_setnum(L, htab, i+1), L->top - actual + i);
- /* store counter in field `n' */
- setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")),
- cast(lua_Number, actual));
- L->top -= actual; /* remove extra elements from the stack */
- sethvalue(L, L->top, htab);
- lua_assert(iswhite(obj2gco(htab)));
- incr_top(L);
+ if (style != NEWSTYLEVARARG) { /* compatibility with old-style vararg */
+ int nvar = actual - nfixargs; /* number of extra arguments */
+ htab = luaH_new(L, nvar, 1); /* create `arg' table */
+ for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
+ setobj2n(L, luaH_setnum(L, htab, i+LUA_FIRSTINDEX), L->top - nvar + i);
+ /* store counter in field `n' */
+ setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")),
+ cast(lua_Number, nvar));
+ }
+ /* move fixed parameters to final position */
+ fixed = L->top - actual; /* first fixed argument */
+ base = L->top; /* final position of first argument */
+ for (i=0; i<nfixargs; i++) {
+ setobjs2s(L, L->top++, fixed+i);
+ setnilvalue(fixed+i);
+ }
+ /* add `arg' parameter */
+ if (htab) {
+ sethvalue(L, L->top++, htab);
+ lua_assert(iswhite(obj2gco(htab)));
+ }
+ return base;
}
@@ -233,44 +231,60 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
}
-StkId luaD_precall (lua_State *L, StkId func) {
+int luaD_precall (lua_State *L, StkId func, int nresults) {
LClosure *cl;
- ptrdiff_t funcr = savestack(L, func);
+ ptrdiff_t funcr;
if (!ttisfunction(func)) /* `func' is not a function? */
func = tryfuncTM(L, func); /* check the `function' tag method */
+ funcr = savestack(L, func);
if (L->ci + 1 == L->end_ci) luaD_growCI(L);
else condhardstacktests(luaD_reallocCI(L, L->size_ci));
cl = &clvalue(func)->l;
if (!cl->isC) { /* Lua function? prepare its call */
CallInfo *ci;
- StkId st;
+ StkId st, base;
Proto *p = cl->p;
- if (p->is_vararg) /* varargs? */
- adjust_varargs(L, p->numparams, func+1);
luaD_checkstack(L, p->maxstacksize);
+ func = restorestack(L, funcr);
+ if (p->is_vararg) { /* varargs? */
+ int nargs = L->top - func - 1;
+ base = adjust_varargs(L, p->numparams, nargs, p->is_vararg);
+ }
+ else
+ base = func + 1;
ci = ++L->ci; /* now `enter' new function */
- L->base = L->ci->base = restorestack(L, funcr) + 1;
+ ci->func = func;
+ L->base = ci->base = base;
ci->top = L->base + p->maxstacksize;
- ci->u.l.savedpc = p->code; /* starting point */
- ci->u.l.tailcalls = 0;
+ ci->savedpc = p->code; /* starting point */
+ ci->tailcalls = 0;
+ ci->nresults = nresults;
for (st = L->top; st < ci->top; st++)
setnilvalue(st);
L->top = ci->top;
- return NULL;
+ return PCRLUA;
}
else { /* if is a C function, call it */
CallInfo *ci;
int n;
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
ci = ++L->ci; /* now `enter' new function */
- L->base = L->ci->base = restorestack(L, funcr) + 1;
+ ci->func = restorestack(L, funcr);
+ L->base = ci->base = ci->func + 1;
ci->top = L->top + LUA_MINSTACK;
if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1);
lua_unlock(L);
n = (*curr_func(L)->c.f)(L); /* do the actual call */
lua_lock(L);
- return L->top - n;
+ if (n >= 0) { /* no yielding? */
+ luaD_poscall(L, nresults, L->top - n);
+ return PCRC;
+ }
+ else {
+ ci->nresults = nresults;
+ return PCRYIELD;
+ }
}
}
@@ -279,7 +293,7 @@ static StkId callrethooks (lua_State *L, StkId firstResult) {
ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
luaD_callhook(L, LUA_HOOKRET, -1);
if (f_isLua(L->ci)) { /* Lua function? */
- while (L->ci->u.l.tailcalls--) /* call hook for eventual tail calls */
+ while (L->ci->tailcalls--) /* call hook for eventual tail calls */
luaD_callhook(L, LUA_HOOKTAILRET, -1);
}
return restorestack(L, fr);
@@ -290,7 +304,7 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
StkId res;
if (L->hookmask & LUA_MASKRET)
firstResult = callrethooks(L, firstResult);
- res = L->base - 1; /* res == final position of 1st result */
+ res = L->ci->func; /* res == final position of 1st result */
L->ci--;
L->base = L->ci->base; /* restore base */
/* move results to correct place */
@@ -311,17 +325,16 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
** function position.
*/
void luaD_call (lua_State *L, StkId func, int nResults) {
- StkId firstResult;
if (++L->nCcalls >= LUA_MAXCCALLS) {
if (L->nCcalls == LUA_MAXCCALLS)
luaG_runerror(L, "C stack overflow");
else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3)))
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
}
- firstResult = luaD_precall(L, func);
- if (firstResult == NULL) /* is a Lua function? */
- firstResult = luaV_execute(L, 1); /* call it */
- luaD_poscall(L, nResults, firstResult);
+ if (luaD_precall(L, func, nResults) == PCRLUA) { /* is a Lua function? */
+ StkId firstResult = luaV_execute(L, 1); /* call it */
+ luaD_poscall(L, nResults, firstResult);
+ }
L->nCcalls--;
luaC_checkGC(L);
}
@@ -333,15 +346,14 @@ static void resume (lua_State *L, void *ud) {
CallInfo *ci = L->ci;
if (!L->isSuspended) {
lua_assert(ci == L->base_ci && nargs < L->top - L->base);
- luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */
+ luaD_precall(L, L->top - (nargs + 1), LUA_MULTRET); /* start coroutine */
}
else { /* resuming from previous yield */
if (!f_isLua(ci)) { /* `common' yield? */
/* finish interrupted execution of `OP_CALL' */
- int nresults;
- lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
- GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
- nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1;
+ int nresults = ci->nresults;
+ lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
+ GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);
luaD_poscall(L, nresults, L->top - nargs); /* complete it */
if (nresults >= 0) L->top = L->ci->top;
} /* else yielded inside a hook: just continue its execution */
diff --git a/src/ldo.h b/src/ldo.h
index 85511f2c..d4072b60 100644
--- a/src/ldo.h
+++ b/src/ldo.h
@@ -1,5 +1,5 @@
/*
-** $Id: ldo.h,v 2.1 2003/12/10 12:13:36 roberto Exp $
+** $Id: ldo.h,v 2.2 2004/05/14 19:25:09 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -38,13 +38,19 @@
#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n)))
+/* results from luaD_precall */
+#define PCRLUA 0 /* initiated a call to a Lua function */
+#define PCRC 1 /* did a call to a C function */
+#define PCRYIELD 2 /* C funtion yielded */
+
+
/* type of protected functions, to be ran by `runprotected' */
typedef void (*Pfunc) (lua_State *L, void *ud);
void luaD_resetprotection (lua_State *L);
int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);
void luaD_callhook (lua_State *L, int event, int line);
-StkId luaD_precall (lua_State *L, StkId func);
+int luaD_precall (lua_State *L, StkId func, int nresults);
void luaD_call (lua_State *L, StkId func, int nResults);
int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t oldtop, ptrdiff_t ef);
diff --git a/src/ldump.c b/src/ldump.c
index dc4ebad1..bd0becb9 100644
--- a/src/ldump.c
+++ b/src/ldump.c
@@ -1,12 +1,13 @@
/*
-** $Id: ldump.c,v 1.6 2004/03/24 00:25:08 lhf Exp $
-** save bytecodes
+** $Id: ldump.c,v 1.8 2004/09/01 21:22:34 lhf Exp $
+** save pre-compiled Lua chunks
** See Copyright Notice in lua.h
*/
#include <stddef.h>
#define ldump_c
+#define LUA_CORE
#include "lua.h"
@@ -20,16 +21,20 @@
typedef struct {
lua_State* L;
- lua_Chunkwriter write;
+ lua_Chunkwriter writer;
void* data;
int strip;
+ int status;
} DumpState;
static void DumpBlock(const void* b, size_t size, DumpState* D)
{
- lua_unlock(D->L);
- (*D->write)(D->L,b,size,D->data);
- lua_lock(D->L);
+ if (D->status==0)
+ {
+ lua_unlock(D->L);
+ D->status=(*D->writer)(D->L,b,size,D->data);
+ lua_lock(D->L);
+ }
}
static void DumpByte(int y, DumpState* D)
@@ -53,7 +58,7 @@ static void DumpNumber(lua_Number x, DumpState* D)
DumpBlock(&x,sizeof(x),D);
}
-static void DumpString(TString* s, DumpState* D)
+static void DumpString(const TString* s, DumpState* D)
{
if (s==NULL || getstr(s)==NULL)
DumpSize(0,D);
@@ -153,16 +158,17 @@ static void DumpHeader(DumpState* D)
}
/*
-** dump function as precompiled chunk
+** dump Lua function as precompiled chunk
*/
-int luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data, int strip)
+int luaU_dump (lua_State* L, const Proto* f, lua_Chunkwriter w, void* data, int strip)
{
DumpState D;
D.L=L;
- D.write=w;
+ D.writer=w;
D.data=data;
D.strip=strip;
+ D.status=0;
DumpHeader(&D);
- DumpFunction(Main,NULL,&D);
- return 1;
+ DumpFunction(f,NULL,&D);
+ return D.status;
}
diff --git a/src/lfunc.c b/src/lfunc.c
index d9f4e27e..7d4fbf20 100644
--- a/src/lfunc.c
+++ b/src/lfunc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lfunc.c,v 2.3 2004/03/15 21:04:33 roberto Exp $
+** $Id: lfunc.c,v 2.4 2004/04/30 20:13:38 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,7 @@
#include <stddef.h>
#define lfunc_c
+#define LUA_CORE
#include "lua.h"
diff --git a/src/lgc.c b/src/lgc.c
index db1b1c89..67a5f1f6 100644
--- a/src/lgc.c
+++ b/src/lgc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.c,v 2.6 2004/03/23 12:57:12 roberto Exp $
+** $Id: lgc.c,v 2.10 2004/08/30 13:44:44 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -7,6 +7,7 @@
#include <string.h>
#define lgc_c
+#define LUA_CORE
#include "lua.h"
@@ -22,10 +23,11 @@
#include "ltm.h"
-#define GCSTEPSIZE (40*sizeof(TValue))
-#define GCFREECOST (sizeof(TValue)/2)
-#define GCSWEEPCOST sizeof(TValue)
-#define GCFINALIZECOST (10*sizeof(TValue))
+#define GCSTEPSIZE 1000
+#define STEPMUL 2
+#define GCSWEEPMAX 10
+#define GCSWEEPCOST 30
+#define GCFINALIZECOST 100
#define FIXEDMASK bitmask(FIXEDBIT)
@@ -266,60 +268,61 @@ static void traversestack (global_State *g, lua_State *l) {
/*
-** traverse a given `quantity' of gray objects,
-** turning them to black. Returns extra `quantity' traversed.
+** traverse one gray object, turning it to black.
+** Returns `quantity' traversed.
*/
-static l_mem propagatemarks (global_State *g, l_mem lim) {
- GCObject *o;
- while ((o = g->gray) != NULL) {
- lua_assert(isgray(o));
- gray2black(o);
- switch (o->gch.tt) {
- case LUA_TTABLE: {
- Table *h = gco2h(o);
- g->gray = h->gclist;
- if (traversetable(g, h)) /* table is weak? */
- black2gray(o); /* keep it gray */
- lim -= sizeof(Table) + sizeof(TValue) * h->sizearray +
- sizeof(Node) * sizenode(h);
- break;
- }
- case LUA_TFUNCTION: {
- Closure *cl = gco2cl(o);
- g->gray = cl->c.gclist;
- traverseclosure(g, cl);
- lim -= (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
- sizeLclosure(cl->l.nupvalues);
- break;
- }
- case LUA_TTHREAD: {
- lua_State *th = gco2th(o);
- g->gray = th->gclist;
- th->gclist = g->grayagain;
- g->grayagain = o;
- black2gray(o);
- traversestack(g, th);
- lim -= sizeof(lua_State) + sizeof(TValue) * th->stacksize +
- sizeof(CallInfo) * th->size_ci;
- break;
- }
- case LUA_TPROTO: {
- Proto *p = gco2p(o);
- g->gray = p->gclist;
- traverseproto(g, p);
- lim -= sizeof(Proto) + sizeof(Instruction) * p->sizecode +
- sizeof(Proto *) * p->sizep +
- sizeof(TValue) * p->sizek +
- sizeof(int) * p->sizelineinfo +
- sizeof(LocVar) * p->sizelocvars +
- sizeof(TString *) * p->sizeupvalues;
- break;
- }
- default: lua_assert(0);
+static l_mem propagatemark (global_State *g) {
+ GCObject *o = g->gray;
+ lua_assert(isgray(o));
+ gray2black(o);
+ switch (o->gch.tt) {
+ case LUA_TTABLE: {
+ Table *h = gco2h(o);
+ g->gray = h->gclist;
+ if (traversetable(g, h)) /* table is weak? */
+ black2gray(o); /* keep it gray */
+ return sizeof(Table) + sizeof(TValue) * h->sizearray +
+ sizeof(Node) * sizenode(h);
+ break;
+ }
+ case LUA_TFUNCTION: {
+ Closure *cl = gco2cl(o);
+ g->gray = cl->c.gclist;
+ traverseclosure(g, cl);
+ return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
+ sizeLclosure(cl->l.nupvalues);
+ break;
+ }
+ case LUA_TTHREAD: {
+ lua_State *th = gco2th(o);
+ g->gray = th->gclist;
+ th->gclist = g->grayagain;
+ g->grayagain = o;
+ black2gray(o);
+ traversestack(g, th);
+ return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
+ sizeof(CallInfo) * th->size_ci;
+ break;
+ }
+ case LUA_TPROTO: {
+ Proto *p = gco2p(o);
+ g->gray = p->gclist;
+ traverseproto(g, p);
+ return sizeof(Proto) + sizeof(Instruction) * p->sizecode +
+ sizeof(Proto *) * p->sizep +
+ sizeof(TValue) * p->sizek +
+ sizeof(int) * p->sizelineinfo +
+ sizeof(LocVar) * p->sizelocvars +
+ sizeof(TString *) * p->sizeupvalues;
+ break;
}
- if (lim <= 0) return lim;
+ default: lua_assert(0); return 0;
}
- return lim;
+}
+
+
+static void propagateall (global_State *g) {
+ while (g->gray) propagatemark(g);
}
@@ -381,6 +384,7 @@ static void freeobj (lua_State *L, GCObject *o) {
break;
}
case LUA_TSTRING: {
+ G(L)->strt.nuse--;
luaM_free(L, o, sizestring(gco2ts(o)->len));
break;
}
@@ -393,59 +397,45 @@ static void freeobj (lua_State *L, GCObject *o) {
}
-static l_mem sweepwholelist (lua_State *L, GCObject **p, int keepfixed,
- lu_int32 *count);
+
+#define sweepwholelist(L,p) sweeplist(L,p,LUA_MAXINT32)
-static GCObject **sweeplist (lua_State *L, GCObject **p, int keepfixed,
- l_mem *plim, lu_int32 *count) {
+static GCObject **sweeplist (lua_State *L, GCObject **p, lu_int32 count) {
GCObject *curr;
global_State *g = G(L);
- l_mem lim = *plim;
- int deadmask = otherwhite(g);
- if (keepfixed) deadmask |= FIXEDMASK;
- while ((curr = *p) != NULL) {
- if (((curr->gch.marked ^ FIXEDMASK) & deadmask) != deadmask) {
- makewhite(g, curr);
+ int whitebit = otherwhite(g);
+ int deadmask = whitebit | FIXEDMASK;
+ int generational = g->gcgenerational;
+ while ((curr = *p) != NULL && count-- > 0) {
+ if ((curr->gch.marked ^ whitebit) & deadmask) {
+ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));
+ if (!generational || isdead(g, curr))
+ makewhite(g, curr);
if (curr->gch.tt == LUA_TTHREAD)
- lim -= sweepwholelist(L, &gco2th(curr)->openupval, keepfixed, count);
+ sweepwholelist(L, &gco2th(curr)->openupval);
p = &curr->gch.next;
- lim -= GCSWEEPCOST;
}
else {
- lua_assert(iswhite(curr));
+ lua_assert(isdead(g, curr));
*p = curr->gch.next;
if (curr == g->rootgc) /* is the first element of the list? */
g->rootgc = curr->gch.next; /* adjust first */
freeobj(L, curr);
- lim -= GCFREECOST;
- if (count) (*count)--;
}
- if (lim <= 0) break;
}
- *plim = lim;
return p;
}
-static l_mem sweepwholelist (lua_State *L, GCObject **p, int keepfixed,
- lu_int32 *count) {
- l_mem lim = MAXLMEM;
- /* empty lists are quite common here, so avoid useless calls */
- if (*p) sweeplist(L, p, keepfixed, &lim, count);
- return MAXLMEM - lim;
-}
-
-static l_mem sweepstrings (lua_State *L, int keepfixed, l_mem lim) {
- int i;
- global_State *g = G(L);
- for (i = g->sweepstrgc; i < g->strt.size; i++) { /* for each list */
- lim -= sweepwholelist(L, &G(L)->strt.hash[i], keepfixed, &g->strt.nuse);
- if (lim <= 0) break;
+static void freelist (lua_State *L, GCObject **p) {
+ while (*p) {
+ GCObject *curr = *p;
+ *p = (*p)->gch.next;
+ if (curr != obj2gco(L))
+ freeobj(L, curr);
}
- g->sweepstrgc = i+1;
- return lim;
}
@@ -494,19 +484,12 @@ void luaC_callGCTM (lua_State *L) {
}
-void luaC_sweepall (lua_State *L) {
+void luaC_freeall (lua_State *L) {
global_State *g = G(L);
- l_mem dummy = MAXLMEM;
- /* finish (occasional) current sweep */
- sweepstrings(L, 0, MAXLMEM);
- sweeplist(L, &g->rootgc, 0, &dummy, NULL);
- /* do a whole new sweep */
- markobject(g, g->mainthread); /* cannot collect main thread */
- g->currentwhite = otherwhite(g);
- g->sweepgc = &g->rootgc;
- g->sweepstrgc = 0;
- sweepstrings(L, 0, MAXLMEM);
- sweeplist(L, &g->rootgc, 0, &dummy, NULL);
+ int i;
+ freelist(L, &g->rootgc);
+ for (i = 0; i < g->strt.size; i++) /* free all string lists */
+ freelist(L, &G(L)->strt.hash[i]);
}
@@ -530,8 +513,10 @@ static void remarkupvals (global_State *g) {
if (iswhite(o)) {
GCObject *curr;
for (curr = gco2th(o)->openupval; curr != NULL; curr = curr->gch.next) {
- if (isgray(curr))
- markvalue(g, gco2uv(curr)->v);
+ if (isgray(curr)) {
+ UpVal *uv = gco2uv(curr);
+ markvalue(g, uv->v);
+ }
}
}
}
@@ -540,6 +525,7 @@ static void remarkupvals (global_State *g) {
static void atomic (lua_State *L) {
global_State *g = G(L);
+ int aux;
lua_assert(g->gray == NULL);
/* remark occasional upvalues of (maybe) dead threads */
remarkupvals(g);
@@ -548,90 +534,130 @@ static void atomic (lua_State *L) {
g->weak = NULL;
lua_assert(!iswhite(obj2gco(g->mainthread)));
markobject(g, L); /* mark running thread */
- propagatemarks(g, MAXLMEM);
+ propagateall(g);
/* remark gray again */
g->gray = g->grayagain;
g->grayagain = NULL;
- propagatemarks(g, MAXLMEM);
+ propagateall(g);
luaC_separateudata(L, 0); /* separate userdata to be preserved */
marktmu(g); /* mark `preserved' userdata */
- propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */
+ propagateall(g); /* remark, to propagate `preserveness' */
cleartable(g->weak); /* remove collected objects from weak tables */
/* flip current white */
g->currentwhite = otherwhite(g);
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
g->gcstate = GCSsweepstring;
+ aux = g->gcgenerational;
+ g->gcgenerational = (g->estimate <= 4*g->prevestimate/2);
+ if (!aux) /* last collection was full? */
+ g->prevestimate = g->estimate; /* keep estimate of last full collection */
+ g->estimate = g->totalbytes; /* first estimate */
}
-static l_mem singlestep (lua_State *L, l_mem lim) {
+static l_mem singlestep (lua_State *L) {
global_State *g = G(L);
+ /*lua_checkmemory(L);*/
switch (g->gcstate) {
+ case GCSpause: {
+ /* start a new collection */
+ if (g->gcgenerational)
+ atomic(L);
+ else
+ markroot(L);
+ return 0;
+ }
case GCSpropagate: {
if (g->gray)
- lim = propagatemarks(g, lim);
+ return propagatemark(g);
else { /* no more `gray' objects */
atomic(L); /* finish mark phase */
- lim = 0;
+ return 0;
}
- break;
}
case GCSsweepstring: {
- lim = sweepstrings(L, 1, lim);
- if (g->sweepstrgc >= g->strt.size) { /* nothing more to sweep? */
- g->sweepstrgc = 0;
+ lu_mem old = g->totalbytes;
+ sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
+ if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
g->gcstate = GCSsweep; /* end sweep-string phase */
- }
- break;
+ g->estimate -= old - g->totalbytes;
+ return GCSWEEPCOST;
}
case GCSsweep: {
- g->sweepgc = sweeplist(L, g->sweepgc, 1, &lim, NULL);
+ lu_mem old = g->totalbytes;
+ g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
if (*g->sweepgc == NULL) { /* nothing more to sweep? */
checkSizes(L);
- g->sweepgc = &g->rootgc;
g->gcstate = GCSfinalize; /* end sweep phase */
}
- break;
+ g->estimate -= old - g->totalbytes;
+ return GCSWEEPMAX*GCSWEEPCOST;
}
case GCSfinalize: {
if (g->tmudata) {
GCTM(L);
- lim -= GCFINALIZECOST;
+ return GCFINALIZECOST;
}
- else { /* no more `udata' to finalize */
- markroot(L); /* may restart collection */
- lim = 0;
+ else {
+ g->gcstate = GCSpause; /* end collection */
+ return 0;
}
- break;
}
- default: lua_assert(0);
+ default: lua_assert(0); return 0;
}
- return lim;
}
void luaC_step (lua_State *L) {
global_State *g = G(L);
- l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2;
+ l_mem lim = (g->totalbytes - (g->GCthreshold - GCSTEPSIZE)) * STEPMUL;
+/*printf("step(%c): ", g->gcgenerational?'g':' ');*/
do {
- lim = singlestep(L, lim);
- if (g->gcstate == GCSfinalize && g->tmudata == NULL)
- break; /* do not start new collection */
+ /*printf("%c", "_pswf"[g->gcstate]);*/
+ lim -= singlestep(L);
+ if (g->gcstate == GCSpause)
+ break;
} while (lim > 0);
- g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2;
- lua_assert((long)g->nblocks + (long)GCSTEPSIZE >= lim/2);
+/*printf("\n");*/
+ if (g->gcstate != GCSpause)
+ g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/STEPMUL; */
+ else {
+/*printf("---\n");*/
+ lua_assert(g->totalbytes >= g->estimate);
+ g->GCthreshold = 2*g->estimate;
+ if (g->GCthreshold < g->totalbytes + GCSTEPSIZE)
+ g->GCthreshold = g->totalbytes + GCSTEPSIZE;
+ }
}
void luaC_fullgc (lua_State *L) {
global_State *g = G(L);
+ if (g->gcstate <= GCSpropagate || g->gcgenerational) {
+ g->gcgenerational = 0;
+ /* reset sweep marks to sweep all elements (returning them to white) */
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
+ /* reset other collector lists */
+ g->gray = NULL;
+ g->grayagain = NULL;
+ g->weak = NULL;
+ g->gcstate = GCSsweepstring;
+ }
+ /* finish any pending sweep phase */
while (g->gcstate != GCSfinalize) {
- singlestep(L, MAXLMEM);
+ lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
+ singlestep(L);
}
markroot(L);
+ lua_assert(!g->gcgenerational);
while (g->gcstate != GCSfinalize) {
- singlestep(L, MAXLMEM);
+ singlestep(L);
+ g->gcgenerational = 0; /* keep it in this mode */
}
- g->GCthreshold = g->nblocks + GCSTEPSIZE;
+ lua_assert(g->estimate == g->totalbytes);
+ g->GCthreshold = 2*g->estimate;
luaC_callGCTM(L); /* call finalizers */
}
@@ -639,7 +665,7 @@ void luaC_fullgc (lua_State *L) {
void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
global_State *g = G(L);
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
- lua_assert(g->gcstate != GCSfinalize);
+ lua_assert(g->gcgenerational || g->gcstate != GCSfinalize);
if (g->gcstate != GCSpropagate) /* sweeping phases? */
black2gray(o); /* just mark as gray to avoid other barriers */
else /* breaking invariant! */
@@ -647,6 +673,16 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
}
+void luaC_barrierback (lua_State *L, GCObject *o, GCObject *v) {
+ global_State *g = G(L);
+ lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
+ lua_assert(g->gcgenerational || g->gcstate != GCSfinalize);
+ black2gray(o); /* make table gray (again) */
+ gco2h(o)->gclist = g->grayagain;
+ g->grayagain = o;
+}
+
+
void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
global_State *g = G(L);
o->gch.next = g->rootgc;
@@ -662,13 +698,13 @@ void luaC_linkupval (lua_State *L, UpVal *uv) {
o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */
g->rootgc = o;
if (isgray(o)) {
- if (g->gcstate == GCSpropagate) {
+ if (g->gcstate == GCSpropagate || g->gcgenerational) {
gray2black(o); /* closed upvalues need barrier */
luaC_barrier(L, uv, uv->v);
}
else { /* sweep phase: sweep it (turning it into white) */
makewhite(g, o);
- lua_assert(g->gcstate != GCSfinalize);
+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
}
}
}
diff --git a/src/lgc.h b/src/lgc.h
index 1ff59860..47a5e932 100644
--- a/src/lgc.h
+++ b/src/lgc.h
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.h,v 2.5 2004/03/15 21:04:33 roberto Exp $
+** $Id: lgc.h,v 2.8 2004/08/30 13:44:44 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -14,10 +14,11 @@
/*
** Possible states of the Garbage Collector
*/
-#define GCSpropagate 0
-#define GCSsweepstring 1
-#define GCSsweep 2
-#define GCSfinalize 3
+#define GCSpause 0
+#define GCSpropagate 1
+#define GCSsweepstring 2
+#define GCSsweep 3
+#define GCSfinalize 4
/*
@@ -39,12 +40,13 @@
/*
** Layout for bit use in `marked' field:
-** bit 0 - object is gray
-** bit 1 - object is black
-** bit 2 - For userdata: is finalized;
- for tables: has weak keys
-** bit 3 - for tables: has weak values
-** bit 4 - object is fixed (should not be collected)
+** bit 0 - object is white (type 0)
+** bit 1 - object is white (type 1)
+** bit 2 - object is black
+** bit 3 - for userdata: has been finalized
+** bit 3 - for tables: has weak keys
+** bit 4 - for tables: has weak values
+** bit 5 - object is fixed (should not be collected)
*/
#define WHITE0BIT 0
@@ -70,25 +72,29 @@
#define luaC_white(g) cast(lu_byte, (g)->currentwhite)
-#define luaC_checkGC(L) { if (G(L)->nblocks >= G(L)->GCthreshold) \
+#define luaC_checkGC(L) { if (G(L)->totalbytes >= G(L)->GCthreshold) \
luaC_step(L); }
#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \
luaC_barrierf(L,obj2gco(p),gcvalue(v)); }
+#define luaC_barriert(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \
+ luaC_barrierback(L,obj2gco(p),gcvalue(v)); }
+
#define luaC_objbarrier(L,p,o) \
{ if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \
luaC_barrierf(L,obj2gco(p),obj2gco(o)); }
size_t luaC_separateudata (lua_State *L, int all);
void luaC_callGCTM (lua_State *L);
-void luaC_sweepall (lua_State *L);
+void luaC_freeall (lua_State *L);
void luaC_step (lua_State *L);
void luaC_fullgc (lua_State *L);
void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
void luaC_linkupval (lua_State *L, UpVal *uv);
void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
+void luaC_barrierback (lua_State *L, GCObject *o, GCObject *v);
#endif
diff --git a/src/lib/Makefile b/src/lib/Makefile
index 3c6c07ab..74f65215 100644
--- a/src/lib/Makefile
+++ b/src/lib/Makefile
@@ -6,8 +6,8 @@ include $(LUA)/config
EXTRA_DEFS= $(POPEN) $(TMPNAM) $(DEGREES) $(LOADLIB)
-OBJS= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o ltablib.o lstrlib.o loadlib.o
-SRCS= lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c ltablib.c lstrlib.c loadlib.c
+OBJS= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o lstrlib.o loadlib.o linit.o
+SRCS= lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c ltablib.c lstrlib.c loadlib.c linit.c
T= $(LIB)/liblualib.a
diff --git a/src/lib/RCS b/src/lib/RCS
deleted file mode 120000
index 1ae38936..00000000
--- a/src/lib/RCS
+++ /dev/null
@@ -1 +0,0 @@
-../RCS \ No newline at end of file
diff --git a/src/lib/lauxlib.c b/src/lib/lauxlib.c
index 96131019..cd4e75f8 100644
--- a/src/lib/lauxlib.c
+++ b/src/lib/lauxlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lauxlib.c,v 1.110 2004/03/23 16:38:43 roberto Exp $
+** $Id: lauxlib.c,v 1.123 2004/08/30 18:35:14 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -18,6 +18,7 @@
*/
#define lauxlib_c
+#define LUA_LIB
#include "lua.h"
@@ -62,7 +63,7 @@ LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {
const char *msg = lua_pushfstring(L, "%s expected, got %s",
- tname, lua_typename(L, lua_type(L,narg)));
+ tname, luaL_typename(L, narg));
return luaL_argerror(L, narg, msg);
}
@@ -242,6 +243,8 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
if (lua_isnil(L, -1)) { /* no? */
lua_pop(L, 1);
lua_newtable(L); /* create it */
+ if (lua_getmetatable(L, LUA_GLOBALSINDEX))
+ lua_setmetatable(L, -2); /* share metatable with global table */
lua_pushvalue(L, -1);
/* register it with given name */
lua_setglobal(L, libname);
@@ -288,7 +291,7 @@ static void getsizes (lua_State *L) {
}
-void luaL_setn (lua_State *L, int t, int n) {
+LUALIB_API void luaL_setn (lua_State *L, int t, int n) {
t = abs_index(L, t);
getsizes(L);
lua_pushvalue(L, t);
@@ -298,7 +301,32 @@ void luaL_setn (lua_State *L, int t, int n) {
}
-int luaL_getn (lua_State *L, int t) {
+/* find an `n' such that t[n] ~= nil and t[n+1] == nil */
+static int countn (lua_State *L, int t) {
+ int i = LUA_FIRSTINDEX - 1;
+ int j = 2;
+ /* find `i' such that i <= n < i*2 (= j) */
+ for (;;) {
+ lua_rawgeti(L, t, j);
+ if (lua_isnil(L, -1)) break;
+ lua_pop(L, 1);
+ i = j;
+ j = i*2;
+ }
+ lua_pop(L, 1);
+ /* i <= n < j; do a binary search */
+ while (i < j-1) {
+ int m = (i+j)/2;
+ lua_rawgeti(L, t, m);
+ if (lua_isnil(L, -1)) j = m;
+ else i = m;
+ lua_pop(L, 1);
+ }
+ return i - LUA_FIRSTINDEX + 1;
+}
+
+
+LUALIB_API int luaL_getn (lua_State *L, int t) {
int n;
t = abs_index(L, t);
getsizes(L); /* try sizes[t] */
@@ -307,18 +335,61 @@ int luaL_getn (lua_State *L, int t) {
if ((n = checkint(L, 2)) >= 0) return n;
lua_getfield(L, t, "n"); /* else try t.n */
if ((n = checkint(L, 1)) >= 0) return n;
- for (n = 1; ; n++) { /* else must count elements */
- lua_rawgeti(L, t, n);
- if (lua_isnil(L, -1)) break;
- lua_pop(L, 1);
- }
- lua_pop(L, 1);
- return n - 1;
+ return countn(L, t);
}
/* }====================================================== */
+static const char *pushnexttemplate (lua_State *L, const char *path) {
+ const char *l;
+ if (*path == '\0') return NULL; /* no more templates */
+ if (*path == LUA_PATH_SEP) path++; /* skip separator */
+ l = strchr(path, LUA_PATH_SEP); /* find next separator */
+ if (l == NULL) l = path+strlen(path);
+ lua_pushlstring(L, path, l - path); /* template */
+ return l;
+}
+
+
+static const char *luaL_gsub (lua_State *L, const char *s,
+ const char *p, const char *r) {
+ const char *wild;
+ int 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 (`n' already includes this) */
+ luaL_pushresult(&b);
+ return lua_tostring(L, -1);
+}
+
+
+LUALIB_API const char *luaL_searchpath (lua_State *L, const char *name,
+ const char *path) {
+ FILE *f;
+ const char *p = path;
+ for (;;) {
+ const char *fname;
+ if ((p = pushnexttemplate(L, p)) == NULL) {
+ lua_pushfstring(L, "no readable `%s' in path `%s'", name, path);
+ return NULL;
+ }
+ fname = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);
+ lua_remove(L, -2); /* remove path template */
+ f = fopen(fname, "r"); /* try to read it */
+ if (f) {
+ fclose(f);
+ return fname;
+ }
+ lua_pop(L, 1); /* remove file name */
+ }
+}
+
/*
** {======================================================
@@ -480,9 +551,10 @@ static const char *getF (lua_State *L, void *ud, size_t *size) {
}
-static int errfile (lua_State *L, int fnameindex) {
+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 read %s: %s", filename, strerror(errno));
+ lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
lua_remove(L, fnameindex);
return LUA_ERRFILE;
}
@@ -501,7 +573,7 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
else {
lua_pushfstring(L, "@%s", filename);
lf.f = fopen(filename, "r");
- if (lf.f == NULL) return errfile(L, fnameindex); /* unable to open file */
+ if (lf.f == NULL) return errfile(L, "open", fnameindex);
}
c = getc(lf.f);
if (c == '#') { /* Unix exec. file? */
@@ -512,7 +584,7 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
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, fnameindex); /* unable to reopen file */
+ if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
/* skip eventual `#!...' */
while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
lf.extraline = 0;
@@ -523,7 +595,7 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
if (lf.f != stdin) fclose(lf.f); /* close file (even in case of errors) */
if (readstatus) {
lua_settop(L, fnameindex); /* ignore results from `lua_load' */
- return errfile(L, fnameindex);
+ return errfile(L, "read", fnameindex);
}
lua_remove(L, fnameindex);
return status;
@@ -554,6 +626,7 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
return lua_load(L, getS, &ls, name);
}
+
/* }====================================================== */
@@ -568,55 +641,15 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
}
-LUALIB_API lua_State *luaL_newstate (void) {
- return lua_newstate(l_alloc, NULL);
-}
-
-
-/*
-** {======================================================
-** compatibility code
-** =======================================================
-*/
-
-
-static void callalert (lua_State *L, int status) {
- if (status != 0) {
- lua_getglobal(L, "_ALERT");
- if (lua_isfunction(L, -1)) {
- lua_insert(L, -2);
- lua_call(L, 1, 0);
- }
- else { /* no _ALERT function; print it on stderr */
- fprintf(stderr, "%s\n", lua_tostring(L, -2));
- lua_pop(L, 2); /* remove error message and _ALERT */
- }
- }
+static int panic (lua_State *L) {
+ fprintf(stderr, "PANIC: unprotected error during Lua-API call\n");
+ return 0;
}
-static int aux_do (lua_State *L, int status) {
- if (status == 0) { /* parse OK? */
- status = lua_pcall(L, 0, LUA_MULTRET, 0); /* call main */
- }
- callalert(L, status);
- return status;
-}
-
-
-LUALIB_API int lua_dofile (lua_State *L, const char *filename) {
- return aux_do(L, luaL_loadfile(L, filename));
-}
-
-
-LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size,
- const char *name) {
- return aux_do(L, luaL_loadbuffer(L, buff, size, name));
-}
-
-
-LUALIB_API int lua_dostring (lua_State *L, const char *str) {
- return lua_dobuffer(L, str, strlen(str), str);
+LUALIB_API lua_State *luaL_newstate (void) {
+ lua_State *L = lua_newstate(l_alloc, NULL);
+ lua_atpanic(L, &panic);
+ return L;
}
-/* }====================================================== */
diff --git a/src/lib/lbaselib.c b/src/lib/lbaselib.c
index 42b0355a..f734f358 100644
--- a/src/lib/lbaselib.c
+++ b/src/lib/lbaselib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lbaselib.c,v 1.140 2004/03/09 17:34:35 roberto Exp $
+** $Id: lbaselib.c,v 1.156 2004/08/30 18:35:14 roberto Exp $
** Basic library
** See Copyright Notice in lua.h
*/
@@ -12,6 +12,7 @@
#include <string.h>
#define lbaselib_c
+#define LUA_LIB
#include "lua.h"
@@ -128,18 +129,9 @@ static void getfunc (lua_State *L) {
}
-static int aux_getfenv (lua_State *L) {
- lua_getfenv(L, -1);
- lua_pushliteral(L, "__fenv");
- lua_rawget(L, -2);
- return !lua_isnil(L, -1);
-}
-
-
static int luaB_getfenv (lua_State *L) {
getfunc(L);
- if (!aux_getfenv(L)) /* __fenv not defined? */
- lua_pop(L, 1); /* remove it, to return real environment */
+ lua_getfenv(L, -1);
return 1;
}
@@ -147,16 +139,14 @@ static int luaB_getfenv (lua_State *L) {
static int luaB_setfenv (lua_State *L) {
luaL_checktype(L, 2, LUA_TTABLE);
getfunc(L);
- if (aux_getfenv(L)) /* __fenv defined? */
- luaL_error(L, "`setfenv' cannot change a protected environment");
- else
- lua_pop(L, 2); /* remove __fenv and real environment table */
lua_pushvalue(L, 2);
- if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0)
+ if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
lua_replace(L, LUA_GLOBALSINDEX);
+ return 0;
+ }
else if (lua_setfenv(L, -2) == 0)
luaL_error(L, "`setfenv' cannot change environment of given function");
- return 0;
+ return 1;
}
@@ -192,22 +182,11 @@ static int luaB_gcinfo (lua_State *L) {
static int luaB_collectgarbage (lua_State *L) {
static const char *const opts[] = {"stop", "restart", "collect", "count",
- NULL};
+ "step", NULL};
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART,
- LUA_GCCOLLECT, LUA_GCCOUNT};
- int o;
- int ex;
-#if 1
- if (lua_isnumber(L, 1)) {
- int v = lua_tointeger(L, 1);
- lua_settop(L, 0);
- if (v == 0) lua_pushstring(L, "collect");
- else if (v >= 10000) lua_pushstring(L, "stop");
- else lua_pushstring(L, "restart");
- }
-#endif
- o = luaL_findstring(luaL_optstring(L, 1, "collect"), opts);
- ex = luaL_optint(L, 2, 0);
+ LUA_GCCOLLECT, LUA_GCCOUNT, LUA_GCSTEP};
+ int o = luaL_findstring(luaL_optstring(L, 1, "collect"), opts);
+ int ex = luaL_optint(L, 2, 0);
luaL_argcheck(L, o >= 0, 1, "invalid option");
lua_pushinteger(L, lua_gc(L, optsnum[o], ex));
return 1;
@@ -216,7 +195,7 @@ static int luaB_collectgarbage (lua_State *L) {
static int luaB_type (lua_State *L) {
luaL_checkany(L, 1);
- lua_pushstring(L, lua_typename(L, lua_type(L, 1)));
+ lua_pushstring(L, luaL_typename(L, 1));
return 1;
}
@@ -235,28 +214,29 @@ static int luaB_next (lua_State *L) {
static int luaB_pairs (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
- lua_getglobal(L, "next"); /* return generator, */
+ 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) {
- int i = (int)lua_tointeger(L, 2);
luaL_checktype(L, 1, LUA_TTABLE);
- if (i == 0 && lua_isnone(L, 2)) { /* `for' start? */
- lua_getglobal(L, "ipairs"); /* return generator, */
- lua_pushvalue(L, 1); /* state, */
- lua_pushinteger(L, 0); /* and initial value */
- return 3;
- }
- else { /* `for' step */
- i++; /* next value */
- lua_pushinteger(L, i);
- lua_rawgeti(L, 1, i);
- return (lua_isnil(L, -1)) ? 0 : 2;
- }
+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
+ lua_pushvalue(L, 1); /* state, */
+ lua_pushinteger(L, LUA_FIRSTINDEX - 1); /* and initial value */
+ return 3;
}
@@ -281,7 +261,15 @@ static int luaB_loadstring (lua_State *L) {
static int luaB_loadfile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
- return load_aux(L, luaL_loadfile(L, fname));
+ const char *path = luaL_optstring(L, 2, NULL);
+ int status;
+ if (path == NULL)
+ status = luaL_loadfile(L, fname);
+ else {
+ fname = luaL_searchpath(L, fname, path);
+ status = (fname) ? luaL_loadfile(L, fname) : 1;
+ }
+ return load_aux(L, status);
}
@@ -339,22 +327,41 @@ static int luaB_assert (lua_State *L) {
luaL_checkany(L, 1);
if (!lua_toboolean(L, 1))
return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
- lua_settop(L, 1);
- return 1;
+ return lua_gettop(L);
}
static int luaB_unpack (lua_State *L) {
- int n, i;
+ int i = luaL_optint(L, 2, LUA_FIRSTINDEX);
+ int e = luaL_optint(L, 3, -1);
+ int n;
luaL_checktype(L, 1, LUA_TTABLE);
- n = luaL_getn(L, 1);
+ if (e == -1)
+ e = luaL_getn(L, 1) + LUA_FIRSTINDEX - 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=1; i<=n; i++) /* push arg[1...n] */
+ 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 = 1;
+ else if (i >= n) i = n;
+ return n - i;
+ }
+}
+
+
static int luaB_pcall (lua_State *L) {
int status;
luaL_checkany(L, 1);
@@ -378,45 +385,36 @@ static int luaB_xpcall (lua_State *L) {
static int luaB_tostring (lua_State *L) {
- char buff[4*sizeof(void *) + 2]; /* enough space for a `%p' */
- const char *tn = "";
- const void *p = NULL;
luaL_checkany(L, 1);
if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */
return 1; /* use its value */
switch (lua_type(L, 1)) {
case LUA_TNUMBER:
lua_pushstring(L, lua_tostring(L, 1));
- return 1;
+ break;
case LUA_TSTRING:
lua_pushvalue(L, 1);
- return 1;
+ break;
case LUA_TBOOLEAN:
lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
- return 1;
+ break;
case LUA_TNIL:
lua_pushliteral(L, "nil");
- return 1;
+ break;
case LUA_TTABLE:
- p = lua_topointer(L, 1);
- tn = "table";
+ lua_pushfstring(L, "table: %p", lua_topointer(L, 1));
break;
case LUA_TFUNCTION:
- p = lua_topointer(L, 1);
- tn = "function";
+ lua_pushfstring(L, "function: %p", lua_topointer(L, 1));
break;
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA:
- p = lua_touserdata(L, 1);
- tn = "userdata";
+ lua_pushfstring(L, "userdata: %p", lua_topointer(L, 1));
break;
case LUA_TTHREAD:
- p = lua_tothread(L, 1);
- tn = "thread";
+ lua_pushfstring(L, "thread: %p", lua_topointer(L, 1));
break;
}
- sprintf(buff, "%p", p);
- lua_pushfstring(L, "%s: %s", tn, buff);
return 1;
}
@@ -454,112 +452,38 @@ static int luaB_newproxy (lua_State *L) {
*/
-/* name of global that holds table with loaded packages */
-#define REQTAB "_LOADED"
-
-/* name of global that holds the search path for packages */
-#define LUA_PATH "LUA_PATH"
-
-#ifndef LUA_PATH_SEP
-#define LUA_PATH_SEP ';'
-#endif
-
-#ifndef LUA_PATH_MARK
-#define LUA_PATH_MARK '?'
-#endif
-
-#ifndef LUA_PATH_DEFAULT
-#define LUA_PATH_DEFAULT "?;?.lua"
-#endif
-
-
static const char *getpath (lua_State *L) {
- const char *path;
- lua_getglobal(L, LUA_PATH); /* try global variable */
- path = lua_tostring(L, -1);
- lua_pop(L, 1);
- if (path) return path;
- path = getenv(LUA_PATH); /* else try environment variable */
- if (path) return path;
- return LUA_PATH_DEFAULT; /* else use default */
-}
-
-
-static const char *pushnextpath (lua_State *L, const char *path) {
- const char *l;
- if (*path == '\0') return NULL; /* no more paths */
- if (*path == LUA_PATH_SEP) path++; /* skip separator */
- l = strchr(path, LUA_PATH_SEP); /* find next separator */
- if (l == NULL) l = path+strlen(path);
- lua_pushlstring(L, path, l - path); /* directory name */
- return l;
-}
-
-
-static void pushcomposename (lua_State *L) {
- const char *path = lua_tostring(L, -1);
- const char *wild;
- int n = 1;
- while ((wild = strchr(path, LUA_PATH_MARK)) != NULL) {
- /* is there stack space for prefix, name, and eventual last suffix? */
- luaL_checkstack(L, 3, "too many marks in a path component");
- lua_pushlstring(L, path, wild - path); /* push prefix */
- lua_pushvalue(L, 1); /* push package name (in place of MARK) */
- path = wild + 1; /* continue after MARK */
- n += 2;
+ /* try first `LUA_PATH' for compatibility */
+ lua_getfield(L, LUA_GLOBALSINDEX, "LUA_PATH");
+ if (!lua_isstring(L, -1)) {
+ lua_pop(L, 1);
+ lua_getfield(L, LUA_GLOBALSINDEX, "_PATH");
}
- lua_pushstring(L, path); /* push last suffix (`n' already includes this) */
- lua_concat(L, n);
+ if (!lua_isstring(L, -1))
+ luaL_error(L, "global _PATH must be a string");
+ return lua_tostring(L, -1);
}
static int luaB_require (lua_State *L) {
- const char *path;
- int status = LUA_ERRFILE; /* not found (yet) */
- luaL_checkstring(L, 1);
- lua_settop(L, 1);
- lua_getglobal(L, REQTAB);
- if (!lua_istable(L, 2)) return luaL_error(L, "`" REQTAB "' is not a table");
- path = getpath(L);
- lua_pushvalue(L, 1); /* check package's name in book-keeping table */
- lua_rawget(L, 2);
+ const char *name = luaL_checkstring(L, 1);
+ const char *fname;
+ lua_getfield(L, lua_upvalueindex(1), name);
if (lua_toboolean(L, -1)) /* is it there? */
return 1; /* package is already loaded; return its result */
- else { /* must load it */
- while (status == LUA_ERRFILE) {
- lua_settop(L, 3); /* reset stack position */
- if ((path = pushnextpath(L, path)) == NULL) break;
- pushcomposename(L);
- status = luaL_loadfile(L, lua_tostring(L, -1)); /* try to load it */
- }
- }
- switch (status) {
- case 0: {
- lua_getglobal(L, "_REQUIREDNAME"); /* save previous name */
- lua_insert(L, -2); /* put it below function */
- lua_pushvalue(L, 1);
- lua_setglobal(L, "_REQUIREDNAME"); /* set new name */
- lua_call(L, 0, 1); /* run loaded module */
- lua_insert(L, -2); /* put result below previous name */
- lua_setglobal(L, "_REQUIREDNAME"); /* reset to previous name */
- if (lua_isnil(L, -1)) { /* no/nil return? */
- lua_pushboolean(L, 1);
- lua_replace(L, -2); /* replace to true */
- }
- lua_pushvalue(L, 1);
- lua_pushvalue(L, -2);
- lua_rawset(L, 2); /* mark it as loaded */
- return 1; /* return value */
- }
- case LUA_ERRFILE: { /* file not found */
- return luaL_error(L, "could not load package `%s' from path `%s'",
- lua_tostring(L, 1), getpath(L));
- }
- default: {
- return luaL_error(L, "error loading package `%s' (%s)",
- lua_tostring(L, 1), lua_tostring(L, -1));
- }
- }
+ /* else must load it; first mark it as loaded */
+ lua_pushboolean(L, 1);
+ lua_setfield(L, lua_upvalueindex(1), name); /* _LOADED[name] = true */
+ fname = luaL_searchpath(L, name, getpath(L));
+ if (fname == NULL || luaL_loadfile(L, fname) != 0)
+ return luaL_error(L, "error loading package `%s' (%s)", name,
+ lua_tostring(L, -1));
+ lua_pushvalue(L, 1); /* pass name as argument to module */
+ lua_call(L, 1, 1); /* run loaded module */
+ if (!lua_isnil(L, -1)) /* nil return? */
+ lua_setfield(L, lua_upvalueindex(1), name);
+ lua_getfield(L, lua_upvalueindex(1), name); /* return _LOADED[name] */
+ return 1;
}
/* }====================================================== */
@@ -572,14 +496,13 @@ static const luaL_reg base_funcs[] = {
{"getfenv", luaB_getfenv},
{"setfenv", luaB_setfenv},
{"next", luaB_next},
- {"ipairs", luaB_ipairs},
- {"pairs", luaB_pairs},
{"print", luaB_print},
{"tonumber", luaB_tonumber},
{"tostring", luaB_tostring},
{"type", luaB_type},
{"assert", luaB_assert},
{"unpack", luaB_unpack},
+ {"select", luaB_select},
{"rawequal", luaB_rawequal},
{"rawget", luaB_rawget},
{"rawset", luaB_rawset},
@@ -591,7 +514,6 @@ static const luaL_reg base_funcs[] = {
{"dofile", luaB_dofile},
{"loadstring", luaB_loadstring},
{"load", luaB_load},
- {"require", luaB_require},
{NULL, NULL}
};
@@ -704,12 +626,23 @@ static const luaL_reg co_funcs[] = {
/* }====================================================== */
+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) {
+ const char *path;
lua_pushvalue(L, LUA_GLOBALSINDEX);
luaL_openlib(L, NULL, base_funcs, 0); /* open lib into global table */
lua_pushliteral(L, LUA_VERSION);
- lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */
+ lua_setfield(L, LUA_GLOBALSINDEX, "_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_newtable(L); /* new table `w' */
lua_pushvalue(L, -1); /* `w' will be its own metatable */
@@ -717,16 +650,27 @@ static void base_open (lua_State *L) {
lua_pushliteral(L, "kv");
lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
lua_pushcclosure(L, luaB_newproxy, 1);
- lua_setfield(L, -2, "newproxy"); /* set global `newproxy' */
- lua_setfield(L, -1, "_G"); /* set global _G */
+ lua_setfield(L, LUA_GLOBALSINDEX, "newproxy"); /* set global `newproxy' */
+ /* `require' needs a table to keep loaded chunks */
+ lua_newtable(L);
+ lua_pushvalue(L, -1);
+ lua_setglobal(L, "_LOADED");
+ lua_pushcclosure(L, luaB_require, 1);
+ lua_setfield(L, LUA_GLOBALSINDEX, "require");
+ /* set global _G */
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ lua_setfield(L, LUA_GLOBALSINDEX, "_G");
+ /* set global _PATH */
+ path = getenv(LUA_PATH);
+ if (path == NULL) path = LUA_PATH_DEFAULT;
+ lua_pushstring(L, path);
+ lua_setfield(L, LUA_GLOBALSINDEX, "_PATH");
}
LUALIB_API int luaopen_base (lua_State *L) {
base_open(L);
luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0);
- lua_newtable(L);
- lua_setglobal(L, REQTAB);
return 2;
}
diff --git a/src/lib/ldblib.c b/src/lib/ldblib.c
index dd4e0363..4ec5f393 100644
--- a/src/lib/ldblib.c
+++ b/src/lib/ldblib.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldblib.c,v 1.84 2003/11/05 11:59:14 roberto Exp $
+** $Id: ldblib.c,v 1.87 2004/08/13 18:02:36 roberto Exp $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
@@ -10,6 +10,7 @@
#include <string.h>
#define ldblib_c
+#define LUA_LIB
#include "lua.h"
@@ -260,7 +261,11 @@ static int debug (lua_State *L) {
if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
strcmp(buffer, "cont\n") == 0)
return 0;
- lua_dostring(L, buffer);
+ if (luaL_loadbuffer(L, buffer, strlen(buffer), "=debug command") ||
+ lua_pcall(L, 0, 0, 0)) {
+ fputs(lua_tostring(L, -1), stderr);
+ fputs("\n", stderr);
+ }
lua_settop(L, 0); /* remove eventual returns */
}
}
@@ -298,22 +303,16 @@ static int errorfb (lua_State *L) {
lua_pushfstring(L, "%s:", ar.short_src);
if (ar.currentline > 0)
lua_pushfstring(L, "%d:", ar.currentline);
- switch (*ar.namewhat) {
- case 'g': /* global */
- case 'l': /* local */
- case 'f': /* field */
- case 'm': /* method */
+ if (*ar.namewhat != '\0') /* is there a name? */
lua_pushfstring(L, " in function `%s'", ar.name);
- break;
- default: {
- if (*ar.what == 'm') /* main? */
- lua_pushfstring(L, " in main chunk");
- else if (*ar.what == 'C' || *ar.what == 't')
- lua_pushliteral(L, " ?"); /* C function or tail call */
- else
- lua_pushfstring(L, " in function <%s:%d>",
- ar.short_src, ar.linedefined);
- }
+ else {
+ if (*ar.what == 'm') /* main? */
+ lua_pushfstring(L, " in main chunk");
+ else if (*ar.what == 'C' || *ar.what == 't')
+ lua_pushliteral(L, " ?"); /* C function or tail call */
+ else
+ lua_pushfstring(L, " in function <%s:%d>",
+ ar.short_src, ar.linedefined);
}
lua_concat(L, lua_gettop(L) - arg);
}
diff --git a/src/lib/linit.c b/src/lib/linit.c
new file mode 100644
index 00000000..0d5f9cd4
--- /dev/null
+++ b/src/lib/linit.c
@@ -0,0 +1,38 @@
+/*
+** $Id: linit.c,v 1.8 2004/07/09 15:47:48 roberto Exp $
+** Initialization of libraries for lua.c
+** See Copyright Notice in lua.h
+*/
+
+
+#define linit_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lualib.h"
+#include "lauxlib.h"
+
+
+static const luaL_reg lualibs[] = {
+ {"", luaopen_base},
+ {LUA_TABLIBNAME, luaopen_table},
+ {LUA_IOLIBNAME, luaopen_io},
+ {LUA_OSLIBNAME, luaopen_os},
+ {LUA_STRLIBNAME, luaopen_string},
+ {LUA_MATHLIBNAME, luaopen_math},
+ {LUA_DBLIBNAME, luaopen_debug},
+ {"", luaopen_loadlib},
+ {NULL, NULL}
+};
+
+
+LUALIB_API int luaopen_stdlibs (lua_State *L) {
+ const luaL_reg *lib = lualibs;
+ for (; lib->func; lib++) {
+ lib->func(L); /* open library */
+ lua_settop(L, 0); /* discard any results */
+ }
+ return 0;
+}
+
diff --git a/src/lib/liolib.c b/src/lib/liolib.c
index 1815c96b..ca9b8025 100644
--- a/src/lib/liolib.c
+++ b/src/lib/liolib.c
@@ -1,18 +1,17 @@
/*
-** $Id: liolib.c,v 2.49 2003/10/10 13:29:28 roberto Exp $
+** $Id: liolib.c,v 2.57 2004/08/13 19:52:13 roberto Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
#include <errno.h>
-#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <time.h>
#define liolib_c
+#define LUA_LIB
#include "lua.h"
@@ -21,50 +20,13 @@
-/*
-** by default, gcc does not get `tmpname'
-*/
-#ifndef USE_TMPNAME
-#ifdef __GNUC__
-#define USE_TMPNAME 0
-#else
-#define USE_TMPNAME 1
-#endif
-#endif
-
-
-/*
-** by default, posix systems get `popen'
-*/
-#ifndef USE_POPEN
-#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 2
-#define USE_POPEN 1
-#else
-#define USE_POPEN 0
-#endif
-#endif
-
-
-
-
-/*
-** {======================================================
-** FILE Operations
-** =======================================================
-*/
-
-
-#if !USE_POPEN
-#define pclose(f) (-1)
-#endif
-
-
-#define FILEHANDLE "FILE*"
-
#define IO_INPUT 1
#define IO_OUTPUT 2
+static const char *const fnames[] = {"input", "output"};
+
+
static int pushresult (lua_State *L, int i, const char *filename) {
if (i) {
lua_pushboolean(L, 1);
@@ -82,15 +44,21 @@ static int pushresult (lua_State *L, int i, const char *filename) {
}
-static FILE **topfile (lua_State *L, int findex) {
- FILE **f = (FILE **)luaL_checkudata(L, findex, FILEHANDLE);
- if (f == NULL) luaL_argerror(L, findex, "bad file");
+static void fileerror (lua_State *L, int arg, const char *filename) {
+ lua_pushfstring(L, "%s: %s", filename, strerror(errno));
+ luaL_argerror(L, arg, lua_tostring(L, -1));
+}
+
+
+static FILE **topfile (lua_State *L) {
+ FILE **f = (FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE);
+ if (f == NULL) luaL_argerror(L, 1, "bad file");
return f;
}
static int io_type (lua_State *L) {
- FILE **f = (FILE **)luaL_checkudata(L, 1, FILEHANDLE);
+ FILE **f = (FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE);
if (f == NULL) lua_pushnil(L);
else if (*f == NULL)
lua_pushliteral(L, "closed file");
@@ -100,8 +68,8 @@ static int io_type (lua_State *L) {
}
-static FILE *tofile (lua_State *L, int findex) {
- FILE **f = topfile(L, findex);
+static FILE *tofile (lua_State *L) {
+ FILE **f = topfile(L);
if (*f == NULL)
luaL_error(L, "attempt to use a closed file");
return *f;
@@ -117,18 +85,18 @@ static FILE *tofile (lua_State *L, int findex) {
static FILE **newfile (lua_State *L) {
FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
*pf = NULL; /* file handle is currently `closed' */
- luaL_getmetatable(L, FILEHANDLE);
+ luaL_getmetatable(L, LUA_FILEHANDLE);
lua_setmetatable(L, -2);
return pf;
}
static int aux_close (lua_State *L) {
- FILE *f = tofile(L, 1);
+ FILE *f = tofile(L);
if (f == stdin || f == stdout || f == stderr)
return 0; /* file cannot be closed */
else {
- int ok = (pclose(f) != -1) || (fclose(f) == 0);
+ int ok = (fclose(f) == 0);
if (ok)
*(FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */
return ok;
@@ -144,7 +112,7 @@ static int io_close (lua_State *L) {
static int io_gc (lua_State *L) {
- FILE **f = topfile(L, 1);
+ FILE **f = topfile(L);
if (*f != NULL) /* ignore closed files */
aux_close(L);
return 0;
@@ -152,13 +120,11 @@ static int io_gc (lua_State *L) {
static int io_tostring (lua_State *L) {
- char buff[4*sizeof(void *) + 2]; /* enough space for a `%p' */
- FILE **f = topfile(L, 1);
- if (*f == NULL)
- strcpy(buff, "closed");
+ FILE *f = *topfile(L);
+ if (f == NULL)
+ lua_pushstring(L, "file (closed)");
else
- sprintf(buff, "%p", lua_touserdata(L, 1));
- lua_pushfstring(L, "file (%s)", buff);
+ lua_pushfstring(L, "file (%p)", f);
return 1;
}
@@ -172,20 +138,6 @@ static int io_open (lua_State *L) {
}
-static int io_popen (lua_State *L) {
-#if !USE_POPEN
- luaL_error(L, "`popen' not supported");
- return 0;
-#else
- const char *filename = luaL_checkstring(L, 1);
- const char *mode = luaL_optstring(L, 2, "r");
- FILE **pf = newfile(L);
- *pf = popen(filename, mode);
- return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
-#endif
-}
-
-
static int io_tmpfile (lua_State *L) {
FILE **pf = newfile(L);
*pf = tmpfile();
@@ -193,9 +145,14 @@ static int io_tmpfile (lua_State *L) {
}
-static FILE *getiofile (lua_State *L, int f) {
- lua_rawgeti(L, lua_upvalueindex(1), f);
- return tofile(L, -1);
+static FILE *getiofile (lua_State *L, int findex) {
+ FILE *f;
+ lua_rawgeti(L, lua_upvalueindex(1), findex);
+ lua_assert(luaL_checkudata(L, -1, LUA_FILEHANDLE));
+ f = *(FILE **)lua_touserdata(L, -1);
+ if (f == NULL)
+ luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
+ return f;
}
@@ -205,15 +162,14 @@ static int g_iofile (lua_State *L, int f, const char *mode) {
if (filename) {
FILE **pf = newfile(L);
*pf = fopen(filename, mode);
- if (*pf == NULL) {
- lua_pushfstring(L, "%s: %s", filename, strerror(errno));
- luaL_argerror(L, 1, lua_tostring(L, -1));
- }
+ if (*pf == NULL)
+ fileerror(L, 1, filename);
}
else {
- tofile(L, 1); /* check that it's a valid file handle */
+ tofile(L); /* check that it's a valid file handle */
lua_pushvalue(L, 1);
}
+ lua_assert(luaL_checkudata(L, -1, LUA_FILEHANDLE));
lua_rawseti(L, lua_upvalueindex(1), f);
}
/* return current value */
@@ -236,7 +192,7 @@ static int io_readline (lua_State *L);
static void aux_lines (lua_State *L, int idx, int close) {
- lua_getfield(L, LUA_REGISTRYINDEX, FILEHANDLE);
+ lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
lua_pushvalue(L, idx);
lua_pushboolean(L, close); /* close/not close file when finished */
lua_pushcclosure(L, io_readline, 3);
@@ -244,7 +200,7 @@ static void aux_lines (lua_State *L, int idx, int close) {
static int f_lines (lua_State *L) {
- tofile(L, 1); /* check that it's a valid file handle */
+ tofile(L); /* check that it's a valid file handle */
aux_lines(L, 1, 0);
return 1;
}
@@ -260,7 +216,8 @@ static int io_lines (lua_State *L) {
const char *filename = luaL_checkstring(L, 1);
FILE **pf = newfile(L);
*pf = fopen(filename, "r");
- luaL_argcheck(L, *pf, 1, strerror(errno));
+ if (*pf == NULL)
+ fileerror(L, 1, filename);
aux_lines(L, lua_gettop(L), 1);
return 1;
}
@@ -336,6 +293,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
int nargs = lua_gettop(L) - 1;
int success;
int n;
+ clearerr(f);
if (nargs == 0) { /* no arguments? */
success = read_line(L, f);
n = first+1; /* to return 1 result */
@@ -370,6 +328,8 @@ static int g_read (lua_State *L, FILE *f, int first) {
}
}
}
+ if (ferror(f))
+ return pushresult(L, 0, NULL);
if (!success) {
lua_pop(L, 1); /* remove last result */
lua_pushnil(L); /* push nil instead */
@@ -384,15 +344,19 @@ static int io_read (lua_State *L) {
static int f_read (lua_State *L) {
- return g_read(L, tofile(L, 1), 2);
+ return g_read(L, tofile(L), 2);
}
static int io_readline (lua_State *L) {
FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(2));
+ int sucess;
if (f == NULL) /* file is already closed? */
luaL_error(L, "file is already closed");
- if (read_line(L, f)) return 1;
+ sucess = read_line(L, f);
+ if (ferror(f))
+ luaL_error(L, "%s", strerror(errno));
+ if (sucess) return 1;
else { /* EOF */
if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
lua_settop(L, 0);
@@ -431,14 +395,14 @@ static int io_write (lua_State *L) {
static int f_write (lua_State *L) {
- return g_write(L, tofile(L, 1), 2);
+ return g_write(L, tofile(L), 2);
}
static int f_seek (lua_State *L) {
static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
static const char *const modenames[] = {"set", "cur", "end", NULL};
- FILE *f = tofile(L, 1);
+ FILE *f = tofile(L);
int op = luaL_findstring(luaL_optstring(L, 2, "cur"), modenames);
lua_Integer offset = luaL_optinteger(L, 3, 0);
luaL_argcheck(L, op != -1, 2, "invalid mode");
@@ -455,7 +419,7 @@ static int f_seek (lua_State *L) {
static int f_setvbuf (lua_State *L) {
static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
static const char *const modenames[] = {"no", "full", "line", NULL};
- FILE *f = tofile(L, 1);
+ FILE *f = tofile(L);
int op = luaL_findstring(luaL_checkstring(L, 2), modenames);
luaL_argcheck(L, op != -1, 2, "invalid mode");
return pushresult(L, setvbuf(f, NULL, mode[op], 0) == 0, NULL);
@@ -469,7 +433,7 @@ static int io_flush (lua_State *L) {
static int f_flush (lua_State *L) {
- return pushresult(L, fflush(tofile(L, 1)) == 0, NULL);
+ return pushresult(L, fflush(tofile(L)) == 0, NULL);
}
@@ -480,7 +444,6 @@ static const luaL_reg iolib[] = {
{"close", io_close},
{"flush", io_flush},
{"open", io_open},
- {"popen", io_popen},
{"read", io_read},
{"tmpfile", io_tmpfile},
{"type", io_type},
@@ -504,239 +467,36 @@ static const luaL_reg flib[] = {
static void createmeta (lua_State *L) {
- luaL_newmetatable(L, FILEHANDLE); /* create new metatable for file handles */
- /* create (and set) default files */
- *newfile(L) = stdin;
- lua_rawseti(L, -2, IO_INPUT);
- *newfile(L) = stdout;
- lua_rawseti(L, -2, IO_OUTPUT);
- /* file methods */
+ luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
lua_pushvalue(L, -1); /* push metatable */
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
- luaL_openlib(L, NULL, flib, 0);
-}
-
-/* }====================================================== */
-
-
-/*
-** {======================================================
-** Other O.S. Operations
-** =======================================================
-*/
-
-static int io_execute (lua_State *L) {
- lua_pushinteger(L, system(luaL_checkstring(L, 1)));
- return 1;
-}
-
-
-static int io_remove (lua_State *L) {
- const char *filename = luaL_checkstring(L, 1);
- return pushresult(L, remove(filename) == 0, filename);
-}
-
-
-static int io_rename (lua_State *L) {
- const char *fromname = luaL_checkstring(L, 1);
- const char *toname = luaL_checkstring(L, 2);
- return pushresult(L, rename(fromname, toname) == 0, fromname);
-}
-
-
-static int io_tmpname (lua_State *L) {
-#if !USE_TMPNAME
- luaL_error(L, "`tmpname' not supported");
- return 0;
-#else
- char buff[L_tmpnam];
- if (tmpnam(buff) != buff)
- return luaL_error(L, "unable to generate a unique filename in `tmpname'");
- lua_pushstring(L, buff);
- return 1;
-#endif
+ luaL_openlib(L, NULL, flib, 0); /* file methods */
}
-static int io_getenv (lua_State *L) {
- lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
- return 1;
-}
-
-
-static int io_clock (lua_State *L) {
- lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
- return 1;
-}
-
-
-/*
-** {======================================================
-** Time/Date operations
-** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
-** wday=%w+1, yday=%j, isdst=? }
-** =======================================================
-*/
-
-static void setfield (lua_State *L, const char *key, int value) {
- lua_pushstring(L, key);
- lua_pushinteger(L, value);
- lua_rawset(L, -3);
-}
-
-static void setboolfield (lua_State *L, const char *key, int value) {
- lua_pushstring(L, key);
- lua_pushboolean(L, value);
- lua_rawset(L, -3);
-}
-
-static int getboolfield (lua_State *L, const char *key) {
- int res;
- lua_getfield(L, -1, key);
- res = lua_toboolean(L, -1);
- lua_pop(L, 1);
- return res;
-}
-
-
-static int getfield (lua_State *L, const char *key, int d) {
- int res;
- lua_getfield(L, -1, key);
- if (lua_isnumber(L, -1))
- res = (int)lua_tointeger(L, -1);
- else {
- if (d < 0)
- return luaL_error(L, "field `%s' missing in date table", key);
- res = d;
- }
- lua_pop(L, 1);
- return res;
-}
-
-
-static int io_date (lua_State *L) {
- const char *s = luaL_optstring(L, 1, "%c");
- lua_Number n = luaL_optnumber(L, 2, -1);
- time_t t = (n == -1) ? time(NULL) : (time_t)n;
- struct tm *stm;
- if (*s == '!') { /* UTC? */
- stm = gmtime(&t);
- s++; /* skip `!' */
- }
- else
- stm = localtime(&t);
- if (stm == NULL) /* invalid date? */
- lua_pushnil(L);
- else if (strcmp(s, "*t") == 0) {
- lua_createtable(L, 0, 9); /* 9 = number of fields */
- setfield(L, "sec", stm->tm_sec);
- setfield(L, "min", stm->tm_min);
- setfield(L, "hour", stm->tm_hour);
- setfield(L, "day", stm->tm_mday);
- setfield(L, "month", stm->tm_mon+1);
- setfield(L, "year", stm->tm_year+1900);
- setfield(L, "wday", stm->tm_wday+1);
- setfield(L, "yday", stm->tm_yday+1);
- setboolfield(L, "isdst", stm->tm_isdst);
- }
- else {
- char b[256];
- if (strftime(b, sizeof(b), s, stm))
- lua_pushstring(L, b);
- else
- return luaL_error(L, "`date' format too long");
- }
- return 1;
-}
-
-
-static int io_time (lua_State *L) {
- if (lua_isnoneornil(L, 1)) /* called without args? */
- lua_pushnumber(L, time(NULL)); /* return current time */
- else {
- time_t t;
- struct tm ts;
- luaL_checktype(L, 1, LUA_TTABLE);
- lua_settop(L, 1); /* make sure table is at the top */
- ts.tm_sec = getfield(L, "sec", 0);
- ts.tm_min = getfield(L, "min", 0);
- ts.tm_hour = getfield(L, "hour", 12);
- ts.tm_mday = getfield(L, "day", -1);
- ts.tm_mon = getfield(L, "month", -1) - 1;
- ts.tm_year = getfield(L, "year", -1) - 1900;
- ts.tm_isdst = getboolfield(L, "isdst");
- t = mktime(&ts);
- if (t == (time_t)(-1))
- lua_pushnil(L);
- else
- lua_pushnumber(L, t);
- }
- return 1;
-}
-
-
-static int io_difftime (lua_State *L) {
- lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
- (time_t)(luaL_optnumber(L, 2, 0))));
- return 1;
-}
-
-/* }====================================================== */
-
-
-static int io_setloc (lua_State *L) {
- static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
- LC_NUMERIC, LC_TIME};
- static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
- "numeric", "time", NULL};
- const char *l = lua_tostring(L, 1);
- int op = luaL_findstring(luaL_optstring(L, 2, "all"), catnames);
- luaL_argcheck(L, l || lua_isnoneornil(L, 1), 1, "string expected");
- luaL_argcheck(L, op != -1, 2, "invalid option");
- lua_pushstring(L, setlocale(cat[op], l));
- return 1;
-}
-
-
-static int io_exit (lua_State *L) {
- exit(luaL_optint(L, 1, EXIT_SUCCESS));
- return 0; /* to avoid warnings */
+static void createupval (lua_State *L) {
+ lua_newtable(L);
+ /* create (and set) default files */
+ *newfile(L) = stdin;
+ lua_rawseti(L, -2, IO_INPUT);
+ *newfile(L) = stdout;
+ lua_rawseti(L, -2, IO_OUTPUT);
}
-static const luaL_reg syslib[] = {
- {"clock", io_clock},
- {"date", io_date},
- {"difftime", io_difftime},
- {"execute", io_execute},
- {"exit", io_exit},
- {"getenv", io_getenv},
- {"remove", io_remove},
- {"rename", io_rename},
- {"setlocale", io_setloc},
- {"time", io_time},
- {"tmpname", io_tmpname},
- {NULL, NULL}
-};
-
-/* }====================================================== */
-
LUALIB_API int luaopen_io (lua_State *L) {
- luaL_openlib(L, LUA_OSLIBNAME, syslib, 0);
createmeta(L);
+ createupval(L);
lua_pushvalue(L, -1);
luaL_openlib(L, LUA_IOLIBNAME, iolib, 1);
/* put predefined file handles into `io' table */
- lua_pushliteral(L, "stdin");
- lua_rawgeti(L, 2, IO_INPUT);
- lua_rawset(L, 3);
- lua_pushliteral(L, "stdout");
- lua_rawgeti(L, 2, IO_OUTPUT);
- lua_rawset(L, 3);
- lua_pushliteral(L, "stderr");
+ lua_rawgeti(L, -2, IO_INPUT); /* get current input from metatable */
+ lua_setfield(L, -2, "stdin"); /* io.stdin = metatable[IO_INPUT] */
+ lua_rawgeti(L, -2, IO_OUTPUT); /* get current output from metatable */
+ lua_setfield(L, -2, "stdout"); /* io.stdout = metatable[IO_OUTPUT] */
*newfile(L) = stderr;
- lua_rawset(L, 3);
+ lua_setfield(L, -2, "stderr"); /* io.stderr = newfile(stderr) */
return 1;
}
diff --git a/src/lib/lmathlib.c b/src/lib/lmathlib.c
index 6041b2e3..fcd2eefb 100644
--- a/src/lib/lmathlib.c
+++ b/src/lib/lmathlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lmathlib.c,v 1.59 2003/11/05 11:59:14 roberto Exp $
+** $Id: lmathlib.c,v 1.61 2004/05/10 18:11:32 roberto Exp $
** Standard mathematical library
** See Copyright Notice in lua.h
*/
@@ -9,6 +9,7 @@
#include <math.h>
#define lmathlib_c
+#define LUA_LIB
#include "lua.h"
@@ -22,56 +23,43 @@
-/*
-** If you want Lua to operate in degrees (instead of radians),
-** define USE_DEGREES
-*/
-#ifdef USE_DEGREES
-#define FROMRAD(a) ((a)/RADIANS_PER_DEGREE)
-#define TORAD(a) ((a)*RADIANS_PER_DEGREE)
-#else
-#define FROMRAD(a) (a)
-#define TORAD(a) (a)
-#endif
-
-
static int math_abs (lua_State *L) {
lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
return 1;
}
static int math_sin (lua_State *L) {
- lua_pushnumber(L, sin(TORAD(luaL_checknumber(L, 1))));
+ lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
return 1;
}
static int math_cos (lua_State *L) {
- lua_pushnumber(L, cos(TORAD(luaL_checknumber(L, 1))));
+ lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
return 1;
}
static int math_tan (lua_State *L) {
- lua_pushnumber(L, tan(TORAD(luaL_checknumber(L, 1))));
+ lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
return 1;
}
static int math_asin (lua_State *L) {
- lua_pushnumber(L, FROMRAD(asin(luaL_checknumber(L, 1))));
+ lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
return 1;
}
static int math_acos (lua_State *L) {
- lua_pushnumber(L, FROMRAD(acos(luaL_checknumber(L, 1))));
+ lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
return 1;
}
static int math_atan (lua_State *L) {
- lua_pushnumber(L, FROMRAD(atan(luaL_checknumber(L, 1))));
+ lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
return 1;
}
static int math_atan2 (lua_State *L) {
- lua_pushnumber(L, FROMRAD(atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))));
+ lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
return 1;
}
diff --git a/src/lib/loadlib.c b/src/lib/loadlib.c
index 2a6b39e1..8b98a2bf 100644
--- a/src/lib/loadlib.c
+++ b/src/lib/loadlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: loadlib.c,v 1.5 2003/05/14 21:01:53 roberto Exp $
+** $Id: loadlib.c,v 1.6 2004/04/30 20:13:38 roberto Exp $
** Dynamic library loader for Lua
** See Copyright Notice in lua.h
*
@@ -26,6 +26,9 @@
*
*/
+#define loadlib_c
+#define LUA_LIB
+
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
diff --git a/src/lib/loslib.c b/src/lib/loslib.c
new file mode 100644
index 00000000..c5726cfe
--- /dev/null
+++ b/src/lib/loslib.c
@@ -0,0 +1,241 @@
+/*
+** $Id: loslib.c,v 1.2 2004/08/05 19:30:37 roberto Exp $
+** Standard Operating System library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <errno.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define loslib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+static int pushresult (lua_State *L, int i, const char *filename) {
+ if (i) {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ else {
+ lua_pushnil(L);
+ if (filename)
+ lua_pushfstring(L, "%s: %s", filename, strerror(errno));
+ else
+ lua_pushfstring(L, "%s", strerror(errno));
+ lua_pushinteger(L, errno);
+ return 3;
+ }
+}
+
+
+static int io_execute (lua_State *L) {
+ lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));
+ return 1;
+}
+
+
+static int io_remove (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ return pushresult(L, remove(filename) == 0, filename);
+}
+
+
+static int io_rename (lua_State *L) {
+ const char *fromname = luaL_checkstring(L, 1);
+ const char *toname = luaL_checkstring(L, 2);
+ return pushresult(L, rename(fromname, toname) == 0, fromname);
+}
+
+
+static int io_tmpname (lua_State *L) {
+#if !USE_TMPNAME
+ luaL_error(L, "`tmpname' not supported");
+ return 0;
+#else
+ char buff[L_tmpnam];
+ if (tmpnam(buff) != buff)
+ return luaL_error(L, "unable to generate a unique filename in `tmpname'");
+ lua_pushstring(L, buff);
+ return 1;
+#endif
+}
+
+
+static int io_getenv (lua_State *L) {
+ lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
+ return 1;
+}
+
+
+static int io_clock (lua_State *L) {
+ lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
+ return 1;
+}
+
+
+/*
+** {======================================================
+** Time/Date operations
+** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
+** wday=%w+1, yday=%j, isdst=? }
+** =======================================================
+*/
+
+static void setfield (lua_State *L, const char *key, int value) {
+ lua_pushstring(L, key);
+ lua_pushinteger(L, value);
+ lua_rawset(L, -3);
+}
+
+static void setboolfield (lua_State *L, const char *key, int value) {
+ lua_pushstring(L, key);
+ lua_pushboolean(L, value);
+ lua_rawset(L, -3);
+}
+
+static int getboolfield (lua_State *L, const char *key) {
+ int res;
+ lua_getfield(L, -1, key);
+ res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ return res;
+}
+
+
+static int getfield (lua_State *L, const char *key, int d) {
+ int res;
+ lua_getfield(L, -1, key);
+ if (lua_isnumber(L, -1))
+ res = (int)lua_tointeger(L, -1);
+ else {
+ if (d < 0)
+ return luaL_error(L, "field `%s' missing in date table", key);
+ res = d;
+ }
+ lua_pop(L, 1);
+ return res;
+}
+
+
+static int io_date (lua_State *L) {
+ const char *s = luaL_optstring(L, 1, "%c");
+ lua_Number n = luaL_optnumber(L, 2, -1);
+ time_t t = (n == -1) ? time(NULL) : (time_t)n;
+ struct tm *stm;
+ if (*s == '!') { /* UTC? */
+ stm = gmtime(&t);
+ s++; /* skip `!' */
+ }
+ else
+ stm = localtime(&t);
+ if (stm == NULL) /* invalid date? */
+ lua_pushnil(L);
+ else if (strcmp(s, "*t") == 0) {
+ lua_createtable(L, 0, 9); /* 9 = number of fields */
+ setfield(L, "sec", stm->tm_sec);
+ setfield(L, "min", stm->tm_min);
+ setfield(L, "hour", stm->tm_hour);
+ setfield(L, "day", stm->tm_mday);
+ setfield(L, "month", stm->tm_mon+1);
+ setfield(L, "year", stm->tm_year+1900);
+ setfield(L, "wday", stm->tm_wday+1);
+ setfield(L, "yday", stm->tm_yday+1);
+ setboolfield(L, "isdst", stm->tm_isdst);
+ }
+ else {
+ char b[256];
+ if (strftime(b, sizeof(b), s, stm))
+ lua_pushstring(L, b);
+ else
+ return luaL_error(L, "`date' format too long");
+ }
+ return 1;
+}
+
+
+static int io_time (lua_State *L) {
+ time_t t;
+ if (lua_isnoneornil(L, 1)) /* called without args? */
+ t = time(NULL); /* get current time */
+ else {
+ struct tm ts;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_settop(L, 1); /* make sure table is at the top */
+ ts.tm_sec = getfield(L, "sec", 0);
+ ts.tm_min = getfield(L, "min", 0);
+ ts.tm_hour = getfield(L, "hour", 12);
+ ts.tm_mday = getfield(L, "day", -1);
+ ts.tm_mon = getfield(L, "month", -1) - 1;
+ ts.tm_year = getfield(L, "year", -1) - 1900;
+ ts.tm_isdst = getboolfield(L, "isdst");
+ t = mktime(&ts);
+ }
+ if (t == (time_t)(-1))
+ lua_pushnil(L);
+ else
+ lua_pushnumber(L, t);
+ return 1;
+}
+
+
+static int io_difftime (lua_State *L) {
+ lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
+ (time_t)(luaL_optnumber(L, 2, 0))));
+ return 1;
+}
+
+/* }====================================================== */
+
+
+static int io_setloc (lua_State *L) {
+ static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
+ LC_NUMERIC, LC_TIME};
+ static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
+ "numeric", "time", NULL};
+ const char *l = lua_tostring(L, 1);
+ int op = luaL_findstring(luaL_optstring(L, 2, "all"), catnames);
+ luaL_argcheck(L, l || lua_isnoneornil(L, 1), 1, "string expected");
+ luaL_argcheck(L, op != -1, 2, "invalid option");
+ lua_pushstring(L, setlocale(cat[op], l));
+ return 1;
+}
+
+
+static int io_exit (lua_State *L) {
+ exit(luaL_optint(L, 1, EXIT_SUCCESS));
+ return 0; /* to avoid warnings */
+}
+
+static const luaL_reg syslib[] = {
+ {"clock", io_clock},
+ {"date", io_date},
+ {"difftime", io_difftime},
+ {"execute", io_execute},
+ {"exit", io_exit},
+ {"getenv", io_getenv},
+ {"remove", io_remove},
+ {"rename", io_rename},
+ {"setlocale", io_setloc},
+ {"time", io_time},
+ {"tmpname", io_tmpname},
+ {NULL, NULL}
+};
+
+/* }====================================================== */
+
+
+
+LUALIB_API int luaopen_os (lua_State *L) {
+ luaL_openlib(L, LUA_OSLIBNAME, syslib, 0);
+ return 1;
+}
+
diff --git a/src/lib/lstrlib.c b/src/lib/lstrlib.c
index 36b226d2..7fa205c0 100644
--- a/src/lib/lstrlib.c
+++ b/src/lib/lstrlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstrlib.c,v 1.101 2004/01/02 11:54:14 roberto Exp $
+** $Id: lstrlib.c,v 1.106 2004/08/09 13:30:33 roberto Exp $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
@@ -12,6 +12,7 @@
#include <string.h>
#define lstrlib_c
+#define LUA_LIB
#include "lua.h"
@@ -20,9 +21,7 @@
/* macro to `unsign' a character */
-#ifndef uchar
#define uchar(c) ((unsigned char)(c))
-#endif
typedef lua_Integer sint32; /* a signed version for size_t */
@@ -108,11 +107,17 @@ static int str_rep (lua_State *L) {
static int str_byte (lua_State *L) {
size_t l;
const char *s = luaL_checklstring(L, 1, &l);
- sint32 pos = posrelat(luaL_optinteger(L, 2, 1), l);
- if (pos <= 0 || (size_t)(pos) > l) /* index out of range? */
- return 0; /* no answer */
- lua_pushinteger(L, uchar(s[pos-1]));
- return 1;
+ sint32 posi = posrelat(luaL_optinteger(L, 2, 1), l);
+ sint32 pose = posrelat(luaL_optinteger(L, 3, posi), l);
+ int n, i;
+ if (posi <= 0) posi = 1;
+ if ((size_t)pose > l) pose = l;
+ if (posi > pose) return 0; /* empty interval; return no values */
+ n = pose - posi + 1;
+ luaL_checkstack(L, n, "string slice too long");
+ for (i=0; i<n; i++)
+ lua_pushinteger(L, uchar(s[posi+i-1]));
+ return n;
}
@@ -134,15 +139,16 @@ static int str_char (lua_State *L) {
static int writer (lua_State *L, const void* b, size_t size, void* B) {
(void)L;
luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
- return 1;
+ return 0;
}
static int str_dump (lua_State *L) {
luaL_Buffer b;
luaL_checktype(L, 1, LUA_TFUNCTION);
+ lua_settop(L, 1);
luaL_buffinit(L,&b);
- if (!lua_dump(L, writer, &b))
+ if (lua_dump(L, writer, &b) != 0)
luaL_error(L, "unable to dump given function");
luaL_pushresult(&b);
return 1;
@@ -156,10 +162,6 @@ static int str_dump (lua_State *L) {
** =======================================================
*/
-#ifndef MAX_CAPTURES
-#define MAX_CAPTURES 32 /* arbitrary limit */
-#endif
-
#define CAP_UNFINISHED (-1)
#define CAP_POSITION (-2)
diff --git a/src/lib/ltablib.c b/src/lib/ltablib.c
index c38da36f..ab953c61 100644
--- a/src/lib/ltablib.c
+++ b/src/lib/ltablib.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltablib.c,v 1.22 2003/10/07 20:13:41 roberto Exp $
+** $Id: ltablib.c,v 1.26 2004/06/15 13:37:21 roberto Exp $
** Library for Table Manipulation
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,7 @@
#include <stddef.h>
#define ltablib_c
+#define LUA_LIB
#include "lua.h"
@@ -22,7 +23,7 @@ static int luaB_foreachi (lua_State *L) {
int i;
int n = aux_getn(L, 1);
luaL_checktype(L, 2, LUA_TFUNCTION);
- for (i=1; i<=n; i++) {
+ for (i=LUA_FIRSTINDEX; i < n+LUA_FIRSTINDEX; i++) {
lua_pushvalue(L, 2); /* function */
lua_pushinteger(L, i); /* 1st argument */
lua_rawgeti(L, 1, i); /* 2nd argument */
@@ -62,25 +63,26 @@ static int luaB_getn (lua_State *L) {
static int luaB_setn (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_setn(L, 1, luaL_checkint(L, 2));
- return 0;
+ lua_pushvalue(L, 1);
+ return 1;
}
static int luaB_tinsert (lua_State *L) {
int v = lua_gettop(L); /* number of arguments */
- int n = aux_getn(L, 1) + 1;
+ int e = aux_getn(L, 1) + LUA_FIRSTINDEX; /* first empty element */
int pos; /* where to insert new element */
if (v == 2) /* called with only 2 arguments */
- pos = n; /* insert new element at the end */
+ pos = e; /* insert new element at the end */
else {
pos = luaL_checkint(L, 2); /* 2nd argument is the position */
- if (pos > n) n = pos; /* `grow' array if necessary */
+ if (pos > e) e = pos; /* `grow' array if necessary */
v = 3; /* function may be called with more than 3 args */
}
- luaL_setn(L, 1, n); /* new size */
- while (--n >= pos) { /* move up elements */
- lua_rawgeti(L, 1, n);
- lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */
+ luaL_setn(L, 1, e - LUA_FIRSTINDEX + 1); /* new size */
+ while (--e >= pos) { /* move up elements */
+ lua_rawgeti(L, 1, e);
+ lua_rawseti(L, 1, e+1); /* t[e+1] = t[e] */
}
lua_pushvalue(L, v);
lua_rawseti(L, 1, pos); /* t[pos] = v */
@@ -89,17 +91,17 @@ static int luaB_tinsert (lua_State *L) {
static int luaB_tremove (lua_State *L) {
- int n = aux_getn(L, 1);
- int pos = luaL_optint(L, 2, n);
- if (n <= 0) return 0; /* table is `empty' */
- luaL_setn(L, 1, n-1); /* t.n = n-1 */
+ int e = aux_getn(L, 1) + LUA_FIRSTINDEX - 1;
+ int pos = luaL_optint(L, 2, e);
+ if (e < LUA_FIRSTINDEX) return 0; /* table is `empty' */
+ luaL_setn(L, 1, e - LUA_FIRSTINDEX); /* t.n = n-1 */
lua_rawgeti(L, 1, pos); /* result = t[pos] */
- for ( ;pos<n; pos++) {
+ for ( ;pos<e; pos++) {
lua_rawgeti(L, 1, pos+1);
lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */
}
lua_pushnil(L);
- lua_rawseti(L, 1, n); /* t[n] = nil */
+ lua_rawseti(L, 1, e); /* t[e] = nil */
return 1;
}
@@ -108,16 +110,17 @@ static int str_concat (lua_State *L) {
luaL_Buffer b;
size_t lsep;
const char *sep = luaL_optlstring(L, 2, "", &lsep);
- int i = luaL_optint(L, 3, 1);
- int n = luaL_optint(L, 4, 0);
+ int i = luaL_optint(L, 3, LUA_FIRSTINDEX);
+ int last = luaL_optint(L, 4, -2);
luaL_checktype(L, 1, LUA_TTABLE);
- if (n == 0) n = luaL_getn(L, 1);
+ if (last == -2)
+ last = luaL_getn(L, 1) + LUA_FIRSTINDEX - 1;
luaL_buffinit(L, &b);
- for (; i <= n; i++) {
+ for (; i <= last; i++) {
lua_rawgeti(L, 1, i);
luaL_argcheck(L, lua_isstring(L, -1), 1, "table contains non-strings");
luaL_addvalue(&b);
- if (i != n)
+ if (i != last)
luaL_addlstring(&b, sep, lsep);
}
luaL_pushresult(&b);
@@ -223,7 +226,7 @@ static int luaB_sort (lua_State *L) {
if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
luaL_checktype(L, 2, LUA_TFUNCTION);
lua_settop(L, 2); /* make sure there is two arguments */
- auxsort(L, 1, n);
+ auxsort(L, LUA_FIRSTINDEX, n + LUA_FIRSTINDEX - 1);
return 0;
}
diff --git a/src/llex.c b/src/llex.c
index 647e77f2..c5e491e5 100644
--- a/src/llex.c
+++ b/src/llex.c
@@ -1,5 +1,5 @@
/*
-** $Id: llex.c,v 2.2 2004/03/12 19:53:56 roberto Exp $
+** $Id: llex.c,v 2.3 2004/04/30 20:13:38 roberto Exp $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -9,6 +9,7 @@
#include <string.h>
#define llex_c
+#define LUA_CORE
#include "lua.h"
diff --git a/src/llimits.h b/src/llimits.h
index 6a2e00bd..ea0caf7b 100644
--- a/src/llimits.h
+++ b/src/llimits.h
@@ -1,5 +1,5 @@
/*
-** $Id: llimits.h,v 1.57 2003/12/01 16:33:30 roberto Exp $
+** $Id: llimits.h,v 1.59 2004/06/23 15:57:29 roberto Exp $
** Limits, basic types, and some other `installation-dependent' definitions
** See Copyright Notice in lua.h
*/
@@ -15,48 +15,9 @@
#include "lua.h"
-/*
-** try to find number of bits in an integer
-*/
-#ifndef BITS_INT
-/* avoid overflows in comparison */
-#if INT_MAX-20 < 32760
-#define BITS_INT 16
-#elif INT_MAX > 2147483640L
-/* machine has at least 32 bits */
-#define BITS_INT 32
-#else
-#error "you must define BITS_INT with number of bits in an integer"
-#endif
-#endif
-
-
-/*
-** the following types define integer types for values that may not
-** fit in a `small int' (16 bits), but may waste space in a
-** `large long' (64 bits). The current definitions should work in
-** any machine, but may not be optimal.
-*/
-
-
-/*
-** an unsigned integer with at least 32 bits
-*/
-#ifndef LUA_UINT32
-#define LUA_UINT32 unsigned long
-#endif
typedef LUA_UINT32 lu_int32;
-
-/*
-** a signed integer with at least 32 bits
-*/
-#ifndef LUA_INT32
-#define LUA_INT32 long
-#define LUA_MAXINT32 LONG_MAX
-#endif
-
typedef LUA_INT32 l_int32;
@@ -95,24 +56,11 @@ typedef unsigned char lu_byte;
/* type to ensure maximum alignment */
-#ifndef LUSER_ALIGNMENT_T
-typedef union { double u; void *s; long l; } L_Umaxalign;
-#else
typedef LUSER_ALIGNMENT_T L_Umaxalign;
-#endif
-/* result of `usual argument conversion' over lua_Number */
-#ifndef LUA_UACNUMBER
-typedef double l_uacNumber;
-#else
+/* result of a `usual argument conversion' over lua_Number */
typedef LUA_UACNUMBER l_uacNumber;
-#endif
-
-
-#ifndef lua_assert
-#define lua_assert(c) /* empty */
-#endif
#ifndef check_exp
@@ -138,43 +86,11 @@ typedef LUA_UACNUMBER l_uacNumber;
typedef lu_int32 Instruction;
-/* maximum depth for calls (unsigned short) */
-#ifndef LUA_MAXCALLS
-#define LUA_MAXCALLS 4096
-#endif
-
-
-/*
-** maximum depth for C calls (unsigned short): Not too big, or may
-** overflow the C stack...
-*/
-
-#ifndef LUA_MAXCCALLS
-#define LUA_MAXCCALLS 200
-#endif
-
-
-/* maximum size for the virtual stack of a C function */
-#ifndef LUA_MAXCSTACK
-#define LUA_MAXCSTACK 2048
-#endif
-
/* maximum stack for a Lua function */
#define MAXSTACK 250
-/* maximum number of variables declared in a function */
-#ifndef MAXVARS
-#define MAXVARS 200 /* <MAXSTACK */
-#endif
-
-
-/* maximum number of upvalues per function */
-#ifndef MAXUPVALUES
-#define MAXUPVALUES 32 /* <MAXSTACK */
-#endif
-
/* minimum size for the string table (must be power of 2) */
#ifndef MINSTRTABSIZE
@@ -188,13 +104,4 @@ typedef lu_int32 Instruction;
#endif
-/*
-** maximum number of syntactical nested non-terminals: Not too big,
-** or may overflow the C stack...
-*/
-#ifndef LUA_MAXPARSERLEVEL
-#define LUA_MAXPARSERLEVEL 200
-#endif
-
-
#endif
diff --git a/src/lmem.c b/src/lmem.c
index 75b274c9..c1802ff9 100644
--- a/src/lmem.c
+++ b/src/lmem.c
@@ -1,5 +1,5 @@
/*
-** $Id: lmem.c,v 1.63 2003/11/27 18:18:37 roberto Exp $
+** $Id: lmem.c,v 1.65 2004/08/30 13:44:44 roberto Exp $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,7 @@
#include <stddef.h>
#define lmem_c
+#define LUA_CORE
#include "lua.h"
@@ -76,8 +77,7 @@ void *luaM_realloc (lua_State *L, void *block, lu_mem osize, lu_mem nsize) {
if (block == NULL && nsize > 0)
luaD_throw(L, LUA_ERRMEM);
lua_assert((nsize == 0) == (block == NULL));
- g->nblocks -= osize;
- g->nblocks += nsize;
+ g->totalbytes = (g->totalbytes - osize) + nsize;
return block;
}
diff --git a/src/lobject.c b/src/lobject.c
index f273796b..1e24bb5d 100644
--- a/src/lobject.c
+++ b/src/lobject.c
@@ -1,5 +1,5 @@
/*
-** $Id: lobject.c,v 2.1 2003/12/10 12:13:36 roberto Exp $
+** $Id: lobject.c,v 2.4 2004/07/09 16:01:38 roberto Exp $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
@@ -10,6 +10,7 @@
#include <string.h>
#define lobject_c
+#define LUA_CORE
#include "lua.h"
@@ -21,11 +22,6 @@
#include "lvm.h"
-/* function to convert a string to a lua_Number */
-#ifndef lua_str2number
-#define lua_str2number(s,p) strtod((s), (p))
-#endif
-
const TValue luaO_nilobject = {LUA_TNIL, {NULL}};
@@ -98,7 +94,7 @@ static void pushstr (lua_State *L, const char *str) {
}
-/* this function handles only `%d', `%c', %f, and `%s' formats */
+/* this function handles only `%d', `%c', %f, %p, and `%s' formats */
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
int n = 1;
pushstr(L, "");
@@ -108,9 +104,10 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));
incr_top(L);
switch (*(e+1)) {
- case 's':
+ case 's': {
pushstr(L, va_arg(argp, char *));
break;
+ }
case 'c': {
char buff[2];
buff[0] = cast(char, va_arg(argp, int));
@@ -118,17 +115,26 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
pushstr(L, buff);
break;
}
- case 'd':
+ case 'd': {
setnvalue(L->top, cast(lua_Number, va_arg(argp, int)));
incr_top(L);
break;
- case 'f':
+ }
+ case 'f': {
setnvalue(L->top, cast(lua_Number, va_arg(argp, l_uacNumber)));
incr_top(L);
break;
- case '%':
+ }
+ case 'p': {
+ char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
+ sprintf(buff, "%p", va_arg(argp, void *));
+ pushstr(L, buff);
+ break;
+ }
+ case '%': {
pushstr(L, "%");
break;
+ }
default: {
char buff[3];
buff[0] = '%';
@@ -177,7 +183,7 @@ void luaO_chunkid (char *out, const char *source, int bufflen) {
strcat(out, source);
}
else { /* out = [string "string"] */
- int len = strcspn(source, "\n"); /* stop at first newline */
+ int len = strcspn(source, "\n\r"); /* stop at first newline */
bufflen -= sizeof(" [string \"...\"] ");
if (len > bufflen) len = bufflen;
strcpy(out, "[string \"");
diff --git a/src/lobject.h b/src/lobject.h
index d5176a23..4b6a684b 100644
--- a/src/lobject.h
+++ b/src/lobject.h
@@ -1,5 +1,5 @@
/*
-** $Id: lobject.h,v 2.4 2004/03/15 21:04:33 roberto Exp $
+** $Id: lobject.h,v 2.5 2004/05/31 18:51:50 roberto Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
@@ -249,6 +249,10 @@ typedef struct Proto {
} Proto;
+/* mask for new-style vararg */
+#define NEWSTYLEVARARG 2
+
+
typedef struct LocVar {
TString *varname;
int startpc; /* first point where variable is active */
diff --git a/src/lopcodes.c b/src/lopcodes.c
index 3ffda71a..87ec8939 100644
--- a/src/lopcodes.c
+++ b/src/lopcodes.c
@@ -1,10 +1,11 @@
/*
-** $Id: lopcodes.c,v 1.25 2003/05/14 21:09:53 roberto Exp $
+** $Id: lopcodes.c,v 1.28 2004/07/16 13:15:32 roberto Exp $
** See Copyright Notice in lua.h
*/
#define lopcodes_c
+#define LUA_CORE
#include "lua.h"
@@ -14,8 +15,6 @@
/* ORDER OP */
-#ifdef LUA_OPNAMES
-
const char *const luaP_opnames[NUM_OPCODES] = {
"MOVE",
"LOADK",
@@ -52,10 +51,10 @@ const char *const luaP_opnames[NUM_OPCODES] = {
"SETLIST",
"SETLISTO",
"CLOSE",
- "CLOSURE"
+ "CLOSURE",
+ "VARARG"
};
-#endif
#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))
@@ -97,5 +96,6 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(0, 0, OpArgU, OpArgN, iABx) /* OP_SETLISTO */
,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */
,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
};
diff --git a/src/lopcodes.h b/src/lopcodes.h
index 28df697d..d3429a59 100644
--- a/src/lopcodes.h
+++ b/src/lopcodes.h
@@ -1,5 +1,5 @@
/*
-** $Id: lopcodes.h,v 1.106 2003/05/15 19:46:03 roberto Exp $
+** $Id: lopcodes.h,v 1.111 2004/08/04 20:18:13 roberto Exp $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -41,18 +41,19 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
#define SIZE_OP 6
-#define POS_C SIZE_OP
+#define POS_OP 0
+#define POS_A (POS_OP + SIZE_OP)
+#define POS_C (POS_A + SIZE_A)
#define POS_B (POS_C + SIZE_C)
#define POS_Bx POS_C
-#define POS_A (POS_B + SIZE_B)
/*
** limits for opcode arguments.
** we use (signed) int to manipulate most arguments,
-** so they must fit in BITS_INT-1 bits (-1 for sign)
+** so they must fit in LUA_BITSINT-1 bits (-1 for sign)
*/
-#if SIZE_Bx < BITS_INT-1
+#if SIZE_Bx < LUA_BITSINT-1
#define MAXARG_Bx ((1<<SIZE_Bx)-1)
#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */
#else
@@ -76,10 +77,11 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
** the following macros help to manipulate instructions
*/
-#define GET_OPCODE(i) (cast(OpCode, (i)&MASK1(SIZE_OP,0)))
-#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,0)) | cast(Instruction, o)))
+#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
+#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
+ ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
-#define GETARG_A(i) (cast(int, (i)>>POS_A))
+#define GETARG_A(i) (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0)))
#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))
@@ -99,16 +101,33 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
-#define CREATE_ABC(o,a,b,c) (cast(Instruction, o) \
+#define CREATE_ABC(o,a,b,c) ((cast(Instruction, o)<<POS_OP) \
| (cast(Instruction, a)<<POS_A) \
| (cast(Instruction, b)<<POS_B) \
| (cast(Instruction, c)<<POS_C))
-#define CREATE_ABx(o,a,bc) (cast(Instruction, o) \
+#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \
| (cast(Instruction, a)<<POS_A) \
| (cast(Instruction, bc)<<POS_Bx))
+/*
+** Macros to operate RK indices
+*/
+
+/* this bit 1 means constant (0 means register) */
+#define BITRK (1 << (SIZE_B - 1))
+
+/* test whether value is a constant */
+#define ISK(x) ((x) & BITRK)
+
+/* gets the index of the constant */
+#define INDEXK(r) ((int)(r) & ~BITRK)
+
+#define MAXINDEXRK (BITRK - 1)
+
+/* code a constant index as a RK value */
+#define RKASK(x) ((x) | BITRK)
/*
@@ -120,7 +139,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
/*
** R(x) - register
** Kst(x) - constant (in constant table)
-** RK(x) == if x < MAXSTACK then R(x) else Kst(x-MAXSTACK)
+** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
*/
@@ -183,25 +202,30 @@ OP_SETLIST,/* A Bx R(A)[Bx-Bx%FPF+i] := R(A+i), 1 <= i <= Bx%FPF+1 */
OP_SETLISTO,/* A Bx */
OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
-OP_CLOSURE/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
+OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
+
+OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
} OpCode;
-#define NUM_OPCODES (cast(int, OP_CLOSURE+1))
+#define NUM_OPCODES (cast(int, OP_VARARG+1))
/*===========================================================================
Notes:
- (1) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
+ (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
and can be 0: OP_CALL then sets `top' to last_result+1, so
next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
- (2) In OP_RETURN, if (B == 0) then return up to `top'
+ (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
+ set top (like in OP_CALL).
+
+ (*) In OP_RETURN, if (B == 0) then return up to `top'
- (3) For comparisons, B specifies what conditions the test should accept.
+ (*) For comparisons, B specifies what conditions the test should accept.
- (4) All `skips' (pc++) assume that next instruction is a jump
+ (*) All `skips' (pc++) assume that next instruction is a jump
===========================================================================*/
diff --git a/src/lparser.c b/src/lparser.c
index a8dafb6f..c0fc1579 100644
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.c,v 2.2 2004/03/12 19:53:56 roberto Exp $
+** $Id: lparser.c,v 2.5 2004/05/31 18:51:50 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,7 @@
#include <string.h>
#define lparser_c
+#define LUA_CORE
#include "lua.h"
@@ -26,6 +27,8 @@
+#define hasmultret(k) ((k) == VCALL || (k) == VVARARG)
+
#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) luaY_errorlimit(fs,l,m)
@@ -271,11 +274,11 @@ static TString *singlevar (LexState *ls, expdesc *var, int base) {
static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
FuncState *fs = ls->fs;
int extra = nvars - nexps;
- if (e->k == VCALL) {
+ if (hasmultret(e->k)) {
extra++; /* includes call itself */
- if (extra <= 0) extra = 0;
- else luaK_reserveregs(fs, extra-1);
- luaK_setcallreturns(fs, e, extra); /* call provides the difference */
+ if (extra < 0) extra = 0;
+ luaK_setreturns(fs, e, extra); /* last exp. provides the difference */
+ if (extra > 1) luaK_reserveregs(fs, extra-1);
}
else {
if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */
@@ -391,6 +394,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
lexstate.nestlevel = 0;
luaX_setinput(L, &lexstate, z, luaS_new(L, name));
open_func(&lexstate, &funcstate);
+ funcstate.f->is_vararg = NEWSTYLEVARARG;
next(&lexstate); /* read first token */
chunk(&lexstate);
check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected");
@@ -480,9 +484,10 @@ static void closelistfield (FuncState *fs, struct ConsControl *cc) {
static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
if (cc->tostore == 0) return;
- if (cc->v.k == VCALL) {
- luaK_setcallreturns(fs, &cc->v, LUA_MULTRET);
+ if (hasmultret(cc->v.k)) {
+ luaK_setmultret(fs, &cc->v);
luaK_codeABx(fs, OP_SETLISTO, cc->t->info, cc->na-1);
+ cc->na--; /* do not count last expression (unknown number of elements) */
}
else {
if (cc->v.k != VVOID)
@@ -556,12 +561,8 @@ static void parlist (LexState *ls) {
if (ls->t.token != ')') { /* is `parlist' not empty? */
do {
switch (ls->t.token) {
- case TK_NAME: { /* param -> NAME [ `=' `...' ] */
+ case TK_NAME: { /* param -> NAME */
new_localvar(ls, str_checkname(ls), nparams++);
- if (testnext(ls, '=')) {
- check(ls, TK_DOTS);
- f->is_vararg = 1;
- }
break;
}
case TK_DOTS: { /* param -> `...' */
@@ -627,7 +628,7 @@ static void funcargs (LexState *ls, expdesc *f) {
args.k = VVOID;
else {
explist1(ls, &args);
- luaK_setcallreturns(fs, &args, LUA_MULTRET);
+ luaK_setmultret(fs, &args);
}
check_match(ls, ')', '(', line);
break;
@@ -648,7 +649,7 @@ static void funcargs (LexState *ls, expdesc *f) {
}
lua_assert(f->k == VNONRELOC);
base = f->info; /* base register for call */
- if (args.k == VCALL)
+ if (hasmultret(args.k))
nparams = LUA_MULTRET; /* open call */
else {
if (args.k != VVOID)
@@ -737,43 +738,47 @@ static void simpleexp (LexState *ls, expdesc *v) {
switch (ls->t.token) {
case TK_NUMBER: {
init_exp(v, VK, luaK_numberK(ls->fs, ls->t.seminfo.r));
- next(ls); /* must use `seminfo' before `next' */
break;
}
case TK_STRING: {
codestring(ls, v, ls->t.seminfo.ts);
- next(ls); /* must use `seminfo' before `next' */
break;
}
case TK_NIL: {
init_exp(v, VNIL, 0);
- next(ls);
break;
}
case TK_TRUE: {
init_exp(v, VTRUE, 0);
- next(ls);
break;
}
case TK_FALSE: {
init_exp(v, VFALSE, 0);
- next(ls);
+ break;
+ }
+ case TK_DOTS: { /* vararg */
+ FuncState *fs = ls->fs;
+ check_condition(ls, fs->f->is_vararg,
+ "cannot use `...' outside a vararg function");
+ fs->f->is_vararg = NEWSTYLEVARARG;
+ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
break;
}
case '{': { /* constructor */
constructor(ls, v);
- break;
+ return;
}
case TK_FUNCTION: {
next(ls);
body(ls, v, 0, ls->linenumber);
- break;
+ return;
}
default: {
primaryexp(ls, v);
- break;
+ return;
}
}
+ next(ls);
}
@@ -950,7 +955,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
ls->fs->freereg -= nexps - nvars; /* remove extra values */
}
else {
- luaK_setcallreturns(ls->fs, &e, 1); /* close last expression */
+ luaK_setoneret(ls->fs, &e); /* close last expression */
luaK_storevar(ls->fs, &lh->v, &e);
return; /* avoid default */
}
@@ -976,12 +981,6 @@ static int cond (LexState *ls) {
** after its body (and thus avoiding one jump in the loop).
*/
-/*
-** maximum size of expressions for optimizing `while' code
-*/
-#ifndef MAXEXPWHILE
-#define MAXEXPWHILE 100
-#endif
/*
** the call `luaK_goiffalse' may grow the size of an expression by
@@ -1240,9 +1239,8 @@ static void exprstat (LexState *ls) {
FuncState *fs = ls->fs;
struct LHS_assign v;
primaryexp(ls, &v.v);
- if (v.v.k == VCALL) { /* stat -> func */
- luaK_setcallreturns(fs, &v.v, 0); /* call statement uses no results */
- }
+ if (v.v.k == VCALL) /* stat -> func */
+ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
else { /* stat -> assignment */
v.prev = NULL;
assignment(ls, &v, 1);
@@ -1260,9 +1258,9 @@ static void retstat (LexState *ls) {
first = nret = 0; /* return no values */
else {
nret = explist1(ls, &e); /* optional return values */
- if (e.k == VCALL) {
- luaK_setcallreturns(fs, &e, LUA_MULTRET);
- if (nret == 1) { /* tail call? */
+ if (hasmultret(e.k)) {
+ luaK_setmultret(fs, &e);
+ if (e.k == VCALL && nret == 1) { /* tail call? */
SET_OPCODE(getcode(fs,&e), OP_TAILCALL);
lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);
}
diff --git a/src/lparser.h b/src/lparser.h
index b4652040..582b4878 100644
--- a/src/lparser.h
+++ b/src/lparser.h
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.h,v 1.50 2003/08/25 19:51:54 roberto Exp $
+** $Id: lparser.h,v 1.51 2004/05/31 18:51:50 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -30,7 +30,8 @@ typedef enum {
VJMP, /* info = instruction pc */
VRELOCABLE, /* info = instruction pc */
VNONRELOC, /* info = result register */
- VCALL /* info = result register */
+ VCALL, /* info = instruction pc */
+ VVARARG /* info = instruction pc */
} expkind;
typedef struct expdesc {
diff --git a/src/lstate.c b/src/lstate.c
index d1494b58..e0a439b1 100644
--- a/src/lstate.c
+++ b/src/lstate.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstate.c,v 2.5 2004/03/23 12:57:12 roberto Exp $
+** $Id: lstate.c,v 2.12 2004/08/30 13:44:44 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,7 @@
#include <stddef.h>
#define lstate_c
+#define LUA_CORE
#include "lua.h"
@@ -56,6 +57,7 @@ static void stack_init (lua_State *L1, lua_State *L) {
L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
L1->ci = L1->base_ci;
+ L1->ci->func = L1->top;
setnilvalue(L1->top++); /* `function' entry for this `ci' */
L1->base = L1->ci->base = L1->top;
L1->ci->top = L1->top + LUA_MINSTACK;
@@ -75,22 +77,25 @@ static void freestack (lua_State *L, lua_State *L1) {
*/
static void f_luaopen (lua_State *L, void *ud) {
Udata *u; /* head of udata list */
+ global_State *g = G(L);
UNUSED(ud);
u = cast(Udata *, luaM_malloc(L, sizeudata(0)));
u->uv.len = 0;
u->uv.metatable = NULL;
- G(L)->firstudata = obj2gco(u);
+ g->firstudata = obj2gco(u);
luaC_link(L, obj2gco(u), LUA_TUSERDATA);
setbit(u->uv.marked, FIXEDBIT);
setbit(L->marked, FIXEDBIT);
stack_init(L, L); /* init stack */
sethvalue(L, gt(L), luaH_new(L, 0, 4)); /* table of globals */
+ hvalue(gt(L))->metatable = luaH_new(L, 0, 0); /* globals metatable */
sethvalue(L, registry(L), luaH_new(L, 4, 4)); /* registry */
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
luaT_init(L);
luaX_init(L);
luaS_fix(luaS_newliteral(L, MEMERRMSG));
- G(L)->GCthreshold = 4*G(L)->nblocks;
+ g->GCthreshold = 4*g->totalbytes;
+ g->prevestimate = g->estimate = g->totalbytes;
}
@@ -119,12 +124,13 @@ static void preinit_state (lua_State *L, global_State *g) {
static void close_state (lua_State *L) {
global_State *g = G(L);
luaF_close(L, L->stack); /* close all upvalues for this thread */
- luaC_sweepall(L); /* collect all elements */
- lua_assert(g->rootgc == obj2gco(L));
- luaS_freeall(L);
+ luaC_freeall(L); /* collect all objects */
+ lua_assert(g->rootgc == NULL);
+ lua_assert(g->strt.nuse == 0);
+ luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
luaZ_freebuffer(L, &g->buff);
freestack(L, L);
- lua_assert(g->nblocks == sizeof(LG));
+ lua_assert(g->totalbytes == sizeof(LG));
(*g->realloc)(g->ud, fromstate(L), state_size(LG), 0);
}
@@ -136,6 +142,10 @@ lua_State *luaE_newthread (lua_State *L) {
preinit_state(L1, G(L));
stack_init(L1, L); /* init stack */
setobj2n(L, gt(L1), gt(L)); /* share table of globals */
+ L1->hookmask = L->hookmask;
+ L1->basehookcount = L->basehookcount;
+ L1->hook = L->hook;
+ resethookcount(L1);
lua_assert(iswhite(obj2gco(L1)));
return L1;
}
@@ -169,7 +179,8 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
setnilvalue(registry(L));
luaZ_initbuffer(L, &g->buff);
g->panic = NULL;
- g->gcstate = GCSfinalize;
+ g->gcstate = GCSpause;
+ g->gcgenerational = 0;
g->rootgc = obj2gco(L);
g->sweepstrgc = 0;
g->sweepgc = &g->rootgc;
@@ -181,13 +192,14 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
setnilvalue(gkey(g->dummynode));
setnilvalue(gval(g->dummynode));
g->dummynode->next = NULL;
- g->nblocks = sizeof(LG);
+ g->totalbytes = sizeof(LG);
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
/* memory allocation error: free partial state */
close_state(L);
L = NULL;
}
- lua_userstateopen(L);
+ else
+ lua_userstateopen(L);
return L;
}
diff --git a/src/lstate.h b/src/lstate.h
index ab01d169..0a178fef 100644
--- a/src/lstate.h
+++ b/src/lstate.h
@@ -1,5 +1,5 @@
/*
-** $Id: lstate.h,v 2.2 2004/03/23 17:02:58 roberto Exp $
+** $Id: lstate.h,v 2.7 2004/08/30 13:44:44 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
@@ -14,30 +14,6 @@
#include "lzio.h"
-/*
-** macros for thread synchronization inside Lua core machine:
-** all accesses to the global state and to global objects are synchronized.
-** Because threads can read the stack of other threads
-** (when running garbage collection),
-** a thread must also synchronize any write-access to its own stack.
-** Unsynchronized accesses are allowed only when reading its own stack,
-** or when reading immutable fields from global objects
-** (such as string values and udata values).
-*/
-#ifndef lua_lock
-#define lua_lock(L) ((void) 0)
-#endif
-
-#ifndef lua_unlock
-#define lua_unlock(L) ((void) 0)
-#endif
-
-
-#ifndef lua_userstateopen
-#define lua_userstateopen(l)
-#endif
-
-
struct lua_longjmp; /* defined in ldo.c */
@@ -70,25 +46,20 @@ typedef struct stringtable {
** informations about a call
*/
typedef struct CallInfo {
- StkId base; /* base for called function */
+ StkId base; /* base for this function */
+ StkId func; /* function index in the stack */
StkId top; /* top for this function */
- union {
- struct { /* for Lua functions */
- const Instruction *savedpc;
- int tailcalls; /* number of tail calls lost under this entry */
- } l;
- struct { /* for C functions */
- int dummy; /* just to avoid an empty struct */
- } c;
- } u;
+ int nresults; /* expected number of results from this function */
+ const Instruction *savedpc;
+ int tailcalls; /* number of tail calls lost under this entry */
} CallInfo;
-#define curr_func(L) (clvalue(L->base - 1))
-#define ci_func(ci) (clvalue((ci)->base - 1))
+#define curr_func(L) (clvalue(L->ci->func))
+#define ci_func(ci) (clvalue((ci)->func))
#define f_isLua(ci) (!ci_func(ci)->c.isC)
-#define isLua(ci) (ttisfunction((ci)->base - 1) && f_isLua(ci))
+#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
/*
@@ -98,7 +69,9 @@ typedef struct global_State {
stringtable strt; /* hash table for strings */
lua_Alloc realloc; /* function to reallocate memory */
void *ud; /* auxiliary data to `realloc' */
- int currentwhite;
+ lu_byte currentwhite;
+ lu_byte gcstate; /* state of garbage collector */
+ lu_byte gcgenerational;
GCObject *rootgc; /* list of all collectable objects */
GCObject *firstudata; /* udata go to the end of `rootgc' */
GCObject **sweepgc; /* position of sweep in `rootgc' */
@@ -107,10 +80,11 @@ typedef struct global_State {
GCObject *grayagain; /* list of objects to be traversed atomically */
GCObject *weak; /* list of weak tables (to be cleared) */
GCObject *tmudata; /* list of userdata to be GC */
- int gcstate; /* state of garbage collector */
Mbuffer buff; /* temporary buffer for string concatentation */
lu_mem GCthreshold;
- lu_mem nblocks; /* number of `bytes' currently allocated */
+ lu_mem totalbytes; /* number of bytes currently allocated */
+ lu_mem estimate; /* an estimate of number of bytes actually in use */
+ lu_mem prevestimate; /* previous estimate */
lua_CFunction panic; /* to be called in unprotected errors */
TValue _registry;
struct lua_State *mainthread;
diff --git a/src/lstring.c b/src/lstring.c
index 9a26cf03..4c34dc9b 100644
--- a/src/lstring.c
+++ b/src/lstring.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstring.c,v 2.1 2003/12/10 12:13:36 roberto Exp $
+** $Id: lstring.c,v 2.3 2004/08/24 20:12:06 roberto Exp $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,7 @@
#include <string.h>
#define lstring_c
+#define LUA_CORE
#include "lua.h"
@@ -18,17 +19,12 @@
-void luaS_freeall (lua_State *L) {
- lua_assert(G(L)->strt.nuse==0);
- luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
-}
-
-
void luaS_resize (lua_State *L, int newsize) {
GCObject **newhash;
stringtable *tb;
int i;
- if (G(L)->sweepstrgc > 0) return; /* cannot resize during GC traverse */
+ if (G(L)->gcstate == GCSsweepstring)
+ return; /* cannot resize during GC traverse */
newhash = luaM_newvector(L, newsize, GCObject *);
tb = &G(L)->strt;
for (i=0; i<newsize; i++) newhash[i] = NULL;
diff --git a/src/lstring.h b/src/lstring.h
index 2ca352c4..2d6e74a4 100644
--- a/src/lstring.h
+++ b/src/lstring.h
@@ -1,5 +1,5 @@
/*
-** $Id: lstring.h,v 1.38 2003/11/17 19:50:05 roberto Exp $
+** $Id: lstring.h,v 1.39 2004/08/24 20:12:06 roberto Exp $
** String table (keep all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -26,7 +26,6 @@
void luaS_resize (lua_State *L, int newsize);
Udata *luaS_newudata (lua_State *L, size_t s);
-void luaS_freeall (lua_State *L);
TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
diff --git a/src/ltable.c b/src/ltable.c
index 9fc508ba..10008c54 100644
--- a/src/ltable.c
+++ b/src/ltable.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltable.c,v 2.1 2003/12/10 12:13:36 roberto Exp $
+** $Id: ltable.c,v 2.5 2004/08/31 17:57:33 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -21,6 +21,7 @@
#include <string.h>
#define ltable_c
+#define LUA_CORE
#include "lua.h"
@@ -36,19 +37,14 @@
/*
** max size of array part is 2^MAXBITS
*/
-#if BITS_INT > 26
+#if LUA_BITSINT > 26
#define MAXBITS 24
#else
-#define MAXBITS (BITS_INT-2)
+#define MAXBITS (LUA_BITSINT-2)
#endif
#define MAXASIZE (1 << MAXBITS)
-/* function to convert a lua_Number to int (with any rounding method) */
-#ifndef lua_number2int
-#define lua_number2int(i,n) ((i)=(int)(n))
-#endif
-
#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
@@ -270,7 +266,7 @@ static void setnodevector (lua_State *L, Table *t, int lsize) {
}
-static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
+void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) {
int i;
int oldasize = t->sizearray;
int oldhsize = t->lsizenode;
@@ -315,7 +311,7 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
static void rehash (lua_State *L, Table *t) {
int nasize, nhsize;
numuse(t, &nasize, &nhsize); /* compute new sizes for array and hash parts */
- resize(L, t, nasize, luaO_log2(nhsize)+1);
+ luaH_resize(L, t, nasize, luaO_log2(nhsize)+1);
}
@@ -349,26 +345,6 @@ void luaH_free (lua_State *L, Table *t) {
}
-#if 0
-/*
-** try to remove an element from a hash table; cannot move any element
-** (because gc can call `remove' during a table traversal)
-*/
-void luaH_remove (Table *t, Node *e) {
- Node *mp = luaH_mainposition(t, gkey(e));
- if (e != mp) { /* element not in its main position? */
- while (mp->next != e) mp = mp->next; /* find previous */
- mp->next = e->next; /* remove `e' from its list */
- }
- else {
- if (e->next != NULL) ??
- }
- lua_assert(ttisnil(gval(node)));
- setnilvalue(gkey(e)); /* clear node `e' */
- e->next = NULL;
-}
-#endif
-
/*
** inserts a new key into a hash table; first, check whether key's main
@@ -399,7 +375,7 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
}
}
setobj2t(L, gkey(mp), key);
- luaC_barrier(L, t, key);
+ luaC_barriert(L, t, key);
lua_assert(ttisnil(gval(mp)));
for (;;) { /* correct `firstfree' */
if (ttisnil(gkey(t->firstfree)))
@@ -418,21 +394,6 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
/*
-** generic search function
-*/
-static const TValue *luaH_getany (Table *t, const TValue *key) {
- if (!ttisnil(key)) {
- Node *n = luaH_mainposition(t, key);
- do { /* check whether `key' is somewhere in the chain */
- if (luaO_rawequalObj(gkey(n), key)) return gval(n); /* that's it */
- else n = n->next;
- } while (n);
- }
- return &luaO_nilobject;
-}
-
-
-/*
** search function for integers
*/
const TValue *luaH_getnum (Table *t, int key) {
@@ -470,6 +431,7 @@ const TValue *luaH_getstr (Table *t, TString *key) {
*/
const TValue *luaH_get (Table *t, const TValue *key) {
switch (ttype(key)) {
+ case LUA_TNIL: return &luaO_nilobject;
case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
case LUA_TNUMBER: {
int k;
@@ -478,7 +440,14 @@ const TValue *luaH_get (Table *t, const TValue *key) {
return luaH_getnum(t, k); /* use specialized version */
/* else go through */
}
- default: return luaH_getany(t, key);
+ default: {
+ Node *n = luaH_mainposition(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+ if (luaO_rawequalObj(gkey(n), key)) return gval(n); /* that's it */
+ else n = n->next;
+ } while (n);
+ return &luaO_nilobject;
+ }
}
}
diff --git a/src/ltable.h b/src/ltable.h
index 566d7cd4..d72cf9f5 100644
--- a/src/ltable.h
+++ b/src/ltable.h
@@ -1,5 +1,5 @@
/*
-** $Id: ltable.h,v 2.1 2003/12/10 12:13:36 roberto Exp $
+** $Id: ltable.h,v 2.2 2004/03/26 14:02:41 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -22,6 +22,7 @@ TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
const TValue *luaH_get (Table *t, const TValue *key);
TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
Table *luaH_new (lua_State *L, int narray, int lnhash);
+void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize);
void luaH_free (lua_State *L, Table *t);
int luaH_next (lua_State *L, Table *t, StkId key);
diff --git a/src/ltests.c b/src/ltests.c
deleted file mode 100644
index 649b14e0..00000000
--- a/src/ltests.c
+++ /dev/null
@@ -1,852 +0,0 @@
-/*
-** $Id: ltests.c,v 1.158 2003/04/07 14:35:00 roberto Exp $
-** Internal Module for Debugging of the Lua Implementation
-** See Copyright Notice in lua.h
-*/
-
-
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define ltests_c
-
-#include "lua.h"
-
-#include "lapi.h"
-#include "lauxlib.h"
-#include "lcode.h"
-#include "ldebug.h"
-#include "ldo.h"
-#include "lfunc.h"
-#include "lmem.h"
-#include "lopcodes.h"
-#include "lstate.h"
-#include "lstring.h"
-#include "ltable.h"
-#include "lualib.h"
-
-
-
-/*
-** The whole module only makes sense with LUA_DEBUG on
-*/
-#ifdef LUA_DEBUG
-
-
-#define lua_pushintegral(L,i) lua_pushnumber(L, cast(lua_Number, (i)))
-
-
-static lua_State *lua_state = NULL;
-
-int islocked = 0;
-
-
-#define func_at(L,k) (L->ci->base+(k) - 1)
-
-
-static void setnameval (lua_State *L, const char *name, int val) {
- lua_pushstring(L, name);
- lua_pushintegral(L, val);
- lua_settable(L, -3);
-}
-
-
-/*
-** {======================================================================
-** Controlled version for realloc.
-** =======================================================================
-*/
-
-#define MARK 0x55 /* 01010101 (a nice pattern) */
-
-#ifndef EXTERNMEMCHECK
-/* full memory check */
-#define HEADER (sizeof(L_Umaxalign)) /* ensures maximum alignment for HEADER */
-#define MARKSIZE 16 /* size of marks after each block */
-#define blockhead(b) (cast(char *, b) - HEADER)
-#define setsize(newblock, size) (*cast(size_t *, newblock) = size)
-#define checkblocksize(b, size) (size == (*cast(size_t *, blockhead(b))))
-#define fillmem(mem,size) memset(mem, -MARK, size)
-#else
-/* external memory check: don't do it twice */
-#define HEADER 0
-#define MARKSIZE 0
-#define blockhead(b) (b)
-#define setsize(newblock, size) /* empty */
-#define checkblocksize(b,size) (1)
-#define fillmem(mem,size) /* empty */
-#endif
-
-unsigned long memdebug_numblocks = 0;
-unsigned long memdebug_total = 0;
-unsigned long memdebug_maxmem = 0;
-unsigned long memdebug_memlimit = ULONG_MAX;
-
-
-static void *checkblock (void *block, size_t size) {
- void *b = blockhead(block);
- int i;
- for (i=0;i<MARKSIZE;i++)
- lua_assert(*(cast(char *, b)+HEADER+size+i) == MARK+i); /* corrupted block? */
- return b;
-}
-
-
-static void freeblock (void *block, size_t size) {
- if (block) {
- lua_assert(checkblocksize(block, size));
- block = checkblock(block, size);
- fillmem(block, size+HEADER+MARKSIZE); /* erase block */
- free(block); /* free original block */
- memdebug_numblocks--;
- memdebug_total -= size;
- }
-}
-
-
-void *debug_realloc (void *block, size_t oldsize, size_t size) {
- lua_assert(oldsize == 0 || checkblocksize(block, oldsize));
- /* ISO does not specify what realloc(NULL, 0) does */
- lua_assert(block != NULL || size > 0);
- if (size == 0) {
- freeblock(block, oldsize);
- return NULL;
- }
- else if (size > oldsize && memdebug_total+size-oldsize > memdebug_memlimit)
- return NULL; /* to test memory allocation errors */
- else {
- void *newblock;
- int i;
- size_t realsize = HEADER+size+MARKSIZE;
- size_t commonsize = (oldsize < size) ? oldsize : size;
- if (realsize < size) return NULL; /* overflow! */
- newblock = malloc(realsize); /* alloc a new block */
- if (newblock == NULL) return NULL;
- if (block) {
- memcpy(cast(char *, newblock)+HEADER, block, commonsize);
- freeblock(block, oldsize); /* erase (and check) old copy */
- }
- /* initialize new part of the block with something `weird' */
- fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize);
- memdebug_total += size;
- if (memdebug_total > memdebug_maxmem)
- memdebug_maxmem = memdebug_total;
- memdebug_numblocks++;
- setsize(newblock, size);
- for (i=0;i<MARKSIZE;i++)
- *(cast(char *, newblock)+HEADER+size+i) = cast(char, MARK+i);
- return cast(char *, newblock)+HEADER;
- }
-}
-
-
-/* }====================================================================== */
-
-
-
-/*
-** {======================================================
-** Disassembler
-** =======================================================
-*/
-
-
-static char *buildop (Proto *p, int pc, char *buff) {
- Instruction i = p->code[pc];
- OpCode o = GET_OPCODE(i);
- const char *name = luaP_opnames[o];
- int line = getline(p, pc);
- sprintf(buff, "(%4d) %4d - ", line, pc);
- switch (getOpMode(o)) {
- case iABC:
- sprintf(buff+strlen(buff), "%-12s%4d %4d %4d", name,
- GETARG_A(i), GETARG_B(i), GETARG_C(i));
- break;
- case iABx:
- sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i));
- break;
- case iAsBx:
- sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i));
- break;
- }
- return buff;
-}
-
-
-#if 0
-void luaI_printcode (Proto *pt, int size) {
- int pc;
- for (pc=0; pc<size; pc++) {
- char buff[100];
- printf("%s\n", buildop(pt, pc, buff));
- }
- printf("-------\n");
-}
-#endif
-
-
-static int listcode (lua_State *L) {
- int pc;
- Proto *p;
- luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
- 1, "Lua function expected");
- p = clvalue(func_at(L, 1))->l.p;
- lua_newtable(L);
- setnameval(L, "maxstack", p->maxstacksize);
- setnameval(L, "numparams", p->numparams);
- for (pc=0; pc<p->sizecode; pc++) {
- char buff[100];
- lua_pushintegral(L, pc+1);
- lua_pushstring(L, buildop(p, pc, buff));
- lua_settable(L, -3);
- }
- return 1;
-}
-
-
-static int listk (lua_State *L) {
- Proto *p;
- int i;
- luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
- 1, "Lua function expected");
- p = clvalue(func_at(L, 1))->l.p;
- lua_newtable(L);
- for (i=0; i<p->sizek; i++) {
- lua_pushintegral(L, i+1);
- luaA_pushobject(L, p->k+i);
- lua_settable(L, -3);
- }
- return 1;
-}
-
-
-static int listlocals (lua_State *L) {
- Proto *p;
- int pc = luaL_checkint(L, 2) - 1;
- int i = 0;
- const char *name;
- luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
- 1, "Lua function expected");
- p = clvalue(func_at(L, 1))->l.p;
- while ((name = luaF_getlocalname(p, ++i, pc)) != NULL)
- lua_pushstring(L, name);
- return i-1;
-}
-
-/* }====================================================== */
-
-
-
-
-static int get_limits (lua_State *L) {
- lua_newtable(L);
- setnameval(L, "BITS_INT", BITS_INT);
- setnameval(L, "LFPF", LFIELDS_PER_FLUSH);
- setnameval(L, "MAXVARS", MAXVARS);
- setnameval(L, "MAXPARAMS", MAXPARAMS);
- setnameval(L, "MAXSTACK", MAXSTACK);
- setnameval(L, "MAXUPVALUES", MAXUPVALUES);
- return 1;
-}
-
-
-static int mem_query (lua_State *L) {
- if (lua_isnone(L, 1)) {
- lua_pushintegral(L, memdebug_total);
- lua_pushintegral(L, memdebug_numblocks);
- lua_pushintegral(L, memdebug_maxmem);
- return 3;
- }
- else {
- memdebug_memlimit = luaL_checkint(L, 1);
- return 0;
- }
-}
-
-
-static int hash_query (lua_State *L) {
- if (lua_isnone(L, 2)) {
- luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected");
- lua_pushintegral(L, tsvalue(func_at(L, 1))->tsv.hash);
- }
- else {
- TObject *o = func_at(L, 1);
- Table *t;
- luaL_checktype(L, 2, LUA_TTABLE);
- t = hvalue(func_at(L, 2));
- lua_pushintegral(L, luaH_mainposition(t, o) - t->node);
- }
- return 1;
-}
-
-
-static int stacklevel (lua_State *L) {
- unsigned long a = 0;
- lua_pushintegral(L, (int)(L->top - L->stack));
- lua_pushintegral(L, (int)(L->stack_last - L->stack));
- lua_pushintegral(L, (int)(L->ci - L->base_ci));
- lua_pushintegral(L, (int)(L->end_ci - L->base_ci));
- lua_pushintegral(L, (unsigned long)&a);
- return 5;
-}
-
-
-static int table_query (lua_State *L) {
- const Table *t;
- int i = luaL_optint(L, 2, -1);
- luaL_checktype(L, 1, LUA_TTABLE);
- t = hvalue(func_at(L, 1));
- if (i == -1) {
- lua_pushintegral(L, t->sizearray);
- lua_pushintegral(L, sizenode(t));
- lua_pushintegral(L, t->firstfree - t->node);
- }
- else if (i < t->sizearray) {
- lua_pushintegral(L, i);
- luaA_pushobject(L, &t->array[i]);
- lua_pushnil(L);
- }
- else if ((i -= t->sizearray) < sizenode(t)) {
- if (!ttisnil(gval(gnode(t, i))) ||
- ttisnil(gkey(gnode(t, i))) ||
- ttisnumber(gkey(gnode(t, i)))) {
- luaA_pushobject(L, gkey(gnode(t, i)));
- }
- else
- lua_pushstring(L, "<undef>");
- luaA_pushobject(L, gval(gnode(t, i)));
- if (t->node[i].next)
- lua_pushintegral(L, t->node[i].next - t->node);
- else
- lua_pushnil(L);
- }
- return 3;
-}
-
-
-static int string_query (lua_State *L) {
- stringtable *tb = &G(L)->strt;
- int s = luaL_optint(L, 2, 0) - 1;
- if (s==-1) {
- lua_pushintegral(L ,tb->nuse);
- lua_pushintegral(L ,tb->size);
- return 2;
- }
- else if (s < tb->size) {
- GCObject *ts;
- int n = 0;
- for (ts = tb->hash[s]; ts; ts = ts->gch.next) {
- setsvalue2s(L->top, gcotots(ts));
- incr_top(L);
- n++;
- }
- return n;
- }
- return 0;
-}
-
-
-static int tref (lua_State *L) {
- int level = lua_gettop(L);
- int lock = luaL_optint(L, 2, 1);
- luaL_checkany(L, 1);
- lua_pushvalue(L, 1);
- lua_pushintegral(L, lua_ref(L, lock));
- assert(lua_gettop(L) == level+1); /* +1 for result */
- return 1;
-}
-
-static int getref (lua_State *L) {
- int level = lua_gettop(L);
- lua_getref(L, luaL_checkint(L, 1));
- assert(lua_gettop(L) == level+1);
- return 1;
-}
-
-static int unref (lua_State *L) {
- int level = lua_gettop(L);
- lua_unref(L, luaL_checkint(L, 1));
- assert(lua_gettop(L) == level);
- return 0;
-}
-
-static int metatable (lua_State *L) {
- luaL_checkany(L, 1);
- if (lua_isnone(L, 2)) {
- if (lua_getmetatable(L, 1) == 0)
- lua_pushnil(L);
- }
- else {
- lua_settop(L, 2);
- luaL_checktype(L, 2, LUA_TTABLE);
- lua_setmetatable(L, 1);
- }
- return 1;
-}
-
-
-static int upvalue (lua_State *L) {
- int n = luaL_checkint(L, 2);
- luaL_checktype(L, 1, LUA_TFUNCTION);
- if (lua_isnone(L, 3)) {
- const char *name = lua_getupvalue(L, 1, n);
- if (name == NULL) return 0;
- lua_pushstring(L, name);
- return 2;
- }
- else {
- const char *name = lua_setupvalue(L, 1, n);
- lua_pushstring(L, name);
- return 1;
- }
-}
-
-
-static int newuserdata (lua_State *L) {
- size_t size = luaL_checkint(L, 1);
- char *p = cast(char *, lua_newuserdata(L, size));
- while (size--) *p++ = '\0';
- return 1;
-}
-
-
-static int pushuserdata (lua_State *L) {
- lua_pushlightuserdata(L, cast(void *, luaL_checkint(L, 1)));
- return 1;
-}
-
-
-static int udataval (lua_State *L) {
- lua_pushintegral(L, cast(int, lua_touserdata(L, 1)));
- return 1;
-}
-
-
-static int doonnewstack (lua_State *L) {
- lua_State *L1 = lua_newthread(L);
- size_t l;
- const char *s = luaL_checklstring(L, 1, &l);
- int status = luaL_loadbuffer(L1, s, l, s);
- if (status == 0)
- status = lua_pcall(L1, 0, 0, 0);
- lua_pushintegral(L, status);
- return 1;
-}
-
-
-static int s2d (lua_State *L) {
- lua_pushnumber(L, *cast(const double *, luaL_checkstring(L, 1)));
- return 1;
-}
-
-static int d2s (lua_State *L) {
- double d = luaL_checknumber(L, 1);
- lua_pushlstring(L, cast(char *, &d), sizeof(d));
- return 1;
-}
-
-
-static int newstate (lua_State *L) {
- lua_State *L1 = lua_open();
- if (L1) {
- lua_userstateopen(L1); /* init lock */
- lua_pushintegral(L, (unsigned long)L1);
- }
- else
- lua_pushnil(L);
- return 1;
-}
-
-
-static int loadlib (lua_State *L) {
- static const luaL_reg libs[] = {
- {"mathlibopen", luaopen_math},
- {"strlibopen", luaopen_string},
- {"iolibopen", luaopen_io},
- {"tablibopen", luaopen_table},
- {"dblibopen", luaopen_debug},
- {"baselibopen", luaopen_base},
- {NULL, NULL}
- };
- lua_State *L1 = cast(lua_State *,
- cast(unsigned long, luaL_checknumber(L, 1)));
- lua_pushvalue(L1, LUA_GLOBALSINDEX);
- luaL_openlib(L1, NULL, libs, 0);
- return 0;
-}
-
-static int closestate (lua_State *L) {
- lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_checknumber(L, 1)));
- lua_close(L1);
- lua_unlock(L); /* close cannot unlock that */
- return 0;
-}
-
-static int doremote (lua_State *L) {
- lua_State *L1 = cast(lua_State *,cast(unsigned long,luaL_checknumber(L, 1)));
- size_t lcode;
- const char *code = luaL_checklstring(L, 2, &lcode);
- int status;
- lua_settop(L1, 0);
- status = luaL_loadbuffer(L1, code, lcode, code);
- if (status == 0)
- status = lua_pcall(L1, 0, LUA_MULTRET, 0);
- if (status != 0) {
- lua_pushnil(L);
- lua_pushintegral(L, status);
- lua_pushstring(L, lua_tostring(L1, -1));
- return 3;
- }
- else {
- int i = 0;
- while (!lua_isnone(L1, ++i))
- lua_pushstring(L, lua_tostring(L1, i));
- lua_pop(L1, i-1);
- return i-1;
- }
-}
-
-
-static int log2_aux (lua_State *L) {
- lua_pushintegral(L, luaO_log2(luaL_checkint(L, 1)));
- return 1;
-}
-
-static int int2fb_aux (lua_State *L) {
- int b = luaO_int2fb(luaL_checkint(L, 1));
- lua_pushintegral(L, b);
- lua_pushintegral(L, fb2int(b));
- return 2;
-}
-
-
-static int test_do (lua_State *L) {
- const char *p = luaL_checkstring(L, 1);
- if (*p == '@')
- lua_dofile(L, p+1);
- else
- lua_dostring(L, p);
- return lua_gettop(L);
-}
-
-
-
-/*
-** {======================================================
-** function to test the API with C. It interprets a kind of assembler
-** language with calls to the API, so the test can be driven by Lua code
-** =======================================================
-*/
-
-static const char *const delimits = " \t\n,;";
-
-static void skip (const char **pc) {
- while (**pc != '\0' && strchr(delimits, **pc)) (*pc)++;
-}
-
-static int getnum_aux (lua_State *L, const char **pc) {
- int res = 0;
- int sig = 1;
- skip(pc);
- if (**pc == '.') {
- res = cast(int, lua_tonumber(L, -1));
- lua_pop(L, 1);
- (*pc)++;
- return res;
- }
- else if (**pc == '-') {
- sig = -1;
- (*pc)++;
- }
- while (isdigit(cast(int, **pc))) res = res*10 + (*(*pc)++) - '0';
- return sig*res;
-}
-
-static const char *getname_aux (char *buff, const char **pc) {
- int i = 0;
- skip(pc);
- while (**pc != '\0' && !strchr(delimits, **pc))
- buff[i++] = *(*pc)++;
- buff[i] = '\0';
- return buff;
-}
-
-
-#define EQ(s1) (strcmp(s1, inst) == 0)
-
-#define getnum (getnum_aux(L, &pc))
-#define getname (getname_aux(buff, &pc))
-
-
-static int testC (lua_State *L) {
- char buff[30];
- const char *pc = luaL_checkstring(L, 1);
- for (;;) {
- const char *inst = getname;
- if EQ("") return 0;
- else if EQ("isnumber") {
- lua_pushintegral(L, lua_isnumber(L, getnum));
- }
- else if EQ("isstring") {
- lua_pushintegral(L, lua_isstring(L, getnum));
- }
- else if EQ("istable") {
- lua_pushintegral(L, lua_istable(L, getnum));
- }
- else if EQ("iscfunction") {
- lua_pushintegral(L, lua_iscfunction(L, getnum));
- }
- else if EQ("isfunction") {
- lua_pushintegral(L, lua_isfunction(L, getnum));
- }
- else if EQ("isuserdata") {
- lua_pushintegral(L, lua_isuserdata(L, getnum));
- }
- else if EQ("isudataval") {
- lua_pushintegral(L, lua_islightuserdata(L, getnum));
- }
- else if EQ("isnil") {
- lua_pushintegral(L, lua_isnil(L, getnum));
- }
- else if EQ("isnull") {
- lua_pushintegral(L, lua_isnone(L, getnum));
- }
- else if EQ("tonumber") {
- lua_pushnumber(L, lua_tonumber(L, getnum));
- }
- else if EQ("tostring") {
- const char *s = lua_tostring(L, getnum);
- lua_pushstring(L, s);
- }
- else if EQ("strlen") {
- lua_pushintegral(L, lua_strlen(L, getnum));
- }
- else if EQ("tocfunction") {
- lua_pushcfunction(L, lua_tocfunction(L, getnum));
- }
- else if EQ("return") {
- return getnum;
- }
- else if EQ("gettop") {
- lua_pushintegral(L, lua_gettop(L));
- }
- else if EQ("settop") {
- lua_settop(L, getnum);
- }
- else if EQ("pop") {
- lua_pop(L, getnum);
- }
- else if EQ("pushnum") {
- lua_pushintegral(L, getnum);
- }
- else if EQ("pushnil") {
- lua_pushnil(L);
- }
- else if EQ("pushbool") {
- lua_pushboolean(L, getnum);
- }
- else if EQ("tobool") {
- lua_pushintegral(L, lua_toboolean(L, getnum));
- }
- else if EQ("pushvalue") {
- lua_pushvalue(L, getnum);
- }
- else if EQ("pushcclosure") {
- lua_pushcclosure(L, testC, getnum);
- }
- else if EQ("pushupvalues") {
- lua_pushupvalues(L);
- }
- else if EQ("remove") {
- lua_remove(L, getnum);
- }
- else if EQ("insert") {
- lua_insert(L, getnum);
- }
- else if EQ("replace") {
- lua_replace(L, getnum);
- }
- else if EQ("gettable") {
- lua_gettable(L, getnum);
- }
- else if EQ("settable") {
- lua_settable(L, getnum);
- }
- else if EQ("next") {
- lua_next(L, -2);
- }
- else if EQ("concat") {
- lua_concat(L, getnum);
- }
- else if EQ("lessthan") {
- int a = getnum;
- lua_pushboolean(L, lua_lessthan(L, a, getnum));
- }
- else if EQ("equal") {
- int a = getnum;
- lua_pushboolean(L, lua_equal(L, a, getnum));
- }
- else if EQ("rawcall") {
- int narg = getnum;
- int nres = getnum;
- lua_call(L, narg, nres);
- }
- else if EQ("call") {
- int narg = getnum;
- int nres = getnum;
- lua_pcall(L, narg, nres, 0);
- }
- else if EQ("loadstring") {
- size_t sl;
- const char *s = luaL_checklstring(L, getnum, &sl);
- luaL_loadbuffer(L, s, sl, s);
- }
- else if EQ("loadfile") {
- luaL_loadfile(L, luaL_checkstring(L, getnum));
- }
- else if EQ("setmetatable") {
- lua_setmetatable(L, getnum);
- }
- else if EQ("getmetatable") {
- if (lua_getmetatable(L, getnum) == 0)
- lua_pushnil(L);
- }
- else if EQ("type") {
- lua_pushstring(L, lua_typename(L, lua_type(L, getnum)));
- }
- else if EQ("getn") {
- int i = getnum;
- lua_pushintegral(L, luaL_getn(L, i));
- }
- else if EQ("setn") {
- int i = getnum;
- int n = cast(int, lua_tonumber(L, -1));
- luaL_setn(L, i, n);
- lua_pop(L, 1);
- }
- else luaL_error(L, "unknown instruction %s", buff);
- }
- return 0;
-}
-
-/* }====================================================== */
-
-
-/*
-** {======================================================
-** tests for yield inside hooks
-** =======================================================
-*/
-
-static void yieldf (lua_State *L, lua_Debug *ar) {
- lua_yield(L, 0);
-}
-
-static int setyhook (lua_State *L) {
- if (lua_isnoneornil(L, 1))
- lua_sethook(L, NULL, 0, 0); /* turn off hooks */
- else {
- const char *smask = luaL_checkstring(L, 1);
- int count = luaL_optint(L, 2, 0);
- int mask = 0;
- if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
- if (count > 0) mask |= LUA_MASKCOUNT;
- lua_sethook(L, yieldf, mask, count);
- }
- return 0;
-}
-
-
-static int coresume (lua_State *L) {
- int status;
- lua_State *co = lua_tothread(L, 1);
- luaL_argcheck(L, co, 1, "coroutine expected");
- status = lua_resume(co, 0);
- if (status != 0) {
- lua_pushboolean(L, 0);
- lua_insert(L, -2);
- return 2; /* return false + error message */
- }
- else {
- lua_pushboolean(L, 1);
- return 1;
- }
-}
-
-/* }====================================================== */
-
-
-
-static const struct luaL_reg tests_funcs[] = {
- {"hash", hash_query},
- {"limits", get_limits},
- {"listcode", listcode},
- {"listk", listk},
- {"listlocals", listlocals},
- {"loadlib", loadlib},
- {"stacklevel", stacklevel},
- {"querystr", string_query},
- {"querytab", table_query},
- {"doit", test_do},
- {"testC", testC},
- {"ref", tref},
- {"getref", getref},
- {"unref", unref},
- {"d2s", d2s},
- {"s2d", s2d},
- {"metatable", metatable},
- {"upvalue", upvalue},
- {"newuserdata", newuserdata},
- {"pushuserdata", pushuserdata},
- {"udataval", udataval},
- {"doonnewstack", doonnewstack},
- {"newstate", newstate},
- {"closestate", closestate},
- {"doremote", doremote},
- {"log2", log2_aux},
- {"int2fb", int2fb_aux},
- {"totalmem", mem_query},
- {"resume", coresume},
- {"setyhook", setyhook},
- {NULL, NULL}
-};
-
-
-static void fim (void) {
- if (!islocked)
- lua_close(lua_state);
- lua_assert(memdebug_numblocks == 0);
- lua_assert(memdebug_total == 0);
-}
-
-
-static int l_panic (lua_State *L) {
- UNUSED(L);
- fprintf(stderr, "unable to recover; exiting\n");
- return 0;
-}
-
-
-int luaB_opentests (lua_State *L) {
- lua_atpanic(L, l_panic);
- lua_userstateopen(L); /* init lock */
- lua_state = L; /* keep first state to be opened */
- luaL_openlib(L, "T", tests_funcs, 0);
- atexit(fim);
- return 0;
-}
-
-
-#undef main
-int main (int argc, char *argv[]) {
- char *limit = getenv("MEMLIMIT");
- if (limit)
- memdebug_memlimit = strtoul(limit, NULL, 10);
- l_main(argc, argv);
- return 0;
-}
-
-#endif
diff --git a/src/ltm.c b/src/ltm.c
index de4bb7af..4515efc6 100644
--- a/src/ltm.c
+++ b/src/ltm.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltm.c,v 2.2 2004/02/16 19:09:52 roberto Exp $
+** $Id: ltm.c,v 2.3 2004/04/30 20:13:38 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,7 @@
#include <string.h>
#define ltm_c
+#define LUA_CORE
#include "lua.h"
diff --git a/src/lua/RCS b/src/lua/RCS
deleted file mode 120000
index 1ae38936..00000000
--- a/src/lua/RCS
+++ /dev/null
@@ -1 +0,0 @@
-../RCS \ No newline at end of file
diff --git a/src/lua/README b/src/lua/README
index fca1e900..1bd07af6 100644
--- a/src/lua/README
+++ b/src/lua/README
@@ -1,4 +1,4 @@
-This is lua, a sample Lua interpreter.
+This is lua, the stand-alone Lua interpreter.
It can be used as a batch interpreter and also interactively.
There are man pages for it in both nroff and html in ../../doc.
@@ -10,7 +10,7 @@ Usage: lua [options] [script [args]]. Available options are:
-v show version information
-- stop handling options
-This interpreter is suitable for using Lua as a standalone language; it loads
+This interpreter is suitable for using Lua as a stand-alone language; it loads
all standard libraries. For a minimal interpreter, see ../../etc/min.c.
If your application simply exports new functions to Lua (which is common),
diff --git a/src/lua/lua.c b/src/lua/lua.c
index 4e669c07..6fe479b3 100644
--- a/src/lua/lua.c
+++ b/src/lua/lua.c
@@ -1,5 +1,5 @@
/*
-** $Id: lua.c,v 1.124 2003/10/23 18:06:22 roberto Exp $
+** $Id: lua.c,v 1.132 2004/08/30 18:35:14 roberto Exp $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
@@ -26,73 +26,25 @@
#endif
-/*
-** definition of `isatty'
-*/
-#ifdef _POSIX_C_SOURCE
-#include <unistd.h>
-#define stdin_is_tty() isatty(0)
-#else
-#define stdin_is_tty() 1 /* assume stdin is a tty */
-#endif
-
-
-
-#ifndef PROMPT
-#define PROMPT "> "
-#endif
-
-
-#ifndef PROMPT2
-#define PROMPT2 ">> "
-#endif
-
-#ifndef PROGNAME
-#define PROGNAME "lua"
-#endif
-
-#ifndef lua_userinit
-#define lua_userinit(L) openstdlibs(L)
-#endif
-
-
-#ifndef LUA_EXTRALIBS
-#define LUA_EXTRALIBS /* empty */
-#endif
-static lua_State *L = NULL;
+static lua_State *globalL = NULL;
static const char *progname = PROGNAME;
-static const luaL_reg lualibs[] = {
- {"base", luaopen_base},
- {"table", luaopen_table},
- {"io", luaopen_io},
- {"string", luaopen_string},
- {"math", luaopen_math},
- {"debug", luaopen_debug},
- {"loadlib", luaopen_loadlib},
- /* add your libraries here */
- LUA_EXTRALIBS
- {NULL, NULL}
-};
-
-
-
-static void lstop (lua_State *l, lua_Debug *ar) {
+static void lstop (lua_State *L, lua_Debug *ar) {
(void)ar; /* unused arg. */
- lua_sethook(l, NULL, 0, 0);
- luaL_error(l, "interrupted!");
+ lua_sethook(L, NULL, 0, 0);
+ luaL_error(L, "interrupted!");
}
static void laction (int i) {
signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
terminate process (default action) */
- lua_sethook(L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
+ lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
}
@@ -116,7 +68,7 @@ static void l_message (const char *pname, const char *msg) {
}
-static int report (int status) {
+static int report (lua_State *L, int status) {
if (status && !lua_isnil(L, -1)) {
const char *msg = lua_tostring(L, -1);
if (msg == NULL) msg = "(error object is not a string)";
@@ -127,7 +79,7 @@ static int report (int status) {
}
-static int lcall (int narg, int clear) {
+static int docall (lua_State *L, int narg, int clear) {
int status;
int base = lua_gettop(L) - narg; /* function index */
lua_pushliteral(L, "_TRACEBACK");
@@ -146,55 +98,46 @@ static void print_version (void) {
}
-static void getargs (char *argv[], int n) {
- int i;
+static int getargs (lua_State *L, char *argv[], int n) {
+ int i, narg;
+ for (i=n+1; argv[i]; i++) {
+ luaL_checkstack(L, 1, "too many arguments to script");
+ lua_pushstring(L, argv[i]);
+ }
+ narg = i-(n+1); /* number of arguments to the script (not to `lua.c') */
lua_newtable(L);
for (i=0; argv[i]; i++) {
- lua_pushnumber(L, i - n);
lua_pushstring(L, argv[i]);
- lua_rawset(L, -3);
+ lua_rawseti(L, -2, i - n);
}
+ return narg;
}
-static int docall (int status) {
- if (status == 0) status = lcall(0, 1);
- return report(status);
-}
-
-
-static int file_input (const char *name) {
- return docall(luaL_loadfile(L, name));
+static int dofile (lua_State *L, const char *name) {
+ int status = luaL_loadfile(L, name) || docall(L, 0, 1);
+ return report(L, status);
}
-static int dostring (const char *s, const char *name) {
- return docall(luaL_loadbuffer(L, s, strlen(s), name));
+static int dostring (lua_State *L, const char *s, const char *name) {
+ int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
+ return report(L, status);
}
-static int load_file (const char *name) {
- lua_pushliteral(L, "require");
- lua_rawget(L, LUA_GLOBALSINDEX);
- if (!lua_isfunction(L, -1)) { /* no `require' defined? */
- lua_pop(L, 1);
- return file_input(name);
- }
- else {
- lua_pushstring(L, name);
- return report(lcall(1, 1));
+static int dolibrary (lua_State *L, const char *name) {
+ lua_getfield(L, LUA_GLOBALSINDEX, "_PATH");
+ if (!lua_isstring(L, -1)) {
+ l_message(progname, "global _PATH must be a string");
+ return 1;
}
+ name = luaL_searchpath(L, name, lua_tostring(L, -1));
+ if (name == NULL) return report(L, 1);
+ else return dofile(L, name);
}
-/*
-** this macro can be used by some `history' system to save lines
-** read in manual input
-*/
-#ifndef lua_saveline
-#define lua_saveline(L,line) /* empty */
-#endif
-
/*
** this macro defines a function to show the prompt and reads the
@@ -209,7 +152,7 @@ static int load_file (const char *name) {
#endif
-static int readline (lua_State *l, const char *prompt) {
+static int readline (lua_State *L, const char *prompt) {
static char buffer[MAXINPUT];
if (prompt) {
fputs(prompt, stdout);
@@ -218,7 +161,7 @@ static int readline (lua_State *l, const char *prompt) {
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
return 0; /* read fails */
else {
- lua_pushstring(l, buffer);
+ lua_pushstring(L, buffer);
return 1;
}
}
@@ -226,7 +169,7 @@ static int readline (lua_State *l, const char *prompt) {
#endif
-static const char *get_prompt (int firstline) {
+static const char *get_prompt (lua_State *L, int firstline) {
const char *p = NULL;
lua_pushstring(L, firstline ? "_PROMPT" : "_PROMPT2");
lua_rawget(L, LUA_GLOBALSINDEX);
@@ -237,7 +180,7 @@ static const char *get_prompt (int firstline) {
}
-static int incomplete (int status) {
+static int incomplete (lua_State *L, int status) {
if (status == LUA_ERRSYNTAX &&
strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) {
lua_pop(L, 1);
@@ -248,10 +191,10 @@ static int incomplete (int status) {
}
-static int load_string (void) {
+static int loadline (lua_State *L) {
int status;
lua_settop(L, 0);
- if (lua_readline(L, get_prompt(1)) == 0) /* no input? */
+ if (lua_readline(L, get_prompt(L, 1)) == 0) /* no input? */
return -1;
if (lua_tostring(L, -1)[0] == '=') { /* line starts with `=' ? */
lua_pushfstring(L, "return %s", lua_tostring(L, -1)+1);/* `=' -> `return' */
@@ -259,8 +202,8 @@ static int load_string (void) {
}
for (;;) { /* repeat until gets a complete line */
status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
- if (!incomplete(status)) break; /* cannot try to add lines? */
- if (lua_readline(L, get_prompt(0)) == 0) /* no more input? */
+ if (!incomplete(L, status)) break; /* cannot try to add lines? */
+ if (lua_readline(L, get_prompt(L, 0)) == 0) /* no more input? */
return -1;
lua_concat(L, lua_gettop(L)); /* join lines */
}
@@ -270,13 +213,14 @@ static int load_string (void) {
}
-static void manual_input (void) {
+static void dotty (lua_State *L) {
int status;
const char *oldprogname = progname;
progname = NULL;
- while ((status = load_string()) != -1) {
- if (status == 0) status = lcall(0, 0);
- report(status);
+ print_version();
+ while ((status = loadline(L)) != -1) {
+ if (status == 0) status = docall(L, 0, 0);
+ report(L, status);
if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
lua_getglobal(L, "print");
lua_insert(L, 1);
@@ -291,14 +235,23 @@ static void manual_input (void) {
}
-static int handle_argv (char *argv[], int *interactive) {
- if (argv[1] == NULL) { /* no more arguments? */
- if (stdin_is_tty()) {
- print_version();
- manual_input();
- }
+static int checkvar (lua_State *L) {
+ const char *name = lua_tostring(L, 2);
+ if (name)
+ luaL_error(L, "attempt to access undefined variable `%s'", name);
+ return 0;
+}
+
+
+#define clearinteractive(i) (*i &= 2)
+
+static int handle_argv (lua_State *L, char *argv[], int *interactive) {
+ if (argv[1] == NULL) { /* no arguments? */
+ *interactive = 0;
+ if (stdin_is_tty())
+ dotty(L);
else
- file_input(NULL); /* executes stdin as a file */
+ dofile(L, NULL); /* executes stdin as a file */
}
else { /* other arguments; loop over them */
int i;
@@ -314,25 +267,35 @@ static int handle_argv (char *argv[], int *interactive) {
goto endloop; /* stop handling arguments */
}
case '\0': {
- file_input(NULL); /* executes stdin as a file */
+ clearinteractive(interactive);
+ dofile(L, NULL); /* executes stdin as a file */
break;
}
case 'i': {
- *interactive = 1;
+ *interactive = 2; /* force interactive mode after arguments */
break;
}
case 'v': {
+ clearinteractive(interactive);
print_version();
break;
}
+ case 'w': {
+ if (lua_getmetatable(L, LUA_GLOBALSINDEX)) {
+ lua_pushcfunction(L, checkvar);
+ lua_setfield(L, -2, "__index");
+ }
+ break;
+ }
case 'e': {
const char *chunk = argv[i] + 2;
+ clearinteractive(interactive);
if (*chunk == '\0') chunk = argv[++i];
if (chunk == NULL) {
print_usage();
return 1;
}
- if (dostring(chunk, "=<command line>") != 0)
+ if (dostring(L, chunk, "=<command line>") != 0)
return 1;
break;
}
@@ -343,19 +306,12 @@ static int handle_argv (char *argv[], int *interactive) {
print_usage();
return 1;
}
- if (load_file(filename))
+ if (dolibrary(L, filename))
return 1; /* stop if file fails */
break;
}
- case 'c': {
- l_message(progname, "option `-c' is deprecated");
- break;
- }
- case 's': {
- l_message(progname, "option `-s' is deprecated");
- break;
- }
default: {
+ clearinteractive(interactive);
print_usage();
return 1;
}
@@ -363,31 +319,30 @@ static int handle_argv (char *argv[], int *interactive) {
} endloop:
if (argv[i] != NULL) {
const char *filename = argv[i];
- getargs(argv, i); /* collect arguments */
+ int narg = getargs(L, argv, i); /* collect arguments */
+ int status;
lua_setglobal(L, "arg");
- return file_input(filename); /* stop scanning arguments */
+ clearinteractive(interactive);
+ status = luaL_loadfile(L, filename);
+ lua_insert(L, -(narg+1));
+ if (status == 0)
+ status = docall(L, narg, 0);
+ else
+ lua_pop(L, narg);
+ return report(L, status);
}
}
return 0;
}
-static void openstdlibs (lua_State *l) {
- const luaL_reg *lib = lualibs;
- for (; lib->func; lib++) {
- lib->func(l); /* open library */
- lua_settop(l, 0); /* discard any results */
- }
-}
-
-
-static int handle_luainit (void) {
+static int handle_luainit (lua_State *L) {
const char *init = getenv("LUA_INIT");
if (init == NULL) return 0; /* status OK */
else if (init[0] == '@')
- return file_input(init+1);
+ return dofile(L, init+1);
else
- return dostring(init, "=LUA_INIT");
+ return dostring(L, init, "=LUA_INIT");
}
@@ -398,17 +353,17 @@ struct Smain {
};
-static int pmain (lua_State *l) {
- struct Smain *s = (struct Smain *)lua_touserdata(l, 1);
+static int pmain (lua_State *L) {
+ struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
int status;
- int interactive = 0;
+ int interactive = 1;
if (s->argv[0] && s->argv[0][0]) progname = s->argv[0];
- L = l;
- lua_userinit(l); /* open libraries */
- status = handle_luainit();
+ globalL = L;
+ lua_userinit(L); /* open libraries */
+ status = handle_luainit(L);
if (status == 0) {
- status = handle_argv(s->argv, &interactive);
- if (status == 0 && interactive) manual_input();
+ status = handle_argv(L, s->argv, &interactive);
+ if (status == 0 && interactive) dotty(L);
}
s->status = status;
return 0;
@@ -418,16 +373,16 @@ static int pmain (lua_State *l) {
int main (int argc, char *argv[]) {
int status;
struct Smain s;
- lua_State *l = lua_open(); /* create state */
- if (l == NULL) {
+ lua_State *L = lua_open(); /* create state */
+ if (L == NULL) {
l_message(argv[0], "cannot create state: not enough memory");
return EXIT_FAILURE;
}
s.argc = argc;
s.argv = argv;
- status = lua_cpcall(l, &pmain, &s);
- report(status);
- lua_close(l);
+ status = lua_cpcall(L, &pmain, &s);
+ report(L, status);
+ lua_close(L);
return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/luac/Makefile b/src/luac/Makefile
index a6c7d38f..509577bb 100644
--- a/src/luac/Makefile
+++ b/src/luac/Makefile
@@ -5,7 +5,7 @@ LUA= ../..
include $(LUA)/config
INCS= -I$(INC) -I.. $(EXTRA_INCS)
-OBJS= luac.o print.o lopcodes.o
+OBJS= luac.o print.o
SRCS= luac.c print.c
T= $(BIN)/luac
@@ -15,10 +15,6 @@ all: $T
$T: $(OBJS) $(LIB)/liblua.a ../lib/lauxlib.o
$(CC) -o $@ $(MYLDFLAGS) $(OBJS) ../lib/lauxlib.o -L$(LIB) -llua $(EXTRA_LIBS)
-# print.c needs opcode names from lopcodes.c
-lopcodes.o: ../lopcodes.c ../lopcodes.h
- $(CC) -o $@ -c $(CFLAGS) -DLUA_OPNAMES ../lopcodes.c
-
$(LIB)/liblua.a:
cd ..; $(MAKE)
diff --git a/src/luac/RCS b/src/luac/RCS
deleted file mode 120000
index 1ae38936..00000000
--- a/src/luac/RCS
+++ /dev/null
@@ -1 +0,0 @@
-../RCS \ No newline at end of file
diff --git a/src/luac/README b/src/luac/README
index 140d9457..00dd1cd4 100644
--- a/src/luac/README
+++ b/src/luac/README
@@ -1,7 +1,7 @@
This is luac, the Lua compiler.
There are man pages for it in both nroff and html in ../../doc.
-luac translates Lua programs into binary files that can be loaded latter.
+luac translates Lua programs into binary files that can be loaded later.
The main advantages of pre-compiling chunks are: faster loading, protecting
source code from user changes, and off-line syntax error detection.
luac can also be used to learn about the Lua virtual machine.
diff --git a/src/luac/luac.c b/src/luac/luac.c
index f634d5f9..dfbcab05 100644
--- a/src/luac/luac.c
+++ b/src/luac/luac.c
@@ -1,5 +1,5 @@
/*
-** $Id: luac.c,v 1.47 2004/03/24 00:25:08 lhf Exp $
+** $Id: luac.c,v 1.49 2004/09/01 21:22:34 lhf Exp $
** Lua compiler (saves bytecodes to files; also list bytecodes)
** See Copyright Notice in lua.h
*/
@@ -9,6 +9,9 @@
#include <stdlib.h>
#include <string.h>
+#define luac_c
+#define LUA_CORE
+
#include "lua.h"
#include "lauxlib.h"
@@ -43,8 +46,7 @@ static void fatal(const char* message)
static void cannot(const char* what)
{
- fprintf(stderr,"%s: cannot %s output file %s: %s\n",
- progname,what,output,strerror(errno));
+ fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno));
exit(EXIT_FAILURE);
}
@@ -84,13 +86,14 @@ static int doargs(int argc, char* argv[])
break;
}
else if (IS("-")) /* end of options; use stdin */
- return i;
+ break;
else if (IS("-l")) /* list */
- listing=1;
+ ++listing;
else if (IS("-o")) /* output file */
{
output=argv[++i];
if (output==NULL || *output==0) usage("`-o' needs argument");
+ if (IS("-")) output=NULL;
}
else if (IS("-p")) /* parse only */
dumping=0;
@@ -112,11 +115,7 @@ static int doargs(int argc, char* argv[])
return i;
}
-static Proto* toproto(lua_State* L, int i)
-{
- const Closure* c=(const Closure*)lua_topointer(L,i);
- return c->l.p;
-}
+#define toproto(L,i) (clvalue(L->top+(i))->l.p)
static Proto* combine(lua_State* L, int n)
{
@@ -124,18 +123,20 @@ static Proto* combine(lua_State* L, int n)
return toproto(L,-1);
else
{
- int i,pc=0;
+ int i,pc;
Proto* f=luaF_newproto(L);
setptvalue2s(L,L->top,f); incr_top(L);
f->source=luaS_newliteral(L,"=(" PROGNAME ")");
f->maxstacksize=1;
+ pc=2*n+1;
+ f->code=luaM_newvector(L,pc,Instruction);
+ f->sizecode=pc;
f->p=luaM_newvector(L,n,Proto*);
f->sizep=n;
- f->sizecode=2*n+1;
- f->code=luaM_newvector(L,f->sizecode,Instruction);
+ pc=0;
for (i=0; i<n; i++)
{
- f->p[i]=toproto(L,i-n);
+ f->p[i]=toproto(L,i-n-1);
f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);
f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);
}
@@ -147,26 +148,23 @@ static Proto* combine(lua_State* L, int n)
static int writer(lua_State* L, const void* p, size_t size, void* u)
{
UNUSED(L);
- return fwrite(p,size,1,(FILE*)u)==1;
+ return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
}
-static int panic(lua_State *L)
-{
- UNUSED(L);
- fatal("not enough memory!");
- return 0;
-}
+void unprint(lua_State* L, const char* name);
-int main(int argc, char* argv[])
+struct Smain {
+ int argc;
+ char **argv;
+};
+
+static int pmain(lua_State *L)
{
- lua_State* L;
+ struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
+ int argc=s->argc;
+ char **argv=s->argv;
Proto* f;
- int i=doargs(argc,argv);
- argc-=i; argv+=i;
- if (argc<=0) usage("no input files given");
- L=lua_open();
- if (L==NULL) fatal("not enough memory for state");
- lua_atpanic(L,panic);
+ int i;
if (!lua_checkstack(L,argc)) fatal("too many input files");
for (i=0; i<argc; i++)
{
@@ -174,10 +172,10 @@ int main(int argc, char* argv[])
if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1));
}
f=combine(L,argc);
- if (listing) luaU_print(f);
+ if (listing) luaU_print(f,listing>1);
if (dumping)
{
- FILE* D=fopen(output,"wb");
+ FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
if (D==NULL) cannot("open");
lua_lock(L);
luaU_dump(L,f,writer,D,stripping);
@@ -185,6 +183,21 @@ int main(int argc, char* argv[])
if (ferror(D)) cannot("write");
if (fclose(D)) cannot("close");
}
+ return 0;
+}
+
+int main(int argc, char* argv[])
+{
+ lua_State* L;
+ struct Smain s;
+ int i=doargs(argc,argv);
+ argc-=i; argv+=i;
+ if (argc<=0) usage("no input files given");
+ L=lua_open();
+ if (L==NULL) fatal("not enough memory for state");
+ s.argc=argc;
+ s.argv=argv;
+ if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1));
lua_close(L);
return EXIT_SUCCESS;
}
diff --git a/src/luac/print.c b/src/luac/print.c
index 2f9e7d12..0d3f18bf 100644
--- a/src/luac/print.c
+++ b/src/luac/print.c
@@ -1,18 +1,13 @@
/*
-** $Id: print.c,v 1.46 2004/03/24 00:25:08 lhf Exp $
+** $Id: print.c,v 1.48 2004/09/01 21:22:34 lhf Exp $
** print bytecodes
** See Copyright Notice in lua.h
*/
+#include <ctype.h>
#include <stdio.h>
-#if 1
-#define DEBUG_PRINT
-#endif
-
-#ifndef LUA_OPNAMES
-#define LUA_OPNAMES
-#endif
+#define LUA_CORE
#include "ldebug.h"
#include "lobject.h"
@@ -38,7 +33,7 @@ static void PrintString(const Proto* f, int n)
case '\r': printf("\\r"); break;
case '\t': printf("\\t"); break;
case '\v': printf("\\v"); break;
- default: putchar(*s); break;
+ default: printf(isprint(*s) ? "%c" : "\\%03d",*s);
}
}
putchar('"');
@@ -88,13 +83,11 @@ static void PrintCode(const Proto* f)
{
case iABC:
printf("%d",a);
- if (getBMode(o)!=OpArgN)
- { if (b>=MAXSTACK) printf(" #%d",b-MAXSTACK); else printf(" %d",b); }
- if (getCMode(o)!=OpArgN)
- { if (c>=MAXSTACK) printf(" #%d",c-MAXSTACK); else printf(" %d",c); }
+ if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b);
+ if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c);
break;
case iABx:
- if (getBMode(o)==OpArgK) printf("%d #%d",a,bx); else printf("%d %d",a,bx);
+ if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx);
break;
case iAsBx:
if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx);
@@ -115,7 +108,7 @@ static void PrintCode(const Proto* f)
break;
case OP_GETTABLE:
case OP_SELF:
- if (c>=MAXSTACK) { printf("\t; "); PrintConstant(f,c-MAXSTACK); }
+ if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); }
break;
case OP_SETTABLE:
case OP_ADD:
@@ -126,12 +119,12 @@ static void PrintCode(const Proto* f)
case OP_EQ:
case OP_LT:
case OP_LE:
- if (b>=MAXSTACK || c>=MAXSTACK)
+ if (ISK(b) || ISK(c))
{
printf("\t; ");
- if (b>=MAXSTACK) PrintConstant(f,b-MAXSTACK); else printf("-");
+ if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-");
printf(" ");
- if (c>=MAXSTACK) PrintConstant(f,c-MAXSTACK); else printf("-");
+ if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-");
}
break;
case OP_JMP:
@@ -161,15 +154,13 @@ static const char* Source(const Proto* f)
return "(string)";
}
-#define IsMain(f) (f->lineDefined==0)
-
#define SS(x) (x==1)?"":"s"
#define S(x) x,SS(x)
static void PrintHeader(const Proto* f)
{
printf("\n%s <%s:%d> (%d instruction%s, %d bytes at %p)\n",
- IsMain(f)?"main":"function",Source(f),f->lineDefined,
+ (f->lineDefined==0)?"main":"function",Source(f),f->lineDefined,
S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f));
printf("%d%s param%s, %d stack%s, %d upvalue%s, ",
f->numparams,f->is_vararg?"+":"",SS(f->numparams),S(f->maxstacksize),
@@ -178,14 +169,13 @@ static void PrintHeader(const Proto* f)
S(f->sizelocvars),S(f->sizek),S(f->sizep));
}
-#ifdef DEBUG_PRINT
static void PrintConstants(const Proto* f)
{
int i,n=f->sizek;
printf("constants (%d) for %p:\n",n,VOID(f));
for (i=0; i<n; i++)
{
- printf("\t%d\t",i);
+ printf("\t%d\t",i+1);
PrintConstant(f,i);
printf("\n");
}
@@ -212,17 +202,17 @@ static void PrintUpvalues(const Proto* f)
printf("\t%d\t%s\n",i,getstr(f->upvalues[i]));
}
}
-#endif
-void luaU_print(const Proto* f)
+void luaU_print(const Proto* f, int full)
{
int i,n=f->sizep;
PrintHeader(f);
PrintCode(f);
-#ifdef DEBUG_PRINT
- PrintConstants(f);
- PrintLocals(f);
- PrintUpvalues(f);
-#endif
- for (i=0; i<n; i++) luaU_print(f->p[i]);
+ if (full)
+ {
+ PrintConstants(f);
+ PrintLocals(f);
+ PrintUpvalues(f);
+ }
+ for (i=0; i<n; i++) luaU_print(f->p[i],full);
}
diff --git a/src/lundump.c b/src/lundump.c
index d79dd898..ee091602 100644
--- a/src/lundump.c
+++ b/src/lundump.c
@@ -1,5 +1,5 @@
/*
-** $Id: lundump.c,v 1.51 2004/03/24 00:25:08 lhf Exp $
+** $Id: lundump.c,v 1.53 2004/09/01 21:22:34 lhf Exp $
** load pre-compiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,7 @@
#include <stddef.h>
#define lundump_c
+#define LUA_CORE
#include "lua.h"
@@ -261,15 +262,15 @@ static void LoadHeader (LoadState* S)
/*
** load precompiled chunk
*/
-Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* s)
+Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
{
LoadState S;
- if (*s=='@' || *s=='=')
- S.name=s+1;
- else if (*s==LUA_SIGNATURE[0])
+ if (*name=='@' || *name=='=')
+ S.name=name+1;
+ else if (*name==LUA_SIGNATURE[0])
S.name="binary string";
else
- S.name=s;
+ S.name=name;
S.L=L;
S.Z=Z;
S.b=buff;
diff --git a/src/lundump.h b/src/lundump.h
index 26c792a8..4628b81d 100644
--- a/src/lundump.h
+++ b/src/lundump.h
@@ -1,5 +1,5 @@
/*
-** $Id: lundump.h,v 1.32 2003/12/09 19:22:19 lhf Exp $
+** $Id: lundump.h,v 1.33 2004/06/09 21:03:53 lhf Exp $
** load pre-compiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -17,10 +17,10 @@ Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char *name);
int luaU_endianness (void);
/* dump one chunk; from ldump.c */
-int luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data, int strip);
+int luaU_dump (lua_State* L, const Proto* f, lua_Chunkwriter w, void* data, int strip);
/* print one chunk; from print.c */
-void luaU_print (const Proto* Main);
+void luaU_print (const Proto* f, int full);
/* definitions for headers of binary files */
#define VERSION 0x51 /* last format change was in 5.1 */
diff --git a/src/lvm.c b/src/lvm.c
index bfbe8bf2..05af9df1 100644
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -1,5 +1,5 @@
/*
-** $Id: lvm.c,v 2.2 2004/03/16 12:31:40 roberto Exp $
+** $Id: lvm.c,v 2.13 2004/08/12 14:19:51 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -8,10 +8,8 @@
#include <stdlib.h>
#include <string.h>
-/* needed only when `lua_number2str' uses `sprintf' */
-#include <stdio.h>
-
#define lvm_c
+#define LUA_CORE
#include "lua.h"
@@ -29,12 +27,6 @@
-/* function to convert a lua_Number to a string */
-#ifndef lua_number2str
-#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
-#endif
-
-
/* limit for table tag-method chains (to avoid loops) */
#define MAXTAGLOOP 100
@@ -66,8 +58,8 @@ int luaV_tostring (lua_State *L, StkId obj) {
static void traceexec (lua_State *L, const Instruction *pc) {
lu_byte mask = L->hookmask;
CallInfo *ci = L->ci;
- const Instruction *oldpc = ci->u.l.savedpc;
- ci->u.l.savedpc = pc;
+ const Instruction *oldpc = ci->savedpc;
+ ci->savedpc = pc;
if (mask > LUA_MASKLINE) { /* instruction-hook set? */
if (L->hookcount == 0) {
resethookcount(L);
@@ -114,7 +106,8 @@ static void callTM (lua_State *L) {
}
-void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+StkId luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val,
+ const Instruction *pc) {
int loop;
for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm;
@@ -124,24 +117,30 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
if (!ttisnil(res) || /* result is no nil? */
(tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
setobj2s(L, val, res);
- return;
+ return L->base;
}
/* else will try the tag method */
}
- else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) {
+ L->ci->savedpc = pc;
luaG_typeerror(L, t, "index");
+ }
if (ttisfunction(tm)) {
+ L->ci->savedpc = pc;
prepTMcall(L, tm, t, key);
callTMres(L, val);
- return;
+ return L->base;
}
t = tm; /* else repeat with `tm' */
}
+ L->ci->savedpc = pc;
luaG_runerror(L, "loop in gettable");
+ return NULL; /* to avoid warnings */
}
-void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+StkId luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val,
+ const Instruction *pc) {
int loop;
for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm;
@@ -151,22 +150,27 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
if (!ttisnil(oldval) || /* result is no nil? */
(tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
setobj2t(L, oldval, val);
- luaC_barrier(L, h, val);
- return;
+ luaC_barriert(L, h, val);
+ return L->base;
}
/* else will try the tag method */
}
- else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) {
+ L->ci->savedpc = pc;
luaG_typeerror(L, t, "index");
+ }
if (ttisfunction(tm)) {
+ L->ci->savedpc = pc;
prepTMcall(L, tm, t, key);
setobj2s(L, L->top+3, val); /* 3th argument */
callTM(L);
- return;
+ return L->base;
}
t = tm; /* else repeat with `tm' */
}
+ L->ci->savedpc = pc;
luaG_runerror(L, "loop in settable");
+ return NULL; /* to avoid warnings */
}
@@ -304,10 +308,11 @@ void luaV_concat (lua_State *L, int total, int last) {
char *buffer;
int i;
while (n < total && tostring(L, top-n-1)) { /* collect total length */
- tl += tsvalue(top-n-1)->len;
+ size_t l = tsvalue(top-n-1)->len;
+ if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow");
+ tl += l;
n++;
}
- if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow");
buffer = luaZ_openspace(L, &G(L)->buff, tl);
tl = 0;
for (i=n; i>0; i--) { /* concat all strings */
@@ -327,7 +332,7 @@ static StkId Arith (lua_State *L, StkId ra, const TValue *rb,
const TValue *rc, TMS op, const Instruction *pc) {
TValue tempb, tempc;
const TValue *b, *c;
- L->ci->u.l.savedpc = pc;
+ L->ci->savedpc = pc;
if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
(c = luaV_tonumber(rc, &tempc)) != NULL) {
switch (op) {
@@ -364,13 +369,13 @@ static StkId Arith (lua_State *L, StkId ra, const TValue *rb,
#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
- (GETARG_B(i) < MAXSTACK) ? base+GETARG_B(i) : k+GETARG_B(i)-MAXSTACK)
+ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
- (GETARG_C(i) < MAXSTACK) ? base+GETARG_C(i) : k+GETARG_C(i)-MAXSTACK)
+ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))
-#define dojump(pc, i) ((pc) += (i))
+#define dojump(L,pc,i) {(pc) += (i); lua_threadyield(L);}
StkId luaV_execute (lua_State *L, int nexeccalls) {
@@ -382,9 +387,9 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1);
retentry: /* entry point when returning to old functions */
- pc = L->ci->u.l.savedpc;
+ pc = L->ci->savedpc;
+ cl = &clvalue(L->ci->func)->l;
base = L->base;
- cl = &clvalue(base - 1)->l;
k = cl->p->k;
/* main loop of interpreter */
for (;;) {
@@ -394,7 +399,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
traceexec(L, pc); /***/
if (L->isSuspended) { /* did hook yield? */
- L->ci->u.l.savedpc = pc - 1;
+ L->ci->savedpc = pc - 1;
return NULL;
}
base = L->base;
@@ -402,85 +407,73 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
/* warning!! several calls may realloc the stack and invalidate `ra' */
ra = RA(i);
lua_assert(base == L->ci->base && base == L->base);
- lua_assert(L->top <= L->stack + L->stacksize && L->top >= base);
- lua_assert(L->top == L->ci->top ||
- GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
- GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO);
+ lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
+ lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
switch (GET_OPCODE(i)) {
case OP_MOVE: {
setobjs2s(L, ra, RB(i));
- break;
+ continue;
}
case OP_LOADK: {
setobj2s(L, ra, KBx(i));
- break;
+ continue;
}
case OP_LOADBOOL: {
setbvalue(ra, GETARG_B(i));
if (GETARG_C(i)) pc++; /* skip next instruction (if C) */
- break;
+ continue;
}
case OP_LOADNIL: {
TValue *rb = RB(i);
do {
setnilvalue(rb--);
} while (rb >= ra);
- break;
+ continue;
}
case OP_GETUPVAL: {
int b = GETARG_B(i);
setobj2s(L, ra, cl->upvals[b]->v);
- break;
+ continue;
}
case OP_GETGLOBAL: {
TValue *rb = KBx(i);
lua_assert(ttisstring(rb) && ttistable(&cl->g));
- L->ci->u.l.savedpc = pc;
- luaV_gettable(L, &cl->g, rb, ra); /***/
- base = L->base;
- break;
+ base = luaV_gettable(L, &cl->g, rb, ra, pc); /***/
+ continue;
}
case OP_GETTABLE: {
- L->ci->u.l.savedpc = pc;
- luaV_gettable(L, RB(i), RKC(i), ra); /***/
- base = L->base;
- break;
+ base = luaV_gettable(L, RB(i), RKC(i), ra, pc); /***/
+ continue;
}
case OP_SETGLOBAL: {
lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g));
- L->ci->u.l.savedpc = pc;
- luaV_settable(L, &cl->g, KBx(i), ra); /***/
- base = L->base;
- break;
+ base = luaV_settable(L, &cl->g, KBx(i), ra, pc); /***/
+ continue;
}
case OP_SETUPVAL: {
UpVal *uv = cl->upvals[GETARG_B(i)];
setobj(L, uv->v, ra);
luaC_barrier(L, uv, ra);
- break;
+ continue;
}
case OP_SETTABLE: {
- L->ci->u.l.savedpc = pc;
- luaV_settable(L, ra, RKB(i), RKC(i)); /***/
- base = L->base;
- break;
+ base = luaV_settable(L, ra, RKB(i), RKC(i), pc); /***/
+ continue;
}
case OP_NEWTABLE: {
int b = GETARG_B(i);
b = fb2int(b);
sethvalue(L, ra, luaH_new(L, b, GETARG_C(i)));
- L->ci->u.l.savedpc = pc;
+ L->ci->savedpc = pc;
luaC_checkGC(L); /***/
base = L->base;
- break;
+ continue;
}
case OP_SELF: {
StkId rb = RB(i);
setobjs2s(L, ra+1, rb);
- L->ci->u.l.savedpc = pc;
- luaV_gettable(L, rb, RKC(i), ra); /***/
- base = L->base;
- break;
+ base = luaV_gettable(L, rb, RKC(i), ra, pc); /***/
+ continue;
}
case OP_ADD: {
TValue *rb = RKB(i);
@@ -490,7 +483,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
}
else
base = Arith(L, ra, rb, rc, TM_ADD, pc); /***/
- break;
+ continue;
}
case OP_SUB: {
TValue *rb = RKB(i);
@@ -500,7 +493,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
}
else
base = Arith(L, ra, rb, rc, TM_SUB, pc); /***/
- break;
+ continue;
}
case OP_MUL: {
TValue *rb = RKB(i);
@@ -510,7 +503,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
}
else
base = Arith(L, ra, rb, rc, TM_MUL, pc); /***/
- break;
+ continue;
}
case OP_DIV: {
TValue *rb = RKB(i);
@@ -520,11 +513,11 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
}
else
base = Arith(L, ra, rb, rc, TM_DIV, pc); /***/
- break;
+ continue;
}
case OP_POW: {
base = Arith(L, ra, RKB(i), RKC(i), TM_POW, pc); /***/
- break;
+ continue;
}
case OP_UNM: {
const TValue *rb = RB(i);
@@ -534,113 +527,131 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
}
else {
setnilvalue(&temp);
- L->ci->u.l.savedpc = pc;
+ L->ci->savedpc = pc;
if (!call_binTM(L, RB(i), &temp, ra, TM_UNM)) /***/
luaG_aritherror(L, RB(i), &temp);
base = L->base;
}
- break;
+ continue;
}
case OP_NOT: {
int res = l_isfalse(RB(i)); /* next assignment may change this value */
setbvalue(ra, res);
- break;
+ continue;
}
case OP_CONCAT: {
int b = GETARG_B(i);
int c = GETARG_C(i);
- L->ci->u.l.savedpc = pc;
+ L->ci->savedpc = pc;
luaV_concat(L, c-b+1, c); /* may change `base' (and `ra') */ /***/
luaC_checkGC(L); /***/
base = L->base;
setobjs2s(L, RA(i), base+b);
- break;
+ continue;
}
case OP_JMP: {
- dojump(pc, GETARG_sBx(i));
- break;
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
}
case OP_EQ: {
- L->ci->u.l.savedpc = pc;
+ L->ci->savedpc = pc;
if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; /***/
- else dojump(pc, GETARG_sBx(*pc) + 1);
+ else dojump(L, pc, GETARG_sBx(*pc) + 1);
base = L->base;
- break;
+ continue;
}
case OP_LT: {
- L->ci->u.l.savedpc = pc;
+ L->ci->savedpc = pc;
if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; /***/
- else dojump(pc, GETARG_sBx(*pc) + 1);
+ else dojump(L, pc, GETARG_sBx(*pc) + 1);
base = L->base;
- break;
+ continue;
}
case OP_LE: {
- L->ci->u.l.savedpc = pc;
+ L->ci->savedpc = pc;
if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; /***/
- else dojump(pc, GETARG_sBx(*pc) + 1);
+ else dojump(L, pc, GETARG_sBx(*pc) + 1);
base = L->base;
- break;
+ continue;
}
case OP_TEST: {
TValue *rb = RB(i);
if (l_isfalse(rb) == GETARG_C(i)) pc++;
else {
setobjs2s(L, ra, rb);
- dojump(pc, GETARG_sBx(*pc) + 1);
+ dojump(L, pc, GETARG_sBx(*pc) + 1);
}
- break;
+ continue;
}
- case OP_CALL:
- case OP_TAILCALL: { /***/
- StkId firstResult;
+ case OP_CALL: { /***/
+ int pcr;
int b = GETARG_B(i);
+ int nresults = GETARG_C(i) - 1;
if (b != 0) L->top = ra+b; /* else previous instruction set top */
- L->ci->u.l.savedpc = pc;
- firstResult = luaD_precall(L, ra);
- if (firstResult) {
- int nresults = GETARG_C(i) - 1;
- if (firstResult > L->top) { /* yield? */
- (L->ci - 1)->u.l.savedpc = pc;
- return NULL;
- }
+ L->ci->savedpc = pc;
+ pcr = luaD_precall(L, ra, nresults);
+ if (pcr == PCRLUA) {
+ nexeccalls++;
+ goto callentry; /* restart luaV_execute over new Lua function */
+ }
+ else if (pcr == PCRC) {
/* it was a C function (`precall' called it); adjust results */
- luaD_poscall(L, nresults, firstResult);
if (nresults >= 0) L->top = L->ci->top;
+ base = L->base;
+ continue;
}
- else { /* it is a Lua function */
- if (GET_OPCODE(i) == OP_CALL) /* regular call? */
- nexeccalls++;
- else { /* tail call: put new frame in place of previous one */
- int aux;
- base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */
- ra = RA(i);
- if (L->openupval) luaF_close(L, base);
- for (aux = 0; ra+aux < L->top; aux++) /* move frame down */
- setobjs2s(L, base+aux-1, ra+aux);
- (L->ci - 1)->top = L->top = base+aux; /* correct top */
- (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc;
- (L->ci - 1)->u.l.tailcalls++; /* one more call lost */
- L->ci--; /* remove new frame */
- L->base = L->ci->base;
- }
+ else {
+ lua_assert(pcr == PCRYIELD);
+ return NULL;
+ }
+ }
+ case OP_TAILCALL: { /***/
+ int pcr;
+ int b = GETARG_B(i);
+ if (b != 0) L->top = ra+b; /* else previous instruction set top */
+ L->ci->savedpc = pc;
+ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
+ pcr = luaD_precall(L, ra, LUA_MULTRET);
+ if (pcr == PCRLUA) {
+ /* tail call: put new frame in place of previous one */
+ CallInfo *ci = L->ci - 1; /* previous frame */
+ int aux;
+ StkId func = ci->func;
+ StkId pfunc = (ci+1)->func; /* previous function index */
+ base = ci->base = ci->func + ((ci+1)->base - pfunc);
+ L->base = base;
+ if (L->openupval) luaF_close(L, base);
+ for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */
+ setobjs2s(L, func+aux, pfunc+aux);
+ ci->top = L->top = func+aux; /* correct top */
+ lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);
+ ci->savedpc = L->ci->savedpc;
+ ci->tailcalls++; /* one more call lost */
+ L->ci--; /* remove new frame */
goto callentry;
}
- base = L->base;
- break;
+ else if (pcr == PCRC) {
+ /* it was a C function (`precall' called it) */
+ base = L->base;
+ continue;
+ }
+ else {
+ lua_assert(pcr == PCRYIELD);
+ return NULL;
+ }
}
case OP_RETURN: {
CallInfo *ci = L->ci - 1; /* previous function frame */
int b = GETARG_B(i);
if (b != 0) L->top = ra+b-1;
if (L->openupval) luaF_close(L, base);
- L->ci->u.l.savedpc = pc;
+ L->ci->savedpc = pc;
if (--nexeccalls == 0) /* was previous function running `here'? */
return ra; /* no: return */
else { /* yes: continue its execution */
- int nresults;
+ int nresults = (ci+1)->nresults;
lua_assert(isLua(ci));
- lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL);
- nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1;
+ lua_assert(GET_OPCODE(*(ci->savedpc - 1)) == OP_CALL);
luaD_poscall(L, nresults, ra);
if (nresults >= 0) L->top = L->ci->top;
goto retentry;
@@ -651,17 +662,17 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
lua_Number idx = nvalue(ra) + step; /* increment index */
lua_Number limit = nvalue(ra+1);
if (step > 0 ? idx <= limit : idx >= limit) {
- dojump(pc, GETARG_sBx(i)); /* jump back */
+ dojump(L, pc, GETARG_sBx(i)); /* jump back */
setnvalue(ra, idx); /* update internal index... */
setnvalue(ra+3, idx); /* ...and external index */
}
- break;
+ continue;
}
case OP_FORPREP: { /***/
const TValue *init = ra;
const TValue *plimit = ra+1;
const TValue *pstep = ra+2;
- L->ci->u.l.savedpc = pc;
+ L->ci->savedpc = pc;
if (!tonumber(init, ra))
luaG_runerror(L, "`for' initial value must be a number");
else if (!tonumber(plimit, ra+1))
@@ -669,8 +680,8 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
else if (!tonumber(pstep, ra+2))
luaG_runerror(L, "`for' step must be a number");
setnvalue(ra, nvalue(ra) - nvalue(pstep));
- dojump(pc, GETARG_sBx(i));
- break;
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
}
case OP_TFORLOOP: {
StkId cb = ra + 3; /* call base */
@@ -678,7 +689,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
setobjs2s(L, cb+1, ra+1);
setobjs2s(L, cb, ra);
L->top = cb+3; /* func. + 2 args (state and index) */
- L->ci->u.l.savedpc = pc;
+ L->ci->savedpc = pc;
luaD_call(L, cb, GETARG_C(i)); /***/
L->top = L->ci->top;
base = L->base;
@@ -687,26 +698,25 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
pc++; /* skip jump (break loop) */
else {
setobjs2s(L, cb-1, cb); /* save control variable */
- dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */
+ dojump(L, pc, GETARG_sBx(*pc) + 1); /* jump back */
}
- break;
+ continue;
}
case OP_TFORPREP: { /* for compatibility only */
if (ttistable(ra)) {
setobjs2s(L, ra+1, ra);
setobj2s(L, ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
}
- dojump(pc, GETARG_sBx(i));
- break;
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
}
case OP_SETLIST:
case OP_SETLISTO: {
- int bc;
- int n;
+ int bc = GETARG_Bx(i);
+ int n, last;
Table *h;
runtime_check(L, ttistable(ra));
h = hvalue(ra);
- bc = GETARG_Bx(i);
if (GET_OPCODE(i) == OP_SETLIST)
n = (bc&(LFIELDS_PER_FLUSH-1)) + 1;
else {
@@ -714,16 +724,19 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
L->top = L->ci->top;
}
bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */
+ last = bc + n + LUA_FIRSTINDEX - 1;
+ if (last > h->sizearray) /* needs more space? */
+ luaH_resize(L, h, last, h->lsizenode); /* pre-alloc it at once */
for (; n > 0; n--) {
TValue *val = ra+n;
- setobj2t(L, luaH_setnum(L, h, bc+n), val);
- luaC_barrier(L, h, val);
+ setobj2t(L, luaH_setnum(L, h, last--), val);
+ luaC_barriert(L, h, val);
}
- break;
+ continue;
}
case OP_CLOSE: {
luaF_close(L, ra);
- break;
+ continue;
}
case OP_CLOSURE: {
Proto *p;
@@ -742,10 +755,25 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
}
}
setclvalue(L, ra, ncl);
- L->ci->u.l.savedpc = pc;
+ L->ci->savedpc = pc;
luaC_checkGC(L); /***/
base = L->base;
- break;
+ continue;
+ }
+ case OP_VARARG: {
+ int b = GETARG_B(i) - 1;
+ int j;
+ CallInfo *ci = L->ci;
+ int n = ci->base - ci->func - cl->p->numparams - 1;
+ if (b == LUA_MULTRET) {
+ b = n;
+ L->top = ra + n;
+ }
+ for (j=0; j<b && j<n; j++)
+ setobjs2s(L, ra+j, ci->base - n + j);
+ for (; j<b; j++)
+ setnilvalue(ra+j);
+ continue;
}
}
}
diff --git a/src/lvm.h b/src/lvm.h
index 64bba128..e1e1f87a 100644
--- a/src/lvm.h
+++ b/src/lvm.h
@@ -1,5 +1,5 @@
/*
-** $Id: lvm.h,v 2.1 2003/12/10 12:13:36 roberto Exp $
+** $Id: lvm.h,v 2.2 2004/05/14 19:25:09 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -26,8 +26,10 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2);
const TValue *luaV_tonumber (const TValue *obj, TValue *n);
int luaV_tostring (lua_State *L, StkId obj);
-void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val);
-void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val);
+StkId luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val,
+ const Instruction *pc);
+StkId luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val,
+ const Instruction *pc);
StkId luaV_execute (lua_State *L, int nexeccalls);
void luaV_concat (lua_State *L, int total, int last);
diff --git a/src/lzio.c b/src/lzio.c
index f538ea75..20f0724c 100644
--- a/src/lzio.c
+++ b/src/lzio.c
@@ -1,5 +1,5 @@
/*
-** $Id: lzio.c,v 1.28 2003/11/18 10:44:53 roberto Exp $
+** $Id: lzio.c,v 1.29 2004/04/30 20:13:38 roberto Exp $
** a generic input stream interface
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,7 @@
#include <string.h>
#define lzio_c
+#define LUA_CORE
#include "lua.h"