From 9f6d7543cd9c80216257c746351a3d4c9128ae28 Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Sat, 22 Sep 2007 16:57:25 +0000 Subject: [PATCH] Remove compiler dependence on mark()/reset() --- .../java/lua/addon/compile/Compiler.java | 38 ++++++++++++++++--- .../java/lua/addon/compile/LexState.java | 4 +- .../java/lua/addon/luacompat/LuaCompat.java | 2 +- src/main/java/lua/io/LoadState.java | 14 +++---- .../lua/addon/compile/AbstractUnitTests.java | 3 +- .../java/lua/addon/compile/SimpleTests.java | 29 +++++++------- 6 files changed, 57 insertions(+), 33 deletions(-) diff --git a/src/addon/java/lua/addon/compile/Compiler.java b/src/addon/java/lua/addon/compile/Compiler.java index 644341b0..6287f46e 100644 --- a/src/addon/java/lua/addon/compile/Compiler.java +++ b/src/addon/java/lua/addon/compile/Compiler.java @@ -1,5 +1,8 @@ package lua.addon.compile; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.io.Reader; import java.util.Hashtable; @@ -8,19 +11,41 @@ import lua.value.LString; public class Compiler { - public int nCcalls; - - public static Proto compile( Reader reader, String name ) { + private static final byte LUAC_BINARY_SIG = '\033'; + + /** Try to compile into prototype. + * If the supplied stream is a binary file (i.e. lua chunk) + * then consume one byte from the input stream, and return null. + * + * Otherwise, try to compile the file, and return the Prototype + * on success, or throw RuntimeException on syntax error or I/O Exception + * + * @param stream InputStream to read from. + * @param name Name of the chunk + * @return null if the first byte indicates it is a binary chunk, + * a Proto instance if it can be compiled, + * or an exception is thrown if there is an error. + * @throws IOException if an I/O exception occurs + * @throws RuntimeException if there is a syntax error. + */ + public static Proto compile(InputStream stream, String name) throws IOException { + + int c = stream.read(); + if ( c == LUAC_BINARY_SIG ) + return null; + // TODO: handle UTF-8 here! + InputStreamReader isr = new InputStreamReader(stream); Compiler compiler = new Compiler(); - return compiler.luaY_parser(reader, name); + return compiler.luaY_parser(c, isr, name); } + public int nCcalls; - Proto luaY_parser(Reader z, String name) { + Proto luaY_parser(int firstByte, Reader z, String name) { LexState lexstate = new LexState(this, z); FuncState funcstate = new FuncState(); // lexstate.buff = buff; - lexstate.setinput( this, z, new LString(name) ); + lexstate.setinput( this, firstByte, z, new LString(name) ); lexstate.open_func(funcstate); /* main func. is always vararg */ funcstate.varargflags = LuaC.VARARG_ISVARARG; @@ -63,4 +88,5 @@ public class Compiler { public LString newlstr(char[] chars, int offset, int len) { return newTString( new String(chars,offset,len) ); } + } diff --git a/src/addon/java/lua/addon/compile/LexState.java b/src/addon/java/lua/addon/compile/LexState.java index 7e339a2a..e4a41453 100644 --- a/src/addon/java/lua/addon/compile/LexState.java +++ b/src/addon/java/lua/addon/compile/LexState.java @@ -252,7 +252,7 @@ public class LexState extends LuaC { syntaxerror("chunk has too many lines"); } - void setinput( Compiler L, Reader z, LString source ) { + void setinput( Compiler L, int firstByte, Reader z, LString source ) { this.decpoint = '.'; this.L = L; this.lookahead.token = TK_EOS; /* no look-ahead token */ @@ -262,7 +262,7 @@ public class LexState extends LuaC { this.lastline = 1; this.source = source; this.nbuff = 0; /* initialize buffer */ - this.nextChar(); /* read first char */ + this.current = firstByte; /* read first char */ this.skipShebang(); } diff --git a/src/addon/java/lua/addon/luacompat/LuaCompat.java b/src/addon/java/lua/addon/luacompat/LuaCompat.java index 5fd19702..1b38b311 100644 --- a/src/addon/java/lua/addon/luacompat/LuaCompat.java +++ b/src/addon/java/lua/addon/luacompat/LuaCompat.java @@ -468,7 +468,7 @@ public class LuaCompat extends LFunction { // return true if loaded, false if error put onto stack - private static boolean loadfile( VM vm, String fileName ) { + public static boolean loadfile( VM vm, String fileName ) { InputStream is; String script; diff --git a/src/main/java/lua/io/LoadState.java b/src/main/java/lua/io/LoadState.java index 9a79f0c4..a19dacea 100644 --- a/src/main/java/lua/io/LoadState.java +++ b/src/main/java/lua/io/LoadState.java @@ -239,16 +239,12 @@ public class LoadState { public static Proto undump( VM L, InputStream stream, String name ) throws IOException { // is this a source file? - stream.mark(1); - if ( stream.read() != LUAC_HEADER_SIGNATURE[0] ) { - stream.reset(); - // TODO: handle UTF-8 here! - return lua.addon.compile.Compiler.compile( - new InputStreamReader(stream), - name ); - } + Proto p = lua.addon.compile.Compiler.compile(stream, name); + if ( p != null ) + return p; - // check signature + // check rest of signature + // (one byte was consumed by compiler check) for ( int i=1; i<4; i++ ) { if ( stream.read() != LUAC_HEADER_SIGNATURE[i] ) throw new IllegalArgumentException("bad signature"); diff --git a/src/test/java/lua/addon/compile/AbstractUnitTests.java b/src/test/java/lua/addon/compile/AbstractUnitTests.java index 1cced23a..189c80e9 100644 --- a/src/test/java/lua/addon/compile/AbstractUnitTests.java +++ b/src/test/java/lua/addon/compile/AbstractUnitTests.java @@ -37,8 +37,7 @@ public class AbstractUnitTests extends TestCase { // compile in memory InputStream is = new ByteArrayInputStream( lua ); - Reader r = new InputStreamReader( is ); - Proto p = Compiler.compile(r, dir+"/"+file); + Proto p = Compiler.compile(is, dir+"/"+file); String actual = protoToString( p ); // load expected value from jar diff --git a/src/test/java/lua/addon/compile/SimpleTests.java b/src/test/java/lua/addon/compile/SimpleTests.java index bb7195ba..4e3825f9 100644 --- a/src/test/java/lua/addon/compile/SimpleTests.java +++ b/src/test/java/lua/addon/compile/SimpleTests.java @@ -1,12 +1,12 @@ package lua.addon.compile; -import java.io.Reader; -import java.io.StringReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; import junit.framework.TestCase; import lua.Print; import lua.StackState; -import lua.addon.compile.Compiler; import lua.io.Closure; import lua.io.Proto; import lua.value.LValue; @@ -14,16 +14,19 @@ import lua.value.LValue; public class SimpleTests extends TestCase { private void doTest( String script ) { - Reader r = new StringReader( script ); - Proto p = Compiler.compile( r, "script" ); - assertNotNull( p ); - Print.printCode( p ); - - // try running the code! - StackState state = new StackState(); - Closure c = new Closure( state, p ); - state.doCall( c, new LValue[0] ); - + try { + InputStream is = new ByteArrayInputStream( script.getBytes("UTF8") ); + Proto p = Compiler.compile( is, "script" ); + assertNotNull( p ); + Print.printCode( p ); + + // try running the code! + StackState state = new StackState(); + Closure c = new Closure( state, p ); + state.doCall( c, new LValue[0] ); + } catch ( Exception e ) { + fail("i/o exception: "+e ); + } } public void testTrivial() {