diff --git a/src/core/org/luaj/compiler/DumpState.java b/src/core/org/luaj/compiler/DumpState.java index 7337f8c8..d85fdfc5 100644 --- a/src/core/org/luaj/compiler/DumpState.java +++ b/src/core/org/luaj/compiler/DumpState.java @@ -51,6 +51,9 @@ public class DumpState { /** expected lua header bytes */ private static final byte[] LUAC_HEADER_SIGNATURE = { '\033', 'L', 'u', 'a' }; + /** set true to allow integer compilation */ + public static boolean ALLOW_INTEGER_CASTING = false; + // header fields private boolean IS_LITTLE_ENDIAN = false; private boolean IS_NUMBER_INTEGRAL = false; @@ -98,12 +101,17 @@ public class DumpState { void dumpNumber(double d) throws IOException { if ( IS_NUMBER_INTEGRAL ) { int i = (int) d; - if ( i != d ) + if ( (! ALLOW_INTEGER_CASTING) && (i != d) ) throw new java.lang.IllegalArgumentException("not an integer: "+d); dumpInt( i ); } else { long l = Double.doubleToLongBits(d); - writer.writeLong(l); + if ( IS_LITTLE_ENDIAN ) { + dumpInt( (int) l ); + dumpInt( (int) (l>>32) ); + } else { + writer.writeLong(l); + } } } diff --git a/src/test/java/org/luaj/AllTests.java b/src/test/java/org/luaj/AllTests.java index cab59fb5..408e51cc 100644 --- a/src/test/java/org/luaj/AllTests.java +++ b/src/test/java/org/luaj/AllTests.java @@ -25,6 +25,7 @@ public class AllTests { compiler.addTestSuite(org.luaj.compiler.SimpleTests.class); compiler.addTestSuite(org.luaj.compiler.RegressionTests.class); compiler.addTestSuite(org.luaj.compiler.CompilerUnitTests.class); + compiler.addTestSuite(org.luaj.compiler.DumpLoadEndianIntTest.class); suite.addTest(compiler); return suite; diff --git a/src/test/java/org/luaj/compiler/DumpLoadEndianIntTest.java b/src/test/java/org/luaj/compiler/DumpLoadEndianIntTest.java new file mode 100644 index 00000000..b4400a82 --- /dev/null +++ b/src/test/java/org/luaj/compiler/DumpLoadEndianIntTest.java @@ -0,0 +1,79 @@ +package org.luaj.compiler; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import junit.framework.TestCase; + +import org.luaj.platform.J2sePlatform; +import org.luaj.vm.LFunction; +import org.luaj.vm.LPrototype; +import org.luaj.vm.LuaState; +import org.luaj.vm.Platform; + +public class DumpLoadEndianIntTest extends TestCase { + + private static final String script = "return tostring(1234)..'-#!-'..tostring(23.75)"; + private static final String withdoubles = "1234-#!-23.75"; + private static final String withints = "1234-#!-23"; + + protected void setUp() throws Exception { + super.setUp(); + Platform.setInstance(new J2sePlatform()); + DumpState.ALLOW_INTEGER_CASTING = true; + } + + public void testBidDoubleCompile() { + doTest( false, false, false, withdoubles ); + doTest( false, false, true, withdoubles ); + } + + public void testLittleDoubleCompile() { + doTest( true, false, false, withdoubles ); + doTest( true, false, true, withdoubles ); + } + + public void testBigIntCompile() { + doTest( false, true, false, withints ); + doTest( false, true, true, withints ); + } + + public void testLittleIntCompile() { + doTest( true, true, false, withints ); + doTest( true, true, true, withints ); + } + + public void doTest( boolean littleEndian, boolean intNumbers, boolean stripDebug, String expected ) { + try { + LuaState vm = Platform.newLuaState(); + + // compile into prototype + InputStream is = new ByteArrayInputStream(script.getBytes()); + LPrototype p = LuaC.compile(is, "script"); + + // double check script result before dumping + LFunction f = p.newClosure(vm._G); + vm.pushfunction(f); + vm.call(0,1); + String actual = vm.poplvalue().toJavaString(); + assertEquals( withdoubles, actual ); + + // dump into bytes + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DumpState.dump(p, baos, false, intNumbers, littleEndian); + byte[] dumped = baos.toByteArray(); + + // load again using compiler + is = new ByteArrayInputStream(dumped); + vm.load(is, "dumped"); + vm.call(0,1); + actual = vm.poplvalue().toJavaString(); + assertEquals( expected, actual ); + + } catch (IOException e) { + fail(e.toString()); + } + } +}