Package it.baeyens.arduino.tools

Source Code of it.baeyens.arduino.tools.ArduinoHelpers

package it.baeyens.arduino.tools;

import it.baeyens.arduino.common.ArduinoConst;
import it.baeyens.arduino.common.ArduinoInstancePreferences;
import it.baeyens.arduino.common.Common;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.envvar.EnvironmentVariable;
import org.eclipse.cdt.core.envvar.IContributedEnvironment;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
import org.eclipse.cdt.core.envvar.IEnvironmentVariableManager;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.settings.model.CIncludePathEntry;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICFolderDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSetting;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.language.settings.providers.AbstractBuiltinSpecsDetector;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IPathVariableManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.console.MessageConsole;

/**
* ArduinoHelpers is a static class containing general purpose functions
*
* @author Jan Baeyens
*
*/
public class ArduinoHelpers extends Common {

    /**
     * This method is the internal working class that adds the provided includepath to all configurations and languages.
     *
     * @param configurationDescription
     *            The configuration description of the project to add it to
     * @param IncludePath
     *            The path to add to the include folders
     * @see addLibraryDependency {@link #addLibraryDependency(IProject, IProject)}
     */
    private static void addIncludeFolder(ICConfigurationDescription configurationDescription, IPath IncludePath) {
  // find all languages
  ICFolderDescription folderDescription = configurationDescription.getRootFolderDescription();
  ICLanguageSetting[] languageSettings = folderDescription.getLanguageSettings();

  // Add include path to all languages
  for (int idx = 0; idx < languageSettings.length; idx++) {
      ICLanguageSetting lang = languageSettings[idx];
      String LangID = lang.getLanguageId();
      if (LangID != null) {
    if (LangID.startsWith("org.eclipse.cdt.")) { //$NON-NLS-1$
        ICLanguageSettingEntry[] OrgIncludeEntries = lang.getSettingEntries(ICSettingEntry.INCLUDE_PATH);
        ICLanguageSettingEntry[] IncludeEntries = new ICLanguageSettingEntry[OrgIncludeEntries.length + 1];
        System.arraycopy(OrgIncludeEntries, 0, IncludeEntries, 0, OrgIncludeEntries.length);
        IncludeEntries[OrgIncludeEntries.length] = new CIncludePathEntry(IncludePath, ICSettingEntry.VALUE_WORKSPACE_PATH); // (location.toString());
        lang.setSettingEntries(ICSettingEntry.INCLUDE_PATH, IncludeEntries);
    }
      }
  }
    }

    /**
     * Removes include folders that are not valid. This method does not save the configurationDescription description
     *
     * @param configurationDescription
     *            the configuration that is checked
     * @return true is a include path has been removed. False if the include path remains unchanged.
     */
    public static boolean removeInvalidIncludeFolders(ICConfigurationDescription configurationDescription) {
  // find all languages
  ICFolderDescription folderDescription = configurationDescription.getRootFolderDescription();
  ICLanguageSetting[] languageSettings = folderDescription.getLanguageSettings();
  boolean hasChange = false;
  // Add include path to all languages
  for (int idx = 0; idx < languageSettings.length; idx++) {
      ICLanguageSetting lang = languageSettings[idx];
      String LangID = lang.getLanguageId();
      if (LangID != null) {
    if (LangID.startsWith("org.eclipse.cdt.")) { //$NON-NLS-1$
        ICLanguageSettingEntry[] OrgIncludeEntries = lang.getSettingEntries(ICSettingEntry.INCLUDE_PATH);
        ICLanguageSettingEntry[] OrgIncludeEntriesFull = lang.getResolvedSettingEntries(ICSettingEntry.INCLUDE_PATH);
        int copiedEntry = 0;
        for (int curEntry = 0; curEntry < OrgIncludeEntries.length; curEntry++) {
      IPath cusPath = ((CIncludePathEntry) OrgIncludeEntriesFull[curEntry]).getFullPath();
      if ((ResourcesPlugin.getWorkspace().getRoot().exists(cusPath))
        || (((CIncludePathEntry) OrgIncludeEntries[curEntry]).isBuiltIn())) {
          OrgIncludeEntries[copiedEntry++] = OrgIncludeEntries[curEntry];
      }
        }
        if (copiedEntry != OrgIncludeEntries.length) // do not save
                 // if nothing
                 // has changed
        {
      ICLanguageSettingEntry[] IncludeEntries = new ICLanguageSettingEntry[copiedEntry];
      System.arraycopy(OrgIncludeEntries, 0, IncludeEntries, 0, copiedEntry);
      lang.setSettingEntries(ICSettingEntry.INCLUDE_PATH, IncludeEntries);
      hasChange = true;
        }
    }
      }
  }
  return hasChange;
    }

    /**
     * This method adds the provided path to the include path of all configurations and languages.
     *
     * @param project
     *            The project to add it to
     * @param IncludePath
     *            The path to add to the include folders
     * @see addLibraryDependency {@link #addLibraryDependency(IProject, IProject)}
     */
    public static void addIncludeFolder(IProject project, IPath IncludePath) {
  // find all languages
  ICProjectDescriptionManager mngr = CoreModel.getDefault().getProjectDescriptionManager();
  ICProjectDescription projectDescription = mngr.getProjectDescription(project, true);
  ICConfigurationDescription configurationDescription = projectDescription.getDefaultSettingConfiguration();
  addIncludeFolder(configurationDescription, IncludePath);

  projectDescription.setActiveConfiguration(configurationDescription);
  projectDescription.setCdtProjectCreated();
  try {
      mngr.setProjectDescription(project, projectDescription, true, null);
  } catch (CoreException e) {
      Common.log(new Status(IStatus.ERROR, ArduinoConst.CORE_PLUGIN_ID, "Could not add folder " + IncludePath.toOSString()
        + " to includepoth in project" + project.getName(), e));
  }

    }

    public static void addCodeFolder(IProject project, String PathVarName, String SubFolder, String LinkName,
      ICConfigurationDescription configurationDescriptions[]) throws CoreException {
  for (ICConfigurationDescription curConfig : configurationDescriptions) {
      ArduinoHelpers.addCodeFolder(project, PathVarName, SubFolder, LinkName, curConfig);
  }

    }

