diff --git a/src/core/org/luaj/vm2/LoadState.java b/src/core/org/luaj/vm2/LoadState.java
index 78d37fd1..20410631 100644
--- a/src/core/org/luaj/vm2/LoadState.java
+++ b/src/core/org/luaj/vm2/LoadState.java
@@ -373,11 +373,12 @@ public class LoadState {
* @param firstByte the first byte of the input stream
* @param stream InputStream to read, after having read the first byte already
* @param name Name to apply to the loaded chunk
+ * @param mode "b" for binary only, "t" for text only, "bt" for binary or text.
* @return {@link Prototype} that was loaded
* @throws IllegalArgumentException if the signature is bac
* @throws IOException if an IOException occurs
*/
- public static LuaFunction load( InputStream stream, String name, LuaValue env ) throws IOException {
+ public static LuaFunction load( InputStream stream, String name, String mode, LuaValue env ) throws IOException {
if ( compiler != null )
return compiler.load(stream, name, env);
else {
diff --git a/src/core/org/luaj/vm2/LuaString.java b/src/core/org/luaj/vm2/LuaString.java
index 50326eed..5e540dee 100644
--- a/src/core/org/luaj/vm2/LuaString.java
+++ b/src/core/org/luaj/vm2/LuaString.java
@@ -420,6 +420,10 @@ public class LuaString extends LuaValue {
return m_length;
}
+ public int rawlen() {
+ return m_length;
+ }
+
public int luaByte(int index) {
return m_bytes[m_offset + index] & 0x0FF;
}
diff --git a/src/core/org/luaj/vm2/LuaTable.java b/src/core/org/luaj/vm2/LuaTable.java
index 93cf9980..9e9a08c8 100644
--- a/src/core/org/luaj/vm2/LuaTable.java
+++ b/src/core/org/luaj/vm2/LuaTable.java
@@ -393,7 +393,11 @@ public class LuaTable extends LuaValue {
public LuaValue len() {
return LuaInteger.valueOf(length());
}
-
+
+ public int rawlen() {
+ return length();
+ }
+
/** Return table.maxn() as defined by lua 5.0.
*
* Provided for compatibility, not a scalable operation.
diff --git a/src/core/org/luaj/vm2/LuaValue.java b/src/core/org/luaj/vm2/LuaValue.java
index e88fb706..0f979644 100644
--- a/src/core/org/luaj/vm2/LuaValue.java
+++ b/src/core/org/luaj/vm2/LuaValue.java
@@ -2014,6 +2014,12 @@ public class LuaValue extends Varargs {
*/
public int length() { return len().toint(); }
+ /** Get raw length of table or string without metatag processing.
+ * @return the length of the table or string.
+ * @throws LuaError if {@code this} is not a table or string.
+ */
+ public int rawlen() { typerror("table or string"); return 0; }
+
/** Implementation of lua 5.0 getn() function.
* @return value of getn() as defined in lua 5.0 spec if {@code this} is a {@link LuaTable}
* @throws LuaError if {@code this} is not a {@link LuaTable}
diff --git a/src/core/org/luaj/vm2/lib/BaseLib.java b/src/core/org/luaj/vm2/lib/BaseLib.java
index 9b5ecffe..cbe9593d 100644
--- a/src/core/org/luaj/vm2/lib/BaseLib.java
+++ b/src/core/org/luaj/vm2/lib/BaseLib.java
@@ -89,30 +89,29 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
private LuaValue next;
private LuaValue inext;
+ private static final String[] LIB1_KEYS = {
+ "getmetatable", // ( object ) -> table
+ "rawlen", // (v) -> value
+ "tostring", // (e) -> value
+ "type", // (v) -> value
+ };
private static final String[] LIB2_KEYS = {
"collectgarbage", // ( opt [,arg] ) -> value
"error", // ( message [,level] ) -> ERR
- "setfenv", // (f, table) -> void
+ "rawequal", // (v1, v2) -> boolean
+ "rawget", // (table, index) -> value
};
private static final String[] LIBV_KEYS = {
"assert", // ( v [,message] ) -> v, message | ERR
"dofile", // ( filename ) -> result1, ...
- "getfenv", // ( [f] ) -> env
- "getmetatable", // ( object ) -> table
- "load", // ( func [,chunkname] ) -> chunk | nil, msg
- "loadfile", // ( [filename] ) -> chunk | nil, msg
- "loadstring", // ( string [,chunkname] ) -> chunk | nil, msg
+ "load", // ( ld [, source [, mode [, env]]] ) -> chunk | nil, msg
+ "loadfile", // ( [filename [, mode [, env]]] ) -> chunk | nil, msg
"pcall", // (f, arg1, ...) -> status, result1, ...
"xpcall", // (f, err) -> result1, ...
"print", // (...) -> void
"select", // (f, ...) -> value1, ...
- "unpack", // (list [,i [,j]]) -> result1, ...
- "type", // (v) -> value
- "rawequal", // (v1, v2) -> boolean
- "rawget", // (table, index) -> value
"rawset", // (table, index, value) -> table
"setmetatable", // (table, metatable) -> table
- "tostring", // (e) -> value
"tonumber", // (e [,base]) -> value
"pairs", // "pairs" (t) -> iter-func, t, nil
"ipairs", // "ipairs", // (t) -> iter-func, t, 0
@@ -130,6 +129,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
public LuaValue call(LuaValue arg) {
env.set( "_G", env );
env.set( "_VERSION", Lua._VERSION );
+ bind( env, BaseLib1.class, LIB1_KEYS );
bind( env, BaseLib2.class, LIB2_KEYS );
bind( env, BaseLibV.class, LIBV_KEYS );
@@ -156,12 +156,42 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
return c.getResourceAsStream(filename.startsWith("/")? filename: "/"+filename);
}
+ static final class BaseLib1 extends OneArgFunction {
+ public LuaValue call(LuaValue arg) {
+ switch ( opcode ) {
+ case 0: // "getmetatable", // ( object ) -> table
+ {
+ LuaValue mt = arg.getmetatable();
+ return mt!=null? mt.rawget(METATABLE).optvalue(mt): NIL;
+ }
+ case 1: // "rawlen", // (v) -> value
+ {
+ return valueOf(arg.rawlen());
+ }
+ case 2: // "tostring", // (e) -> value
+ {
+ LuaValue h = arg.metatag(TOSTRING);
+ if ( ! h.isnil() )
+ return h.call(arg);
+ LuaValue v = arg.tostring();
+ if ( ! v.isnil() )
+ return v;
+ return valueOf(arg.tojstring());
+ }
+ case 3: // "type", // (v) -> value
+ {
+ return valueOf(arg.typename());
+ }
+ }
+ return NIL;
+ }
+ }
+
static final class BaseLib2 extends TwoArgFunction {
public LuaValue call(LuaValue arg1, LuaValue arg2) {
switch ( opcode ) {
case 0: // "collectgarbage", // ( opt [,arg] ) -> value
String s = arg1.checkjstring();
- int result = 0;
if ( "collect".equals(s) ) {
System.gc();
return ZERO;
@@ -173,35 +203,19 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
System.gc();
return LuaValue.TRUE;
} else {
- this.argerror(1, "gc op");
+ this.argerror("gc op");
}
return NIL;
case 1: // "error", // ( message [,level] ) -> ERR
throw new LuaError( arg1.isnil()? null: arg1.tojstring(), arg2.optint(1) );
- case 2: { // "setfenv", // (f, table) -> void
- LuaTable t = arg2.checktable();
- LuaValue f = getfenvobj(arg1);
- if ( ! f.isfunction() && ! f.isclosure() )
- error("'setfenv' cannot change environment of given object");
- f.setfenv(t);
- return f.isthread()? NONE: f;
- }
+ case 2: // "rawequal", // (v1, v2) -> boolean
+ return valueOf(arg1.raweq(arg2));
+ case 3: // "rawget", // (table, index) -> value
+ return arg1.rawget(arg2);
}
return NIL;
}
}
-
- private static LuaValue getfenvobj(LuaValue arg) {
- if ( arg.isfunction() )
- return arg;
- int level = arg.optint(1);
- arg.argcheck(level>=0, 1, "level must be non-negative");
- if ( level == 0 )
- return LuaThread.getRunning();
- LuaValue f = LuaThread.getCallstackFunction(level);
- arg.argcheck(f != null, 1, "invalid level");
- return f;
- }
static final class BaseLibV extends VarArgFunction {
public BaseLib baselib;
@@ -213,41 +227,34 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
return args;
case 1: // "dofile", // ( filename ) -> result1, ...
{
- Varargs v = args.isnil(1)?
- BaseLib.loadStream( baselib.STDIN, "=stdin" ):
- BaseLib.loadFile( args.checkjstring(1) );
+ args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
+ String filename = args.isstring(1)? args.tojstring(1): null;
+ Varargs v = filename == null?
+ BaseLib.loadStream( baselib.STDIN, "=stdin", "bt", LuaThread.getGlobals() ):
+ BaseLib.loadFile( args.checkjstring(1), "bt", LuaThread.getGlobals() );
return v.isnil(1)? error(v.tojstring(2)): v.arg1().invoke();
}
- case 2: // "getfenv", // ( [f] ) -> env
+ case 2: // "load", // ( ld [, source [, mode [, env]]] ) -> chunk | nil, msg
{
- LuaValue f = getfenvobj(args.arg1());
- LuaValue e = f.getfenv();
- return e!=null? e: NIL;
+ LuaValue ld = args.arg1();
+ args.argcheck(ld.isstring() || ld.isfunction(), 1, "ld must be string or function");
+ String source = args.optjstring(2, ld.isstring()? ld.tojstring(): "=(load)");
+ String mode = args.optjstring(3, "bt");
+ LuaValue env = args.optvalue(4, LuaThread.getGlobals());
+ return BaseLib.loadStream(ld.isstring()? ld.strvalue().toInputStream():
+ new StringInputStream(ld.checkfunction()), source, mode, env);
}
- case 3: // "getmetatable", // ( object ) -> table
+ case 3: // "loadfile", // ( [filename [, mode [, env]]] ) -> chunk | nil, msg
{
- LuaValue mt = args.checkvalue(1).getmetatable();
- return mt!=null? mt.rawget(METATABLE).optvalue(mt): NIL;
+ args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
+ String filename = args.isstring(1)? args.tojstring(1): null;
+ String mode = args.optjstring(2, "bt");
+ LuaValue env = args.optvalue(3, LuaThread.getGlobals());
+ return filename == null?
+ BaseLib.loadStream( baselib.STDIN, "=stdin", mode, env ):
+ BaseLib.loadFile( filename, mode, env );
}
- case 4: // "load", // ( func [,chunkname] ) -> chunk | nil, msg
- {
- LuaValue func = args.checkfunction(1);
- String chunkname = args.optjstring(2, "function");
- return BaseLib.loadStream(new StringInputStream(func), chunkname);
- }
- case 5: // "loadfile", // ( [filename] ) -> chunk | nil, msg
- {
- return args.isnil(1)?
- BaseLib.loadStream( baselib.STDIN, "stdin" ):
- BaseLib.loadFile( args.checkjstring(1) );
- }
- case 6: // "loadstring", // ( string [,chunkname] ) -> chunk | nil, msg
- {
- LuaString script = args.checkstring(1);
- String chunkname = args.optjstring(2, "string");
- return BaseLib.loadStream(script.toInputStream(),chunkname);
- }
- case 7: // "pcall", // (f, arg1, ...) -> status, result1, ...
+ case 4: // "pcall", // (f, arg1, ...) -> status, result1, ...
{
LuaValue func = args.checkvalue(1);
LuaThread.CallStack cs = LuaThread.onCall(this);
@@ -257,7 +264,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
cs.onReturn();
}
}
- case 8: // "xpcall", // (f, err) -> result1, ...
+ case 5: // "xpcall", // (f, err) -> result1, ...
{
LuaThread.CallStack cs = LuaThread.onCall(this);
try {
@@ -266,7 +273,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
cs.onReturn();
}
}
- case 9: // "print", // (...) -> void
+ case 6: // "print", // (...) -> void
{
LuaValue tostring = LuaThread.getGlobals().get("tostring");
for ( int i=1, n=args.narg(); i<=n; i++ ) {
@@ -278,7 +285,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
baselib.STDOUT.println();
return NONE;
}
- case 10: // "select", // (f, ...) -> value1, ...
+ case 7: // "select", // (f, ...) -> value1, ...
{
int n = args.narg()-1;
if ( args.arg1().equals(valueOf("#")) )
@@ -288,34 +295,12 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
argerror(1,"index out of range");
return args.subargs(i<0? n+i+2: i+1);
}
- case 11: // "unpack", // (list [,i [,j]]) -> result1, ...
- {
- int na = args.narg();
- LuaTable t = args.checktable(1);
- int n = t.length();
- int i = na>=2? args.checkint(2): 1;
- int j = na>=3? args.checkint(3): n;
- n = j-i+1;
- if ( n<0 ) return NONE;
- if ( n==1 ) return t.get(i);
- if ( n==2 ) return varargsOf(t.get(i),t.get(j));
- LuaValue[] v = new LuaValue[n];
- for ( int k=0; k value
- return valueOf(args.checkvalue(1).typename());
- case 13: // "rawequal", // (v1, v2) -> boolean
- return valueOf(args.checkvalue(1) == args.checkvalue(2));
- case 14: // "rawget", // (table, index) -> value
- return args.checktable(1).rawget(args.checkvalue(2));
- case 15: { // "rawset", // (table, index, value) -> table
+ case 8: { // "rawset", // (table, index, value) -> table
LuaTable t = args.checktable(1);
t.rawset(args.checknotnil(2), args.checkvalue(3));
return t;
}
- case 16: { // "setmetatable", // (table, metatable) -> table
+ case 9: { // "setmetatable", // (table, metatable) -> table
final LuaValue t = args.arg1();
final LuaValue mt0 = t.getmetatable();
if ( mt0!=null && !mt0.rawget(METATABLE).isnil() )
@@ -323,17 +308,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
final LuaValue mt = args.checkvalue(2);
return t.setmetatable(mt.isnil()? null: mt.checktable());
}
- case 17: { // "tostring", // (e) -> value
- LuaValue arg = args.checkvalue(1);
- LuaValue h = arg.metatag(TOSTRING);
- if ( ! h.isnil() )
- return h.call(arg);
- LuaValue v = arg.tostring();
- if ( ! v.isnil() )
- return v;
- return valueOf(arg.tojstring());
- }
- case 18: { // "tonumber", // (e [,base]) -> value
+ case 10: { // "tonumber", // (e [,base]) -> value
LuaValue arg1 = args.checkvalue(1);
final int base = args.optint(2,10);
if (base == 10) { /* standard conversion */
@@ -344,13 +319,13 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
return arg1.checkstring().tonumber(base);
}
}
- case 19: // "pairs" (t) -> iter-func, t, nil
+ case 11: // "pairs" (t) -> iter-func, t, nil
return varargsOf( baselib.next, args.checktable(1), NIL );
- case 20: // "ipairs", // (t) -> iter-func, t, 0
+ case 12: // "ipairs", // (t) -> iter-func, t, 0
return varargsOf( baselib.inext, args.checktable(1), ZERO );
- case 21: // "next" ( table, [index] ) -> next-index, next-value
+ case 13: // "next" ( table, [index] ) -> next-index, next-value
return args.checktable(1).next(args.arg(2));
- case 22: // "inext" ( table, [int-index] ) -> next-index, next-value
+ case 14: // "inext" ( table, [int-index] ) -> next-index, next-value
return args.checktable(1).inext(args.arg(2));
}
return NONE;
@@ -376,14 +351,16 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
/**
* Load from a named file, returning the chunk or nil,error of can't load
+ * @param env
+ * @param mode
* @return Varargs containing chunk, or NIL,error-text on error
*/
- public static Varargs loadFile(String filename) {
+ public static Varargs loadFile(String filename, String mode, LuaValue env) {
InputStream is = FINDER.findResource(filename);
if ( is == null )
return varargsOf(NIL, valueOf("cannot open "+filename+": No such file or directory"));
try {
- return loadStream(is, "@"+filename);
+ return loadStream(is, "@"+filename, mode, env);
} finally {
try {
is.close();
@@ -393,11 +370,11 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
}
}
- public static Varargs loadStream(InputStream is, String chunkname) {
+ public static Varargs loadStream(InputStream is, String chunkname, String mode, LuaValue env) {
try {
if ( is == null )
return varargsOf(NIL, valueOf("not found: "+chunkname));
- return LoadState.load(is, chunkname, LuaThread.getGlobals());
+ return LoadState.load(is, chunkname, mode, env);
} catch (Exception e) {
return varargsOf(NIL, valueOf(e.getMessage()));
}
diff --git a/src/core/org/luaj/vm2/lib/DebugLib.java b/src/core/org/luaj/vm2/lib/DebugLib.java
index 55f74858..1b423e8c 100644
--- a/src/core/org/luaj/vm2/lib/DebugLib.java
+++ b/src/core/org/luaj/vm2/lib/DebugLib.java
@@ -76,14 +76,12 @@ public class DebugLib extends VarArgFunction {
static final String[] NAMES = {
"debug",
- "getfenv",
"gethook",
"getinfo",
"getlocal",
"getmetatable",
"getregistry",
"getupvalue",
- "setfenv",
"sethook",
"setlocal",
"setmetatable",
@@ -93,19 +91,17 @@ public class DebugLib extends VarArgFunction {
private static final int INIT = 0;
private static final int DEBUG = 1;
- private static final int GETFENV = 2;
- private static final int GETHOOK = 3;
- private static final int GETINFO = 4;
- private static final int GETLOCAL = 5;
- private static final int GETMETATABLE = 6;
- private static final int GETREGISTRY = 7;
- private static final int GETUPVALUE = 8;
- private static final int SETFENV = 9;
- private static final int SETHOOK = 10;
- private static final int SETLOCAL = 11;
- private static final int SETMETATABLE = 12;
- private static final int SETUPVALUE = 13;
- private static final int TRACEBACK = 14;
+ private static final int GETHOOK = 2;
+ private static final int GETINFO = 3;
+ private static final int GETLOCAL = 4;
+ private static final int GETMETATABLE = 5;
+ private static final int GETREGISTRY = 6;
+ private static final int GETUPVALUE = 7;
+ private static final int SETHOOK = 8;
+ private static final int SETLOCAL = 9;
+ private static final int SETMETATABLE = 10;
+ private static final int SETUPVALUE = 11;
+ private static final int TRACEBACK = 12;
/* maximum stack for a Lua function */
private static final int MAXSTACK = 250;
@@ -153,14 +149,12 @@ public class DebugLib extends VarArgFunction {
switch ( opcode ) {
case INIT: return init();
case DEBUG: return _debug(args);
- case GETFENV: return _getfenv(args);
case GETHOOK: return _gethook(args);
case GETINFO: return _getinfo(args,this);
case GETLOCAL: return _getlocal(args);
case GETMETATABLE: return _getmetatable(args);
case GETREGISTRY: return _getregistry(args);
case GETUPVALUE: return _getupvalue(args);
- case SETFENV: return _setfenv(args);
case SETHOOK: return _sethook(args);
case SETLOCAL: return _setlocal(args);
case SETMETATABLE: return _setmetatable(args);
@@ -438,19 +432,6 @@ public class DebugLib extends VarArgFunction {
return NONE;
}
- static Varargs _getfenv(Varargs args) {
- LuaValue object = args.arg1();
- LuaValue env = object.getfenv();
- return env!=null? env: LuaValue.NIL;
- }
-
- static Varargs _setfenv(Varargs args) {
- LuaValue object = args.arg1();
- LuaTable table = args.checktable(2);
- object.setfenv(table);
- return object;
- }
-
protected static Varargs _getinfo(Varargs args, LuaValue level0func) {
int a=1;
LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();
diff --git a/src/core/org/luaj/vm2/lib/MathLib.java b/src/core/org/luaj/vm2/lib/MathLib.java
index 7146a8bc..e55b5b40 100644
--- a/src/core/org/luaj/vm2/lib/MathLib.java
+++ b/src/core/org/luaj/vm2/lib/MathLib.java
@@ -42,7 +42,6 @@ import org.luaj.vm2.Varargs;
* atan
* cosh
* log
- * log10
* sinh
* tanh
* atan2
diff --git a/src/core/org/luaj/vm2/lib/PackageLib.java b/src/core/org/luaj/vm2/lib/PackageLib.java
index 256c2519..cdaa8b74 100644
--- a/src/core/org/luaj/vm2/lib/PackageLib.java
+++ b/src/core/org/luaj/vm2/lib/PackageLib.java
@@ -76,51 +76,47 @@ public class PackageLib extends OneArgFunction {
public static PackageLib instance;
/** Loader that loads from preload table if found there */
- public LuaValue preload_loader;
+ public LuaValue preload_searcher;
/** Loader that loads as a lua script using the LUA_PATH */
- public LuaValue lua_loader;
+ public LuaValue lua_searcher;
/** Loader that loads as a Java class. Class must have public constructor and be a LuaValue */
- public LuaValue java_loader;
+ public LuaValue java_searcher;
- private static final LuaString _M = valueOf("_M");
- private static final LuaString _NAME = valueOf("_NAME");
- private static final LuaString _PACKAGE = valueOf("_PACKAGE");
- private static final LuaString _DOT = valueOf(".");
- private static final LuaString _LOADERS = valueOf("loaders");
- private static final LuaString _LOADED = valueOf("loaded");
- private static final LuaString _LOADLIB = valueOf("loadlib");
- private static final LuaString _PRELOAD = valueOf("preload");
- private static final LuaString _PATH = valueOf("path");
- private static final LuaString _SEEALL = valueOf("seeall");
- private static final LuaString _SENTINEL = valueOf("\u0001");
-
- private static final int OP_MODULE = 0;
- private static final int OP_REQUIRE = 1;
- private static final int OP_LOADLIB = 2;
- private static final int OP_SEEALL = 3;
- private static final int OP_PRELOAD_LOADER = 4;
- private static final int OP_LUA_LOADER = 5;
- private static final int OP_JAVA_LOADER = 6;
+ private static final LuaString _LOADED = valueOf("loaded");
+ private static final LuaString _LOADLIB = valueOf("loadlib");
+ private static final LuaString _PRELOAD = valueOf("preload");
+ private static final LuaString _PATH = valueOf("path");
+ private static final LuaString _SEARCHERS = valueOf("searchers");
+ private static final LuaString _SEARCHPATH = valueOf("searchpath");
+ private static final LuaString _SENTINEL = valueOf("\u0001");
+ private static final int OP_REQUIRE = 0;
+ private static final int OP_LOADLIB = 1;
+ private static final int OP_SEARCHPATH = 2;
+ private static final int OP_PRELOAD_SEARCHER = 3;
+ private static final int OP_LUA_SEARCHER = 4;
+ private static final int OP_JAVA_SEARCHER = 5;
+
+ private static final String FILE_SEP = System.getProperty("file.separator");
+
public PackageLib() {
instance = this;
}
public LuaValue call(LuaValue arg) {
env.set("require", new PkgLib1(env,"require",OP_REQUIRE,this));
- env.set("module", new PkgLibV(env,"module",OP_MODULE,this));
env.set( "package", PACKAGE=tableOf( new LuaValue[] {
_LOADED, LOADED=tableOf(),
_PRELOAD, tableOf(),
_PATH, valueOf(DEFAULT_LUA_PATH),
_LOADLIB, new PkgLibV(env,"loadlib",OP_LOADLIB,this),
- _SEEALL, new PkgLib1(env,"seeall",OP_SEEALL,this),
- _LOADERS, listOf(new LuaValue[] {
- preload_loader = new PkgLibV(env,"preload_loader", OP_PRELOAD_LOADER,this),
- lua_loader = new PkgLibV(env,"lua_loader", OP_LUA_LOADER,this),
- java_loader = new PkgLibV(env,"java_loader", OP_JAVA_LOADER,this),
+ _SEARCHPATH, new PkgLibV(env,"searchpath",OP_SEARCHPATH,this),
+ _SEARCHERS, listOf(new LuaValue[] {
+ preload_searcher = new PkgLibV(env,"preload_searcher", OP_PRELOAD_SEARCHER,this),
+ lua_searcher = new PkgLibV(env,"lua_searcher", OP_LUA_SEARCHER,this),
+ java_searcher = new PkgLibV(env,"java_searcher", OP_JAVA_SEARCHER,this),
}) }) );
LOADED.set("package", PACKAGE);
return env;
@@ -138,14 +134,6 @@ public class PackageLib extends OneArgFunction {
switch ( opcode ) {
case OP_REQUIRE:
return lib.require(arg);
- case OP_SEEALL: {
- LuaTable t = arg.checktable();
- LuaValue m = t.getmetatable();
- if ( m == null )
- t.setmetatable(m=tableOf());
- m.set( INDEX, LuaThread.getGlobals() );
- return NONE;
- }
}
return NIL;
}
@@ -161,18 +149,24 @@ public class PackageLib extends OneArgFunction {
}
public Varargs invoke(Varargs args) {
switch ( opcode ) {
- case OP_MODULE:
- return lib.module(args);
- case OP_LOADLIB:
+ case OP_LOADLIB: {
return loadlib(args);
- case OP_PRELOAD_LOADER: {
- return lib.loader_preload(args);
}
- case OP_LUA_LOADER: {
- return lib.loader_Lua(args);
+ case OP_PRELOAD_SEARCHER: {
+ return lib.searcher_preload(args);
}
- case OP_JAVA_LOADER: {
- return lib.loader_Java(args);
+ case OP_LUA_SEARCHER: {
+ return lib.searcher_Lua(args);
+ }
+ case OP_JAVA_SEARCHER: {
+ return lib.searcher_Java(args);
+ }
+ case OP_SEARCHPATH: {
+ String name = args.checkjstring(1);
+ String path = args.checkjstring(2);
+ String sep = args.optjstring(3, ".");
+ String rep = args.optjstring(4, FILE_SEP);
+ return lib.searchpath(name, path, sep, rep);
}
}
return NONE;
@@ -184,6 +178,7 @@ public class PackageLib extends OneArgFunction {
LOADED.set(name, value);
}
+
public void setLuaPath( String newLuaPath ) {
PACKAGE.set( _PATH, valueOf(newLuaPath) );
}
@@ -193,102 +188,7 @@ public class PackageLib extends OneArgFunction {
}
- // ======================== Module, Package loading =============================
- /**
- * module (name [, ...])
- *
- * Creates a module. If there is a table in package.loaded[name], this table
- * is the module. Otherwise, if there is a global table t with the given
- * name, this table is the module. Otherwise creates a new table t and sets
- * it as the value of the global name and the value of package.loaded[name].
- * This function also initializes t._NAME with the given name, t._M with the
- * module (t itself), and t._PACKAGE with the package name (the full module
- * name minus last component; see below). Finally, module sets t as the new
- * environment of the current function and the new value of
- * package.loaded[name], so that require returns t.
- *
- * If name is a compound name (that is, one with components separated by
- * dots), module creates (or reuses, if they already exist) tables for each
- * component. For instance, if name is a.b.c, then module stores the module
- * table in field c of field b of global a.
- *
- * This function may receive optional options after the module name, where
- * each option is a function to be applied over the module.
- */
- public Varargs module(Varargs args) {
- LuaString modname = args.checkstring(1);
- int n = args.narg();
- LuaValue value = LOADED.get(modname);
- LuaValue module;
- if ( ! value.istable() ) { /* not found? */
-
- /* try global variable (and create one if it does not exist) */
- LuaValue globals = LuaThread.getGlobals();
- module = findtable( globals, modname );
- if ( module == null )
- error( "name conflict for module '"+modname+"'" );
- LOADED.set(modname, module);
- } else {
- module = (LuaTable) value;
- }
-
-
- /* check whether table already has a _NAME field */
- LuaValue name = module.get(_NAME);
- if ( name.isnil() ) {
- modinit( module, modname );
- }
-
- // set the environment of the current function
- LuaFunction f = LuaThread.getCallstackFunction(1);
- if ( f == null )
- error("no calling function");
- if ( ! f.isclosure() )
- error("'module' not called from a Lua function");
- f.setfenv(module);
-
- // apply the functions
- for ( int i=2; i<=n; i++ )
- args.arg(i).call( module );
-
- // returns no results
- return NONE;
- }
-
- /**
- *
- * @param table the table at which to start the search
- * @param fname the name to look up or create, such as "abc.def.ghi"
- * @return the table for that name, possible a new one, or null if a non-table has that name already.
- */
- private static final LuaValue findtable(LuaValue table, LuaString fname) {
- int b, e=(-1);
- do {
- e = fname.indexOf(_DOT, b=e+1 );
- if ( e < 0 )
- e = fname.m_length;
- LuaString key = fname.substring(b, e);
- LuaValue val = table.rawget(key);
- if ( val.isnil() ) { /* no such field? */
- LuaTable field = new LuaTable(); /* new table for field */
- table.set(key, field);
- table = field;
- } else if ( ! val.istable() ) { /* field has a non-table value? */
- return null;
- } else {
- table = val;
- }
- } while ( e < fname.m_length );
- return table;
- }
-
- private static final void modinit(LuaValue module, LuaString modname) {
- /* module._M = module */
- module.set(_M, module);
- int e = modname.lastIndexOf(_DOT);
- module.set(_NAME, modname );
- module.set(_PACKAGE, (e<0? EMPTYSTRING: modname.substring(0,e+1)) );
- }
+ // ======================== Package loading =============================
/**
* require (modname)
@@ -326,7 +226,7 @@ public class PackageLib extends OneArgFunction {
}
/* else must load it; iterate over available loaders */
- LuaTable tbl = PACKAGE.get(_LOADERS).checktable();
+ LuaTable tbl = PACKAGE.get(_SEARCHERS).checktable();
StringBuffer sb = new StringBuffer();
LuaValue chunk = null;
for ( int i=1; true; i++ ) {
@@ -358,7 +258,7 @@ public class PackageLib extends OneArgFunction {
return varargsOf(NIL, valueOf("dynamic libraries not enabled"), valueOf("absent"));
}
- LuaValue loader_preload( Varargs args ) {
+ LuaValue searcher_preload( Varargs args ) {
LuaString name = args.checkstring(1);
LuaValue preload = PACKAGE.get(_PRELOAD).checktable();
LuaValue val = preload.get(name);
@@ -367,22 +267,40 @@ public class PackageLib extends OneArgFunction {
val;
}
- LuaValue loader_Lua( Varargs args ) {
- String name = args.checkjstring(1);
+ Varargs searcher_Lua( Varargs args ) {
+ LuaString name = args.checkstring(1);
InputStream is = null;
-
-
+
// get package path
- LuaValue pp = PACKAGE.get(_PATH);
- if ( ! pp.isstring() )
+ LuaValue path = PACKAGE.get(_PATH);
+ if ( ! path.isstring() )
return valueOf("package.path is not a string");
- String path = pp.tojstring();
+
+ // get the searchpath function.
+ LuaValue searchpath = PACKAGE.get(_SEARCHPATH);
+ Varargs v = searchpath.invoke(varargsOf(name, path));
+
+ // Didd we get a result?
+ if (!v.isstring(1))
+ return v.arg(2).tostring();
+ LuaString filename = v.arg1().strvalue();
+
+ // Try to load the file.
+ v = BaseLib.loadFile(filename.tojstring(), "bt", LuaThread.getGlobals());
+ if ( v.arg1().isfunction() )
+ return LuaValue.varargsOf(v.arg1(), filename);
+
+ // report error
+ return varargsOf(NIL, valueOf("'"+filename+"': "+v.arg(2).tojstring()));
+ }
+
+ public Varargs searchpath(String name, String path, String sep, String rep) {
// check the path elements
int e = -1;
int n = path.length();
StringBuffer sb = null;
- name = name.replace('.','/');
+ name = name.replace(sep.charAt(0), rep.charAt(0));
while ( e < n ) {
// find next template
@@ -399,20 +317,22 @@ public class PackageLib extends OneArgFunction {
filename = template.substring(0,q) + name + template.substring(q+1);
}
- // try loading the file
- Varargs v = BaseLib.loadFile(filename);
- if ( v.arg1().isfunction() )
- return v.arg1();
+ // try opening the file
+ InputStream is = BaseLib.FINDER.findResource(filename);
+ if (is != null) {
+ try { is.close(); } catch ( java.io.IOException ioe ) {}
+ return valueOf(filename);
+ }
// report error
if ( sb == null )
sb = new StringBuffer();
- sb.append( "\n\t'"+filename+"': "+v.arg(2) );
+ sb.append( "\n\t"+filename );
}
- return valueOf(sb.toString());
+ return varargsOf(NIL, valueOf(sb.toString()));
}
- LuaValue loader_Java( Varargs args ) {
+ LuaValue searcher_Java( Varargs args ) {
String name = args.checkjstring(1);
String classname = toClassname( name );
Class c = null;
diff --git a/src/core/org/luaj/vm2/lib/TableLib.java b/src/core/org/luaj/vm2/lib/TableLib.java
index c26b9d40..e5c92f75 100644
--- a/src/core/org/luaj/vm2/lib/TableLib.java
+++ b/src/core/org/luaj/vm2/lib/TableLib.java
@@ -65,7 +65,7 @@ public class TableLib extends OneArgFunction {
LuaTable t = new LuaTable();
bind(t, TableLib.class, new String[] { "getn", "maxn", }, 1 );
bind(t, TableLibV.class, new String[] {
- "remove", "concat", "insert", "sort", "foreach", "foreachi", } );
+ "remove", "concat", "insert", "sort", "foreach", "foreachi", "unpack", } );
env.set("table", t);
PackageLib.instance.LOADED.set("table", t);
return t;
@@ -117,6 +117,22 @@ public class TableLib extends OneArgFunction {
case 5: { // "foreachi" (table, func) -> void
return args.checktable(1).foreachi( args.checkfunction(2) );
}
+ case 6: // "unpack", // (list [,i [,j]]) -> result1, ...
+ {
+ int na = args.narg();
+ LuaTable t = args.checktable(1);
+ int n = t.length();
+ int i = na>=2? args.checkint(2): 1;
+ int j = na>=3? args.checkint(3): n;
+ n = j-i+1;
+ if ( n<0 ) return NONE;
+ if ( n==1 ) return t.get(i);
+ if ( n==2 ) return varargsOf(t.get(i),t.get(j));
+ LuaValue[] v = new LuaValue[n];
+ for ( int k=0; k 2 )
usageExit();
@@ -190,7 +198,14 @@ public class lua {
try {
LuaFunction c;
try {
- c = LoadState.load(script, chunkname, _G);
+ c = LoadState.load(script, chunkname, "bt", _G);
+ if (c instanceof LuaClosure) {
+ LuaClosure closure = (LuaClosure) c;
+ Print.print(closure.p);
+ // DebugLib.DEBUG_ENABLED = true;
+ } else {
+ System.out.println( "Not a LuaClosure: "+c);
+ }
} finally {
script.close();
}
diff --git a/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java b/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java
index 1f8d2e69..3b028a2a 100644
--- a/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java
+++ b/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java
@@ -64,7 +64,7 @@ public class JseMathLib extends org.luaj.vm2.lib.MathLib {
LuaValue t = super.call(arg);
bind( t, JseMathLib1.class, new String[] {
"acos", "asin", "atan", "cosh",
- "exp", "log", "log10", "sinh",
+ "exp", "log", "sinh",
"tanh" } );
bind( t, JseMathLib2.class, new String[] {
"atan2", "pow", } );
@@ -80,9 +80,8 @@ public class JseMathLib extends org.luaj.vm2.lib.MathLib {
case 3: return valueOf(Math.cosh(arg.checkdouble()));
case 4: return valueOf(Math.exp(arg.checkdouble()));
case 5: return valueOf(Math.log(arg.checkdouble()));
- case 6: return valueOf(Math.log10(arg.checkdouble()));
- case 7: return valueOf(Math.sinh(arg.checkdouble()));
- case 8: return valueOf(Math.tanh(arg.checkdouble()));
+ case 6: return valueOf(Math.sinh(arg.checkdouble()));
+ case 7: return valueOf(Math.tanh(arg.checkdouble()));
}
return NIL;
}
diff --git a/src/jse/org/luaj/vm2/script/LuaScriptEngine.java b/src/jse/org/luaj/vm2/script/LuaScriptEngine.java
index 468a095d..4b69305a 100644
--- a/src/jse/org/luaj/vm2/script/LuaScriptEngine.java
+++ b/src/jse/org/luaj/vm2/script/LuaScriptEngine.java
@@ -162,7 +162,7 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
try {
InputStream ris = new Utf8Encoder(reader);
try {
- final LuaFunction f = LoadState.load(ris, "script", null);
+ final LuaFunction f = LoadState.load(ris, "script", "bt", null);
if ( f.isclosure() ) {
// most compiled functions are closures with prototypes
final Prototype p = f.checkclosure().p;
diff --git a/test/junit/org/luaj/vm2/FragmentsTest.java b/test/junit/org/luaj/vm2/FragmentsTest.java
index 25132deb..3b7c9d6e 100644
--- a/test/junit/org/luaj/vm2/FragmentsTest.java
+++ b/test/junit/org/luaj/vm2/FragmentsTest.java
@@ -123,7 +123,6 @@ public class FragmentsTest extends TestSuite {
}
public void testArgParamUseNone() {
- // the name "arg" is treated specially, and ends up masking the argument value in 5.1
runFragment( LuaValue.valueOf("string"),
"function v(arg,...)\n" +
" return type(arg)\n" +
diff --git a/test/junit/org/luaj/vm2/MathLibTest.java b/test/junit/org/luaj/vm2/MathLibTest.java
index 47e34238..d9bba861 100644
--- a/test/junit/org/luaj/vm2/MathLibTest.java
+++ b/test/junit/org/luaj/vm2/MathLibTest.java
@@ -93,22 +93,6 @@ public class MathLibTest extends TestCase {
tryMathOp( "log", -9 );
}
- public void testLog10() {
- supportedOnJ2me = false;
- tryMathOp( "log10", 0.1 );
- tryMathOp( "log10", .9 );
- tryMathOp( "log10", 1. );
- tryMathOp( "log10", 9 );
- tryMathOp( "log10", 10 );
- tryMathOp( "log10", 100 );
- tryMathOp( "log10", -.1 );
- tryMathOp( "log10", -.9 );
- tryMathOp( "log10", -1. );
- tryMathOp( "log10", -9 );
- tryMathOp( "log10", -10 );
- tryMathOp( "log10", -100 );
- }
-
public void testRad() {
tryMathOp( "rad", 0 );
tryMathOp( "rad", 0.1 );
diff --git a/test/junit/org/luaj/vm2/OrphanedThreadTest.java b/test/junit/org/luaj/vm2/OrphanedThreadTest.java
index 2c801abb..ed8e67ab 100644
--- a/test/junit/org/luaj/vm2/OrphanedThreadTest.java
+++ b/test/junit/org/luaj/vm2/OrphanedThreadTest.java
@@ -75,7 +75,7 @@ public class OrphanedThreadTest extends TestCase {
"print('leakage in closure.3, arg is '..arg)\n" +
"return 'done'\n";
LuaC.install();
- function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", env);
+ function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", "bt", env);
doTest(LuaValue.TRUE, LuaValue.ZERO);
}
@@ -91,7 +91,7 @@ public class OrphanedThreadTest extends TestCase {
"end\n" +
"print( 'pcall-closre.result:', pcall( f, ... ) )\n";
LuaC.install();
- function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", env);
+ function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", "bt", env);
doTest(LuaValue.TRUE, LuaValue.ZERO);
}
@@ -108,7 +108,7 @@ public class OrphanedThreadTest extends TestCase {
"end\n" +
"load(f)()\n";
LuaC.install();
- function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", env);
+ function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", "bt", env);
doTest(LuaValue.TRUE, LuaValue.ONE);
}
diff --git a/test/junit/org/luaj/vm2/ScriptDrivenTest.java b/test/junit/org/luaj/vm2/ScriptDrivenTest.java
index ed6de2e2..a2964af5 100644
--- a/test/junit/org/luaj/vm2/ScriptDrivenTest.java
+++ b/test/junit/org/luaj/vm2/ScriptDrivenTest.java
@@ -125,7 +125,7 @@ public class ScriptDrivenTest extends TestCase {
}
default:
script = new FileInputStream(file);
- return LoadState.load(script, "=stdin", _G);
+ return LoadState.load(script, "=stdin", "bt", _G);
}
} catch ( Exception e ) {
e.printStackTrace();
diff --git a/test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java b/test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java
index 119d0ea5..7b5d9e0a 100644
--- a/test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java
+++ b/test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java
@@ -108,7 +108,7 @@ public class DumpLoadEndianIntTest extends TestCase {
// load again using compiler
is = new ByteArrayInputStream(dumped);
- f = LoadState.load(is, "dumped", _G);
+ f = LoadState.load(is, "dumped", "bt", _G);
r = f.call();
actual = r.tojstring();
assertEquals( expectedPostDump, actual );
diff --git a/test/lua/baselib.lua b/test/lua/baselib.lua
index dae00527..fb84ce94 100644
--- a/test/lua/baselib.lua
+++ b/test/lua/baselib.lua
@@ -152,6 +152,17 @@ printtables()
print( 'pcall(rawset,t,"dd","zzz")', rawset(t,"dd","zzz"))
printtables()
+-- rawlen
+print( 'pcall(rawlen, {})', pcall(rawlen, {}))
+print( 'pcall(rawlen, {"a"})', pcall(rawlen, {'a'}))
+print( 'pcall(rawlen, {"a","b"})', pcall(rawlen, {'a','b'}))
+print( 'pcall(rawlen, "")', pcall(rawlen, ""))
+print( 'pcall(rawlen, "a")', pcall(rawlen, 'a'))
+print( 'pcall(rawlen, "ab")', pcall(rawlen, 'ab'))
+print( 'pcall(rawlen, 1)', pcall(rawlen, 1))
+print( 'pcall(rawlen, nil)', pcall(rawlen, nil))
+print( 'pcall(rawlen)', pcall(rawlen))
+
printtables()
print( 's["ee"]="ppp"' ); s["ee"]="ppp"
printtables()