1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-08-11 09:43:08 +03:00

Merge branch 'master' into esp8266

* master: (414 commits)
  Don't export sketch if the underlying core does not support it. Fixes #3171
  RSyntaxTextArea: using a modified version, tracked at https://github.com/arduino/RSyntaxTextArea. Fixes #3099
  Updated keywords.txt
  New editor on MacOSX: since CMD+J is known as "jump to selection" and the editor has no such feature, CMD+J is disabled on mac. See #3098
  Old Preferences class remains for backwards compatibility as a delegate for PreferencesData
  New Preferences window: renders fine on every OS and it's easier to adapt using NetBeans as visual editor. Fixes #3140
  Remove spawn from exec command
  Removed redundant call to File.deleteIfExists()
  Removed buggy redundant check in FileUtils.deleteIfExists()
  Restored current line/current selected lines display on lower left of the IDE. Fixes #3134
  Updated cursor.ino
  New editor on MacOSX: restored CMD+E for finding selected text
  New editor on MacOSX: CMD+UP/DOWN moves cursor to start or end of sketch. See #3098
  New editor on MacOSX: CMD+BACKSPACE deletes current line until cursor position, ALT+BACKSPACE deletes previous word. See #3098
  ArduinoIDE is in the default package. Removed
  Fixes  #2969:
  Fix Uncategorized warning message
  New editor: ALT+ BACKSPACE deletes next word (OSX only). See #3098
  New editor: ALT+ UP/DOWN move current line only if "editor.advanced" (hidden pref) is true. Fixes #3101
  New editor: mark occurrences enable when "editor.advanced" (hidden pref) is true. Fixes #3102
  ...

Conflicts:
	.gitignore
	build/build.xml
	hardware/esp8266com/esp8266/libraries/ESP8266WiFi/keywords.txt
	hardware/esp8266com/esp8266/libraries/ESP8266WiFi/library.properties
	hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h
	libraries/WiFi/README.adoc
	libraries/WiFi/src/WiFi.cpp
	libraries/WiFi/src/WiFiClient.cpp
	libraries/WiFi/src/WiFiClient.h
	libraries/WiFi/src/WiFiServer.cpp
	libraries/WiFi/src/WiFiUdp.cpp
This commit is contained in:
Ivan Grokhotkov
2015-05-18 14:54:06 +03:00
644 changed files with 37518 additions and 12166 deletions

View File