    /**
     * Creates a folder and links the folder to an existing folder Parent folders of the target folder are created if needed. In case this method
     * fails an error is logged.
     *
     * @param project
     *            the project the newly created folder will belong to
     * @param target
     *            the folder name relative to the project
     * @param source
     *            the fully qualified name of the folder to link to
     */
    public static void LinkFolderToFolder(IProject project, IPath source, IPath target) {

  // create target parent folder and grandparents
  IPath ParentFolders = new Path(target.toString()).removeLastSegments(1);
  for (int curfolder = ParentFolders.segmentCount() - 1; curfolder >= 0; curfolder--) {
      try {
    createNewFolder(project, ParentFolders.removeLastSegments(curfolder).toString(), null);
      } catch (CoreException e) {// ignore this error as the parent
               // folders may have been created yet
      }
  }

  // create the actual link
  try {
      createNewFolder(project, target.toString(), URIUtil.toURI(source));
  } catch (CoreException e) {
      Common.log(new Status(IStatus.ERROR, ArduinoConst.CORE_PLUGIN_ID, "Could not create folder " + target, e));
  }
    }

    /**
     * This method creates a link folder in the project and add the folder as a source path to the project it also adds the path to the include folder
     * if the includepath parameter points to a path that contains a subfolder named "utility" this subfolder will be added to the include path as
     * well <br/>
     * Forget about this. Arduino made this all so complicated I don't know anymore what needs to be added to what<br/>
     * <br/>
     *
     * note Arduino has these subfolders in the libraries that need to be include.<br/>
     * <br/>
     *
     * note that in the current eclipse version, there is no need to add the subfolder as a code folder. This may change in the future as it looks
     * like a bug to me.<br/>
     *
     * @param project
     * @param Path
     * @throws CoreException
     *
     * @see addLibraryDependency {@link #addLibraryDependency(IProject, IProject)}
     */
    public static void addCodeFolder(IProject project, String PathVarName, String SubFolder, String LinkName,
      ICConfigurationDescription configurationDescription) throws CoreException {
  IFolder link = project.getFolder(LinkName);

  LinkFolderToFolder(project, new Path(PathVarName).append(SubFolder), new Path(LinkName));

  // Now the folder has been created we need to make sure the special folders are added to the path
  addIncludeFolder(configurationDescription, link.getFullPath());

  IPathVariableManager pathMan = project.getPathVariableManager();

  String possibleIncludeFolder = "utility";
  File file = new File(new Path(pathMan.resolveURI(pathMan.getURIValue(PathVarName)).getPath()).append(SubFolder).append(possibleIncludeFolder)
    .toString());
  if (file.exists()) {
      addIncludeFolder(configurationDescription, link.getFullPath().append(possibleIncludeFolder));
  }

  possibleIncludeFolder = "src";
  file = new File(new Path(pathMan.resolveURI(pathMan.getURIValue(PathVarName)).getPath()).append(SubFolder).append(possibleIncludeFolder)
    .toString());
  if (file.exists()) {
      addIncludeFolder(configurationDescription, link.getFullPath().append(possibleIncludeFolder));
  }

  possibleIncludeFolder = "arch";
  file = new File(new Path(pathMan.resolveURI(pathMan.getURIValue(PathVarName)).getPath()).append(SubFolder).append(possibleIncludeFolder)
    .toString());
  if (file.exists()) {
      addIncludeFolder(configurationDescription,
        link.getFullPath().append(possibleIncludeFolder).append(makeEnvironmentVar(ENV_KEY_ARCHITECTURE)));
  }
    }

    /**
     * This method creates a link folder in the project and adds the folder as a source path to the project it also adds the path to the include
     * folder if the includepath parameter points to a path that contains a subfolder named "utility" this subfolder will be added to the include path
     * as well <br/>
     * <br/>
     *
     * note Arduino has these subfolders in the libraries that need to be include.<br/>
     * <br/>
     *
     * note that in the current eclipse version, there is no need to add the subfolder as a code folder. This may change in the future as it looks
     * like a bug to me.<br/>
     *
     * @param project
     * @param Path
     * @throws CoreException
     *
     * @see addLibraryDependency {@link #addLibraryDependency(IProject, IProject)}
     */
    public static void addCodeFolder(IProject project, IPath Path, ICConfigurationDescription configurationDescription) throws CoreException {

  // create a link to the path
  String NiceName = Path.lastSegment();
  String PathName = project.getName() + NiceName;
  URI ShortPath = URIUtil.toURI(Path.removeTrailingSeparator().removeLastSegments(1));

  IWorkspace workspace = project.getWorkspace();
  IPathVariableManager pathMan = workspace.getPathVariableManager();

  pathMan.setURIValue(PathName, ShortPath);

  addCodeFolder(project, PathName, NiceName, NiceName, configurationDescription);

    }

    /**
     * addTheNatures replaces all existing natures by the natures needed for a arduino project
     *
     * @param project
     *            The project where the natures need to be added to
     * @throws CoreException
     */
    public static void addTheNatures(IProject project) throws CoreException {
  IProjectDescription description = project.getDescription();

  String[] newnatures = new String[5];
  newnatures[0] = ArduinoConst.Cnatureid;
  newnatures[1] = ArduinoConst.CCnatureid;
  newnatures[2] = ArduinoConst.Buildnatureid;
  newnatures[3] = ArduinoConst.Scannernatureid;
  newnatures[4] = ArduinoConst.ArduinoNatureID;
  description.setNatureIds(newnatures);
  project.setDescription(description, new NullProgressMonitor());
    }

    /**
     * This method adds the content of a content stream to a file
     *
     * @param container
     *            used as a reference to the file
     * @param path
     *            The path to the file relative from the container
     * @param contentStream
     *            The stream to put in the file
     * @param monitor
     *            A monitor to show progress
     * @throws CoreException
     */
    public static void addFileToProject(IContainer container, Path path, InputStream contentStream, IProgressMonitor monitor) throws CoreException {
  final IFile file = container.getFile(path);
  if (file.exists()) {
      file.setContents(contentStream, true, true, monitor);
  } else {
      file.create(contentStream, true, monitor);
  }

    }

