1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-23 19:21:59 +03:00

Syncing with Processing 1.0.9 (revision 5766).

This commit is contained in:
David A. Mellis
2009-10-22 00:56:16 +00:00
parent 7f58e2213e
commit 2e26a2d994
38 changed files with 16818 additions and 901 deletions

View File

@ -180,71 +180,7 @@ public class Base {
// setup the theme coloring fun
Theme.init();
if (Base.isMacOS()) {
String properMenuBar = "apple.laf.useScreenMenuBar";
String menubar = Preferences.get(properMenuBar);
if (menubar != null) {
// Get the current menu bar setting and use it
System.setProperty(properMenuBar, menubar);
} else {
// 10.4 is not affected, 10.5 (and prolly 10.6) are
if (System.getProperty("os.version").startsWith("10.4")) {
// Don't bother checking next time
Preferences.set(properMenuBar, "true");
// Also set the menubar now
System.setProperty(properMenuBar, "true");
} else {
// Running 10.5 or 10.6 or whatever, give 'em the business
String warning =
"<html>" +
"<head> <style type=\"text/css\">"+
"b { font: 13pt \"Lucida Grande\" }"+
"p { font: 11pt \"Lucida Grande\"; margin-top: 8px }"+
"</style> </head> <body>" +
"<b>Some menus have been disabled.</b>" +
"<p>Due to an Apple bug, the Sketchbook and Example menus " +
"are unusable. <br>" +
"As a workaround, these items will be disabled from the " +
"standard menu bar, <br>" +
"but you can use the Open button on " +
"the toolbar to access the same items. <br>" +
"If this bug makes you sad, " +
"please contact Apple via bugreporter.apple.com.</p>" +
"</body> </html>";
Object[] options = { "OK", "More Info" };
int result = JOptionPane.showOptionDialog(new Frame(),
warning,
"Menu Bar Problem",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE,
null,
options,
options[0]);
if (result == -1) {
// They hit ESC or closed the window, so just hide it for now
// But don't bother setting the preference in the file
} else {
// Shut off in the preferences for next time
//Preferences.set(properMenuBar, "false");
// For 1.0.4, we'll stick with the Apple menu bar,
// and just disable the sketchbook and examples sub-menus.
Preferences.set(properMenuBar, "true");
if (result == 1) { // More Info
Base.openURL("http://dev.processing.org/bugs/show_bug.cgi?id=786");
}
}
// Whether or not canceled, set to false (right now) if we're on 10.5
//System.setProperty(properMenuBar, "false");
// Changing this behavior for 1.0.4
System.setProperty(properMenuBar, "true");
}
}
}
// Set the look and feel before opening the window
// For 0158, moving it lower so that the apple.laf.useScreenMenuBar stuff works
try {
platform.setLookAndFeel();
} catch (Exception e) {
@ -815,7 +751,8 @@ public class Base {
*/
public boolean handleClose(Editor editor) {
// Check if modified
if (!editor.checkModified(false)) {
boolean immediate = editors.size() == 1;
if (!editor.checkModified(immediate)) {
return false;
}
@ -993,17 +930,9 @@ public class Base {
protected void rebuildSketchbookMenu(JMenu menu) {
//System.out.println("rebuilding sketchbook menu");
//new Exception().printStackTrace();
//boolean nativeButBroken = Base.isMacOS() ?
//Preferences.getBoolean("apple.laf.useScreenMenuBar") : false;
boolean nativeButBroken = false;
try {
if (nativeButBroken) { // osx workaround
menu.setEnabled(false);
} else {
menu.removeAll();
addSketches(menu, getSketchbookFolder(), false);
}
} catch (IOException e) {
e.printStackTrace();
}
@ -1045,21 +974,13 @@ public class Base {
public void rebuildExamplesMenu(JMenu menu) {
//System.out.println("rebuilding examples menu");
//boolean nativeButBroken = Base.isMacOS() ?
//Preferences.getBoolean("apple.laf.useScreenMenuBar") : false;
boolean nativeButBroken = false;
try {
if (nativeButBroken) { // osx workaround
menu.setEnabled(false);
} else {
menu.removeAll();
boolean found = addSketches(menu, examplesFolder, false);
if (found) menu.addSeparator();
found = addSketches(menu, getSketchbookLibrariesFolder(), false);
if (found) menu.addSeparator();
addSketches(menu, librariesFolder, false);
}
menu.removeAll();
boolean found = addSketches(menu, examplesFolder, false);
if (found) menu.addSeparator();
found = addSketches(menu, getSketchbookLibrariesFolder(), false);
if (found) menu.addSeparator();
addSketches(menu, librariesFolder, false);
} catch (IOException e) {
e.printStackTrace();
}
@ -1965,56 +1886,30 @@ public class Base {
* Grab the contents of a file as a string.
*/
static public String loadFile(File file) throws IOException {
return PApplet.join(PApplet.loadStrings(file), "\n");
/*
// empty code file.. no worries, might be getting filled up later
if (file.length() == 0) return "";
//FileInputStream fis = new FileInputStream(file);
//InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
//BufferedReader reader = new BufferedReader(isr);
BufferedReader reader = PApplet.createReader(file);
StringBuffer buffer = new StringBuffer();
String line = null;
while ((line = reader.readLine()) != null) {
// char[] cc = line.toCharArray();
// for (int i = 0; i < cc.length; i++) {
// char c = cc[i];
// if (c < 32 || c > 126) System.out.println("found " + c + " " + ((int) c));
// }
//
buffer.append(line);
buffer.append('\n');
String[] contents = PApplet.loadStrings(file);
if (contents == null) return null;
return PApplet.join(contents, "\n");
}
reader.close();
return buffer.toString();
*/
}
/**
* Spew the contents of a String object out to a file.
*/
static public void saveFile(String str, File file) throws IOException {
PApplet.saveStrings(file, new String[] { str });
/*
ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
InputStreamReader isr = new InputStreamReader(bis);
BufferedReader reader = new BufferedReader(isr);
FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
PrintWriter writer = new PrintWriter(osw);
String line = null;
while ((line = reader.readLine()) != null) {
writer.println(line);
File temp = File.createTempFile(file.getName(), null, file.getParentFile());
PApplet.saveStrings(temp, new String[] { str });
if (file.exists()) {
boolean result = file.delete();
if (!result) {
throw new IOException("Could not remove old version of " +
file.getAbsolutePath());
}
}
boolean result = temp.renameTo(file);
if (!result) {
throw new IOException("Could not replace " +
file.getAbsolutePath());
}
writer.flush();
writer.close();
*/
}

View File

@ -114,6 +114,9 @@ public class Editor extends JFrame implements RunnerListener {
EditorLineStatus lineStatus;
boolean newEditor = true;
JEditorPane editorPane;
JEditTextArea textarea;
EditorListener listener;
@ -229,7 +232,22 @@ public class Editor extends JFrame implements RunnerListener {
lineStatus = new EditorLineStatus(textarea);
consolePanel.add(lineStatus, BorderLayout.SOUTH);
// if (newEditor) {
// try {
// setupEditorPane();
// upper.add(editorPane);
// } catch (Exception e1) {
// PrintWriter w = PApplet.createWriter(new File("/Users/fry/Desktop/blah.txt"));
// w.println(e1.getMessage());
// e1.printStackTrace(w);
// w.flush();
// w.close();
//// e1.printStackTrace());
//// e1.printStackTrace(System.out);
// }
// } else {
upper.add(textarea);
// }
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
upper, consolePanel);
@ -345,6 +363,46 @@ public class Editor extends JFrame implements RunnerListener {
}
/*
// http://wiki.netbeans.org/DevFaqEditorCodeCompletionAnyJEditorPane
void setupEditorPane() throws IOException {
editorPane = new JEditorPane();
// This will find the Java editor kit and associate it with
// our editor pane. But that does not give us code completion
// just yet because we have no Java context (i.e. no class path, etc.).
// However, this does give us syntax coloring.
EditorKit kit = CloneableEditorSupport.getEditorKit("text/x-java");
editorPane.setEditorKit(kit);
// You can specify any ".java" file.
// If the file does not exist, it will be created.
// The contents of the file does not matter.
// The extension must be ".java", however.
// String newSourcePath = "/Users/fry/Desktop/tmp.java";
// File tmpFile = new File(newSourcePath);
// System.out.println(tmpFile.getParent() + " " + tmpFile.getName());
// FileObject fob = FileUtil.createData(tmpFile);
File tmpFile = File.createTempFile("temp", ".java");
FileObject fob = FileUtil.toFileObject(FileUtil.normalizeFile(tmpFile));
DataObject dob = DataObject.find(fob);
editorPane.getDocument().putProperty(Document.StreamDescriptionProperty, dob);
// This sets up a default class path for us so that
// we can find all the JDK classes via code completion.
DialogBinding.bindComponentToFile(fob, 0, 0, editorPane);
// Last but not least, we need to fill the editor pane with
// some initial dummy code - as it seems somehow required to
// kick-start code completion.
// A simple dummy package declaration will do.
editorPane.setText("package dummy;");
}
*/
protected void setPlacement(int[] location) {
setBounds(location[0], location[1], location[2], location[3]);
if (location[4] != 0) {
@ -859,6 +917,13 @@ public class Editor extends JFrame implements RunnerListener {
menu.add(createToolMenuItem("processing.app.tools.Archiver"));
menu.add(createToolMenuItem("processing.app.tools.FixEncoding"));
/*
//menu.add(createToolMenuItem("processing.app.tools.android.Build"));
item = createToolMenuItem("processing.app.tools.android.Build");
item.setAccelerator(KeyStroke.getKeyStroke('D', modifiers));
menu.add(item);
*/
return menu;
}

View File

@ -34,6 +34,8 @@ import processing.app.syntax.*;
import processing.core.*;
/**
* Storage class for user preferences and environment settings.
* <P>
@ -68,13 +70,6 @@ public class Preferences {
static final String PREFS_FILE = "preferences.txt";
// platform strings (used to get settings for specific platforms)
//static final String platforms[] = {
// "other", "windows", "macosx", "linux"
//};
// prompt text stuff
static final String PROMPT_YES = "Yes";
@ -97,12 +92,6 @@ public class Preferences {
* inside a static block.
*/
static public int BUTTON_HEIGHT = 24;
/*
// remove this for 0121, because quaqua takes care of it
static {
if (Base.isMacOS()) BUTTON_HEIGHT = 29;
}
*/
// value for the size bars, buttons, etc
@ -125,14 +114,12 @@ public class Preferences {
JTextField sketchbookLocationField;
JCheckBox exportSeparateBox;
JCheckBox deletePreviousBox;
// JCheckBox closingLastQuitsBox;
JCheckBox externalEditorBox;
JCheckBox memoryOverrideBox;
JTextField memoryField;
JCheckBox checkUpdatesBox;
JTextField fontSizeField;
JCheckBox autoAssociateBox;
JCheckBox menubarWorkaroundBox;
// the calling editor, so updates can be applied
@ -142,9 +129,9 @@ public class Preferences {
// data model
static HashMap<String,String> defaults;
static HashMap<String,String> table = new HashMap<String,String>();;
static HashMap<String,HashMap<String,String>> prefixes = new HashMap<String,HashMap<String,String>>();
static Hashtable defaults;
static Hashtable table = new Hashtable();;
static Hashtable prefixes = new Hashtable();
static File preferencesFile;
@ -159,8 +146,22 @@ public class Preferences {
"You'll need to reinstall Arduino.", e);
}
// check for platform-specific properties in the defaults
String platformExt = "." + PConstants.platformNames[PApplet.platform];
int platformExtLength = platformExt.length();
Enumeration e = table.keys();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
if (key.endsWith(platformExt)) {
// this is a key specific to a particular platform
String actualKey = key.substring(0, key.length() - platformExtLength);
String value = get(key);
table.put(actualKey, value);
}
}
// clone the hash table
defaults = (HashMap<String, String>) table.clone();
defaults = (Hashtable) table.clone();
// other things that have to be set explicitly for the defaults
setColor("run.window.bgcolor", SystemColor.control);
@ -197,14 +198,6 @@ public class Preferences {
" and restart Arduino.", ex);
}
}
// Theme settings always override preferences
// try {
// load(Base.getStream("theme/theme.txt"));
// } catch (Exception te) {
// Base.showError(null, "Could not read color theme settings.\n" +
// "You'll need to reinstall Processing.", te);
// }
}
try {
@ -250,43 +243,6 @@ public class Preferences {
int h, vmax;
// [ ] Quit after closing last sketch window
/*
closingLastQuitsBox =
new JCheckBox("Quit after closing last sketch window");
pain.add(closingLastQuitsBox);
d = closingLastQuitsBox.getPreferredSize();
closingLastQuitsBox.setBounds(left, top, d.width + 10, d.height);
right = Math.max(right, left + d.width);
top += d.height + GUI_BETWEEN;
*/
/*
// [ ] Prompt for name and folder when creating new sketch
sketchPromptBox =
new JCheckBox("Prompt for name when opening or creating a sketch");
pain.add(sketchPromptBox);
d = sketchPromptBox.getPreferredSize();
sketchPromptBox.setBounds(left, top, d.width + 10, d.height);
right = Math.max(right, left + d.width);
top += d.height + GUI_BETWEEN;
*/
// [ ] Delete empty sketches on Quit
/*
sketchCleanBox = new JCheckBox("Delete empty sketches on Quit");
pain.add(sketchCleanBox);
d = sketchCleanBox.getPreferredSize();
sketchCleanBox.setBounds(left, top, d.width + 10, d.height);
right = Math.max(right, left + d.width);
top += d.height + GUI_BETWEEN;
*/
// Sketchbook location:
// [...............................] [ Browse ]
@ -303,17 +259,6 @@ public class Preferences {
button = new JButton(PROMPT_BROWSE);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
/*
JFileChooser fc = new JFileChooser();
fc.setSelectedFile(new File(sketchbookLocationField.getText()));
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returned = fc.showOpenDialog(new JDialog());
if (returned == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
sketchbookLocationField.setText(file.getAbsolutePath());
}
*/
File dflt = new File(sketchbookLocationField.getText());
File file =
Base.selectFolder("Select new sketchbook location", dflt, dialog);
@ -327,13 +272,9 @@ public class Preferences {
// take max height of all components to vertically align em
vmax = Math.max(d.height, d2.height);
//label.setBounds(left, top + (vmax-d.height)/2,
// d.width, d.height);
//h = left + d.width + GUI_BETWEEN;
sketchbookLocationField.setBounds(left, top + (vmax-d.height)/2,
d.width, d.height);
h = left + d.width + GUI_SMALL; //GUI_BETWEEN;
h = left + d.width + GUI_SMALL;
button.setBounds(h, top + (vmax-d2.height)/2,
d2.width, d2.height);
@ -402,22 +343,6 @@ public class Preferences {
}
// [ ] Place menu bar inside
if (Base.isMacOS()) {
if (System.getProperty("os.version").startsWith("10.5")) {
menubarWorkaroundBox =
new JCheckBox("Place menus inside editor window to avoid " +
"Apple Java bug (requires restart)");
pain.add(menubarWorkaroundBox);
d = menubarWorkaroundBox.getPreferredSize();
menubarWorkaroundBox.setBounds(left, top, d.width + 10, d.height);
right = Math.max(right, left + d.width);
top += d.height + GUI_BETWEEN;
}
}
// More preferences are in the ...
label = new JLabel("More preferences can be edited directly in the file");
@ -491,7 +416,6 @@ public class Preferences {
wide = right + GUI_BIG;
high = top + GUI_SMALL;
//setSize(wide, high);
// closing the window is same as hitting cancel button
@ -535,26 +459,6 @@ public class Preferences {
}
/*
protected JRootPane createRootPane() {
System.out.println("creating root pane esc received");
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
//setVisible(false);
System.out.println("esc received");
}
};
JRootPane rootPane = new JRootPane();
KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
rootPane.registerKeyboardAction(actionListener, stroke,
JComponent.WHEN_IN_FOCUSED_WINDOW);
return rootPane;
}
*/
public Dimension getPreferredSize() {
return new Dimension(wide, high);
}
@ -624,11 +528,6 @@ public class Preferences {
autoAssociateBox.isSelected());
}
if (menubarWorkaroundBox != null) {
setBoolean("apple.laf.useScreenMenuBar",
!menubarWorkaroundBox.isSelected());
}
editor.applyPreferences();
}
@ -659,11 +558,6 @@ public class Preferences {
setSelected(getBoolean("platform.auto_file_type_associations"));
}
if (menubarWorkaroundBox != null) {
menubarWorkaroundBox.
setSelected(!getBoolean("apple.laf.useScreenMenuBar"));
}
dialog.setVisible(true);
}
@ -676,16 +570,12 @@ public class Preferences {
}
static protected void load(InputStream input, String prefix) throws IOException {
LinkedHashMap<String,String> table = new LinkedHashMap<String,String>();
LinkedHashMap table = new LinkedHashMap();
prefixes.put(prefix, table);
load(input, table);
}
static protected void load(InputStream input, Map table) throws IOException {
// check for platform-specific properties in the defaults
String platformExt = "." + PConstants.platformNames[PApplet.platform];
int platformExtLength = platformExt.length();
String[] lines = PApplet.loadStrings(input); // Reads as UTF-8
for (String line : lines) {
if ((line.length() == 0) ||
@ -695,12 +585,6 @@ public class Preferences {
int equals = line.indexOf('=');
if (equals != -1) {
String key = line.substring(0, equals).trim();
// check if this is a platform-specific key, and if so, shave things
if (key.endsWith(platformExt)) {
// this is a key specific to this platform
key = key.substring(0, key.length() - platformExtLength);
}
String value = line.substring(equals + 1).trim();
table.put(key, value);
}
@ -721,8 +605,10 @@ public class Preferences {
// Fix for 0163 to properly use Unicode when writing preferences.txt
PrintWriter writer = PApplet.createWriter(preferencesFile);
for (String key : table.keySet()) {
writer.println(key + "=" + table.get(key));
Enumeration e = table.keys(); //properties.propertyNames();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
writer.println(key + "=" + ((String) table.get(key)));
}
writer.flush();
@ -748,15 +634,15 @@ public class Preferences {
// preference files, look up the attribute in that file's Hashtable
// (don't override with or fallback to the main file). otherwise,
// look up the attribute in the main file's Hashtable.
HashMap<String,String> table = Preferences.table;
Map table = Preferences.table;
if (attribute.indexOf('.') != -1) {
String prefix = attribute.substring(0, attribute.indexOf('.'));
if (prefixes.containsKey(prefix)) {
table = prefixes.get(prefix);
table = (Map) prefixes.get(prefix);
attribute = attribute.substring(attribute.indexOf('.') + 1);
}
}
return table.get(attribute);
return (String) table.get(attribute);
/*
//String value = (properties != null) ?
//properties.getProperty(attribute) : applet.getParameter(attribute);
@ -791,7 +677,7 @@ public class Preferences {
static public String getDefault(String attribute) {
return defaults.get(attribute);
return (String) defaults.get(attribute);
}

View File

@ -233,11 +233,12 @@ public class Sketch {
ensureExistence();
// add file to the code/codeCount list, resort the list
if (codeCount == code.length) {
//if (codeCount == code.length) {
code = (SketchCode[]) PApplet.append(code, newCode);
codeCount++;
//}
//code[codeCount++] = newCode;
}
code[codeCount++] = newCode;
}
protected void sortCode() {
@ -390,7 +391,7 @@ public class Sketch {
// Make sure no .pde *and* no .java files with the same name already exist
// http://dev.processing.org/bugs/show_bug.cgi?id=543
for (SketchCode c : code) {
if (sanitaryName.equals(c.getPrettyName())) {
if (sanitaryName.equalsIgnoreCase(c.getPrettyName())) {
Base.showMessage("Nope",
"A file named \"" + c.getFileName() + "\" already exists\n" +
"in \"" + folder.getAbsolutePath() + "\"");
@ -599,6 +600,7 @@ public class Sketch {
code[j] = code[j+1];
}
codeCount--;
code = (SketchCode[]) PApplet.shorten(code);
return;
}
}
@ -759,7 +761,7 @@ public class Sketch {
// but ignore this situation for the first tab, since it's probably being
// resaved (with the same name) to another location/folder.
for (int i = 1; i < codeCount; i++) {
if (newName.equals(code[i].getPrettyName())) {
if (newName.equalsIgnoreCase(code[i].getPrettyName())) {
Base.showMessage("Nope",
"You can't save the sketch as \"" + newName + "\"\n" +
"because the sketch already has a tab with that name.");
@ -1198,6 +1200,10 @@ public class Sketch {
* @return null if compilation failed, main class name if not
*/
public String preprocess(String buildPath, Target target) throws RunnerException {
return preprocess(buildPath, new PdePreprocessor(), target);
}
public String preprocess(String buildPath, PdePreprocessor preprocessor, Target target) throws RunnerException {
// make sure the user didn't hide the sketch folder
ensureExistence();
@ -1268,7 +1274,18 @@ public class Sketch {
// Note that the headerOffset isn't applied until compile and run, because
// it only applies to the code after it's been written to the .java file.
int headerOffset = 0;
PdePreprocessor preprocessor = new PdePreprocessor();
//PdePreprocessor preprocessor = new PdePreprocessor();
try {
headerOffset = preprocessor.writePrefix(bigCode.toString(),
buildPath,
name,
codeFolderPackages,
target);
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
String msg = "Build folder disappeared or could not be written";
throw new RunnerException(msg);
}
// 2. run preproc on that code using the sugg class name
// to create a single .java file and write to buildpath
@ -1278,12 +1295,7 @@ public class Sketch {
try {
// if (i != 0) preproc will fail if a pde file is not
// java mode, since that's required
String className = preprocessor.write(bigCode.toString(),
buildPath,
name,
codeFolderPackages,
target);
headerOffset = preprocessor.headerCount + preprocessor.prototypeCount;
String className = preprocessor.write();
if (className == null) {
throw new RunnerException("Could not find main class");

View File

@ -385,9 +385,15 @@ public class Runner implements MessageConsumer {
commandArgs =
"java -Xrunjdwp:transport=dt_shmem,address=" + addr + ",suspend=y ";
} else if (Base.isMacOS()) {
if (System.getProperty("os.version").startsWith("10.4")) {
// -d32 not understood by 10.4 (and not needed)
commandArgs =
"java -Xrunjdwp:transport=dt_socket,address=" + addr + ",suspend=y ";
} else {
commandArgs =
"java -d32 -Xrunjdwp:transport=dt_socket,address=" + addr + ",suspend=y ";
}
}
for (int i = 0; i < vmParams.length; i++) {
commandArgs = addArgument(commandArgs, vmParams[i], ' ');

View File

@ -48,6 +48,7 @@ public class Platform extends processing.app.Platform {
public void init(Base base) {
System.setProperty("apple.laf.useScreenMenuBar", "true");
ThinkDifferent.init(base);
/*
try {
@ -129,6 +130,7 @@ public class Platform extends processing.app.Platform {
}
*/
}
// for Java 1.6, replace with java.awt.Desktop.browse() and java.awt.Desktop.open()
com.apple.eio.FileManager.openURL(url);
}

View File

@ -34,58 +34,222 @@ import processing.app.debug.Target;
import processing.core.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import antlr.*;
import antlr.collections.*;
import antlr.collections.impl.*;
import java.util.*;
import com.oroinc.text.regex.*;
/**
* Class that orchestrates preprocessing p5 syntax into straight Java.
*/
public class PdePreprocessor {
static final int JDK11 = 0;
static final int JDK13 = 1;
static final int JDK14 = 2;
//static String defaultImports[][] = new String[3][];
// these ones have the .* at the end, since a class name
// might be at the end instead of .* whcih would make trouble
// other classes using this can lop of the . and anything after
// it to produce a package name consistently.
//public String extraImports[];
ArrayList<String> programImports;
static public final int STATIC = 0; // formerly BEGINNER
static public final int ACTIVE = 1; // formerly INTERMEDIATE
static public final int JAVA = 2; // formerly ADVANCED
// static to make it easier for the antlr preproc to get at it
static public int programType = -1;
Reader programReader;
String buildPath;
// stores number of built user-defined function prototypes
public int prototypeCount = 0;
// stores number of included library headers written
// we always write one header: WProgram.h
public int headerCount = 1;
/**
* These may change in-between (if the prefs panel adds this option)
* so grab them here on construction.
*/
public PdePreprocessor() {}
/**
* Used by PdeEmitter.dumpHiddenTokens()
*/
//public static TokenStreamCopyingHiddenTokenFilter filter;
Target target;
List prototypes;
String[] defaultImports;
// these ones have the .* at the end, since a class name might be at the end
// instead of .* which would make trouble other classes using this can lop
// off the . and anything after it to produce a package name consistently.
//public String extraImports[];
ArrayList<String> programImports;
// imports just from the code folder, treated differently
// than the others, since the imports are auto-generated.
ArrayList<String> codeFolderImports;
String indent;
PrintStream stream;
String program;
String buildPath;
String name;
/**
* Setup a new preprocessor.
*/
public PdePreprocessor() { }
public int writePrefix(String program, String buildPath,
String name, String codeFolderPackages[],
Target target)
throws FileNotFoundException {
this.buildPath = buildPath;
this.name = name;
this.target = target;
int tabSize = Preferences.getInteger("editor.tabs.size");
char[] indentChars = new char[tabSize];
Arrays.fill(indentChars, ' ');
indent = new String(indentChars);
// if the program ends with no CR or LF an OutOfMemoryError will happen.
// not gonna track down the bug now, so here's a hack for it:
// http://dev.processing.org/bugs/show_bug.cgi?id=5
program += "\n";
// if the program ends with an unterminated multi-line comment,
// an OutOfMemoryError or NullPointerException will happen.
// again, not gonna bother tracking this down, but here's a hack.
// http://dev.processing.org/bugs/show_bug.cgi?id=16
Sketch.scrubComments(program);
// this returns the scrubbed version, but more important for this
// function, it'll check to see if there are errors with the comments.
if (Preferences.getBoolean("preproc.substitute_unicode")) {
// check for non-ascii chars (these will be/must be in unicode format)
char p[] = program.toCharArray();
int unicodeCount = 0;
for (int i = 0; i < p.length; i++) {
if (p[i] > 127) unicodeCount++;
}
// if non-ascii chars are in there, convert to unicode escapes
if (unicodeCount != 0) {
// add unicodeCount * 5.. replacing each unicode char
// with six digit uXXXX sequence (xxxx is in hex)
// (except for nbsp chars which will be a replaced with a space)
int index = 0;
char p2[] = new char[p.length + unicodeCount*5];
for (int i = 0; i < p.length; i++) {
if (p[i] < 128) {
p2[index++] = p[i];
} else if (p[i] == 160) { // unicode for non-breaking space
p2[index++] = ' ';
} else {
int c = p[i];
p2[index++] = '\\';
p2[index++] = 'u';
char str[] = Integer.toHexString(c).toCharArray();
// add leading zeros, so that the length is 4
//for (int i = 0; i < 4 - str.length; i++) p2[index++] = '0';
for (int m = 0; m < 4 - str.length; m++) p2[index++] = '0';
System.arraycopy(str, 0, p2, index, str.length);
index += str.length;
}
}
program = new String(p2, 0, index);
}
}
// These may change in-between (if the prefs panel adds this option)
// so grab them here on construction.
String prefsLine = Preferences.get("preproc.imports");
defaultImports = PApplet.splitTokens(prefsLine, ", ");
//String importRegexp = "(?:^|\\s|;)(import\\s+)(\\S+)(\\s*;)";
String importRegexp = "^\\s*#include\\s+[<\"](\\S+)[\">]";
programImports = new ArrayList<String>();
String[][] pieces = PApplet.matchAll(program, importRegexp);
if (pieces != null)
for (int i = 0; i < pieces.length; i++)
programImports.add(pieces[i][1]); // the package name
codeFolderImports = new ArrayList<String>();
// if (codeFolderPackages != null) {
// for (String item : codeFolderPackages) {
// codeFolderImports.add(item + ".*");
// }
// }
prototypes = new ArrayList();
try {
prototypes = prototypes(program);
} catch (MalformedPatternException e) {
System.out.println("Internal error while pre-processing; " +
"not generating function prototypes.\n\n" + e);
}
// store # of prototypes so that line number reporting can be adjusted
prototypeCount = prototypes.size();
// do this after the program gets re-combobulated
this.program = program;
// output the code
File streamFile = new File(buildPath, name + ".cpp");
stream = new PrintStream(new FileOutputStream(streamFile));
return headerCount + prototypeCount;
}
/**
* preprocesses a pde file and write out a java file
* @return the classname of the exported Java
*/
//public String write(String program, String buildPath, String name,
// String extraImports[]) throws java.lang.Exception {
public String write() throws java.lang.Exception {
writeProgram(stream, program, prototypes);
writeFooter(stream, target);
stream.close();
return name;
}
// Write the pde program to the cpp file
protected void writeProgram(PrintStream out, String program, List prototypes) {
int prototypeInsertionPoint = firstStatement(program);
out.print(program.substring(0, prototypeInsertionPoint));
out.print("#include \"WProgram.h\"\n");
// print user defined prototypes
for (int i = 0; i < prototypes.size(); i++) {
out.print(prototypes.get(i) + "\n");
}
out.print(program.substring(prototypeInsertionPoint));
}
/**
* Write any necessary closing text.
*
* @param out PrintStream to write it to.
*/
protected void writeFooter(PrintStream out, Target target) throws java.lang.Exception {
// Open the file main.cxx and copy its entire contents to the bottom of the
// generated sketch .cpp file...
String mainFileName = target.getPath() + File.separator + "main.cxx";
FileReader reader = null;
reader = new FileReader(mainFileName);
LineNumberReader mainfile = new LineNumberReader(reader);
String line;
while ((line = mainfile.readLine()) != null) {
out.print(line + "\n");
}
mainfile.close();
}
public ArrayList<String> getExtraImports() {
return programImports;
}
/**
* Returns the index of the first character that's not whitespace, a comment
* or a pre-processor directive.
@ -204,185 +368,4 @@ public class PdePreprocessor {
return matches;
}
/**
* preprocesses a pde file and write out a java file
* @param pretty true if should also space out/indent lines
* @return the classname of the exported Java
*/
//public String write(String program, String buildPath, String name,
// String extraImports[]) throws java.lang.Exception {
public String write(String program, String buildPath,
String name, String codeFolderPackages[],
Target target)
throws java.lang.Exception {
// if the program ends with no CR or LF an OutOfMemoryError will happen.
// not gonna track down the bug now, so here's a hack for it:
// bug filed at http://dev.processing.org/bugs/show_bug.cgi?id=5
//if ((program.length() > 0) &&
//program.charAt(program.length()-1) != '\n') {
program += "\n";
//}
// if the program ends with an unterminated multiline comment,
// an OutOfMemoryError or NullPointerException will happen.
// again, not gonna bother tracking this down, but here's a hack.
// http://dev.processing.org/bugs/show_bug.cgi?id=16
Sketch.scrubComments(program);
// this returns the scrubbed version, but more important for this
// function, it'll check to see if there are errors with the comments.
if (Preferences.getBoolean("preproc.substitute_unicode")) {
// check for non-ascii chars (these will be/must be in unicode format)
char p[] = program.toCharArray();
int unicodeCount = 0;
for (int i = 0; i < p.length; i++) {
if (p[i] > 127) unicodeCount++;
}
// if non-ascii chars are in there, convert to unicode escapes
if (unicodeCount != 0) {
// add unicodeCount * 5.. replacing each unicode char
// with six digit uXXXX sequence (xxxx is in hex)
// (except for nbsp chars which will be a replaced with a space)
int index = 0;
char p2[] = new char[p.length + unicodeCount*5];
for (int i = 0; i < p.length; i++) {
if (p[i] < 128) {
p2[index++] = p[i];
} else if (p[i] == 160) { // unicode for non-breaking space
p2[index++] = ' ';
} else {
int c = p[i];
p2[index++] = '\\';
p2[index++] = 'u';
char str[] = Integer.toHexString(c).toCharArray();
// add leading zeros, so that the length is 4
//for (int i = 0; i < 4 - str.length; i++) p2[index++] = '0';
for (int m = 0; m < 4 - str.length; m++) p2[index++] = '0';
System.arraycopy(str, 0, p2, index, str.length);
index += str.length;
}
}
program = new String(p2, 0, index);
}
}
// if this guy has his own imports, need to remove them
// just in case it's not an advanced mode sketch
PatternMatcher matcher = new Perl5Matcher();
PatternCompiler compiler = new Perl5Compiler();
//String mess = "^\\s*(import\\s+\\S+\\s*;)";
//String mess = "^\\s*(import\\s+)(\\S+)(\\s*;)";
String mess = "^\\s*#include\\s+[<\"](\\S+)[\">]";
programImports = new ArrayList<String>();
Pattern pattern = null;
try {
pattern = compiler.compile(mess);
} catch (MalformedPatternException e) {
e.printStackTrace();
return null;
}
PatternMatcherInput input = new PatternMatcherInput(program);
while (matcher.contains(input, pattern)) {
programImports.add(matcher.getMatch().group(1));
}
// do this after the program gets re-combobulated
this.programReader = new StringReader(program);
this.buildPath = buildPath;
List prototypes = prototypes(program);
// store # of prototypes so that line number reporting can be adjusted
prototypeCount = prototypes.size();
if (name == null) return null;
// output the code
File streamFile = new File(buildPath, name + ".cpp");
PrintStream stream = new PrintStream(new FileOutputStream(streamFile));
writeHeader(stream);
//added to write the pde code to the cpp file
writeProgram(stream, program, prototypes);
writeFooter(stream, target);
stream.close();
return name;
}
// Write the pde program to the cpp file
void writeProgram(PrintStream out, String program, List prototypes) {
int prototypeInsertionPoint = firstStatement(program);
out.print(program.substring(0, prototypeInsertionPoint));
out.print("#include \"WProgram.h\"\n");
// print user defined prototypes
for (int i = 0; i < prototypes.size(); i++) {
out.print(prototypes.get(i) + "\n");
}
out.print(program.substring(prototypeInsertionPoint));
}
/**
* Write any required header material (eg imports, class decl stuff)
*
* @param out PrintStream to write it to.
*/
void writeHeader(PrintStream out) throws IOException {}
/**
* Write any necessary closing text.
*
* @param out PrintStream to write it to.
*/
void writeFooter(PrintStream out, Target target) throws java.lang.Exception {
// Open the file main.cxx and copy its entire contents to the bottom of the
// generated sketch .cpp file...
String mainFileName = target.getPath() + File.separator + "main.cxx";
FileReader reader = null;
reader = new FileReader(mainFileName);
LineNumberReader mainfile = new LineNumberReader(reader);
String line;
while ((line = mainfile.readLine()) != null) {
out.print(line + "\n");
}
mainfile.close();
}
public ArrayList<String> getExtraImports() {
return programImports;
}
static String advClassName = "";
/**
* Find the first CLASS_DEF node in the tree, and return the name of the
* class in question.
*
* XXXdmose right now, we're using a little hack to the grammar to get
* this info. In fact, we should be descending the AST passed in.
*/
String getFirstClassName(AST ast) {
String t = advClassName;
advClassName = "";
return t;
}
}