mirror of
https://github.com/processing/processing4.git
synced 2026-02-03 21:59:20 +01:00
Backend refactoring: KjcEngine has been split up into separate classes for preprocessing, compiling, and running.
This commit is contained in:
@@ -2,10 +2,10 @@
|
||||
// while the kjc engine is in use. takes care of error handling.
|
||||
|
||||
public class KjcApplet extends BApplet {
|
||||
KjcEngine engine;
|
||||
PdeRuntime pdeRuntime;
|
||||
|
||||
public void setEngine(KjcEngine engine) {
|
||||
this.engine = engine;
|
||||
public void setRuntime(PdeRuntime pdeRuntime) {
|
||||
this.pdeRuntime = pdeRuntime;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
@@ -16,8 +16,8 @@ public class KjcApplet extends BApplet {
|
||||
//System.out.println("ex found in run");
|
||||
e.printStackTrace();
|
||||
//engine.error(e);
|
||||
engine.newMessage = true;
|
||||
e.printStackTrace(engine.leechErr);
|
||||
pdeRuntime.newMessage = true;
|
||||
e.printStackTrace(pdeRuntime.leechErr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1240
app/KjcEngine.java
1240
app/KjcEngine.java
File diff suppressed because it is too large
Load Diff
85
app/PdeCompiler.java
Normal file
85
app/PdeCompiler.java
Normal file
@@ -0,0 +1,85 @@
|
||||
// -*- Mode: JDE; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
|
||||
import java.io.*;
|
||||
|
||||
// This class will be the new default of Jikes.
|
||||
//
|
||||
public class PdeCompiler implements PdeMessageConsumer{
|
||||
|
||||
String buildPath;
|
||||
String className;
|
||||
PdeException exception;
|
||||
PdeEditor editor;
|
||||
|
||||
public PdeCompiler(String buildPath, String className, PdeEditor editor) {
|
||||
this.buildPath = buildPath;
|
||||
this.className = className;
|
||||
this.editor = editor;
|
||||
}
|
||||
|
||||
public boolean compileJava(PrintStream leechErr) {
|
||||
String command[] = new String[] {
|
||||
"jikes",
|
||||
"+E", // output errors in machine-parsable format
|
||||
"-d", buildPath, // output the classes in the buildPath
|
||||
buildPath + File.separator + className + ".java" // file to compile
|
||||
};
|
||||
|
||||
int result;
|
||||
// XXXdmose try/catch should be separate
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(command);
|
||||
// XXXdmose race condition?
|
||||
new PdeMessageSiphon(process.getInputStream(),
|
||||
process.getErrorStream(),
|
||||
this);
|
||||
|
||||
result = process.waitFor();
|
||||
} catch (Exception e) {
|
||||
result = -1;
|
||||
}
|
||||
//System.err.println("result = " + result);
|
||||
|
||||
return result == 0 ? true : false;
|
||||
}
|
||||
|
||||
// part of the PdeMessageConsumer interface
|
||||
//
|
||||
public void message(String s) {
|
||||
|
||||
// as in: lib\build\Temporary_5476_6442.java:88: caution:Assignment of an expression to itself [KOPI]
|
||||
if (s.indexOf("caution") != -1) return;
|
||||
|
||||
// jikes always uses a forward slash character as its separator, so
|
||||
// we need to replace any platform-specific separator characters before
|
||||
// attemping to compare
|
||||
//
|
||||
String fullTempFilename = buildPath.replace(File.separatorChar, '/')
|
||||
+ "/" + className + ".java";
|
||||
|
||||
if (s.indexOf(fullTempFilename) == 0) {
|
||||
String s1 = s.substring(fullTempFilename.length() + 1);
|
||||
int colon = s1.indexOf(':');
|
||||
int lineNumber = Integer.parseInt(s1.substring(0, colon));
|
||||
//System.out.println("pde / line number: " + lineNumber);
|
||||
|
||||
//String s2 = s1.substring(colon + 2);
|
||||
int err = s1.indexOf("Error:");
|
||||
if (err != -1) {
|
||||
//err += "error:".length();
|
||||
String description = s1.substring(err + "Error:".length());
|
||||
description = description.trim();
|
||||
System.out.println("description = " + description);
|
||||
exception = new PdeException(description, lineNumber-1);
|
||||
editor.error(exception);
|
||||
|
||||
} else {
|
||||
System.err.println("i suck: " + s);
|
||||
}
|
||||
|
||||
} else {
|
||||
// this isn't the start of an error line, so don't attempt to parse
|
||||
// a line number out of it
|
||||
}
|
||||
}
|
||||
}
|
||||
69
app/PdeCompilerKjc.java
Normal file
69
app/PdeCompilerKjc.java
Normal file
@@ -0,0 +1,69 @@
|
||||
// -*- Mode: JDE; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
|
||||
// The existing Kjc code lives here, and can someday go away.
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
public class PdeCompilerKjc extends PdeCompiler {
|
||||
|
||||
public PdeCompilerKjc(String buildPath, String className, PdeEditor editor) {
|
||||
super(buildPath, className, editor);
|
||||
}
|
||||
|
||||
public boolean compileJava(PrintStream leechErr) {
|
||||
|
||||
System.setErr(leechErr); // redirect stderr to our leech filter
|
||||
|
||||
String args[] = new String[2];
|
||||
args[0] = "-d" + buildPath;
|
||||
args[1] = buildPath + File.separator + className + ".java";
|
||||
//System.out.println("args = " + args[0] + " " + args[1]);
|
||||
|
||||
boolean success = at.dms.kjc.Main.compile(args);
|
||||
|
||||
System.setErr(PdeEditorConsole.consoleErr);
|
||||
|
||||
//System.err.println("success = " + success);
|
||||
return success;
|
||||
}
|
||||
|
||||
// part of the PdeMessageConsumer interface
|
||||
//
|
||||
public void message(String s) {
|
||||
// as in: lib\build\Temporary_5476_6442.java:88: caution:Assignment of an expression to itself [KOPI]
|
||||
if (s.indexOf("caution") != -1) return;
|
||||
|
||||
//
|
||||
//System.out.println("leech2: " + new String(b, offset, length));
|
||||
//String s = new String(b, offset, length);
|
||||
//if (s.indexOf(tempFilename) == 0) {
|
||||
String fullTempFilename = buildPath + File.separator + className + ".java";
|
||||
if (s.indexOf(fullTempFilename) == 0) {
|
||||
String s1 = s.substring(fullTempFilename.length() + 1);
|
||||
int colon = s1.indexOf(':');
|
||||
int lineNumber = Integer.parseInt(s1.substring(0, colon));
|
||||
//System.out.println("pde / line number: " + lineNumber);
|
||||
|
||||
//String s2 = s1.substring(colon + 2);
|
||||
int err = s1.indexOf("error:");
|
||||
if (err != -1) {
|
||||
//err += "error:".length();
|
||||
String description = s1.substring(err + "error:".length());
|
||||
description = description.trim();
|
||||
//exception = new PdeException(description, lineNumber-2);
|
||||
exception = new PdeException(description, lineNumber-1);
|
||||
editor.error(exception);
|
||||
|
||||
} else {
|
||||
System.err.println("i suck: " + s);
|
||||
}
|
||||
|
||||
} else {
|
||||
//System.err.println("don't understand: " + s);
|
||||
exception = new PdeException("Error while compiling, " +
|
||||
"please send code to bugs@proce55ing.net");
|
||||
editor.error(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
// -*- Mode: JDE; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.*;
|
||||
@@ -66,8 +68,6 @@ public class PdeEditor extends Panel {
|
||||
//String lastFile;
|
||||
|
||||
//PdeRunner runner;
|
||||
//KjcEngine engine;
|
||||
PdeEngine engine;
|
||||
Point appletLocation; //= new Point(0, 0);
|
||||
Point presentLocation; // = new Point(0, 0);
|
||||
|
||||
@@ -76,6 +76,8 @@ public class PdeEditor extends Panel {
|
||||
|
||||
RunButtonWatcher watcher;
|
||||
|
||||
PdeRuntime pdeRuntime;
|
||||
|
||||
static final int GRID_SIZE = 33;
|
||||
static final int INSET_SIZE = 5;
|
||||
|
||||
@@ -85,6 +87,13 @@ public class PdeEditor extends Panel {
|
||||
|
||||
PdeBase base;
|
||||
|
||||
PrintStream leechErr;
|
||||
PdeMessageStream messageStream;
|
||||
String buildPath;
|
||||
|
||||
static final String TEMP_CLASS = "Temporary";
|
||||
|
||||
|
||||
// hack while fixing layout issues
|
||||
//Component pain;
|
||||
|
||||
@@ -335,7 +344,7 @@ public class PdeEditor extends Panel {
|
||||
//if (frame != null) frame.toFront(); // editor to front
|
||||
try {
|
||||
//System.out.println("moving to front");
|
||||
engine.window.toFront();
|
||||
pdeRuntime.window.toFront();
|
||||
} catch (Exception ex) { }
|
||||
}
|
||||
});
|
||||
@@ -645,27 +654,33 @@ public class PdeEditor extends Panel {
|
||||
|
||||
try {
|
||||
if (presenting) {
|
||||
presentationWindow.show();
|
||||
presentationWindow.toFront();
|
||||
//doRun(true);
|
||||
presentationWindow.show();
|
||||
presentationWindow.toFront();
|
||||
//doRun(true);
|
||||
}
|
||||
|
||||
String program = textarea.getText();
|
||||
makeHistory(program, RUN);
|
||||
|
||||
//if (program.length() != 0) {
|
||||
String buildPath = "lib" + File.separator + "build"; // TEMPORARY
|
||||
//if (PdeBase.platform == PdeBase.MACOSX) {
|
||||
//String pkg = "Proce55ing.app/Contents/Resources/Java/";
|
||||
//buildPath = pkg + "build";
|
||||
//String pkg = "Proce55ing.app/Contents/Resources/Java/";
|
||||
//buildPath = pkg + "build";
|
||||
//}
|
||||
buildPath = "lib" + File.separator + "build";
|
||||
|
||||
File buildDir = new File(buildPath);
|
||||
if (!buildDir.exists()) buildDir.mkdirs();
|
||||
if (!buildDir.exists()) {
|
||||
buildDir.mkdirs();
|
||||
}
|
||||
|
||||
String dataPath =
|
||||
sketchFile.getParent() + File.separator + "data";
|
||||
//editor.sketchFile.getParent() + File.separator + "data";
|
||||
String dataPath = sketchFile.getParent() + File.separator + "data";
|
||||
|
||||
if (dataPath != null) {
|
||||
File dataDir = new File(dataPath);
|
||||
if (dataDir.exists()) {
|
||||
PdeEditor.copyDir(dataDir, buildDir);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
this needs to be reworked. there are three essential parts
|
||||
@@ -690,21 +705,60 @@ this needs to be reworked. there are three essential parts
|
||||
|
||||
afterwards, some of these steps need a cleanup function
|
||||
*/
|
||||
int numero1 = (int) (Math.random() * 10000);
|
||||
int numero2 = (int) (Math.random() * 10000);
|
||||
String className = TEMP_CLASS + "_" + numero1 + "_" + numero2;
|
||||
|
||||
engine = new KjcEngine(this, program, buildPath, dataPath);
|
||||
//engine.start();
|
||||
//engine.start(presenting ? presentLocation : appletLocation);
|
||||
engine.start(presenting ? presentLocation : appletLocation);
|
||||
//System.out.println("done iwth engine.start()");
|
||||
//}
|
||||
// do the preprocessing and write a .java file
|
||||
//
|
||||
// in an advanced program, the returned classname could be different,
|
||||
// which is why we need to set className based on the return value
|
||||
//
|
||||
PdePreprocessor preprocessorOro =
|
||||
new PdePreprocessorOro(program, buildPath);
|
||||
className = preprocessorOro.writeJava(className, true);
|
||||
|
||||
watcher = new RunButtonWatcher();
|
||||
// compile the program
|
||||
//
|
||||
PdeCompiler compilerKjc = new PdeCompilerKjc(buildPath, className, this);
|
||||
|
||||
// this will catch and parse errors during compilation
|
||||
messageStream = new PdeMessageStream(this, compilerKjc);
|
||||
leechErr = new PrintStream(messageStream);
|
||||
|
||||
boolean result = compilerKjc.compileJava(leechErr);
|
||||
|
||||
// if the compilation worked, run the applet
|
||||
//
|
||||
if (result) {
|
||||
|
||||
// create a runtime object
|
||||
pdeRuntime = new PdeRuntime(this, className);
|
||||
|
||||
// use the runtime object to consume the errors now
|
||||
messageStream.setMessageConsumer(pdeRuntime);
|
||||
|
||||
// start the applet
|
||||
pdeRuntime.start(presenting ? presentLocation : appletLocation,
|
||||
leechErr);
|
||||
|
||||
// spawn a thread to update PDE GUI state
|
||||
watcher = new RunButtonWatcher();
|
||||
|
||||
} else {
|
||||
cleanTempFiles(buildPath);
|
||||
}
|
||||
} catch (PdeException e) {
|
||||
//state = RUNNER_ERROR;
|
||||
//forceStop = false;
|
||||
//this.stop();
|
||||
engine.stop();
|
||||
|
||||
// if we made it to the runtime stage, stop that thread
|
||||
//
|
||||
if (pdeRuntime != null) {
|
||||
pdeRuntime.stop();
|
||||
}
|
||||
cleanTempFiles(buildPath);
|
||||
e.printStackTrace();
|
||||
//editor.error(e);
|
||||
error(e);
|
||||
@@ -712,8 +766,16 @@ afterwards, some of these steps need a cleanup function
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
//this.stop();
|
||||
engine.stop();
|
||||
|
||||
// if we made it to the runtime stage, stop that thread
|
||||
//
|
||||
if (pdeRuntime != null) {
|
||||
pdeRuntime.stop();
|
||||
}
|
||||
|
||||
cleanTempFiles(buildPath);
|
||||
}
|
||||
|
||||
//engine = null;
|
||||
//System.out.println("out of doRun()");
|
||||
// required so that key events go to the panel and <key> works
|
||||
@@ -730,16 +792,15 @@ afterwards, some of these steps need a cleanup function
|
||||
|
||||
public void run() {
|
||||
while (Thread.currentThread() == thread) {
|
||||
KjcEngine eng = (KjcEngine)engine;
|
||||
if ((engine != null) && (eng.applet != null)) {
|
||||
//System.out.println(eng.applet.finished);
|
||||
buttons.running(!eng.applet.finished);
|
||||
//} else {
|
||||
//System.out.println("still pooping");
|
||||
}
|
||||
try {
|
||||
Thread.sleep(250);
|
||||
} catch (InterruptedException e) { }
|
||||
if ((pdeRuntime != null) && (pdeRuntime.applet != null)) {
|
||||
//System.out.println(pdeRuntime.applet.finished);
|
||||
buttons.running(!pdeRuntime.applet.finished);
|
||||
//} else {
|
||||
//System.out.println("still pooping");
|
||||
}
|
||||
try {
|
||||
Thread.sleep(250);
|
||||
} catch (InterruptedException e) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -758,8 +819,7 @@ afterwards, some of these steps need a cleanup function
|
||||
}
|
||||
*/
|
||||
|
||||
//System.out.println("stop1");
|
||||
if (engine != null) engine.stop();
|
||||
if (pdeRuntime != null) pdeRuntime.stop();
|
||||
if (watcher != null) watcher.stop();
|
||||
//System.out.println("stop2");
|
||||
message(EMPTY);
|
||||
@@ -784,7 +844,7 @@ afterwards, some of these steps need a cleanup function
|
||||
|
||||
} else {
|
||||
try {
|
||||
appletLocation = engine.window.getLocation();
|
||||
appletLocation = pdeRuntime.window.getLocation();
|
||||
} catch (NullPointerException e) { }
|
||||
}
|
||||
//System.out.println("doclose2");
|
||||
@@ -796,12 +856,17 @@ afterwards, some of these steps need a cleanup function
|
||||
|
||||
//System.out.println("doclose3");
|
||||
try {
|
||||
engine.close(); // kills the window
|
||||
engine = null; // will this help?
|
||||
|
||||
if (pdeRuntime != null) {
|
||||
pdeRuntime.close(); // kills the window
|
||||
pdeRuntime = null; // will this help?
|
||||
}
|
||||
} catch (Exception e) { }
|
||||
//System.out.println("doclose4");
|
||||
//buttons.clear(); // done by doStop
|
||||
|
||||
if (buildPath != null) {
|
||||
cleanTempFiles(buildPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1364,19 +1429,28 @@ afterwards, some of these steps need a cleanup function
|
||||
// create the project directory
|
||||
// pass null for datapath because the files shouldn't be
|
||||
// copied to the build dir.. that's only for the temp stuff
|
||||
KjcEngine ex_engine = new KjcEngine(this, program,
|
||||
appletDir.getPath(), null);
|
||||
//dataDir.getPath(), this);
|
||||
|
||||
//File projectDir = new File(appletDir, projectName);
|
||||
//projectDir.mkdirs();
|
||||
appletDir.mkdirs();
|
||||
|
||||
// projectName will be updated with actual class name
|
||||
exportSketchName = ex_engine.writeJava(exportSketchName, false);
|
||||
if (!ex_engine.compileJava()) {
|
||||
//throw new Exception("error while compiling, couldn't export");
|
||||
// message() will already have error message in this case
|
||||
return;
|
||||
// preprocess the program
|
||||
//
|
||||
PdePreprocessor preprocessorOro =
|
||||
new PdePreprocessorOro(program, appletDir.getPath());
|
||||
exportSketchName = preprocessorOro.writeJava(exportSketchName, false);
|
||||
|
||||
PdeCompiler compilerKjc = new PdeCompilerKjc(appletDir.getPath(),
|
||||
exportSketchName, this);
|
||||
|
||||
// this will catch and parse errors during compilation
|
||||
messageStream = new PdeMessageStream(this, compilerKjc);
|
||||
leechErr = new PrintStream(messageStream);
|
||||
|
||||
if (!compilerKjc.compileJava(leechErr)) {
|
||||
//throw new Exception("error while compiling, couldn't export");
|
||||
// message() will already have error message in this case
|
||||
return;
|
||||
}
|
||||
|
||||
// not necessary, now compiles into applet dir
|
||||
@@ -1387,7 +1461,7 @@ afterwards, some of these steps need a cleanup function
|
||||
//copyFile(new File(javaName), new File(appletDir, javaName));
|
||||
|
||||
// remove temporary .java and .class files
|
||||
//ex_engine.cleanup();
|
||||
// cleanTempFiles(buildPath);
|
||||
|
||||
int wide = BApplet.DEFAULT_WIDTH;
|
||||
int high = BApplet.DEFAULT_HEIGHT;
|
||||
@@ -1850,8 +1924,8 @@ afterwards, some of these steps need a cleanup function
|
||||
}
|
||||
if (end == -1) end = len;
|
||||
|
||||
// sometimes KJC claims that the line it found an error in is
|
||||
// the last line in the file + 1. Just highlight the last line
|
||||
// sometimes KJC claims that the line it found an error in is
|
||||
// the last line in the file + 1. Just highlight the last line
|
||||
// in this case. [dmose]
|
||||
if (st == -1) st = len;
|
||||
|
||||
@@ -1971,21 +2045,50 @@ afterwards, some of these steps need a cleanup function
|
||||
}
|
||||
}
|
||||
|
||||
static protected void removeDir(File dir) {
|
||||
//System.out.println("removing " + dir);
|
||||
// cleanup temp files
|
||||
//
|
||||
static protected void cleanTempFiles(String buildPath) {
|
||||
|
||||
// if the java runtime is holding onto any files in the build dir, we
|
||||
// won't be able to delete them, so we need to force a gc here
|
||||
//
|
||||
System.gc();
|
||||
|
||||
File dirObject = new File(buildPath);
|
||||
|
||||
// note that we can't remove the builddir itself, otherwise
|
||||
// the next time we start up, internal runs using PdeRuntime won't
|
||||
// work because the build dir won't exist at startup, so the classloader
|
||||
// will ignore the fact that that dir is in the CLASSPATH in run.sh
|
||||
//
|
||||
if (dirObject.exists()) {
|
||||
removeDescendants(dirObject);
|
||||
}
|
||||
}
|
||||
|
||||
// remove all files in a directory
|
||||
//
|
||||
static protected void removeDescendants(File dir) {
|
||||
|
||||
String files[] = dir.list();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if (files[i].equals(".") || files[i].equals("..")) continue;
|
||||
File dead = new File(dir, files[i]);
|
||||
if (!dead.isDirectory()) {
|
||||
if (!dead.delete()) System.err.println("couldn't delete " + dead);
|
||||
if (!dead.delete())
|
||||
System.err.println("couldn't delete " + dead);
|
||||
} else {
|
||||
removeDir(dead);
|
||||
//dead.delete();
|
||||
removeDir(dead);
|
||||
//dead.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove all files in a directory and the dir itself
|
||||
//
|
||||
static protected void removeDir(File dir) {
|
||||
//System.out.println("removing " + dir);
|
||||
removeDescendants(dir);
|
||||
dir.delete();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
15
app/PdeMessageConsumer.java
Normal file
15
app/PdeMessageConsumer.java
Normal file
@@ -0,0 +1,15 @@
|
||||
// -*- Mode: JDE; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
|
||||
// Different instances of PdeMessageStream need to do different things with
|
||||
// messages. In particular, a stream instance used for parsing output from
|
||||
// the compiler compiler has to interpret its messages differently than one
|
||||
// parsing output from the runtime.
|
||||
//
|
||||
// Classes which consume messages and do something with them should implement
|
||||
// this interface.
|
||||
//
|
||||
public interface PdeMessageConsumer {
|
||||
|
||||
public void message(String s);
|
||||
|
||||
}
|
||||
57
app/PdeMessageSiphon.java
Normal file
57
app/PdeMessageSiphon.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/// -*- Mode: JDE; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
|
||||
import java.io.*;
|
||||
|
||||
// XXXdmose error checking
|
||||
|
||||
class PdeMessageSiphon implements Runnable {
|
||||
BufferedReader stdout, stderr;
|
||||
PrintStream leechErr;
|
||||
Thread thread;
|
||||
PdeMessageConsumer consumer;
|
||||
|
||||
public PdeMessageSiphon(InputStream stdout, InputStream stderr,
|
||||
PdeMessageConsumer consumer) {
|
||||
|
||||
// XXXdmose error checking here
|
||||
|
||||
this.stdout = new BufferedReader(new InputStreamReader(stdout));
|
||||
this.stderr = new BufferedReader(new InputStreamReader(stderr));
|
||||
this.consumer = consumer;
|
||||
|
||||
thread = new Thread(this);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
String currentLine;
|
||||
|
||||
while (Thread.currentThread() == thread) {
|
||||
|
||||
// XXX put back while loops
|
||||
|
||||
try {
|
||||
if (stderr.ready()) {
|
||||
currentLine = stderr.readLine();
|
||||
System.err.println(currentLine);
|
||||
consumer.message(currentLine);
|
||||
}
|
||||
|
||||
if (stdout.ready()) {
|
||||
currentLine = stdout.readLine();
|
||||
System.err.println(currentLine);
|
||||
consumer.message(currentLine);
|
||||
}
|
||||
|
||||
Thread.sleep(10);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("PdeMessageSiphon err " + e);
|
||||
|
||||
thread.stop();
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
36
app/PdeMessageStream.java
Normal file
36
app/PdeMessageStream.java
Normal file
@@ -0,0 +1,36 @@
|
||||
// -*- Mode: JDE; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
|
||||
import java.io.*;
|
||||
|
||||
class PdeMessageStream extends OutputStream {
|
||||
|
||||
PdeEditor editor;
|
||||
PdeMessageConsumer messageConsumer;
|
||||
|
||||
public PdeMessageStream(PdeEditor editor,
|
||||
PdeMessageConsumer messageConsumer) {
|
||||
this.editor = editor;
|
||||
this.messageConsumer = messageConsumer;
|
||||
}
|
||||
|
||||
public void setMessageConsumer(PdeMessageConsumer messageConsumer) {
|
||||
this.messageConsumer = messageConsumer;
|
||||
}
|
||||
|
||||
public void close() { }
|
||||
|
||||
public void flush() { }
|
||||
|
||||
public void write(byte b[]) {
|
||||
System.out.println("leech1: " + new String(b));
|
||||
}
|
||||
|
||||
public void write(byte b[], int offset, int length) {
|
||||
//System.out.println("leech2: " + new String(b));
|
||||
this.messageConsumer.message(new String(b, offset, length));
|
||||
}
|
||||
|
||||
public void write(int b) {
|
||||
System.out.println("leech3: '" + ((char)b) + "'");
|
||||
}
|
||||
}
|
||||
11
app/PdePreprocessor.java
Normal file
11
app/PdePreprocessor.java
Normal file
@@ -0,0 +1,11 @@
|
||||
// This class will be the new CUP-generated preprocessor.
|
||||
//
|
||||
public class PdePreprocessor {
|
||||
|
||||
public PdePreprocessor() {
|
||||
}
|
||||
|
||||
public String writeJava(String name, boolean kjc) {
|
||||
return "This class is currently purely abstract";
|
||||
}
|
||||
}
|
||||
441
app/PdePreprocessorOro.java
Normal file
441
app/PdePreprocessorOro.java
Normal file
@@ -0,0 +1,441 @@
|
||||
// -*- Mode: JDE; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
|
||||
// The existing ORO-based preprocessing code lives here, and can
|
||||
// someday go away.
|
||||
|
||||
import com.oroinc.text.regex.*;
|
||||
import java.io.*;
|
||||
|
||||
public class PdePreprocessorOro extends PdePreprocessor {
|
||||
|
||||
static final String EXTENDS = "extends BApplet ";
|
||||
static final String EXTENDS_KJC = "extends KjcApplet ";
|
||||
|
||||
static final String applet_imports[] = {
|
||||
"java.applet", "java.awt", "java.awt.image", "java.awt.event",
|
||||
"java.io", "java.net", "java.text", "java.util", "java.util.zip"
|
||||
};
|
||||
|
||||
static final String application_imports[] = {
|
||||
"java.applet", "java.awt", "java.awt.image", "java.awt.event",
|
||||
"java.io", "java.net", "java.text", "java.util", "java.util.zip",
|
||||
"javax.comm",
|
||||
|
||||
// if jdk14 defined, jdk13 will be as well
|
||||
#ifdef JDK13
|
||||
"javax.sound.midi", "javax.sound.midi.spi",
|
||||
"javax.sound.sampled", "javax.sound.sampled.spi",
|
||||
#endif
|
||||
|
||||
#ifdef JDK14
|
||||
"javax.xml.parsers", "javax.xml.transform",
|
||||
"javax.xml.transform.dom", "javax.xml.transform.sax",
|
||||
"javax.xml.transform.stream", "org.xml.sax",
|
||||
"org.xml.sax.ext", "org.xml.sax.helpers"
|
||||
#endif
|
||||
};
|
||||
|
||||
String program;
|
||||
String buildPath;
|
||||
boolean usingExternal; // use an external process to display the applet?
|
||||
|
||||
String tempClass;
|
||||
String tempFilename;
|
||||
String tempClassFilename;
|
||||
|
||||
public PdePreprocessorOro(String program, String buildPath) {
|
||||
this.program = program;
|
||||
this.buildPath = buildPath;
|
||||
|
||||
usingExternal = PdeBase.getBoolean("play.external", false);
|
||||
}
|
||||
|
||||
static final int BEGINNER = 0;
|
||||
static final int INTERMEDIATE = 1;
|
||||
static final int ADVANCED = 2;
|
||||
|
||||
// writes .java file into buildPath
|
||||
public String writeJava(String name, boolean kjc) {
|
||||
//System.out.println("writing java");
|
||||
try {
|
||||
int programType = BEGINNER;
|
||||
|
||||
// remove (encode) comments temporarily
|
||||
program = commentsCodec(program /*, true*/);
|
||||
|
||||
// insert 'f' for all floats
|
||||
// shouldn't substitute f's for: "Univers76.vlw.gz";
|
||||
if (PdeBase.getBoolean("compiler.substitute_f", true)) {
|
||||
/*
|
||||
a = 0.2 * 3
|
||||
(3.)
|
||||
(.3 * 6)
|
||||
(.30*7)
|
||||
float f = 0.3;
|
||||
fill(0.3, 0.2, 0.1);
|
||||
|
||||
next to white space \s or math ops +-/*()
|
||||
or , on either side,
|
||||
followed by ; (might as well on either side)
|
||||
|
||||
// allow 3. to work (also allows x.x too)
|
||||
program = substipoot(program, "(\\d+\\.\\d*)(\\D)", "$1f$2");
|
||||
program = substipoot(program, "(\\d+\\.\\d*)ff", "$1f");
|
||||
|
||||
// allow .3 to work (also allows x.x)
|
||||
program = substipoot(program, "(\\d*\\.\\d+)(\\D)", "$1f$2");
|
||||
program = substipoot(program, "(\\d*\\.\\d+)ff", "$1f");
|
||||
*/
|
||||
|
||||
program = substipoot(program, "([\\s\\,\\;\\+\\-\\/\\*\\(\\)])(\\d+\\.\\d*)([\\s\\,\\;\\+\\-\\/\\*\\(\\)])", "$1$2f$3");
|
||||
program = substipoot(program, "([\\s\\,\\;\\+\\-\\/\\*\\(\\)])(\\d*\\.\\d+)([\\s\\,\\;\\+\\-\\/\\*\\(\\)])", "$1$2f$3");
|
||||
}
|
||||
|
||||
// allow int(3.75) instead of just (int)3.75
|
||||
if (PdeBase.getBoolean("compiler.enhanced_casting", true)) {
|
||||
program = substipoot(program, "([^A-Za-z0-9_])byte\\((.*)\\)", "$1(byte)($2)");
|
||||
program = substipoot(program, "([^A-Za-z0-9_])char\\((.*)\\)", "$1(char)($2)");
|
||||
program = substipoot(program, "([^A-Za-z0-9_])int\\((.*)\\)", "$1(int)($2)");
|
||||
program = substipoot(program, "([^A-Za-z0-9_])float\\((.*)\\)", "$1(float)($2)");
|
||||
}
|
||||
|
||||
if (PdeBase.getBoolean("compiler.color_datatype", true)) {
|
||||
// so that regexp works correctly in this strange edge case
|
||||
if (program.indexOf("color") == 0) program = " " + program;
|
||||
// swap 'color' with 'int' when used as a datatype
|
||||
program = substipoot(program,
|
||||
"([;\\s\\(])color([\\s\\[])", "$1int$2");
|
||||
// had to add ( at beginning for addPixel(color c...)
|
||||
//"([;\\s])color([\\s\\[])", "$1int$2");
|
||||
// had to add [ to that guy for color[] stuff
|
||||
//"([;\\s])color([\\s])", "$1int$2");
|
||||
//"([^A-Za-z0-9_.])color([^A-Za-z0-9_\\(.])", "$1int$2");
|
||||
// color(something) like int() and the rest is no good
|
||||
// because there is already a function called 'color' in BGraphics
|
||||
//program = substipoot(program, "([^A-Za-z0-9_])color\\((.*)\\)", "$1(int)($2)");
|
||||
}
|
||||
|
||||
if (PdeBase.getBoolean("compiler.inline_web_colors", true)) {
|
||||
// convert "= #cc9988" into "= 0xffcc9988"
|
||||
//program = substipoot(program, "(=\\s*)\\#([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])", "$1 0xff$2$3$4");
|
||||
//program = substipoot(program, "#([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([;\\s])", "0xff$1$2$3$4");
|
||||
//program = substipoot(program, "#([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([;\\s])", "0x$4$1$2$3$5");
|
||||
program = substipoot(program, "#([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])", "0xff$1$2$3");
|
||||
}
|
||||
|
||||
if ((program.indexOf("void setup()") != -1) ||
|
||||
(program.indexOf("void loop()") != -1) ||
|
||||
(program.indexOf("void draw()") != -1)) {
|
||||
programType = INTERMEDIATE;
|
||||
}
|
||||
|
||||
int index = program.indexOf("public class");
|
||||
if (index != -1) {
|
||||
programType = ADVANCED;
|
||||
// kjc will get pissed off if i call the .java file
|
||||
// something besides the name of the class.. so here goes
|
||||
String s = program.substring(index + "public class".length()).trim();
|
||||
index = s.indexOf(' ');
|
||||
name = s.substring(0, index);
|
||||
tempClass = name;
|
||||
|
||||
// and we're running inside
|
||||
if (kjc) { // if running inside processing...
|
||||
index = program.indexOf(EXTENDS); // ...and extends BApplet
|
||||
if (index != -1) { // just extends object
|
||||
String left = program.substring(0, index);
|
||||
String right = program.substring(index + EXTENDS.length());
|
||||
// replace with 'extends KjcApplet'
|
||||
program = left + ((usingExternal) ? EXTENDS : EXTENDS_KJC) + right;
|
||||
}
|
||||
}
|
||||
}
|
||||
tempFilename = name + ".java";
|
||||
tempClassFilename = name + ".class";
|
||||
|
||||
PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(buildPath + File.separator + tempFilename))));
|
||||
|
||||
//String eol = System.getProperties().getProperty("line.separator");
|
||||
|
||||
if (programType < ADVANCED) {
|
||||
// spew out a bunch of java imports
|
||||
if (kjc) { // if running in environment, or exporting an app
|
||||
for (int i = 0; i < application_imports.length; i++) {
|
||||
writer.print("import " + application_imports[i] + ".*; ");
|
||||
}
|
||||
|
||||
} else { // exporting an applet
|
||||
for (int i = 0; i < applet_imports.length; i++) {
|
||||
writer.println("import " + applet_imports[i] + ".*; ");
|
||||
//writer.print("import " + applet_imports[i] + ".*; ");
|
||||
//if (!kjc) writer.println();
|
||||
}
|
||||
}
|
||||
|
||||
// add serial if running inside pde
|
||||
//if (kjc) writer.print("import javax.comm.*;");
|
||||
if (!kjc) writer.println();
|
||||
|
||||
writer.print("public class " + name + " extends " +
|
||||
((kjc && !usingExternal) ?
|
||||
"KjcApplet" : "BApplet") + " {");
|
||||
}
|
||||
if (programType == BEGINNER) {
|
||||
if (!kjc) writer.println();
|
||||
|
||||
// hack so that the regexp below works
|
||||
//if (program.indexOf("size(") == 0) program = " " + program;
|
||||
if ((program.indexOf("size(") == 0) ||
|
||||
(program.indexOf("background(") == 0)) {
|
||||
program = " " + program;
|
||||
}
|
||||
|
||||
|
||||
PatternMatcher matcher = null;
|
||||
PatternCompiler compiler = null;
|
||||
Pattern pattern = null;
|
||||
Perl5Substitution subst = null;
|
||||
PatternMatcherInput input = null;
|
||||
|
||||
|
||||
///////// grab (first) reference to size()
|
||||
|
||||
|
||||
matcher = new Perl5Matcher();
|
||||
compiler = new Perl5Compiler();
|
||||
try {
|
||||
pattern =
|
||||
compiler.compile("[\\s\\;](size\\(\\s*\\d+,\\s*\\d+\\s*\\);)");
|
||||
//compiler.compile("^([^A-Za-z0-9_]+)(size\\(\\s*\\d+,\\s*\\d+\\s*\\);)");
|
||||
|
||||
} catch (MalformedPatternException e){
|
||||
e.printStackTrace();
|
||||
//System.err.println("Bad pattern.");
|
||||
//System.err.println(e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
String sizeInfo = null;
|
||||
input = new PatternMatcherInput(program);
|
||||
if (matcher.contains(input, pattern)) {
|
||||
MatchResult result = matcher.getMatch();
|
||||
//int wide = Integer.parseInt(result.group(1).toString());
|
||||
//int high = Integer.parseInt(result.group(2).toString());
|
||||
//sizeInfo = "void setup() { " + result.group(0) + " } ";
|
||||
sizeInfo = result.group(0);
|
||||
|
||||
} else {
|
||||
// no size() defined, make it default
|
||||
sizeInfo = "size(" + BApplet.DEFAULT_WIDTH + ", " +
|
||||
BApplet.DEFAULT_HEIGHT + "); ";
|
||||
}
|
||||
|
||||
|
||||
// remove references to size()
|
||||
// this winds up removing every reference to size()
|
||||
// not really intended, but will help things work
|
||||
|
||||
subst = new Perl5Substitution("", Perl5Substitution.INTERPOLATE_ALL);
|
||||
//subst = new Perl5Substitution("$1", Perl5Substitution.INTERPOLATE_ALL);
|
||||
program = Util.substitute(matcher, pattern, subst, program,
|
||||
Util.SUBSTITUTE_ALL);
|
||||
|
||||
|
||||
/////////// grab (first) reference to background()
|
||||
|
||||
matcher = new Perl5Matcher();
|
||||
compiler = new Perl5Compiler();
|
||||
try {
|
||||
pattern =
|
||||
compiler.compile("[\\s\\;](background\\(.*\\);)");
|
||||
//[\\s\\;]
|
||||
//compiler.compile("([^A-Za-z0-9_]+)(background\\(.*\\);)");
|
||||
|
||||
} catch (MalformedPatternException e){
|
||||
//System.err.println("Bad pattern.");
|
||||
//System.err.println(e.getMessage());
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
String backgroundInfo = "";
|
||||
input = new PatternMatcherInput(program);
|
||||
if (matcher.contains(input, pattern)) {
|
||||
MatchResult result = matcher.getMatch();
|
||||
//int wide = Integer.parseInt(result.group(1).toString());
|
||||
//int high = Integer.parseInt(result.group(2).toString());
|
||||
//sizeInfo = "void setup() { " + result.group(0) + " } ";
|
||||
backgroundInfo = result.group(0);
|
||||
|
||||
//} else {
|
||||
// no size() defined, make it default
|
||||
//sizeInfo = "size(" + BApplet.DEFAULT_WIDTH + ", " +
|
||||
//BApplet.DEFAULT_HEIGHT + "); ";
|
||||
}
|
||||
|
||||
// remove references to size()
|
||||
// this winds up removing every reference to size()
|
||||
// not really intended, but will help things work
|
||||
subst = new Perl5Substitution("", Perl5Substitution.INTERPOLATE_ALL);
|
||||
//subst = new Perl5Substitution("$1", Perl5Substitution.INTERPOLATE_ALL);
|
||||
program = Util.substitute(matcher, pattern, subst, program,
|
||||
Util.SUBSTITUTE_ALL);
|
||||
|
||||
|
||||
//////// spew out the size and background info
|
||||
|
||||
writer.print("void setup() { ");
|
||||
writer.print(sizeInfo);
|
||||
writer.print(backgroundInfo);
|
||||
writer.print("} ");
|
||||
writer.print("void draw() {");
|
||||
}
|
||||
|
||||
// decode comments to bring them back
|
||||
program = commentsCodec(program /*, false*/);
|
||||
|
||||
// spew the actual program
|
||||
// this should really add extra indents,
|
||||
// especially when not in kjc mode (!kjc == export)
|
||||
|
||||
// things will be one line off if there's an error in the code
|
||||
if (!kjc) writer.println();
|
||||
|
||||
writer.println(program);
|
||||
//System.out.println(program);
|
||||
|
||||
if (programType == BEGINNER) {
|
||||
writer.println("}");
|
||||
}
|
||||
if (programType < ADVANCED) {
|
||||
writer.print("}");
|
||||
}
|
||||
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
protected String commentsCodec(String program /*, boolean encode*/) {
|
||||
// need to preprocess class to remove comments
|
||||
// so tthat they don't fool this crappy parsing below
|
||||
char p[] = program.toCharArray();
|
||||
char lastp = 0;
|
||||
boolean insideComment = false;
|
||||
boolean eolComment = false;
|
||||
boolean slash = false;
|
||||
boolean insideQuote = false;
|
||||
for (int i = 0; i < p.length; i++) {
|
||||
if (insideComment) {
|
||||
if (eolComment &&
|
||||
((p[i] == '\r') || (p[i] == '\n'))) {
|
||||
insideComment = false;
|
||||
slash = false;
|
||||
|
||||
} else if (!eolComment &&
|
||||
(p[i] == '*') &&
|
||||
(i != (p.length-1)) &&
|
||||
(p[i+1] == '/')) {
|
||||
insideComment = false;
|
||||
slash = false;
|
||||
|
||||
} else {
|
||||
//if ((p[i] > 32) && (p[i] < 127)) {
|
||||
if ((p[i] >= 48) && (p[i] < 128)) {
|
||||
p[i] = rotateTable[p[i]];
|
||||
//p[i] = encode ? encodeTable[p[i]] : decodeTable[p[i]];
|
||||
}
|
||||
//p[i] = ' ';
|
||||
}
|
||||
} else { // not yet inside a comment
|
||||
if (insideQuote) {
|
||||
if ((p[i] == '\"') && (lastp != '\\')) {
|
||||
insideQuote = !insideQuote;
|
||||
} else {
|
||||
if ((p[i] >= 48) && (p[i] < 128)) {
|
||||
p[i] = rotateTable[p[i]];
|
||||
//p[i] = encode ? encodeTable[p[i]] : decodeTable[p[i]];
|
||||
}
|
||||
}
|
||||
|
||||
} else { // not inside a quote
|
||||
if (p[i] == '/') {
|
||||
if (slash) {
|
||||
insideComment = true;
|
||||
eolComment = true;
|
||||
} else {
|
||||
slash = true;
|
||||
}
|
||||
} else if (p[i] == '\"') {
|
||||
if (lastp != '\\') insideQuote = !insideQuote;
|
||||
|
||||
} else if (p[i] == '*') {
|
||||
if (slash) {
|
||||
insideComment = true;
|
||||
eolComment = false;
|
||||
}
|
||||
} else {
|
||||
slash = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
lastp = p[i];
|
||||
}
|
||||
//System.out.println(new String(p));
|
||||
return new String(p);
|
||||
}
|
||||
|
||||
protected String substipoot(String what, String incoming, String outgoing) {
|
||||
PatternMatcher matcher = new Perl5Matcher();
|
||||
PatternCompiler compiler = new Perl5Compiler();
|
||||
Pattern pattern = null;
|
||||
|
||||
try {
|
||||
pattern = compiler.compile(incoming);
|
||||
|
||||
} catch (MalformedPatternException e){
|
||||
System.err.println("Bad pattern.");
|
||||
System.err.println(e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
Perl5Substitution subst =
|
||||
new Perl5Substitution(outgoing, Perl5Substitution.INTERPOLATE_ALL);
|
||||
return Util.substitute(matcher, pattern, subst, what,
|
||||
Util.SUBSTITUTE_ALL);
|
||||
}
|
||||
|
||||
|
||||
//static char encodeTable[] = new char[127];
|
||||
//static char decodeTable[] = new char[127];
|
||||
static char rotateTable[] = new char[128];
|
||||
static {
|
||||
for (int i = 0; i < 80; i++) {
|
||||
rotateTable[i+48] = (char) (48 + ((i + 40) % 80));
|
||||
}
|
||||
|
||||
/*
|
||||
int rot = (123 - 65) / 2;
|
||||
for (int i = 65; i < 123; i++) {
|
||||
rotateTable[i] = (char) (((i - 65 + rot) % (rot*2)) + 65); // : (char)i;
|
||||
}
|
||||
*/
|
||||
|
||||
//for (int i = 33; i < 127; i++) {
|
||||
//rotateTable[i] = //Character.isAlpha((char)i) ?
|
||||
//(char) (((i - 33 + rot) % 94) + 33) : (char)i;
|
||||
|
||||
//encodeTable[i] = (char) (i+1);
|
||||
//decodeTable[i] = (char) (i-1);
|
||||
//encodeTable[i] = (char) (((i - 33 + rot) % 94) + 33);
|
||||
//decodeTable[i] = encodeTable[i];
|
||||
//encodeTable[i] = (char) (((i - 33 + rot) % 94) + 33);
|
||||
//decodeTable[i] = (char) (((i + 33 + rot) % 94) + 33);
|
||||
//System.out.println((int) decodeTable[i]);
|
||||
//}
|
||||
}
|
||||
}
|
||||
332
app/PdeRuntime.java
Normal file
332
app/PdeRuntime.java
Normal file
@@ -0,0 +1,332 @@
|
||||
// -*- Mode: JDE; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
|
||||
import java.awt.*; // for window
|
||||
import java.awt.event.*; // also for window
|
||||
import java.io.*;
|
||||
|
||||
// Runs the compiled java applet.
|
||||
//
|
||||
public class PdeRuntime implements PdeMessageConsumer {
|
||||
|
||||
Process process;
|
||||
KjcApplet applet;
|
||||
PdeException exception;
|
||||
Window window;
|
||||
PdeEditor editor;
|
||||
PrintStream leechErr;
|
||||
String className;
|
||||
|
||||
boolean newMessage;
|
||||
int messageLineCount;
|
||||
|
||||
public PdeRuntime(PdeEditor editor, String className) {
|
||||
this.editor = editor;
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
public void start(Point windowLocation, PrintStream leechErr)
|
||||
throws PdeException {
|
||||
|
||||
this.leechErr = leechErr;
|
||||
|
||||
Frame frame = PdeBase.frame;
|
||||
Point parentLoc = frame.getLocation();
|
||||
Insets parentInsets = frame.getInsets();
|
||||
|
||||
int x1 = parentLoc.x - 20;
|
||||
int y1 = parentLoc.y;
|
||||
|
||||
try {
|
||||
if (PdeBase.getBoolean("play.external", false)) {
|
||||
String cmd = PdeBase.get("play.external.command");
|
||||
// "cmd /c " + not helpful?
|
||||
process = Runtime.getRuntime().exec(cmd + " " + className +
|
||||
" " + className +
|
||||
" " + x1 + " " + y1);
|
||||
new PdeMessageSiphon(process.getInputStream(),
|
||||
process.getErrorStream(),
|
||||
this);
|
||||
|
||||
} else {
|
||||
// temporarily disabled
|
||||
//KjcClassLoader loader = new KjcClassLoader(buildPath);
|
||||
//Class c = loader.loadClass(tempClass);
|
||||
Class c = Class.forName(className);
|
||||
|
||||
//try {
|
||||
applet = (KjcApplet) c.newInstance();
|
||||
//} catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
//}
|
||||
//System.out.println(c + " " + applet);
|
||||
//((KjcApplet)applet).errStream = leechErr;
|
||||
applet.setRuntime(this);
|
||||
// has to be before init
|
||||
applet.serialProperties(PdeBase.properties);
|
||||
applet.init();
|
||||
if (applet.exception != null) {
|
||||
if (applet.exception instanceof javax.comm.PortInUseException) {
|
||||
throw new PdeException("Another program is already " +
|
||||
"using the serial port.");
|
||||
} else {
|
||||
throw new PdeException(applet.exception.getMessage());
|
||||
}
|
||||
}
|
||||
applet.start();
|
||||
|
||||
if (editor.presenting) {
|
||||
window = new Window(new Frame());
|
||||
window.addKeyListener(new KeyAdapter() {
|
||||
public void keyPressed(KeyEvent e) {
|
||||
//System.out.println("window got " + e);
|
||||
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
|
||||
//editor.doClose();
|
||||
//new DelayedClose(editor);
|
||||
stop();
|
||||
editor.doClose();
|
||||
}
|
||||
}
|
||||
});
|
||||
/*
|
||||
window.addFocusListener(new FocusAdapter() {
|
||||
public void focusLost(FocusEvent e) {
|
||||
System.out.println(e);
|
||||
window.toFront();
|
||||
}});
|
||||
*/
|
||||
|
||||
} else {
|
||||
window = new Frame(editor.sketchName); // gonna use ugly windows instead
|
||||
((Frame)window).setResizable(false);
|
||||
if (PdeBase.icon != null) ((Frame)window).setIconImage(PdeBase.icon);
|
||||
window.pack(); // to get a peer, size set later, need for insets
|
||||
|
||||
window.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
stop();
|
||||
editor.doClose();
|
||||
//new DelayedClose(editor);
|
||||
//editor.doClose();
|
||||
//editor.doStop();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!(window instanceof Frame)) y1 += parentInsets.top;
|
||||
window.add(applet);
|
||||
|
||||
applet.addKeyListener(new KeyAdapter() {
|
||||
public void keyPressed(KeyEvent e) {
|
||||
//System.out.println("applet got " + e);
|
||||
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
|
||||
stop();
|
||||
editor.doClose();
|
||||
//new DelayedClose(editor);
|
||||
//editor.doClose();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// @#$((* java 1.3
|
||||
// removed because didn't seem to be needed anymore
|
||||
// also, was causing offset troubles
|
||||
/*
|
||||
window.addMouseListener(applet);
|
||||
window.addMouseMotionListener(applet);
|
||||
window.addKeyListener(applet);
|
||||
*/
|
||||
|
||||
Dimension screen =
|
||||
Toolkit.getDefaultToolkit().getScreenSize();
|
||||
|
||||
//System.out.println(SystemColor.windowBorder.toString());
|
||||
|
||||
//window.setLayout(new BorderLayout());
|
||||
window.setLayout(null);
|
||||
if (editor.presenting) {
|
||||
window.setBounds((screen.width - applet.width) / 2,
|
||||
(screen.height - applet.height) / 2,
|
||||
applet.width, applet.height);
|
||||
applet.setBounds(0, 0, applet.width, applet.height);
|
||||
|
||||
} else {
|
||||
Insets insets = window.getInsets();
|
||||
//System.out.println(insets);
|
||||
int mw = PdeBase.getInteger("run.window.width.minimum", 120);
|
||||
int mh = PdeBase.getInteger("run.window.height.minimum", 120);
|
||||
int ww = Math.max(applet.width, mw) + insets.left + insets.right;
|
||||
int wh = Math.max(applet.height, mh) + insets.top + insets.bottom;
|
||||
if (x1 - ww > 10) { // if it fits to the left of the window
|
||||
window.setBounds(x1 - ww, y1, ww, wh);
|
||||
|
||||
} else { // if it fits inside the editor window
|
||||
x1 = parentLoc.x + PdeEditor.GRID_SIZE * 2;
|
||||
y1 = parentLoc.y + PdeEditor.GRID_SIZE * 2;
|
||||
|
||||
if ((x1 + ww > screen.width - PdeEditor.GRID_SIZE) ||
|
||||
(y1 + wh > screen.height - PdeEditor.GRID_SIZE)) {
|
||||
// otherwise center on screen
|
||||
x1 = (screen.width - ww) / 2;
|
||||
y1 = (screen.height - wh) / 2;
|
||||
}
|
||||
window.setBounds(x1, y1, ww, wh);
|
||||
}
|
||||
|
||||
Color windowBgColor =
|
||||
PdeBase.getColor("run.window.bgcolor", SystemColor.control);
|
||||
//new Color(102, 102, 102));
|
||||
window.setBackground(windowBgColor);
|
||||
//window.setBackground(SystemColor.windowBorder);
|
||||
//window.setBackground(SystemColor.control);
|
||||
|
||||
applet.setBounds((ww - applet.width)/2,
|
||||
insets.top + ((wh-insets.top-insets.bottom) -
|
||||
applet.height)/2, ww, wh);
|
||||
}
|
||||
|
||||
applet.setVisible(true); // no effect
|
||||
if (windowLocation != null) {
|
||||
window.setLocation(windowLocation);
|
||||
}
|
||||
window.show();
|
||||
applet.requestFocus(); // necessary for key events
|
||||
}
|
||||
//System.out.println("KJC RUNNING");
|
||||
|
||||
//need to parse this code to give a decent error message
|
||||
//internal error
|
||||
//java.lang.NullPointerException
|
||||
// at ProcessingApplet.colorMode(ProcessingApplet.java:652)
|
||||
// at Temporary_203_1176.setup(Temporary_203_1176.java:3)
|
||||
|
||||
} catch (Exception e) {
|
||||
// this will pass through to the first part of message
|
||||
// this handles errors that happen inside setup()
|
||||
newMessage = true;
|
||||
e.printStackTrace(this.leechErr);
|
||||
//if (exception != null) throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
//System.out.println();
|
||||
//System.out.println("* stopping");
|
||||
|
||||
// in case stop is called during compilation
|
||||
if (applet != null) applet.stop();
|
||||
//if (window != null) window.hide();
|
||||
|
||||
// above avoids NullPointerExceptions
|
||||
// but still threading is too complex, and so
|
||||
// some boogers are being left behind
|
||||
|
||||
applet = null;
|
||||
//window = null;
|
||||
|
||||
if (process != null) { // running externally
|
||||
//System.out.println("killing external process");
|
||||
//process.destroy();
|
||||
|
||||
//System.out.println("cutting umbilical cord");
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream("die");
|
||||
fos.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//try {
|
||||
//umbilical.close();
|
||||
//umbilical = null;
|
||||
//} catch (IOException e) {
|
||||
//e.printStackTrace();w
|
||||
//}
|
||||
}
|
||||
|
||||
//System.gc();
|
||||
//System.out.println("* stopped");
|
||||
|
||||
//System.out.println("thread count: " + Thread.activeCount());
|
||||
//System.out.println();
|
||||
//System.out.println();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
//if (window != null) window.hide();
|
||||
if (window != null) {
|
||||
//System.err.println("disposing window");
|
||||
window.dispose();
|
||||
window = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void message(String s) {
|
||||
|
||||
//if (s.indexOf("MAKE WAY") != -1) {
|
||||
//System.out.println("new message coming");
|
||||
//newMessage = true;
|
||||
|
||||
//} else {
|
||||
if (newMessage) {
|
||||
//System.out.println("making msg of " + s);
|
||||
exception = new PdeException(s); // type of java ex
|
||||
//System.out.println("setting ex type to " + s);
|
||||
newMessage = false;
|
||||
messageLineCount = 0;
|
||||
|
||||
} else {
|
||||
messageLineCount++;
|
||||
|
||||
int index = s.indexOf(className + ".java");
|
||||
//System.out.println("> " + index + " " + s);
|
||||
if (index != -1) {
|
||||
int len = (className + ".java").length();
|
||||
String lineNumberStr = s.substring(index + len + 1);
|
||||
index = lineNumberStr.indexOf(')');
|
||||
lineNumberStr = lineNumberStr.substring(0, index);
|
||||
//System.err.println("error line is: " + lineNumberStr);
|
||||
try {
|
||||
exception.line = Integer.parseInt(lineNumberStr) - 1; //2;
|
||||
//System.out.println("exception in RUNNING");
|
||||
editor.error(exception);
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} else if ((index = s.indexOf(className + ".class")) != -1) {
|
||||
// code to check for:
|
||||
// at Temporary_484_3845.loop(Compiled Code)
|
||||
// would also probably get:
|
||||
// at Temporary_484_3845.loop
|
||||
// which (i believe) is used by the mac and/or jview
|
||||
String functionStr = s.substring(index +
|
||||
(className + ".class").length() + 1);
|
||||
index = functionStr.indexOf('(');
|
||||
if (index != -1) {
|
||||
functionStr = functionStr.substring(0, index);
|
||||
}
|
||||
exception = new PdeException(//"inside \"" + functionStr + "()\": " +
|
||||
exception.getMessage() +
|
||||
" inside " + functionStr + "() " +
|
||||
"[add Compiler.disable() to setup()]");
|
||||
editor.error(exception);
|
||||
// this will fall through in tihs example:
|
||||
// at Temporary_4636_9696.pootie(Compiled Code)
|
||||
// at Temporary_4636_9696.loop(Temporary_4636_9696.java:24)
|
||||
// because pootie() (re)sets the exception title
|
||||
// and throws it, but then the line number gets set
|
||||
// because of the line that comes after
|
||||
|
||||
} else if (messageLineCount > 5) {
|
||||
// this means the class name may not be mentioned
|
||||
// in the stack trace.. this is just a general purpose
|
||||
// error, but needs to make it through anyway.
|
||||
// so if five lines have gone past, might as well signal
|
||||
|
||||
//System.out.println("signalling");
|
||||
messageLineCount = -100;
|
||||
exception = new PdeException(exception.getMessage());
|
||||
editor.error(exception);
|
||||
}
|
||||
//System.out.println("got it " + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user