    /**
     * This method sets the eclipse path variables to contain the 3 important Arduino hardware folders (code wise that is)
     *
     * Core path (used when referencing Arduino Code) The Arduino Pin Path (used from Arduino 1.0 to reference the arduino pin variants) The libraries
     * path (used to find libraries)
     *
     * Paths are given relative to the arduino folder to avoid conflict when a version control system is being used (these values are in the .project
     * file) As the arduino folder location is in the workspace all values in the .project file become relative avoiding conflict.
     *
     * @param project
     */
    public static void setProjectPathVariables(IProject project, IPath platformPath) {
  IPath PinPath = platformPath.append(ArduinoConst.VARIANTS_FOLDER);
  IPath arduinoHardwareLibraryPath = platformPath.append(ArduinoConst.LIBRARY_PATH_SUFFIX);
  IPathVariableManager pathMan = project.getPathVariableManager();
  try {
      // TODO the code below was changed for issue #34 (better multiple user support) but fails on Mac
      // So i split it to use the old code on mac.
      // but they should be merged
      // then it turned out nothing worked anymore. So I reverted to the old code
      // Path arduinoPath = new Path(pathMan.getURIValue(ArduinoConst.WORKSPACE_PATH_VARIABLE_NAME_ARDUINO).getRawPath());
      // if (Platform.getOS().equals(Platform.OS_MACOSX)) {
      pathMan.setURIValue(ArduinoConst.WORKSPACE_PATH_VARIABLE_NAME_HARDWARE_LIB, URIUtil.toURI(arduinoHardwareLibraryPath));
      pathMan.setURIValue(ArduinoConst.PATH_VARIABLE_NAME_ARDUINO_PLATFORM, URIUtil.toURI(platformPath));
      pathMan.setURIValue(ArduinoConst.PATH_VARIABLE_NAME_ARDUINO_PINS, URIUtil.toURI(PinPath));
      // } else {
      //
      // String prefix = "${" + ArduinoConst.WORKSPACE_PATH_VARIABLE_NAME_ARDUINO + "}/";
      // String test = prefix + arduinoHardwareLibraryPath.makeRelativeTo(arduinoPath).toString();
      // // URI uriTest = URIUtil.toURI(test, false);
      //
      // pathMan.setURIValue(ArduinoConst.WORKSPACE_PATH_VARIABLE_NAME_HARDWARE_LIB, pathMan.getURIValue(test));
      // test = prefix + platformPath.makeRelativeTo(arduinoPath).toString();
      // // uriTest = URIUtil.toURI(test, false);
      // pathMan.setURIValue(ArduinoConst.PATH_VARIABLE_NAME_ARDUINO_PLATFORM, pathMan.getURIValue(test));
      // test = prefix + PinPath.makeRelativeTo(arduinoPath).toString();
      // URI uriTest = URIUtil.toURI(pathMan.convertFromUserEditableFormat(test, true));
      // pathMan.setURIValue(ArduinoConst.PATH_VARIABLE_NAME_ARDUINO_PINS, uriTest);
      // }
  } catch (CoreException e) {
      Common.log(new Status(IStatus.ERROR, ArduinoConst.CORE_PLUGIN_ID,
        "Failed to create the path variable variables. The setup will not work properly", e));
      e.printStackTrace();
  }
    }

    private static void searchFiles(File folder, HashSet<String> Hardwarelists, String Filename, int depth) {
  if (depth > 0) {
      File[] a = folder.listFiles();
      if (a == null) {
    Common.log(new Status(IStatus.INFO, ArduinoConst.CORE_PLUGIN_ID, "The folder " + folder + " does not contain any files.", null));
    return;
      }
      for (File f : a) {
    if (f.isDirectory()) {
        searchFiles(f, Hardwarelists, Filename, depth - 1);
    } else if (f.getName().equals(Filename)) {
        try {
      Hardwarelists.add(f.getCanonicalPath());
        } catch (IOException e) {
      // e.printStackTrace();
        }
    }
      }
  }
    }

    public static MessageConsole findConsole(String name) {
  ConsolePlugin plugin = ConsolePlugin.getDefault();
  IConsoleManager conMan = plugin.getConsoleManager();
  IConsole[] existing = conMan.getConsoles();
  for (int i = 0; i < existing.length; i++)
      if (name.equals(existing[i].getName()))
    return (MessageConsole) existing[i];
  // no console found, so create a new one
  MessageConsole myConsole = new MessageConsole(name, null);
  conMan.addConsoles(new IConsole[] { myConsole });
  return myConsole;
    }

    /**
     * This method adds the Arduino code in a subfolder named Arduino. 2 linked subfolders named core and variant link to the real Arduino code note
     * if your arduino ide version is from before 1.0 only 1 folder is created
     *
     * @param project
     *            The project to add the arduino code to
     * @param ProjectProperties
     *            The properties to use to add the core folder
     * @throws CoreException
     */
    public static void addArduinoCodeToProject(IProject project, ICConfigurationDescription configurationDescription) throws CoreException {

  String boardVariant = getBuildEnvironmentVariable(configurationDescription, ENV_KEY_build_variant, "");
  String buildCoreFolder = getBuildEnvironmentVariable(configurationDescription, ENV_KEY_build_core_folder, "");
  if (buildCoreFolder.contains(":")) {
      String sections[] = buildCoreFolder.split(":");
      if (sections.length != 2) {
    Common.log(new Status(IStatus.ERROR, ArduinoConst.CORE_PLUGIN_ID, "the value for key " + ENV_KEY_build_core_folder
      + " in boards.txt is invalid:" + buildCoreFolder, null));
      } else {
    String architecture = getBuildEnvironmentVariable(configurationDescription, ENV_KEY_ARCHITECTURE, "");
    addCodeFolder(project, WORKSPACE_PATH_VARIABLE_NAME_ARDUINO, ARDUINO_HARDWARE_FOLDER_NAME + "/" + sections[1] + "/" + architecture
      + "/" + ARDUINO_CORE_FOLDER_NAME + "/" + sections[1], "arduino/core", configurationDescription);
      }
  } else {
      addCodeFolder(project, PATH_VARIABLE_NAME_ARDUINO_PLATFORM, ARDUINO_CORE_FOLDER_NAME + "/" + buildCoreFolder, "arduino/core",
        configurationDescription);
  }
  if (!boardVariant.equals("")) {
      ArduinoHelpers.addCodeFolder(project, PATH_VARIABLE_NAME_ARDUINO_PINS, boardVariant, "arduino/variant", configurationDescription);
  } else {// this is Arduino version 1.0
      IFolder variantFolder = project.getFolder("arduino/variant");
      if (variantFolder.exists()) {
    try {
        variantFolder.delete(true, null);
    } catch (CoreException e) {
        Common.log(new Status(IStatus.ERROR, ArduinoConst.CORE_PLUGIN_ID, "failed to delete the variant folder", e));
    }
      }
  }

    }