@@ -1,45 +1,53 @@
package processing.app;
import static processing.app.I18n._;
import cc.arduino.contributions.SignatureVerificationFailedException;
import cc.arduino.contributions.libraries.LibrariesIndexer;
import cc.arduino.contributions.packages.ContributedTool;
import cc.arduino.contributions.packages.ContributionsIndexer;
import cc.arduino.files.DeleteFilesOnShutdown;
import cc.arduino.packages.DiscoveryManager;
import cc.arduino.packages.Uploader;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.commons.logging.impl.LogFactoryImpl;
import org.apache.commons.logging.impl.NoOpLog;
import processing.app.debug.Compiler;
import processing.app.debug.*;
import processing.app.helpers.*;
import processing.app.helpers.filefilters.OnlyDirs;
import processing.app.helpers.filefilters.OnlyFilesWithExtension;
import processing.app.legacy.PApplet;
import processing.app.packages.LibraryList;
import processing.app.packages.UserLibrary;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.*;
import java.net.URISyntaxException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.logging.impl.LogFactoryImpl;
import org.apache.commons.logging.impl.NoOpLog;
import cc.arduino.packages.DiscoveryManager;
import cc.arduino.packages.Uploader;
import processing.app.debug.Compiler;
import processing.app.debug.TargetBoard;
import processing.app.debug.TargetPackage;
import processing.app.debug.TargetPlatform;
import processing.app.debug.TargetPlatformException;
import processing.app.helpers.BasicUserNotifier;
import processing.app.helpers.CommandlineParser;
import processing.app.helpers.OSUtils;
import processing.app.helpers.PreferencesMap;
import processing.app.helpers.UserNotifier;
import processing.app.helpers.filefilters.OnlyDirs;
import processing.app.helpers.filefilters.OnlyFilesWithExtension;
import processing.app.legacy.PApplet;
import processing.app.packages.Library;
import processing.app.packages.LibraryList;
import static processing.app.I18n._;
public class BaseNoGui {
/** Version string to be used for build */
public static final int REVISION = 10601;
public static final int REVISION = 10605;
/** Extended version string displayed on GUI */
static String VERSION_NAME = "1.6.1";
public static final String VERSION_NAME = "1.6.5";
public static final String VERSION_NAME_LONG;
static {
String versionNameLong = VERSION_NAME;
File hourlyBuildTxt = new File(getContentFile("lib"), "hourlyBuild.txt");
if (hourlyBuildTxt.exists() && hourlyBuildTxt.canRead()) {
versionNameLong += " Hourly Build";
try {
versionNameLong += " " + FileUtils.readFileToString(hourlyBuildTxt).trim();
} catch (IOException e) {
//noop
}
}
VERSION_NAME_LONG = versionNameLong;
}
static File buildFolder;
@@ -54,11 +62,12 @@ public class BaseNoGui {
static private File toolsFolder;
// maps #included files to their library folder
public static Map<String, Library> importToLibraryTable;
public static Map<String, LibraryList> importToLibraryTable;
// maps library name to their library folder
static private LibraryList libraries;
// XXX: Remove this field
static private List<File> librariesFolders;
static UserNotifier notifier = new BasicUserNotifier();
@@ -68,9 +77,11 @@ public class BaseNoGui {
static Platform platform;
static File portableFolder = null;
static final String portableSketchbookFolder = "sketchbook";
public static ContributionsIndexer indexer;
static LibrariesIndexer librariesIndexer;
// Returns a File object for the given pathname. If the pathname
// is not absolute, it is interpreted relative to the current
// directory when starting the IDE (which is not the same as the
@@ -139,7 +150,7 @@ public class BaseNoGui {
//File folder = new File(getTempFolder(), "build");
//if (!folder.exists()) folder.mkdirs();
buildFolder = createTempFolder("build");
buildFolder.deleteOnExit();
DeleteFilesOnShutdown.add(buildFolder);
}
}
return buildFolder;
@@ -238,13 +249,6 @@ public class BaseNoGui {
return librariesFolders;
}
/**
* Return an InputStream for a file inside the Processing lib folder.
*/
static public InputStream getLibStream(String filename) throws IOException {
return new FileInputStream(new File(getContentFile("lib"), filename));
}
static public Platform getPlatform() {
return platform;
}
@@ -403,9 +407,8 @@ public class BaseNoGui {
}
static public LibraryList getUserLibs() {
if (libraries == null)
return new LibraryList();
return libraries.filterLibrariesInSubfolder(getSketchbookFolder());
LibraryList libs = BaseNoGui.librariesIndexer.getInstalledLibraries();
return libs.filterLibrariesInSubfolder(getSketchbookFolder());
}
/**
@@ -421,7 +424,7 @@ public class BaseNoGui {
return list;
}
static public void init(String[] args) {
static public void init(String[] args) throws Exception {
getPlatform().init();
String sketchbookPath = getSketchbookPath();
@@ -508,7 +511,7 @@ public class BaseNoGui {
// - calls Sketch.build(verbose=false) that calls Sketch.ensureExistence(), set progressListener and calls Compiler.build()
// - calls Sketch.upload() (see later...)
if (!data.getFolder().exists()) showError(_("No sketch"), _("Can't find the sketch in the specified path"), null);
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild());
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild(), false);
if (suggestedClassName == null) showError(_("Error while verifying"), _("An error occurred while verifying the sketch"), null);
showMessage(_("Done compiling"), _("Done compiling"));
@@ -553,7 +556,7 @@ public class BaseNoGui {
// if (!data.getFolder().exists()) showError(...);
// String ... = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, verbose);
if (!data.getFolder().exists()) showError(_("No sketch"), _("Can't find the sketch in the specified path"), null);
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild());
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild(), false);
if (suggestedClassName == null) showError(_("Error while verifying"), _("An error occurred while verifying the sketch"), null);
showMessage(_("Done compiling"), _("Done compiling"));
} catch (Exception e) {
@@ -582,13 +585,77 @@ public class BaseNoGui {
Logger.getLogger("javax.jmdns").setLevel(Level.OFF);
}
static public void initPackages() {
static public void initPackages() throws Exception {
indexer = new ContributionsIndexer(BaseNoGui.getSettingsFolder());
File indexFile = indexer.getIndexFile("package_index.json");
File defaultPackageJsonFile = new File(getContentFile("dist"), "package_index.json");
if (!indexFile.isFile() || (defaultPackageJsonFile.isFile() && defaultPackageJsonFile.lastModified() > indexFile.lastModified())) {
FileUtils.copyFile(defaultPackageJsonFile, indexFile);
} else if (!indexFile.isFile()) {
// Otherwise create an empty packages index
FileOutputStream out = null;
try {
out = new FileOutputStream(indexFile);
out.write("{ \"packages\" : [ ] }".getBytes());
out.close();
} finally {
if (out != null) {
out.close();
}
}
}
File indexSignatureFile = indexer.getIndexFile("package_index.json.sig");
File defaultPackageJsonSignatureFile = new File(getContentFile("dist"), "package_index.json.sig");
if (!indexSignatureFile.isFile() || (defaultPackageJsonSignatureFile.isFile() && defaultPackageJsonSignatureFile.lastModified() > indexSignatureFile.lastModified())) {
FileUtils.copyFile(defaultPackageJsonSignatureFile, indexSignatureFile);
}
try {
indexer.parseIndex();
} catch (JsonProcessingException e) {
FileUtils.deleteIfExists(indexFile);
FileUtils.deleteIfExists(indexSignatureFile);
throw e;
} catch (SignatureVerificationFailedException e) {
FileUtils.deleteIfExists(indexFile);
FileUtils.deleteIfExists(indexSignatureFile);
throw e;
}
indexer.syncWithFilesystem(getHardwareFolder());
packages = new HashMap<String, TargetPackage>();
loadHardware(getHardwareFolder());
loadHardware(getSketchbookHardwareFolder());
if (packages.size() == 0) {
System.out.println(_("No valid configured cores found! Exiting..."));
System.exit(3);
loadContributedHardware(indexer);
createToolPreferences(indexer);
librariesIndexer = new LibrariesIndexer(BaseNoGui.getSettingsFolder());
File librariesIndexFile = librariesIndexer.getIndexFile();
if (!librariesIndexFile.isFile()) {
File defaultLibraryJsonFile = new File(getContentFile("dist"), "library_index.json");
if (defaultLibraryJsonFile.isFile()) {
FileUtils.copyFile(defaultLibraryJsonFile, librariesIndexFile);
} else {
FileOutputStream out = null;
try {
// Otherwise create an empty packages index
out = new FileOutputStream(librariesIndexFile);
out.write("{ \"libraries\" : [ ] }".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
}
}
try {
librariesIndexer.parseIndex();
} catch (JsonProcessingException e) {
FileUtils.deleteIfExists(librariesIndexFile);
throw e;
}
}
@@ -649,9 +716,9 @@ public class BaseNoGui {
File subfolder = new File(folder, target);
try {
packages.put(target, new TargetPackage(target, subfolder));
packages.put(target, new LegacyTargetPackage(target, subfolder));
} catch (TargetPlatformException e) {
System.out.println("WARNING: Error loading hardware folder " + target);
System.out.println("WARNING: Error loading hardware folder " + new File(folder, target));
System.out.println(" " + e.getMessage());
}
}
@@ -670,6 +737,8 @@ public class BaseNoGui {
if (args.length == 0)
showError(_("No parameters"), _("No command line parameters found"), null);
Runtime.getRuntime().addShutdownHook(new Thread(DeleteFilesOnShutdown.INSTANCE));
initPlatform();
initPortableFolder();
@@ -683,9 +752,10 @@ public class BaseNoGui {
examplesFolder = getContentFile("examples");
toolsFolder = getContentFile("tools");
librariesFolders = new ArrayList<File>();
// Add IDE libraries folder
librariesFolders.add(getContentFile("libraries"));
// Add library folder for the current selected platform
TargetPlatform targetPlatform = getTargetPlatform();
if (targetPlatform != null) {
String core = getBoardPreferences().get("build.core", "arduino");
@@ -694,35 +764,69 @@ public class BaseNoGui {
TargetPlatform referencedPlatform = getTargetPlatform(referencedCore, targetPlatform.getId());
if (referencedPlatform != null) {
File referencedPlatformFolder = referencedPlatform.getFolder();
librariesFolders.add(new File(referencedPlatformFolder, "libraries"));
// Add libraries folder for the referenced platform
File folder = new File(referencedPlatformFolder, "libraries");
librariesFolders.add(folder);
}
}
File platformFolder = targetPlatform.getFolder();
librariesFolders.add(new File(platformFolder, "libraries"));
librariesFolders.add(getSketchbookLibrariesFolder());
// Add libraries folder for the selected platform
File folder = new File(platformFolder, "libraries");
librariesFolders.add(folder);
}
// Add libraries folder for the sketchbook
librariesFolders.add(getSketchbookLibrariesFolder());
// Scan for libraries in each library folder.
// Libraries located in the latest folders on the list can override
// other libraries with the same name.
try {
scanAndUpdateLibraries(librariesFolders);
} catch (IOException e) {
showWarning(_("Error"), _("Error loading libraries"), e);
}
BaseNoGui.librariesIndexer.setSketchbookLibrariesFolder(getSketchbookLibrariesFolder());
BaseNoGui.librariesIndexer.setLibrariesFolders(librariesFolders);
BaseNoGui.librariesIndexer.rescanLibraries();
populateImportToLibraryTable();
}
static protected void loadContributedHardware(ContributionsIndexer indexer) throws TargetPlatformException {
for (TargetPackage pack : indexer.createTargetPackages()) {
packages.put(pack.getId(), pack);
}
}
static private void createToolPreferences(ContributionsIndexer indexer) {
// Remove previous runtime preferences
final String prefix = "runtime.tools.";
PreferencesData.removeAllKeysWithPrefix(prefix);
for (ContributedTool tool : indexer.getInstalledTools()) {
File installedFolder = tool.getDownloadableContribution().getInstalledFolder();
if (installedFolder != null) {
PreferencesData.set(prefix + tool.getName() + ".path", installedFolder.getAbsolutePath());
PreferencesData.set(prefix + tool.getName() + "-" + tool.getVersion() + ".path", installedFolder.getAbsolutePath());
}
}
}
static public void populateImportToLibraryTable() {
// Populate importToLibraryTable
importToLibraryTable = new HashMap<String, Library>();
for (Library lib : getLibraries()) {
// Populate importToLibraryTable. Each header filename maps to
// a list of libraries. Compiler.java will use only the first
// library on each list. The others are used only to advise
// user of ambiguously matched and duplicate libraries.
importToLibraryTable = new HashMap<String, LibraryList>();
for (UserLibrary lib : librariesIndexer.getInstalledLibraries()) {
try {
String headers[] = headerListFromIncludePath(lib.getSrcFolder());
for (String header : headers) {
Library old = importToLibraryTable.get(header);
if (old != null) {
LibraryList list = importToLibraryTable.get(header);
if (list == null) {
// This is the first library found with this header
list = new LibraryList();
list.addFirst(lib);
importToLibraryTable.put(header, list);
} else {
UserLibrary old = list.peekFirst();
boolean useThisLib = true;
// This is the case where 2 libraries have a .h header
// with the same name. We must decide which library to
// use when a sketch has #include "name.h"
@@ -737,61 +841,84 @@ public class BaseNoGui {
// for "libName", then for "oldName".
//
String name = header.substring(0, header.length() - 2); // name without ".h"
String oldName = old.getFolder().getName(); // just the library folder name
String libName = lib.getFolder().getName(); // just the library folder name
String oldName = old.getInstalledFolder().getName(); // just the library folder name
String libName = lib.getInstalledFolder().getName(); // just the library folder name
//System.out.println("name conflict: " + name);
//System.out.println(" old = " + oldName + " -> " + old.getFolder().getPath());
//System.out.println(" new = " + libName + " -> " + lib.getFolder().getPath());
//System.out.println(" old = " + oldName + " -> " + old.getInstalledFolder().getPath());
//System.out.println(" new = " + libName + " -> " + lib.getInstalledFolder().getPath());
String name_lc = name.toLowerCase();
String oldName_lc = oldName.toLowerCase();
String libName_lc = libName.toLowerCase();
// always favor a perfect name match
if (libName.equals(name)) {
} else if (oldName.equals(name)) {
continue;
useThisLib = false;
// check for "-master" appended (zip file from github)
} else if (libName.equals(name+"-master")) {
} else if (oldName.equals(name+"-master")) {
continue;
useThisLib = false;
// next, favor a match with other stuff appended
} else if (libName.startsWith(name)) {
} else if (oldName.startsWith(name)) {
continue;
useThisLib = false;
// otherwise, favor a match with stuff prepended
} else if (libName.endsWith(name)) {
} else if (oldName.endsWith(name)) {
continue;
useThisLib = false;
// as a last resort, match if stuff prepended and appended
} else if (libName.contains(name)) {
} else if (oldName.contains(name)) {
continue;
useThisLib = false;
// repeat all the above tests, with case insensitive matching
} else if (libName_lc.equals(name_lc)) {
} else if (oldName_lc.equals(name_lc)) {
continue;
useThisLib = false;
} else if (libName_lc.equals(name_lc+"-master")) {
} else if (oldName_lc.equals(name_lc+"-master")) {
continue;
useThisLib = false;
} else if (libName_lc.startsWith(name_lc)) {
} else if (oldName_lc.startsWith(name_lc)) {
continue;
useThisLib = false;
} else if (libName_lc.endsWith(name_lc)) {
} else if (oldName_lc.endsWith(name_lc)) {
continue;
useThisLib = false;
} else if (libName_lc.contains(name_lc)) {
} else if (oldName_lc.contains(name_lc)) {
continue;
useThisLib = false;
} else {
// none of these tests matched, so just default to "libName".
}
if (useThisLib) {
list.addFirst(lib);
} else {
list.addLast(lib);
}
}
importToLibraryTable.put(header, lib);
}
} catch (IOException e) {
showWarning(_("Error"), I18n
.format("Unable to list header files in {0}", lib.getSrcFolder()), e);
}
}
// repeat for ALL libraries, to pick up duplicates not visible normally.
// any new libraries found here are NEVER used, but they are added to the
// end of already-found headers, to allow Compiler to report them if
// the sketch tries to use them.
for (UserLibrary lib : librariesIndexer.getInstalledLibrariesWithDuplicates()) {
try {
String headers[] = headerListFromIncludePath(lib.getSrcFolder());
for (String header : headers) {
LibraryList list = importToLibraryTable.get(header);
if (list != null) {
if (!(list.hasLibrary(lib))) {
list.addLast(lib);
//System.out.println(" duplicate lib: " + lib.getInstalledFolder().getPath());
}
}
}
} catch (IOException e) {
}
}
}
static public void initParameters(String args[]) {
@@ -926,49 +1053,6 @@ public class BaseNoGui {
}
}
static public void scanAndUpdateLibraries(List<File> folders) throws IOException {
libraries = scanLibraries(folders);
}
static public LibraryList scanLibraries(List<File> folders) throws IOException {
LibraryList res = new LibraryList();
for (File folder : folders)
res.addOrReplaceAll(scanLibraries(folder));
return res;
}
static public LibraryList scanLibraries(File folder) throws IOException {
LibraryList res = new LibraryList();
String list[] = folder.list(new OnlyDirs());
// if a bad folder or something like that, this might come back null
if (list == null)
return res;
for (String libName : list) {
File subfolder = new File(folder, libName);
if (!isSanitaryName(libName)) {
String mess = I18n.format(_("The library \"{0}\" cannot be used.\n"
+ "Library names must contain only basic letters and numbers.\n"
+ "(ASCII only and no spaces, and it cannot start with a number)"),
libName);
showMessage(_("Ignoring bad library name"), mess);
continue;
}
try {
Library lib = Library.create(subfolder);
// (also replace previously found libs with the same name)
if (lib != null)
res.addOrReplace(lib);
} catch (IOException e) {
System.out.println(I18n.format(_("Invalid library found in {0}: {1}"),
subfolder, e.getMessage()));
}
}
return res;
}
static public void selectBoard(TargetBoard targetBoard) {
TargetPlatform targetPlatform = targetBoard.getContainerPlatform();
TargetPackage targetPackage = targetPlatform.getContainerPackage();

View File

@@ -24,11 +24,11 @@ public class I18n {
// prompt text stuff
static String PROMPT_YES;
static String PROMPT_NO;
static String PROMPT_CANCEL;
static String PROMPT_OK;
static String PROMPT_BROWSE;
public static String PROMPT_YES;
public static String PROMPT_NO;
public static String PROMPT_CANCEL;
public static String PROMPT_OK;
public static String PROMPT_BROWSE;
static protected void init(String language) throws MissingResourceException {
String[] languageParts = language.split("_");

View File

@@ -21,24 +21,19 @@
*/
package processing.app;
import static processing.app.I18n._;
import java.io.File;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.swing.UIManager;
import cc.arduino.packages.BoardPort;
import com.sun.jna.Library;
import com.sun.jna.Native;
import processing.app.debug.TargetBoard;
import processing.app.debug.TargetPackage;
import processing.app.debug.TargetPlatform;
import processing.app.legacy.PConstants;
import javax.swing.*;
import java.io.*;
import java.util.*;
import static processing.app.I18n._;
/**
* Used by Base for platform-specific tweaking, for instance finding the
@@ -75,7 +70,7 @@ public class Platform {
}
public void init() {
public void init() throws IOException {
}
@@ -169,6 +164,8 @@ public class Platform {
}
public String resolveDeviceByBoardID(Map<String, TargetPackage> packages, String boardId) {
assert packages != null;
assert boardId != null;
for (TargetPackage targetPackage : packages.values()) {
for (TargetPlatform targetPlatform : targetPackage.getPlatforms().values()) {
for (TargetBoard board : targetPlatform.getBoards().values()) {
@@ -183,33 +180,6 @@ public class Platform {
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)Native.loadLibrary("c", CLibrary.class);
int setenv(String name, String value, int overwrite);
String getenv(String name);
int unsetenv(String name);
int putenv(String string);
}
public void setenv(String variable, String value) {
CLibrary clib = CLibrary.INSTANCE;
clib.setenv(variable, value, 1);
}
public String getenv(String variable) {
CLibrary clib = CLibrary.INSTANCE;
return clib.getenv(variable);
}
public int unsetenv(String variable) {
CLibrary clib = CLibrary.INSTANCE;
return clib.unsetenv(variable);
}
public String getName() {
return PConstants.platformNames[PConstants.OTHER];
}
@@ -227,4 +197,39 @@ public class Platform {
public List<BoardPort> filterPorts(List<BoardPort> ports, boolean aBoolean) {
return new LinkedList<BoardPort>(ports);
}
public void fixPrefsFilePermissions(File prefsFile) throws IOException, InterruptedException {
Process process = Runtime.getRuntime().exec(new String[]{"chmod", "600", prefsFile.getAbsolutePath()}, null, null);
process.waitFor();
}
public List<File> postInstallScripts(File folder) {
List<File> scripts = new LinkedList<File>();
scripts.add(new File(folder, "install_script.sh"));
scripts.add(new File(folder, "post_install.sh"));
return scripts;
}
public String getOsName() {
return System.getProperty("os.name");
}
public String getOsArch() {
return System.getProperty("os.arch");
}
public void symlink(String something, File somewhere) throws IOException, InterruptedException {
Process process = Runtime.getRuntime().exec(new String[]{"ln", "-s", something, somewhere.getAbsolutePath()}, null, somewhere.getParentFile());
process.waitFor();
}
public void link(File something, File somewhere) throws IOException, InterruptedException {
Process process = Runtime.getRuntime().exec(new String[]{"ln", something.getAbsolutePath(), somewhere.getAbsolutePath()}, null, null);
process.waitFor();
}
public void chmod(File file, int mode) throws IOException, InterruptedException {
Process process = Runtime.getRuntime().exec(new String[]{"chmod", Integer.toOctalString(mode), file.getAbsolutePath()}, null, null);
process.waitFor();
}
}

View File

@@ -2,6 +2,7 @@ package processing.app;
import static processing.app.I18n._;
import java.awt.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
@@ -9,8 +10,10 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Iterator;
import java.util.MissingResourceException;
import processing.app.helpers.PreferencesHelper;
import processing.app.helpers.PreferencesMap;
import processing.app.legacy.PApplet;
import processing.app.legacy.PConstants;
@@ -18,7 +21,7 @@ import processing.app.legacy.PConstants;
public class PreferencesData {
static final String PREFS_FILE = "preferences.txt";
private static final String PREFS_FILE = "preferences.txt";
// data model
@@ -29,18 +32,25 @@ public class PreferencesData {
static public void init(File file) {
if (file != null)
if (file != null) {
preferencesFile = file;
else
} else {
preferencesFile = BaseNoGui.getSettingsFile(PREFS_FILE);
}
try {
BaseNoGui.getPlatform().fixPrefsFilePermissions(preferencesFile);
} catch (Exception e) {
//ignore
}
// start by loading the defaults, in case something
// important was deleted from the user prefs
try {
prefs.load(BaseNoGui.getLibStream("preferences.txt"));
prefs.load(new File(BaseNoGui.getContentFile("lib"), PREFS_FILE));
} catch (IOException e) {
BaseNoGui.showError(null, _("Could not read default settings.\n" +
"You'll need to reinstall Arduino."), e);
"You'll need to reinstall Arduino."), e);
}
// set some runtime constants (not saved on preferences file)
@@ -78,6 +88,10 @@ public class PreferencesData {
fixPreferences();
}
public static File getPreferencesFile() {
return preferencesFile;
}
private static void fixPreferences() {
String baud = get("serial.debug_rate");
if ("14400".equals(baud) || "28800".equals(baud)) {
@@ -86,41 +100,6 @@ public class PreferencesData {
}
static public String[] loadStrings(InputStream input) {
try {
BufferedReader reader =
new BufferedReader(new InputStreamReader(input, "UTF-8"));
String lines[] = new String[100];
int lineCount = 0;
String line = null;
while ((line = reader.readLine()) != null) {
if (lineCount == lines.length) {
String temp[] = new String[lineCount << 1];
System.arraycopy(lines, 0, temp, 0, lineCount);
lines = temp;
}
lines[lineCount++] = line;
}
reader.close();
if (lineCount == lines.length) {
return lines;
}
// resize array to appropriate amount for these lines
String output[] = new String[lineCount];
System.arraycopy(lines, 0, output, 0, lineCount);
return output;
} catch (IOException e) {
e.printStackTrace();
//throw new RuntimeException("Error inside loadStrings()");
}
return null;
}
static protected void save() {
if (!doSave)
return;
@@ -131,18 +110,30 @@ public class PreferencesData {
if (preferencesFile == null) return;
// Fix for 0163 to properly use Unicode when writing preferences.txt
PrintWriter writer = PApplet.createWriter(preferencesFile);
PrintWriter writer = null;
try {
writer = PApplet.createWriter(preferencesFile);
String[] keys = prefs.keySet().toArray(new String[0]);
Arrays.sort(keys);
for (String key: keys) {
if (key.startsWith("runtime."))
continue;
writer.println(key + "=" + prefs.get(key));
String[] keys = prefs.keySet().toArray(new String[0]);
Arrays.sort(keys);
for (String key : keys) {
if (key.startsWith("runtime."))
continue;
writer.println(key + "=" + prefs.get(key));
}
writer.flush();
} finally {
if (writer != null) {
writer.close();
}
}
writer.flush();
writer.close();
try {
BaseNoGui.getPlatform().fixPrefsFilePermissions(preferencesFile);
} catch (Exception e) {
//ignore
}
}
@@ -194,6 +185,13 @@ public class PreferencesData {
return Integer.parseInt(get(attribute));
}
static public int getInteger(String attribute, int defaultValue) {
if (has(attribute)) {
return getInteger(attribute);
}
return defaultValue;
}
static public void setInteger(String key, int value) {
set(key, String.valueOf(value));
@@ -205,10 +203,27 @@ public class PreferencesData {
return new PreferencesMap(prefs);
}
static public void removeAllKeysWithPrefix(String prefix) {
Iterator<String> keys = prefs.keySet().iterator();
while (keys.hasNext())
if (keys.next().startsWith(prefix))
keys.remove();
}
// Decide wether changed preferences will be saved. When value is
// false, Preferences.save becomes a no-op.
static public void setDoSave(boolean value)
{
doSave = value;
}
static public Font getFont(String attr) {
Font font = PreferencesHelper.getFont(prefs, attr);
if (font == null) {
String value = defaults.get(attr);
prefs.put(attr, value);
font = PreferencesHelper.getFont(prefs, attr);
}
return font;
}
}

View File

@@ -88,11 +88,12 @@ public class Serial implements SerialPortEventListener {
BaseNoGui.getBoardPreferences().get("serial.disableDTR") == null);
}
public static boolean touchPort(String iname, int irate) throws SerialException {
public static boolean touchForCDCReset(String iname) throws SerialException {
SerialPort serialPort = new SerialPort(iname);
try {
serialPort.openPort();
serialPort.setParams(irate, 8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
serialPort.setParams(1200, 8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
serialPort.setDTR(false);
serialPort.closePort();
return true;
} catch (SerialPortException e) {

View File

@@ -25,13 +25,7 @@ package processing.app.debug;
import static processing.app.I18n._;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -45,6 +39,9 @@ import cc.arduino.packages.BoardPort;
import cc.arduino.packages.Uploader;
import cc.arduino.packages.UploaderFactory;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteStreamHandler;
import processing.app.BaseNoGui;
import processing.app.I18n;
import processing.app.PreferencesData;
@@ -52,10 +49,12 @@ import processing.app.SketchCode;
import processing.app.SketchData;
import processing.app.helpers.*;
import processing.app.helpers.filefilters.OnlyDirs;
import processing.app.packages.Library;
import processing.app.packages.LibraryList;
import processing.app.preproc.PdePreprocessor;
import processing.app.legacy.PApplet;
import processing.app.packages.LegacyUserLibrary;
import processing.app.packages.UserLibrary;
import processing.app.tools.DoubleQuotedArgumentsOnWindowsCommandLine;
public class Compiler implements MessageConsumer {
@@ -68,6 +67,7 @@ public class Compiler implements MessageConsumer {
private SketchData sketch;
private PreferencesMap prefs;
private boolean verbose;
private boolean saveHex;
private List<File> objectFiles;
@@ -84,7 +84,7 @@ public class Compiler implements MessageConsumer {
private ProgressListener progressListener;
static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose) throws RunnerException, PreferencesMapException {
static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose, boolean save) throws RunnerException, PreferencesMapException {
if (SketchData.checkSketchFile(data.getPrimaryFile()) == null)
BaseNoGui.showError(_("Bad file selected"),
_("Bad sketch primary file or bad sketch directory structure"), null);
@@ -113,9 +113,16 @@ public class Compiler implements MessageConsumer {
// compile the program. errors will happen as a RunnerException
// that will bubble up to whomever called build().
if (compiler.compile(verbose)) {
compiler.size(compiler.getBuildPreferences());
return primaryClassName;
try {
if (compiler.compile(verbose, save)) {
compiler.size(compiler.getBuildPreferences());
return primaryClassName;
}
} catch (RunnerException e) {
// when the compile fails, take this opportunity to show
// any helpful info possible before throwing the exception
compiler.adviseDuplicateLibraries();
throw e;
}
return null;
}
@@ -183,6 +190,9 @@ public class Compiler implements MessageConsumer {
sketch = _sketch;
prefs = createBuildPreferences(_buildPath, _primaryClassName);
// provide access to the source tree
prefs.put("build.source.path", _sketch.getFolder().getAbsolutePath());
// Start with an empty progress listener
progressListener = new ProgressListener() {
@Override
@@ -311,10 +321,10 @@ public class Compiler implements MessageConsumer {
if (maxDataSize > 0) {
System.out
.println(I18n
.format(
_("Global variables use {0} bytes ({2}%%) of dynamic memory, leaving {3} bytes for local variables. Maximum is {1} bytes."),
dataSize, maxDataSize, dataSize * 100 / maxDataSize,
maxDataSize - dataSize));
.format(
_("Global variables use {0} bytes ({2}%%) of dynamic memory, leaving {3} bytes for local variables. Maximum is {1} bytes."),
dataSize, maxDataSize, dataSize * 100 / maxDataSize,
maxDataSize - dataSize));
} else {
System.out.println(I18n
.format(_("Global variables use {0} bytes of dynamic memory."), dataSize));
@@ -341,11 +351,16 @@ public class Compiler implements MessageConsumer {
* @return true if successful.
* @throws RunnerException Only if there's a problem. Only then.
*/
public boolean compile(boolean _verbose) throws RunnerException, PreferencesMapException {
public boolean compile(boolean _verbose, boolean _save) throws RunnerException, PreferencesMapException {
preprocess(prefs.get("build.path"));
verbose = _verbose || PreferencesData.getBoolean("build.verbose");
saveHex = _save;
sketchIsCompiled = false;
// Hook runs at Start of Compilation
runActions("hooks.prebuild", prefs);
objectFiles = new ArrayList<File>();
// 0. include paths for core + all libraries
@@ -354,11 +369,15 @@ public class Compiler implements MessageConsumer {
includeFolders.add(prefs.getFile("build.core.path"));
if (prefs.getFile("build.variant.path") != null)
includeFolders.add(prefs.getFile("build.variant.path"));
for (Library lib : importedLibraries) {
if (verbose)
for (UserLibrary lib : importedLibraries) {
if (verbose) {
String legacy = "";
if (lib instanceof LegacyUserLibrary)
legacy = "(legacy)";
System.out.println(I18n
.format(_("Using library {0} in folder: {1} {2}"), lib.getName(),
lib.getFolder(), lib.isLegacy() ? "(legacy)" : ""));
lib.getInstalledFolder(), legacy));
}
includeFolders.add(lib.getSrcFolder());
}
if (verbose)
@@ -370,7 +389,7 @@ public class Compiler implements MessageConsumer {
String[] overrides = prefs.get("architecture.override_check").split(",");
archs.addAll(Arrays.asList(overrides));
}
for (Library lib : importedLibraries) {
for (UserLibrary lib : importedLibraries) {
if (!lib.supportsArchitecture(archs)) {
System.err.println(I18n
.format(_("WARNING: library {0} claims to run on {1} "
@@ -382,26 +401,26 @@ public class Compiler implements MessageConsumer {
}
// 1. compile the sketch (already in the buildPath)
progressListener.progress(30);
progressListener.progress(20);
compileSketch(includeFolders);
sketchIsCompiled = true;
// 2. compile the libraries, outputting .o files to: <buildPath>/<library>/
// Doesn't really use configPreferences
progressListener.progress(40);
progressListener.progress(30);
compileLibraries(includeFolders);
// 3. compile the core, outputting .o files to <buildPath> and then
// collecting them into the core.a library file.
progressListener.progress(50);
progressListener.progress(40);
compileCore();
// 4. link it all together into the .elf file
progressListener.progress(60);
progressListener.progress(50);
compileLink();
// 5. run objcopy to generate output files
progressListener.progress(75);
progressListener.progress(60);
List<String> objcopyPatterns = new ArrayList<String>();
for (String key : prefs.keySet()) {
if (key.startsWith("recipe.objcopy.") && key.endsWith(".pattern"))
@@ -412,10 +431,39 @@ public class Compiler implements MessageConsumer {
runRecipe(recipe);
}
// 7. save the hex file
if (saveHex) {
progressListener.progress(80);
saveHex();
}
progressListener.progress(90);
// Hook runs at End of Compilation
runActions("hooks.postbuild", prefs);
adviseDuplicateLibraries();
return true;
}
private void adviseDuplicateLibraries() {
for (int i=0; i < importedDuplicateHeaders.size(); i++) {
System.out.println(I18n.format(_("Multiple libraries were found for \"{0}\""),
importedDuplicateHeaders.get(i)));
boolean first = true;
for (UserLibrary lib : importedDuplicateLibraries.get(i)) {
if (first) {
System.out.println(I18n.format(_(" Used: {0}"),
lib.getInstalledFolder().getPath()));
first = false;
} else {
System.out.println(I18n.format(_(" Not used: {0}"),
lib.getInstalledFolder().getPath()));
}
}
}
}
private PreferencesMap createBuildPreferences(String _buildPath,
String _primaryClassName)
throws RunnerException {
@@ -647,7 +695,6 @@ public class Compiler implements MessageConsumer {
command = stringList.toArray(new String[stringList.size()]);
if (command.length == 0)
return;
int result = 0;
if (verbose) {
for (String c : command)
@@ -655,30 +702,57 @@ public class Compiler implements MessageConsumer {
System.out.println();
}
Process process;
DefaultExecutor executor = new DefaultExecutor();
executor.setStreamHandler(new ExecuteStreamHandler() {
@Override
public void setProcessInputStream(OutputStream os) throws IOException {
}
@Override
public void setProcessErrorStream(InputStream is) throws IOException {
forwardToMessage(is);
}
@Override
public void setProcessOutputStream(InputStream is) throws IOException {
forwardToMessage(is);
}
private void forwardToMessage(InputStream is) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = reader.readLine()) != null) {
message(line + "\n");
}
}
@Override
public void start() throws IOException {
}
@Override
public void stop() {
}
});
CommandLine commandLine = new DoubleQuotedArgumentsOnWindowsCommandLine(command[0]);
for (int i = 1; i < command.length; i++) {
commandLine.addArgument(command[i], false);
}
int result;
executor.setExitValues(null);
try {
process = ProcessUtils.exec(command);
result = executor.execute(commandLine);
} catch (IOException e) {
RunnerException re = new RunnerException(e.getMessage());
re.hideStackTrace();
throw re;
}
MessageSiphon in = new MessageSiphon(process.getInputStream(), this);
MessageSiphon err = new MessageSiphon(process.getErrorStream(), this);
// wait for the process to finish. if interrupted
// before waitFor returns, continue waiting
boolean compiling = true;
while (compiling) {
try {
in.join();
err.join();
result = process.waitFor();
//System.out.println("result is " + result);
compiling = false;
} catch (InterruptedException ignored) { }
}
executor.setExitValues(new int[0]);
// an error was queued up by message(), barf this back to compile(),
// which will barf it back to Editor. if you're having trouble
@@ -720,10 +794,10 @@ public class Compiler implements MessageConsumer {
s = s.substring(0, i) + s.substring(i + (buildPath + File.separator).length());
}
}
// look for error line, which contains file name, line number,
// and at least the first line of the error message
String errorFormat = "([\\w\\d_]+.\\w+):(\\d+):\\s*error:\\s*(.*)\\s*";
String errorFormat = "(.+\\.\\w+):(\\d+)(:\\d+)*:\\s*error:\\s*(.*)\\s*";
String[] pieces = PApplet.match(s, errorFormat);
// if (pieces != null && exception == null) {
@@ -732,56 +806,56 @@ public class Compiler implements MessageConsumer {
// }
if (pieces != null) {
String error = pieces[3], msg = "";
String error = pieces[pieces.length - 1], msg = "";
if (pieces[3].trim().equals("SPI.h: No such file or directory")) {
if (error.trim().equals("SPI.h: No such file or directory")) {
error = _("Please import the SPI library from the Sketch > Import Library menu.");
msg = _("\nAs of Arduino 0019, the Ethernet library depends on the SPI library." +
"\nYou appear to be using it or another library that depends on the SPI library.\n\n");
}
if (pieces[3].trim().equals("'BYTE' was not declared in this scope")) {
if (error.trim().equals("'BYTE' was not declared in this scope")) {
error = _("The 'BYTE' keyword is no longer supported.");
msg = _("\nAs of Arduino 1.0, the 'BYTE' keyword is no longer supported." +
"\nPlease use Serial.write() instead.\n\n");
}
if (pieces[3].trim().equals("no matching function for call to 'Server::Server(int)'")) {
if (error.trim().equals("no matching function for call to 'Server::Server(int)'")) {
error = _("The Server class has been renamed EthernetServer.");
msg = _("\nAs of Arduino 1.0, the Server class in the Ethernet library " +
"has been renamed to EthernetServer.\n\n");
}
if (pieces[3].trim().equals("no matching function for call to 'Client::Client(byte [4], int)'")) {
if (error.trim().equals("no matching function for call to 'Client::Client(byte [4], int)'")) {
error = _("The Client class has been renamed EthernetClient.");
msg = _("\nAs of Arduino 1.0, the Client class in the Ethernet library " +
"has been renamed to EthernetClient.\n\n");
}
if (pieces[3].trim().equals("'Udp' was not declared in this scope")) {
if (error.trim().equals("'Udp' was not declared in this scope")) {
error = _("The Udp class has been renamed EthernetUdp.");
msg = _("\nAs of Arduino 1.0, the Udp class in the Ethernet library " +
"has been renamed to EthernetUdp.\n\n");
}
if (pieces[3].trim().equals("'class TwoWire' has no member named 'send'")) {
if (error.trim().equals("'class TwoWire' has no member named 'send'")) {
error = _("Wire.send() has been renamed Wire.write().");
msg = _("\nAs of Arduino 1.0, the Wire.send() function was renamed " +
"to Wire.write() for consistency with other libraries.\n\n");
}
if (pieces[3].trim().equals("'class TwoWire' has no member named 'receive'")) {
if (error.trim().equals("'class TwoWire' has no member named 'receive'")) {
error = _("Wire.receive() has been renamed Wire.read().");
msg = _("\nAs of Arduino 1.0, the Wire.receive() function was renamed " +
"to Wire.read() for consistency with other libraries.\n\n");
}
if (pieces[3].trim().equals("'Mouse' was not declared in this scope")) {
if (error.trim().equals("'Mouse' was not declared in this scope")) {
error = _("'Mouse' only supported on the Arduino Leonardo");
//msg = _("\nThe 'Mouse' class is only supported on the Arduino Leonardo.\n\n");
}
if (pieces[3].trim().equals("'Keyboard' was not declared in this scope")) {
if (error.trim().equals("'Keyboard' was not declared in this scope")) {
error = _("'Keyboard' only supported on the Arduino Leonardo");
//msg = _("\nThe 'Keyboard' class is only supported on the Arduino Leonardo.\n\n");
}
@@ -799,13 +873,15 @@ public class Compiler implements MessageConsumer {
SketchCode code = sketch.getCode(e.getCodeIndex());
String fileName = (code.isExtension("ino") || code.isExtension("pde")) ? code.getPrettyName() : code.getFileName();
int lineNum = e.getCodeLine() + 1;
s = fileName + ":" + lineNum + ": error: " + pieces[3] + msg;
s = fileName + ":" + lineNum + ": error: " + error + msg;
}
if (e != null) {
if (exception == null || exception.getMessage().equals(e.getMessage())) {
exception = e;
exception.hideStackTrace();
}
}
if (exception == null && e != null) {
exception = e;
exception.hideStackTrace();
}
}
if (s.contains("undefined reference to `SPIClass::begin()'") &&
@@ -831,6 +907,8 @@ public class Compiler implements MessageConsumer {
dict.put("source_file", sourceFile.getAbsolutePath());
dict.put("object_file", objectFile.getAbsolutePath());
setupWarningFlags(dict);
String cmd = prefs.getOrExcept(recipe);
try {
return StringReplacer.formatAndSplit(cmd, dict, true);
@@ -839,6 +917,19 @@ public class Compiler implements MessageConsumer {
}
}
private void setupWarningFlags(PreferencesMap dict) {
if (dict.containsKey("compiler.warning_level")) {
String key = "compiler.warning_flags." + dict.get("compiler.warning_level");
dict.put("compiler.warning_flags", dict.get(key));
} else {
dict.put("compiler.warning_flags", dict.get("compiler.warning_flags.none"));
}
if (dict.get("compiler.warning_flags") == null) {
dict.remove("compiler.warning_flags");
}
}
/////////////////////////////////////////////////////////////////////////////
private void createFolder(File folder) throws RunnerException {
@@ -886,21 +977,21 @@ public class Compiler implements MessageConsumer {
// 2. compile the libraries, outputting .o files to:
// <buildPath>/<library>/
void compileLibraries(List<File> includeFolders) throws RunnerException, PreferencesMapException {
for (Library lib : importedLibraries) {
for (UserLibrary lib : importedLibraries) {
compileLibrary(lib, includeFolders);
}
}
private void compileLibrary(Library lib, List<File> includeFolders)
private void compileLibrary(UserLibrary lib, List<File> includeFolders)
throws RunnerException, PreferencesMapException {
File libFolder = lib.getSrcFolder();
File libBuildFolder = prefs.getFile(("build.path"), lib.getName());
if (lib.useRecursion()) {
// libBuildFolder == {build.path}/LibName
// libFolder == {lib.path}/src
recursiveCompileFilesInFolder(libBuildFolder, libFolder, includeFolders);
} else {
// libFolder == {lib.path}/
// utilityFolder == {lib.path}/utility
@@ -908,11 +999,11 @@ public class Compiler implements MessageConsumer {
// utilityBuildFolder == {build.path}/LibName/utility
File utilityFolder = new File(libFolder, "utility");
File utilityBuildFolder = new File(libBuildFolder, "utility");
includeFolders.add(utilityFolder);
compileFilesInFolder(libBuildFolder, libFolder, includeFolders);
compileFilesInFolder(utilityBuildFolder, utilityFolder, includeFolders);
// other libraries should not see this library's utility/ folder
includeFolders.remove(utilityFolder);
}
@@ -1031,6 +1122,8 @@ public class Compiler implements MessageConsumer {
dict.put("object_files", objectFileList);
dict.put("ide_version", "" + BaseNoGui.REVISION);
setupWarningFlags(dict);
String[] cmdArray;
String cmd = prefs.getOrExcept("recipe.c.combine.pattern");
try {
@@ -1041,6 +1134,18 @@ public class Compiler implements MessageConsumer {
execAsynchronously(cmdArray);
}
void runActions(String recipeClass, PreferencesMap prefs) throws RunnerException, PreferencesMapException {
List<String> patterns = new ArrayList<String>();
for (String key : prefs.keySet()) {
if (key.startsWith("recipe."+recipeClass) && key.endsWith(".pattern"))
patterns.add(key);
}
Collections.sort(patterns);
for (String recipe : patterns) {
runRecipe(recipe);
}
}
void runRecipe(String recipe) throws RunnerException, PreferencesMapException {
PreferencesMap dict = new PreferencesMap(prefs);
dict.put("ide_version", "" + BaseNoGui.REVISION);
@@ -1054,6 +1159,32 @@ public class Compiler implements MessageConsumer {
}
execAsynchronously(cmdArray);
}
//7. Save the .hex file
void saveHex() throws RunnerException {
if (!prefs.containsKey("recipe.output.tmp_file") || !prefs.containsKey("recipe.output.save_file")) {
System.err.println(_("Warning: This core does not support exporting sketches. Please consider upgrading it or contacting its author"));
return;
}
PreferencesMap dict = new PreferencesMap(prefs);
dict.put("ide_version", "" + BaseNoGui.REVISION);
try {
String compiledSketch = prefs.getOrExcept("recipe.output.tmp_file");
compiledSketch = StringReplacer.replaceFromMapping(compiledSketch, dict);
String copyOfCompiledSketch = prefs.getOrExcept("recipe.output.save_file");
copyOfCompiledSketch = StringReplacer.replaceFromMapping(copyOfCompiledSketch, dict);
File compiledSketchFile = new File(prefs.get("build.path"), compiledSketch);
File copyOfCompiledSketchFile = new File(sketch.getFolder(), copyOfCompiledSketch);
FileUtils.copyFile(compiledSketchFile, copyOfCompiledSketchFile);
} catch (Exception e) {
throw new RunnerException(e);
}
}
private static String prepareIncludes(List<File> includeFolders) {
String res = "";
@@ -1120,12 +1251,12 @@ public class Compiler implements MessageConsumer {
// 2. run preproc on that code using the sugg class name
// to create a single .java file and write to buildpath
FileOutputStream outputStream = null;
try {
// Output file
File streamFile = new File(buildPath, sketch.getName() + ".cpp");
FileOutputStream outputStream = new FileOutputStream(streamFile);
outputStream = new FileOutputStream(streamFile);
preprocessor.write(outputStream);
outputStream.close();
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
String msg = _("Build folder disappeared or could not be written");
@@ -1140,15 +1271,32 @@ public class Compiler implements MessageConsumer {
System.err.println(I18n.format(_("Uncaught exception type: {0}"), ex.getClass()));
ex.printStackTrace();
throw new RunnerException(ex.toString());
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
//noop
}
}
}
// grab the imports from the code just preproc'd
importedLibraries = new LibraryList();
importedDuplicateHeaders = new ArrayList<String>();
importedDuplicateLibraries = new ArrayList<LibraryList>();
for (String item : preprocessor.getExtraImports()) {
Library lib = BaseNoGui.importToLibraryTable.get(item);
if (lib != null && !importedLibraries.contains(lib)) {
importedLibraries.add(lib);
LibraryList list = BaseNoGui.importToLibraryTable.get(item);
if (list != null) {
UserLibrary lib = list.peekFirst();
if (lib != null && !importedLibraries.contains(lib)) {
importedLibraries.add(lib);
if (list.size() > 1) {
importedDuplicateHeaders.add(item);
importedDuplicateLibraries.add(list);
}
}
}
}
@@ -1180,6 +1328,8 @@ public class Compiler implements MessageConsumer {
* List of library folders.
*/
private LibraryList importedLibraries;
private List<String> importedDuplicateHeaders;
private List<LibraryList> importedDuplicateLibraries;
/**
* Map an error from a set of processed .java files back to its location

View File

@@ -0,0 +1,113 @@
/*
TargetPackage - Represents a hardware package
Part of the Arduino project - http://www.arduino.cc/
Copyright (c) 2014 Cristian Maglie
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package processing.app.debug;
import static processing.app.I18n._;
import static processing.app.I18n.format;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import processing.app.helpers.PreferencesMap;
public class LegacyTargetBoard implements TargetBoard {
private String id;
private PreferencesMap prefs;
private Map<String, PreferencesMap> menuOptions = new LinkedHashMap<String, PreferencesMap>();
private TargetPlatform containerPlatform;
/**
* Create a TargetBoard based on preferences passed as argument.
*
* @param _prefs
* @return
*/
public LegacyTargetBoard(String _id, PreferencesMap _prefs,
TargetPlatform parent) {
containerPlatform = parent;
id = _id;
prefs = new PreferencesMap(_prefs);
// Setup sub-menus
PreferencesMap menus = prefs.firstLevelMap().get("menu");
if (menus != null)
menuOptions = menus.firstLevelMap();
// Auto generate build.board if not set
if (!prefs.containsKey("build.board")) {
String board = containerPlatform.getId() + "_" + id;
board = board.toUpperCase();
prefs.put("build.board", board);
System.out
.println(format(_("Board {0}:{1}:{2} doesn''t define a ''build.board'' preference. Auto-set to: {3}"),
containerPlatform.getContainerPackage().getId(),
containerPlatform.getId(), id, board));
}
}
@Override
public String getName() {
return prefs.get("name");
}
@Override
public String getId() {
return id;
}
@Override
public PreferencesMap getPreferences() {
return prefs;
}
@Override
public boolean hasMenu(String menuId) {
return menuOptions.containsKey(menuId);
}
@Override
public PreferencesMap getMenuLabels(String menuId) {
return menuOptions.get(menuId).topLevelMap();
}
@Override
public String getMenuLabel(String menuId, String selectionId) {
return getMenuLabels(menuId).get(selectionId);
}
@Override
public Set<String> getMenuIds() {
return menuOptions.keySet();
}
@Override
public PreferencesMap getMenuPreferences(String menuId, String selectionId) {
return menuOptions.get(menuId).subTree(selectionId);
}
@Override
public TargetPlatform getContainerPlatform() {
return containerPlatform;
}
}

View File

@@ -0,0 +1,89 @@
/*
TargetPackage - Represents a hardware package
Part of the Arduino project - http://www.arduino.cc/
Copyright (c) 2011 Cristian Maglie
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package processing.app.debug;
import static processing.app.I18n._;
import static processing.app.helpers.filefilters.OnlyDirs.ONLY_DIRS;
import java.io.File;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import processing.app.I18n;
public class LegacyTargetPackage implements TargetPackage {
private String id;
private Map<String, TargetPlatform> platforms;
public LegacyTargetPackage(String _id, File _folder) throws TargetPlatformException {
id = _id;
platforms = new LinkedHashMap<String, TargetPlatform>();
File[] folders = _folder.listFiles(ONLY_DIRS);
if (folders == null)
return;
for (File subFolder : folders) {
if (!subFolder.exists() || !subFolder.canRead())
continue;
String arch = subFolder.getName();
try {
TargetPlatform platform = new LegacyTargetPlatform(arch, subFolder, this);
platforms.put(arch, platform);
} catch (TargetPlatformException e) {
System.out.println(e.getMessage());
}
}
if (platforms.size() == 0) {
throw new TargetPlatformException(I18n
.format(_("No valid hardware definitions found in folder {0}."),
_folder.getName()));
}
}
@Override
public Map<String, TargetPlatform> getPlatforms() {
return platforms;
}
@Override
public Collection<TargetPlatform> platforms() {
return platforms.values();
}
@Override
public TargetPlatform get(String platform) {
return platforms.get(platform);
}
@Override
public boolean hasPlatform(TargetPlatform platform) {
return platforms.containsKey(platform.getId());
}
@Override
public String getId() {
return id;
}
}

View File

@@ -0,0 +1,241 @@
/*
TargetPlatform - Represents a hardware platform
Part of the Arduino project - http://www.arduino.cc/
Copyright (c) 2009-2014 Arduino
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package processing.app.debug;
import processing.app.BaseNoGui;
import processing.app.I18n;
import processing.app.helpers.PreferencesMap;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import static processing.app.I18n._;
import static processing.app.I18n.format;
public class LegacyTargetPlatform implements TargetPlatform {
private String id;
private File folder;
private TargetPackage containerPackage;
protected PreferencesMap preferences = new PreferencesMap();
private Map<String, TargetBoard> boards = new LinkedHashMap<String, TargetBoard>();
private TargetBoard defaultBoard;
/**
* Contains preferences for every defined programmer
*/
private Map<String, PreferencesMap> programmers = new LinkedHashMap<String, PreferencesMap>();
/**
* Contains labels for top level menus
*/
private PreferencesMap customMenus = new PreferencesMap();
public LegacyTargetPlatform(String _name, File _folder, TargetPackage parent)
throws TargetPlatformException {
id = _name;
folder = _folder;
containerPackage = parent;
// If there is no boards.txt, this is not a valid 1.5 hardware folder
File boardsFile = new File(folder, "boards.txt");
if (!boardsFile.exists() || !boardsFile.canRead())
throw new TargetPlatformException(
format(_("Could not find boards.txt in {0}. Is it pre-1.5?"),
folder.getAbsolutePath()));
// Load boards
try {
Map<String, PreferencesMap> boardsPreferences = new PreferencesMap(
boardsFile).firstLevelMap();
// Create custom menus for this platform
PreferencesMap menus = boardsPreferences.get("menu");
if (menus != null)
customMenus = menus.topLevelMap();
boardsPreferences.remove("menu");
// Create boards
Set<String> boardIds = boardsPreferences.keySet();
for (String boardId : boardIds) {
PreferencesMap preferences = boardsPreferences.get(boardId);
TargetBoard board = new LegacyTargetBoard(boardId, preferences, this);
boards.put(boardId, board);
// Pick the first board as default
if (defaultBoard == null)
defaultBoard = board;
}
} catch (IOException e) {
throw new TargetPlatformException(format(_("Error loading {0}"),
boardsFile.getAbsolutePath()), e);
}
File platformsFile = new File(folder, "platform.txt");
try {
if (platformsFile.exists() && platformsFile.canRead()) {
preferences.load(platformsFile);
}
} catch (IOException e) {
throw new TargetPlatformException(
format(_("Error loading {0}"), platformsFile.getAbsolutePath()), e);
}
// Allow overriding values in platform.txt. This allows changing
// platform.txt (e.g. to use a system-wide toolchain), without
// having to modify platform.txt (which, when running from git,
// prevents files being marked as changed).
File localPlatformsFile = new File(folder, "platform.local.txt");
try {
if (localPlatformsFile.exists() && localPlatformsFile.canRead()) {
preferences.load(localPlatformsFile);
}
} catch (IOException e) {
throw new TargetPlatformException(
format(_("Error loading {0}"), localPlatformsFile.getAbsolutePath()), e);
}
if (!preferences.containsKey("rewriting") || !"disabled".equals(preferences.get("rewriting"))) {
try {
rewriteKeysOfOldPlatformsTxtAndWarnAboutIt();
} catch (IOException e) {
throw new TargetPlatformException(e);
}
}
File progFile = new File(folder, "programmers.txt");
try {
if (progFile.exists() && progFile.canRead()) {
PreferencesMap prefs = new PreferencesMap();
prefs.load(progFile);
programmers = prefs.firstLevelMap();
}
} catch (IOException e) {
throw new TargetPlatformException(format(_("Error loading {0}"),
progFile.getAbsolutePath()), e);
}
}
private void rewriteKeysOfOldPlatformsTxtAndWarnAboutIt() throws IOException {
File platformRewrite = new File(BaseNoGui.getHardwareFolder(), "platform.keys.rewrite.txt");
PreferencesMap platformRewriteProps = new PreferencesMap(platformRewrite);
PreferencesMap oldProps = platformRewriteProps.subTree("old");
PreferencesMap newProps = platformRewriteProps.subTree("new");
String platformName = preferences.get("name");
if (platformName == null) {
platformName = folder.getAbsolutePath();
}
for (Map.Entry<String, String> entry : oldProps.entrySet()) {
String preferencesKey = entry.getKey().substring(entry.getKey().indexOf(".") + 1);
if (preferences.containsKey(preferencesKey) && entry.getValue().equals(preferences.get(preferencesKey))) {
System.err.println(I18n.format(_("Warning: platform.txt from core '{0}' contains deprecated {1}, automatically converted to {2}. Consider upgrading this core."), platformName, preferencesKey + "=" + entry.getValue(), preferencesKey + "=" + newProps.get(entry.getKey())));
preferences.put(preferencesKey, newProps.get(entry.getKey()));
}
}
PreferencesMap addedProps = platformRewriteProps.subTree("added");
for (Map.Entry<String, String> entry : addedProps.entrySet()) {
String keyToAdd = entry.getKey();
String[] keyToAddParts = keyToAdd.split("\\.");
String keyToAddFirstLevel = keyToAddParts[0];
String keyToAddSecondLevel = keyToAddParts[0] + "." + keyToAddParts[1];
if (!preferences.subTree(keyToAddFirstLevel).isEmpty() && !preferences.subTree(keyToAddSecondLevel).isEmpty() && !preferences.containsKey(keyToAdd)) {
System.err.println(I18n.format(_("Warning: platform.txt from core '{0}' misses property {1}, automatically set to {2}. Consider upgrading this core."), platformName, keyToAdd, entry.getValue()));
preferences.put(keyToAdd, entry.getValue());
}
}
}
@Override
public String getId() {
return id;
}
@Override
public File getFolder() {
return folder;
}
@Override
public Map<String, TargetBoard> getBoards() {
return boards;
}
@Override
public PreferencesMap getCustomMenus() {
return customMenus;
}
@Override
public Set<String> getCustomMenuIds() {
return customMenus.keySet();
}
@Override
public Map<String, PreferencesMap> getProgrammers() {
return programmers;
}
@Override
public PreferencesMap getProgrammer(String programmer) {
return getProgrammers().get(programmer);
}
@Override
public PreferencesMap getTool(String tool) {
return getPreferences().subTree("tools").subTree(tool);
}
@Override
public PreferencesMap getPreferences() {
return preferences;
}
@Override
public TargetBoard getBoard(String boardId) {
if (boards.containsKey(boardId)) {
return boards.get(boardId);
}
return defaultBoard;
}
@Override
public TargetPackage getContainerPackage() {
return containerPackage;
}
@Override
public String toString() {
String res = "TargetPlatform: name=" + id + " boards={\n";
for (String boardId : boards.keySet())
res += " " + boardId + " = " + boards.get(boardId) + "\n";
return res + "}";
}
}

View File

@@ -1,76 +1,51 @@
/*
TargetBoard - Represents a hardware board
Part of the Arduino project - http://www.arduino.cc/
Copyright (c) 2014 Cristian Maglie
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package processing.app.debug;
import static processing.app.I18n._;
import static processing.app.I18n.format;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import processing.app.helpers.PreferencesMap;
public class TargetBoard {
private String id;
private PreferencesMap prefs;
private Map<String, PreferencesMap> menuOptions = new LinkedHashMap<String, PreferencesMap>();
private TargetPlatform containerPlatform;
/**
* Create a TargetBoard based on preferences passed as argument.
*
* @param _prefs
* @return
*/
public TargetBoard(String _id, PreferencesMap _prefs, TargetPlatform parent) {
containerPlatform = parent;
id = _id;
prefs = new PreferencesMap(_prefs);
// Setup sub-menus
PreferencesMap menus = prefs.firstLevelMap().get("menu");
if (menus != null)
menuOptions = menus.firstLevelMap();
// Auto generate build.board if not set
if (!prefs.containsKey("build.board")) {
String board = containerPlatform.getId() + "_" + id;
board = board.toUpperCase();
prefs.put("build.board", board);
System.out
.println(format(
_("Board {0}:{1}:{2} doesn''t define a ''build.board'' preference. Auto-set to: {3}"),
containerPlatform.getContainerPackage().getId(),
containerPlatform.getId(), id, board));
}
}
public interface TargetBoard {
/**
* Get the name of the board.
*
* @return
*/
public String getName() {
return prefs.get("name");
}
public String getName();
/**
* Get the identifier of the board
*
* @return
*/
public String getId() {
return id;
}
public String getId();
/**
* Get the full preferences map of the board with a given identifier
* Get the full preferences map of the board
*
* @return
*/
public PreferencesMap getPreferences() {
return prefs;
}
public PreferencesMap getPreferences();
/**
* Check if the board has a sub menu.
@@ -79,9 +54,7 @@ public class TargetBoard {
* The menu ID to check
* @return
*/
public boolean hasMenu(String menuId) {
return menuOptions.containsKey(menuId);
}
public boolean hasMenu(String menuId);
/**
* Returns the options available on a specific menu
@@ -90,9 +63,7 @@ public class TargetBoard {
* The menu ID
* @return
*/
public PreferencesMap getMenuLabels(String menuId) {
return menuOptions.get(menuId).topLevelMap();
}
public PreferencesMap getMenuLabels(String menuId);
/**
* Returns the label of the specified option in the specified menu
@@ -103,13 +74,9 @@ public class TargetBoard {
* The option ID
* @return
*/
public String getMenuLabel(String menuId, String selectionId) {
return getMenuLabels(menuId).get(selectionId);
}
public String getMenuLabel(String menuId, String selectionId);
public Set<String> getMenuIds() {
return menuOptions.keySet();
}
public Set<String> getMenuIds();
/**
* Returns the configuration parameters to override (as a PreferenceMap) when
@@ -121,12 +88,8 @@ public class TargetBoard {
* The option ID
* @return
*/
public PreferencesMap getMenuPreferences(String menuId, String selectionId) {
return menuOptions.get(menuId).subTree(selectionId);
}
public PreferencesMap getMenuPreferences(String menuId, String selectionId);
public TargetPlatform getContainerPlatform() {
return containerPlatform;
}
public TargetPlatform getContainerPlatform();
}

View File

@@ -1,9 +1,8 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
TargetPackage - Represents a hardware package
Part of the Arduino project - http://www.arduino.cc/
Copyright (c) 2011 Cristian Maglie
Copyright (c) 2014 Cristian Maglie
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,61 +20,18 @@
*/
package processing.app.debug;
import static processing.app.I18n._;
import java.io.File;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import processing.app.I18n;
import processing.app.helpers.filefilters.OnlyDirs;
public interface TargetPackage {
public class TargetPackage {
String getId();
private String id;
Map<String, TargetPlatform> getPlatforms();
Map<String, TargetPlatform> platforms = new LinkedHashMap<String, TargetPlatform>();
Collection<TargetPlatform> platforms();
public TargetPackage(String _id, File _folder) throws TargetPlatformException {
id = _id;
TargetPlatform get(String platform);
File[] folders = _folder.listFiles(new OnlyDirs());
if (folders == null)
return;
for (File subFolder : folders) {
if (!subFolder.exists() || !subFolder.canRead())
continue;
String arch = subFolder.getName();
try {
TargetPlatform platform = new TargetPlatform(arch, subFolder, this);
platforms.put(arch, platform);
} catch (TargetPlatformException e) {
System.out.println(e.getMessage());
}
}
if (platforms.size() == 0) {
throw new TargetPlatformException(I18n
.format(_("No valid hardware definitions found in folder {0}."),
_folder.getName()));
}
}
public Map<String, TargetPlatform> getPlatforms() {
return platforms;
}
public Collection<TargetPlatform> platforms() {
return platforms.values();
}
public TargetPlatform get(String platform) {
return platforms.get(platform);
}
public String getId() {
return id;
}
boolean hasPlatform(TargetPlatform platform);
}

View File

@@ -1,9 +1,8 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
TargetPlatform - Represents a hardware platform
Part of the Arduino project - http://www.arduino.cc/
Copyright (c) 2009 David A. Mellis
Copyright (c) 2014 Arduino
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,174 +20,78 @@
*/
package processing.app.debug;
import static processing.app.I18n._;
import static processing.app.I18n.format;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import processing.app.helpers.PreferencesMap;
public class TargetPlatform {
public interface TargetPlatform {
private String id;
private File folder;
private TargetPackage containerPackage;
public String getId();
public File getFolder();
/**
* Contains preferences for every defined board
* Get TargetBoards under this TargetPlatform into a Map that maps the board
* id with the corresponding TargetBoard
*
* @return a Map<String, TargetBoard>
*/
private Map<String, TargetBoard> boards = new LinkedHashMap<String, TargetBoard>();
private TargetBoard defaultBoard;
public Map<String, TargetBoard> getBoards();
public PreferencesMap getCustomMenus();
/**
* Contains preferences for every defined programmer
* Return ids for top level menus
*
* @return a Set<String> with the ids of the top level custom menus
*/
private Map<String, PreferencesMap> programmers = new LinkedHashMap<String, PreferencesMap>();
public Set<String> getCustomMenuIds();
/**
* Contains preferences for platform
* Get preferences for all programmers
*
* @return
*/
private PreferencesMap preferences = new PreferencesMap();
public Map<String, PreferencesMap> getProgrammers();
/**
* Contains labels for top level menus
* Get preferences for a specific programmer
*
* @param programmer
* @return
*/
private PreferencesMap customMenus = new PreferencesMap();
public PreferencesMap getProgrammer(String programmer);
public TargetPlatform(String _name, File _folder, TargetPackage parent)
throws TargetPlatformException {
/**
* Get preferences for a specific tool
*
* @param tool
* @return
*/
public PreferencesMap getTool(String tool);
id = _name;
folder = _folder;
containerPackage = parent;
/**
* Return TargetPlatform preferences
*
* @return
*/
public PreferencesMap getPreferences();
// If there is no boards.txt, this is not a valid 1.5 hardware folder
File boardsFile = new File(folder, "boards.txt");
if (!boardsFile.exists() || !boardsFile.canRead())
throw new TargetPlatformException(
format(_("Could not find boards.txt in {0}. Is it pre-1.5?"),
folder.getAbsolutePath()));
/**
* Get a target board
*
* @param boardId
* @return
*/
public TargetBoard getBoard(String boardId);
// Load boards
try {
Map<String, PreferencesMap> boardsPreferences = new PreferencesMap(
boardsFile).firstLevelMap();
/**
* Get the TargetPackage that contains this TargetPlatform
*
* @return
*/
public TargetPackage getContainerPackage();
// Create custom menus for this platform
PreferencesMap menus = boardsPreferences.get("menu");
if (menus != null)
customMenus = menus.topLevelMap();
boardsPreferences.remove("menu");
// Create boards
Set<String> boardIds = boardsPreferences.keySet();
for (String boardId : boardIds) {
PreferencesMap preferences = boardsPreferences.get(boardId);
TargetBoard board = new TargetBoard(boardId, preferences, this);
boards.put(boardId, board);
// Pick the first board as default
if (defaultBoard == null)
defaultBoard = board;
}
} catch (IOException e) {
throw new TargetPlatformException(format(_("Error loading {0}"),
boardsFile.getAbsolutePath()), e);
}
File platformsFile = new File(folder, "platform.txt");
try {
if (platformsFile.exists() && platformsFile.canRead()) {
preferences.load(platformsFile);
}
} catch (IOException e) {
throw new TargetPlatformException(
format(_("Error loading {0}"), platformsFile.getAbsolutePath()), e);
}
// Allow overriding values in platform.txt. This allows changing
// platform.txt (e.g. to use a system-wide toolchain), without
// having to modify platform.txt (which, when running from git,
// prevents files being marked as changed).
File localPlatformsFile = new File(folder, "platform.local.txt");
try {
if (localPlatformsFile.exists() && localPlatformsFile.canRead()) {
preferences.load(localPlatformsFile);
}
} catch (IOException e) {
throw new TargetPlatformException(
format(_("Error loading {0}"), localPlatformsFile.getAbsolutePath()), e);
}
File progFile = new File(folder, "programmers.txt");
try {
if (progFile.exists() && progFile.canRead()) {
PreferencesMap prefs = new PreferencesMap();
prefs.load(progFile);
programmers = prefs.firstLevelMap();
}
} catch (IOException e) {
throw new TargetPlatformException(format(_("Error loading {0}"), progFile
.getAbsolutePath()), e);
}
}
public String getId() {
return id;
}
public File getFolder() {
return folder;
}
public Map<String, TargetBoard> getBoards() {
return boards;
}
public PreferencesMap getCustomMenus() {
return customMenus;
}
public Set<String> getCustomMenuIds() {
return customMenus.keySet();
}
public Map<String, PreferencesMap> getProgrammers() {
return programmers;
}
public PreferencesMap getProgrammer(String programmer) {
return getProgrammers().get(programmer);
}
public PreferencesMap getTool(String tool) {
return getPreferences().subTree("tools").subTree(tool);
}
public PreferencesMap getPreferences() {
return preferences;
}
public TargetBoard getBoard(String boardId) {
if (boards.containsKey(boardId)) {
return boards.get(boardId);
}
return defaultBoard;
}
public TargetPackage getContainerPackage() {
return containerPackage;
}
@Override
public String toString() {
String res = "TargetPlatform: name=" + id + " boards={\n";
for (String boardId : boards.keySet())
res += " " + boardId + " = " + boards.get(boardId) + "\n";
return res + "}";
}
}

View File

@@ -1,13 +1,5 @@
package processing.app.helpers;
import static processing.app.I18n._;
import java.io.File;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import processing.app.BaseNoGui;
import processing.app.I18n;
import processing.app.PreferencesData;
@@ -16,34 +8,59 @@ import processing.app.debug.TargetPackage;
import processing.app.debug.TargetPlatform;
import processing.app.legacy.PApplet;
import java.io.File;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static processing.app.I18n._;
public class CommandlineParser {
protected static enum ACTION { GUI, NOOP, VERIFY, UPLOAD, GET_PREF };
private enum ACTION {
GUI, NOOP, VERIFY("--verify"), UPLOAD("--upload"), GET_PREF("--get-pref"), INSTALL_BOARD("--install-boards"), INSTALL_LIBRARY("--install-library");
private final String value;
ACTION() {
this.value = null;
}
ACTION(String value) {
this.value = value;
}
}
private ACTION action = ACTION.GUI;
private boolean doVerboseBuild = false;
private boolean doVerboseUpload = false;
private boolean doUseProgrammer = false;
private boolean preserveTempFiles;
private boolean noUploadPort = false;
private boolean forceSavePrefs = false;
private String getPref = null;
private String getPref;
private String boardToInstall;
private String libraryToInstall;
private List<String> filenames = new LinkedList<String>();
public static CommandlineParser newCommandlineParser(String[] args) {
return new CommandlineParser(args);
}
private CommandlineParser(String[] args) {
parseArguments(args);
checkAction();
}
private void parseArguments(String[] args) {
// Map of possible actions and corresponding options
final Map<String, ACTION> actions = new HashMap<String, ACTION>();
actions.put("--verify", ACTION.VERIFY);
actions.put("--upload", ACTION.UPLOAD);
actions.put("--get-pref", ACTION.GET_PREF);
actions.put("--install-boards", ACTION.INSTALL_BOARD);
actions.put("--install-library", ACTION.INSTALL_LIBRARY);
// Check if any files were passed in on the command line
for (int i = 0; i < args.length; i++) {
@@ -56,10 +73,25 @@ public class CommandlineParser {
}
if (a == ACTION.GET_PREF) {
i++;
if (i >= args.length)
BaseNoGui.showError(null, _("Argument required for --get-pref"), 3);
if (i >= args.length) {
BaseNoGui.showError(null, I18n.format(_("Argument required for {0}"), a.value), 3);
}
getPref = args[i];
}
if (a == ACTION.INSTALL_BOARD) {
i++;
if (i >= args.length) {
BaseNoGui.showError(null, I18n.format(_("Argument required for {0}"), a.value), 3);
}
boardToInstall = args[i];
}
if (a == ACTION.INSTALL_LIBRARY) {
i++;
if (i >= args.length) {
BaseNoGui.showError(null, I18n.format(_("Argument required for {0}"), a.value), 3);
}
libraryToInstall = args[i];
}
action = a;
continue;
}
@@ -74,6 +106,12 @@ public class CommandlineParser {
action = ACTION.NOOP;
continue;
}
if (args[i].equals("--preserve-temp-files")) {
preserveTempFiles = true;
if (action == ACTION.GUI)
action = ACTION.NOOP;
continue;
}
if (args[i].equals("--verbose-build")) {
doVerboseBuild = true;
if (action == ACTION.GUI)
@@ -164,7 +202,7 @@ public class CommandlineParser {
filenames.add(args[i]);
}
}
private void checkAction() {
if ((action == ACTION.UPLOAD || action == ACTION.VERIFY) && filenames.size() != 1)
BaseNoGui.showError(null, _("Must specify exactly one sketch file"), 3);
@@ -179,7 +217,7 @@ public class CommandlineParser {
private void processBoardArgument(String selectBoard) {
// No board selected? Nothing to do
if (selectBoard == null)
return;
return;
String[] split = selectBoard.split(":", 4);
@@ -251,27 +289,27 @@ public class CommandlineParser {
public List<String> getFilenames() {
return filenames;
}
public boolean isGetPrefMode() {
return action == ACTION.GET_PREF;
}
public boolean isGuiMode() {
return action == ACTION.GUI;
}
public boolean isNoOpMode() {
return action == ACTION.NOOP;
}
public boolean isUploadMode() {
return action == ACTION.UPLOAD;
}
public boolean isVerifyMode() {
return action == ACTION.VERIFY;
}
public boolean isVerifyOrUploadMode() {
return isVerifyMode() || isUploadMode();
}
@@ -284,4 +322,23 @@ public class CommandlineParser {
return noUploadPort;
}
public boolean isInstallBoard() {
return action == ACTION.INSTALL_BOARD;
}
public boolean isInstallLibrary() {
return action == ACTION.INSTALL_LIBRARY;
}
public String getBoardToInstall() {
return this.boardToInstall;
}
public String getLibraryToInstall() {
return libraryToInstall;
}
public boolean isPreserveTempFiles() {
return preserveTempFiles;
}
}

View File

@@ -73,17 +73,28 @@ public class FileUtils {
}
public static void recursiveDelete(File file) {
if (file == null)
if (file == null) {
return;
}
if (file.isDirectory()) {
for (File current : file.listFiles())
File[] files = file.listFiles();
if (files == null) {
return;
}
for (File current : files) {
recursiveDelete(current);
}
}
file.delete();
}
public static File createTempFolder() throws IOException {
File tmpFolder = new File(System.getProperty("java.io.tmpdir"), "arduino_" + new Random().nextInt(1000000));
return createTempFolderIn(new File(System.getProperty("java.io.tmpdir")));
}
public static File createTempFolderIn(File parent) throws IOException {
File tmpFolder = new File(parent, "arduino_"
+ new Random().nextInt(1000000));
if (!tmpFolder.mkdir()) {
throw new IOException("Unable to create temp folder " + tmpFolder);
}
@@ -249,5 +260,21 @@ public class FileUtils {
return result;
}
public static File newFile(File parent, String... parts) {
File result = parent;
for (String part : parts) {
result = new File(result, part);
}
return result;
}
public static boolean deleteIfExists(File file) {
if (file == null) {
return true;
}
return file.delete();
}
}

View File

@@ -11,7 +11,7 @@ public abstract class NetUtils {
private static boolean isReachableByEcho(InetAddress address) {
try {
return address.isReachable(100);
return address.isReachable(300);
} catch (IOException e) {
return false;
}
@@ -38,7 +38,7 @@ public abstract class NetUtils {
Socket socket = null;
try {
socket = new Socket();
socket.connect(new InetSocketAddress(address, port), 300);
socket.connect(new InetSocketAddress(address, port), 1000);
return true;
} catch (IOException e) {
return false;

View File

@@ -21,18 +21,14 @@
*/
package processing.app.helpers;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import processing.app.legacy.PApplet;
import java.io.*;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import processing.app.legacy.PApplet;
@SuppressWarnings("serial")
public class PreferencesMap extends LinkedHashMap<String, String> {
@@ -71,7 +67,15 @@ public class PreferencesMap extends LinkedHashMap<String, String> {
* @throws IOException
*/
public void load(File file) throws IOException {
load(new FileInputStream(file));
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);
load(fileInputStream);
} finally {
if (fileInputStream != null) {
fileInputStream.close();
}
}
}
protected String processPlatformSuffix(String key, String suffix, boolean isCurrentPlatform) {
@@ -311,7 +315,7 @@ public class PreferencesMap extends LinkedHashMap<String, String> {
* insensitive compared), <b>false</b> in any other case
*/
public boolean getBoolean(String key) {
return new Boolean(get(key));
return Boolean.valueOf(get(key));
}
/**

View File

@@ -26,4 +26,18 @@ public class StringUtils {
String regex = pattern.replace("?", ".?").replace("*", ".*?");
return input.matches(regex);
}
/**
* Returns the string without trailing whitespace characters
*
* @param s
* @return
*/
public static String rtrim(String s) {
int i = s.length() - 1;
while (i >= 0 && Character.isWhitespace(s.charAt(i))) {
i--;
}
return s.substring(0, i + 1);
}
}

View File

@@ -32,11 +32,17 @@ import java.io.FilenameFilter;
*/
public class OnlyDirs implements FilenameFilter {
public boolean accept(File dir, String name) {
if (name.charAt(0) == '.')
return false;
if (name.equals("CVS"))
return false;
return new File(dir, name).isDirectory();
}
public boolean accept(File dir, String name) {
if (name.charAt(0) == '.')
return false;
if (name.equals("CVS"))
return false;
return new File(dir, name).isDirectory();
}
/**
* An handy pre-instantiated object
*/
public static final OnlyDirs ONLY_DIRS = new OnlyDirs();
}

View File

@@ -29,13 +29,15 @@ public class OnlyFilesWithExtension implements FilenameFilter {
String extensions[];
public OnlyFilesWithExtension(String... ext) {
extensions = ext;
this.extensions = ext;
}
public boolean accept(File dir, String name) {
for (String ext : extensions)
if (name.endsWith(ext))
for (String ext : extensions) {
if (name.endsWith(ext)) {
return true;
}
}
return false;
}

View File

@@ -1,16 +1,6 @@
package processing.app.legacy;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.io.*;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.StringTokenizer;
@@ -276,15 +266,26 @@ public class PApplet {
}
static public String[] loadStrings(File file) {
InputStream is = createInput(file);
if (is != null) return loadStrings(is);
return null;
InputStream is = null;
try {
is = createInput(file);
if (is != null) return loadStrings(is);
return null;
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// noop
}
}
}
}
static public String[] loadStrings(InputStream input) {
BufferedReader reader = null;
try {
BufferedReader reader =
new BufferedReader(new InputStreamReader(input, "UTF-8"));
reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
String lines[] = new String[100];
int lineCount = 0;
@@ -297,7 +298,6 @@ public class PApplet {
}
lines[lineCount++] = line;
}
reader.close();
if (lineCount == lines.length) {
return lines;
@@ -311,6 +311,15 @@ public class PApplet {
} catch (IOException e) {
e.printStackTrace();
//throw new RuntimeException("Error inside loadStrings()");
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
//ignore
}
}
}
return null;
}
@@ -321,14 +330,29 @@ public class PApplet {
static public void saveStrings(File file, String strings[]) {
saveStrings(createOutput(file), strings);
OutputStream outputStream = null;
try {
outputStream = createOutput(file);
saveStrings(outputStream, strings);
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
//noop
}
}
}
}
static public void saveStrings(OutputStream output, String strings[]) {
PrintWriter writer = createWriter(output);
for (int i = 0; i < strings.length; i++) {
writer.println(strings[i]);
if (writer == null) {
return;
}
for (String string : strings) {
writer.println(string);
}
writer.flush();
writer.close();

View File

@@ -0,0 +1,151 @@
/*
* This file is part of Arduino.
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
*/
package processing.app.linux;
import javax.swing.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class GTKLookAndFeelFixer {
/*
* All functions of this class courtesy of Klaus Reimer
* https://www.ailis.de/~k/archives/67-Workaround-for-borderless-Java-Swing-menus-on-Linux.html
*/
/*
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* 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 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.
*
* For more information, please refer to <http://unlicense.org/>
*/
/**
* Swing menus are looking pretty bad on Linux when the GTK LaF is used (See
* bug #6925412). It will most likely never be fixed anytime soon so this
* method provides a workaround for it. It uses reflection to change the GTK
* style objects of Swing so popup menu borders have a minimum thickness of
* 1 and menu separators have a minimum vertical thickness of 1.
*/
public static void installGtkPopupBugWorkaround() {
// Get current look-and-feel implementation class
LookAndFeel laf = UIManager.getLookAndFeel();
Class<?> lafClass = laf.getClass();
// Do nothing when not using the problematic LaF
if (!lafClass.getName().equals("com.sun.java.swing.plaf.gtk.GTKLookAndFeel")) {
return;
}
// We do reflection from here on. Failure is silently ignored. The
// workaround is simply not installed when something goes wrong here
try {
// Access the GTK style factory
Field field = lafClass.getDeclaredField("styleFactory");
boolean accessible = field.isAccessible();
field.setAccessible(true);
Object styleFactory = field.get(laf);
field.setAccessible(accessible);
// Fix the horizontal and vertical thickness of popup menu style
Object style = getGtkStyle(styleFactory, new JPopupMenu(), "POPUP_MENU");
fixGtkThickness(style, "yThickness");
fixGtkThickness(style, "xThickness");
// Fix the vertical thickness of the popup menu separator style
style = getGtkStyle(styleFactory, new JSeparator(), "POPUP_MENU_SEPARATOR");
fixGtkThickness(style, "yThickness");
} catch (Exception e) {
// Silently ignored. Workaround can't be applied.
}
}
/**
* Called internally by installGtkPopupBugWorkaround to fix the thickness
* of a GTK style field by setting it to a minimum value of 1.
*
* @param style The GTK style object.
* @param fieldName The field name.
* @throws Exception When reflection fails.
*/
private static void fixGtkThickness(Object style, String fieldName) throws Exception {
Field field = style.getClass().getDeclaredField(fieldName);
boolean accessible = field.isAccessible();
field.setAccessible(true);
field.setInt(style, Math.max(1, field.getInt(style)));
field.setAccessible(accessible);
}
/**
* Called internally by installGtkPopupBugWorkaround. Returns a specific
* GTK style object.
*
* @param styleFactory The GTK style factory.
* @param component The target component of the style.
* @param regionName The name of the target region of the style.
* @return The GTK style.
* @throws Exception When reflection fails.
*/
private static Object getGtkStyle(Object styleFactory, JComponent component, String regionName) throws Exception {
// Create the region object
Class<?> regionClass = Class.forName("javax.swing.plaf.synth.Region");
Field field = regionClass.getField(regionName);
Object region = field.get(regionClass);
// Get and return the style
Class<?> styleFactoryClass = styleFactory.getClass();
Method method = styleFactoryClass.getMethod("getStyle", JComponent.class, regionClass);
boolean accessible = method.isAccessible();
method.setAccessible(true);
Object style = method.invoke(styleFactory, component, region);
method.setAccessible(accessible);
return style;
}
}

View File

@@ -26,10 +26,12 @@ import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.Executor;
import processing.app.PreferencesData;
import processing.app.debug.TargetPackage;
import processing.app.tools.ExternalProcessExecutor;
import processing.app.legacy.PConstants;
import processing.app.tools.CollectStdOutExecutor;
import java.io.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Map;
@@ -42,17 +44,7 @@ public class Platform extends processing.app.Platform {
// TODO Need to be smarter here since KDE people ain't gonna like that GTK.
// It may even throw a weird exception at 'em for their trouble.
public void setLookAndFeel() throws Exception {
// Linux is by default even uglier than metal (Motif?).
// Actually, i'm using native menus, so they're even uglier
// and Motif-looking (Lesstif?). Ick. Need to fix this.
//String lfname = UIManager.getCrossPlatformLookAndFeelClassName();
//UIManager.setLookAndFeel(lfname);
// For 0120, trying out the gtk+ look and feel as the default.
// This is available in Java 1.4.2 and later, and it can't possibly
// be any worse than Metal. (Ocean might also work, but that's for
// Java 1.5, and we aren't going there yet)
//UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
GTKLookAndFeelFixer.installGtkPopupBugWorkaround();
}
@@ -130,8 +122,9 @@ public class Platform extends processing.app.Platform {
@Override
public Map<String, Object> resolveDeviceAttachedTo(String serial, Map<String, TargetPackage> packages, String devicesListOutput) {
assert packages != null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Executor executor = new ExternalProcessExecutor(baos);
Executor executor = new CollectStdOutExecutor(baos);
try {
CommandLine toDevicePath = CommandLine.parse("udevadm info -q path -n " + serial);

View File

@@ -26,12 +26,12 @@ import cc.arduino.packages.BoardPort;
import com.apple.eio.FileManager;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.Executor;
import org.apache.commons.lang3.StringUtils;
import processing.app.debug.TargetPackage;
import processing.app.tools.ExternalProcessExecutor;
import processing.app.legacy.PApplet;
import processing.app.legacy.PConstants;
import processing.app.tools.CollectStdOutExecutor;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.lang.reflect.Method;
@@ -45,12 +45,9 @@ import java.util.List;
*/
public class Platform extends processing.app.Platform {
private String osArch;
public void setLookAndFeel() throws Exception {
// Use the Quaqua L & F on OS X to make JFileChooser less awful
UIManager.setLookAndFeel("ch.randelshofer.quaqua.QuaquaLookAndFeel");
// undo quaqua trying to fix the margins, since we've already
// hacked that in, bit by bit, over the years
UIManager.put("Component.visualMargin", new Insets(1, 1, 1, 1));
}
public Platform() {
@@ -59,35 +56,18 @@ public class Platform extends processing.app.Platform {
Toolkit.getDefaultToolkit();
}
public void init() {
public void init() throws IOException {
System.setProperty("apple.laf.useScreenMenuBar", "true");
/*
try {
String name = "processing.app.macosx.ThinkDifferent";
Class osxAdapter = ClassLoader.getSystemClassLoader().loadClass(name);
Class[] defArgs = { Base.class };
Method registerMethod = osxAdapter.getDeclaredMethod("register", defArgs);
if (registerMethod != null) {
Object[] args = { this };
registerMethod.invoke(osxAdapter, args);
}
} catch (NoClassDefFoundError e) {
// This will be thrown first if the OSXAdapter is loaded on a system without the EAWT
// because OSXAdapter extends ApplicationAdapter in its def
System.err.println("This version of Mac OS X does not support the Apple EAWT." +
"Application Menu handling has been disabled (" + e + ")");
discoverRealOsArch();
}
} catch (ClassNotFoundException e) {
// This shouldn't be reached; if there's a problem with the OSXAdapter
// we should get the above NoClassDefFoundError first.
System.err.println("This version of Mac OS X does not support the Apple EAWT. " +
"Application Menu handling has been disabled (" + e + ")");
} catch (Exception e) {
System.err.println("Exception while loading BaseOSX:");
e.printStackTrace();
}
*/
private void discoverRealOsArch() throws IOException {
CommandLine uname = CommandLine.parse("uname -m");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CollectStdOutExecutor executor = new CollectStdOutExecutor(baos);
executor.execute(uname);
osArch = StringUtils.trim(new String(baos.toByteArray()));
}
@@ -115,7 +95,7 @@ public class Platform extends processing.app.Platform {
public void openURL(String url) throws Exception {
if (PApplet.javaVersion < 1.6f) {
if (url.startsWith("http://")) {
if (url.startsWith("http")) {
// formerly com.apple.eio.FileManager.openURL(url);
// but due to deprecation, instead loading dynamically
try {
@@ -139,7 +119,7 @@ public class Platform extends processing.app.Platform {
// for Java 1.6, replacing with java.awt.Desktop.browse()
// and java.awt.Desktop.open()
if (url.startsWith("http://")) { // browse to a location
if (url.startsWith("http")) { // browse to a location
Method browseMethod =
desktopClass.getMethod("browse", new Class[] { URI.class });
browseMethod.invoke(desktop, new Object[] { new URI(url) });
@@ -211,6 +191,7 @@ public class Platform extends processing.app.Platform {
@Override
public Map<String, Object> resolveDeviceAttachedTo(String serial, Map<String, TargetPackage> packages, String devicesListOutput) {
assert packages != null;
if (devicesListOutput == null) {
return super.resolveDeviceAttachedTo(serial, packages, devicesListOutput);
}
@@ -231,7 +212,7 @@ public class Platform extends processing.app.Platform {
@Override
public String preListAllCandidateDevices() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Executor executor = new ExternalProcessExecutor(baos);
Executor executor = new CollectStdOutExecutor(baos);
try {
CommandLine toDevicePath = CommandLine.parse("/usr/sbin/system_profiler SPUSBDataType");
@@ -250,11 +231,16 @@ public class Platform extends processing.app.Platform {
List<BoardPort> filteredPorts = new LinkedList<BoardPort>();
for (BoardPort port : ports) {
if (!port.getAddress().startsWith("/dev/cu.")) {
if (!port.getAddress().startsWith("/dev/tty.")) {
filteredPorts.add(port);
}
}
return filteredPorts;
}
@Override
public String getOsArch() {
return osArch;
}
}

View File

@@ -0,0 +1,126 @@
/*
* This file is part of Arduino.
*
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package processing.app.packages;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import cc.arduino.contributions.libraries.ContributedLibraryReference;
public class LegacyUserLibrary extends UserLibrary {
private String name;
public static LegacyUserLibrary create(File libFolder) {
// construct an old style library
LegacyUserLibrary res = new LegacyUserLibrary();
res.setInstalledFolder(libFolder);
res.setInstalled(true);
res.layout = LibraryLayout.FLAT;
res.name = libFolder.getName();
return res;
}
@Override
public String getName() {
return name;
}
@Override
public List<String> getArchitectures() {
return Arrays.asList("*");
}
@Override
public String getAuthor() {
return null;
}
@Override
public String getParagraph() {
return null;
}
@Override
public String getSentence() {
return null;
}
@Override
public String getWebsite() {
return null;
}
@Override
public String getCategory() {
return "Uncategorized";
}
@Override
public String getLicense() {
return null;
}
@Override
public String getVersion() {
return null;
}
@Override
public String getMaintainer() {
return null;
}
@Override
public String getChecksum() {
return null;
}
@Override
public long getSize() {
return 0;
}
@Override
public String getUrl() {
return null;
}
@Override
public List<ContributedLibraryReference> getRequires() {
return null;
}
@Override
public String toString() {
return "LegacyLibrary:" + name + "\n";
}
}

View File

@@ -1,14 +1,42 @@
/*
* This file is part of Arduino.
*
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package processing.app.packages;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import processing.app.helpers.FileUtils;
@SuppressWarnings("serial")
public class LibraryList extends ArrayList<Library> {
public class LibraryList extends LinkedList<UserLibrary> {
public LibraryList(LibraryList libs) {
super(libs);
@@ -18,53 +46,46 @@ public class LibraryList extends ArrayList<Library> {
super();
}
public Library getByName(String name) {
for (Library l : this)
public LibraryList(List<UserLibrary> ideLibs) {
super(ideLibs);
}
public UserLibrary getByName(String name) {
for (UserLibrary l : this)
if (l.getName().equals(name))
return l;
return null;
}
public void addOrReplace(Library lib) {
Library l = getByName(lib.getName());
if (l != null)
remove(l);
public void addOrReplace(UserLibrary lib) {
remove(lib);
add(lib);
}
public void addOrReplaceAll(Collection<? extends Library> c) {
for (Library l : c)
addOrReplace(l);
public void remove(UserLibrary lib) {
UserLibrary l = getByName(lib.getName());
if (l != null)
super.remove(l);
}
public void sort() {
Collections.sort(this, Library.CASE_INSENSITIVE_ORDER);
}
public Library search(String name, String arch) {
for (Library lib : this) {
if (!lib.getName().equals(name))
continue;
if (!lib.supportsArchitecture(arch))
continue;
return lib;
}
return null;
}
public LibraryList filterByArchitecture(String reqArch) {
LibraryList res = new LibraryList();
for (Library lib : this)
if (lib.supportsArchitecture(reqArch))
res.add(lib);
return res;
Collections.sort(this, UserLibrary.CASE_INSENSITIVE_ORDER);
}
public LibraryList filterLibrariesInSubfolder(File subFolder) {
LibraryList res = new LibraryList();
for (Library lib : this)
if (FileUtils.isSubDirectory(subFolder, lib.getFolder()))
for (UserLibrary lib : this) {
if (FileUtils.isSubDirectory(subFolder, lib.getInstalledFolder())) {
res.add(lib);
}
}
return res;
}
public boolean hasLibrary(UserLibrary lib) {
for (UserLibrary l : this)
if (l == lib) return true;
return false;
}
}

View File

@@ -1,16 +1,46 @@
/*
* This file is part of Arduino.
*
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
*
* Arduino is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package processing.app.packages;
import cc.arduino.contributions.libraries.ContributedLibrary;
import cc.arduino.contributions.libraries.ContributedLibraryReference;
import processing.app.helpers.FileUtils;
import processing.app.helpers.PreferencesMap;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import processing.app.helpers.FileUtils;
import processing.app.helpers.PreferencesMap;
public class Library {
public class UserLibrary extends ContributedLibrary {
private String name;
private String version;
@@ -18,44 +48,23 @@ public class Library {
private String maintainer;
private String sentence;
private String paragraph;
private String url;
private String website;
private String category;
private String license;
private List<String> architectures;
private File folder;
private boolean isLegacy;
private enum LibraryLayout { FLAT, RECURSIVE };
private LibraryLayout layout;
private List<String> types;
private List<String> declaredTypes;
private static final List<String> MANDATORY_PROPERTIES = Arrays
.asList(new String[] { "name", "version", "author", "maintainer",
"sentence", "paragraph", "url" });
.asList(new String[]{"name", "version", "author", "maintainer",
"sentence", "paragraph", "url"});
private static final List<String> CATEGORIES = Arrays.asList(new String[] {
"Display", "Communication", "Signal Input/Output", "Sensors",
"Device Control", "Timing", "Data Storage", "Data Processing", "Other",
"Uncategorized" });
private static final List<String> CATEGORIES = Arrays.asList(new String[]{
"Display", "Communication", "Signal Input/Output", "Sensors",
"Device Control", "Timing", "Data Storage", "Data Processing", "Other",
"Uncategorized"});
/**
* Scans inside a folder and create a Library object out of it. Automatically
* detects legacy libraries. Automatically fills metadata from
* library.properties file if found.
*
* @param libFolder
* @return
*/
static public Library create(File libFolder) throws IOException {
// A library is considered "new" if it contains a file called
// "library.properties"
File check = new File(libFolder, "library.properties");
if (!check.exists() || !check.isFile())
return createLegacyLibrary(libFolder);
else
return createLibrary(libFolder);
}
private static Library createLibrary(File libFolder) throws IOException {
public static UserLibrary create(File libFolder) throws IOException {
// Parse metadata
File propertiesFile = new File(libFolder, "library.properties");
PreferencesMap properties = new PreferencesMap();
@@ -66,16 +75,16 @@ public class Library {
// Compatibility with 1.5 rev.1 libraries:
// "email" field changed to "maintainer"
if (!properties.containsKey("maintainer") &&
properties.containsKey("email"))
if (!properties.containsKey("maintainer") && properties.containsKey("email")) {
properties.put("maintainer", properties.get("email"));
}
// Compatibility with 1.5 rev.1 libraries:
// "arch" folder no longer supported
File archFolder = new File(libFolder, "arch");
if (archFolder.isDirectory())
throw new IOException("'arch' folder is no longer supported! See "
+ "http://goo.gl/gfFJzU for more information");
+ "http://goo.gl/gfFJzU for more information");
// Check mandatory properties
for (String p : MANDATORY_PROPERTIES)
@@ -93,7 +102,7 @@ public class Library {
File utilFolder = new File(libFolder, "utility");
if (utilFolder.exists() && utilFolder.isDirectory()) {
throw new IOException(
"Library can't use both 'src' and 'utility' folders.");
"Library can't use both 'src' and 'utility' folders.");
}
} else {
// Layout with source code on library's root and "utility" folders
@@ -104,8 +113,7 @@ public class Library {
for (File file : libFolder.listFiles()) {
if (file.isDirectory()) {
if (FileUtils.isSCCSOrHiddenFile(file)) {
System.out.println("WARNING: Spurious " + file.getName() +
" folder in '" + properties.get("name") + "' library");
System.out.println("WARNING: Spurious " + file.getName() + " folder in '" + properties.get("name") + "' library");
continue;
}
}
@@ -123,110 +131,88 @@ public class Library {
if (category == null)
category = "Uncategorized";
if (!CATEGORIES.contains(category)) {
category = "Uncategorized";
System.out.println("WARNING: Category '" + category + "' in library " +
properties.get("name") + " is not valid. Setting to 'Uncategorized'");
properties.get("name") + " is not valid. Setting to 'Uncategorized'");
category = "Uncategorized";
}
String license = properties.get("license");
if (license == null)
if (license == null) {
license = "Unspecified";
}
Library res = new Library();
res.folder = libFolder;
String types = properties.get("types");
if (types == null) {
types = "Contributed";
}
List<String> typesList = new LinkedList<String>();
for (String type : types.split(",")) {
typesList.add(type.trim());
}
UserLibrary res = new UserLibrary();
res.setInstalledFolder(libFolder);
res.setInstalled(true);
res.name = properties.get("name").trim();
res.version = properties.get("version").trim();
res.author = properties.get("author").trim();
res.maintainer = properties.get("maintainer").trim();
res.sentence = properties.get("sentence").trim();
res.paragraph = properties.get("paragraph").trim();
res.url = properties.get("url").trim();
res.website = properties.get("url").trim();
res.category = category.trim();
res.license = license.trim();
res.architectures = archs;
res.isLegacy = false;
res.layout = layout;
res.declaredTypes = typesList;
return res;
}
private static Library createLegacyLibrary(File libFolder) {
// construct an old style library
Library res = new Library();
res.folder = libFolder;
res.layout = LibraryLayout.FLAT;
res.name = libFolder.getName();
res.architectures = Arrays.asList("*");
res.isLegacy = true;
return res;
}
/**
* Returns <b>true</b> if the library declares to support the specified
* architecture (through the "architectures" property field).
*
* @param reqArch
* @return
*/
public boolean supportsArchitecture(String reqArch) {
return architectures.contains(reqArch) || architectures.contains("*");
}
/**
* Returns <b>true</b> if the library declares to support at least one of the
* specified architectures.
*
* @param reqArchs
* A List of architectures to check
* @return
*/
public boolean supportsArchitecture(List<String> reqArchs) {
if (reqArchs.contains("*"))
return true;
for (String reqArch : reqArchs)
if (supportsArchitecture(reqArch))
return true;
return false;
}
public static final Comparator<Library> CASE_INSENSITIVE_ORDER = new Comparator<Library>() {
@Override
public int compare(Library o1, Library o2) {
return o1.getName().compareToIgnoreCase(o2.getName());
}
};
@Override
public String getName() {
return name;
}
public File getFolder() {
return folder;
}
@Override
public List<String> getArchitectures() {
return architectures;
}
@Override
public String getAuthor() {
return author;
}
@Override
public String getParagraph() {
return paragraph;
}
@Override
public String getSentence() {
return sentence;
}
public String getUrl() {
return url;
@Override
public String getWebsite() {
return website;
}
@Override
public String getCategory() {
return category;
}
@Override
public List<String> getTypes() {
return types;
}
public void setTypes(List<String> types) {
this.types = types;
}
@Override
public String getLicense() {
return license;
}
@@ -235,44 +221,82 @@ public class Library {
return CATEGORIES;
}
@Override
public void setCategory(String category) {
this.category = category;
}
@Override
public String getVersion() {
return version;
}
@Override
public String getMaintainer() {
return maintainer;
}
@Override
public String getChecksum() {
return null;
}
@Override
public long getSize() {
return 0;
}
@Override
public String getUrl() {
return null;
}
@Override
public String getArchiveFileName() {
return null;
}
@Override
public List<ContributedLibraryReference> getRequires() {
return null;
}
public List<String> getDeclaredTypes() {
return declaredTypes;
}
protected enum LibraryLayout {
FLAT, RECURSIVE
}
protected LibraryLayout layout;
public File getSrcFolder() {
switch (layout) {
case FLAT:
return getInstalledFolder();
case RECURSIVE:
return new File(getInstalledFolder(), "src");
default:
return null; // Keep compiler happy :-(
}
}
public boolean useRecursion() {
return (layout == LibraryLayout.RECURSIVE);
}
public File getSrcFolder() {
switch (layout) {
case FLAT:
return folder;
case RECURSIVE:
return new File(folder, "src");
default:
return null; // Keep compiler happy :-(
}
}
public boolean isLegacy() {
return isLegacy;
}
@Override
public String toString() {
String res = "Library:";
res += " (name=" + name + ")";
res += " (version=" + version + ")";
res += " (author=" + author + ")";
res += " (maintainer=" + maintainer + ")";
res += " (sentence=" + sentence + ")";
res += " (paragraph=" + paragraph + ")";
res += " (url=" + url + ")";
res += " (architectures=" + architectures + ")";
String res = "Library: " + name + "\n";
res += " (version=" + version + ")\n";
res += " (author=" + author + ")\n";
res += " (maintainer=" + maintainer + ")\n";
res += " (sentence=" + sentence + ")\n";
res += " (paragraph=" + paragraph + ")\n";
res += " (url=" + website + ")\n";
res += " (architectures=" + architectures + ")\n";
return res;
}
}

View File

@@ -42,6 +42,9 @@ import java.util.regex.*;
* Class that orchestrates preprocessing p5 syntax into straight Java.
*/
public class PdePreprocessor {
private static final String IMPORT_REGEX = "^\\s*#include\\s*[<\"](\\S+)[\">]";
// stores number of built user-defined function prototypes
public int prototypeCount = 0;
@@ -94,10 +97,9 @@ public class PdePreprocessor {
}
//String importRegexp = "(?:^|\\s|;)(import\\s+)(\\S+)(\\s*;)";
String importRegexp = "^\\s*#include\\s*[<\"](\\S+)[\">]";
programImports = new ArrayList<String>();
String[][] pieces = PApplet.matchAll(program, importRegexp);
String[][] pieces = PApplet.matchAll(program, IMPORT_REGEX);
if (pieces != null)
for (int i = 0; i < pieces.length; i++)
@@ -121,6 +123,19 @@ public class PdePreprocessor {
return headerCount + prototypeCount;
}
public static List<String> findIncludes(String code){
String[][] pieces = PApplet.matchAll(code, IMPORT_REGEX);
ArrayList programImports = new ArrayList<String>();
if (pieces != null)
for (int i = 0; i < pieces.length; i++)
programImports.add(pieces[i][1]); // the package name
return programImports;
}
static String substituteUnicode(String program) {
// check for non-ascii chars (these will be/must be in unicode format)

View File

@@ -10,9 +10,9 @@ import java.io.OutputStream;
/**
* Handy process executor, collecting stdout into a given OutputStream
*/
public class ExternalProcessExecutor extends DefaultExecutor {
public class CollectStdOutExecutor extends DefaultExecutor {
public ExternalProcessExecutor(final OutputStream os) {
public CollectStdOutExecutor(final OutputStream stdout) {
this.setStreamHandler(new ExecuteStreamHandler() {
@Override
public void setProcessInputStream(OutputStream outputStream) throws IOException {
@@ -27,7 +27,7 @@ public class ExternalProcessExecutor extends DefaultExecutor {
byte[] buf = new byte[4096];
int bytes = -1;
while ((bytes = inputStream.read(buf)) != -1) {
os.write(buf, 0, bytes);
stdout.write(buf, 0, bytes);
}
}

View File

@@ -0,0 +1,49 @@
package processing.app.tools;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteStreamHandler;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Handy process executor, collecting stdout and stderr into given OutputStreams
*/
public class CollectStdOutStdErrExecutor extends DefaultExecutor {
public CollectStdOutStdErrExecutor(final OutputStream stdout, final OutputStream stderr) {
this.setStreamHandler(new ExecuteStreamHandler() {
@Override
public void setProcessInputStream(OutputStream outputStream) throws IOException {
}
@Override
public void setProcessErrorStream(InputStream inputStream) throws IOException {
byte[] buf = new byte[4096];
int bytes = -1;
while ((bytes = inputStream.read(buf)) != -1) {
stderr.write(buf, 0, bytes);
}
}
@Override
public void setProcessOutputStream(InputStream inputStream) throws IOException {
byte[] buf = new byte[4096];
int bytes = -1;
while ((bytes = inputStream.read(buf)) != -1) {
stdout.write(buf, 0, bytes);
}
}
@Override
public void start() throws IOException {
}
@Override
public void stop() {
}
});
}
}

View File

@@ -0,0 +1,35 @@
package processing.app.tools;
import org.apache.commons.exec.CommandLine;
import processing.app.helpers.OSUtils;
import java.io.File;
public class DoubleQuotedArgumentsOnWindowsCommandLine extends CommandLine {
public DoubleQuotedArgumentsOnWindowsCommandLine(String executable) {
super(executable);
}
public DoubleQuotedArgumentsOnWindowsCommandLine(File executable) {
super(executable);
}
public DoubleQuotedArgumentsOnWindowsCommandLine(CommandLine other) {
super(other);
}
@Override
public CommandLine addArgument(String argument, boolean handleQuoting) {
// Brutal hack to workaround windows command line parsing.
// http://stackoverflow.com/questions/5969724/java-runtime-exec-fails-to-escape-characters-properly
// http://msdn.microsoft.com/en-us/library/a1y7w461.aspx
// http://bugs.sun.com/view_bug.do?bug_id=6468220
// http://bugs.sun.com/view_bug.do?bug_id=6518827
if (argument.contains("\"") && OSUtils.isWindows()) {
argument = argument.replace("\"", "\\\"");
}
return super.addArgument(argument, handleQuoting);
}
}

View File

@@ -22,23 +22,21 @@
package processing.app.windows;
import com.sun.jna.Library;
import com.sun.jna.Native;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.Executor;
import processing.app.PreferencesData;
import processing.app.debug.TargetPackage;
import processing.app.legacy.PApplet;
import processing.app.legacy.PConstants;
import processing.app.tools.ExternalProcessExecutor;
import processing.app.tools.CollectStdOutExecutor;
import processing.app.windows.Registry.REGISTRY_ROOT_KEY;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -55,7 +53,7 @@ public class Platform extends processing.app.Platform {
"\\arduino.exe \"%1\"";
static final String DOC = "Arduino.Document";
public void init() {
public void init() throws IOException {
super.init();
checkAssociations();
@@ -244,7 +242,7 @@ public class Platform extends processing.app.Platform {
// "Access is denied" in both cygwin and the "dos" prompt.
//Runtime.getRuntime().exec("cmd /c " + currentDir + "\\reference\\" +
// referenceFile + ".html");
if (url.startsWith("http://")) {
if (url.startsWith("http")) {
// open dos prompt, give it 'start' command, which will
// open the url properly. start by itself won't work since
// it appears to need cmd
@@ -281,36 +279,6 @@ public class Platform extends processing.app.Platform {
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
// Code partially thanks to Richard Quirk from:
// http://quirkygba.blogspot.com/2009/11/setting-environment-variables-in-java.html
static WinLibC clib = (WinLibC) Native.loadLibrary("msvcrt", WinLibC.class);
public interface WinLibC extends Library {
//WinLibC INSTANCE = (WinLibC) Native.loadLibrary("msvcrt", WinLibC.class);
//libc = Native.loadLibrary("msvcrt", WinLibC.class);
public int _putenv(String name);
}
public void setenv(String variable, String value) {
//WinLibC clib = WinLibC.INSTANCE;
clib._putenv(variable + "=" + value);
}
public String getenv(String variable) {
return System.getenv(variable);
}
public int unsetenv(String variable) {
//WinLibC clib = WinLibC.INSTANCE;
//clib._putenv(variable + "=");
//return 0;
return clib._putenv(variable + "=");
}
@Override
public String getName() {
return PConstants.platformNames[PConstants.WINDOWS];
@@ -318,6 +286,7 @@ public class Platform extends processing.app.Platform {
@Override
public Map<String, Object> resolveDeviceAttachedTo(String serial, Map<String, TargetPackage> packages, String devicesListOutput) {
assert packages != null;
if (devicesListOutput == null) {
return super.resolveDeviceAttachedTo(serial, packages, devicesListOutput);
}
@@ -338,7 +307,7 @@ public class Platform extends processing.app.Platform {
@Override
public String preListAllCandidateDevices() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Executor executor = new ExternalProcessExecutor(baos);
Executor executor = new CollectStdOutExecutor(baos);
try {
String listComPorts = new File(System.getProperty("user.dir"), "hardware/tools/listComPorts.exe").getCanonicalPath();
@@ -350,4 +319,24 @@ public class Platform extends processing.app.Platform {
return super.preListAllCandidateDevices();
}
}
@Override
public void fixPrefsFilePermissions(File prefsFile) throws IOException {
//noop
}
public List<File> postInstallScripts(File folder) {
List<File> scripts = new LinkedList<File>();
scripts.add(new File(folder, "post_install.bat"));
return scripts;
}
public void symlink(File something, File somewhere) throws IOException, InterruptedException {
}
public void link(File something, File somewhere) throws IOException, InterruptedException {
}
public void chmod(File file, int mode) throws IOException, InterruptedException {
}
}