Improve compatibility with lua 5.2.

This commit is contained in:
James Roseborough
2012-09-30 15:42:36 +00:00
parent a529cbaf5c
commit 8b50a3b36b
5 changed files with 209 additions and 140 deletions

View File

@@ -23,9 +23,19 @@ package org.luaj.vm2.lib;
import java.io.IOException;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.PackageLib.java_searcher;
import org.luaj.vm2.lib.PackageLib.loadlib;
import org.luaj.vm2.lib.PackageLib.lua_searcher;
import org.luaj.vm2.lib.PackageLib.preload_searcher;
import org.luaj.vm2.lib.PackageLib.require;
import org.luaj.vm2.lib.PackageLib.searchpath;
import org.luaj.vm2.lib.jme.JmePlatform;
import org.luaj.vm2.lib.jse.JseOsLib;
import org.luaj.vm2.lib.jse.JsePlatform;
/**
* Subclass of {@link LibFunction} which implements the standard lua {@code os} library.
@@ -72,22 +82,21 @@ import org.luaj.vm2.Varargs;
* @see JmePlatform
* @see <a href="http://www.lua.org/manual/5.1/manual.html#5.8">http://www.lua.org/manual/5.1/manual.html#5.8</a>
*/
public class OsLib extends VarArgFunction {
public class OsLib extends OneArgFunction {
public static String TMP_PREFIX = ".luaj";
public static String TMP_SUFFIX = "tmp";
private static final int INIT = 0;
private static final int CLOCK = 1;
private static final int DATE = 2;
private static final int DIFFTIME = 3;
private static final int EXECUTE = 4;
private static final int EXIT = 5;
private static final int GETENV = 6;
private static final int REMOVE = 7;
private static final int RENAME = 8;
private static final int SETLOCALE = 9;
private static final int TIME = 10;
private static final int TMPNAME = 11;
private static final int CLOCK = 0;
private static final int DATE = 1;
private static final int DIFFTIME = 2;
private static final int EXECUTE = 3;
private static final int EXIT = 4;
private static final int GETENV = 5;
private static final int REMOVE = 6;
private static final int RENAME = 7;
private static final int SETLOCALE = 8;
private static final int TIME = 9;
private static final int TMPNAME = 10;
private static final String[] NAMES = {
"clock",
@@ -106,61 +115,69 @@ public class OsLib extends VarArgFunction {
private static final long t0 = System.currentTimeMillis();
private static long tmpnames = t0;
protected Globals globals;
/**
* Create and OsLib instance.
*/
public OsLib() {
}
public LuaValue init(LuaValue env) {
LuaTable t = new LuaTable();
bind(t, this.getClass(), NAMES, CLOCK);
env.set("os", t);
env.get("package").get("loaded").set("os", t);
return t;
public LuaValue call(LuaValue env) {
globals = env.checkglobals();
LuaTable os = new LuaTable();
for (int i = 0; i < NAMES.length; ++i)
os.set(NAMES[i], new OsLibFunc(i, NAMES[i]));
env.set("os", os);
globals.package_.loaded.set("os", os);
return os;
}
public Varargs invoke(Varargs args) {
try {
switch ( opcode ) {
case INIT:
return init(args.arg1());
case CLOCK:
return valueOf(clock());
case DATE: {
String s = args.optjstring(1, null);
double t = args.optdouble(2,-1);
return valueOf( date(s, t==-1? System.currentTimeMillis()/1000.: t) );
}
case DIFFTIME:
return valueOf(difftime(args.checkdouble(1),args.checkdouble(2)));
case EXECUTE:
return valueOf(execute(args.optjstring(1, null)));
case EXIT:
exit(args.optint(1, 0));
class OsLibFunc extends VarArgFunction {
public OsLibFunc(int opcode, String name) {
this.opcode = opcode;
this.name = name;
}
public Varargs invoke(Varargs args) {
try {
switch ( opcode ) {
case CLOCK:
return valueOf(clock());
case DATE: {
String s = args.optjstring(1, null);
double t = args.optdouble(2,-1);
return valueOf( date(s, t==-1? System.currentTimeMillis()/1000.: t) );
}
case DIFFTIME:
return valueOf(difftime(args.checkdouble(1),args.checkdouble(2)));
case EXECUTE:
return execute(args.optjstring(1, null));
case EXIT:
exit(args.optint(1, 0));
return NONE;
case GETENV: {
final String val = getenv(args.checkjstring(1));
return val!=null? valueOf(val): NIL;
}
case REMOVE:
remove(args.checkjstring(1));
return LuaValue.TRUE;
case RENAME:
rename(args.checkjstring(1), args.checkjstring(2));
return LuaValue.TRUE;
case SETLOCALE: {
String s = setlocale(args.optjstring(1,null), args.optjstring(2, "all"));
return s!=null? valueOf(s): NIL;
}
case TIME:
return valueOf(time(args.arg1().isnil()? null: args.checktable(1)));
case TMPNAME:
return valueOf(tmpname());
}
return NONE;
case GETENV: {
final String val = getenv(args.checkjstring(1));
return val!=null? valueOf(val): NIL;
} catch ( IOException e ) {
return varargsOf(NIL, valueOf(e.getMessage()));
}
case REMOVE:
remove(args.checkjstring(1));
return LuaValue.TRUE;
case RENAME:
rename(args.checkjstring(1), args.checkjstring(2));
return LuaValue.TRUE;
case SETLOCALE: {
String s = setlocale(args.optjstring(1,null), args.optjstring(2, "all"));
return s!=null? valueOf(s): NIL;
}
case TIME:
return valueOf(time(args.arg1().isnil()? null: args.checktable(1)));
case TMPNAME:
return valueOf(tmpname());
}
return NONE;
} catch ( IOException e ) {
return varargsOf(NIL, valueOf(e.getMessage()));
}
}
@@ -219,8 +236,8 @@ public class OsLib extends VarArgFunction {
* is available and zero otherwise.
* @param command command to pass to the system
*/
protected int execute(String command) {
return 0;
protected Varargs execute(String command) {
return varargsOf(NIL, valueOf("exit"), ONE);
}
/**

View File

@@ -24,6 +24,7 @@ import java.io.File;
import java.io.IOException;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.LibFunction;
/**
@@ -79,23 +80,20 @@ public class JseOsLib extends org.luaj.vm2.lib.OsLib {
public JseOsLib() {
}
protected int execute(String command) {
Runtime r = Runtime.getRuntime();
protected Varargs execute(String command) {
int exitValue;
try {
final Process p = r.exec(command);
try {
p.waitFor();
return p.exitValue();
} finally {
p.destroy();
}
exitValue = new JseProcess(command, null, globals.STDOUT, globals.STDERR).waitFor();
} catch (IOException ioe) {
return EXEC_IOEXCEPTION;
exitValue = EXEC_IOEXCEPTION;
} catch (InterruptedException e) {
return EXEC_INTERRUPTED;
exitValue = EXEC_INTERRUPTED;
} catch (Throwable t) {
return EXEC_ERROR;
}
exitValue = EXEC_ERROR;
}
if (exitValue == 0)
return varargsOf(TRUE, valueOf("exit"), ZERO);
return varargsOf(NIL, valueOf("signal"), valueOf(exitValue));
}
protected void remove(String filename) throws IOException {

View File

@@ -0,0 +1,116 @@
/*******************************************************************************
* Copyright (c) 2012 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.lib.jse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/** Analog of Process that pipes input and output to client-specified streams.
*/
public class JseProcess {
final Process process;
final Thread input,output,error;
/** Construct a process around a command, with specified streams to redirect input and output to.
*
* @param cmd The command to execute, including arguments, if any
* @param stdin Optional InputStream to read from as process input, or null if input is not needed.
* @param stdout Optional OutputStream to copy process output to, or null if output is ignored.
* @param stderr Optinoal OutputStream to copy process stderr output to, or null if output is ignored.
* @throws IOException If the system process could not be created.
* @see Process
*/
public JseProcess(String[] cmd, InputStream stdin, OutputStream stdout, OutputStream stderr) throws IOException {
this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr);
}
/** Construct a process around a command, with specified streams to redirect input and output to.
*
* @param cmd The command to execute, including arguments, if any
* @param stdin Optional InputStream to read from as process input, or null if input is not needed.
* @param stdout Optional OutputStream to copy process output to, or null if output is ignored.
* @param stderr Optinoal OutputStream to copy process stderr output to, or null if output is ignored.
* @throws IOException If the system process could not be created.
* @see Process
*/
public JseProcess(String cmd, InputStream stdin, OutputStream stdout, OutputStream stderr) throws IOException {
this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr);
}
private JseProcess(Process process, InputStream stdin, OutputStream stdout, OutputStream stderr) {
this.process = process;
input = stdin == null? null: copyBytes(stdin, process.getOutputStream(), null, process.getOutputStream());
output = stdout == null? null: copyBytes(process.getInputStream(), stdout, process.getInputStream(), null);
error = stderr == null? null: copyBytes(process.getErrorStream(), stderr, process.getErrorStream(), null);
}
/** Get the exit value of the process. */
public int exitValue() {
return process.exitValue();
}
/** Wait for the process to complete, and all pending output to finish.
* @return The exit status.
* @throws InterruptedException
*/
public int waitFor() throws InterruptedException {
int r = process.waitFor();
if (input != null)
input.join();
if (output != null)
output.join();
if (error != null)
error.join();
process.destroy();
return r;
}
/** Create a thread to copy bytes from input to output. */
private Thread copyBytes(final InputStream input,
final OutputStream output, final InputStream ownedInput,
final OutputStream ownedOutput) {
Thread t = (new Thread() {
public void run() {
try {
byte[] buf = new byte[1024];
int r;
try {
while ((r = input.read(buf)) >= 0) {
output.write(buf, 0, r);
}
} finally {
if (ownedInput != null)
ownedInput.close();
if (ownedOutput != null)
ownedOutput.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
return t;
}
}

View File

@@ -34,8 +34,8 @@ import java.net.URL;
import junit.framework.TestCase;
import org.luaj.vm2.lib.BaseLib;
import org.luaj.vm2.lib.ResourceFinder;
import org.luaj.vm2.lib.jse.JseProcess;
import org.luaj.vm2.luajc.LuaJC;
abstract
@@ -235,69 +235,8 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder {
throws IOException, InterruptedException {
Runtime r = Runtime.getRuntime();
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final Process p = r.exec(cmd);
try {
// start a thread to write the given input to the subprocess.
Thread inputCopier = (new Thread() {
public void run() {
try {
OutputStream processStdIn = p.getOutputStream();
try {
copy(input, processStdIn);
} finally {
processStdIn.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
inputCopier.start();
// start another thread to read output from the subprocess.
Thread outputCopier = (new Thread() {
public void run() {
try {
InputStream processStdOut = p.getInputStream();
try {
copy(processStdOut, baos);
} finally {
processStdOut.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
});
outputCopier.start();
// start another thread to read output from the subprocess.
Thread errorCopier = (new Thread() {
public void run() {
try {
InputStream processError = p.getErrorStream();
try {
copy(processError, System.err);
} finally {
processError.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
});
errorCopier.start();
p.waitFor();
inputCopier.join();
outputCopier.join();
errorCopier.join();
return new String(baos.toByteArray());
} finally {
p.destroy();
}
new JseProcess(cmd, input, baos, System.err).waitFor();
return new String(baos.toByteArray());
}
private String readString(InputStream is) throws IOException {

View File

@@ -8,13 +8,12 @@
--
local pcall = function(...)
local s,e,f = pcall(...)
return s,type(e)
return s,type(e),type(f)
end
print( 'os', type(os) )
print( 'os.clock()', pcall( os.clock ) )
print( 'os.date()', pcall( os.date ) )
print( 'os.difftime(123000, 21500)', pcall( os.difftime, 123000, 21250 ) )
print( 'os.execute("bogus")', pcall( os.execute, '' ) )
print( 'os.getenv()', pcall( os.getenv ) )
print( 'os.getenv("bogus.key")', pcall( os.getenv, 'bogus.key' ) )
local s,p = pcall( os.tmpname )