    /**
     * Creates a new folder resource as a link or local
     *
     * @param Project
     *            the project the folder is added to
     * @param newFolderName
     *            the new folder to create (can contain subfolders)
     * @param linklocation
     *            if null a local folder is created using newFolderName if not null a link folder is created with the name newFolderName and pointing
     *            to linklocation
     *
     * @return nothing
     * @throws CoreException
     */
    public static void createNewFolder(IProject Project, String newFolderName, URI linklocation) throws CoreException {
  // IPath newFolderPath = Project.getFullPath().append(newFolderName);
  final IFolder newFolderHandle = Project.getFolder(newFolderName);
  if (linklocation != null) {
      newFolderHandle.createLink(linklocation, IResource.REPLACE | IResource.ALLOW_MISSING_LOCAL, null);
  } else {
      newFolderHandle.create(0, true, null);
  }

    }

    /**
     * Remove all the arduino environment variables.
     *
     * @param contribEnv
     * @param confDesc
     */
    private static void RemoveAllArduinoEnvironmentVariables(IContributedEnvironment contribEnv, ICConfigurationDescription confDesc) {

  IEnvironmentVariable[] CurVariables = contribEnv.getVariables(confDesc);
  for (int i = (CurVariables.length - 1); i > 0; i--) {
      if (CurVariables[i].getName().startsWith(ArduinoConst.ENV_KEY_ARDUINO_START)) {
    contribEnv.removeVariable(CurVariables[i].getName(), confDesc);
      }
  }
    }

    /**
     * Sets the default values. Basically some settings are not set in the platform.txt file. Here I set these values. This method should be called as
     * first. This way the values in platform.txt and boards.txt will take precedence of the default values declared here
     *
     * @param contribEnv
     * @param confDesc
     * @param platformFile
     *            Used to define the hardware as different settings are needed for avr and sam
     */
    private static void setTheEnvironmentVariablesSetTheDefaults(IContributedEnvironment contribEnv, ICConfigurationDescription confDesc,
      IPath platformFile) {
  // Set some default values because the platform.txt does not contain
  // them
  IEnvironmentVariable var = new EnvironmentVariable(ENV_KEY_ARDUINO_PATH, getArduinoPath().toString());
  contribEnv.addVariable(var, confDesc);

  // from 1.5.3 onwards 3 more environment variables need to be added
  var = new EnvironmentVariable(ENV_KEY_ARCHITECTURE, platformFile.removeLastSegments(1).lastSegment());
  contribEnv.addVariable(var, confDesc);
  var = new EnvironmentVariable(ENV_KEY_BUILD_ARCH, platformFile.removeLastSegments(1).lastSegment().toUpperCase());
  contribEnv.addVariable(var, confDesc);
  var = new EnvironmentVariable(ENV_KEY_HARDWARE_PATH, platformFile.removeLastSegments(3).toString());
  contribEnv.addVariable(var, confDesc);

  // from 1.5.8 onward 1 more environment variable is needed
  var = new EnvironmentVariable(ENV_KEY_PLATFORM_PATH, platformFile.removeLastSegments(1).toString());
  contribEnv.addVariable(var, confDesc);

  // I'm not sure why but till now arduino refused to put this in the platform.txt file
  // I won't call them idiots for this but it is getting close
  var = new EnvironmentVariable(ENV_KEY_SOFTWARE, "ARDUINO");
  contribEnv.addVariable(var, confDesc);
  var = new EnvironmentVariable(ENV_KEY_runtime_ide_version, GetARDUINODefineValue());
  contribEnv.addVariable(var, confDesc);
  // End of section permitting denigrating remarks on arduino software development team

  // // Arduino uses the board approach for the upload tool.
  // // as I'm not I create some special entries to work around it
  // var = new EnvironmentVariable("A.CMD", makeEnvironmentVar("A.TOOLS.BOSSAC.CMD"));
  // contribEnv.addVariable(var, confDesc);
  // var = new EnvironmentVariable("A.PATH", makeEnvironmentVar("A.TOOLS.BOSSAC.PATH"));
  // contribEnv.addVariable(var, confDesc);
  // var = new EnvironmentVariable("A.CMD.PATH", makeEnvironmentVar("A.TOOLS.AVRDUDE.CMD.PATH"));
  // contribEnv.addVariable(var, confDesc);
  // var = new EnvironmentVariable("A.CONFIG.PATH", makeEnvironmentVar("A.TOOLS.AVRDUDE.CONFIG.PATH"));
  // contribEnv.addVariable(var, confDesc); // End of section Arduino uses
  // // the board approach for the
  // // upload tool.

  // For Teensy I added a flag that allows to compile everything in one
  // project not using the archiving functionality
  // I set the default value to: use the archiver
  var = new EnvironmentVariable(ENV_KEY_use_archiver, "true");
  contribEnv.addVariable(var, confDesc);
  // End of Teensy specific settings

  if (platformFile.segment(platformFile.segmentCount() - 2).equals("avr")) {
      var = new EnvironmentVariable(ENV_KEY_compiler_path, makeEnvironmentVar("A.RUNTIME.IDE.PATH") + "/hardware/tools/avr/bin/");
      contribEnv.addVariable(var, confDesc);
  } else if (platformFile.segment(platformFile.segmentCount() - 2).equals("sam")) {
      var = new EnvironmentVariable(ENV_KEY_build_system_path, makeEnvironmentVar("A.RUNTIME.IDE.PATH") + "/hardware/arduino/sam/system");
      contribEnv.addVariable(var, confDesc);
      var = new EnvironmentVariable(ENV_KEY_build_generic_path, makeEnvironmentVar("A.RUNTIME.IDE.PATH")
        + "/hardware/tools/g++_arm_none_eabi/arm-none-eabi/bin");
      contribEnv.addVariable(var, confDesc);
  }

  // some glue to make it work
  String extraPathForOS = "";
  if (Platform.getWS().equals(Platform.WS_WIN32)) {
      extraPathForOS = "${PathDelimiter}${" + ENV_KEY_ARDUINO_PATH + "}/hardware/tools/avr/utils/bin${PathDelimiter}${" + ENV_KEY_ARDUINO_PATH
        + "}";
  }
  var = new EnvironmentVariable("PATH", "${A.COMPILER.PATH}${PathDelimiter}${" + ENV_KEY_build_generic_path + "}" + extraPathForOS
    + "${PathDelimiter}${PATH}");
  contribEnv.addVariable(var, confDesc);

  var = new EnvironmentVariable(ENV_KEY_build_path, "${ProjDirPath}/${ConfigName}");
  contribEnv.addVariable(var, confDesc);

  var = new EnvironmentVariable(ENV_KEY_build_project_name, makeEnvironmentVar("ProjName"));
  contribEnv.addVariable(var, confDesc);

  // if (firstTime) {
  if (getBuildEnvironmentVariable(confDesc, ENV_KEY_JANTJE_SIZE_SWITCH, "").isEmpty()) {
      var = new EnvironmentVariable(ENV_KEY_JANTJE_SIZE_SWITCH, makeEnvironmentVar(ENV_KEY_recipe_size_pattern));
      contribEnv.addVariable(var, confDesc);
  }
  if (getBuildEnvironmentVariable(confDesc, ENV_KEY_JANTJE_SIZE_COMMAND, "").isEmpty()) {
      var = new EnvironmentVariable(ENV_KEY_JANTJE_SIZE_COMMAND, JANTJE_SIZE_COMMAND);
      contribEnv.addVariable(var, confDesc);
  }

  // Set the warning level default off like arduino does
  if (getBuildEnvironmentVariable(confDesc, ENV_KEY_JANTJE_WARNING_LEVEL, "").isEmpty()) {
      var = new EnvironmentVariable(ENV_KEY_JANTJE_WARNING_LEVEL, ENV_KEY_WARNING_LEVEL_OFF);
      contribEnv.addVariable(var, confDesc);
  }

  var = new EnvironmentVariable(ENV_KEY_archive_file, "arduino.ar");
  contribEnv.addVariable(var, confDesc);

  IPathVariableManager pathMan = confDesc.getProjectDescription().getProject().getPathVariableManager();
  URI buildVariantURI = pathMan.getURIValue(ArduinoConst.PATH_VARIABLE_NAME_ARDUINO_PINS);
  buildVariantURI = pathMan.resolveURI(buildVariantURI);
  String buildVariantPath = buildVariantURI.getPath() + "/${" + ArduinoConst.ENV_KEY_build_variant + "}";
  var = new EnvironmentVariable(ENV_KEY_build_variant_path, buildVariantPath);
  contribEnv.addVariable(var, confDesc);
  // IPath platformPath = new Path(arduinoProperties.getPlatformFolder());
  // IPath PinPath = platformPath.append(ArduinoConst.VARIANTS_FOLDER);

    }

