package js.tinyvm;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import js.common.AbstractTool;
import js.common.ToolProgressMonitor;
import js.tinyvm.io.BEByteWriter;
import js.tinyvm.io.IByteWriter;
import js.tinyvm.io.LEByteWriter;
/**
* Tiny VM.
*/
public class TinyVMTool extends AbstractTool
{
// /**
// * Constructor.
// */
// public TinyVMTool (ToolProgressMonitor monitor)
// {
// super(monitor);
// }
/**
* Execute tiny vm.
*
* @param classpath classpath
* @param classes main classes to compile
* @param all
* @param stream output stream to write binary to
* @param bigEndian write big endian output?
* @param options
* @param debug true to add debug monitor
* @throws TinyVMException
*/
public void link (String classpath, String[] classes, boolean all,
OutputStream stream, boolean bigEndian, int options, boolean debug) throws TinyVMException
{
assert classpath != null: "Precondition: classpath != null";
assert classes != null: "Precondition: classes != null";
assert stream != null: "Precondition: stream != null";
Binary binary = link(classpath, classes, all, options, debug);
for(ToolProgressMonitor monitor : _monitors) {
binary.log(monitor);
}
//binary.log(getProgressMonitor());
dump(binary, stream, bigEndian);
}
/**
* Link classes.
*
* @param classpath class path
* @param entryClassNames entry class names to link
* @param all do not filter classes?
* @param options
* @param debug
* @return binary
* @throws TinyVMException
*/
public Binary link (String classpath, String[] entryClassNames, boolean all, int options, boolean debug)
throws TinyVMException
{
assert classpath != null: "Precondition: classpath != null";
assert entryClassNames != null: "Precondition: entryClassNames != null";
if (entryClassNames.length >= 255)
{
throw new TinyVMException("Too many entry classes (max is 254!)");
}
if (debug)
{
// Insert the debug monitor class as the first entry class
int names = entryClassNames.length;
String [] newNames = new String[names+1];
System.arraycopy(entryClassNames, 0, newNames, 1, names);
entryClassNames = newNames;
entryClassNames[0] = "lejos.nxt.debug.DebugMonitor";
}
ClassPath computedClasspath = new ClassPath(classpath);
for (int i = 0; i < entryClassNames.length; i++)
{
entryClassNames[i] = entryClassNames[i].replace('.', '/');
}
Binary result = Binary.createFromClosureOf(entryClassNames,
computedClasspath, all);
for (int i = 0; i < entryClassNames.length; i++)
{
if (!result.hasMain(entryClassNames[i]))
{
throw new TinyVMException("Class " + entryClassNames[i]
+ " doesn't have a static void main(String[]) method");
}
}
result.setRunTimeOptions(options);
assert result != null: "Postconditon: result != null";
return result;
}
/**
* Dump binary to stream.
*
* @param binary binary
* @param stream stream to write to
* @param bigEndian use big endian encoding?
* @throws TinyVMException
*/
public void dump (Binary binary, OutputStream stream, boolean bigEndian)
throws TinyVMException
{
assert binary != null: "Precondition: binary != null";
assert stream != null: "Precondition: stream != null";
try
{
OutputStream bufferedStream = new BufferedOutputStream(stream, 4096);
IByteWriter byteWriter = bigEndian
? (IByteWriter) new BEByteWriter(bufferedStream)
: (IByteWriter) new LEByteWriter(bufferedStream);
binary.dump(byteWriter);
bufferedStream.close();
}
catch (IOException e)
{
throw new TinyVMException(e.getMessage(), e);
}
}
private static final Logger _logger = Logger.getLogger("TinyVM");
static
{
_logger.setLevel(Level.OFF);
}
}