    /**
     * This method parses the platform.txt file for values to be added to the environment variables
     *
     * @param contribEnv
     * @param confDesc
     * @param platformFile
     *            The file to parse
     * @throws IOException
     */
    private static void setTheEnvironmentVariablesAddthePlatformTxt(IContributedEnvironment contribEnv, ICConfigurationDescription confDesc,
      IPath platformFile) throws IOException {
  DataInputStream dataInputStream = new DataInputStream(new FileInputStream(platformFile.toOSString()));
  BufferedReader br = new BufferedReader(new InputStreamReader(dataInputStream));
  String strLine;
  IEnvironmentVariable var = null;
  // Read File Line By Line
  while ((strLine = br.readLine()) != null) {
      String RealData[] = strLine.split("#");// Ignore everything after
               // first #
      if (RealData.length > 0) {
    String Var[] = RealData[0].split("=", 2); // look for assignment
    if (Var.length == 2) {
        String Value = MakeEnvironmentString(Var[1].replace("\"{build.path}/syscalls_sam3.c.o\"",
          "\"{build.path}/arduino/syscalls_sam3.c.o\""));
        var = new EnvironmentVariable(MakeKeyString(Var[0]), Value);
        contribEnv.addVariable(var, confDesc);
    }
      }
  }
  dataInputStream.close(); // Close the platform.txt
    }

    /**
     * This method parses the boards.txt file for values to be added to the environment variables First it adds all the variables based on the board
     * name [boardID].[key]=[value] results in [key]=[value] (taking in account the modifiers) Then it parses for the menu variables
     * menu.[menuID].[boardID].[selectionID].[key]=[value] results in [key]=[value] (taking in account the modifiers)
     *
     * @param contribEnv
     * @param confDesc
     * @param platformFilename
     *            The file to parse
     * @throws IOException
     */
    private static void setTheEnvironmentVariablesAddtheBoardsTxt(IContributedEnvironment contribEnv, ICConfigurationDescription confDesc,
      IPath boardFileName, String boardName) throws IOException {
  ArduinoBoards boardsFile = new ArduinoBoards(boardFileName.toOSString());
  String boardID = boardsFile.getBoardIDFromName(boardName);

  // Get the boards section and add all entries to the environment variables
  Map<String, String> boardSectionMap = boardsFile.getSection(boardID);
  for (Entry<String, String> currentPair : boardSectionMap.entrySet()) {
      // if it is not a menu item add it
      if (!currentPair.getKey().startsWith("menu.")) {
    String keyString = MakeKeyString(currentPair.getKey());
    String valueString = MakeEnvironmentString(currentPair.getValue());
    contribEnv.addVariable(new EnvironmentVariable(keyString, valueString), confDesc);
      } else {

    String[] keySplit = currentPair.getKey().split("\\.");
    String menuID = keySplit[1];
    String menuItemID = keySplit[2];
    if (isThisMenuItemSelected(boardsFile, confDesc, boardID, menuID, menuItemID)) {
        // we also need to skip the name
        String StartValue = "menu." + menuID + "." + menuItemID + ".";
        if (currentPair.getKey().startsWith(StartValue)) {
      String keyString = MakeKeyString(currentPair.getKey().substring(StartValue.length()));
      String valueString = MakeEnvironmentString(currentPair.getValue());
      contribEnv.addVariable(new EnvironmentVariable(keyString, valueString), confDesc);
        }
    }
      }
  }

  Map<String, String> menuSectionMap = boardsFile.getSection("menu");
  String[] optionNames = boardsFile.getMenuNames();
  for (int currentOption = 0; currentOption < optionNames.length; currentOption++) {
      String optionName = optionNames[currentOption];
      String optionValue = getBuildEnvironmentVariable(confDesc, ArduinoConst.ENV_KEY_JANTJE_START + optionName, "");
      if (!optionValue.isEmpty()) {
    String optionValueID = null;
    String optionID = null;
    // Look for the option ID
    for (Entry<String, String> curOption : menuSectionMap.entrySet()) {
        if (curOption.getValue().equals(optionName)) {
      String[] keySplit = curOption.getKey().split("\\.");
      if (keySplit.length == 1)
          optionID = keySplit[0];
        }
    }
    if (optionID != null) { // we have the option ID lets look for
          // the option value ID
        for (Entry<String, String> curOption : menuSectionMap.entrySet()) {
      if (curOption.getValue().equals(optionValue)) {
          String[] keySplit = curOption.getKey().split("\\.");
          if (keySplit.length == 3 && keySplit[0].equals(optionID) && keySplit[1].equals(boardID))
        optionValueID = keySplit[2];
      }
        }
    }
    if (optionValueID != null) // now we have all the info to find
             // the key value pairs for the
             // environment vars
    {
        // The arduino menu way
        String keyStartsWithValue = optionID + "." + boardID + "." + optionValueID + ".";
        for (Entry<String, String> curOption : menuSectionMap.entrySet()) {
      if (curOption.getKey().startsWith(keyStartsWithValue)) {
          String key = curOption.getKey().substring(keyStartsWithValue.length());
          contribEnv
            .addVariable(new EnvironmentVariable(MakeKeyString(key), MakeEnvironmentString(curOption.getValue())), confDesc);
      }
        }

    }
      }

  }
    }

    private static boolean isThisMenuItemSelected(ArduinoBoards boardsFile, ICConfigurationDescription confDesc, String boardID, String menuID,
      String menuItemID) {

  String MenuName = boardsFile.getMenuNameFromID(menuID);
  String MenuItemName = boardsFile.getMenuItemNameFromID(boardID, menuID, menuItemID);

  String SelectedMenuItemName = getBuildEnvironmentVariable(confDesc, ArduinoConst.ENV_KEY_JANTJE_START + MenuName, "");
  if (SelectedMenuItemName.isEmpty()) {
      return false; // This menu item has not been selected
      // this should not happen
  }
  if (MenuItemName.equalsIgnoreCase(SelectedMenuItemName))
      return true;
  return false;
    }

    /**
     * This method creates environment variables based on the platform.txt and boards.txt platform.txt is processed first and then boards.txt. This
     * way boards.txt settings can overwrite common settings in platform.txt The environment variables are only valid for the project given as
     * parameter The project properties are used to identify the boards.txt and platform.txt as well as the board id to select the settings in the
     * board.txt file At the end also the path variable is set
     *
     * @param project
     *            the project for which the environment variables are set
     * @param arduinoProperties
     *            the info of the selected board to set the variables for
     */

    public static void setTheEnvironmentVariables(IProject project, ICConfigurationDescription confDesc, boolean debugCompilerSettings) {

  IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
  IContributedEnvironment contribEnv = envManager.getContributedEnvironment();

  IPath boardFileName = new Path(Common.getBuildEnvironmentVariable(confDesc, ArduinoConst.ENV_KEY_JANTJE_BOARDS_FILE,
    ArduinoInstancePreferences.getLastUsedBoardsFile()));
  // TODO arduino specification makes it possible to have more than 1 platformfile lets for now assume there is only 1
  IPath platformFilename = new Path(Common.getBuildEnvironmentVariable(confDesc, ArduinoConst.ENV_KEY_JANTJE_PLATFORM_FILE, ""));
  if (!platformFilename.toFile().exists()) {
      // TODO lets for now hardcode this is arduino
      for (int cursegment = 0; cursegment < platformFilename.segmentCount(); cursegment++) {
    if (ARDUINO_HARDWARE_FOLDER_NAME.equals(platformFilename.segment(cursegment))) {

        platformFilename = getArduinoPath().append(ARDUINO_HARDWARE_FOLDER_NAME).append("arduino")
          .append(platformFilename.removeFirstSegments(cursegment + 2));
        cursegment = platformFilename.segmentCount();
    }
      }
  }
  String boardName = Common.getBuildEnvironmentVariable(confDesc, ArduinoConst.ENV_KEY_JANTJE_BOARD_NAME,
    ArduinoInstancePreferences.getLastUsedArduinoBoardName());

  // first remove all Arduino Variables so there is no memory effect
  RemoveAllArduinoEnvironmentVariables(contribEnv, confDesc);

  // process the default env variables first. This way the platform.txt
  // and boards.txt will
  // overwrite the default settings
  setTheEnvironmentVariablesSetTheDefaults(contribEnv, confDesc, platformFilename);
  try {
      // process the platform.txt file first. This way the boards.txt will
      // overwrite the default settings
      setTheEnvironmentVariablesAddthePlatformTxt(contribEnv, confDesc, platformFilename);
      // now process the boards file
      setTheEnvironmentVariablesAddtheBoardsTxt(contribEnv, confDesc, boardFileName, boardName);
      // Do some post processing
      setTheEnvironmentVariablesPostProcessing(contribEnv, confDesc);

      // If this is a debug config we modify the environment variables for compilation
      if (debugCompilerSettings) {
    setTheEnvironmentVariablesModifyDebugCompilerSettings(confDesc, envManager, contribEnv);
      }

  } catch (Exception e) {// Catch exception if any
      Common.log(new Status(IStatus.ERROR, ArduinoConst.CORE_PLUGIN_ID, "Error parsing " + platformFilename + " or " + boardFileName, e));
      return;
  }

    }

    /**
     * Some post processing is needed because the macro expansion resolves the "file tag" Therefore I split the "recipe" patterns in 2 parts (before
     * and after the "file tag") the pattern in the toolchain is then ${first part} ${files} ${second part}
     *
     * @param contribEnv
     * @param confDesc
     */
    private static void setTheEnvironmentVariablesPostProcessing(IContributedEnvironment contribEnv, ICConfigurationDescription confDesc) {

  String recipes[] = { ENV_KEY_recipe_c_o_pattern, ENV_KEY_recipe_cpp_o_pattern, ENV_KEY_recipe_S_o_pattern,
    ENV_KEY_recipe_objcopy_hex_pattern, ENV_KEY_recipe_objcopy_eep_pattern, ENV_KEY_recipe_size_pattern, ENV_KEY_recipe_AR_pattern,
    ENV_KEY_recipe_c_combine_pattern };
  IEnvironmentVariable var = null;
  for (int curRecipe = 0; curRecipe < recipes.length; curRecipe++) {
      String recipe = getBuildEnvironmentVariable(confDesc, recipes[curRecipe], "", false);

      String recipeParts[] = recipe.split("(\"\\$\\{A.OBJECT_FILE}\")|(\\$\\{A.OBJECT_FILES})|(\"\\$\\{A.SOURCE_FILE}\")", 3);
      switch (recipeParts.length) {
      case 0:
    var = new EnvironmentVariable(recipes[curRecipe] + ".1", "echo no command for " + recipes[curRecipe]);
    contribEnv.addVariable(var, confDesc);
    break;
      case 1:
    var = new EnvironmentVariable(recipes[curRecipe] + ".1", recipeParts[0]);
    contribEnv.addVariable(var, confDesc);
    break;
      case 2:
    var = new EnvironmentVariable(recipes[curRecipe] + ".1", recipeParts[0]);
    contribEnv.addVariable(var, confDesc);
    var = new EnvironmentVariable(recipes[curRecipe] + ".2", recipeParts[1]);
    contribEnv.addVariable(var, confDesc);
    break;
      case 3:
    var = new EnvironmentVariable(recipes[curRecipe] + ".1", recipeParts[0]);
    contribEnv.addVariable(var, confDesc);
    var = new EnvironmentVariable(recipes[curRecipe] + ".2", recipeParts[1]);
    contribEnv.addVariable(var, confDesc);
    var = new EnvironmentVariable(recipes[curRecipe] + ".3", recipeParts[2]);
    contribEnv.addVariable(var, confDesc);
    break;
      default:
    // this should never happen as the split is limited to 2

      }

  }
  var = new EnvironmentVariable(ArduinoConst.ENV_KEY_SOFTWARE, "ARDUINO");
  contribEnv.addVariable(var, confDesc);
  String uploadProg = ArduinoInstancePreferences.getLastUsedUploadProgrammer();
  // If the user selected a different upload protocol replace the protocol with the selected one
  if (!uploadProg.equals(ArduinoConst.DEFAULT)) {
      var = new EnvironmentVariable(ArduinoConst.ENV_KEY_ARDUINO_UPLOAD_PROTOCOL, uploadProg);
      contribEnv.addVariable(var, confDesc);
  }

  // Arduino uses the board approach for the upload tool.
  // as I'm not I create some special entries to work around it
  String uploadTool = contribEnv.getVariable(ArduinoConst.ENV_KEY_upload_tool, confDesc).getValue().toUpperCase();
  var = new EnvironmentVariable("A.CMD", makeEnvironmentVar("A.TOOLS." + uploadTool + ".CMD"));
  contribEnv.addVariable(var, confDesc);
  var = new EnvironmentVariable("A.PATH", makeEnvironmentVar("A.TOOLS." + uploadTool + ".PATH"));
  contribEnv.addVariable(var, confDesc);
  var = new EnvironmentVariable("A.CMD.PATH", makeEnvironmentVar("A.TOOLS." + uploadTool + ".CMD.PATH"));
  contribEnv.addVariable(var, confDesc);
  var = new EnvironmentVariable("A.CONFIG.PATH", makeEnvironmentVar("A.TOOLS." + uploadTool + ".CONFIG.PATH"));
  contribEnv.addVariable(var, confDesc); // End of section Arduino uses
                 // the board approach for the
                 // upload tool.

    }

    /**
     * Converts the CPP and C compiler flags to not optimise for space/size and to leave symbols in. These changes allow step through debugging with
     * JTAG and Dragon AVR
     *
     * @param confDesc
     * @param envManager
     * @param contribEnv
     */

    private static void setTheEnvironmentVariablesModifyDebugCompilerSettings(ICConfigurationDescription confDesc,
      IEnvironmentVariableManager envManager, IContributedEnvironment contribEnv) {

  // Modify the compiler flags for the debug configuration
  // Replace "-g" with "-g2"
  // Replace "-Os" with ""
  // TODO: This should move to another location eventually -- a bit hacky here (considering other env vars come from other -- a little bit
  // magical -- places).
  // I couldn't easily determine where that magic happened :(
  IEnvironmentVariable original = null;
  IEnvironmentVariable replacement = null;

  original = envManager.getVariable(ENV_KEY_ARDUINO_START + "COMPILER.C.FLAGS", confDesc, true);
  if (original != null) {
      replacement = new EnvironmentVariable(original.getName(), original.getValue().replace("-g", "-g2").replace("-Os", ""),
        original.getOperation(), original.getDelimiter());
      contribEnv.addVariable(replacement, confDesc);
  }

  original = envManager.getVariable(ENV_KEY_ARDUINO_START + "COMPILER.CPP.FLAGS", confDesc, true);
  if (original != null) {
      replacement = new EnvironmentVariable(original.getName(), original.getValue().replace("-g", "-g2").replace("-Os", ""),
        original.getOperation(), original.getDelimiter());
      contribEnv.addVariable(replacement, confDesc);
  }
    }

    /**
     * When parsing boards.txt and platform.txt some processing needs to be done to get "acceptable environment variable values" This method does the
     * parsing
     *
     * @param inputString
     *            the value string as read from the file
     * @return the string to be stored as value for the environment variable
     */
    public static String MakeEnvironmentString(String inputString) {
  // String ret = inputString.replaceAll("-o \"\\{object_file}\"",
  // "").replaceAll("\"\\{object_file}\"",
  // "").replaceAll("\"\\{source_file}\"", "")
  // .replaceAll("\\{", "\\${" + ArduinoConst.ENV_KEY_START);
  String ret = inputString.replaceAll("\\{(?!\\{)", "\\${" + ArduinoConst.ENV_KEY_ARDUINO_START);
  StringBuilder sb = new StringBuilder(ret);
  String regex = "\\{[^}]*\\}";
  Pattern p = Pattern.compile(regex); // Create the pattern.
  Matcher matcher = p.matcher(sb); // Create the matcher.
  while (matcher.find()) {
      String buf = sb.substring(matcher.start(), matcher.end()).toUpperCase();
      sb.replace(matcher.start(), matcher.end(), buf);
  }
  return sb.toString();
    }

    /**
     * When parsing boards.txt and platform.txt some processing needs to be done to get "acceptable environment variable keys" This method does the
     * parsing
     *
     * @param inputString
     *            the key string as read from the file
     * @return the string to be used as key for the environment variable
     */
    static String osString = null;

    private static String MakeKeyString(String string) {
  if (osString == null) {
      if (Platform.getOS().equals(Platform.OS_LINUX)) {
    osString = "\\.LINUX";
      } else if (Platform.getOS().equals(Platform.OS_WIN32)) {
    osString = "\\.WINDOWS";
      } else {
    osString = "\\.\\.";
      }
  }
  return ArduinoConst.ENV_KEY_ARDUINO_START + string.toUpperCase().replaceAll(osString, "");
    }

    /**
     * Set the project to force a rebuild. This method is called after the arduino settings have been updated. Note the only way I found I could get
     * this to work is by deleting the build folder Still then the "indexer needs to recheck his includes from the language provider which still is
     * not working
     *
     * @param project
     */
    public static void setDirtyFlag(IProject project, ICConfigurationDescription cfgDescription) {
  IManagedBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(project);
  if (buildInfo == null) {
      return; // Project is not a managed build project
  }

  IFolder buildFolder = project.getFolder(cfgDescription.getName());
  if (buildFolder.exists()) {
      try {
    buildFolder.delete(true, null);
      } catch (CoreException e) {
    Common.log(new Status(IStatus.ERROR, ArduinoConst.CORE_PLUGIN_ID, "failed to delete the folder " + cfgDescription.getName(), e));
      }
  }

  List<ILanguageSettingsProvider> providers;
  if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
      providers = new ArrayList<ILanguageSettingsProvider>(((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders());
      for (ILanguageSettingsProvider provider : providers) {
    if ((provider instanceof AbstractBuiltinSpecsDetector)) { // basically
                    // check
                    // for
                    // working
                    // copy
        // clear and reset isExecuted flag
        ((AbstractBuiltinSpecsDetector) provider).clear();
    }
      }
  }
    }

    /**
     * Given a source file calculates the base of the output file. this method may not be needed if I can used the eclipse default behavior. However
     * the eclipse default behavior is different from the arduino default behavior. So I keep it for now and we'll see how it goes The eclipse default
     * behavior is (starting from the project folder [configuration]/Source The Arduino default behavior is all in 1 location (so no subfolders)
     *
     * @param Source
     *            The source file to find the
     * @return The base file name for the ouput if Source is "file.cpp" the output is "file.cpp"
     */
    public static IPath GetOutputName(IPath Source) {
  IPath outputName;
  if (Source.toString().startsWith("arduino")) {
      outputName = new Path("arduino").append(Source.lastSegment());
  } else {
      outputName = Source;
  }
  return outputName;
    }

    /**
     * Searches for all platform.txt files from the arduino hardware folder
     *
     * @return all the platform.txt files with full path
     */
    public static String[] getPlatformFiles() {

  File HardwareFolder = ArduinoInstancePreferences.getArduinoPath().append(ArduinoConst.ARDUINO_HARDWARE_FOLDER_NAME).toFile();

  HashSet<String> Hardwarelists = new HashSet<String>();
  searchFiles(HardwareFolder, Hardwarelists, ArduinoConst.PLATFORM_FILE_NAME, 3);
  if (Hardwarelists.size() == 0) {
      Common.log(new Status(IStatus.ERROR, ArduinoConst.CORE_PLUGIN_ID, "No platform.txt files found in the arduino hardware folder", null));
      return null;
  }

  return Hardwarelists.toArray(new String[Hardwarelists.size()]);
    }

    /**
     * Searches for all boards.txt files from the arduino hardware folder
     *
     * @return all the boards.txt files with full path
     */
    public static String[] getBoardsFiles() {
  File HardwareFolder = ArduinoInstancePreferences.getArduinoPath().append(ArduinoConst.ARDUINO_HARDWARE_FOLDER_NAME).toFile();

  HashSet<String> boardFiles = new HashSet<String>();
  searchFiles(HardwareFolder, boardFiles, ArduinoConst.BOARDS_FILE_NAME, 3);
  if (boardFiles.size() == 0) {
      Common.log(new Status(IStatus.ERROR, ArduinoConst.CORE_PLUGIN_ID, "No boards.txt files found in the arduino hardware folder", null));
      return null;
  }
  searchFiles(new File(getPrivateHardwarePath()), boardFiles, ArduinoConst.BOARDS_FILE_NAME, 3);

  return boardFiles.toArray(new String[boardFiles.size()]);

    }

    /**
     * Reads the version number from the lib/version.txt file
     *
     * @return the version number if found if no version number found the error returned by the file read method
     */
    static public String GetIDEVersion(IPath arduinoIDEPath) {

  File file = arduinoIDEPath.append(ArduinoConst.LIB_VERSION_FILE).toFile();
  try {
      // Open the file that is the first
      // command line parameter
      FileInputStream fstream = new FileInputStream(file);
      // Get the object of DataInputStream
      DataInputStream in = new DataInputStream(fstream);
      BufferedReader br = new BufferedReader(new InputStreamReader(in));
      String strLine = br.readLine();
      in.close();
      return strLine;
  } catch (Exception e) {// Catch exception if any
      System.err.println("Error: " + e.getMessage());
      return e.getMessage();
  }
    }

    private static String makeEnvironmentVar(String string) {
  return "${" + string + "}";
    }

    /**
     * Give the string entered in the com port try to extract a host. If no host is found return null yun at xxx.yyy.zzz (arduino yun) returns
     * yun.local
     *
     * @param mComPort
     * @return
     */
    public static String getHostFromComPort(String mComPort) {
  String host = mComPort.split(" ")[0];
  if (host.equals(mComPort))
      return null;
  return host;
    }

    /**
     * creates links to the root files and folders of the source location
     *
     * @param source
     *            the location where the files are that need to be linked to
     * @param target
     *            the location where the links are to be created
     */
    public static void linkDirectory(IProject project, IPath source, IPath target) {

  File[] a = source.toFile().listFiles();
  if (a == null) {
      Common.log(new Status(IStatus.INFO, ArduinoConst.CORE_PLUGIN_ID, "The folder you want to link to '" + source
        + "' does not contain any files.", null));
      return;
  }
  for (File f : a) {
      if (f.isDirectory()) {
    LinkFolderToFolder(project, source.append(f.getName()), target.append(f.getName()));
      } else {
    final IFile newFileHandle = project.getFile(target.append(f.getName()));
    try {
        newFileHandle.createLink(source.append(f.getName()), IResource.REPLACE | IResource.ALLOW_MISSING_LOCAL, null);
    } catch (CoreException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
      }
  }

    }
}
TOP

Related Classes of it.baeyens.arduino.tools.ArduinoHelpers

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.