diff options
Diffstat (limited to 'autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools')
82 files changed, 10797 insertions, 0 deletions
diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsBuilder.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsBuilder.java new file mode 100644 index 0000000000..f51c2b64d7 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsBuilder.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools; + +import org.eclipse.cdt.core.settings.model.COutputEntry; +import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; +import org.eclipse.cdt.core.settings.model.ICOutputEntry; +import org.eclipse.cdt.managedbuilder.core.IBuilder; +import org.eclipse.cdt.managedbuilder.internal.core.Builder; +import org.eclipse.cdt.managedbuilder.internal.core.ToolChain; +import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.linuxtools.cdt.autotools.ui.properties.AutotoolsPropertyConstants; + + + +// Proxy class for IBuilder to allow overriding of getBuildLocation(). + +@SuppressWarnings("restriction") +public class AutotoolsBuilder extends Builder { + + private String buildPath; + private IProject project; + + public AutotoolsBuilder(IBuilder builder, IProject project, ToolChain toolChain) { + super(toolChain, builder.getId(), builder.getName(), (Builder)builder); + this.project = project; + } + + protected IProject getProject() { + return project; + } + + + public String getBuildPath() { + // TODO Auto-generated method stub + return buildPath; + } + + + public void setBuildPath(String path) { + // TODO Auto-generated method stub + this.buildPath = path; + } + + public String getCleanBuildTarget() { + String target = null; + try { + target = getProject().getPersistentProperty(AutotoolsPropertyConstants.CLEAN_MAKE_TARGET); + } catch (CoreException ce) { + // do nothing + } + if (target == null) + target = AutotoolsPropertyConstants.CLEAN_MAKE_TARGET_DEFAULT; + return target; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.IBuilder#getBuildFileGenerator() + */ + public IManagedBuilderMakefileGenerator getBuildFileGenerator() { + return new MakeGenerator(); + } + + /* @override */ + public ICOutputEntry[] getOutputEntries() { + return new ICOutputEntry[]{new COutputEntry(buildPath, null, ICLanguageSettingEntry.VALUE_WORKSPACE_PATH | ICLanguageSettingEntry.RESOLVED)}; + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsDefaultBuildDirHandler.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsDefaultBuildDirHandler.java new file mode 100644 index 0000000000..e1a3e5ae59 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsDefaultBuildDirHandler.java @@ -0,0 +1,155 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools; + +import java.util.SortedSet; +import java.util.TreeSet; + +import org.eclipse.cdt.managedbuilder.core.BuildException; +import org.eclipse.cdt.managedbuilder.core.IBuildObject; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.cdt.managedbuilder.core.IHoldsOptions; +import org.eclipse.cdt.managedbuilder.core.IManagedOptionValueHandler; +import org.eclipse.cdt.managedbuilder.core.IOption; +import org.eclipse.cdt.managedbuilder.core.IOptionApplicability; +import org.eclipse.cdt.managedbuilder.core.ITool; +import org.eclipse.cdt.managedbuilder.core.ManagedOptionValueHandler; + +public class AutotoolsDefaultBuildDirHandler extends ManagedOptionValueHandler + implements IOptionApplicability { + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.IManagedOptionValueHandler#handleValue(IConfiguration,IToolChain,IOption,String,int) + */ + + public final static String DEFAULT_BUILD_DIR = "build"; //$NON-NLS-1$ + public final static String CONFIGURE_TOOL_ID = "org.eclipse.linuxtools.cdt.autotools.gnu.toolchain.tool.configure"; //$NON-NLS-1$ + public final static String BUILD_DIR_OPTION_ID = "org.eclipse.linuxtools.cdt.autotools.option.configure.builddir"; //$NON-NLS-1$ + public final static String BUILD_DIR_APPLY = "BuildDir.apply"; //$NON-NLS-1$ + public final static String BUILD_DIR_DEFAULT_QUESTION = "BuildDir.default"; //$NON-NLS-1$ + public final static String BUILD_DIR_YES = "BuildDir.yes"; //$NON-NLS-1$ + public final static String BUILD_DIR_NO = "BuildDir.no"; //$NON-NLS-1$ + + //FIXME: Use holder to set option value, not the "option" parameter + public boolean handleValue(IBuildObject buildObject, + IHoldsOptions holder, + IOption option, + String extraArgument, int event) + { + // Get the current value of the build dir option. + String value = (String)option.getValue(); + String valueBase = value; + + if (buildObject instanceof IConfiguration && + (event == IManagedOptionValueHandler.EVENT_OPEN)) { +// || event == IManagedOptionValueHandler.EVENT_APPLY)) { + SortedSet<Integer> nums = new TreeSet<Integer>(); + IConfiguration configuration = (IConfiguration)buildObject; + IConfiguration[] cfgs = configuration.getManagedProject().getConfigurations(); + int index = 1; + boolean valueFound = false; + for (int i = 0; i < cfgs.length; ++i) { + IConfiguration config = cfgs[i]; + if (config == null || config.getName().equals(configuration.getName())) { + continue; + } + ITool tool = config.getToolFromOutputExtension("status"); //$NON-NLS-1$ + if (tool == null) // can happen if user has purposely mixed autotools and non-autotools cfgs + continue; + + // We now want to get the builddir option for the tool. If we use + // getOptionById(), we must know the full id which in our case has a generated + // numeric extension at the end. Otherwise, the base builddir option id + // will get us the default option, not the one for the configuration we + // are currently looking at. We use getOptionBySuperClassId() instead + // which will find us options that are based off the original builddir + // option which include those with generated extensions at the end. + IOption buildDirOption = tool.getOptionBySuperClassId(BUILD_DIR_OPTION_ID); + String buildDir = (String)buildDirOption.getValue(); + if (buildDir.equals(value)) { + valueFound = true; + } + // For "buildXX" values, store the XX values in a list of used extensions. + if (buildDir.startsWith(DEFAULT_BUILD_DIR)) { + String numstr = buildDir.substring(DEFAULT_BUILD_DIR.length()); + try { + Integer k = Integer.valueOf(numstr); + // Assume the value to start with is the last value in the list + // plus 1. + index = k.intValue() + 1; + nums.add(k); + } catch (NumberFormatException e) { + // ignore + } + } + } + + // If there is no name collision for the configurations, then we simply return. + if (!valueFound) + return true; + +// // If the user has applied a change and it matches an existing build directory, +// // then warn and ask if the user wants the value defaulted to a safe value. +// if (event == EVENT_APPLY) { +// String title = AutotoolsPlugin.getResourceString(BUILD_DIR_APPLY); +// String question = AutotoolsPlugin.getResourceString(BUILD_DIR_DEFAULT_QUESTION); +// String[] buttonLabels = new String[2]; +// buttonLabels[0] = AutotoolsPlugin.getResourceString(BUILD_DIR_YES); +// buttonLabels[1] = AutotoolsPlugin.getResourceString(BUILD_DIR_NO); +// MessageDialog d = new MessageDialog(AutotoolsPlugin.getActiveWorkbenchShell(), +// title, null, question, MessageDialog.QUESTION, buttonLabels, 0); +// int result = d.open(); +// if (result == 1) +// return true; +// } + + // For defaulted buildXX values, we support defaulting a unique XX value. + if (value.startsWith(DEFAULT_BUILD_DIR)) { + valueBase = DEFAULT_BUILD_DIR; + // Try and establish a unique "buildXX" name that hasn't been used yet. + while (nums.contains(Integer.valueOf(index))) { + ++index; + } + } + + // Reset the default build directory for this opened configuration. + try { + IOption optionToSet = holder.getOptionToSet(option, false); + optionToSet.setValue(valueBase + index); + } catch (BuildException e) { + return false; + } + } + + // The event was not handled, thus return false + return true; + } + + // IOptionApplicability methods + + public boolean isOptionEnabled(IBuildObject configuration, + IHoldsOptions holder, IOption option) { + return true; + } + + public boolean isOptionUsedInCommandLine(IBuildObject configuration, + IHoldsOptions holder, IOption option) { + return false; + } + + public boolean isOptionVisible(IBuildObject configuration, + IHoldsOptions holder, IOption option) { + if (option.getName().equals("includes") || option.getName().equals("symbols")) + return false; + return true; + } + + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsMakefileBuilder.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsMakefileBuilder.java new file mode 100644 index 0000000000..198d89d075 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsMakefileBuilder.java @@ -0,0 +1,512 @@ +/******************************************************************************* + * Copyright (c) 2002, 2005, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.CommandLauncher; +import org.eclipse.cdt.core.ConsoleOutputStream; +import org.eclipse.cdt.core.envvar.IEnvironmentVariable; +import org.eclipse.cdt.core.resources.IConsole; +import org.eclipse.cdt.make.core.IMakeCommonBuildInfo; +import org.eclipse.cdt.managedbuilder.core.IBuilder; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.IManagedProject; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; +import org.eclipse.cdt.managedbuilder.core.ManagedCProjectNature; +import org.eclipse.cdt.managedbuilder.internal.core.Builder; +import org.eclipse.cdt.managedbuilder.internal.core.CommonBuilder; +import org.eclipse.cdt.managedbuilder.internal.core.ToolChain; +import org.eclipse.cdt.managedbuilder.macros.BuildMacroException; +import org.eclipse.cdt.managedbuilder.macros.IBuildMacroProvider; +import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.linuxtools.cdt.autotools.ui.properties.AutotoolsPropertyConstants; + + +/** + * This is the incremental builder associated with a managed build project. It dynamically + * decides the makefile generator it wants to use for a specific target. + * + * @since 1.2 + */ +@SuppressWarnings("restriction") +public class AutotoolsMakefileBuilder extends CommonBuilder { + public static final String BUILDER_NAME = "genmakebuilder"; //$NON-NLS-1$ + public static final String BUILDER_ID = AutotoolsPlugin.getUniqueIdentifier() + "." + BUILDER_NAME; //$NON-NLS-1$ + public static final String MANAGED_BUILDER_ID = ManagedBuilderCorePlugin.getUniqueIdentifier() + "." + BUILDER_NAME; //$NON-NLS-1$ + public static final String AUTOTOOLS_CONFIG_ID = AutotoolsPlugin.getUniqueIdentifier() + ".configuration.build"; //$NON-NLS-1$ + public static final String AUTOTOOLS_PROJECT_TYPE_ID = AutotoolsPlugin.getUniqueIdentifier() + ".projectType"; //$NON-NLS-1$ + + private static final String BUILD_FINISHED = "AutotoolsMakefileBuilder.message.finished"; //$NON-NLS-1$ + private static final String TYPE_CLEAN = "AutotoolsMakefileBuilder.type.clean"; //$NON-NLS-1$ + private static final String CONSOLE_HEADER = "AutotoolsMakefileBuilder.message.console.header"; //$NON-NLS-1$ + + private static final String EMPTY_STRING = new String(); + public final String WHITESPACE = " "; //$NON-NLS-1$ + + protected boolean buildCalled; + + private String makeTargetName; + + @SuppressWarnings("unused") + private String preBuildErrMsg = new String(); + @SuppressWarnings("unused") + private String postBuildErrMsg = new String(); + + public static String getBuilderId() { + return BUILDER_ID; + } + + public static boolean hasTargetBuilder(IProject project) { + try { + // When a project is converted to an Autotools project, we + // replace the ManagedMake builder with a special one that + // handles MakeTargets. If a project is brought into Eclipse and + // uses the New Project Wizard to create a ManagedMake project that + // is of type: Autotools, this added step is not done. If we know + // we have an Autotools project from the configuration id, then + // we should add the builder now. We also should replace the + // default ManagedMake scanner provider with the Autotools one, + // then return true. + if (project.getNature(ManagedCProjectNature.MNG_NATURE_ID) != null) { + IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project); + IManagedProject m = info.getManagedProject(); + if (m != null && m.getProjectType().getId().equals(AUTOTOOLS_PROJECT_TYPE_ID)) { + AutotoolsProjectNature.addAutotoolsBuilder(project, new NullProgressMonitor()); + AutotoolsPlugin.verifyScannerInfoProvider(project); + return true; + } + } + } catch (CoreException e) { + // Don't care...fall through to not found. + } catch (Exception f) { + // Don't care...fall through to not found. + } + // Otherwise not found. + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.core.internal.events.InternalBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor) + */ + @SuppressWarnings({ "unchecked", "deprecation" }) + protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { + IProject[] results = null; + IProject project = getProject(); + IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project); + IManagedBuilderMakefileGenerator generator = null; + try { + // Figure out the working directory for the build and make sure there is a makefile there + // If not, mark a rebuild is required so that configuration will get + // invoked. + IWorkspace workspace = project.getWorkspace(); + if (workspace != null) { + IWorkspaceRoot root = workspace.getRoot(); + if (root != null) { + if (info.getDefaultConfiguration() == null) + return null; + generator = new MakeGenerator(); + generator.initialize(getProject(), info, monitor); + IPath buildDir = project.getLocation().append(generator.getBuildWorkingDir()); + IPath makefilePath = buildDir.append(generator.getMakefileName()); + IFile makefile = root.getFileForLocation(makefilePath); + if (makefile == null || !makefile.exists()) { + info.setRebuildState(true); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + makeTargetName = (String)args.get("org.eclipse.cdt.make.core.build.target.inc"); //$NON-NLS-1$ + + buildCalled = true; + /** + * @see IncrementalProjectBuilder#build + */ +// fBuildSet.start(this); + + // Hijack the build. This is because the CommonBuilder code will + // try and create builders for a MakeTarget build. We don't want + // that because this will default to using the GnuMakefileGenerator + // which fails. We want to use our Autotools MakeGenerator and + // perform a make from the top-level. + if(VERBOSE) + outputTrace(project.getName(), ">>build requested, type = " + kind); //$NON-NLS-1$ + + IConfiguration cfg = info.getDefaultConfiguration(); + + // Assemble the information needed to generate the targets + String prebuildStep = cfg.getPrebuildStep(); + try{ + //try to resolve the build macros in the prebuild step + prebuildStep = ManagedBuildManager.getBuildMacroProvider().resolveValueToMakefileFormat( + prebuildStep, + EMPTY_STRING, + WHITESPACE, + IBuildMacroProvider.CONTEXT_CONFIGURATION, + cfg); + } catch (BuildMacroException e){ + } + prebuildStep = prebuildStep.trim(); // Remove leading and trailing whitespace (and control characters) + + String postbuildStep = cfg.getPostbuildStep(); + try{ + //try to resolve the build macros in the postbuild step + postbuildStep = ManagedBuildManager.getBuildMacroProvider().resolveValueToMakefileFormat( + postbuildStep, + EMPTY_STRING, + WHITESPACE, + IBuildMacroProvider.CONTEXT_CONFIGURATION, + cfg); + + } catch (BuildMacroException e){ + } + postbuildStep = postbuildStep.trim(); // Remove leading and trailing whitespace (and control characters) + String preannouncebuildStep = cfg.getPreannouncebuildStep(); + String postannouncebuildStep = cfg.getPostannouncebuildStep(); + + IConsole console = null; + ConsoleOutputStream consoleOutStream = null; + CommandLauncher launcher = null; + String[] env = null; + Process proc = null; + OutputStream stdout = null; + OutputStream stderr = null; + + // If we have a prebuild or postbuild step, set up a command launcher to use. + if (!prebuildStep.equals("") || !postbuildStep.equals("")) { + console = CCorePlugin.getDefault().getConsole("org.eclipse.linuxtools.cdt.autotools.buildStepsConsole"); // $NON-NLS-1$ + console.start(project); + consoleOutStream = console.getOutputStream(); + stdout = consoleOutStream; + stderr = consoleOutStream; + launcher = new CommandLauncher(); + // Set the environment + IEnvironmentVariable variables[] = ManagedBuildManager + .getEnvironmentVariableProvider().getVariables(cfg, true); + ArrayList<String> envList = new ArrayList<String>(); + if (variables != null) { + for (int i = 0; i < variables.length; i++) { + envList.add(variables[i].getName() + + "=" + variables[i].getValue()); //$NON-NLS-1$ + } + env = (String[]) envList.toArray(new String[envList.size()]); + } + } + + // Check for a prebuild step and execute it if it exists. + if (!prebuildStep.equals("")) { + monitor.subTask(preannouncebuildStep); + + StringBuffer buffer = new StringBuffer(); + buffer.append(preannouncebuildStep); + buffer.append(System.getProperty("line.separator", "\n")); // $NON-NLS-1$ // $NON-NLS-2$ + + try { + consoleOutStream.write(buffer.toString().getBytes()); + consoleOutStream.flush(); + } catch (IOException e) { + // do nothing + } + + launcher.showCommand(true); + String[] tmp = prebuildStep.split("\\s"); + String[] cmdargs = new String[tmp.length - 1]; + if (tmp.length > 1) + System.arraycopy(tmp, 1, cmdargs, 0, tmp.length - 1); + proc = launcher.execute(new Path(tmp[0]), cmdargs, env, + project.getLocation().append(generator.getBuildWorkingDir()), monitor); + if (proc != null) { + try { + // Close the input of the process since we will never write to + // it + proc.getOutputStream().close(); + } catch (IOException e) { + } + + if (launcher.waitAndRead(stdout, stderr, new SubProgressMonitor( + monitor, IProgressMonitor.UNKNOWN)) != CommandLauncher.OK) { + preBuildErrMsg = launcher.getErrorMessage(); + } + } + } + + // Perform build + + ToolChain toolChain = (ToolChain)cfg.getToolChain(); + IBuilder oldBuilder = cfg.getBuilder(); + String workingDir = generator.getBuildWorkingDir().toString(); + IPath location = project.getLocation().append(workingDir); + oldBuilder.setBuildPath(location.toString()); + oldBuilder.setBuildFileGeneratorElement(AutotoolsPlugin.getDefault().getGeneratorElement()); + IBuilder builder = new AutotoolsBuilder(cfg.getEditableBuilder(), project, toolChain); + String buildLocation = null; + String buildCommand = null; + String buildArguments = null; + if (makeTargetName != null) { + // We have a MakeTarget. Get the location and command. + buildLocation = (String)args.get("org.eclipse.cdt.make.core.build.location"); // $NON-NLS-1$ + buildCommand = (String)args.get("org.eclipse.cdt.make.core.build.command"); // $NON-NLS-1$ + buildArguments = (String)args.get("org.eclipse.cdt.make.core.build.arguments"); // $NON-NLS-1$ + } + if (buildLocation == null) { + builder.setBuildPath(location.toString()); + } + else { + IWorkspace workspace = project.getWorkspace(); + builder.setBuildPath(workspace.getRoot().getLocation().append(buildLocation).toString()); + builder.setManagedBuildOn(false); // needed to avoid ManagedBuild from defaulting directory of makefile. + } + if (buildCommand != null) + builder.setBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND, buildCommand); + if (buildArguments != null) + builder.setBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, buildArguments); + builder.setAutoBuildEnable(true); + builder.setCleanBuildEnable(false); // Don't want clean build done ahead of our build. + // Following is needed to circumvent the CommonBuilder from using the default + // GNUMakefileGenerator. + builder.setBuildFileGeneratorElement(AutotoolsPlugin.getDefault().getGeneratorElement()); + toolChain.setBuilder((Builder)builder); + + IProject[] projects = null; + try { + projects = super.build(kind, args, monitor); + } finally { + // Must ensure we reset everything back so configuration will be run in future. + toolChain.setBuilder((Builder)oldBuilder); + } + + if(VERBOSE) + outputTrace(project.getName(), "<<done build requested, type = " + kind); //$NON-NLS-1$ + + results = projects; + buildCalled = false; + // Check for a postbuild step and execute it if it exists. + if (!postbuildStep.equals("")) { + monitor.subTask(postannouncebuildStep); + StringBuffer buffer = new StringBuffer(); + buffer.append(postannouncebuildStep); + buffer.append(System.getProperty("line.separator", "\n")); // $NON-NLS-1$ // $NON-NLS-2$ + + try { + consoleOutStream.write(buffer.toString().getBytes()); + consoleOutStream.flush(); + } catch (IOException e) { + // do nothing + } + String[] tmp = postbuildStep.split("\\s"); + String[] cmdargs = new String[tmp.length - 1]; + if (tmp.length > 1) + System.arraycopy(tmp, 1, cmdargs, 0, tmp.length - 1); + proc = launcher.execute(new Path(tmp[0]), cmdargs, env, + project.getLocation().append(generator.getBuildWorkingDir()), monitor); + if (proc != null) { + try { + // Close the input of the process since we will never write to + // it + proc.getOutputStream().close(); + } catch (IOException e) { + } + + if (launcher.waitAndRead(stdout, stderr, new SubProgressMonitor( + monitor, IProgressMonitor.UNKNOWN)) != CommandLauncher.OK) { + postBuildErrMsg = launcher.getErrorMessage(); + } + } + } + } + return results; + } + + @SuppressWarnings({ "unchecked", "deprecation" }) + protected void clean(IProgressMonitor monitor) throws CoreException { + // See what type of cleaning the user has set up in the + // build properties dialog. + String cleanDelete = null; + try { + cleanDelete = getProject().getPersistentProperty(AutotoolsPropertyConstants.CLEAN_DELETE); + } catch (CoreException ce) { + // do nothing + } + + if (cleanDelete != null && cleanDelete.equals(AutotoolsPropertyConstants.TRUE)) + removeBuildDir(monitor); + else { + IProject project = getProject(); + IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project); + IConfiguration cfg = info.getDefaultConfiguration(); + IManagedBuilderMakefileGenerator generator = new MakeGenerator(); + generator.initialize(getProject(), info, monitor); + +// // Hijack the builder itself so that instead of ManagedMake +// // policy of defaulting the build path to the configuration name, +// // we get the build occurring in the builddir configure tool setting. +// builders[0] = new AutotoolsBuilder(cfg.getEditableBuilder(), project); +// builders[0].setBuildPath(project.getLocation().append(generator.getBuildWorkingDir()).toOSString()); +// builders[0].setAutoBuildEnable(true); +// builders[0].setCleanBuildEnable(true); +// builders[0].setManagedBuildOn(false); + + ToolChain toolChain = (ToolChain)cfg.getToolChain(); + IBuilder oldBuilder = cfg.getBuilder(); + IBuilder builder = new AutotoolsBuilder(cfg.getEditableBuilder(), project, toolChain); + builder.setBuildPath(project.getLocation().append(generator.getBuildWorkingDir()).toOSString()); + builder.setAutoBuildEnable(true); + builder.setCleanBuildEnable(true); + builder.setManagedBuildOn(false); + // Following is needed to circumvent the CommonBuilder from using the default + // GNUMakefileGenerator. + builder.setBuildFileGeneratorElement(AutotoolsPlugin.getDefault().getGeneratorElement()); + toolChain.setBuilder((Builder)builder); + + try { + super.build(CLEAN_BUILD, (Map)null, monitor); + } finally { + toolChain.setBuilder((Builder)oldBuilder); + } + } + } + + protected void removeBuildDir(IProgressMonitor monitor) { + try { + // use brute force approach + IProject project = getProject(); + IWorkspace workspace = AutotoolsPlugin.getWorkspace(); + IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project); + IConfiguration cfg = info.getDefaultConfiguration(); + IManagedBuilderMakefileGenerator generator = new MakeGenerator(); + generator.initialize(getProject(), info, monitor); + String buildPath = project.getFullPath().append(generator.getBuildWorkingDir()).toOSString(); + IResource rc = workspace.getRoot().findMember(buildPath); + if (rc == null || rc.getType() != IResource.FOLDER) + return; + IFolder buildDir = (IFolder)rc; + String status = AutotoolsPlugin.getFormattedString("AutotoolsMakefileBuilder.message.clean.deleting.output", new String[]{buildDir.getName()}); //$NON-NLS-1$ + monitor.subTask(status); + workspace.delete(new IResource[]{buildDir}, true, monitor); + StringBuffer buf = new StringBuffer(); + // write to the console + +// IConsole console = CCorePlugin.getDefault().getConsole(); +// console.start(getProject()); + // Get a build console for the project + IConsole console = CCorePlugin.getDefault().getConsole(); + console.start(project); +// IConsole console = bInfo.getConsole(); + ConsoleOutputStream consoleOutStream = console.getOutputStream(); + String[] consoleHeader = new String[3]; + consoleHeader[0] = AutotoolsPlugin.getResourceString(TYPE_CLEAN); + consoleHeader[1] = cfg.getName(); + consoleHeader[2] = project.getName(); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + buf.append(AutotoolsPlugin.getFormattedString(CONSOLE_HEADER, consoleHeader)); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + consoleOutStream.write(buf.toString().getBytes()); + consoleOutStream.flush(); + buf = new StringBuffer(); + // Report a successful clean + String successMsg = AutotoolsPlugin.getFormattedString(BUILD_FINISHED, new String[]{project.getName()}); + buf.append(successMsg); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ + consoleOutStream.write(buf.toString().getBytes()); + consoleOutStream.flush(); + consoleOutStream.close(); + } catch (IOException io) { + // Ignore console failures... + } catch (CoreException e) { + // Ignore console failures... + } + } + + /* (non-javadoc) + * Answers an array of strings with the proper make targets + * for a build with no custom prebuild/postbuild steps + * + * @param fullBuild + * @return + */ + protected String[] getTargets(int kind, IBuilder builder) { + List<String> args = new ArrayList<String>(); + String buildTarget = "all"; + switch (kind) { + case CLEAN_BUILD: + // For a clean build, we use the clean make target set up by the user + // in the build properties dialog. Otherwise, we use the default for + // an autotools project. + String target = null; + try { + target = getProject().getPersistentProperty(AutotoolsPropertyConstants.CLEAN_MAKE_TARGET); + } catch (CoreException ce) { + // do nothing + } + if (target == null) + target = AutotoolsPropertyConstants.CLEAN_MAKE_TARGET_DEFAULT; + args.add(target); + break; + case FULL_BUILD: + if (makeTargetName != null) + buildTarget = makeTargetName; + case AUTO_BUILD: + case INCREMENTAL_BUILD: + args.addAll(makeArrayList(buildTarget)); + break; + } + return (String[])args.toArray(new String[args.size()]); + } + + // Turn the string into an array. + ArrayList<String> makeArrayList(String string) { + string.trim(); + char[] array = string.toCharArray(); + ArrayList<String> aList = new ArrayList<String>(); + StringBuffer buffer = new StringBuffer(); + boolean inComment = false; + for (int i = 0; i < array.length; i++) { + char c = array[i]; + if (array[i] == '"' || array[i] == '\'') { + if (i > 0 && array[i - 1] == '\\') { + inComment = false; + } else { + inComment = !inComment; + } + } + if (c == ' ' && !inComment) { + aList.add(buffer.toString()); + buffer = new StringBuffer(); + } else { + buffer.append(c); + } + } + if (buffer.length() > 0) + aList.add(buffer.toString()); + return aList; + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsPlugin.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsPlugin.java new file mode 100644 index 0000000000..5e2e495cbe --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsPlugin.java @@ -0,0 +1,324 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools; + +import java.lang.reflect.InvocationTargetException; +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.ICDescriptor; +import org.eclipse.cdt.core.ICExtensionReference; +import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The main plugin class to be used in the desktop. + */ +@SuppressWarnings("deprecation") +public class AutotoolsPlugin extends AbstractUIPlugin { + + //The shared instance. + private static AutotoolsPlugin plugin; + private ResourceBundle resourceBundle; + + public static final String PLUGIN_ID = "org.eclipse.linuxtools.cdt.autotools"; //$NON-NLS-1$ + + private IConfigurationElement generatorElement; + + public static final String EXTENSION_POINT_ID = ManagedBuilderCorePlugin.getUniqueIdentifier() + ".buildDefinitions"; //$NON-NLS-1$ + public static final String BUILDER = "builder"; //$NON-NLS-1$ + public static final String ID_ELEMENT_NAME = "id"; // $NON-NLS-1$ + public static final String AUTOTOOLS_BUILDER_ID = PLUGIN_ID + ".builder"; // $NON-NLS-1$ + + /** + * The constructor. + */ + public AutotoolsPlugin() { + plugin = this; + try { + resourceBundle = ResourceBundle.getBundle("org.eclipse.linuxtools.cdt.autotools.Resources"); //$NON-NLS-1$ + } catch (MissingResourceException x) { + resourceBundle = null; + } + + } + + public static String getPluginId() { + return PLUGIN_ID; + } + + public static String getUniqueIdentifier() { + if (getDefault() == null) { + // If the default instance is not yet initialized, + // return a static identifier. This identifier must + // match the plugin id defined in plugin.xml + return PLUGIN_ID; + } + return getDefault().getBundle().getSymbolicName(); + } + + public static void verifyScannerInfoProvider(IProject project) throws CoreException { + boolean found = false; + ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(project, true); + ICExtensionReference[] refs = desc.get(CCorePlugin.BUILD_SCANNER_INFO_UNIQ_ID); + for (int i = 0; i < refs.length; ++i) { + if (refs[i].getID().equals(AutotoolsScannerInfoProvider.INTERFACE_IDENTITY)) + found = true; + } + if (!found) { + setScannerInfoProvider(project); + } + } + + public static void setScannerInfoProvider(IProject project) throws CoreException { + ICDescriptor desc = CCorePlugin.getDefault().getCProjectDescription(project, true); + desc.remove(CCorePlugin.BUILD_SCANNER_INFO_UNIQ_ID); + desc.create(CCorePlugin.BUILD_SCANNER_INFO_UNIQ_ID, AutotoolsScannerInfoProvider.INTERFACE_IDENTITY); + } + + /** + * This method is called upon plug-in activation + */ + public void start(BundleContext context) throws Exception { + super.start(context); + } + + /** + * This method is called when the plug-in is stopped + */ + public void stop(BundleContext context) throws Exception { + super.stop(context); + plugin = null; + } + + /** + * Returns the shared instance. + */ + public static AutotoolsPlugin getDefault() { + return plugin; + } + + /** + * Returns active shell. + */ + public static Shell getActiveWorkbenchShell() { + IWorkbenchWindow window = getDefault().getWorkbench().getActiveWorkbenchWindow(); + if (window != null) { + return window.getShell(); + } + return null; + } + + /** + * Returns the string from the plugin's resource bundle, + * or 'key' if not found. + * + * @param key the message key + * @return the resource bundle message + */ + public static String getResourceString(String key) { + ResourceBundle bundle = AutotoolsPlugin.getDefault().getResourceBundle(); + try { + return bundle.getString(key); + } catch (MissingResourceException e) { + return key; + } + } + + /** + * Returns the string from the plugin's resource bundle, + * or 'key' if not found. + * + * @param key the message key + * @param args an array of substituition strings + * @return the resource bundle message + */ + public static String getFormattedString(String key, String[] args) { + return MessageFormat.format(getResourceString(key), (Object[])args); + } + + /** + * Returns the plugin's resource bundle, + */ + public ResourceBundle getResourceBundle() { + return resourceBundle; + } + + /** + * Get the configuration element for the Autotools Makefile generator + * @return the generator element + */ + public IConfigurationElement getGeneratorElement() { + if (generatorElement == null) { + IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(EXTENSION_POINT_ID); + if( extensionPoint != null) { + IExtension[] extensions = extensionPoint.getExtensions(); + if (extensions != null) { + for (int i = 0; i < extensions.length; ++i) { + IExtension extension = extensions[i]; + + IConfigurationElement[] elements = extension.getConfigurationElements(); + + // Get the managedBuildRevsion of the extension. + for (int j = 0; j < elements.length; j++) { + IConfigurationElement element = elements[j]; + if (element.getName().equals(BUILDER)) { + String id = element.getAttribute(ID_ELEMENT_NAME); + if (id.equals(AUTOTOOLS_BUILDER_ID)) { + generatorElement = element; + break; + } + } + } + } + } + } + } + return generatorElement; + } + + /** + * Returns an image descriptor for the image file at the given + * plug-in relative path. + * + * @param path the path + * @return the image descriptor + */ + public static ImageDescriptor getImageDescriptor(String path) { + return AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.linuxtools.cdt.autotools", path); + } + + public static void log(IStatus status) { + ResourcesPlugin.getPlugin().getLog().log(status); + } + + public static void logErrorMessage(String message) { + log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, message, null)); + } + + public static void logException(Throwable e, final String title, String message) { + if (e instanceof InvocationTargetException) { + e = ((InvocationTargetException) e).getTargetException(); + } + IStatus status = null; + if (e instanceof CoreException) + status = ((CoreException) e).getStatus(); + else { + if (message == null) + message = e.getMessage(); + if (message == null) + message = e.toString(); + status = new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.OK, message, e); + } + ResourcesPlugin.getPlugin().getLog().log(status); + Display display; + display = Display.getCurrent(); + if (display == null) + display = Display.getDefault(); + final IStatus fstatus = status; + display.asyncExec(new Runnable() { + public void run() { + ErrorDialog.openError(null, title, null, fstatus); + } + }); + } + + public static void logException(Throwable e) { + logException(e, null, null); + } + + public static void log(Throwable e) { + if (e instanceof InvocationTargetException) + e = ((InvocationTargetException) e).getTargetException(); + IStatus status = null; + if (e instanceof CoreException) + status = ((CoreException) e).getStatus(); + else + status = new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.OK, e.getMessage(), e); + log(status); + } + + /** + * Utility method with conventions + */ + public static void errorDialog(Shell shell, String title, String message, IStatus s) { + log(s); + // if the 'message' resource string and the IStatus' message are the same, + // don't show both in the dialog + if (s != null && message.equals(s.getMessage())) { + message = null; + } + ErrorDialog.openError(shell, title, message, s); + } + + /** + * Utility method with conventions + */ + public static void errorDialog(Shell shell, String title, String message, Throwable t) { + log(t); + IStatus status; + if (t instanceof CoreException) { + status = ((CoreException) t).getStatus(); + // if the 'message' resource string and the IStatus' message are the same, + // don't show both in the dialog + if (status != null && message.equals(status.getMessage())) { + message = null; + } + } else { + status = new Status(IStatus.ERROR, AutotoolsPlugin.getUniqueIdentifier(), -1, "Internal Error: ", t); //$NON-NLS-1$ + } + ErrorDialog.openError(shell, title, message, status); + } + + /** + * Returns the workspace instance. + */ + public static IWorkspace getWorkspace() { + return ResourcesPlugin.getWorkspace(); + } + + /** + * Returns the active workbench window or <code>null</code> if none + */ + public static IWorkbenchWindow getActiveWorkbenchWindow() { + return getDefault().getWorkbench().getActiveWorkbenchWindow(); + } + + /** + * Returns the active workbench page or <code>null</code> if none. + */ + public static IWorkbenchPage getActivePage() { + IWorkbenchWindow window= getActiveWorkbenchWindow(); + if (window != null) { + return window.getActivePage(); + } + return null; + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsProjectNature.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsProjectNature.java new file mode 100644 index 0000000000..5a7f311a29 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsProjectNature.java @@ -0,0 +1,175 @@ +/******************************************************************************* + * Copyright (c) 2008 Red Hat Inc.. and others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial implementation + * IBM Rational Software - add and remove nature static methods + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Vector; + +import org.eclipse.core.resources.ICommand; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IProjectNature; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; + +public class AutotoolsProjectNature implements IProjectNature { + + public static final String AUTOTOOLS_NATURE_ID = AutotoolsPlugin.getUniqueIdentifier() + ".autotoolsNature"; //$NON-NLS-1$ + + private IProject project; + + /* (non-Javadoc) + * @see org.eclipse.core.resources.IProjectNature#configure() + */ + public void configure() throws CoreException { + addAutotoolsBuilder(project, new NullProgressMonitor()); + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.IProjectNature#deconfigure() + */ + public void deconfigure() throws CoreException { + // TODO remove builder from here + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.IProjectNature#getProject() + */ + public IProject getProject() { + return project; + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core.resources.IProject) + */ + public void setProject(IProject project) { + this.project = project; + } + + /** + * Add the Autotools builder to the project + * @param project + * @param monitor + * @throws CoreException + */ + public static void addAutotoolsBuilder(IProject project, IProgressMonitor monitor) throws CoreException { + // Add the builder to the project + IProjectDescription description = project.getDescription(); + ICommand[] commands = description.getBuildSpec(); + + // TODO Remove the cbuilder check when the new StandardBuild nature adds the cbuilder + for (int i = 0; i < commands.length; i++) { + ICommand command = commands[i]; + String builderName = command.getBuilderName(); + // If there is a ManagedMake makefile generator, remove it as it will + // cause an additional build "all" to occur when we are making any target. + if (builderName.equals("org.eclipse.cdt.core.cbuilder") || + builderName.equals(AutotoolsMakefileBuilder.MANAGED_BUILDER_ID)) { //$NON-NLS-1$ + // Remove the command + Vector<ICommand> vec = new Vector<ICommand>(Arrays.asList(commands)); + vec.removeElementAt(i); + vec.trimToSize(); + ICommand[] tempCommands = (ICommand[]) vec.toArray(new ICommand[commands.length-1]); + description.setBuildSpec(tempCommands); + project.setDescription(description, new NullProgressMonitor()); + break; + } + } + + commands = description.getBuildSpec(); + boolean found = false; + // See if the builder is already there + for (int i = 0; i < commands.length; ++i) { + if (commands[i].getBuilderName().equals(AutotoolsMakefileBuilder.BUILDER_ID)) { + found = true; + break; + } + } + if (!found) { + //add builder to project + ICommand command = description.newCommand(); + command.setBuilderName(AutotoolsMakefileBuilder.BUILDER_ID); + ICommand[] newCommands = new ICommand[commands.length + 1]; + // Add it before other builders. + System.arraycopy(commands, 0, newCommands, 1, commands.length); + newCommands[0] = command; + description.setBuildSpec(newCommands); + project.setDescription(description, new NullProgressMonitor()); + } + } + + /** + * Utility method for adding an autotools nature to a project. + * + * @param proj the project to add the autotools nature to. + * @param monitor a progress monitor to indicate the duration of the operation, or + * <code>null</code> if progress reporting is not required. + */ + public static void addAutotoolsNature(IProject project, IProgressMonitor monitor) throws CoreException { + addNature(project, AUTOTOOLS_NATURE_ID, monitor); + } + + /** + * Utility method for adding a nature to a project. + * + * @param proj the project to add the nature to. + * @param natureId the id of the nature to assign to the project + * @param monitor a progress monitor to indicate the duration of the operation, or + * <code>null</code> if progress reporting is not required. + */ + public static void addNature(IProject project, String natureId, IProgressMonitor monitor) throws CoreException { + IProjectDescription description = project.getDescription(); + String[] prevNatures = description.getNatureIds(); + for (int i = 0; i < prevNatures.length; i++) { + if (natureId.equals(prevNatures[i])) + return; + } + String[] newNatures = new String[prevNatures.length + 1]; + System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length); + newNatures[prevNatures.length] = natureId; + description.setNatureIds(newNatures); + project.setDescription(description, monitor); + } + + /** + * Utility method to remove the autotools nature from a project. + * + * @param project to remove the autotools nature from + * @param mon progress monitor to indicate the duration of the operation, or + * <code>null</code> if progress reporting is not required. + * @throws CoreException + */ + public static void removeAutotoolsNature(IProject project, IProgressMonitor mon) throws CoreException { + removeNature(project, AUTOTOOLS_NATURE_ID, mon); + } + + /** + * Utility method for removing a project nature from a project. + * + * @param proj the project to remove the nature from + * @param natureId the nature id to remove + * @param monitor a progress monitor to indicate the duration of the operation, or + * <code>null</code> if progress reporting is not required. + */ + public static void removeNature(IProject project, String natureId, IProgressMonitor monitor) throws CoreException { + IProjectDescription description = project.getDescription(); + String[] prevNatures = description.getNatureIds(); + List<String> newNatures = new ArrayList<String>(Arrays.asList(prevNatures)); + newNatures.remove(natureId); + description.setNatureIds((String[])newNatures.toArray(new String[newNatures.size()])); + project.setDescription(description, monitor); + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsProjectPropertyTester.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsProjectPropertyTester.java new file mode 100644 index 0000000000..a561d6a4d8 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsProjectPropertyTester.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools; + +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; + +public class AutotoolsProjectPropertyTester extends PropertyTester { + + public AutotoolsProjectPropertyTester() { + // nothing needed + } + + public boolean test(Object receiver, String property, Object[] args, + Object expectedValue) { + IProject project = null; + IResource resource = (IResource)receiver; + project = resource.getProject(); + return AutotoolsMakefileBuilder.hasTargetBuilder(project); + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsScannerInfo.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsScannerInfo.java new file mode 100644 index 0000000000..83c331d6e1 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsScannerInfo.java @@ -0,0 +1,431 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.CommandLauncher; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfoChangeListener; +import org.eclipse.cdt.managedbuilder.core.BuildException; +import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.IOption; +import org.eclipse.cdt.managedbuilder.core.ITool; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.linuxtools.cdt.autotools.ui.properties.AutotoolsPropertyConstants; + + +// This class is used to get and store information from the Autotools +// makefiles for a specific file in a specific Autotools project. +// It gets information by invoking make with special options +// to find out what occurs if the file in question has changed. +public class AutotoolsScannerInfo implements IScannerInfo { + + private IResource res; + private IProject project; + private IPath filePath; + private String[] includePaths; + @SuppressWarnings("unchecked") + private HashMap definedSymbols; + private boolean isDirty; + private String compilationString; + private String dirName; + private HashSet<IScannerInfoChangeListener> listeners = new HashSet<IScannerInfoChangeListener>(); + + public AutotoolsScannerInfo (IResource res) { + this.res = res; + this.project = res.getProject(); + this.filePath = res.getFullPath(); + } + + public void addListener(IScannerInfoChangeListener listener) { + if (!listeners.contains(listener)) { + listeners.add(listener); + } + } + + public void removeListener(IScannerInfoChangeListener listener) { + if (listeners.contains(listener)) { + listeners.remove(listener); + } + } + + // TODO: Should make a listener to watch all Makefiles up the + // tree from the resource. If any change, the include + // paths and options passed to make the file in question + // could change. + public void setDirty (boolean isDirty) { + this.isDirty = isDirty; + } + + private String buildFile (IPath filePath, IFile makefile, IManagedBuildInfo info) { + String outString = ""; + IPath dir = makefile.getFullPath().removeLastSegments(1); + IPath relFilePath = filePath.removeFirstSegments(dir.segmentCount()); + CommandLauncher launcher = new CommandLauncher(); + String[] env = null; + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + ByteArrayOutputStream stderr = stdout; + IPath makeCommandPath = new Path(info.getBuildCommand()); + ITool tool = info.getToolFromOutputExtension("status"); // $NON-NLS-1$ + IOption[] options = tool.getOptions(); + IPath runPath = null; + boolean done = false; + + for (int i = 0; i < options.length && !done; ++i) { + try { + if (options[i].getValueType() == IOption.STRING) { + String value = (String) options[i].getValue(); + String id = options[i].getId(); + if (id.indexOf("builddir") > 0) { // $NON-NLS-1$ + runPath = makefile.getProject().getLocation().append(value.trim()); + done = true; + } + } + } catch (BuildException e) { + // do nothing + } + } + + IProgressMonitor monitor = new NullProgressMonitor(); + String errMsg = null; + String[] makeArgs = new String[3]; + makeArgs[0] = "-n"; // $NON-NLS-1$ + makeArgs[1] = "all"; // $NON-NLS-1$ + makeArgs[2] = "MAKE=make -W " + relFilePath.toOSString(); //$NON-NLS-1$ + + try { + Process proc = launcher.execute(makeCommandPath, makeArgs, env, + runPath, new NullProgressMonitor()); + if (proc != null) { + try { + // Close the input of the process since we will never write to + // it + proc.getOutputStream().close(); + } catch (IOException e) { + } + + if (launcher.waitAndRead(stdout, stderr, new SubProgressMonitor( + monitor, IProgressMonitor.UNKNOWN)) != CommandLauncher.OK) { + errMsg = launcher.getErrorMessage(); + } + outString = stdout.toString(); + } else { + errMsg = launcher.getErrorMessage(); + } + } catch (CoreException e) { + errMsg = e.getLocalizedMessage(); + AutotoolsPlugin.logErrorMessage(errMsg); + } + return outString; + } + + private IFile getMakefile (IManagedBuildInfo info, IPath filePath) { + IWorkspaceRoot root = CCorePlugin.getWorkspace().getRoot(); + IPath dir = filePath.removeLastSegments(1); + IFile makefile = null; + boolean done = false; + IPath makefilePath = null; + // Look starting at source file directory for the + // Makefile.in or Makefile for the given file. + while (!done) { + makefilePath = dir.append("Makefile.in"); // $NON-NLS-1$ + makefile = root.getFile(makefilePath); + if (makefile != null && makefile.exists()) { + done = true; + continue; + } + makefilePath = dir.append("Makefile"); // $NON-NLS-1$ + makefile = root.getFile(makefilePath); + if (makefile != null && makefile.exists()) { + done = true; + } + else { + dir = dir.removeLastSegments(1); + if (dir.lastSegment() == null) + done = true; + } + } + return makefile; + } + + private String getCompilationString() { + if (compilationString != null && !isDirty) + return compilationString; + String makeWEnabled = null; + try { + makeWEnabled = project.getPersistentProperty(AutotoolsPropertyConstants.SCANNER_USE_MAKE_W); + } catch (CoreException e) { + // do nothing + } + if (!(res instanceof IFile) || + makeWEnabled == null || + makeWEnabled.equals("false")) // $NON-NLS-1$ + return null; + isDirty = false; + IWorkspaceRoot root = CCorePlugin.getWorkspace().getRoot(); + IFile file = root.getFile(filePath); + IFile makefile = null; + IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project); + // If the given file exists and we have a ManagedBuild, we may have + // an Autotools project source file. + if (file != null && file.exists() && info != null) { + makefile = getMakefile(info, filePath); + } + // We now have the closest directory to the given path + // that contains a Makefile.in or Makefile. This Makefile + // should contain a relative reference to the file in + // question. We now want to try and extract the include + // path from the top-level make run with the assumption + // that the file in question has been altered. + if (makefile != null) { + IPath dir = makefile.getFullPath().removeLastSegments(1); + // Get relative name of file as we assume the Makefile will + // refer to it this way. + String out = buildFile(filePath, makefile, info); + try { + boolean topLevel = dir.equals(project.getFullPath()); + Pattern p = null; + Matcher m = null; + if (!topLevel) { + String regex1 = "^Making.*in.*" + dir.lastSegment(); // $NON-NLS-1$ + p = Pattern.compile(regex1, Pattern.MULTILINE); + m = p.matcher(out); + } + if (topLevel || m.find()) { + Pattern p2 = null; + Matcher m2 = null; + String substr2 = out; + if (!topLevel) { + substr2 = out.substring(m.end()); + String regex2 = "^make.*Entering directory.*`(.*)'"; // $NON-NLS-1$ + p2 = Pattern.compile(regex2, Pattern.MULTILINE); + m2 = p2.matcher(substr2); + } + if (topLevel || m2.find()) { + String substr3 = null; + if (!topLevel) { + dirName = m2.group(1); + substr3 = substr2.substring(m2.start()); + } else { + dirName = ""; + substr3 = out; + } + // We need to test for both gcc and g++ compilers. + String regex3 = "^.*gcc.*?-I.*?" + filePath.lastSegment(); // $NON-NLS-1$ + String regex4 = "^.*g[+][+].*?-I.*?" + filePath.lastSegment(); // $NON-NLS-1$ + // Replace all continuation markers so we don't have to worry about newlines in + // the middle of a compilation string. + substr3 = substr3.replaceAll("\\\\\\n", ""); + Pattern p3 = Pattern.compile(regex3, Pattern.MULTILINE); + Matcher m3 = p3.matcher(substr3); + if (m3.find()) + compilationString = substr3.substring(m3.start(),m3.end()); + else { + String substr4 = substr3; + Pattern p4 = Pattern.compile(regex4, Pattern.MULTILINE); + Matcher m4 = p4.matcher(substr4); + if (m4.find()) + compilationString = substr3.substring(m4.start(),m4.end()); + } + } + } else if (!out.equals("")) { + compilationString = ""; + } + } catch (IllegalStateException t) { + // Mark as dirty for next time. + isDirty = true; + } + } + return compilationString; + } + + public String[] getIncludePaths() { + String[] pathArray = new String[0]; + if (project == null || filePath == null) + return pathArray; + if (includePaths != null && !isDirty && compilationString != null) { + return includePaths; + } + ArrayList<String> pathList = new ArrayList<String>(); + String cs = getCompilationString(); + if (cs != null) { + // Grab include paths specified via -I + Pattern p4 = Pattern.compile(" -I"); + String[] tokens = p4.split(cs); + for (int j = 1; j < tokens.length; ++j) { + String x = tokens[j].trim(); + int firstSpace = x.indexOf(' '); + if (firstSpace != -1) { + x = x.substring(0, firstSpace); + } + if (x.charAt(0) == '/') { + pathList.add(x); + } else { + IPath relPath = new Path(dirName); + relPath = relPath.append(x); + pathList.add(relPath.toOSString()); + } + } + // Grab include paths that are specified via -isystem + Pattern p5 = Pattern.compile(" -isystem"); + tokens = p5.split(cs); + for (int j = 1; j < tokens.length; ++j) { + String x = tokens[j].trim(); + int firstSpace = x.indexOf(' '); + if (firstSpace != -1) { + x = x.substring(0, firstSpace); + } + if (x.charAt(0) == '/') { + pathList.add(x); + } else { + IPath relPath = new Path(dirName); + relPath = relPath.append(x); + pathList.add(relPath.toOSString()); + } + } + } + + // The ManagedBuildManager is the normal default IScannerInfoProvider + // for Managed Projects. It has the ability to check gcc for the + // default include paths and we don't want to lose that. Append + // the include paths from it to the end of our list which is dynamically + // picking up the -I options. + + // TODO: Should we even allow the user-defined includePaths in settings? + // These will be picked up by the ManagedBuildManager. + IScannerInfo info = (IScannerInfo)ManagedBuildManager.getBuildInfo(project); + if (info != null) { + String[] extraIncludePaths = info.getIncludePaths(); + for (int i = 0; i < extraIncludePaths.length; ++i) { + pathList.add(extraIncludePaths[i]); + } + } + + includePaths = (String[])pathList.toArray(pathArray); + + // FIXME: Info has been updated. Is this the best place to notify listeners? + Iterator<IScannerInfoChangeListener> i = listeners.iterator(); + while (i.hasNext()) { + IScannerInfoChangeListener listener = (IScannerInfoChangeListener)i.next(); + listener.changeNotification(project, this); + } + return includePaths; + } + + @SuppressWarnings("unchecked") + public Map getDefinedSymbols () { + HashMap symbolMap = new HashMap(); + if (project == null || filePath == null) + return symbolMap; + if (definedSymbols != null && !isDirty && compilationString != null) { + return definedSymbols; + } + // Extract -D directives from the compilation string. + // TODO: Handle -U directives as well. + String cs = getCompilationString(); + if (cs != null) { + Pattern p4 = Pattern.compile("\\s-D([^\\s=]+)(?:=(\\\\\".*?\\\\\"|\\S*))?"); // $NON-NLS-1$ + Matcher m = p4.matcher(cs); + while(m.find()) { + String name = m.group(1); + String value = m.group(2); + if(value != null) + symbolMap.put(name, value.replace("\\", "")); // $NON-NLS-1$ $NON-NLS-2$ + else + symbolMap.put(name, ""); + } + } + // Add the defined symbols from ManagedBuildManager. This will include + // the builtin implicit defines from the compiler and the user-set + // defines from settings. Since these are added last, they will overwrite + // existing defines fished out of the Makefiles above. For the user-defined + // symbols, this is the correct behavior. For the implicit defines, + // this is not; however, this is not valid programming behavior and + // the compiler definitely warns against it. + IScannerInfo info = (IScannerInfo)ManagedBuildManager.getBuildInfo(project); + if (info != null) { + Map builtinDefinedSymbols = info.getDefinedSymbols(); + symbolMap.putAll(builtinDefinedSymbols); + } + + definedSymbols = symbolMap; + return definedSymbols; + } + + public void createIncludeChain(IFile include, IResource res) { + try { + // We store two different values. The first only lasts for the + // the session and is the actual resource. We prefer to work with + // this form as it is quicker. To handle persistence across + // sessions, we also store a persistent copy of the resource's + // path. When the session is brought back again, we will recreate + // the session chain again using the persistent data. + include.setSessionProperty(AutotoolsPropertyConstants.OPEN_INCLUDE, res); + include.setPersistentProperty(AutotoolsPropertyConstants.OPEN_INCLUDE_P, res.getLocation().toPortableString()); + } catch (CoreException e) { + // Do nothing + } + } + + /** + * + * @param resource the resource we are scanning + * @return the final resource in the include chain if one exists + * otherwise the resource itself + */ + public static IResource followIncludeChain(IResource resource) { + IResource res = resource; + try { + boolean done = false; + // In the case of include files, we chain to the file that + // included the header file. This may end up ultimately as + // a source file which has build parameters such as flag + // defines and a separate include path. + while (!done) { + while (res.getSessionProperty(AutotoolsPropertyConstants.OPEN_INCLUDE) != null) + res = (IResource)res.getSessionProperty(AutotoolsPropertyConstants.OPEN_INCLUDE); + String chainPath = res.getPersistentProperty(AutotoolsPropertyConstants.OPEN_INCLUDE_P); + if (chainPath != null) { + IPath location = Path.fromPortableString(chainPath); + IResource next = res.getWorkspace().getRoot().getFileForLocation(location); + res.setSessionProperty(AutotoolsPropertyConstants.OPEN_INCLUDE, next); + res = next; + } else + done = true; + } + } catch (CoreException e) { + // Do nothing + } finally { + resource = res; + } + return resource; + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsScannerInfoProvider.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsScannerInfoProvider.java new file mode 100644 index 0000000000..572ce76d5e --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/AutotoolsScannerInfoProvider.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.cdt.core.AbstractCExtension; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfoChangeListener; +import org.eclipse.cdt.core.parser.IScannerInfoProvider; +import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.linuxtools.cdt.autotools.ui.properties.AutotoolsPropertyConstants; + + +public class AutotoolsScannerInfoProvider extends AbstractCExtension implements IScannerInfoProvider { + + static private Map<String, Map<IResource, AutotoolsScannerInfo>> infoCollections = new HashMap<String, Map<IResource, AutotoolsScannerInfo>>(); + static public final String INTERFACE_IDENTITY = + AutotoolsPlugin.PLUGIN_ID + "." + "AutotoolsScannerInfoProvider"; // $NON-NLS-1$ + + protected String getCollectionName(IProject project) { + IManagedBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(project); + String config = project.getName() + "." + buildInfo.getConfigurationName(); + return config; + } + + public synchronized IScannerInfo getScannerInformation(IResource resource) { + IResource res = AutotoolsScannerInfo.followIncludeChain(resource); + // We keep scanner info separate per configuration. + // This is because one configuration may result in a file being + // compiled with one include path while another configuration + // may change the include path / defined symbols. + IProject project = resource.getProject(); + + // We punt for non-Autotools projects. This ScannerInfoProvider is used for + // all C Projects and we might get called for a non-Autotools project (e.g. + // unsubscribe operation when converting to C project). + if (!AutotoolsMakefileBuilder.hasTargetBuilder(project)) + return null; + + // Check if the scanner info has been marked dirty, in which case we need + // to mark all entries dirty. + Boolean isDirty = Boolean.FALSE; + try { + isDirty = (Boolean)project.getSessionProperty(AutotoolsPropertyConstants.SCANNER_INFO_DIRTY); + } catch (CoreException e) { + // do nothing + } + if (isDirty != null && isDirty.equals(Boolean.TRUE)) { + setDirty(project); + try { + project.setSessionProperty(AutotoolsPropertyConstants.SCANNER_INFO_DIRTY, Boolean.FALSE); + } catch (CoreException ce) { + // do nothing + } + } + String config = getCollectionName(project); + // Get the ScannerInfo collection for current configuration or else + // create an empty collection if one doesn't already exist. + Map<IResource, AutotoolsScannerInfo> infoCollection = infoCollections.get(config); + if (infoCollection == null) { + infoCollection = new HashMap<IResource, AutotoolsScannerInfo>(); + infoCollections.put(config, infoCollection); + } + AutotoolsScannerInfo info = (AutotoolsScannerInfo)infoCollection.get(res); + if (info == null) { + info = new AutotoolsScannerInfo(res); + infoCollection.put(res, info); + } + return info; + } + + private void setDirty(IProject project) { + String config = getCollectionName(project); + Map<IResource, AutotoolsScannerInfo> infoCollection = infoCollections.get(config); + if (infoCollection != null) { + Collection<AutotoolsScannerInfo> s = infoCollection.values(); + for (Iterator<AutotoolsScannerInfo> i = s.iterator(); i.hasNext();) { + AutotoolsScannerInfo info = (AutotoolsScannerInfo)i.next(); + info.setDirty(true); + } + } + } + + public void subscribe(IResource resource, + IScannerInfoChangeListener listener) { + AutotoolsScannerInfo info = (AutotoolsScannerInfo)getScannerInformation(resource); + info.addListener(listener); + } + + public void unsubscribe(IResource resource, + IScannerInfoChangeListener listener) { + AutotoolsScannerInfo info = (AutotoolsScannerInfo)getScannerInformation(resource); + if (info != null) + info.removeListener(listener); + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/MakeGenerator.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/MakeGenerator.java new file mode 100644 index 0000000000..aca5677d0e --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/MakeGenerator.java @@ -0,0 +1,1374 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.EOFException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.CommandLauncher; +import org.eclipse.cdt.core.ConsoleOutputStream; +import org.eclipse.cdt.core.ICDescriptor; +import org.eclipse.cdt.core.envvar.IEnvironmentVariable; +import org.eclipse.cdt.core.resources.IConsole; +import org.eclipse.cdt.core.settings.model.ICStorageElement; +import org.eclipse.cdt.make.core.IMakeTarget; +import org.eclipse.cdt.make.core.IMakeTargetManager; +import org.eclipse.cdt.make.core.MakeCorePlugin; +import org.eclipse.cdt.make.core.makefile.IMakefile; +import org.eclipse.cdt.make.core.makefile.ITarget; +import org.eclipse.cdt.make.core.makefile.ITargetRule; +import org.eclipse.cdt.managedbuilder.core.BuildException; +import org.eclipse.cdt.managedbuilder.core.IBuilder; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.IOption; +import org.eclipse.cdt.managedbuilder.core.ITool; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.cdt.managedbuilder.macros.BuildMacroException; +import org.eclipse.cdt.managedbuilder.macros.IBuildMacroProvider; +import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator; +import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator2; +import org.eclipse.cdt.newmake.core.IMakeCommonBuildInfo; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.resources.IWorkspaceRoot; +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.MultiStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.linuxtools.cdt.autotools.ui.properties.AutotoolsPropertyConstants; +import org.eclipse.linuxtools.internal.cdt.autotools.MarkerGenerator; + + +@SuppressWarnings("deprecation") +public class MakeGenerator extends MarkerGenerator implements IManagedBuilderMakefileGenerator, IManagedBuilderMakefileGenerator2 { + + public final String CONFIG_STATUS = "config.status"; //$NON-NLS-1$ + public final String MAKEFILE = "Makefile"; //$NON-NLS-1$ + public final String MAKEFILE_CVS = "Makefile.cvs"; //$NON-NLS-1$ + public final String SETTINGS_FILE_NAME = ".cdtconfigure"; //$NON-NLS-1$ + public final String SHELL_COMMAND = "sh"; //$NON-NLS-1$ + + public final String AUTOGEN_TOOL_ID = "org.eclipse.linuxtools.cdt.autotools.tool.autogen"; //$NON-NLS-1$ + public final String CONFIGURE_TOOL_ID = "org.eclipse.linuxtools.cdt.autotools.tool.configure"; //$NON-NLS-1$ + + public final String GENERATED_TARGET = AutotoolsPlugin.PLUGIN_ID + ".generated.MakeTarget"; //$NON-NLS-1$ + + private static final String MAKE_TARGET_KEY = MakeCorePlugin.getUniqueIdentifier() + ".buildtargets"; //$NON-NLS-1$ + private static final String BUILD_TARGET_ELEMENT = "buildTargets"; //$NON-NLS-1$ + private static final String TARGET_ELEMENT = "target"; //$NON-NLS-1$ + private static final String TARGET_ATTR_ID = "targetID"; //$NON-NLS-1$ + private static final String TARGET_ATTR_PATH = "path"; //$NON-NLS-1$ + private static final String TARGET_ATTR_NAME = "name"; //$NON-NLS-1$ + private static final String TARGET_STOP_ON_ERROR = "stopOnError"; //$NON-NLS-1$ + private static final String TARGET_USE_DEFAULT_CMD = "useDefaultCommand"; //$NON-NLS-1$ + private static final String TARGET_ARGUMENTS = "buildArguments"; //$NON-NLS-1$ + private static final String TARGET_COMMAND = "buildCommand"; //$NON-NLS-1$ + private static final String TARGET_RUN_ALL_BUILDERS = "runAllBuilders"; + private static final String TARGET = "buildTarget"; //$NON-NLS-1$ + + private IProject project; + + private IProgressMonitor monitor; + + private String buildDir; + private String srcDir; + + private IConfiguration cfg; + private IBuilder builder; + + public void generateDependencies() throws CoreException { + // TODO Auto-generated method stub + + } + + public MultiStatus generateMakefiles(IResourceDelta delta) + throws CoreException { + return regenerateMakefiles(); + } + + private void initializeBuildConfigDirs() { + ITool tool = cfg.getToolFromOutputExtension("status"); //$NON-NLS-1$ + IOption[] options = tool.getOptions(); + for (int i = 0; i < options.length; ++i) { + String id = options[i].getId(); + if (id.indexOf("builddir") > 0) { //$NON-NLS-1$ + buildDir = (String) options[i].getValue(); + try { + String resolved = ManagedBuildManager.getBuildMacroProvider().resolveValue(buildDir, "build", null, + IBuildMacroProvider.CONTEXT_CONFIGURATION, cfg); + buildDir = resolved; + } catch (BuildMacroException e) { + // do nothing + } +// try { +// builder.setBuildAttribute(IMakeCommonBuildInfo.BUILD_LOCATION, +// project.getLocation().append(buildDir).toOSString()); +// } catch (CoreException e) { +// e.printStackTrace(); +// } + } else if (id.indexOf("configdir") > 0) { //$NON-NLS-1$ + srcDir = (String) options[i].getValue(); + try { + String resolved = ManagedBuildManager.getBuildMacroProvider().resolveValue(srcDir, "", null, + IBuildMacroProvider.CONTEXT_CONFIGURATION, cfg); + srcDir = resolved; + } catch (BuildMacroException e) { + // do nothing + } + } + } + } + + public void initialize(IProject project, IManagedBuildInfo info, + IProgressMonitor monitor) { + this.project = project; + this.cfg = info.getDefaultConfiguration(); + this.builder = cfg.getBuilder(); + this.monitor = monitor; + initializeBuildConfigDirs(); + } + + public void initialize(int buildKind, IConfiguration cfg, IBuilder builder, + IProgressMonitor monitor) { + this.cfg = cfg; + this.builder = builder; + this.monitor = monitor; + this.project = (IProject)cfg.getManagedProject().getOwner(); + initializeBuildConfigDirs(); + } + + public IProject getProject() { + return project; + } + + public boolean isGeneratedResource(IResource resource) { + // TODO Auto-generated method stub + return false; + } + + public void regenerateDependencies(boolean force) throws CoreException { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) Check whether the build has been cancelled. Cancellation + * requests propagated to the caller by throwing <code>OperationCanceledException</code>. + * + * @see org.eclipse.core.runtime.OperationCanceledException#OperationCanceledException() + */ + protected void checkCancel() { + if (monitor != null && monitor.isCanceled()) { + throw new OperationCanceledException(); + } + } + + /* + * (non-Javadoc) Return or create the makefile needed for the build. If we + * are creating the resource, set the derived bit to true so the CM system + * ignores the contents. If the resource exists, respect the existing + * derived setting. + * + * @param makefilePath @return IFile + */ + protected IFile createFile(IPath makefilePath) throws CoreException { + // Create or get the handle for the makefile + IWorkspaceRoot root = CCorePlugin.getWorkspace().getRoot(); + IFile newFile = root.getFileForLocation(makefilePath); + if (newFile == null) { + newFile = root.getFile(makefilePath); + } + // Create the file if it does not exist + ByteArrayInputStream contents = new ByteArrayInputStream(new byte[0]); + try { + newFile.create(contents, false, new SubProgressMonitor(monitor, 1)); + // Make sure the new file is marked as derived + if (!newFile.isDerived()) { + newFile.setDerived(true); + } + + } catch (CoreException e) { + // If the file already existed locally, just refresh to get contents + if (e.getStatus().getCode() == IResourceStatus.PATH_OCCUPIED) + newFile.refreshLocal(IResource.DEPTH_ZERO, null); + else + throw e; + } + + return newFile; + } + + /* + * (non-Javadoc) Return or create the folder needed for the build output. If + * we are creating the folder, set the derived bit to true so the CM system + * ignores the contents. If the resource exists, respect the existing + * derived setting. + * + * @param string @return IPath + */ + private boolean createDirectory(String dirName) throws CoreException { + // Create or get the handle for the build directory + boolean rc = true; + IPath path = new Path(dirName); + if (dirName.length() == 0 || dirName.startsWith(".") || !dirName.startsWith("/")) + path = project.getLocation().append(dirName); + File f = path.toFile(); + if (!f.exists()) + rc = f.mkdirs(); + + return rc; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator#getBuildWorkingDir() + */ + public IPath getBuildWorkingDir() { + return new Path(buildDir); + } + + /* + * (non-Javadoc) Get the project's absolute path. @return IPath + */ + private IPath getProjectLocation() { + return project.getLocation(); + } + + private String getAbsoluteDirectory(String dir) { + IPath path = new Path(dir); + if (!path.isAbsolute()) { + IPath absPath = getProjectLocation().addTrailingSeparator().append( + path); + return getPathString(absPath); + } + return dir; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator#getMakefileName() + */ + public String getMakefileName() { + return new String(MAKEFILE); + } + + /* + * (non-Javadoc) + * + * @return the path to the configuration settings file + */ + protected IPath getConfigSettingsPath() { + IPath path = project.getWorkingLocation(AutotoolsPlugin.PLUGIN_ID).append(SETTINGS_FILE_NAME + "." + cfg.getName()); //$NON-NLS-1$ + return path; + } + + public void removeConfigSettings() { + File f = getConfigSettingsPath().toFile(); + try { + f.delete(); + } catch (Exception e) { + // do nothing + } + } + + public MultiStatus regenerateMakefiles() throws CoreException { + MultiStatus status; + int rc = IStatus.OK; + String errMsg = new String(); + boolean needFullConfigure = true; + + // See if the user has cancelled the build + checkCancel(); + + // Create the top-level directory for the build output + if (!createDirectory(buildDir)) { + rc = IStatus.ERROR; + errMsg = AutotoolsPlugin.getFormattedString("MakeGenerator.createdir.error", //$NON-NLS-1$ + new String[] {buildDir}); + return new MultiStatus(AutotoolsPlugin.getUniqueIdentifier(), + rc, errMsg, null); + } + + checkCancel(); + + // // How did we do + // if (!getInvalidDirList().isEmpty()) { + // status = new MultiStatus ( + // ManagedBuilderCorePlugin.getUniqueIdentifier(), + // IStatus.WARNING, + // new String(), + // null); + // // Add a new status for each of the bad folders + // iter = getInvalidDirList().iterator(); + // while (iter.hasNext()) { + // status.add(new Status ( + // IStatus.WARNING, + // ManagedBuilderCorePlugin.getUniqueIdentifier(), + // SPACES_IN_PATH, + // ((IContainer)iter.next()).getFullPath().toString(), + // null)); + // } + // } else { + // status = new MultiStatus( + // ManagedBuilderCorePlugin.getUniqueIdentifier(), + // IStatus.OK, + // new String(), + // null); + // } + + // Get a build console for the project + IConsole console = CCorePlugin.getDefault().getConsole("org.eclipse.linuxtools.cdt.autotools.configureConsole"); //$NON-NLS-1$ + + // Get the project and make sure there's a monitor to cancel the build + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + + try { + // If a config.status file exists in the build directory, we call it + // to + // regenerate the makefile + IPath configfile = getProjectLocation().append(buildDir).append( + CONFIG_STATUS); + IPath makefilePath = getProjectLocation().append(buildDir).append(MAKEFILE); + File configStatus = configfile.toFile(); + File makefile = makefilePath.toFile(); + IPath configSettingsPath = getConfigSettingsPath(); + File configSettings = configSettingsPath.toFile(); + String[] configArgs = getConfigArgs(); + + // We need to figure out if the end-user has changed the configuration + // settings. In such a case, we need to reconfigure from scratch + // regardless of whether config.status exists or not. + // We figure this out by saving the configuration settings to + // a special file and reading/comparing whenever we are asked to build. + if (configSettings.exists()) { + int i = 0; + boolean needSaveConfigArgs = false; + needFullConfigure = false; + try { + DataInputStream settings = new DataInputStream( + new BufferedInputStream(new FileInputStream(configSettings))); + // Get the first String in the configure settings file. + // Newer configure settings file start with the project name. + // If the project name is present and doesn't match the + // current project name, the project has been refactored and + // we need to do a full reconfigure. + settings.mark(100); + String s = settings.readUTF(); + if (s.startsWith("project=")) { //$NON-NLS-1$ + if (!s.substring(8).equals(project.getName())) { + needFullConfigure = true; + } + } else { + // An older configure arguments file. Reset + // to beginning and process as normal. + needSaveConfigArgs = true; + settings.reset(); + } + while (i < configArgs.length) { + s = settings.readUTF(); + if (!s.equals(configArgs[i])) { + i = configArgs.length; + needFullConfigure = true; + } + ++i; + } + if (settings.available() > 0) + needFullConfigure = true; + } catch (EOFException e) { + needFullConfigure = true; + } catch (IOException e) { + needFullConfigure = true; + } + if (needFullConfigure) { + // If we are going to do a full reconfigure, then if the current + // build directory exists, we should clean it out first. This is + // because the reconfiguration could change compile flags, etc.. + // and the Makefile might not detect a rebuild is required. In + // addition, the build directory itself could have been changed and + // we should remove the previous build. + File r = project.getLocation().append(buildDir).toFile(); + if (r != null && r.exists()) { + // See what type of cleaning the user has set up in the + // build properties dialog. + String cleanDelete = null; + try { + cleanDelete = getProject().getPersistentProperty(AutotoolsPropertyConstants.CLEAN_DELETE); + } catch (CoreException ce) { + // do nothing + } + + if (cleanDelete != null && cleanDelete.equals(AutotoolsPropertyConstants.TRUE)) { + SubProgressMonitor sub = new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN); + sub.beginTask(AutotoolsPlugin.getResourceString("MakeGenerator.clean.builddir"), IProgressMonitor.UNKNOWN); + try { + r.delete(); + } finally { + sub.done(); + } + } + else { + // There is a make target for cleaning. + if (makefile != null && makefile.exists()) { + String[] makeargs = new String[1]; + IPath makeCmd = new Path("make"); //$NON-NLS-1$ + String target = null; + try { + target = getProject().getPersistentProperty(AutotoolsPropertyConstants.CLEAN_MAKE_TARGET); + } catch (CoreException ce) { + // do nothing + } + if (target == null) + target = AutotoolsPropertyConstants.CLEAN_MAKE_TARGET_DEFAULT; + String args = builder.getBuildArguments(); + if (args != null && !(args = args.trim()).equals("")) { //$NON-NLS-1$ + String[] newArgs = makeArray(args); + makeargs = new String[newArgs.length + 1]; + System.arraycopy(newArgs, 0, makeargs, 0, newArgs.length); + } + makeargs[makeargs.length - 1] = target; + rc = runCommand(makeCmd, + project.getLocation().append(buildDir), + makeargs, + AutotoolsPlugin.getResourceString("MakeGenerator.clean.builddir"), //$NON-NLS-1$ + errMsg, console, true); + } + } + } + initializeBuildConfigDirs(); + createDirectory(buildDir); + // Mark the scanner info as dirty. + try { + project.setSessionProperty(AutotoolsPropertyConstants.SCANNER_INFO_DIRTY, Boolean.TRUE); + } catch (CoreException ce) { + // do nothing + } + } else if (needSaveConfigArgs) { + // No change in configuration args, but we have old + // style settings format which can't determine if project has + // been renamed. Refresh the settings file. + saveConfigArgs(configArgs); + } + } + + ArrayList<String> configureEnvs = new ArrayList<String>(); + IPath configurePath = getConfigurePath(configureEnvs); + ArrayList<String> autogenEnvs = new ArrayList<String>(); + IPath autogenPath = getAutogenPath(autogenEnvs); + + // Check if we have a config.status (meaning configure has already run). + if (!needFullConfigure && configStatus != null && configStatus.exists()) { + // If no corresponding Makefile in the same build location, then we + // can simply run config.status again to ensure the top level Makefile has been + // created. + if (makefile == null || !makefile.exists()) { + rc = runScript(configfile, project.getLocation().append( + buildDir), null, + AutotoolsPlugin.getResourceString("MakeGenerator.run.config.status"), //$NON-NLS-1$ + errMsg, console, null, true); + } + } + // Look for configure and configure from scratch + else if (configurePath.toFile().exists()) { + rc = runScript(configurePath, + project.getLocation().append(buildDir), + configArgs, + AutotoolsPlugin.getResourceString("MakeGenerator.gen.makefile"), //$NON-NLS-1$ + errMsg, console, configureEnvs, true); + if (rc != IStatus.ERROR) { + File makefileFile = project.getLocation().append(buildDir) + .append(MAKEFILE).toFile(); + addMakeTargetsToManager(makefileFile); + // TODO: should we do something special if configure doesn't + // return ok? + saveConfigArgs(configArgs); + } + } + // If no configure, look for autogen.sh which may create configure and + // possibly even run it. + else if (autogenPath.toFile().exists()) { + // Remove the existing config.status file since we use it + // to figure out if configure was run. + if (configStatus.exists()) + configStatus.delete(); + // Get any user-specified arguments for autogen. + String[] autogenArgs = getAutogenArgs(); + rc = runScript(autogenPath, + autogenPath.removeLastSegments(1), autogenArgs, + AutotoolsPlugin.getResourceString("MakeGenerator.autogen.sh"), //$NON-NLS-1$ + errMsg, console, autogenEnvs, true); + if (rc != IStatus.ERROR) { + configStatus =configfile.toFile(); + // Check for config.status. If it is created, then + // autogen.sh ran configure and we should not run it + // ourselves. + if (configStatus == null || !configStatus.exists()) { + rc = runScript(configurePath, + project.getLocation().append(buildDir), + configArgs, + AutotoolsPlugin.getResourceString("MakeGenerator.gen.makefile"), //$NON-NLS-1$ + errMsg, console, configureEnvs, false); + if (rc != IStatus.ERROR) { + File makefileFile = project.getLocation().append(buildDir) + .append(MAKEFILE).toFile(); + addMakeTargetsToManager(makefileFile); + } + } else { + File makefileFile = project.getLocation().append(buildDir) + .append(MAKEFILE).toFile(); + addMakeTargetsToManager(makefileFile); + } + } + } + // If nothing this far, look for a Makefile.cvs file which needs to be run. + else if (makefileCvsExists()) { + String[] makeargs = new String[1]; + IPath makeCmd = new Path("make"); //$NON-NLS-1$ + makeargs[0] = "-f" + getMakefileCVSPath().toOSString(); //$NON-NLS-1$ + rc = runCommand(makeCmd, + project.getLocation().append(buildDir), + makeargs, + AutotoolsPlugin.getResourceString("MakeGenerator.makefile.cvs"), //$NON-NLS-1$ + errMsg, console, true); + if (rc != IStatus.ERROR) { + File makefileFile = project.getLocation().append(buildDir) + .append(MAKEFILE).toFile(); + addMakeTargetsToManager(makefileFile); + saveConfigArgs(configArgs); + } + } + // If nothing this far, try running autoreconf -i + else { + String[] reconfArgs = new String[1]; + String reconfCmd = project.getPersistentProperty(AutotoolsPropertyConstants.AUTORECONF_TOOL); + if (reconfCmd == null) + reconfCmd = "autoreconf"; // $NON-NLS-1$ + IPath reconfCmdPath = new Path(reconfCmd); + reconfArgs[0] = "-i"; //$NON-NLS-1$ + rc = runCommand(reconfCmdPath, + project.getLocation().append(srcDir), + reconfArgs, + AutotoolsPlugin.getResourceString("MakeGenerator.autoreconf"), //$NON-NLS-1$ + errMsg, console, true); + // Check if configure generated and if yes, run it. + if (rc != IStatus.ERROR) { + if (configurePath.toFile().exists()) { + + rc = runScript(configurePath, + project.getLocation().append(buildDir), + configArgs, + AutotoolsPlugin.getResourceString("MakeGenerator.gen.makefile"), //$NON-NLS-1$ + errMsg, console, configureEnvs, false); + if (rc != IStatus.ERROR) { + File makefileFile = project.getLocation().append(buildDir) + .append(MAKEFILE).toFile(); + addMakeTargetsToManager(makefileFile); + // TODO: should we do something special if configure doesn't + // return ok? + saveConfigArgs(configArgs); + } + } + } + } + + // Treat no Makefile as generation error. + if (makefile == null || !makefile.exists()) { + rc = IStatus.ERROR; + errMsg = AutotoolsPlugin.getResourceString("MakeGenerator.didnt.generate"); //$NON-NLS-1$ + } + } catch (Exception e) { + e.printStackTrace(); + // forgetLastBuiltState(); + rc = IStatus.ERROR; + } finally { + // getGenerationProblems().clear(); + status = new MultiStatus(AutotoolsPlugin + .getUniqueIdentifier(), rc, errMsg, null); + } + return status; + } + + /** + * Strip a command of VAR=VALUE pairs that appear ahead of the command and add + * them to a list of environment variables. + * + * @param command - command to strip + * @param envVars - ArrayList to add environment variables to + * @return stripped command + */ + public static String stripEnvVars(String command, ArrayList<String> envVars) { + Pattern p = Pattern.compile("(\\w+[=]([$]?\\w+[:;]?)+\\s+)\\w+.*"); + Pattern p2 = Pattern.compile("(\\w+[=]\\\".*?\\\"\\s+)\\w+.*"); + Pattern p3 = Pattern.compile("(\\w+[=]'.*?'\\s+)\\w+.*"); + boolean finished = false; + while (!finished) { + Matcher m = p.matcher(command); + if (m.matches()) { + command = command.replaceFirst("\\w+[=]([$]?\\w+[:;]?)+", "").trim(); + envVars.add(m.group(1).trim()); + } else { + Matcher m2 = p2.matcher(command); + if (m2.matches()) { + command = command.replaceFirst("\\w+[=]\\\".*?\\\"","").trim(); + String s = m2.group(1).trim(); + envVars.add(s.replaceAll("\\\"", "")); + } else { + Matcher m3 = p3.matcher(command); + if (m3.matches()) { + command = command.replaceFirst("\\w+[=]'.*?'", "").trim(); + String s = m3.group(1).trim(); + envVars.add(s.replaceAll("'", "")); + } else { + finished = true; + } + } + } + } + return command; + } + + protected IPath getConfigurePath(ArrayList<String> envVars) { + IPath configPath; + ITool[] tool = cfg.getToolsBySuperClassId(CONFIGURE_TOOL_ID); + String command = stripEnvVars(tool[0].getToolCommand().trim(), envVars); + + if (srcDir.equals("")) + configPath = project.getLocation().append(command); + else + configPath = project.getLocation().append(srcDir).append(command); + return configPath; + } + + protected IPath getMakefileCVSPath() { + IPath makefileCVSPath; + if (srcDir.equals("")) + makefileCVSPath = project.getLocation().append(MAKEFILE_CVS); + else + makefileCVSPath= project.getLocation().append(srcDir).append( + MAKEFILE_CVS); + return makefileCVSPath; + } + + protected boolean makefileCvsExists() { + IPath makefileCVSPath = getMakefileCVSPath(); + return makefileCVSPath.toFile().exists(); + } + + protected IPath getAutogenPath(ArrayList<String> envVars) { + IPath autogenPath; + ITool[] tool = cfg.getToolsBySuperClassId(AUTOGEN_TOOL_ID); + String command = stripEnvVars(tool[0].getToolCommand().trim(), envVars); + + if (srcDir.equals("")) + autogenPath = project.getLocation().append(command); + else + autogenPath = project.getLocation().append(srcDir).append(command); + return autogenPath; + } + + private void saveConfigArgs(String[] args) { + IPath settingsPath = getConfigSettingsPath(); + try { + File f = settingsPath.toFile(); + DataOutputStream settings = new DataOutputStream( + new BufferedOutputStream(new FileOutputStream(f))); + // Write the project name in the configure arguments + // so we know if the project gets refactored. + settings.writeUTF("project=" + project.getName()); //$NON-NLS-1$ + for (int i = 0; i < args.length; ++i) { + settings.writeUTF(args[i]); + } + settings.close(); + } catch (IOException e) { + /* What should we do? */ + } + } + + private String[] getAutogenArgs() throws BuildException { + // Get the arguments to be passed to config from build model + ITool[] tool = cfg.getToolsBySuperClassId(AUTOGEN_TOOL_ID); + IOption[] options = tool[0].getOptions(); + ArrayList<String> autogenArgs = new ArrayList<String>(); + + for (int i = 0; i < options.length; ++i) { + if (options[i].getValueType() == IOption.STRING) { + String value = (String) options[i].getValue(); + try { + String resolved = ManagedBuildManager.getBuildMacroProvider().resolveValue(value, "", null, + IBuildMacroProvider.CONTEXT_CONFIGURATION, cfg); + value = resolved; + } catch (BuildMacroException e) { + // do nothing + } + String id = options[i].getId(); + if (id.indexOf("user") > 0) { //$NON-NLS-1$ + // May be multiple user-specified options in which case we + // need to split them up into individual options + value = value.trim(); + boolean finished = false; + int lastIndex = value.indexOf("--"); //$NON-NLS-1$ + if (lastIndex != -1) { + while (!finished) { + int index = value.indexOf("--",lastIndex+2); //$NON-NLS-1$ + if (index != -1) { + String previous = value.substring(lastIndex, index).trim(); + autogenArgs.add(previous); + value = value.substring(index); + } else { + autogenArgs.add(value); + finished = true; + } + } + } + } + } + } + return (String[]) autogenArgs.toArray(new String[autogenArgs.size()]); + } + + private String[] getConfigArgs() throws BuildException { + // Get the arguments to be passed to config from build model + ITool tool = cfg.getToolFromOutputExtension("status"); //$NON-NLS-1$ + IOption[] options = tool.getOptions(); + ArrayList<String> configArgs = new ArrayList<String>(); + for (int i = 0; i < options.length; ++i) { + if (options[i].getValueType() == IOption.STRING) { + String value = (String) options[i].getValue(); + try { + String resolved = ManagedBuildManager.getBuildMacroProvider().resolveValue(value, "", null, + IBuildMacroProvider.CONTEXT_CONFIGURATION, cfg); + value = resolved; + } catch (BuildMacroException e) { + // do nothing + } + String id = options[i].getId(); + if (id.indexOf("configdir") > 0 || id.indexOf("builddir") > 0) //$NON-NLS-1$ $NON-NLS-2$ + continue; + else if (id.indexOf("user") > 0) { //$NON-NLS-1$ + // May be multiple user-specified options in which case we + // need to split them up into individual options + value = value.trim(); + boolean finished = false; + int lastIndex = value.indexOf("--"); //$NON-NLS-1$ + if (lastIndex != -1) { + while (!finished) { + int index = value.indexOf("--",lastIndex+2); //$NON-NLS-1$ + if (index != -1) { + String previous = value.substring(lastIndex, index).trim(); + configArgs.add(previous); + value = value.substring(index); + } else { + configArgs.add(value); + finished = true; + } + } + } else { + // No --xxx arguments, but there might still be some NAME=VALUE args + // and we should pass them on regardless + configArgs.add(value); + } + } + else if (value.trim().length() > 0) { + String categoryId = options[i].getCategory().getId(); + if (categoryId.indexOf("directories") >= 0) //$NON-NLS-1$ + value = getAbsoluteDirectory(value); + String cmd = options[i].getCommand().concat(value); + configArgs.add(cmd); + } + } else if (options[i].getValueType() == IOption.BOOLEAN) { + Boolean value = (Boolean) options[i].getValue(); + if (value.booleanValue()) + configArgs.add(options[i].getCommand()); + else if (!options[i].getCommandFalse().equals("")) + configArgs.add(options[i].getCommandFalse()); + } + } + return (String[]) configArgs.toArray(new String[configArgs.size()]); + } + + // Run a command or executable (e.g. make). + private int runCommand(IPath commandPath, IPath runPath, String[] args, + String jobDescription, String errMsg, IConsole console, + boolean consoleStart) throws BuildException, CoreException, + NullPointerException, IOException { + // TODO: Figure out what this next stuff is used for + // //try to resolve the build macros in the builder command + // try{ + // String resolved = + // ManagedBuildManager.getBuildMacroProvider().resolveValueToMakefileFormat( + // configCmd, + // "", //$NON-NLS-1$ + // " ", //$NON-NLS-1$ + // IBuildMacroProvider.CONTEXT_CONFIGURATION, + // info.getDefaultConfiguration()); + // if((resolved = resolved.trim()).length() > 0) + // configCmd = resolved; + // } catch (BuildMacroException e){ + // } + + int rc = IStatus.OK; + + removeAllMarkers(project); + + String[] configTargets = args; + if (args == null) + configTargets = new String[0]; + + String[] msgs = new String[2]; + msgs[0] = commandPath.toString(); + msgs[1] = project.getName(); + monitor.subTask(AutotoolsPlugin.getFormattedString( + "MakeGenerator.make.message", msgs)); //$NON-NLS-1$ + + + ConsoleOutputStream consoleOutStream = null; + StringBuffer buf = new StringBuffer(); + + // Launch command - main invocation + if (consoleStart) + console.start(project); + consoleOutStream = console.getOutputStream(); + String[] consoleHeader = new String[3]; + + consoleHeader[0] = jobDescription; + consoleHeader[1] = cfg.getName(); + consoleHeader[2] = project.getName(); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + buf.append(jobDescription); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + + if (!cfg.isSupported()) { + String msgArgs[] = new String[1]; + msgArgs[0] = cfg.getName(); + buf.append(AutotoolsPlugin.getFormattedString("MakeGenerator.unsupportedConfig", msgArgs)); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + } + consoleOutStream.write(buf.toString().getBytes()); + consoleOutStream.flush(); + + // Get a launcher for the config command + CommandLauncher launcher = new CommandLauncher(); + // Set the environment + IEnvironmentVariable variables[] = ManagedBuildManager + .getEnvironmentVariableProvider().getVariables(cfg, true); + String[] env = null; + ArrayList<String> envList = new ArrayList<String>(); + if (variables != null) { + for (int i = 0; i < variables.length; i++) { + envList.add(variables[i].getName() + + "=" + variables[i].getValue()); //$NON-NLS-1$ + } + env = (String[]) envList.toArray(new String[envList.size()]); + } + + // // Hook up an error parser manager + // String[] errorParsers = + // info.getDefaultConfiguration().getErrorParserList(); + // ErrorParserManager epm = new ErrorParserManager(project, topBuildDir, + // this, errorParsers); + // epm.setOutputStream(consoleOutStream); + OutputStream stdout = consoleOutStream; + OutputStream stderr = consoleOutStream; + + launcher.showCommand(true); + Process proc = launcher.execute(commandPath, configTargets, env, + runPath, new NullProgressMonitor()); + if (proc != null) { + try { + // Close the input of the process since we will never write to + // it + proc.getOutputStream().close(); + } catch (IOException e) { + } + + if (launcher.waitAndRead(stdout, stderr, new SubProgressMonitor( + monitor, IProgressMonitor.UNKNOWN)) != CommandLauncher.OK) { + errMsg = launcher.getErrorMessage(); + } + + // Force a resync of the projects without allowing the user to + // cancel. + // This is probably unkind, but short of this there is no way to + // ensure + // the UI is up-to-date with the build results + // monitor.subTask(ManagedMakeMessages + // .getResourceString(REFRESH)); + monitor.subTask(AutotoolsPlugin.getResourceString("MakeGenerator.refresh")); //$NON-NLS-1$ + try { + project.refreshLocal(IResource.DEPTH_INFINITE, null); + } catch (CoreException e) { + monitor.subTask(AutotoolsPlugin + .getResourceString("MakeGenerator.refresh.error")); //$NON-NLS-1$ + } + } else { + errMsg = launcher.getErrorMessage(); + } + + // Report either the success or failure of our mission + buf = new StringBuffer(); + if (errMsg != null && errMsg.length() > 0) { + String errorDesc = AutotoolsPlugin + .getResourceString("MakeGenerator.generation.error"); //$NON-NLS-1$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ + buf.append(errorDesc); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ + buf.append("(").append(errMsg).append(")"); //$NON-NLS-1$ //$NON-NLS-2$ + rc = IStatus.ERROR; + } else if (proc.exitValue() >= 1 || proc.exitValue() < 0) { + // We have an invalid return code from configuration. + String[] errArg = new String[2]; + errArg[0] = Integer.toString(proc.exitValue()); + errArg[1] = commandPath.toString(); + errMsg = AutotoolsPlugin.getFormattedString( + "MakeGenerator.config.error", errArg); //$NON-NLS-1$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ + buf.append(AutotoolsPlugin.getResourceString("MakeGenerator.generation.error")); //$NON-NLS-1$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ + if (proc.exitValue() == 1) + rc = IStatus.WARNING; + else + rc = IStatus.ERROR; + } else { + // Report a successful build + String successMsg = + AutotoolsPlugin.getResourceString("MakeGenerator.success"); //$NON-NLS-1$ + buf.append(successMsg); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ + rc = IStatus.OK; + } + + // Write message on the console + consoleOutStream.write(buf.toString().getBytes()); + consoleOutStream.flush(); + + // // Generate any error markers that the build has discovered + // monitor.subTask(ManagedMakeMessages + // .getResourceString(MARKERS)); + // epm.reportProblems(); + consoleOutStream.close(); + + // TODO: For now, add a marker with our generated error message. + // In the future, we might add an error parser to do this properly + // and give the actual error line, etc.. + if (rc == IStatus.ERROR) { + addMarker(project, -1, errMsg, SEVERITY_ERROR_BUILD, null); + // Mark the configuration as needing a full rebuild. + cfg.setRebuildState(true); + } + + return rc; + } + + // Get the path string. We add a Win check to handle MingW. + // For MingW, we would rather represent C:\a\b as /C/a/b which + // doesn't cause Makefile to choke. + // TODO: further logic would be needed to handle cygwin if desired + private String getPathString(IPath path) { + String s = path.toString(); + if (Platform.getOS().equals(Platform.OS_WIN32)) + s = s.replaceAll("^([A-Z])(:)", "/$1"); + return s; + } + + // Run an autotools script (e.g. configure, autogen.sh, config.status). + private int runScript(IPath commandPath, IPath runPath, String[] args, + String jobDescription, String errMsg, IConsole console, + ArrayList<String> additionalEnvs, + boolean consoleStart) throws BuildException, CoreException, + NullPointerException, IOException { + // TODO: Figure out what this next stuff is used for + // //try to resolve the build macros in the builder command + // try{ + // String resolved = + // ManagedBuildManager.getBuildMacroProvider().resolveValueToMakefileFormat( + // configCmd, + // "", //$NON-NLS-1$ + // " ", //$NON-NLS-1$ + // IBuildMacroProvider.CONTEXT_CONFIGURATION, + // info.getDefaultConfiguration()); + // if((resolved = resolved.trim()).length() > 0) + // configCmd = resolved; + // } catch (BuildMacroException e){ + // } + + int rc = IStatus.OK; + + removeAllMarkers(project); + + // We want to run the script via the shell command. So, we add the command + // script as the first argument and expect "sh" to be on the runtime path. + // Any other arguments are placed after the script name. + String[] configTargets = null; + if (args == null) + configTargets = new String[1]; + else { + configTargets = new String[args.length+1]; + System.arraycopy(args, 0, configTargets, 1, args.length); + } + configTargets[0] = getPathString(commandPath); + + String[] msgs = new String[2]; + msgs[0] = commandPath.toString(); + msgs[1] = project.getName(); + monitor.subTask(AutotoolsPlugin.getFormattedString( + "MakeGenerator.make.message", msgs)); //$NON-NLS-1$ + + + ConsoleOutputStream consoleOutStream = null; + StringBuffer buf = new StringBuffer(); + + // Launch command - main invocation + if (consoleStart) + console.start(project); + consoleOutStream = console.getOutputStream(); + String[] consoleHeader = new String[3]; + + consoleHeader[0] = jobDescription; + consoleHeader[1] = cfg.getName(); + consoleHeader[2] = project.getName(); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + buf.append(jobDescription); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + + if (!cfg.isSupported()) { + String msgArgs[] = new String[1]; + msgArgs[0] = cfg.getName(); + buf.append(AutotoolsPlugin.getFormattedString("MakeGenerator.unsupportedConfig", msgArgs)); // $NON-NLS-1$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + } + consoleOutStream.write(buf.toString().getBytes()); + consoleOutStream.flush(); + + // Get a launcher for the config command + CommandLauncher launcher = new CommandLauncher(); + // Set the environment + IEnvironmentVariable variables[] = ManagedBuildManager + .getEnvironmentVariableProvider().getVariables(cfg, true); + String[] env = null; + ArrayList<String> envList = new ArrayList<String>(); + if (variables != null) { + for (int i = 0; i < variables.length; i++) { + envList.add(variables[i].getName() + + "=" + variables[i].getValue()); //$NON-NLS-1$ + } + if (additionalEnvs != null) + envList.addAll(additionalEnvs); // add any additional environment variables specified ahead of script + env = (String[]) envList.toArray(new String[envList.size()]); + } + + // // Hook up an error parser manager + // String[] errorParsers = + // info.getDefaultConfiguration().getErrorParserList(); + // ErrorParserManager epm = new ErrorParserManager(project, topBuildDir, + // this, errorParsers); + // epm.setOutputStream(consoleOutStream); + OutputStream stdout = consoleOutStream; + OutputStream stderr = consoleOutStream; + + launcher.showCommand(true); + // Run the shell script via shell command. + Process proc = launcher.execute(new Path(SHELL_COMMAND), configTargets, env, + runPath, new NullProgressMonitor()); + if (proc != null) { + try { + // Close the input of the process since we will never write to + // it + proc.getOutputStream().close(); + } catch (IOException e) { + } + + if (launcher.waitAndRead(stdout, stderr, new SubProgressMonitor( + monitor, IProgressMonitor.UNKNOWN)) != CommandLauncher.OK) { + errMsg = launcher.getErrorMessage(); + } + + // Force a resync of the projects without allowing the user to + // cancel. + // This is probably unkind, but short of this there is no way to + // ensure + // the UI is up-to-date with the build results + // monitor.subTask(ManagedMakeMessages + // .getResourceString(REFRESH)); + monitor.subTask(AutotoolsPlugin.getResourceString("MakeGenerator.refresh")); //$NON-NLS-1$ + try { + project.refreshLocal(IResource.DEPTH_INFINITE, null); + } catch (CoreException e) { + monitor.subTask(AutotoolsPlugin + .getResourceString("MakeGenerator.refresh.error")); //$NON-NLS-1$ + } + } else { + errMsg = launcher.getErrorMessage(); + } + + // Report either the success or failure of our mission + buf = new StringBuffer(); + if (errMsg != null && errMsg.length() > 0) { + String errorDesc = AutotoolsPlugin + .getResourceString("MakeGenerator.generation.error"); //$NON-NLS-1$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ + buf.append(errorDesc); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ + buf.append("(").append(errMsg).append(")"); //$NON-NLS-1$ //$NON-NLS-2$ + rc = IStatus.ERROR; + } else if (proc.exitValue() >= 1 || proc.exitValue() < 0) { + // We have an invalid return code from configuration. + String[] errArg = new String[2]; + errArg[0] = Integer.toString(proc.exitValue()); + errArg[1] = commandPath.toString(); + errMsg = AutotoolsPlugin.getFormattedString( + "MakeGenerator.config.error", errArg); //$NON-NLS-1$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ + buf.append(AutotoolsPlugin.getResourceString("MakeGenerator.generation.error")); //$NON-NLS-1$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ + if (proc.exitValue() == 1) + rc = IStatus.WARNING; + else + rc = IStatus.ERROR; + } else { + // Report a successful build + String successMsg = + AutotoolsPlugin.getResourceString("MakeGenerator.success"); //$NON-NLS-1$ + buf.append(successMsg); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ + rc = IStatus.OK; + } + + // Write message on the console + consoleOutStream.write(buf.toString().getBytes()); + consoleOutStream.flush(); + + // // Generate any error markers that the build has discovered + // monitor.subTask(ManagedMakeMessages + // .getResourceString(MARKERS)); + // epm.reportProblems(); + consoleOutStream.close(); + + // TODO: For now, add a marker with our generated error message. + // In the future, we might add an error parser to do this properly + // and give the actual error line, etc.. + if (rc == IStatus.ERROR) { + addMarker(project, -1, errMsg, SEVERITY_ERROR_BUILD, null); + // Mark the configuration as needing a full rebuild. + cfg.setRebuildState(true); + } + + return rc; + } + + private ICStorageElement createTargetElement(ICStorageElement parent, IMakeTarget target) { + ICStorageElement targetElem = parent.createChild(TARGET_ELEMENT); + targetElem.setAttribute(TARGET_ATTR_NAME, target.getName()); + targetElem.setAttribute(TARGET_ATTR_ID, target.getTargetBuilderID()); + targetElem.setAttribute(TARGET_ATTR_PATH, target.getContainer().getProjectRelativePath().toString()); + ICStorageElement elem = targetElem.createChild(TARGET_COMMAND); + elem.setValue(target.getBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND, "make")); //$NON-NLS-1$ + + String targetAttr = target.getBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS, null); + if ( targetAttr != null) { + elem = targetElem.createChild(TARGET_ARGUMENTS); + elem.setValue(targetAttr); + } + + targetAttr = target.getBuildAttribute(IMakeTarget.BUILD_TARGET, null); + if (targetAttr != null) { + elem = targetElem.createChild(TARGET); + elem.setValue(targetAttr); + } + + elem = targetElem.createChild(TARGET_STOP_ON_ERROR); + elem.setValue(new Boolean(target.isStopOnError()).toString()); + + elem = targetElem.createChild(TARGET_USE_DEFAULT_CMD); + elem.setValue(new Boolean(target.isDefaultBuildCmd()).toString()); + + elem = targetElem.createChild(TARGET_RUN_ALL_BUILDERS); + elem.setValue(new Boolean(target.runAllBuilders()).toString()); + + return targetElem; + } + + /** + * This output method saves the information into the .cdtproject metadata file. + * + * @param doc + * @throws CoreException + */ + private void saveTargets(IMakeTarget[] makeTargets) throws CoreException { + ICDescriptor descriptor = CCorePlugin.getDefault().getCProjectDescription(getProject(), true); + ICStorageElement rootElement = descriptor.getProjectStorageElement(MAKE_TARGET_KEY); + + //Nuke the children since we are going to write out new ones + rootElement.clear(); + + // Fetch the ProjectTargets as ICStorageElements + rootElement = rootElement.createChild(BUILD_TARGET_ELEMENT); + for (int i = 0; i < makeTargets.length; ++i) + createTargetElement(rootElement, makeTargets[i]); + + //Save the results + descriptor.saveProjectData(); + } + + + protected class MakeTargetComparator implements Comparator<Object> { + public int compare(Object a, Object b) { + IMakeTarget make1 = (IMakeTarget)a; + IMakeTarget make2 = (IMakeTarget)b; + return make1.getName().compareToIgnoreCase(make2.getName()); + } + + } + + /** + * This method parses the given Makefile and produces MakeTargets for all targets so the + * end-user can access them from the MakeTargets popup-menu. + * + * @param makefileFile the Makefile to parse + * @throws CoreException + */ + private void addMakeTargetsToManager(File makefileFile) throws CoreException { + // Return immediately if no Makefile. + if (makefileFile == null || !makefileFile.exists()) + return; + + checkCancel(); + if (monitor == null) + monitor = new NullProgressMonitor(); + String statusMsg = AutotoolsPlugin.getResourceString("MakeGenerator.refresh.MakeTargets"); //$NON-NLS-1$ + monitor.subTask(statusMsg); + + IMakeTargetManager makeTargetManager = + MakeCorePlugin.getDefault().getTargetManager(); + + IMakefile makefile = MakeCorePlugin.createMakefile(makefileFile.toURI(), false, null); + ITargetRule[] targets = makefile.getTargetRules(); + ITarget target = null; + Map<String, IMakeTarget> makeTargets = new HashMap<String, IMakeTarget>(); // use a HashMap so duplicate names are handled + for (int i = 0; i < targets.length; i++) { + target = targets[i].getTarget(); + String targetName = target.toString(); + if (!isValidTarget(targetName, makeTargetManager)) + continue; + try { + IMakeTarget makeTarget = makeTargetManager.createTarget( + project, targetName, "org.eclipse.linuxtools.cdt.autotools.builder1"); //$NON-NLS-1$ + makeTarget.setContainer(project); + makeTarget.setStopOnError(true); + makeTarget.setRunAllBuilders(false); + makeTarget.setUseDefaultBuildCmd(true); + + makeTarget.setBuildAttribute(GENERATED_TARGET, "true"); + makeTarget.setBuildAttribute(IMakeTarget.BUILD_TARGET, + targetName); + + makeTarget.setBuildAttribute(IMakeTarget.BUILD_LOCATION, + buildDir); + makeTargets.put(makeTarget.getName(), makeTarget); + } catch (CoreException e) { + // Duplicate target. Ignore. + } + } + + IMakeTarget[] makeTargetArray = new IMakeTarget[makeTargets.size()]; + Collection<IMakeTarget> values = makeTargets.values(); + ArrayList<IMakeTarget> valueList = new ArrayList<IMakeTarget>(values); + valueList.toArray(makeTargetArray); + MakeTargetComparator compareMakeTargets = new MakeTargetComparator(); + Arrays.sort(makeTargetArray, compareMakeTargets); + + saveTargets(makeTargetArray); + } + + private boolean isValidTarget(String targetName, IMakeTargetManager makeTargetManager) { + return !(targetName.endsWith("-am") //$NON-NLS-1$ + || targetName.endsWith("PROGRAMS") //$NON-NLS-1$ + || targetName.endsWith("-generic") //$NON-NLS-1$ + || (targetName.indexOf('$') >= 0) + || (targetName.charAt(0) == '.') + || targetName.equals(targetName.toUpperCase())); + } + + // Turn the string into an array. + private String[] makeArray(String string) { + string = string.trim(); + char[] array = string.toCharArray(); + ArrayList<String> aList = new ArrayList<String>(); + StringBuilder buffer = new StringBuilder(); + boolean inComment = false; + for (int i = 0; i < array.length; i++) { + char c = array[i]; + boolean needsToAdd = true; + if (array[i] == '"' || array[i] == '\'') { + if (i > 0 && array[i - 1] == '\\') { + inComment = false; + } else { + inComment = !inComment; + needsToAdd = false; // skip it + } + } + if (c == ' ' && !inComment) { + if (buffer.length() > 0){ + String str = buffer.toString().trim(); + if(str.length() > 0){ + aList.add(str); + } + } + buffer = new StringBuilder(); + } else { + if (needsToAdd) + buffer.append(c); + } + } + if (buffer.length() > 0){ + String str = buffer.toString().trim(); + if(str.length() > 0){ + aList.add(str); + } + } + return (String[])aList.toArray(new String[aList.size()]); + } + +}
\ No newline at end of file diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/Resources.properties b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/Resources.properties new file mode 100644 index 0000000000..7b4c9179b2 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/Resources.properties @@ -0,0 +1,95 @@ +################################################################################# +# Copyright (c) 2006, 2007 Red Hat, Inc. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Red Hat Incorporated - initial API and implementation +# IBM Rational Software - ManagedMakeMessages copied to AutotoolsMakefileBuilder +################################################################################# +MakeCWizard.title=C/Make Project +MakeCWizard.description=Create a New C Project using 'make' to build it + +WARNING_UNSUPPORTED_CONFIGURATION=Warning: unsupported configuration + +AutotoolsMakefileBuilder.message.finished=Build complete for project {0} +AutotoolsMakefileBuilder.type.clean=Clean-only build +AutotoolsMakefileBuilder.message.clean.deleting.output=Removing build artifacts from {0} +AutotoolsMakefileBuilder.message.console.header=**** {0} of configuration {1} for project {2} **** + +MakeGenerator.makefile.built=Makefile built +MakeGenerator.refresh=Refresh +MakeGenerator.refresh.error=Refresh error +MakeGenerator.generation.error=Configuration failed with error +MakeGenerator.configuring=Configuring +MakeGenerator.createdir.error=Error creating build directory: {0} +MakeGenerator.make.message=Invoking {0} for project {1} +MakeGenerator.config.error=Error {0} occurred while running {1} +MakeGenerator.run.config.status=Running config.status +MakeGenerator.makefile.cvs=Invoking Makefile.cvs +MakeGenerator.autogen.sh=Invoking autogen.sh +MakeGenerator.autoreconf=Invoking autoreconf +MakeGenerator.gen.makefile=Generating Makefile +MakeGenerator.gen.configure=Generating configure +MakeGenerator.unsupportedConfig=Warning: unsupported configuration {0} +MakeGenerator.success=[Operation successful] +MakeGenerator.didnt.generate=No Makefile generated +MakeGenerator.refresh.MakeTargets=Refreshing Make Targets +MakeGenerator.clean.builddir=Cleaning build directory before reconfiguring + + +BuildDir.apply=Build directory already in use +BuildDir.default=Default build directory to unused value? +BuildDir.yes=Yes +BuildDir.no=No + +WizardAutotoolsProjectConversion.title=Convert to a CVS C/C++ Autotools Project +WizardAutotoolsProjectConversion.description=Convert a CVS source repository to C/C++ Autotools Project +WizardAutotoolsProjectConversion.message.add_nature=Adding C/C++ Autotools Managed Project Nature +WizardAutotoolsProjectConversion.message.add_builder=Adding C/C++ Autotools Managed Project Builder +WizardMakeProjectConversion.monitor.convertingToMakeProject=Converting Project... +WizardAutotoolsConversion=CVS C/C++ Autotools Conversion +WizardAutotoolsConversion.windowTitle=Conversion to CVS C/C++ Autotools Project +WizardAutotoolsConversion.config.title=Select a configuration +WizardAutotoolsConversion.config.desc=Select the configuration you wish to deploy on +WizardAutotoolsConversion.options.title=Additional Project Settings +WizardAutotoolsConversion.options.desc=Define the inter-project dependencies, if any. +WizardAutotoolsConversion.message.save=Saving new build options + +WizardAutotoolsNewCProject.title=Autotools C Project +WizardAutotoolsNewCProject.description=Create a new C Autotools project +WizardAutotoolsNewCProject.monitor.creatingProject=Creating Project... +WizardAutotoolsNewCProject.windowTitle=GNU Autotools C Project +WizardAutotoolsNewCProject.config.title=Select a configuration +WizardAutotoolsNewCProject.config.desc=Select the configuration you wish to deploy on +WizardAutotoolsNewCProject.options.title=Additional Project Settings +WizardAutotoolsNewCProject.options.desc=Define the inter-project dependencies, if any. +WizardAutotoolsNewCProject.message.save=Saving new build options + +WizardAutotoolsNewCCProject.title=Autotools C++ Project +WizardAutotoolsNewCCProject.description=Create a new C++ Autotools project +WizardAutotoolsNewCCProject.monitor.creatingProject=Creating Project... +WizardAutotoolsNewCCProject.windowTitle=GNU Autotools C++ Project +WizardAutotoolsNewCCProject.config.title=Select a configuration +WizardAutotoolsNewCCProject.config.desc=Select the configuration you wish to deploy on +WizardAutotoolsNewCCProject.options.title=Additional Project Settings +WizardAutotoolsNewCCProject.options.desc=Define the inter-project dependencies, if any. +WizardAutotoolsNewCCProject.message.save=Saving new build options + + +BuildTargetDialog.title.buildTarget=Build Special Targets +BuildTargetDialog.title.makeTargetsFor=Make targets for +BuildTargetDialog.button.build=Build + +TargetListViewer.button.add=Add... +TargetListViewer.button.remove=Remove +TargetListViewer.button.edit=Edit... +TargetListViewer.label.target=Target +TargetListViewer.label.location=Location +TargetListViewer.exception.error=Error +TargetListViewer.exception.message=An error occurred performing the selected action + +AutotoolsPreferencePage.useAutotoolsFileScanner.label=Use make -w for includepath scanning +MakeTargetPreferencePage.buildTargetInBackground.label=Build target in background diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AbstractAutotoolsHandler.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AbstractAutotoolsHandler.java new file mode 100644 index 0000000000..be54ee8fb5 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AbstractAutotoolsHandler.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import java.util.Collection; + +import org.eclipse.cdt.core.model.ICContainer; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.expressions.IEvaluationContext; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IResource; + +public abstract class AbstractAutotoolsHandler extends AbstractHandler { + + @SuppressWarnings("unchecked") + protected IContainer getContainer(IEvaluationContext e) { + IContainer fContainer = null; + + Object obj = e.getDefaultVariable(); + if (obj instanceof Collection) { + Collection<Object> c = (Collection<Object>)obj; + Object[] objArray = c.toArray(); + if (objArray.length > 0) + obj = objArray[0]; + } + if (obj instanceof ICElement) { + if ( obj instanceof ICContainer || obj instanceof ICProject) { + fContainer = (IContainer) ((ICElement) obj).getUnderlyingResource(); + } else { + obj = ((ICElement)obj).getResource(); + if ( obj != null) { + fContainer = ((IResource)obj).getParent(); + } + } + } else if (obj instanceof IResource) { + if (obj instanceof IContainer) { + fContainer = (IContainer) obj; + } else { + fContainer = ((IResource)obj).getParent(); + } + } else { + fContainer = null; + } + return fContainer; + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AbstractTargetAction.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AbstractTargetAction.java new file mode 100644 index 0000000000..367d63a7be --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AbstractTargetAction.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.cdt.core.model.ICContainer; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.linuxtools.cdt.autotools.AutotoolsMakefileBuilder; +import org.eclipse.linuxtools.cdt.autotools.AutotoolsPlugin; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.actions.ActionDelegate; + + +public abstract class AbstractTargetAction + extends ActionDelegate + implements IObjectActionDelegate, IWorkbenchWindowActionDelegate { + private IWorkbenchPart fPart; + private IWorkbenchWindow fWindow; + private IContainer fContainer; + + protected Shell getShell() { + if (fPart != null) { + return fPart.getSite().getShell(); + } else if (fWindow != null) { + return fWindow.getShell(); + } + return AutotoolsPlugin.getActiveWorkbenchShell(); + } + + protected IContainer getSelectedContainer() { + return fContainer; + } + + public void setSelectedContainer(IContainer container) { + fContainer = container; + } + + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + fPart = targetPart; + } + + public void init(IWorkbenchWindow window) { + fWindow = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + boolean enabled = false; + if (selection instanceof IStructuredSelection) { + IStructuredSelection sel = (IStructuredSelection) selection; + Object obj = sel.getFirstElement(); + if (obj instanceof ICElement) { + if ( obj instanceof ICContainer || obj instanceof ICProject) { + fContainer = (IContainer) ((ICElement) obj).getUnderlyingResource(); + } else { + obj = ((ICElement)obj).getResource(); + if ( obj != null) { + fContainer = ((IResource)obj).getParent(); + } + } + } else if (obj instanceof IResource) { + if (obj instanceof IContainer) { + fContainer = (IContainer) obj; + } else { + fContainer = ((IResource)obj).getParent(); + } + } else { + fContainer = null; + } + if (fContainer != null && AutotoolsMakefileBuilder.hasTargetBuilder(fContainer.getProject())) { + enabled = true; + } + } + action.setEnabled(enabled); + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AclocalHandler.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AclocalHandler.java new file mode 100644 index 0000000000..b534cfe06a --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AclocalHandler.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2008 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.expressions.IEvaluationContext; +import org.eclipse.core.resources.IContainer; + +/** + * @author Jeff Johnston + * + */ +public class AclocalHandler extends AbstractAutotoolsHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + InvokeAclocalAction a = new InvokeAclocalAction(); + Object o = event.getApplicationContext(); + if (o instanceof IEvaluationContext) { + IContainer container = getContainer((IEvaluationContext)o); + if (container != null) { + a.setSelectedContainer(container); + a.run(null); + } + } + return null; + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AutoconfHandler.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AutoconfHandler.java new file mode 100644 index 0000000000..9dc28e2935 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AutoconfHandler.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.expressions.IEvaluationContext; +import org.eclipse.core.resources.IContainer; + +public class AutoconfHandler extends AbstractAutotoolsHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + InvokeAutoconfAction a = new InvokeAutoconfAction(); + Object o = event.getApplicationContext(); + if (o instanceof IEvaluationContext) { + IContainer container = getContainer((IEvaluationContext)o); + if (container != null) { + a.setSelectedContainer(container); + a.run(null); + } + } + return null; + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AutoheaderHandler.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AutoheaderHandler.java new file mode 100644 index 0000000000..e64ad41799 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AutoheaderHandler.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.expressions.IEvaluationContext; +import org.eclipse.core.resources.IContainer; + +/** + * @author Jeff Johnston + * + */ +public class AutoheaderHandler extends AbstractAutotoolsHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + InvokeAutoheaderAction a = new InvokeAutoheaderAction(); + Object o = event.getApplicationContext(); + if (o instanceof IEvaluationContext) { + IContainer container = getContainer((IEvaluationContext)o); + if (container != null) { + a.setSelectedContainer(container); + a.run(null); + } + } + return null; + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AutomakeHandler.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AutomakeHandler.java new file mode 100644 index 0000000000..c1bbcf4f47 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AutomakeHandler.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.expressions.IEvaluationContext; +import org.eclipse.core.resources.IContainer; + +public class AutomakeHandler extends AbstractAutotoolsHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + InvokeAutomakeAction a = new InvokeAutomakeAction(); + Object o = event.getApplicationContext(); + if (o instanceof IEvaluationContext) { + IContainer container = getContainer((IEvaluationContext)o); + if (container != null) { + a.setSelectedContainer(container); + a.run(null); + } + } + return null; + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AutoreconfHandler.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AutoreconfHandler.java new file mode 100644 index 0000000000..d9b0c8c72f --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/AutoreconfHandler.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.expressions.IEvaluationContext; +import org.eclipse.core.resources.IContainer; + +/** + * @author Jeff Johnston + * + */ +public class AutoreconfHandler extends AbstractAutotoolsHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + InvokeAutoreconfAction a = new InvokeAutoreconfAction(); + Object o = event.getApplicationContext(); + if (o instanceof IEvaluationContext) { + IContainer container = getContainer((IEvaluationContext)o); + if (container != null) { + a.setSelectedContainer(container); + a.run(null); + } + } + return null; + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAclocalAction.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAclocalAction.java new file mode 100644 index 0000000000..0834ef434b --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAclocalAction.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jface.action.IAction; +import org.eclipse.linuxtools.cdt.autotools.ui.properties.AutotoolsPropertyConstants; +import org.eclipse.swt.widgets.Shell; + + +public class InvokeAclocalAction extends InvokeAction { + + private static final String DEFAULT_OPTION = ""; //$NON-NLS-1$ + private static final String DEFAULT_COMMAND = "aclocal"; //$NON-NLS-1$ + + public void run(IAction action) { + + IContainer container = getSelectedContainer(); + if (container == null) + return; + + IPath execDir = getExecDir(container); + String cwd = InvokeMessages.getString("CWD") + getCWD(container); //$NON-NLS-1$ + + TwoInputDialog optionDialog = new TwoInputDialog( + new Shell(), + cwd, + InvokeMessages + .getString("InvokeAclocalAction.windowTitle.options"), //$NON-NLS-1$ + InvokeMessages + .getString("InvokeAclocalAction.message.options.otherOptions"), //$NON-NLS-1$ + InvokeMessages + .getString("InvokeAclocalAction.message.options.includeDir"), DEFAULT_OPTION, null); //$NON-NLS-1$ + + optionDialog.open(); + + // chop args into string array + String rawArgList = optionDialog.getValue(); + + String[] optionsList = separateOptions(rawArgList); + + // chop args into string array + rawArgList = optionDialog.getSecondValue(); + + String[] targetList = separateTargets(rawArgList); + + if (targetList == null) { + + showError(InvokeMessages + .getString("InvokeAction.execute.windowTitle.error"), //$NON-NLS-1$ + InvokeMessages + .getString("InvokeAction.windowTitle.quoteError")); //$NON-NLS-1$ + return; + } + + int iOption = 0; + if (targetList.length > 0) + iOption = 1; + + String[] argumentList = new String[targetList.length + + optionsList.length + iOption]; + + System.arraycopy(optionsList, 0, argumentList, 0, optionsList.length); + + if (iOption == 1) + argumentList[optionsList.length] = "-I"; //$NON-NLS-1$ + + System.arraycopy(targetList, 0, argumentList, optionsList.length + + iOption, targetList.length); + + if (container != null) { + String aclocalCommand = null; + IProject project = getSelectedContainer().getProject(); + try { + aclocalCommand = project.getPersistentProperty(AutotoolsPropertyConstants.ACLOCAL_TOOL); + } catch (CoreException e) { + // do nothing + } + + // If unset, use default system path + if (aclocalCommand == null) + aclocalCommand = DEFAULT_COMMAND; + + executeConsoleCommand(DEFAULT_COMMAND, aclocalCommand, + argumentList, execDir); + } + } + + public void dispose() { + + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAction.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAction.java new file mode 100644 index 0000000000..01979735f6 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAction.java @@ -0,0 +1,442 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007, 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.StringTokenizer; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.CommandLauncher; +import org.eclipse.cdt.core.ConsoleOutputStream; +import org.eclipse.cdt.core.envvar.IEnvironmentVariable; +import org.eclipse.cdt.core.resources.IConsole; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRunnable; +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.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.linuxtools.cdt.autotools.AutotoolsPlugin; +import org.eclipse.linuxtools.cdt.autotools.MakeGenerator; +import org.eclipse.swt.widgets.Shell; + +public abstract class InvokeAction extends AbstractTargetAction { + + protected void showInformation(String title, String content) { + + MessageDialog.openInformation(new Shell(), title, content); + } + + protected void showError(String title, String content) { + + MessageDialog.openError(new Shell(), title, content); + } + + protected void showSuccess(String title) { + MessageDialog.openInformation(new Shell(), title, + InvokeMessages.getString("InvokeAction.success")); //$NON-NLS-1$ + } + + protected String showInput(String title, String content, String defaultTxt) { + InputDialog getOptionDialog = new InputDialog(new Shell(), title, + content, defaultTxt, null); + + getOptionDialog.open(); + + return getOptionDialog.getValue(); + } + + /** + * Separate targets to array from a string. + * + * @param rawArgList + * @return targets in string[] array. if targets are not formatted properly, + * returns null + */ + protected String[] separateTargets(String rawArgList) { + + StringTokenizer st = new StringTokenizer(rawArgList, " "); //$NON-NLS-1$ + ArrayList<String> targetList = new ArrayList<String>(); + + while (st.hasMoreTokens()) { + String currentWord = st.nextToken().trim(); + + if (currentWord.startsWith("'")) { //$NON-NLS-1$ + String tmpTarget = ""; //$NON-NLS-1$ + while (!currentWord.endsWith("'")) { //$NON-NLS-1$ + tmpTarget += currentWord + " "; //$NON-NLS-1$ + if (!st.hasMoreTokens()) { + // quote not closed properly, so return null + return null; + } + currentWord = st.nextToken().trim(); + } + + tmpTarget += currentWord; + targetList.add(tmpTarget); + continue; + } + + if (currentWord.startsWith("\"")) { //$NON-NLS-1$ + String tmpTarget = ""; //$NON-NLS-1$ + while (!currentWord.endsWith("\"")) { //$NON-NLS-1$ + tmpTarget += currentWord + " "; //$NON-NLS-1$ + if (!st.hasMoreTokens()) { + // double quote not closed properly, so return null + return null; + } + currentWord = st.nextToken().trim(); + } + + tmpTarget += currentWord; + targetList.add(tmpTarget); + continue; + } + + // for targets without quote/double quotes. + targetList.add(currentWord); + + } + + return (String[])targetList.toArray(new String[targetList.size()]); + } + + protected String[] separateOptions(String rawArgList) { + ArrayList<String> argList = new ArrayList<String>(); + // May be multiple user-specified options in which case we + // need to split them up into individual options + rawArgList = rawArgList.trim(); + boolean finished = false; + int lastIndex = rawArgList.indexOf("--"); //$NON-NLS-1$ + if (lastIndex != -1) { + while (!finished) { + int index = rawArgList.indexOf("--", lastIndex + 2); //$NON-NLS-1$ + if (index != -1) { + String previous = rawArgList.substring(lastIndex, index) + .trim(); + argList.add(previous); + rawArgList = rawArgList.substring(index); + } else { + argList.add(rawArgList); + finished = true; + } + } + } + + return (String[])argList.toArray(new String[argList.size()]); + + } + + protected String[] simpleParseOptions(String rawArgList) { + ArrayList<String> argList = new ArrayList<String>(); + int lastArgIndex = -1; + int i = 0; + while (i < rawArgList.length()) { + char ch = rawArgList.charAt(i); + // Skip white-space + while (Character.isWhitespace(ch)) { + ++i; + if (i < rawArgList.length()) + ch = rawArgList.charAt(i); + else // Otherwise we are done + return argList.toArray(new String[argList.size()]); + } + + // Simplistic parser. We break up into strings delimited + // by blanks. If quotes are used, we ignore blanks within. + // If a backslash is used, we ignore the next character and + // pass it through. + lastArgIndex = i; + boolean inString = false; + while (i < rawArgList.length()) { + ch = rawArgList.charAt(i); + if (ch == '\\') // escape character + ++i; // skip over the next character + else if (ch == '\"') { // double quotes + inString = !inString; + } else if (Character.isWhitespace(ch)) { + if (!inString) { + argList.add(rawArgList.substring(lastArgIndex, i)); + break; + } + } + ++i; + } + // Look for the case where we ran out of chars for the last + // token. + if (i >= rawArgList.length()) + argList.add(rawArgList.substring(lastArgIndex)); + ++i; + } + return argList.toArray(new String[argList.size()]); + } + + protected IPath getExecDir(IContainer container) { + int type = container.getType(); + IPath execDir = null; + if (type == IContainer.FILE) { + execDir = container.getLocation().removeLastSegments(1); + } else { + execDir = container.getLocation(); + } + return execDir; + } + + protected IPath getCWD(IContainer container) { + int type = container.getType(); + IPath cwd = null; + if (type == IContainer.FILE) { + cwd = container.getFullPath().removeLastSegments(1); + } else { + cwd = container.getFullPath(); + } + return cwd; + } + + private class ExecuteProgressDialog implements IRunnableWithProgress { + private IPath command; + private String[] argumentList; + private String[] envList; + private IPath execDir; + private int status; + private HashMap<String, String> outputs = null; + + public ExecuteProgressDialog(IPath command, String[] argumentList, + String[] envList, IPath execDir) { + this.command = command; + this.argumentList = argumentList; + this.envList = envList; + this.execDir = execDir; + } + + public void run(IProgressMonitor monitor) + throws InvocationTargetException, InterruptedException { + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + ByteArrayOutputStream stderr = new ByteArrayOutputStream(); + CommandLauncher cmdL = new CommandLauncher(); + outputs = null; + + // invoke command + try { + monitor.beginTask( + InvokeMessages.getFormattedString("InvokeAction.progress.message", // $NON-NLS-1$ + new String[]{command.toOSString()}), IProgressMonitor.UNKNOWN); + monitor.worked(1); + Process process = cmdL.execute(command, argumentList, envList, + execDir, new NullProgressMonitor()); + + if (cmdL.waitAndRead(stdout, stderr) == CommandLauncher.OK) { + try { + status = 0; + monitor.done(); + process.getOutputStream().close(); + } catch (IOException e) { + // ignore + } + } else { + // failed to execute command + status = -1; + monitor.done(); + return; + } + } catch (CoreException e) { + monitor.done(); + throw new InvocationTargetException(e); + } + + outputs = new HashMap<String, String>(); + + outputs.put("stdout", stdout.toString()); //$NON-NLS-1$ + outputs.put("stderr", stderr.toString()); //$NON-NLS-1$ + + try { + stdout.close(); + stderr.close(); + } catch (IOException e) { + // ignore + } + } + + public HashMap<String, String> getOutputs() { + return outputs; + } + + public int getStatus() { + return status; + } + } + + + protected HashMap<String, String> executeCommand(IPath command, + String[] argumentList, String[] envList, IPath execDir) { + try { + ExecuteProgressDialog d = new ExecuteProgressDialog(command, + argumentList, envList, execDir); + new ProgressMonitorDialog(new Shell()).run(false, false, d); + if (d.getStatus() == -1) + showError(InvokeMessages + .getString("InvokeAction.execute.windowTitle.error"), InvokeMessages //$NON-NLS-1$ + .getString("InvokeAction.execute.message") //$NON-NLS-1$ + + command.toOSString()); //$NON-NLS-1$ + return d.getOutputs(); + } catch (InvocationTargetException e) { + showError(InvokeMessages + .getString("InvokeAction.execute.windowTitle.error"), InvokeMessages //$NON-NLS-1$ + .getString("InvokeAction.execute.message") //$NON-NLS-1$ + + command.toOSString()); //$NON-NLS-1$ + AutotoolsPlugin.logException(e); + return null; + } catch (InterruptedException e) { + return null; + } + } + + protected void executeConsoleCommand(final String actionName, final String command, + final String[] argumentList, final IPath execDir) { + // We need to use a workspace root scheduling rule because adding MakeTargets + // may end up saving the project description which runs under a workspace root rule. + final ISchedulingRule rule = ResourcesPlugin.getWorkspace().getRoot(); + + Job backgroundJob = new Job(actionName) { + /* (non-Javadoc) + * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) + */ + protected IStatus run(IProgressMonitor monitor) { + try { + ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() { + + public void run(IProgressMonitor monitor) throws CoreException { + try { + String errMsg = null; + IProject project = getSelectedContainer().getProject(); + // Get a build console for the project + IConsole console = CCorePlugin.getDefault().getConsole("org.eclipse.linuxtools.cdt.autotools.autotoolsConsole"); //$NON-NLS-1$ + console.start(project); + ConsoleOutputStream consoleOutStream = console.getOutputStream(); + // FIXME: we want to remove need for ManagedBuilderManager, but how do we + // get environment variables. + IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project); + IConfiguration cfg = info.getDefaultConfiguration(); + + StringBuffer buf = new StringBuffer(); + String[] consoleHeader = new String[3]; + + consoleHeader[0] = actionName; + consoleHeader[1] = cfg.getName(); + consoleHeader[2] = project.getName(); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + String invokeMsg = InvokeMessages.getFormattedString("InvokeAction.console.message", //$NON-NLS-1$ + new String[]{actionName, execDir.toString()}); //$NON-NLS-1$ + buf.append(invokeMsg); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + consoleOutStream.write(buf.toString().getBytes()); + consoleOutStream.flush(); + + ArrayList<String> additionalEnvs = new ArrayList<String>(); + String strippedCommand = MakeGenerator.stripEnvVars(command, additionalEnvs); + // Get a launcher for the config command + CommandLauncher launcher = new CommandLauncher(); + // Set the environment + IEnvironmentVariable variables[] = ManagedBuildManager + .getEnvironmentVariableProvider().getVariables(cfg, true); + String[] env = null; + ArrayList<String> envList = new ArrayList<String>(); + if (variables != null) { + for (int i = 0; i < variables.length; i++) { + envList.add(variables[i].getName() + + "=" + variables[i].getValue()); //$NON-NLS-1$ + } + if (additionalEnvs.size() > 0) + envList.addAll(additionalEnvs); // add any additional environment variables specified ahead of script + env = (String[]) envList.toArray(new String[envList.size()]); + } + OutputStream stdout = consoleOutStream; + OutputStream stderr = consoleOutStream; + + launcher.showCommand(true); + // Run the shell script via shell command. + Process proc = launcher.execute(new Path(strippedCommand), argumentList, env, + execDir, new NullProgressMonitor()); + if (proc != null) { + try { + // Close the input of the process since we will never write to + // it + proc.getOutputStream().close(); + } catch (IOException e) { + } + + if (launcher.waitAndRead(stdout, stderr, new SubProgressMonitor( + monitor, IProgressMonitor.UNKNOWN)) != CommandLauncher.OK) { + errMsg = launcher.getErrorMessage(); + } + + // Force a resync of the projects without allowing the user to + // cancel. + // This is probably unkind, but short of this there is no way to + // ensure + // the UI is up-to-date with the build results + // monitor.subTask(ManagedMakeMessages + // .getResourceString(REFRESH)); + monitor.subTask(AutotoolsPlugin.getResourceString("MakeGenerator.refresh")); //$NON-NLS-1$ + try { + project.refreshLocal(IResource.DEPTH_INFINITE, null); + } catch (CoreException e) { + monitor.subTask(AutotoolsPlugin + .getResourceString("MakeGenerator.refresh.error")); //$NON-NLS-1$ + } + } else { + errMsg = launcher.getErrorMessage(); + } + + if (errMsg != null) + AutotoolsPlugin.logErrorMessage(errMsg); + + } catch (IOException e) { + AutotoolsPlugin.log(e); + } + } + }, rule, IWorkspace.AVOID_UPDATE, monitor); + } catch (CoreException e) { + return e.getStatus(); + } + IStatus returnStatus = Status.OK_STATUS; + return returnStatus; + } + }; + + backgroundJob.setRule(rule); + backgroundJob.schedule(); + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAutoconfAction.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAutoconfAction.java new file mode 100644 index 0000000000..6440dfa025 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAutoconfAction.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jface.action.IAction; +import org.eclipse.linuxtools.cdt.autotools.ui.properties.AutotoolsPropertyConstants; + + +/** + * Class responsible for invoking autoconf. + * + * @author klee + * + */ +public class InvokeAutoconfAction extends InvokeAction { + + private final static String DEFAULT_COMMAND = "autoconf"; //$NON-NLS-1$ + public void run(IAction action) { + IContainer container = getSelectedContainer(); + if (container == null) + return; + + IPath execDir = getExecDir(container); + + if (container != null) { + IProject project = container.getProject(); + String autoconfCommand = null; + try { + autoconfCommand = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOCONF_TOOL); + } catch (CoreException e) { + // do nothing + } + + // If unset for the project, default to system path + if (autoconfCommand == null) + autoconfCommand = DEFAULT_COMMAND; + + executeConsoleCommand(DEFAULT_COMMAND, autoconfCommand, new String[]{}, execDir); + } + } + + + public void dispose() { + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAutoheaderAction.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAutoheaderAction.java new file mode 100644 index 0000000000..1057d45743 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAutoheaderAction.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.linuxtools.cdt.autotools.ui.properties.AutotoolsPropertyConstants; +import org.eclipse.swt.widgets.Shell; + + +public class InvokeAutoheaderAction extends InvokeAction { + + private static final String DEFAULT_OPTION = ""; //$NON-NLS-1$ + private static final String DEFAULT_COMMAND = "autoheader"; //$NON-NLS-1$ + + public void run(IAction action) { + + IContainer container = getSelectedContainer(); + if (container == null) + return; + + IPath execDir = getExecDir(container); + String cwd = InvokeMessages.getString("CWD") + getCWD(container); //$NON-NLS-1$ + + InputDialog optionDialog = new SingleInputDialog( + new Shell(), + cwd, + InvokeMessages + .getString("InvokeAutoheaderAction.windowTitle.options"), //$NON-NLS-1$ + InvokeMessages + .getString("InvokeAutoheaderAction.message.options.otherOptions"), //$NON-NLS-1$ + DEFAULT_OPTION, null); + optionDialog.open(); + + // chop args into string array + String rawArgList = optionDialog.getValue(); + + String[] optionsList = simpleParseOptions(rawArgList); + + String[] argumentList = new String[optionsList.length]; + + System.arraycopy(optionsList, 0, argumentList, 0, optionsList.length); + + if (container != null) { + String autoheaderCommand = null; + IProject project = getSelectedContainer().getProject(); + try { + autoheaderCommand = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOHEADER_TOOL); + } catch (CoreException e) { + // do nothing + } + + // If unset, use default system path + if (autoheaderCommand == null) + autoheaderCommand = DEFAULT_COMMAND; + + executeConsoleCommand(DEFAULT_COMMAND, autoheaderCommand, + argumentList, execDir); + } + + } + + public void dispose() { + + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAutomakeAction.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAutomakeAction.java new file mode 100644 index 0000000000..2e973849f9 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAutomakeAction.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jface.action.IAction; +import org.eclipse.linuxtools.cdt.autotools.ui.properties.AutotoolsPropertyConstants; +import org.eclipse.swt.widgets.Shell; + + +/** + * Class responsible for invoking automake. + * + * @author klee + * + */ +public class InvokeAutomakeAction extends InvokeAction { + + private static final String DEFAULT_OPTION = ""; //$NON-NLS-1$ + private static final String DEFAULT_COMMAND = "automake"; //$NON-NLS-1$ + + public void run(IAction action) { + + IContainer container = getSelectedContainer(); + if (container == null) + return; + + IPath execDir = getExecDir(container); + String cwd = InvokeMessages.getString("CWD") + getCWD(container); //$NON-NLS-1$ +; + TwoInputDialog optionDialog = new TwoInputDialog(new Shell(), cwd, + InvokeMessages + .getString("InvokeAutomakeAction.windowTitle.options"), //$NON-NLS-1$ +InvokeMessages + .getString("InvokeAutomakeAction.message.options.otherOptions"),InvokeMessages //$NON-NLS-1$ + .getString("InvokeAutomakeAction.message.options.makeTargets"), DEFAULT_OPTION, null); //$NON-NLS-1$ + + optionDialog.open(); + + // chop args into string array + String rawArgList = optionDialog.getValue(); + + String[] optionsList = separateOptions(rawArgList); + + + // chop args into string array + rawArgList = optionDialog.getSecondValue(); + + String[] targetList = separateTargets(rawArgList); + + if (targetList == null) { + + showError(InvokeMessages.getString("InvokeAction.execute.windowTitle.error"), //$NON-NLS-1$ + InvokeMessages.getString("InvokeAction.windowTitle.quoteError")); //$NON-NLS-1$ + return; + } + + String[] argumentList = new String[targetList.length + + optionsList.length]; + + System.arraycopy(optionsList, 0, argumentList, 0, optionsList.length); + System.arraycopy(targetList, 0, argumentList, optionsList.length, + targetList.length); + + if (container != null) { + IProject project = container.getProject(); + String automakeCommand = null; + try { + automakeCommand = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOMAKE_TOOL); + } catch (CoreException e) { + // do nothing + } + + // If automake path not set for the project, default to system path + if (automakeCommand == null) + automakeCommand = DEFAULT_COMMAND; + + executeConsoleCommand(DEFAULT_COMMAND, automakeCommand, + argumentList, execDir); + } + } + + public void dispose() { + + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAutoreconfAction.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAutoreconfAction.java new file mode 100644 index 0000000000..b16de919d3 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeAutoreconfAction.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.linuxtools.cdt.autotools.ui.properties.AutotoolsPropertyConstants; +import org.eclipse.swt.widgets.Shell; + + +public class InvokeAutoreconfAction extends InvokeAction { + + private static final String DEFAULT_OPTION = ""; //$NON-NLS-1$ + private static final String DEFAULT_COMMAND = "autoreconf"; //$NON-NLS-1$ + + public void run(IAction action) { + + IContainer container = getSelectedContainer(); + if (container == null) + return; + + IPath execDir = getExecDir(container); + String cwd = InvokeMessages.getString("CWD") + getCWD(container); //$NON-NLS-1$ + + InputDialog optionDialog = new SingleInputDialog( + new Shell(), + cwd, + InvokeMessages + .getString("InvokeAutoreconfAction.windowTitle.options"), //$NON-NLS-1$ + InvokeMessages + .getString("InvokeAutoreconfAction.message.options.otherOptions"), //$NON-NLS-1$ + DEFAULT_OPTION, null); + optionDialog.open(); + + // chop args into string array + String rawArgList = optionDialog.getValue(); + + String[] optionsList = simpleParseOptions(rawArgList); + + String[] argumentList = new String[optionsList.length]; + + System.arraycopy(optionsList, 0, argumentList, 0, optionsList.length); + + if (container != null) { + String autoreconfCommand = null; + IProject project = getSelectedContainer().getProject(); + try { + autoreconfCommand = project.getPersistentProperty(AutotoolsPropertyConstants.AUTORECONF_TOOL); + } catch (CoreException e) { + // do nothing + } + + // If unset, use default system path + if (autoreconfCommand == null) + autoreconfCommand = DEFAULT_COMMAND; + + executeConsoleCommand(DEFAULT_COMMAND, autoreconfCommand, + argumentList, execDir); + } + } + + public void dispose() { + + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeLibtoolizeAction.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeLibtoolizeAction.java new file mode 100644 index 0000000000..03e04273db --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeLibtoolizeAction.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.linuxtools.cdt.autotools.ui.properties.AutotoolsPropertyConstants; +import org.eclipse.swt.widgets.Shell; + + +public class InvokeLibtoolizeAction extends InvokeAction { + + private static final String DEFAULT_OPTION = ""; //$NON-NLS-1$ + private static final String DEFAULT_COMMAND = "libtoolize"; //$NON-NLS-1$ + + public void run(IAction action) { + + IContainer container = getSelectedContainer(); + if (container == null) + return; + + IPath execDir = getExecDir(container); + String cwd = InvokeMessages.getString("CWD") + getCWD(container); //$NON-NLS-1$ + + InputDialog optionDialog = new SingleInputDialog( + new Shell(), + cwd, + InvokeMessages + .getString("InvokeLibtoolizeAction.windowTitle.options"), //$NON-NLS-1$ + InvokeMessages + .getString("InvokeLibtoolizeAction.message.options.otherOptions"), //$NON-NLS-1$ + DEFAULT_OPTION, null); + optionDialog.open(); + + // chop args into string array + String rawArgList = optionDialog.getValue(); + + String[] optionsList = simpleParseOptions(rawArgList); + + String[] argumentList = new String[optionsList.length]; + + System.arraycopy(optionsList, 0, argumentList, 0, optionsList.length); + + if (container != null) { + String libtoolizeCommand = null; + IProject project = getSelectedContainer().getProject(); + try { + libtoolizeCommand = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOHEADER_TOOL); + } catch (CoreException e) { + // do nothing + } + + // If unset, use default system path + if (libtoolizeCommand == null) + libtoolizeCommand = DEFAULT_COMMAND; + + executeConsoleCommand(DEFAULT_COMMAND, libtoolizeCommand, + argumentList, execDir); + } + } + + public void dispose() { + + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeMessages.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeMessages.java new file mode 100644 index 0000000000..b62632a1c2 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeMessages.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007, 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class InvokeMessages { + private static final String BUNDLE_NAME = InvokeMessages.class.getName(); + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle + .getBundle(BUNDLE_NAME); + + private InvokeMessages() { + } + + /** + * Returns the string from the resource bundle, + * or 'key' if not found. + * + * @param key the message key + * @return the resource bundle message + */ + public static String getString(String key) { + try { + return RESOURCE_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } + + /** + * Returns the formatted string from the resource bundle, + * or 'key' if not found. + * + * @param key the message key + * @param args an array of substituition strings + * @return the resource bundle message + */ + public static String getFormattedString(String key, String[] args) { + return MessageFormat.format(getString(key), (Object[])args); + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeMessages.properties b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeMessages.properties new file mode 100644 index 0000000000..b2da117fef --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/InvokeMessages.properties @@ -0,0 +1,56 @@ +################################################################################# +# Copyright (c) 2006, 2007, 2009 Red Hat, Inc. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Red Hat Incorporated - initial API and implementation +################################################################################# +CWD=Working Directory: + +InvokeAction.windowTitle.quoteError=Quote/Double quote not correct +InvokeAction.progress.message=Running {0} +InvokeAction.execute.windowTitle.error=Invoke Action Error +InvokeAction.execute.message=Couldn't execute command : +InvokeAction.success=Command executed successfully +InvokeAction.console.message=Invoking {0} in {1} + + +InvokeAutoconfAction.command=Running autoconf in {0} +InvokeAutoconfAction.windowTitle.stdout=Invoke Autoconf - Output +InvokeAutoconfAction.windowTitle.stderr=Invoke Autoconf - Error + + +InvokeAutomakeAction.command=Running automake +InvokeAutomakeAction.windowTitle.options=Automake Options +InvokeAutomakeAction.message.options.makeTargets=Enter targets separated by space : +InvokeAutomakeAction.message.options.otherOptions=Enter options separated by space : +InvokeAutomakeAction.windowTitle.stdout=Invoke Automake - Output +InvokeAutomakeAction.windowTitle.stderr=Invoke Automake - Error + +InvokeAutoheaderAction.command=Running autoheader +InvokeAutoheaderAction.windowTitle.options=Autoheader Options +InvokeAutoheaderAction.message.options.otherOptions=Enter options separated by space : +InvokeAutoheaderAction.windowTitle.stdout=Invoke Autoheader - Output +InvokeAutoheaderAction.windowTitle.stderr=Invoke Autoheader - Error + +InvokeAutoreconfAction.command=Running autoreconf +InvokeAutoreconfAction.windowTitle.options=Autoreconf Options +InvokeAutoreconfAction.message.options.otherOptions=Enter options separated by space : +InvokeAutoreconfAction.windowTitle.stdout=Invoke Autoreconf - Output +InvokeAutoreconfAction.windowTitle.stderr=Invoke Autoreconf - Error + +InvokeAclocalAction.command=Running aclocal +InvokeAclocalAction.windowTitle.options=Aclocal Options +InvokeAclocalAction.message.options.includeDir=Add directory to search list for .m4 files : +InvokeAclocalAction.message.options.otherOptions=Enter options separated by space : +InvokeAclocalAction.windowTitle.stdout=Invoke Automake - Output +InvokeAclocalAction.windowTitle.stderr=Invoke Automake - Error + +InvokeLibtoolizeAction.command=Running libtoolize +InvokeLibtoolizeAction.windowTitle.options=Libtoolize Options +InvokeLibtoolizeAction.message.options.otherOptions=Enter options separated by space : +InvokeLibtoolizeAction.windowTitle.stdout=Invoke Libtoolize - Output +InvokeLibtoolizeAction.windowTitle.stderr=Invoke Libtoolize - Error diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/LibtoolizeHandler.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/LibtoolizeHandler.java new file mode 100644 index 0000000000..202f1b6476 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/LibtoolizeHandler.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.expressions.IEvaluationContext; +import org.eclipse.core.resources.IContainer; + +/** + * @author Jeff Johnston + * + */ +public class LibtoolizeHandler extends AbstractAutotoolsHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + InvokeLibtoolizeAction a = new InvokeLibtoolizeAction(); + Object o = event.getApplicationContext(); + if (o instanceof IEvaluationContext) { + IContainer container = getContainer((IEvaluationContext)o); + if (container != null) { + a.setSelectedContainer(container); + a.run(null); + } + } + return null; + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/ReconfigureAction.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/ReconfigureAction.java new file mode 100644 index 0000000000..96ef9a6823 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/ReconfigureAction.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.action.IAction; +import org.eclipse.linuxtools.cdt.autotools.MakeGenerator; + + +public class ReconfigureAction extends InvokeAction { + + public void run(IAction action) { + IContainer container = getSelectedContainer(); + if (container == null) + return; + + // We need to use a workspace root scheduling rule because adding MakeTargets + // may end up saving the project description which runs under a workspace root rule. + final ISchedulingRule rule = ResourcesPlugin.getWorkspace().getRoot(); + + Job backgroundJob = new Job("Reconfigure Action"){ //$NON-NLS-1$ + /* (non-Javadoc) + * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) + */ + protected IStatus run(IProgressMonitor monitor) { + try { + ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() { + + public void run(IProgressMonitor monitor) throws CoreException { + IProject project = getSelectedContainer().getProject(); + MakeGenerator m = new MakeGenerator(); + IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project); + m.initialize(project, info, monitor); + m.removeConfigSettings(); + try { + m.regenerateMakefiles(); + } catch (CoreException e) { + // do nothing for now + } + } + }, rule, IWorkspace.AVOID_UPDATE, monitor); + } catch (CoreException e) { + return e.getStatus(); + } + IStatus returnStatus = Status.OK_STATUS; + return returnStatus; + } + }; + + backgroundJob.setRule(rule); + backgroundJob.schedule(); + } + + public void dispose() { + + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/ReconfigureHandler.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/ReconfigureHandler.java new file mode 100644 index 0000000000..843d7bbabc --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/ReconfigureHandler.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2009 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.expressions.IEvaluationContext; +import org.eclipse.core.resources.IContainer; + +/** + * @author Jeff Johnston + * + */ +public class ReconfigureHandler extends AbstractAutotoolsHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + ReconfigureAction a = new ReconfigureAction(); + Object o = event.getApplicationContext(); + if (o instanceof IEvaluationContext) { + IContainer container = getContainer((IEvaluationContext)o); + if (container != null) { + a.setSelectedContainer(container); + a.run(null); + } + } + return null; + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/SingleInputDialog.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/SingleInputDialog.java new file mode 100644 index 0000000000..8a5f8bc456 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/SingleInputDialog.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; + +public class SingleInputDialog extends InputDialog { + + private String firstMessage; + + public SingleInputDialog(Shell parentShell, String firstMessage, String dialogTitle, + String dialogMessage, String initialValue, + IInputValidator validator) { + super(parentShell, dialogTitle, dialogMessage, initialValue, validator); + + this.firstMessage = firstMessage; + } + + /* + * (non-Javadoc) Method declared on Dialog. + */ + protected void buttonPressed(int buttonId) { + super.buttonPressed(buttonId); + } + + protected Control createDialogArea(Composite parent) { + + // create composite + Composite composite = (Composite) super.createDialogArea(parent); + + CLabel label0 = new CLabel(composite, SWT.WRAP); + label0.setText(firstMessage); + GridData data = new GridData(GridData.GRAB_HORIZONTAL + | GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL + | GridData.VERTICAL_ALIGN_CENTER); + data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH); + label0.setLayoutData(data); + label0.setFont(parent.getFont()); + + // remove error message dialog from focusing. + composite.getTabList()[2].setVisible(false); + composite.getTabList()[2].setEnabled(false); + + return composite; + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/TwoInputDialog.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/TwoInputDialog.java new file mode 100644 index 0000000000..f786e449f2 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/actions/TwoInputDialog.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 Red Hat Inc.. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.actions; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +public class TwoInputDialog extends InputDialog { + + private Text secondText; + + private String secondValue; + + private String secondMessage; + + private String firstMessage; + + public TwoInputDialog(Shell parentShell, String firstMessage, String dialogTitle, + String dialogMessage, String secondMessage, String initialValue, + IInputValidator validator) { + super(parentShell, dialogTitle, dialogMessage, initialValue, validator); + + this.firstMessage = firstMessage; + this.secondMessage = secondMessage; + } + + /* + * (non-Javadoc) Method declared on Dialog. + */ + protected void buttonPressed(int buttonId) { + if (buttonId == IDialogConstants.OK_ID) { + secondValue = secondText.getText(); + } else { + secondValue = null; + } + super.buttonPressed(buttonId); + } + + protected Control createDialogArea(Composite parent) { + + // create composite + Composite composite = (Composite) super.createDialogArea(parent); + + CLabel label0 = new CLabel(composite, SWT.WRAP); + label0.setText(firstMessage); + Label label = new Label(composite, SWT.WRAP); + label.setText(secondMessage); + GridData data = new GridData(GridData.GRAB_HORIZONTAL + | GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL + | GridData.VERTICAL_ALIGN_CENTER); + data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH); + label0.setLayoutData(data); + label0.setFont(parent.getFont()); + label.setLayoutData(data); + label.setFont(parent.getFont()); + + + secondText = new Text(composite, SWT.SINGLE | SWT.BORDER); + secondText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL + | GridData.HORIZONTAL_ALIGN_FILL)); + secondText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + validateInput(); + } + }); + + // remove error message dialog from focusing. + composite.getTabList()[2].setVisible(false); + composite.getTabList()[2].setEnabled(false); + + return composite; + } + + /** + * Returns the text area. + * + * @return the text area + */ + protected Text getSecondText() { + return secondText; + } + + /** + * Returns the string typed into this input dialog. + * + * @return the input string + */ + public String getSecondValue() { + return secondValue; + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfCaseConditionElement.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfCaseConditionElement.java new file mode 100644 index 0000000000..d06e73d091 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfCaseConditionElement.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +public class AutoconfCaseConditionElement extends AutoconfElement { + + public AutoconfCaseConditionElement() { + super(""); + } + + public AutoconfCaseConditionElement(String name) { + super(name); + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfCaseElement.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfCaseElement.java new file mode 100644 index 0000000000..c8ad284dd4 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfCaseElement.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +public class AutoconfCaseElement extends AutoconfElement { + + public AutoconfCaseElement() { + super("case"); //$NON-NLS-1$ + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfEditorMessages.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfEditorMessages.java new file mode 100644 index 0000000000..53c7a7d857 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfEditorMessages.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2002, 2006 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + + +/** + * AutoconfEditorMessages + */ +public class AutoconfEditorMessages { + + private static final String RESOURCE_BUNDLE= AutoconfEditorMessages.class.getName(); + + private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE); + + private AutoconfEditorMessages() { + } + + public static ResourceBundle getResourceBundle() { + return fgResourceBundle; + } + + public static String getString(String key) { + try { + return fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ + } + } + /** + * Gets a string from the resource bundle and formats it with the argument + * + * @param key the string used to get the bundle value, must not be null + * @since 3.0 + */ + public static String getFormattedString(String key, Object arg) { + String format= null; + try { + format= fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ + } + if (arg == null) + arg= ""; //$NON-NLS-1$ + return MessageFormat.format(format, new Object[] { arg }); + } + /** + * Gets a string from the resource bundle and formats it with the arguments + * + * @param key the string used to get the bundle value, must not be null + * @since 3.0 + */ + public static String getFormattedString(String key, Object arg1, Object arg2) { + String format= null; + try { + format= fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ + } + if (arg1 == null) + arg1= ""; //$NON-NLS-1$ + if (arg2 == null) + arg2= ""; //$NON-NLS-1$ + return MessageFormat.format(format, new Object[] { arg1, arg2 }); + } + + /** + * Gets a string from the resource bundle and formats it with the arguments + * + * @param key the string used to get the bundle value, must not be null + * @since 3.0 + */ + public static String getFormattedString(String key, Object arg1, Object arg2, Object arg3) { + String format= null; + try { + format= fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ + } + if (arg1 == null) + arg1= ""; //$NON-NLS-1$ + if (arg2 == null) + arg2= ""; //$NON-NLS-1$ + if (arg3 == null) + arg3= ""; //$NON-NLS-1$ + return MessageFormat.format(format, new Object[] { arg1, arg2, arg3 }); + } + + /** + * Gets a string from the resource bundle and formats it with the argument + * + * @param key the string used to get the bundle value, must not be null + * @since 3.0 + */ + public static String getFormattedString(String key, boolean arg) { + String format= null; + try { + format= fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ + } + return MessageFormat.format(format, new Object[] { new Boolean(arg) }); + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfEditorMessages.properties b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfEditorMessages.properties new file mode 100644 index 0000000000..692d0649fb --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfEditorMessages.properties @@ -0,0 +1,47 @@ +################################################################################# +# Copyright (c) 2007 Red Hat, Inc., (c) 2008 Nokia Inc +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Red Hat Incorporated - initial API and implementation +# Nokia Inc - refactoring +################################################################################# +UnmatchedRightParenthesis=Unmatched right parenthesis +UnmatchedLeftParenthesis=Unmatched left parenthesis +UnmatchedRightQuote=Unmatched right quote, expected {0} +UnmatchedLeftQuote=Unmatched left quote, expected {0} +UnmatchedCloseComment=Unmatched end of comment, expected {0} +UnterminatedString=Unterminated string, expected {0} + +AutoconfMacroArgsTooFew=The autoconf version {0} definition of macro "{1}" requires at least {2} arguments +AutoconfMacroArgsTooMany=The autoconf version {0} definition of macro "{1}" may have a maximum of {2} arguments +M4MacroArgsTooFew=The m4 macro "{0}" requires at least {1} arguments +M4MacroArgsTooMany=The m4 macro "{0}" may have a maximum of {1} arguments +MissingSpecifier=Missing "{0}" specifier +InvalidSpecifier=The specifier "{0}" should be separated from condition by semicolon or newline +InvalidTermination=The specifier "{0}" should appear after semicolon or newline +UnterminatedConstruct=This "{0}" construct is unterminated +MissingCondition=Missing condition for {0} specifier +InvalidElif=The "elif" keyword should appear in an "if" or "elif" construct +InvalidElse=The "else" keyword should appear in an "if" or "elif" construct +InvalidFi=The "fi" keyword should terminate an "if", "elif", or "else" construct +InvalidEsac=The "esac" keyword should terminate a "case" statement +InvalidDone=The "done" keyword should terminate a "for", "while", "until", or "select" statement +InvalidDo=The "do" keyword should appear in a "for", "while", "until", or "select" statement +InvalidThen=The "then" keyword should appear in an "if" or "elif" statement +InvalidIn=The "in" keyword should appear in a "case" statement +UnterminatedCaseCondition=Case condition is not terminated before "esac" keyword +ImproperCaseCondition=Case condition expected to end with ")" +UnterminatedInlineDocument=Inline document started with "<<" is unterminated +IncompleteInlineMarker=Inline document marker has incomplete quote +MissingInlineMarker=Inline document specification is missing end marker +AutoconfAnnotationHover.multipleMarkers=Multiple markers at this line + +ShowToolTip.label=Show T&ooltip Description +ContentAssistProposal.label=Co&ntent Assist +ContentAssistProposal.tooltip=Content Assist +ContentAssistProposal.description=Content Assist + diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfElement.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfElement.java new file mode 100644 index 0000000000..2bf2a28c39 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfElement.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +import java.util.ArrayList; +import java.util.Iterator; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; + +public class AutoconfElement { + + protected String name; + protected String var; + protected int startOffset; + protected int endOffset; + protected ArrayList<AutoconfElement> children; + protected AutoconfElement parent; + private IDocument document; + + public AutoconfElement(String name) { + this(name, null); + } + + public AutoconfElement(String name, String var) { + this.name = name; + this.var = var; + this.startOffset = 0; + this.children = new ArrayList<AutoconfElement>(); + } + + + public String toString() { + String source = getSource(); + if (source == null) { + StringBuffer kids = new StringBuffer(); + for (Iterator<AutoconfElement> iterator = children.iterator(); iterator.hasNext();) { + AutoconfElement kid = (AutoconfElement) iterator.next(); + kids.append(kid.toString()); + kids.append(","); + } + source = kids.toString(); + } + return getClass().getSimpleName() + ": '" + source + "'"; + } + + public void addChild(AutoconfElement element) { + children.add(element); + if (element.getParent() == null) + element.setParent(this); + } + + public void addSibling(AutoconfElement element) { + parent.addChild(element); + } + + public AutoconfElement getLastChild() { + if (hasChildren()) + return (AutoconfElement)children.get(children.size() - 1); + return null; + } + + public AutoconfElement getParent() { + return parent; + } + + public void setParent(AutoconfElement parent) { + this.parent = parent; + } + + public AutoconfElement[] getChildren() { + return (AutoconfElement[]) children.toArray(new AutoconfElement[children.size()]); + } + + public boolean hasChildren() { + return !children.isEmpty(); + } + + public String getName() { + return name; + } + + public void setName(String string) { + this.name = string; + } + + + public String getVar() { + return var; + } + + public void setVar(String value) { + var = value; + } + + public void setDocument(IDocument document) { + this.document = document; + } + + public IDocument getDocument() { + return document; + } + + public void setStartOffset(int offset) { + this.startOffset = offset; + } + + public int getStartOffset() { + return startOffset; + } + + public void setEndOffset(int offset) { + this.endOffset = offset; + } + + public int getEndOffset() { + return endOffset; + } + + public String getSource() { + if (document != null && startOffset >= 0 && endOffset >= startOffset) { + try { + return document.get(startOffset, endOffset - startOffset); + } catch (BadLocationException e) { + return null; + } + } + return null; + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfElifElement.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfElifElement.java new file mode 100644 index 0000000000..a990ea82d5 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfElifElement.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +public class AutoconfElifElement extends AutoconfElement { + + public AutoconfElifElement() { + super("elif"); //$NON-NLS-1$ + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfElseElement.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfElseElement.java new file mode 100644 index 0000000000..bbaa2c2c76 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfElseElement.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +public class AutoconfElseElement extends AutoconfElement { + + public AutoconfElseElement() { + super("else"); //$NON-NLS-1$ + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfForElement.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfForElement.java new file mode 100644 index 0000000000..6b0ffcc9a4 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfForElement.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +public class AutoconfForElement extends AutoconfElement { + + public AutoconfForElement() { + super("for"); //$NON-NLS-1$ + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfIfElement.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfIfElement.java new file mode 100644 index 0000000000..6ad658979c --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfIfElement.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +public class AutoconfIfElement extends AutoconfElement { + + public AutoconfIfElement() { + super("if"); //$NON-NLS-1$ + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfMacroArgumentElement.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfMacroArgumentElement.java new file mode 100644 index 0000000000..24bf1d5f0b --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfMacroArgumentElement.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ed Swartz (Nokia) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +/** + * This is a macro argument node. It may also hold + * other AutoconfMacroElements. The source range includes any quotes around an argument + * but the #getName() has them stripped. + * @author eswartz + * + */ +public class AutoconfMacroArgumentElement extends AutoconfElement { + + public AutoconfMacroArgumentElement() { + super(""); // //$NON-NLS-N$ + } + public AutoconfMacroArgumentElement(String name) { + super(name); // //$NON-NLS-N$ + } + public String getVar() { + return super.getVar(); + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfMacroDetector.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfMacroDetector.java new file mode 100644 index 0000000000..3635bcd5a9 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfMacroDetector.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc., (c) 2008 Nokia Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + * Ed Swartz (Nokia) - refactoring + *******************************************************************************/ + +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +import java.util.regex.Pattern; + +/** + * + */ +public class AutoconfMacroDetector implements IAutoconfMacroDetector { + + private static final Pattern AUTOCONF_MACRO_PATTERN = Pattern.compile("PKG_.*|AC_.*|AM_.*|m4.*"); //$NON-NLS-1$ + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.cdt.autotools.ui.editors.parser.IAutoconfMacroDetector#isMacroIdentifier(java.lang.String) + */ + public boolean isMacroIdentifier(String name) { + return AUTOCONF_MACRO_PATTERN.matcher(name).matches(); + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfMacroElement.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfMacroElement.java new file mode 100644 index 0000000000..1168f910cc --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfMacroElement.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + * Ed Swartz (NOKIA Inc) - support standalone parser + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +/** + * A call to a macro. + * <p> + * Macro element now stores arguments as AutoconfMacroElement or AutoconfMacroArgument children + * + */ +public class AutoconfMacroElement extends AutoconfElement { + + public AutoconfMacroElement(String name) { + super(name); + } + + public String getVar() { + if (children.size() > 0) + return getParameter(0); + else + return null; + } + public int getParameterCount() { + return children.size(); + } + + public String getParameter(int num) { + return ((AutoconfElement) children.get(num)).getName(); + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfOutlineErrorHandler.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfOutlineErrorHandler.java new file mode 100644 index 0000000000..9a5100eff7 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfOutlineErrorHandler.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.linuxtools.cdt.autotools.AutotoolsPlugin; +import org.eclipse.ui.IStorageEditorInput; +import org.eclipse.ui.texteditor.MarkerUtilities; + + +public class AutoconfOutlineErrorHandler { + + public static final String PARSE_ERROR_MARKER_ID = AutotoolsPlugin.PLUGIN_ID + + ".outlineparsefileerror"; + + private IFile file; + private IDocument document; + + public AutoconfOutlineErrorHandler(IStorageEditorInput input, IDocument document) + { + this.document = document; + IWorkspaceRoot root = CCorePlugin.getWorkspace().getRoot(); + try { + IPath absPath = input.getStorage().getFullPath(); + IPath rootPath = root.getLocation(); + IPath relPath = new Path(""); + + for (int i = 0; i < rootPath.segmentCount(); ++i) { + relPath = relPath.append("../"); + } + relPath = relPath.append(absPath); + this.file = root.getFileForLocation(relPath); + if (this.file == null) { + this.file = root.getFile(relPath); + } + } catch (CoreException e) { + e.printStackTrace(); + } + } + + public IDocument getDocument() { + return document; + } + + public void handleError(ParseException e) { + if (!file.exists()) + return; + + int lineNumber = e.getLineNumber(); + + Map<String, Object> map = new HashMap<String, Object>(); + MarkerUtilities.setLineNumber(map, lineNumber); + MarkerUtilities.setMessage(map, e.getMessage()); + map.put(IMarker.MESSAGE, e.getMessage()); + map.put(IMarker.LOCATION, file.getFullPath().toString()); + + Integer charStart = getCharOffset(lineNumber, e.getStartColumn()); + if (charStart != null) { + map.put(IMarker.CHAR_START, charStart); + } + Integer charEnd = getCharOffset(lineNumber, e.getEndColumn()); + if (charEnd != null) { + map.put(IMarker.CHAR_END, charEnd); + } + + // FIXME: add severity level + map.put(IMarker.SEVERITY, new Integer(e.getSeverity())); + + try { + MarkerUtilities.createMarker(file, map, PARSE_ERROR_MARKER_ID); + } catch (CoreException ee) { + ee.printStackTrace(); + } + return; + } + + public void removeAllExistingMarkers() { + if (!file.exists()) + return; + + try { + file.deleteMarkers(PARSE_ERROR_MARKER_ID, true, IResource.DEPTH_ZERO); + } catch (CoreException e1) { + e1.printStackTrace(); + } + } + + public void removeExistingMarkers(int offset, int length) { + if (!file.exists()) + return; + + try { + IMarker[] markers = file.findMarkers(PARSE_ERROR_MARKER_ID, true, IResource.DEPTH_ZERO); + // Delete all markers that start in the given document range. + for (int i = 0; i < markers.length; ++i) { + IMarker marker = markers[i]; + int charEnd = MarkerUtilities.getCharEnd(marker); + int charStart = MarkerUtilities.getCharStart(marker); + if (charStart >= offset && charEnd <= (offset + length)) + marker.delete(); + } + } catch (CoreException e1) { + e1.printStackTrace(); + } + } + + private Integer getCharOffset(int lineNumber, int columnNumber) { + try { + return new Integer(document.getLineOffset(lineNumber) + columnNumber); + } catch (BadLocationException e) { + e.printStackTrace(); + return null; + } + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfParser.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfParser.java new file mode 100644 index 0000000000..e6996035c2 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfParser.java @@ -0,0 +1,1041 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc., (c) 2008 Nokia + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + * Ed Swartz (Nokia) - refactoring + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; + + +/** + * Tokenizing autoconf parser, based on original work by Jeff Johnston + * @author eswartz + */ +public class AutoconfParser { + + public static final String MISSING_SPECIFIER = "MissingSpecifier"; //$NON-NLS-1$ + public static final String INVALID_SPECIFIER = "InvalidSpecifier"; //$NON-NLS-1$ + public static final String INVALID_TERMINATION = "InvalidTermination"; //$NON-NLS-1$ + public static final String UNTERMINATED_CONSTRUCT = "UnterminatedConstruct"; //$NON-NLS-1$ + public static final String MISSING_CONDITION = "MissingCondition"; //$NON-NLS-1$ + public static final String INVALID_ELIF = "InvalidElif"; //$NON-NLS-1$ + public static final String INVALID_ELSE = "InvalidElse"; //$NON-NLS-1$ + public static final String INVALID_FI = "InvalidFi"; //$NON-NLS-1$ + public static final String INVALID_DONE = "InvalidDone"; //$NON-NLS-1$ + public static final String INVALID_ESAC = "InvalidEsac"; //$NON-NLS-1$ + public static final String INVALID_DO = "InvalidDo"; //$NON-NLS-1$ + public static final String INVALID_THEN = "InvalidThen"; //$NON-NLS-1$ + public static final String INVALID_IN = "InvalidIn"; //$NON-NLS-1$ + public static final String IMPROPER_CASE_CONDITION = "ImproperCaseCondition"; //$NON-NLS-1$ + public static final String UNTERMINATED_CASE_CONDITION = "UnterminatedCaseCondition"; //$NON-NLS-1$ + public static final String UNTERMINATED_INLINE_DOCUMENT = "UnterminatedInlineDocument"; //$NON-NLS-1$ + public static final String INCOMPLETE_INLINE_MARKER="IncompleteInlineMarker"; //$NON-NLS-1$ + public static final String MISSING_INLINE_MARKER="MissingInlineMarker"; //$NON-NLS-1$ + public static final String UNMATCHED_RIGHT_PARENTHESIS = "UnmatchedRightParenthesis"; //$NON-NLS-1$ + public static final String UNMATCHED_LEFT_PARENTHESIS = "UnmatchedLeftParenthesis"; //$NON-NLS-1$ + + private IAutoconfErrorHandler errorHandler; + private IAutoconfMacroValidator macroValidator; + private AutoconfTokenizer tokenizer; + private IAutoconfMacroDetector macroDetector; + + private static final String M4_BUILTINS = + "define undefine defn pushdef popdef indir builtin ifdef ifelse shift reverse cond " + + "dumpdef traceon traceoff debugmode debugfile dnl changequote changecom changeword " + + "m4wrap " + + "include sinclude divert undivert divnum len index regexp substr translit patsubst " + + "format incr decr eval syscmd esyscmd sysval mkstemp maketemp errprint m4exit " + + "__file__ __line__ __program__ "; + + private static List<String> m4builtins = new ArrayList<String>(); + static { + m4builtins.addAll(Arrays.asList(M4_BUILTINS.split(" "))); + } + + /** + * Create a parser for autoconf-style sources. + * @param errorHandler + * @param macroDetector + * @param macroValidator + */ + public AutoconfParser(IAutoconfErrorHandler errorHandler, + IAutoconfMacroDetector macroDetector, + IAutoconfMacroValidator macroValidator) { + this.errorHandler = errorHandler; + this.macroDetector = macroDetector; + this.macroValidator = macroValidator; + } + + /** + * Parse the given document and produce an AutoconfElement tree + * @param errorHandler + * @param macroValidator + * @param document + * @return element tree + */ + public AutoconfElement parse(IDocument document) { + return parse(document, true); + } + + /** + * Parse the given document and produce an AutoconfElement tree, + * and control whether the initial quoting style is m4 style (`...') + * or autoconf style ([ ... ]). + * @param errorHandler + * @param macroValidator + * @param document + * @param useAutoconfQuotes + * @return element tree + */ + public AutoconfElement parse(IDocument document, boolean useAutoconfQuotes) { + this.tokenizer = new AutoconfTokenizer(document, errorHandler); + if (useAutoconfQuotes) + tokenizer.setM4Quote("[", "]"); + + AutoconfElement root = new AutoconfRootElement(); + Token eof = parseTopLevel(root); + + root.setStartOffset(0); + root.setDocument(document); + + setSourceEnd(root, eof); + + return root; + } + + + static class BlockEndCondition extends Exception { + /** + * + */ + private static final long serialVersionUID = 1L; + private Token token; + + public BlockEndCondition(Token token) { + this.token = token; + } + + public Token getToken() { + return token; + } + + } + + static class ExprEndCondition extends Exception { + /** + * + */ + private static final long serialVersionUID = 1L; + private Token token; + + public ExprEndCondition(Token token) { + this.token = token; + } + + public Token getToken() { + return token; + } + + } + + /** + * Parse individual top-level nodes: divide text into macro calls + * and recognized shell constructs. Anything else is not accounted for. + * @param parent + * @return + */ + protected Token parseTopLevel(AutoconfElement parent) { + while (true) { + try { + parseStatement(parent); + } catch (BlockEndCondition e) { + // don't terminate here; we may have constructs closed too early + Token token = tokenizer.peekToken(); + if (token.getType() == ITokenConstants.EOF) + return token; + } + } + } + + /** + * Parse a block of nodes, which starts with an expression and contains + * subnodes. Divide text into macro calls and recognized shell constructs. + * Anything else is not accounted for. + * @param parent + */ + protected void parseBlock(AutoconfElement parent, Token open, AutoconfElement block) throws BlockEndCondition { + parent.addChild(block); + + setSourceStart(block, open); + + // get the expression part + Token token; + try { + token = parseBlockExpression(open, block); + } catch (BlockEndCondition e) { + setSourceEndBefore(block, e.getToken()); + throw e; + } + + // parse the block proper + if (token.getType() != ITokenConstants.EOF) { + while (true) { + try { + parseStatement(block); + } catch (BlockEndCondition e) { + setSourceEnd(block, e.getToken()); + return; + } + } + } else { + setSourceEnd(block, token); + } + } + + private Token parseBlockExpression(Token open, AutoconfElement block) throws BlockEndCondition { + Token token; + try { + if (block instanceof AutoconfIfElement + || block instanceof AutoconfElifElement + || block instanceof AutoconfCaseElement + || block instanceof AutoconfWhileElement) { + token = parseExpression(block); + } else if (block instanceof AutoconfForElement) { + token = parseForExpression(block); + } else { + // no expression + return open; + } + block.setVar(getTokenSpanTextBetween(open, token)); + } catch (BlockEndCondition e) { + // oops, premature end + setSourceEnd(block, e.getToken()); + throw e; + } + + // check for expected token + while (true) { + token = tokenizer.readToken(); + if (token.getType() == ITokenConstants.EOF) + break; + if (token.getType() != ITokenConstants.EOL) + break; + } + + if (token.getType() == ITokenConstants.SH_DO) { + checkBlockValidity(block, token, + new Class[] { AutoconfForElement.class, AutoconfWhileElement.class }, + INVALID_DO); + } + else if (token.getType() == ITokenConstants.SH_THEN) { + checkBlockValidity(block, token, + new Class[] { AutoconfIfElement.class, AutoconfElifElement.class }, + INVALID_THEN); + } + else { + String exp; + if (block instanceof AutoconfIfElement || block instanceof AutoconfElifElement) + exp = "then"; + else + exp = "do"; + + handleError(block, token, AutoconfEditorMessages.getFormattedString(MISSING_SPECIFIER, exp)); + + // assume we're still in the block... + tokenizer.unreadToken(token); + } + return token; + } + + /** + * Parse a case statement. Scoop up statements into case conditional blocks. + * <pre> + * 'case' EXPR 'in' + * { EXPR ')' { STMTS } ';;' } + * 'esac' + * </pre> + * @param parent + * @return + */ + protected void parseCaseBlock(AutoconfElement parent, Token open, AutoconfElement block) throws BlockEndCondition { + parent.addChild(block); + + setSourceStart(block, open); + + // get the case expression, terminating at 'in' + Token token; + try { + token = parseCaseExpression(block); + } catch (BlockEndCondition e) { + // oops, premature end + setSourceEnd(block, e.getToken()); + throw e; + } + + block.setVar(getTokenSpanTextBetween(open, token)); + + // now get the statements, which are themselves blocks... just read statements + // that terminate with ';;' and stuff those into blocks. + + while (true) { + AutoconfCaseConditionElement condition = new AutoconfCaseConditionElement(); + + // skip EOLs and get the first "real" token + while (true) { + token = tokenizer.readToken(); + setSourceStart(condition, token); + if (token.getType() == ITokenConstants.EOF) + break; + if (token.getType() == ITokenConstants.EOL) + continue; + break; + } + + if (token.getType() == ITokenConstants.SH_ESAC) { + break; + } + + try { + Token start = token; + token = parseCaseExpression(condition); + condition.setName(getTokenSpanTextFromUpTo(start, token)); + + while (true) { + parseStatement(condition); + } + } catch (BlockEndCondition e) { + setSourceEnd(condition, e.getToken()); + + if (condition.getSource().length() > 0) + block.addChild(condition); + + if (e.getToken().getType() != ITokenConstants.SH_CASE_CONDITION_END) { + token = e.getToken(); + break; + } + } + } + + setSourceEnd(block, token); + + if (token.getType() != ITokenConstants.SH_ESAC) { + handleError(parent, token, AutoconfEditorMessages.getFormattedString(UNTERMINATED_CONSTRUCT, block.getName())); + } + } + + private String getTokenSpanTextBetween(Token open, Token close) { + int startOffset = open.getOffset() + open.getLength(); + int endOffset = close.getOffset(); + if (open.getDocument() != close.getDocument()) + return open.getText(); + + String text; + try { + text = open.getDocument().get(startOffset, endOffset - startOffset).trim(); + } catch (BadLocationException e) { + text = open.getText(); + // TODO: error + } + + return text; + } + + private String getTokenSpanTextFromUpTo(Token open, Token close) { + int startOffset = open.getOffset(); + int endOffset = close.getOffset(); + if (open.getDocument() != close.getDocument()) + return open.getText(); + + String text; + try { + text = open.getDocument().get(startOffset, endOffset - startOffset).trim(); + } catch (BadLocationException e) { + text = open.getText(); + // TODO: error + } + + return text; + } + private void setSourceStart(AutoconfElement block, Token open) { + int offset = open.getOffset(); + block.setDocument(open.getDocument()); + block.setStartOffset(offset); + } + + private void setSourceEnd(AutoconfElement block, Token close) { + int offset = close.getOffset() + close.getLength(); + if (block.getDocument() != null && block.getDocument() != close.getDocument()) + throw new IllegalStateException(); + block.setDocument(close.getDocument()); + block.setEndOffset(offset); + } + + private void setSourceEndBefore(AutoconfElement block, Token close) { + int offset = close.getOffset(); + if (block.getDocument() != null && block.getDocument() != close.getDocument()) + throw new IllegalStateException(); + block.setDocument(close.getDocument()); + block.setEndOffset(offset); + } + + /** + * Parse a single statement (macro call or a shell construct). + * This can recursively invoke parseBlock() or parseStatement() to populate the tree. + * Whenever a token terminates a block, we check its validity and then throw BlockEndCondition. + * @param parent the parent into which to add statements. The type of this element is used + * to validate the legality of block closing tokens. + */ + protected void parseStatement(AutoconfElement parent) throws BlockEndCondition { + + boolean atStart = true; + + while (true) { + Token token = tokenizer.readToken(); + + switch (token.getType()) { + // 0. Check EOF + case ITokenConstants.EOF: + AutoconfElement element = parent; + while (element != null && !(element instanceof AutoconfRootElement)) { + handleError(element, token, AutoconfEditorMessages.getFormattedString(UNTERMINATED_CONSTRUCT, element.getName())); + element = element.getParent(); + } + throw new BlockEndCondition(token); + + + // 1. Check for end of statement + case ITokenConstants.EOL: + case ITokenConstants.SEMI: + return; + + + // 2. Check macro expansions + case ITokenConstants.WORD: + checkMacro(parent, token); + atStart = false; + break; + + // Check for shell constructs. These should appear at the start of a line + // or after a semicolon. If they don't, just report an error and continue, + // to be tolerant of our own lax parsing. + + // 3.a) Check dollar variables + case ITokenConstants.SH_DOLLAR: + // skip the next token + atStart = false; + token = tokenizer.readToken(); + continue; + + // 3.b) Look for if/else/elif/fi constructs, + // being tolerant of nesting problems by allowing + // stranded else/elif nodes but reporting errors. + case ITokenConstants.SH_IF: + checkLineStart(parent, token, atStart); + parseBlock(parent, token, new AutoconfIfElement()); + break; + + case ITokenConstants.SH_ELIF: + checkLineStart(parent, token, atStart); + checkBlockValidity( + parent, token, + new Class[] { AutoconfIfElement.class, AutoconfElifElement.class }, + INVALID_ELIF); + parseBlock(parent, token, new AutoconfElifElement()); + token = tokenizer.peekToken(); + throw new BlockEndCondition(token); + + case ITokenConstants.SH_ELSE: + checkLineStart(parent, token, atStart); + checkBlockValidity( + parent, token, + new Class[] { AutoconfIfElement.class, AutoconfElifElement.class }, + INVALID_ELSE); + parseBlock(parent, token, new AutoconfElseElement()); + token = tokenizer.peekToken(); + throw new BlockEndCondition(token); + + case ITokenConstants.SH_FI: + checkLineStart(parent, token, atStart); + checkBlockValidity( + parent, token, + new Class[] { AutoconfIfElement.class, AutoconfElifElement.class, AutoconfElseElement.class }, + INVALID_FI); + throw new BlockEndCondition(token); + + + // 4. Look for for/while loops + case ITokenConstants.SH_FOR: + checkLineStart(parent, token, atStart); + parseBlock(parent, token, new AutoconfForElement()); + break; + + case ITokenConstants.SH_WHILE: + checkLineStart(parent, token, atStart); + parseBlock(parent, token, new AutoconfWhileElement()); + break; + + case ITokenConstants.SH_UNTIL: + checkLineStart(parent, token, atStart); + parseBlock(parent, token, new AutoconfUntilElement()); + break; + + case ITokenConstants.SH_SELECT: + checkLineStart(parent, token, atStart); + parseBlock(parent, token, new AutoconfSelectElement()); + break; + + case ITokenConstants.SH_DONE: + checkLineStart(parent, token, atStart); + checkBlockValidity( + parent, token, + new Class[] { AutoconfForElement.class, AutoconfWhileElement.class, + AutoconfUntilElement.class, AutoconfSelectElement.class }, + INVALID_DONE); + throw new BlockEndCondition(token); + + // 5. Look for case statements + case ITokenConstants.SH_CASE: + checkLineStart(parent, token, atStart); + parseCaseBlock(parent, token, new AutoconfCaseElement()); + break; + + case ITokenConstants.SH_CASE_CONDITION_END: + checkBlockValidity( + parent, token, + new Class[] { AutoconfCaseConditionElement.class }, + IMPROPER_CASE_CONDITION); + throw new BlockEndCondition(token); + + case ITokenConstants.SH_ESAC: + checkLineStart(parent, token, atStart); + checkBlockValidity( + parent, token, + // note: we don't strictly recurse here, so accept either parent + new Class[] { AutoconfCaseElement.class, AutoconfCaseConditionElement.class }, + INVALID_ESAC); + throw new BlockEndCondition(token); + + + // 6. Check for HERE documents + case ITokenConstants.SH_HERE: + case ITokenConstants.SH_HERE_DASH: + + parseHERE(parent, token); + break; + } + } + } + + private void checkLineStart(AutoconfElement parent, Token token, boolean atStart) { + if (!atStart) { + handleError(parent, token, AutoconfEditorMessages.getFormattedString(INVALID_TERMINATION, token.getText())); + } + } + + /** + * Parse the Here document, whose control token is provided (SH_HERE or SH_HERE_DASH). + * Contents are thrown away except for any macro calls. + * @param parent + * @param controlToken + */ + private void parseHERE(AutoconfElement parent, Token controlToken) { + Token token = tokenizer.readToken(); + if (token.getType() == ITokenConstants.EOL || token.getType() == ITokenConstants.EOF) { + handleError(parent, token, + AutoconfEditorMessages.getString(INCOMPLETE_INLINE_MARKER)); + + } else { + String hereTag = token.getText(); + + boolean atEOL = false; + while (true) { + token = tokenizer.readToken(); + if (token.getType() == ITokenConstants.EOF) { + handleError(parent, token, AutoconfEditorMessages.getFormattedString(UNTERMINATED_CONSTRUCT, parent.getName())); + break; + } else if (token.getType() == ITokenConstants.EOL) { + atEOL = true; + } else { + if (atEOL && token.getText().equals(hereTag)) { + // only the end if it is also followed by EOL without any whitespace + Token eol = tokenizer.readToken(); + if (eol.getType() == ITokenConstants.EOL && eol.getOffset() == token.getOffset() + token.getLength()) { + break; + } + } + if (token.getType() == ITokenConstants.WORD) { + checkMacro(parent, token); + } + atEOL = false; + } + } + } + } + + /** + * Parse through a single expression up to a semicolon or newline. + * Add a macro call to the element or just return upon finding the desired token. + * Whenever a token terminates the expression, we check its validity and return the final token + * Throw {@link BlockEndCondition} if an unexpected token was found. + * @param parent the parent into which to add statements. The type of this element is used + * to validate the legality of block closing tokens. + */ + protected Token parseExpression(AutoconfElement parent) throws BlockEndCondition { + + while (true) { + Token token = tokenizer.readToken(); + + // 0. Ignore comments (tokenizer skipped them!) + + switch (token.getType()) { + // 1. Check EOF + case ITokenConstants.EOF: + throw new BlockEndCondition(token); + + // 2. Check macro expansions + case ITokenConstants.WORD: + token = checkMacro(parent, token); + break; + + // 3. Check expression terminators + case ITokenConstants.SEMI: + case ITokenConstants.EOL: + return token; + + // 4. Handle variables + case ITokenConstants.SH_DOLLAR: + token = tokenizer.readToken(); + break; + + case ITokenConstants.SH_IN: + // in 'for' or 'select, an 'in' may occur before 'do' + if (!(parent instanceof AutoconfForElement) + && !(parent instanceof AutoconfSelectElement)) + return token; + // fall through + + // 5. Abort on unexpected tokens + case ITokenConstants.SH_DO: + case ITokenConstants.SH_THEN: + handleError(parent, token, AutoconfEditorMessages.getFormattedString(INVALID_SPECIFIER, token.getText())); + tokenizer.unreadToken(token); + // close enough... + return token; + + case ITokenConstants.SH_ESAC: + case ITokenConstants.SH_CASE: + case ITokenConstants.SH_CASE_CONDITION_END: + case ITokenConstants.SH_FOR: + case ITokenConstants.SH_IF: + case ITokenConstants.SH_ELIF: + case ITokenConstants.SH_ELSE: + case ITokenConstants.SH_FI: + case ITokenConstants.SH_DONE: + handleError(parent, token, AutoconfEditorMessages.getFormattedString(UNTERMINATED_CONSTRUCT, parent.getName())); + tokenizer.unreadToken(token); + throw new BlockEndCondition(token); + } + } + } + + /** + * Parse through a single expression up to 'do'. + * Add a macro call to the element or just return upon finding the desired token. + * Whenever a token terminates the expression, we check its validity and then throw ExprEndCondition. + * Throw {@link BlockEndCondition} if an unexpected token was found. + * @param parent the parent into which to add statements. The type of this element is used + * to validate the legality of block closing tokens. + */ + protected Token parseForExpression(AutoconfElement parent) throws BlockEndCondition { + while (true) { + Token token = tokenizer.readToken(); + + // 0. Ignore comments (tokenizer skipped them!) + + // 1. Check EOF + if (token.getType() == ITokenConstants.EOF) { + throw new BlockEndCondition(token); + } + + // 2. Check macro expansions + else if (token.getType() == ITokenConstants.WORD) { + token = checkMacro(parent, token); + } + + // 3. Check expression terminators -- not ';' here, but 'do' + else if (token.getType() == ITokenConstants.SH_DO) { + tokenizer.unreadToken(token); + return tokenizer.peekToken(); + } + + // 4. Abort on unexpected tokens + else switch (token.getType()) { + case ITokenConstants.SH_THEN: + handleError(parent, token, AutoconfEditorMessages.getFormattedString(INVALID_SPECIFIER, token.getText())); + tokenizer.unreadToken(token); + // close enough... + //throw new ExprEndCondition(token); + return token; + + case ITokenConstants.SH_ESAC: + case ITokenConstants.SH_CASE: + case ITokenConstants.SH_CASE_CONDITION_END: + case ITokenConstants.SH_FOR: + case ITokenConstants.SH_IF: + case ITokenConstants.SH_ELIF: + case ITokenConstants.SH_ELSE: + case ITokenConstants.SH_FI: + case ITokenConstants.SH_DONE: + handleError(parent, token, AutoconfEditorMessages.getFormattedString(UNTERMINATED_CONSTRUCT, parent.getName())); + tokenizer.unreadToken(token); + throw new BlockEndCondition(token); + } + } + } + + /** + * Parse through a single expression up to 'in'. + * Add a macro call to the element or just return upon finding the desired token. + * Whenever a token terminates the expression, we check its validity and then throw ExprEndCondition. + * Throw {@link BlockEndCondition} if an unexpected token was found. + * @param parent the parent into which to add statements. The type of this element is used + * to validate the legality of block closing tokens. + */ + protected Token parseCaseExpression(AutoconfElement parent) throws BlockEndCondition { + while (true) { + Token token = tokenizer.readToken(); + + // 0. Ignore comments (tokenizer skipped them!) + + // 1. Check EOF + if (token.getType() == ITokenConstants.EOF) { + throw new BlockEndCondition(token); + } + + // 2. Check macro expansions + else if (token.getType() == ITokenConstants.WORD) { + token = checkMacro(parent, token); + } + + // 3. Check expression terminators + else if (parent instanceof AutoconfCaseElement && token.getType() == ITokenConstants.SH_IN) { + return token; + } + else if (parent instanceof AutoconfCaseConditionElement && token.getType() == ITokenConstants.RPAREN) { + return token; + } + + // 4. Abort on unexpected tokens + else switch (token.getType()) { + case ITokenConstants.SEMI: + case ITokenConstants.SH_IN: + case ITokenConstants.RPAREN: + case ITokenConstants.SH_DO: + case ITokenConstants.SH_THEN: + if (parent instanceof AutoconfCaseElement) + handleError(parent, token, AutoconfEditorMessages.getString(INVALID_IN)); + else + handleError(parent, token, AutoconfEditorMessages.getString(IMPROPER_CASE_CONDITION)); + // close enough... + return token; + + case ITokenConstants.SH_ESAC: + case ITokenConstants.SH_CASE: + case ITokenConstants.SH_CASE_CONDITION_END: + case ITokenConstants.SH_FOR: + case ITokenConstants.SH_IF: + case ITokenConstants.SH_ELIF: + case ITokenConstants.SH_ELSE: + case ITokenConstants.SH_FI: + case ITokenConstants.SH_DONE: + handleError(parent, token, AutoconfEditorMessages.getFormattedString(UNTERMINATED_CONSTRUCT, parent.getName())); + tokenizer.unreadToken(token); + throw new BlockEndCondition(token); + } + } + } + + /** + * Check a given close block token against the current parent by checking that + * the parent's class is one of classes, If a match happens, + * optionally push back the token if it will be used to parse new statements in the parent. + * Report an error if the parent is not one of the expected kinds. + * @param parent + * @param token + * @param classes + */ + private void checkBlockValidity( + AutoconfElement parent, + Token token, + Class<?>[] classes, + String errorMessage) { + for (int i = 0; i < classes.length; i++) { + if (classes[i].isInstance(parent)) { + return; + } + } + + // not a match + handleError(parent, token, + AutoconfEditorMessages.getFormattedString(errorMessage, parent.getName(), token.getText())); + } + + /** + * Check whether the given token is part of a macro, and parse it as such + * if necessary. + * @param parent + * @param token + * @return Token last read for the macro call + */ + private Token checkMacro(AutoconfElement parent, Token token) { + String name = token.getText(); + + boolean hasArguments = tokenizer.peekToken().getType() == ITokenConstants.LPAREN; + if (macroDetector != null && macroDetector.isMacroIdentifier(name)) { + // ok + } else if (m4builtins.contains(name)) { + // all of these except dnl take arguments + if (!name.equals("dnl") && !hasArguments) + return token; + } else { + return token; + } + + AutoconfMacroElement macro = new AutoconfMacroElement(name); + token = parseMacro(macro, token); + + // handle special macros here + if ("dnl".equals(name)) { + // consume to EOL + while (true) { + token = tokenizer.readToken(); + if (token.getType() == ITokenConstants.EOF || token.getType() == ITokenConstants.EOL) + break; + } + + // ignore macro entirely + macro = null; + } else if ("changequote".equals(name)) { + // change quote delimiters + validateMacroParameterCount(macro, token, 2); + + // GNU behavior for invalid argument count + String parm0 = "`"; + String parm1 = "'"; + if (macro.getParameterCount() >= 1) + parm0 = macro.getParameter(0); + if (macro.getParameterCount() >= 2) + parm1 = macro.getParameter(1); + + tokenizer.setM4Quote(parm0, parm1); + } else if ("changecom".equals(name)) { + // change comment delimiters + validateMacroParameterCount(macro, token, 2); + + // GNU behavior for invalid argument count + String parm0 = "#"; + String parm1 = "\n"; + if (macro.getParameterCount() >= 1) + parm0 = macro.getParameter(0); + if (macro.getParameterCount() >= 2) + parm1 = macro.getParameter(1); + + tokenizer.setM4Comment(parm0, parm1); + } + + if (macro != null) { + parent.addChild(macro); + } + + // now validate that the macro is properly terminated + if (!(parent instanceof AutoconfMacroArgumentElement) + && !(parent instanceof AutoconfMacroElement) + && !(parent instanceof AutoconfForElement)) { + Token peek = tokenizer.peekToken(); + if (peek.getType() == ITokenConstants.RPAREN) { + handleError(macro, peek, AutoconfEditorMessages.getString(UNMATCHED_RIGHT_PARENTHESIS)); + } + } + + return token; + } + + private void validateMacroParameterCount(AutoconfMacroElement macro, Token token, int count) { + if (macro.getParameterCount() < count) { + handleError(macro, token, AutoconfEditorMessages.getFormattedString("M4MacroArgsTooFew", macro.getName(), new Integer(2))); + } else if (macro.getParameterCount() > count) { + handleError(macro, token, AutoconfEditorMessages.getFormattedString("M4MacroArgsTooMany", macro.getName(), new Integer(2))); + } + } + + /** + * Start parsing a macro call at a suspected macro expansion location. + * @param macro + * @param line the line containing the start of the + * @param parent + * @return last token parsed + */ + protected Token parseMacro(AutoconfMacroElement macro, Token macroName) { + setSourceStart(macro, macroName); + + // parse any arguments + tokenizer.setM4Context(true); + + Token token = tokenizer.readToken(); + if (token.getType() == ITokenConstants.LPAREN) { + token = parseMacroArguments(macro, token); + setSourceEnd(macro, token); + } else { + tokenizer.unreadToken(token); + setSourceEnd(macro, macroName); + } + + tokenizer.setM4Context(false); + + // validate macro arguments? + if (macroValidator != null) { + try { + macroValidator.validateMacroCall(macro); + } catch (ParseException e) { + errorHandler.handleError(e); + } + } + + return token; + } + + /** + * Parse the arguments for the given macro. These are not interpreted as shell + * constructs but just as text with possibly more macro expansions inside. + * @param macro + * @return final token (')') + */ + protected Token parseMacroArguments(AutoconfMacroElement macro, Token lparen) { + Token argStart = null; + Token argEnd = null; + Token token; + + // When parsing, we want to ignore the whitespace around the arguments. + // So, instead of taking the source range "between" a parenthesis and a comma, + // track the exact tokens forming the start and end of an argument, defaulting + // to the borders of the parentheses and commas if no text is included. + + StringBuffer argBuffer = new StringBuffer(); + AutoconfMacroArgumentElement arg = new AutoconfMacroArgumentElement(); + + while (true) { + token = tokenizer.readToken(); + + if (token.getType() == ITokenConstants.EOL) { + if (argBuffer.length() > 0) + argBuffer.append(token.getText()); + continue; + } + + if (token.getType() == ITokenConstants.COMMA + || token.getType() == ITokenConstants.RPAREN + || token.getType() == ITokenConstants.EOF) { + + arg.setName(argBuffer.toString()); + argBuffer.setLength(0); + + if (argStart != null && argEnd != null) { + setSourceStart(arg, argStart); + setSourceEnd(arg, argEnd); + } else if (argEnd != null) { + setSourceStart(arg, argStart); + setSourceEndBefore(arg, token); + } else { + // empty argument + setSourceStart(arg, token); + setSourceEndBefore(arg, token); + } + + macro.addChild(arg); + + if (token.getType() != ITokenConstants.COMMA) + break; + + argStart = null; + argEnd = null; + + arg = new AutoconfMacroArgumentElement(); + + } else { + if (argStart == null) { + argStart = token; + } + argEnd = token; + + if (argBuffer.length() > 0 && token.followsSpace()) + argBuffer.append(' '); + argBuffer.append(token.getText()); + + // handle nested macro calls in arguments + if (token.getType() == ITokenConstants.WORD) { + argEnd = checkMacro(arg, token); + } + } + } + + if (token.getType() != ITokenConstants.RPAREN) { + handleError(macro, token, AutoconfEditorMessages.getString(UNMATCHED_LEFT_PARENTHESIS)); + } + + // note: moved 15-char truncation to AutoconfLabelProvider + AutoconfElement[] children = macro.getChildren(); + if (children.length > 0) + macro.setVar(children[0].getVar()); + + return token; + } + + + + protected void handleError(AutoconfElement element, Token token, String message) { + handleMessage(element, token, message, IMarker.SEVERITY_ERROR); + } + protected void handleWarning(AutoconfElement element, Token token, String message) { + handleMessage(element, token, message, IMarker.SEVERITY_WARNING); + } + protected void handleMessage(AutoconfElement element, Token token, String message, int severity) { + if (errorHandler != null) { + int lineNumber = 0; + int startColumn = 0; + int endColumn = 0; + try { + lineNumber = token.getDocument().getLineOfOffset(token.getOffset()); + int lineOffs = token.getDocument().getLineOffset(lineNumber); + startColumn = token.getOffset() - lineOffs; + endColumn = startColumn + token.getLength(); + } catch (BadLocationException e) { + // Don't care if we blow up trying to issue marker + } + errorHandler.handleError(new ParseException( + message, + token.getOffset(), + token.getOffset() + token.getLength(), + lineNumber, + startColumn, endColumn, + severity)); + } + } + + public IAutoconfErrorHandler getErrorHandler() { + return errorHandler; + } +} + diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfRootElement.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfRootElement.java new file mode 100644 index 0000000000..105d00b88d --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfRootElement.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +public class AutoconfRootElement extends AutoconfElement { + + public AutoconfRootElement() { + super(""); //$NON-NLS-1$ + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfSelectElement.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfSelectElement.java new file mode 100644 index 0000000000..aded97c871 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfSelectElement.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +public class AutoconfSelectElement extends AutoconfElement { + + public AutoconfSelectElement() { + super("select"); + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfTokenizer.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfTokenizer.java new file mode 100644 index 0000000000..a34cbb2448 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfTokenizer.java @@ -0,0 +1,434 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ed Swartz (Nokia) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; + + +/** + * This tokenizer traverses autotools-style text (m4 or configure.ac) to support the + * autoconf parser. It tracks the current context (m4 macro call or shell commands) + * to detect appropriate tokens, and tracks the m4 current quote style as well. + * <p> + * In m4 mode, its primary purpose is to find word boundaries, detect comments and quoted + * strings, and to find the macro punctuation tokens. It will not interpret anything + * (e.g. '$1' inside a macro) -- this is up to the parser. + * <p> + * In shell script mode, its primary purpose is to identify enough + * tokens to get a general picture of the structure of source for use by the autoconf + * parser. This isn't intended to be used for full shell script parsing. In fact, + * aside from the known tokens and identifiers, only individual characters will be returned. + * <p> + * Both modes know about "words" or identifiers and use the same syntax to detect these. + * It's expected that the parser will detect a word as a macro or possible macro and + * switch the mode of the tokenizer to fit. The parser should invoke "setM4Context(...)" + * (and "unreadToken" if necessary) to switch modes. + * @author eswartz + * + */ +public class AutoconfTokenizer { + + private static final String UNTERMINATED_STRING = "UnterminatedString"; //$NON-NLS-1$ + public static final String UNMATCHED_RIGHT_QUOTE = "UnmatchedRightQuote"; //$NON-NLS-1$ + public static final String UNMATCHED_LEFT_QUOTE = "UnmatchedLeftQuote"; //$NON-NLS-1$ + public static final String UNMATCHED_CLOSE_COMMENT = "UnmatchedCloseComment"; //$NON-NLS-1$ + + private IDocument document; + private int offset; + private String m4OpenQuote; + private String m4CloseQuote; + private String m4OpenComment; + private String m4CloseComment; + private char[] chars; + private int startOffset; + private boolean isM4Context; + private Token eofToken; + private IAutoconfErrorHandler errorHandler; + + /** Create a tokenizer for a document. */ + public AutoconfTokenizer(IDocument document, IAutoconfErrorHandler errorHandler) { + if (document == null /* || macroDetector == null*/) + throw new IllegalArgumentException(); + this.document = document; + this.errorHandler = errorHandler; + + this.chars = document.get().toCharArray(); + this.offset = 0; + + this.eofToken = new Token(ITokenConstants.EOF, "", document, chars.length, 0); + + this.m4OpenQuote = "`"; + this.m4CloseQuote = "'"; + this.m4OpenComment = "#"; + this.m4CloseComment = "\n"; + } + + /** + * Tell whether the tokenizer considers itself to be in an m4 context. + * This determines what kinds of tokens it returns. + * @return + */ + public boolean isM4Context() { + return isM4Context; + } + + /** + * Switch the tokenizer into or out of m4 context. + * @return + */ + public void setM4Context(boolean flag) { + isM4Context = flag; + } + + /** + * Set the m4 quote delimiters + */ + public void setM4Quote(String open, String close) { + this.m4OpenQuote = open; + this.m4CloseQuote = close; + } + + /** + * Set the m4 comment delimiters + */ + public void setM4Comment(String open, String close) { + this.m4OpenComment = open; + this.m4CloseComment = close; + } + + /** Push back the given token. This allows the tokenizer to restart from its start position, + * potentially in a different context. */ + public void unreadToken(Token token) { + if (token.getLength() > 0 && offset == token.getOffset()) + throw new IllegalStateException(); + offset = token.getOffset(); + } + + /** Read the next token. Returns an EOF token at EOF. */ + public Token readToken() { + if (offset >= chars.length) + return eofToken; + + char ch = chars[offset]; + + // skip whitespace (but not EOL) + while (isWhitespace(ch)) { + offset++; + if (offset >= chars.length) + return eofToken; + ch = chars[offset]; + } + + // in shell mode, strip comments up to eol + if (!isM4Context && ch == '#') { + while (offset < chars.length) { + ch = chars[offset]; + if (ch == '\n') + break; + offset++; + } + + // keep inside doc if we didn't find that EOL + if (offset >= chars.length) + offset--; + } + + startOffset = offset; + StringBuffer buffer = new StringBuffer(); + + // check EOL + if (ch == '\r' || ch == '\n') { + buffer.append(ch); + offset++; + if (ch == '\r' && offset < chars.length && chars[offset] == '\n') { + buffer.append(chars[offset++]); + } + return makeToken(ITokenConstants.EOL, buffer.toString()); + } + + // TODO: this parser always uses fixed logic for identifier reading, ignoring m4's "changeword" + if (isLeadIdentifierChar(ch)) { + return parseWord(ch); + } + + // check comments and quotes + if (isM4Context) { + if (lookAhead(m4OpenComment)) { + boolean found = false; + // keep reading until the close comment (these are NOT nested) + while (offset < chars.length) { + if (lookAhead(m4CloseComment)) { + found = true; + break; + } + offset++; + } + if (!found) { + handleError(startOffset, offset, AutoconfEditorMessages.getFormattedString(UNMATCHED_CLOSE_COMMENT, + m4CloseComment.equals("\n") ? "newline" : m4CloseComment)); //$NON-NLS-1$ + } + return makeToken(ITokenConstants.M4_COMMENT); + } + + if (lookAhead(m4OpenQuote)) { + return parseQuote(); + } + } + + // check shell punctuation + if (!isM4Context) { + if (ch == ';' && offset + 1 < chars.length && chars[offset + 1] == ';') { + offset += 2; + return makeToken(ITokenConstants.SH_CASE_CONDITION_END); + } + if (ch == '<' && offset + 1 < chars.length && chars[offset + 1] == '<') { + offset += 2; + if (offset < chars.length && chars[offset] == '-') { + offset++; + return makeToken(ITokenConstants.SH_HERE_DASH); + } else { + return makeToken(ITokenConstants.SH_HERE); + } + } + switch (ch) { + case '$': + offset++; + return makeToken(ITokenConstants.SH_DOLLAR); + case '[': + offset++; + return makeToken(ITokenConstants.SH_LBRACKET); + case ']': + offset++; + return makeToken(ITokenConstants.SH_RBRACKET); + case '{': + offset++; + return makeToken(ITokenConstants.SH_LBRACE); + case '}': + offset++; + return makeToken(ITokenConstants.SH_RBRACE); + case '\'': + return parseString(ITokenConstants.SH_STRING_SINGLE, ch); + case '\"': + return parseString(ITokenConstants.SH_STRING_DOUBLE, ch); + case '`': + return parseString(ITokenConstants.SH_STRING_BACKTICK, ch); + } + } + + // check common punctuation + if (ch == ';') { + offset++; + return makeToken(ITokenConstants.SEMI); + } + if (ch == ',') { + offset++; + return makeToken(ITokenConstants.COMMA); + } + if (ch == '(') { + offset++; + return makeToken(ITokenConstants.LPAREN); + } + if (ch == ')') { + offset++; + return makeToken(ITokenConstants.RPAREN); + } + + // unknown text + offset++; + return makeToken(ITokenConstants.TEXT); + } + + private Token parseWord(char ch) { + StringBuffer buffer = new StringBuffer(); + + buffer.append(ch); + offset++; + do { + if (offset >= chars.length) + break; + ch = chars[offset]; + if (!isIdentifierChar(ch)) + break; + buffer.append(ch); + offset++; + } while (true); + + String text = buffer.toString(); + + if (!isM4Context) { + // detect sh tokens + if ("case".equals(text)) + return makeToken(ITokenConstants.SH_CASE, text); + if ("in".equals(text)) + return makeToken(ITokenConstants.SH_IN, text); + if ("esac".equals(text)) + return makeToken(ITokenConstants.SH_ESAC, text); + if ("while".equals(text)) + return makeToken(ITokenConstants.SH_WHILE, text); + if ("select".equals(text)) + return makeToken(ITokenConstants.SH_SELECT, text); + if ("until".equals(text)) + return makeToken(ITokenConstants.SH_UNTIL, text); + if ("for".equals(text)) + return makeToken(ITokenConstants.SH_FOR, text); + if ("do".equals(text)) + return makeToken(ITokenConstants.SH_DO, text); + if ("done".equals(text)) + return makeToken(ITokenConstants.SH_DONE, text); + if ("if".equals(text)) + return makeToken(ITokenConstants.SH_IF, text); + if ("then".equals(text)) + return makeToken(ITokenConstants.SH_THEN, text); + if ("else".equals(text)) + return makeToken(ITokenConstants.SH_ELSE, text); + if ("elif".equals(text)) + return makeToken(ITokenConstants.SH_ELIF, text); + if ("fi".equals(text)) + return makeToken(ITokenConstants.SH_FI, text); + } + + // other identifier-looking word + return makeToken(ITokenConstants.WORD, text); + } + + private Token parseQuote() { + // read text, honoring nested quotes, but don't put the outermost quotes in the token + + StringBuffer buffer = new StringBuffer(); + + int quoteLevel = 1; + // keep reading until the close quote + while (offset < chars.length) { + if (lookAhead(m4CloseQuote)) { + quoteLevel--; + if (quoteLevel == 0) + break; + buffer.append(m4CloseQuote); + } else if (lookAhead(m4OpenQuote)) { + buffer.append(m4OpenQuote); + quoteLevel++; + } else { + buffer.append(chars[offset]); + offset++; + } + } + + if (quoteLevel > 0) { + handleError(startOffset, offset, AutoconfEditorMessages.getFormattedString(UNMATCHED_LEFT_QUOTE, m4CloseQuote)); + } else if (quoteLevel < 0) { + handleError(startOffset, offset, AutoconfEditorMessages.getFormattedString(UNMATCHED_RIGHT_QUOTE, m4OpenQuote)); + } + + return makeToken(ITokenConstants.M4_STRING, buffer.toString()); + } + + private Token parseString(int type, char terminal) { + startOffset = offset; + offset++; + + StringBuffer buffer = new StringBuffer(); + + char ch = 0; + while (offset < chars.length) { + ch = chars[offset++]; + if (ch == '\\') { + if (offset < chars.length) + buffer.append(chars[offset++]); + else + buffer.append(ch); + } else if (ch == terminal) { + break; + } else { + buffer.append(ch); + } + } + + if (ch != terminal) { + handleError(startOffset, offset, AutoconfEditorMessages.getFormattedString(UNTERMINATED_STRING, "" + ch)); + } + + return makeToken(type, buffer.toString()); + } + + private void handleError(int start, int end, + String message) { + if (errorHandler != null) { + int lineNumber = 0; + int startColumn = 0; + int endColumn = 0; + try { + lineNumber = document.getLineOfOffset(start); + int lineOffs = document.getLineOffset(lineNumber); + startColumn = start - lineOffs; + endColumn = end - lineOffs; + } catch (BadLocationException e) { + // Don't care if we blow up trying to issue marker + } + errorHandler.handleError(new ParseException( + message, + start, end, + lineNumber, + startColumn, endColumn, + IMarker.SEVERITY_ERROR)); + } + } + + /** + * Look ahead for the given string. If found, return true, and have + * offset updated. Otherwise, return false with offset unchanged. + * @param keyword + * @param text + * @return + */ + private boolean lookAhead(String keyword) { + int length = keyword.length(); + if (offset + length > chars.length) { + return false; + } + for (int idx = 0; idx < length; idx++) { + if (chars[offset + idx] != keyword.charAt(idx)) + return false; + } + offset += length; + return true; + } + + private boolean isWhitespace(char ch) { + return ch == ' ' || ch == '\t' || ch == '\f'; + } + + private Token makeToken(int type) { + return new Token(type, + new String(chars, startOffset, offset - startOffset), + document, startOffset, offset - startOffset); + } + + private Token makeToken(int type, String text) { + return new Token(type, text, document, startOffset, offset - startOffset); + } + + private boolean isIdentifierChar(char ch) { + return isLeadIdentifierChar(ch) || (ch >= '0' && ch <= '9'); + } + + private boolean isLeadIdentifierChar(char ch) { + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_'; + } + + public Token peekToken() { + Token token = readToken(); + unreadToken(token); + return token; + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfUntilElement.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfUntilElement.java new file mode 100644 index 0000000000..bf6eb597eb --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfUntilElement.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +public class AutoconfUntilElement extends AutoconfElement { + + public AutoconfUntilElement() { + super("until"); + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfWhileElement.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfWhileElement.java new file mode 100644 index 0000000000..8d247f73d3 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/AutoconfWhileElement.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +public class AutoconfWhileElement extends AutoconfElement { + + public AutoconfWhileElement() { + super("while"); + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/IAutoconfErrorHandler.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/IAutoconfErrorHandler.java new file mode 100644 index 0000000000..1363240bbc --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/IAutoconfErrorHandler.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ed Swartz (Nokia) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + + +/** + * Clients implement this interface to handle errors encountered while parsing. + * @author eswartz + * + */ +public interface IAutoconfErrorHandler { + + /** + * Handle an exception associated with the given element + * @param exception the exception to handle; has a line number + * at the time of call + */ + void handleError(ParseException exception); +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/IAutoconfMacroDetector.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/IAutoconfMacroDetector.java new file mode 100644 index 0000000000..e4387316e5 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/IAutoconfMacroDetector.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ed Swartz (Nokia) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + + +/** + * Clients implement this interface to identify what identifiers represent + * macros for the autoconf tree. + * @author eswartz + * + */ +public interface IAutoconfMacroDetector { + + /** + * Tell if this identifier should be treated as an m4 macro call. + * The identifier has already been judged to be a valid candidate + * (i.e. it's not quoted). + * @param name the string to check + */ + boolean isMacroIdentifier(String name); +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/IAutoconfMacroValidator.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/IAutoconfMacroValidator.java new file mode 100644 index 0000000000..2a54ee4773 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/IAutoconfMacroValidator.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ed Swartz (Nokia) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + + +/** + * Clients implement this interface to validate macro calls. + * @author eswartz + * + */ +public interface IAutoconfMacroValidator { + + /** + * Validate the given macro call. + * @param element macro call, never <code>null</code> + * @throws ParseException if the call doesn't match the expected number of elements + */ + void validateMacroCall(AutoconfMacroElement element) throws ParseException; +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/IMacroDetector.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/IMacroDetector.java new file mode 100644 index 0000000000..b225942cfe --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/IMacroDetector.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ed Swartz (Nokia) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +/** + * Clients implement this interface to detect whether a given identifier + * represents a known or potential macro in m4 or configure.ac text. + * @author eswartz + * + */ +public interface IMacroDetector { + boolean isMacro(String identifier); +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/ITokenConstants.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/ITokenConstants.java new file mode 100644 index 0000000000..b665115f8d --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/ITokenConstants.java @@ -0,0 +1,87 @@ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +public interface ITokenConstants { + + /** end of file */ + public static final int EOF = 0; + /** end of line */ + public static final int EOL = 1; + + /** an open parenthesis */ + public static final int LPAREN = 2; + /** a close parenthesis */ + public static final int RPAREN = 3; + /** a comma */ + public static final int COMMA = 4; + /** a semicolon */ + public static final int SEMI = 5; + + /** a word (either m4 word or shell identifier-looking word) */ + public static final int WORD = 6; + + /** other text (usually punctuation or number, one char at a time) */ + public static final int TEXT = 7; + + /** an m4 string (the text does not contain the outermost quotes) */ + public static final int M4_STRING = 21; + /** an m4 comment (as determined by changecomment, NOT dnl) */ + public static final int M4_COMMENT = 22; + + /** the sh 'if' token */ + public static final int SH_IF = 40; + /** the sh 'then' token */ + public static final int SH_THEN = 41; + /** the sh 'else' token */ + public static final int SH_ELSE = 42; + /** the sh 'elif' token */ + public static final int SH_ELIF = 43; + /** the sh 'fi' token */ + public static final int SH_FI = 44; + + /** the sh 'while' token */ + public static final int SH_WHILE = 45; + /** the sh 'for' token */ + public static final int SH_FOR = 46; + /** the sh 'select' token */ + public static final int SH_SELECT = 47; + /** the sh 'until' token */ + public static final int SH_UNTIL = 48; + /** the sh 'do' token */ + public static final int SH_DO = 49; + /** the sh 'done' token */ + public static final int SH_DONE = 50; + /** the sh 'case' token */ + + public static final int SH_CASE = 51; + /** the sh 'in' token */ + public static final int SH_IN = 52; + /** the sh ';;' token */ + public static final int SH_CASE_CONDITION_END = 53; + /** the sh 'esac' token */ + public static final int SH_ESAC = 54; + + /** the sh '$' token */ + public static final int SH_DOLLAR = 60; + + /** the sh '{' token */ + public static final int SH_LBRACE = 61; + /** the sh '}' token */ + public static final int SH_RBRACE = 62; + /** the sh '[' token */ + public static final int SH_LBRACKET = 63; + /** the sh ']' token */ + public static final int SH_RBRACKET = 64; + + /** the sh '<<' token */ + public static final int SH_HERE = 65; + /** the sh '<<-' token */ + public static final int SH_HERE_DASH = 66; + /** an sh double-quoted string */ + public static final int SH_STRING_DOUBLE = 67; + /** an sh single-quoted string */ + public static final int SH_STRING_SINGLE = 68; + /** an sh backtick-quoted string */ + public static final int SH_STRING_BACKTICK = 69; + + +}
\ No newline at end of file diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/ParseException.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/ParseException.java new file mode 100644 index 0000000000..f0bc442469 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/ParseException.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +public class ParseException extends Exception { + + static final long serialVersionUID = 1; + String message; + int severity; + int lineNumber; + int startColumn; + int endColumn; + private int startOffset; + private int endOffset; + public int getEndColumn() { + return endColumn; + } + public void setEndColumn(int endColumn) { + this.endColumn = endColumn; + } + public int getLineNumber() { + return lineNumber; + } + public void setLineNumber(int lineNumber) { + this.lineNumber = lineNumber; + } + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + public int getStartColumn() { + return startColumn; + } + public void setStartColumn(int startColumn) { + this.startColumn = startColumn; + } + public ParseException(String message, + int startOffset, int endOffset, + int lineNumber, int startColumn, int endColumn, int severity) { + super(); + this.message = message; + this.startOffset = startOffset; + this.endOffset = endOffset; + this.lineNumber = lineNumber; + this.startColumn = startColumn; + this.endColumn = endColumn; + this.severity = severity; + } + public int getSeverity() { + return severity; + } + public void setSeverity(int severity) { + this.severity = severity; + } + public int getStartOffset() { + return startOffset; + } + public int getEndOffset() { + return endOffset; + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/Token.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/Token.java new file mode 100644 index 0000000000..9690363b4b --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/editors/parser/Token.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ed Swartz (Nokia) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.cdt.autotools.ui.editors.parser; + +import org.eclipse.jface.text.IDocument; + +/** + * A single token parsed from an autotools-style file. This represents m4 and sh + * tokens. Punctuation characters shared by both are not in a namespace. + * + * @author eswartz + * + */ +public class Token implements ITokenConstants { + /** Type: + * @see ITokenConstants + */ + final int type; + /** + * Text of token, possibly interpreted or reduced from original characters + */ + final String text; + /** + * Offset of token before interpretation + */ + final int offset; + /** + * Length of token before interpretation + */ + final int length; + /** + * The document providing the text + */ + final IDocument document; + + public Token(int type, String text, IDocument document, int offset, int length) { + this.type = type; + this.text = text; + this.document = document; + this.offset = offset; + this.length = length; + } + + public String toString() { + return text; + } + + public int getType() { + return type; + } + + public String getText() { + return text; + } + + public IDocument getDocument() { + return document; + } + + public int getOffset() { + return offset; + } + + public int getLength() { + return length; + } + + public boolean followsSpace() { + char[] text = document.get().toCharArray(); + if (offset == 0) + return false; + return (" \t\r\n\f".indexOf(text[offset - 1]) >= 0); + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsBuildPropertyPage.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsBuildPropertyPage.java new file mode 100644 index 0000000000..8bc173fe35 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsBuildPropertyPage.java @@ -0,0 +1,243 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.properties; + +import org.eclipse.cdt.core.settings.model.ICResourceDescription; +import org.eclipse.cdt.managedbuilder.ui.properties.AbstractCBuildPropertyTab; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.linuxtools.cdt.autotools.AutotoolsMakefileBuilder; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + + +public class AutotoolsBuildPropertyPage extends AbstractCBuildPropertyTab { + + private String TRUE = "true"; // $NON-NLS-1$ + private String FALSE = "false"; // $NON-NLS-1$ + private String SCANNERMAKEW_LABEL = "ScannerMakeW.label"; // $NON-NLS-1$ + private String SCANNERMAKEW_TOOLTIP = "ScannerMakeW.tooltip"; // $NON-NLS-1$ + + protected Button fCleanDelete; + protected Button fCleanMake; + protected Text fCleanMakeTarget; + protected Button fScannerMakeW; + + private IProject getProject() { + return (IProject)getCfg().getManagedProject().getOwner(); + } + + public boolean canBeVisible() { + return AutotoolsMakefileBuilder.hasTargetBuilder(getProject()); + } + + public void createControls(Composite parent) { + super.createControls(parent); + Composite composite= usercomp; + // assume parent page uses griddata + GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_CENTER | GridData.VERTICAL_ALIGN_FILL | GridData.FILL_HORIZONTAL); + composite.setLayoutData(gd); + GridLayout layout= new GridLayout(); + layout.numColumns= 2; + //PixelConverter pc= new PixelConverter(composite); + //layout.verticalSpacing= pc.convertHeightInCharsToPixels(1) / 2; + composite.setLayout(layout); + + Group g = new Group(composite, SWT.SHADOW_ETCHED_IN); + g.setText(AutotoolsPropertyMessages.getString("CleanBehavior.title")); + gd = new GridData(GridData.HORIZONTAL_ALIGN_CENTER | GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + g.setLayoutData(gd); + layout= new GridLayout(); + layout.numColumns= 2; + g.setLayout(layout); + + fCleanDelete = new Button(g, SWT.RADIO); + fCleanDelete.setText(AutotoolsPropertyMessages.getString("CleanDelete.label")); + gd= new GridData(); + gd.horizontalAlignment= GridData.BEGINNING; + gd.horizontalSpan = 2; + fCleanDelete.setLayoutData(gd); + fCleanMake = new Button(g, SWT.RADIO); + fCleanMake.setText(AutotoolsPropertyMessages.getString("CleanMake.label")); + gd= new GridData(); + gd.horizontalAlignment= GridData.BEGINNING; + gd.horizontalSpan = 2; + fCleanMake.setLayoutData(gd); + + Label label = new Label(g, SWT.LEFT); + label.setText(AutotoolsPropertyMessages.getString("CleanMakeTarget.label")); + gd= new GridData(); + gd.horizontalAlignment= GridData.BEGINNING; + label.setLayoutData(gd); + + fCleanMakeTarget = new Text(g, SWT.SINGLE | SWT.BORDER); + fCleanMakeTarget.setText(AutotoolsPropertyConstants.CLEAN_MAKE_TARGET_DEFAULT); + gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); + fCleanMakeTarget.setLayoutData(gd); + + fCleanDelete.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + fCleanMake.setSelection(false); + fCleanDelete.setSelection(true); + fCleanMakeTarget.setEnabled(false); + } + + public void widgetDefaultSelected(SelectionEvent e) { + // do nothing + } + }); + + fCleanMake.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + fCleanDelete.setSelection(false); + fCleanMake.setSelection(true); + fCleanMakeTarget.setEnabled(true); + } + + public void widgetDefaultSelected(SelectionEvent e) { + // do nothing + } + }); + + fCleanMakeTarget.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + if (fCleanMakeTarget.getText().equals("")) { // $NON-NLS-1$ + // FIXME: should probably issue warning here, but how? + } + } + }); + + fScannerMakeW = new Button(composite, SWT.LEFT | SWT.CHECK); + fScannerMakeW.setText(AutotoolsPropertyMessages.getString(SCANNERMAKEW_LABEL)); + fScannerMakeW.setToolTipText(AutotoolsPropertyMessages.getString(SCANNERMAKEW_TOOLTIP)); + gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING); + fScannerMakeW.setLayoutData(gd); + + initialize(); + } + + protected void performOK() { + IProject project = getProject(); + if (fCleanDelete.getSelection()) { + try { + project.setPersistentProperty(AutotoolsPropertyConstants.CLEAN_DELETE, TRUE); + } catch (CoreException ce) { + // FIXME: what can we do here? + } + } else { + try { + project.setPersistentProperty(AutotoolsPropertyConstants.CLEAN_DELETE, FALSE); + } catch (CoreException ce) { + // FIXME: what can we do here? + } + try { + project.setPersistentProperty(AutotoolsPropertyConstants.CLEAN_MAKE_TARGET, fCleanMakeTarget.getText()); + } catch (CoreException ce) { + // FIXME: what can we do here? + } + } + boolean setScannerInfoDirty = false; + try { + // Get old scanner method setting to see if it has changed. + String oldScannerMakeW = project.getPersistentProperty(AutotoolsPropertyConstants.SCANNER_USE_MAKE_W); + if (fScannerMakeW.getSelection()) { + project.setPersistentProperty(AutotoolsPropertyConstants.SCANNER_USE_MAKE_W, TRUE); + if (oldScannerMakeW == null || !oldScannerMakeW.equals(TRUE)) + setScannerInfoDirty = true; + } else { + project.setPersistentProperty(AutotoolsPropertyConstants.SCANNER_USE_MAKE_W, null); + if (oldScannerMakeW != null && oldScannerMakeW.equals(TRUE)) + setScannerInfoDirty = true; + } + } catch (CoreException ce) { + ce.printStackTrace(); // FIXME: what can we do here? + } + // If the scanner info method changes, we must mark the current data as + // dirty so it will be recalculated. + if (setScannerInfoDirty) { + try { + project.setSessionProperty(AutotoolsPropertyConstants.SCANNER_INFO_DIRTY, Boolean.TRUE); + } catch (CoreException ce2) { + // FIXME: what can we do here? + } + } + } + + protected void performApply(ICResourceDescription src, ICResourceDescription dst) { + performOK(); + } + + protected void performDefaults() { + fCleanDelete.setSelection(false); + fCleanMake.setSelection(true); + fCleanMakeTarget.setText(AutotoolsPropertyConstants.CLEAN_MAKE_TARGET_DEFAULT); + fCleanMakeTarget.setEnabled(true); + fScannerMakeW.setSelection(true); + } + + public void updateData(ICResourceDescription cfgd) { + // what to do here? + } + + public void updateButtons() { + // what to do here? + } + + public void setVisible (boolean b) { + super.setVisible(b); + } + + private void initialize() { + IProject project = getProject(); + String cleanDelete = null; + String cleanMakeTarget = null; + String scannerMakeW = null; + try { + cleanDelete = project.getPersistentProperty(AutotoolsPropertyConstants.CLEAN_DELETE); + cleanMakeTarget = project.getPersistentProperty(AutotoolsPropertyConstants.CLEAN_MAKE_TARGET); + scannerMakeW = project.getPersistentProperty(AutotoolsPropertyConstants.SCANNER_USE_MAKE_W); + } catch (CoreException e) { + // do nothing + } + + if (cleanMakeTarget == null) { + cleanMakeTarget = AutotoolsPropertyConstants.CLEAN_MAKE_TARGET_DEFAULT; + } + fCleanMakeTarget.setText(cleanMakeTarget); + + if (cleanDelete == null || cleanDelete.equals(FALSE)) { + fCleanDelete.setSelection(false); + fCleanMake.setSelection(true); + fCleanMakeTarget.setEnabled(true); + } else { + fCleanDelete.setSelection(true); + fCleanMake.setSelection(false); + fCleanMakeTarget.setEnabled(false); + } + + if (scannerMakeW == null || !scannerMakeW.equals(TRUE)) { + fScannerMakeW.setSelection(false); + } else + fScannerMakeW.setSelection(true); + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsEditorPropertyPage.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsEditorPropertyPage.java new file mode 100644 index 0000000000..9ee6a4bf7a --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsEditorPropertyPage.java @@ -0,0 +1,278 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.properties; + +import org.eclipse.cdt.core.settings.model.ICResourceDescription; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.cdt.ui.newui.AbstractCPropertyTab; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.linuxtools.cdt.autotools.AutotoolsPlugin; +import org.eclipse.linuxtools.internal.cdt.autotools.ui.preferences.AutotoolsEditorPreferenceConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + + +public class AutotoolsEditorPropertyPage extends AbstractCPropertyTab { + + protected Combo fACVersionCombo; + protected Combo fAMVersionCombo; + IProject project; + +// private class ACVersionSelectionListener implements SelectionListener { +// ICPropertyProvider p; +// public ACVersionSelectionListener(ICPropertyProvider p) { +// this.p = p; +// } +// +// public void widgetSelected(SelectionEvent e) { +// int index = fACVersionCombo.getSelectionIndex(); +// try { +// AutotoolsEditorPropertyPage.getProject(p).setPersistentProperty(AutotoolsPropertyConstants.AUTOCONF_VERSION, fACVersionCombo.getItem(index)); +// } catch (CoreException ce) { +// // FIXME: what can we do here? +// } +// } +// +// public void widgetDefaultSelected(SelectionEvent e) { +// // do nothing +// } +// } +// +// private class AMVersionSelectionListener implements SelectionListener { +// ICPropertyProvider p; +// public AMVersionSelectionListener(ICPropertyProvider p) { +// this.p = p; +// } +// +// public void widgetSelected(SelectionEvent e) { +// int index = fAMVersionCombo.getSelectionIndex(); +// try { +// AutotoolsEditorPropertyPage.getProject(p).setPersistentProperty(AutotoolsPropertyConstants.AUTOMAKE_VERSION, fAMVersionCombo.getItem(index)); +// } catch (CoreException ce) { +// // FIXME: what can we do here? +// } +// } +// +// public void widgetDefaultSelected(SelectionEvent e) { +// // do nothing +// } +// } + + private IProject getProject() { + IConfiguration c = ManagedBuildManager.getConfigurationForDescription(getResDesc().getConfiguration()); + return (IProject)c.getManagedProject().getOwner(); + } + + public boolean canBeVisible() { + return true; + } + + public void createControls(Composite parent) { + // TODO Auto-generated method stub + super.createControls(parent); + Composite composite= usercomp; + + // assume parent page uses griddata + GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_CENTER | GridData.VERTICAL_ALIGN_FILL); + composite.setLayoutData(gd); + GridLayout layout= new GridLayout(); + layout.numColumns= 2; + //PixelConverter pc= new PixelConverter(composite); + //layout.verticalSpacing= pc.convertHeightInCharsToPixels(1) / 2; + composite.setLayout(layout); + + project = getProject(); + + /* check box for new editors */ + fACVersionCombo= new Combo(composite, SWT.CHECK | SWT.DROP_DOWN | SWT.READ_ONLY); + fACVersionCombo.setItems(AutotoolsPropertyConstants.fACVersions); + fACVersionCombo.select(AutotoolsPropertyConstants.fACVersions.length - 1); + gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING); + fACVersionCombo.setLayoutData(gd); + + Label label= new Label(composite, SWT.LEFT); + label.setText(AutotoolsPropertyMessages.getString("ACEditor.autoconfVersion")); //$NON-NLS-1$ + gd= new GridData(); + gd.horizontalAlignment= GridData.BEGINNING; + label.setLayoutData(gd); + + /* check box for new editors */ + fAMVersionCombo= new Combo(composite, SWT.CHECK | SWT.DROP_DOWN | SWT.READ_ONLY); + fAMVersionCombo.setItems(AutotoolsPropertyConstants.fAMVersions); + fAMVersionCombo.select(AutotoolsPropertyConstants.fAMVersions.length - 1); + gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING); + fAMVersionCombo.setLayoutData(gd); + + Label label2= new Label(composite, SWT.LEFT); + label2.setText(AutotoolsPropertyMessages.getString("ACEditor.automakeVersion")); //$NON-NLS-1$ + gd= new GridData(); + gd.horizontalAlignment= GridData.BEGINNING; + label2.setLayoutData(gd); + + initialize(); + } + + public void performOK() { + String acVer = null; + String amVer = null; + boolean changed = false; + try { + acVer = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOCONF_VERSION); + amVer = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOMAKE_VERSION); + } catch (CoreException e) { + acVer = ""; + amVer = ""; + } + int index = fACVersionCombo.getSelectionIndex(); + String acVerSelected = fACVersionCombo.getItem(index); + if (!acVerSelected.equals(acVer)) { + changed = true; + try { + project.setPersistentProperty(AutotoolsPropertyConstants.AUTOCONF_VERSION, fACVersionCombo.getItem(index)); + } catch (CoreException ce) { + // Not much we can do at this point + } + } + + index = fAMVersionCombo.getSelectionIndex(); + String amVerSelected = fAMVersionCombo.getItem(index); + if (!amVerSelected.equals(amVer)) { + changed = true; + try { + project.setPersistentProperty(AutotoolsPropertyConstants.AUTOMAKE_VERSION, fAMVersionCombo.getItem(index)); + } catch (CoreException ce) { + // Not much we can do here either + } + } + + // Notify any Autoconf editors that are open for this project that macro versioning + // has changed. + if (changed) + AutotoolsPropertyManager.getDefault().notifyPropertyListeners(project, AutotoolsPropertyConstants.AUTOCONF_MACRO_VERSIONING); + } + + protected void performApply(ICResourceDescription src, ICResourceDescription dst) { + performOK(); + } + + public void performDefaults() { + // For default Autoconf and Automake versions, use the setting from the + // Autotools preference dialog. + String version = AutotoolsPlugin.getDefault().getPreferenceStore().getString(AutotoolsEditorPreferenceConstants.AUTOCONF_VERSION); + String[] items = fACVersionCombo.getItems(); + // Try and find which list item matches the current preference stored and + // select it in the list. + int i; + for (i = 0; i < items.length; ++i) { + if (items[i].equals(version)) + break; + } + if (i >= items.length) + i = items.length - 1; + fACVersionCombo.select(i); + + version = AutotoolsPlugin.getDefault().getPreferenceStore().getString(AutotoolsEditorPreferenceConstants.AUTOMAKE_VERSION); + items = fAMVersionCombo.getItems(); + // Try and find which list item matches the current preference stored and + // select it in the list + for (i = 0; i < items.length; ++i) { + if (items[i].equals(version)) + break; + } + if (i >= items.length) + i = items.length - 1; + fAMVersionCombo.select(i); + } + + public void updateData(ICResourceDescription cfgd) { + // what to do here? + } + + public void updateButtons() { + // what to do here? + } + + public void setVisible (boolean b) { + super.setVisible(b); + } + +// private IProject getProject(ICPropertyProvider provider) { +// Object element = provider.getElement(); +// if (element != null) { +// if (element instanceof IFile || +// element instanceof IProject || +// element instanceof IFolder) +// { +// IResource f = (IResource) element; +// return f.getProject(); +// } +// else if (element instanceof ICProject) +// return ((ICProject)element).getProject(); +// } +// return null; +// } + + private void initialize() { + initializeACVersion(); + initializeAMVersion(); + } + + void initializeACVersion() { + String version = ""; + try { + version = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOCONF_VERSION); + if (version == null) + version = AutotoolsPlugin.getDefault().getPreferenceStore().getString(AutotoolsEditorPreferenceConstants.AUTOCONF_VERSION); + } catch (CoreException e) { + // do nothing + } + String[] items = fACVersionCombo.getItems(); + // Try and find which list item matches the current preference stored and + // select it in the list. + int i; + for (i = 0; i < items.length; ++i) { + if (items[i].equals(version)) + break; + } + if (i >= items.length) + i = items.length - 1; + fACVersionCombo.select(i); + } + + void initializeAMVersion() { + String version = ""; + try { + version = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOMAKE_VERSION); + if (version == null) + version = AutotoolsPlugin.getDefault().getPreferenceStore().getString(AutotoolsEditorPreferenceConstants.AUTOMAKE_VERSION); + } catch (CoreException e) { + // do nothing + } + String[] items = fAMVersionCombo.getItems(); + // Try and find which list item matches the current preference stored and + // select it in the list. + int i; + for (i = 0; i < items.length; ++i) { + if (items[i].equals(version)) + break; + } + if (i >= items.length) + i = items.length - 1; + fAMVersionCombo.select(i); + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyConstants.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyConstants.java new file mode 100644 index 0000000000..f020ce0252 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyConstants.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.properties; + +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.linuxtools.cdt.autotools.AutotoolsPlugin; + + +public class AutotoolsPropertyConstants { + + static final String PREFIX = AutotoolsPlugin.getUniqueIdentifier() + "."; // $NON-NLS-1$ + public static final String AUTOMAKE_VERSION_STRING = "AutoconfEditorAutomakeVersion"; // $NON-NLS-1$ + public static final QualifiedName AUTOMAKE_VERSION = new QualifiedName(PREFIX, AUTOMAKE_VERSION_STRING); + public static final String AUTOCONF_VERSION_STRING = "AutoconfEditorAutoconfVersion"; // $NON-NLS-1$ + public static final QualifiedName AUTOCONF_VERSION = new QualifiedName(PREFIX, AUTOCONF_VERSION_STRING); + public static final String AUTOCONF_MACRO_VERSIONING = "AutoconfEditorMacroVersioning"; // $NON-NLS-1$ + public static final QualifiedName AUTOCONF_TOOL = new QualifiedName(PREFIX, "AutoconfToolPath"); // $NON-NLS-1$ + public static final QualifiedName AUTOMAKE_TOOL = new QualifiedName(PREFIX, "AutomakeToolPath"); // $NON-NLS-1$ + public static final QualifiedName ACLOCAL_TOOL = new QualifiedName(PREFIX, "AclocalToolPath"); // $NON-NLS-1$ + public static final QualifiedName AUTOHEADER_TOOL = new QualifiedName(PREFIX, "AutoheaderToolPath"); // $NON-NLS-1$ + public static final QualifiedName AUTORECONF_TOOL = new QualifiedName(PREFIX, "AutoreconfToolPath"); // $NON-NLS-1$ + public static final QualifiedName LIBTOOLIZE_TOOL = new QualifiedName(PREFIX, "LibtoolizePath"); // $NON-NLS-1$ + public static final QualifiedName CLEAN_DELETE = new QualifiedName(PREFIX, "CleanDelete"); // $NON-NLS-1$ + public static final QualifiedName CLEAN_MAKE_TARGET = new QualifiedName(PREFIX, "CleanMakeTarget"); // $NON-NLS-1$ + public static final QualifiedName SCANNER_USE_MAKE_W = new QualifiedName(PREFIX, "ScannerUseMakeW"); + public static final QualifiedName OPEN_INCLUDE = new QualifiedName(PREFIX, "IncludeResourceMapping"); // $NON-NLS-1$ + public static final QualifiedName OPEN_INCLUDE_P = new QualifiedName(PREFIX, "PersistentIncludeResourceMapping"); //$NON-NLS-1$ + public static final QualifiedName SCANNER_INFO_DIRTY = new QualifiedName(PREFIX, "ScannerInfoDirty"); // $NON-NLSp-1$ + + static String[] fACVersions = {"2.13", "2.59", "2.61"}; // $NON-NLS-1$ + static final String LATEST_AC_VERSION = fACVersions[fACVersions.length - 1]; + + static String[] fAMVersions = {"1.4-p6", "1.9.5", "1.9.6"}; // $NON-NLS-1$ + static final String LATEST_AM_VERSION = fAMVersions[fAMVersions.length - 1]; + + public static final String CLEAN_MAKE_TARGET_DEFAULT = "distclean"; // $NON-NLS-1$ + public static final String TRUE = "true"; // $NON-NLS-1$ + public static final String FALSE = "false"; // $NON-NLS-1$ +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyManager.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyManager.java new file mode 100644 index 0000000000..1bdcca5ac1 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyManager.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.properties; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.ListenerList; + +public class AutotoolsPropertyManager implements IPropertyChangeManager { + + private static AutotoolsPropertyManager fInstance; + private Map<IProject, ListenerList> projectList; + + private AutotoolsPropertyManager() { + projectList = new HashMap<IProject, ListenerList>(); + } + + public static AutotoolsPropertyManager getDefault() { + if (fInstance == null) + fInstance = new AutotoolsPropertyManager(); + return fInstance; + } + + public synchronized void addProjectPropertyListener(IProject project, + IProjectPropertyListener listener) { + ListenerList list = (ListenerList)projectList.get(project); + if (list == null) { + list = new ListenerList(); + projectList.put(project, list); + } + list.add(listener); + } + + public synchronized void notifyPropertyListeners(IProject project, String property) { + ListenerList list = (ListenerList)projectList.get(project); + if (list != null) { + Object[] listeners = list.getListeners(); + for (int i = 0; i < listeners.length; ++i) { + ((IProjectPropertyListener)listeners[i]).handleProjectPropertyChanged(project, property); + } + } + } + + public synchronized void removeProjectPropertyListener(IProject project, + IProjectPropertyListener listener) { + ListenerList list = (ListenerList)projectList.get(project); + if (list != null) + list.remove(listener); + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyMessages.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyMessages.java new file mode 100644 index 0000000000..8fb1becc62 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyMessages.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2002, 2006 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.cdt.autotools.ui.properties; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * MakefilePreferencesMessages + */ +public class AutotoolsPropertyMessages { + + /** + * + */ + private AutotoolsPropertyMessages() { + } + + private static final String BUNDLE_NAME = AutotoolsPropertyMessages.class.getName(); + + public static String getString(String key) { + try { + return ResourceBundle.getBundle(BUNDLE_NAME).getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } catch (NullPointerException e) { + return '#' + key + '#'; + } + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyMessages.properties b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyMessages.properties new file mode 100644 index 0000000000..d729559cc6 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyMessages.properties @@ -0,0 +1,41 @@ +############################################################################### +# Copyright (c) 2007 Red Hat Inc. and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Red Hat Inc. - initial API and implementation +############################################################################### + +Edit.name=Editors +Build.name=Build + +Autotools.aclocalPath=aclocal +Autotools.aclocalPath.tooltip=Specify desired aclocal to use for project +Autotools.automakePath=automake +Autotools.automakePath.tooltip=Specify desired automake to use for project +Autotools.autoconfPath=autoconf +Autotools.autoconfPath.tooltip=Specify desired autoconf to use for project +Autotools.autoheaderPath=autoheader +Autotools.autoheaderPath.tooltip=Specify desired autoheader to use for project +Autotools.autoreconfPath=autoreconf +Autotools.autoreconfPath.tooltip=Specify desired autoreconf to use for project +Autotools.libtoolizePath=libtoolize +Autotools.libtoolizePath.tooltip=Specify desired libtoolize to use for project + +ACEditor.version=&Version +ACEditor.autoconfVersion=Version of Autoconf to use for syntax checking +ACEditor.automakeVersion=Version of Automake to use for syntax checking + +ScannerMakeW.label=Use make -n -w per file to generate scanner info +ScannerMakeW.tooltip=Use this option only if necessary to get correct include path + +CleanBehavior.title=Clean Build Behavior + +CleanDelete.label=Delete build directory on "clean" operation +CleanMake.label=Use make target to clean +CleanMakeTarget.label=Make target: +CleanMakeTarget.default=distclean +CleanMakeTarget.tooltip=Specify a top-level make target to clean build directory diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyPage.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyPage.java new file mode 100644 index 0000000000..95fb589c95 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsPropertyPage.java @@ -0,0 +1,376 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.properties; + +import org.eclipse.cdt.ui.newui.AbstractPage; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +public class AutotoolsPropertyPage extends AbstractPage { + + public AutotoolsPropertyPage() { + super(); + } + + protected boolean isSingle() { + return false; + } + + protected Control createContents(Composite parent) { + return super.createContents(parent); + } + + protected boolean showsConfig() { + return false; + } + +// protected Combo fACVersionCombo; +// protected Combo fAMVersionCombo; +// +// protected Button fCleanDelete; +// protected Button fCleanMake; +// protected Combo fCleanMakeTarget; +// protected Button fScannerMakeW; +// +// +// public boolean isApplicable() { +// IProject project = getProject(); +// if (project != null && !AutotoolsMakefileBuilder.hasTargetBuilder(project)) +// return false; +// else +// return super.isApplicable(); +// } +// +// protected Control createContents(Composite parent) { +// +// TabFolder folder= new TabFolder(parent, SWT.NONE); +// folder.setLayout(new TabFolderLayout()); +// folder.setLayoutData(new GridData(GridData.FILL_BOTH)); +// +// // Allow end-user to select which version of autoconf to use for hover help +// // and syntax checking of macros. +// TabItem item= new TabItem(folder, SWT.NONE); +// item.setText(AutotoolsPropertyMessages.getString("Edit.name")); //$NON-NLS-1$ +// item.setControl(createEditTabContent(folder)); +// +// // Build options. +// item= new TabItem(folder, SWT.NONE); +// item.setText(AutotoolsPropertyMessages.getString("Build.name")); //$NON-NLS-1$ +// item.setControl(createBuildTabContent(folder)); +// +// initialize(); +// +// applyDialogFont(folder); +// return folder; +// } +// +// private Composite createEditTabContent(TabFolder folder) { +// Composite composite= new Composite(folder, SWT.NULL); +// // assume parent page uses griddata +// GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_CENTER | GridData.VERTICAL_ALIGN_FILL); +// composite.setLayoutData(gd); +// GridLayout layout= new GridLayout(); +// layout.numColumns= 2; +// //PixelConverter pc= new PixelConverter(composite); +// //layout.verticalSpacing= pc.convertHeightInCharsToPixels(1) / 2; +// composite.setLayout(layout); +// +// +// /* check box for new editors */ +// fACVersionCombo= new Combo(composite, SWT.CHECK | SWT.DROP_DOWN | SWT.READ_ONLY); +// fACVersionCombo.setItems(AutotoolsPropertyConstants.fACVersions); +// fACVersionCombo.select(AutotoolsPropertyConstants.fACVersions.length - 1); +// gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING); +// fACVersionCombo.setLayoutData(gd); +// fACVersionCombo.addSelectionListener(new SelectionListener() { +// public void widgetSelected(SelectionEvent e) { +// int index = fACVersionCombo.getSelectionIndex(); +// try { +// getProject().setPersistentProperty(AutotoolsPropertyConstants.AUTOCONF_VERSION, fACVersionCombo.getItem(index)); +// } catch (CoreException ce) { +// // FIXME: what can we do here? +// } +// } +// +// public void widgetDefaultSelected(SelectionEvent e) { +// String version = AutotoolsPlugin.getDefault().getPreferenceStore().getString(AutotoolsEditorPreferenceConstants.AUTOCONF_VERSION); +// String[] items = fACVersionCombo.getItems(); +// // Try and find which list item matches the current preference stored and +// // select it in the list. +// int i; +// for (i = 0; i < items.length; ++i) { +// if (items[i].equals(version)) +// break; +// } +// if (i >= items.length) +// i = items.length - 1; +// fACVersionCombo.select(i); +// } +// }); +// +// Label label= new Label(composite, SWT.LEFT); +// label.setText(AutotoolsPropertyMessages.getString("ACEditor.autoconfVersion")); //$NON-NLS-1$ +// gd= new GridData(); +// gd.horizontalAlignment= GridData.BEGINNING; +// label.setLayoutData(gd); +// +// /* check box for new editors */ +// fAMVersionCombo= new Combo(composite, SWT.CHECK | SWT.DROP_DOWN | SWT.READ_ONLY); +// fAMVersionCombo.setItems(AutotoolsPropertyConstants.fAMVersions); +// fAMVersionCombo.select(AutotoolsPropertyConstants.fAMVersions.length - 1); +// gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING); +// fAMVersionCombo.setLayoutData(gd); +// fAMVersionCombo.addSelectionListener(new SelectionListener() { +// public void widgetSelected(SelectionEvent e) { +// int index = fAMVersionCombo.getSelectionIndex(); +// try { +// getProject().setPersistentProperty(AutotoolsPropertyConstants.AUTOMAKE_VERSION, fAMVersionCombo.getItem(index)); +// } catch (CoreException ce) { +// // FIXME: what can we do here? +// } +// } +// +// public void widgetDefaultSelected(SelectionEvent e) { +// String version = AutotoolsPlugin.getDefault().getPreferenceStore().getString(AutotoolsEditorPreferenceConstants.AUTOMAKE_VERSION); +// String[] items = fAMVersionCombo.getItems(); +// // Try and find which list item matches the current preference stored and +// // select it in the list. +// int i; +// for (i = 0; i < items.length; ++i) { +// if (items[i].equals(version)) +// break; +// } +// if (i >= items.length) +// i = items.length - 1; +// fAMVersionCombo.select(i); +// } +// }); +// +// Label label2= new Label(composite, SWT.LEFT); +// label2.setText(AutotoolsPropertyMessages.getString("ACEditor.automakeVersion")); //$NON-NLS-1$ +// gd= new GridData(); +// gd.horizontalAlignment= GridData.BEGINNING; +// label2.setLayoutData(gd); +// +// return composite; +// } +// +// private Composite createBuildTabContent(TabFolder folder) { +// Composite composite= new Composite(folder, SWT.NULL); +// // assume parent page uses griddata +// GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_CENTER | GridData.VERTICAL_ALIGN_FILL); +// composite.setLayoutData(gd); +// GridLayout layout= new GridLayout(); +// layout.numColumns= 2; +// //PixelConverter pc= new PixelConverter(composite); +// //layout.verticalSpacing= pc.convertHeightInCharsToPixels(1) / 2; +// composite.setLayout(layout); +// +// +// Group g = new Group(composite, SWT.SHADOW_ETCHED_IN); +// g.setText(AutotoolsPropertyMessages.getString("CleanBehavior.title")); +// gd = new GridData(GridData.HORIZONTAL_ALIGN_CENTER | GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); +// gd.horizontalSpan = 2; +// g.setLayoutData(gd); +// layout= new GridLayout(); +// layout.numColumns= 2; +// g.setLayout(layout); +// +// fCleanDelete = new Button(g, SWT.RADIO); +// fCleanDelete.setText(AutotoolsPropertyMessages.getString("CleanDelete.label")); +// gd= new GridData(); +// gd.horizontalAlignment= GridData.BEGINNING; +// gd.horizontalSpan = 2; +// fCleanDelete.setLayoutData(gd); +// fCleanMake = new Button(g, SWT.RADIO); +// fCleanMake.setText(AutotoolsPropertyMessages.getString("CleanMake.label")); +// gd= new GridData(); +// gd.horizontalAlignment= GridData.BEGINNING; +// gd.horizontalSpan = 2; +// fCleanMake.setLayoutData(gd); +// +// Label label = new Label(g, SWT.LEFT); +// label.setText(AutotoolsPropertyMessages.getString("CleanMakeTarget.label")); +// gd= new GridData(); +// gd.horizontalAlignment= GridData.BEGINNING; +// label.setLayoutData(gd); +// +// fCleanMakeTarget = new Combo(g, SWT.SIMPLE); +// fCleanMakeTarget.setText(AutotoolsPropertyMessages.getString("CleanMakeTarget.default")); +// fCleanMakeTarget.setTextLimit(40); +// fCleanMakeTarget.setVisibleItemCount(0); +// gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING); +// fCleanMakeTarget.setLayoutData(gd); +// +// fCleanDelete.addSelectionListener(new SelectionListener() { +// public void widgetSelected(SelectionEvent e) { +// fCleanMake.setSelection(false); +// fCleanDelete.setSelection(true); +// fCleanMakeTarget.setEnabled(false); +// try { +// getProject().setPersistentProperty(AutotoolsPropertyConstants.CLEAN_DELETE, "true"); +// } catch (CoreException ce) { +// // FIXME: what can we do here? +// } +// } +// +// public void widgetDefaultSelected(SelectionEvent e) { +// fCleanDelete.setSelection(false); +// fCleanMake.setSelection(true); +// fCleanMakeTarget.setEnabled(true); +// try { +// getProject().setPersistentProperty(AutotoolsPropertyConstants.CLEAN_DELETE, "false"); +// getProject().setPersistentProperty(AutotoolsPropertyConstants.CLEAN_MAKE_TARGET, "distclean"); +// } catch (CoreException ce) { +// // FIXME: what can we do here? +// } +// } +// }); +// +// fCleanMake.addSelectionListener(new SelectionListener() { +// public void widgetSelected(SelectionEvent e) { +// fCleanDelete.setSelection(false); +// fCleanMake.setSelection(true); +// fCleanMakeTarget.setEnabled(true); +// try { +// getProject().setPersistentProperty(AutotoolsPropertyConstants.CLEAN_DELETE, "false"); +// } catch (CoreException ce) { +// // FIXME: what can we do here? +// } +// } +// +// public void widgetDefaultSelected(SelectionEvent e) { +//// fCleanDelete.setSelection(false); +//// fCleanMake.setSelection(true); +//// try { +//// getProject().setPersistentProperty(AutotoolsPropertyConstants.CLEAN_DELETE, "false"); +//// getProject().setPersistentProperty(AutotoolsPropertyConstants.CLEAN_MAKE_TARGET, "distclean"); +//// } catch (CoreException ce) { +//// // FIXME: what can we do here? +//// } +// } +// }); +// +// fCleanMakeTarget.addModifyListener(new ModifyListener() { +// public void modifyText(ModifyEvent e) { +// try { +// getProject().setPersistentProperty(AutotoolsPropertyConstants.CLEAN_MAKE_TARGET, fCleanMakeTarget.getText()); +// } catch (CoreException ce) { +// // FIXME: what can we do here? +// } +// } +// }); +// +// fScannerMakeW = new Button(composite, SWT.LEFT | SWT.CHECK); +// fScannerMakeW.setText(AutotoolsPropertyMessages.getString("ScannerMakeW.label")); +// fScannerMakeW.setToolTipText(AutotoolsPropertyMessages.getString("ScannerMakeW.tooltip")); +// gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING); +// fScannerMakeW.setLayoutData(gd); +// fScannerMakeW.addSelectionListener(new SelectionListener() { +// public void widgetSelected(SelectionEvent e) { +// try { +// getProject().setPersistentProperty(AutotoolsPropertyConstants.SCANNER_USE_MAKE_W, "true"); +// } catch (CoreException ce) { +// // FIXME: what can we do here? +// } +// } +// +// public void widgetDefaultSelected(SelectionEvent e) { +// fScannerMakeW.setSelection(false); +// try { +// // This is only a temporary work-around so we remove the property rather than set it false. +// getProject().setPersistentProperty(AutotoolsPropertyConstants.SCANNER_USE_MAKE_W, null); +// } catch (CoreException ce) { +// // FIXME: what can we do here? +// } +// } +// }); +// +// return composite; +// } +// +// void initializeACVersion() { +// String version = ""; +// try { +// version = getProject().getPersistentProperty(AutotoolsPropertyConstants.AUTOCONF_VERSION); +// if (version == null) +// version = AutotoolsPlugin.getDefault().getPreferenceStore().getString(AutotoolsEditorPreferenceConstants.AUTOCONF_VERSION); +// } catch (CoreException e) { +// // do nothing +// } +// String[] items = fACVersionCombo.getItems(); +// // Try and find which list item matches the current preference stored and +// // select it in the list. +// int i; +// for (i = 0; i < items.length; ++i) { +// if (items[i].equals(version)) +// break; +// } +// if (i >= items.length) +// i = items.length - 1; +// fACVersionCombo.select(i); +// } +// +// void initializeAMVersion() { +// String version = ""; +// try { +// version = getProject().getPersistentProperty(AutotoolsPropertyConstants.AUTOMAKE_VERSION); +// if (version == null) +// version = AutotoolsPlugin.getDefault().getPreferenceStore().getString(AutotoolsEditorPreferenceConstants.AUTOMAKE_VERSION); +// } catch (CoreException e) { +// // do nothing +// } +// String[] items = fAMVersionCombo.getItems(); +// // Try and find which list item matches the current preference stored and +// // select it in the list. +// int i; +// for (i = 0; i < items.length; ++i) { +// if (items[i].equals(version)) +// break; +// } +// if (i >= items.length) +// i = items.length - 1; +// fAMVersionCombo.select(i); +// } +// +// void initializeBuild() { +// String cleanDelete = null; +// String cleanMakeTarget = null; +// try { +// cleanDelete = getProject().getPersistentProperty(AutotoolsPropertyConstants.CLEAN_DELETE); +// cleanMakeTarget = getProject().getPersistentProperty(AutotoolsPropertyConstants.CLEAN_MAKE_TARGET); +// } catch (CoreException e) { +// // do nothing +// } +// +// if (cleanMakeTarget == null) { +// cleanMakeTarget = AutotoolsPropertyMessages.getString("CleanMakeTarget.default"); // $NON-NLS-1$ +// fCleanMakeTarget.setText(cleanMakeTarget); +// } +// +// if (cleanDelete == null || cleanDelete.equals("false")) { +// fCleanDelete.setSelection(false); +// fCleanMake.setSelection(true); +// fCleanMakeTarget.setEnabled(true); +// } else { +// fCleanDelete.setSelection(true); +// fCleanMake.setSelection(false); +// fCleanMakeTarget.setEnabled(false); +// } +// } +// +// private void initialize() { +// initializeACVersion(); +// initializeAMVersion(); +// initializeBuild(); +// } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsToolsPropertyPage.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsToolsPropertyPage.java new file mode 100644 index 0000000000..7b56c2b213 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/AutotoolsToolsPropertyPage.java @@ -0,0 +1,343 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.properties; + +import org.eclipse.cdt.core.settings.model.ICResourceDescription; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.cdt.ui.newui.AbstractCPropertyTab; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public class AutotoolsToolsPropertyPage extends AbstractCPropertyTab { + + public static final String DEFAULT_ACLOCAL = "aclocal"; // $NON-NLS-1$ + public static final String DEFAULT_AUTOMAKE = "automake"; // $NON-NLS-1$ + public static final String DEFAULT_AUTOCONF = "autoconf"; // $NON-NLS-1$ + public static final String DEFAULT_AUTOHEADER = "autoheader"; // $NON-NLS-1$ + public static final String DEFAULT_AUTORECONF = "autoreconf"; // $NON-NLS-1$ + public static final String DEFAULT_LIBTOOLIZE = "libtoolize"; // $NON-NLS-1$ + + protected Text fAclocalPath; + protected Text fAutoheaderPath; + protected Text fAutomakePath; + protected Text fAutoreconfPath; + protected Text fAutoconfPath; + protected Text fLibtoolizePath; + private IProject project; + + + private IProject getProject() { + IConfiguration c = ManagedBuildManager.getConfigurationForDescription(getResDesc().getConfiguration()); + return (IProject)c.getManagedProject().getOwner(); + } + + public boolean canBeVisible() { + return true; + } + + public void createControls(Composite parent) { + // TODO Auto-generated method stub + super.createControls(parent); + Composite composite= usercomp; + + // assume parent page uses griddata + GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_CENTER | GridData.VERTICAL_ALIGN_FILL | GridData.FILL_HORIZONTAL); + composite.setLayoutData(gd); + GridLayout layout= new GridLayout(); + layout.numColumns= 2; + //PixelConverter pc= new PixelConverter(composite); + //layout.verticalSpacing= pc.convertHeightInCharsToPixels(1) / 2; + composite.setLayout(layout); + + project = getProject(); + + Label label= new Label(composite, SWT.LEFT); + label.setText(AutotoolsPropertyMessages.getString("Autotools.aclocalPath")); //$NON-NLS-1$ + gd= new GridData(); + gd.horizontalAlignment= GridData.BEGINNING; + label.setLayoutData(gd); + + /* text window for aclocal path */ + fAclocalPath = new Text(composite, SWT.BORDER | SWT.SINGLE); + fAclocalPath.setToolTipText(AutotoolsPropertyMessages.getString("Autotools.aclocalPath.tooltip")); // $NON-NLS-1$ + gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); + fAclocalPath.setLayoutData(gd); + + Label label2= new Label(composite, SWT.LEFT); + label2.setText(AutotoolsPropertyMessages.getString("Autotools.automakePath")); //$NON-NLS-1$ + gd= new GridData(); + gd.horizontalAlignment= GridData.BEGINNING; + label2.setLayoutData(gd); + + /* text window for automake path */ + fAutomakePath = new Text(composite, SWT.BORDER | SWT.SINGLE); + fAutomakePath.setToolTipText(AutotoolsPropertyMessages.getString("Autotools.automakePath.tooltip")); // $NON-NLS-1# + gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); + fAutomakePath.setLayoutData(gd); + + Label label3 = new Label(composite, SWT.LEFT); + label3.setText(AutotoolsPropertyMessages.getString("Autotools.autoconfPath")); //$NON-NLS-1$ + gd= new GridData(); + gd.horizontalAlignment= GridData.BEGINNING; + label3.setLayoutData(gd); + + /* text window for autoconf path */ + fAutoconfPath = new Text(composite, SWT.BORDER | SWT.SINGLE); + fAutoconfPath.setToolTipText(AutotoolsPropertyMessages.getString("Autotools.autoconfPath.tooltip")); // $NON-NLS-1$ + gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); + fAutoconfPath.setLayoutData(gd); + + Label label4= new Label(composite, SWT.LEFT); + label4.setText(AutotoolsPropertyMessages.getString("Autotools.autoheaderPath")); //$NON-NLS-1$ + gd= new GridData(); + gd.horizontalAlignment= GridData.BEGINNING; + label4.setLayoutData(gd); + + /* text window for aclocal path */ + fAutoheaderPath = new Text(composite, SWT.BORDER | SWT.SINGLE); + fAutoheaderPath.setToolTipText(AutotoolsPropertyMessages.getString("Autotools.autoheaderPath.tooltip")); // $NON-NLS-1$ + gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); + fAutoheaderPath.setLayoutData(gd); + + Label label5= new Label(composite, SWT.LEFT); + label5.setText(AutotoolsPropertyMessages.getString("Autotools.autoreconfPath")); //$NON-NLS-1$ + gd= new GridData(); + gd.horizontalAlignment= GridData.BEGINNING; + label5.setLayoutData(gd); + + /* text window for aclocal path */ + fAutoreconfPath = new Text(composite, SWT.BORDER | SWT.SINGLE); + fAutoreconfPath.setToolTipText(AutotoolsPropertyMessages.getString("Autotools.autoreconfPath.tooltip")); // $NON-NLS-1$ + gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); + fAutoreconfPath.setLayoutData(gd); + + Label label6= new Label(composite, SWT.LEFT); + label6.setText(AutotoolsPropertyMessages.getString("Autotools.libtoolizePath")); //$NON-NLS-1$ + gd= new GridData(); + gd.horizontalAlignment= GridData.BEGINNING; + label6.setLayoutData(gd); + + /* text window for aclocal path */ + fLibtoolizePath = new Text(composite, SWT.BORDER | SWT.SINGLE); + fLibtoolizePath.setToolTipText(AutotoolsPropertyMessages.getString("Autotools.libtoolizePath.tooltip")); // $NON-NLS-1$ + gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); + fLibtoolizePath.setLayoutData(gd); + + initialize(); + } + + public void performOK() { + String aclocalPath = null; + String automakePath = null; + String autoconfPath = null; + String autoheaderPath = null; + String autoreconfPath = null; + String libtoolizePath = null; + try { + aclocalPath = project.getPersistentProperty(AutotoolsPropertyConstants.ACLOCAL_TOOL); + } catch (CoreException e1) { + aclocalPath = DEFAULT_ACLOCAL; + } + + String newAclocalPath = fAclocalPath.getText().trim(); + if (aclocalPath == null || !newAclocalPath.equals(aclocalPath)) { + try { + project.setPersistentProperty(AutotoolsPropertyConstants.ACLOCAL_TOOL, newAclocalPath); + } catch (CoreException e1) { + // Not much we can do at this point + } + } + + try { + automakePath = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOMAKE_TOOL); + } catch (CoreException e1) { + automakePath = DEFAULT_AUTOMAKE; + } + + String newAutomakePath = fAutomakePath.getText().trim(); + if (automakePath == null || !newAutomakePath.equals(automakePath)) { + try { + project.setPersistentProperty(AutotoolsPropertyConstants.AUTOMAKE_TOOL, newAutomakePath); + } catch (CoreException e2) { + // Not much we can do at this point + } + } + + try { + autoconfPath = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOCONF_TOOL); + } catch (CoreException e1) { + autoconfPath = DEFAULT_AUTOCONF; + } + + String newAutoconfPath = fAutoconfPath.getText().trim(); + if (autoconfPath == null || !newAutoconfPath.equals(autoconfPath)) { + try { + project.setPersistentProperty(AutotoolsPropertyConstants.AUTOCONF_TOOL, newAutoconfPath); + } catch (CoreException e2) { + // Not much we can do at this point + } + } + + try { + autoheaderPath = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOHEADER_TOOL); + } catch (CoreException e1) { + autoheaderPath = DEFAULT_AUTOHEADER; + } + + String newAutoheaderPath = fAutoheaderPath.getText().trim(); + if (autoheaderPath == null || !newAutoheaderPath.equals(autoheaderPath)) { + try { + project.setPersistentProperty(AutotoolsPropertyConstants.AUTOHEADER_TOOL, newAutoheaderPath); + } catch (CoreException e2) { + // Not much we can do at this point + } + } + + try { + autoreconfPath = project.getPersistentProperty(AutotoolsPropertyConstants.AUTORECONF_TOOL); + } catch (CoreException e1) { + autoreconfPath = DEFAULT_AUTORECONF; + } + + String newAutoreconfPath = fAutoreconfPath.getText().trim(); + if (autoreconfPath == null || !newAutoreconfPath.equals(autoreconfPath)) { + try { + project.setPersistentProperty(AutotoolsPropertyConstants.AUTORECONF_TOOL, newAutoreconfPath); + } catch (CoreException e2) { + // Not much we can do at this point + } + } + + try { + libtoolizePath = project.getPersistentProperty(AutotoolsPropertyConstants.LIBTOOLIZE_TOOL); + } catch (CoreException e1) { + libtoolizePath = DEFAULT_LIBTOOLIZE; + } + + String newLibtoolizePath = fLibtoolizePath.getText().trim(); + if (libtoolizePath == null || !newLibtoolizePath.equals(libtoolizePath)) { + try { + project.setPersistentProperty(AutotoolsPropertyConstants.LIBTOOLIZE_TOOL, newLibtoolizePath); + } catch (CoreException e2) { + // Not much we can do at this point + } + } + } + + protected void performApply(ICResourceDescription src, ICResourceDescription dst) { + performOK(); + } + + public void performDefaults() { + // For default tool settings, simply default the base tool names + fAclocalPath.setText(DEFAULT_ACLOCAL); + fAutomakePath.setText(DEFAULT_AUTOMAKE); + fAutoconfPath.setText(DEFAULT_AUTOCONF); + fAutoheaderPath.setText(DEFAULT_AUTOHEADER); + fAutoreconfPath.setText(DEFAULT_AUTORECONF); + fLibtoolizePath.setText(DEFAULT_LIBTOOLIZE); + } + + public void updateData(ICResourceDescription cfgd) { + // what to do here? + } + + public void updateButtons() { + // what to do here? + } + + public void setVisible (boolean b) { + super.setVisible(b); + } + + private void initialize() { + String aclocalPath = null; + String automakePath = null; + String autoconfPath = null; + String autoheaderPath = null; + String autoreconfPath = null; + String libtoolizePath = null; + + try { + aclocalPath = project.getPersistentProperty(AutotoolsPropertyConstants.ACLOCAL_TOOL); + } catch (CoreException e1) { + // do nothing + } + + if (aclocalPath == null) + aclocalPath = DEFAULT_ACLOCAL; + + fAclocalPath.setText(aclocalPath); + + try { + automakePath = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOMAKE_TOOL); + } catch (CoreException e1) { + // do nothing + } + + if (automakePath == null) + automakePath = DEFAULT_AUTOMAKE; + + fAutomakePath.setText(automakePath); + + try { + autoconfPath = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOCONF_TOOL); + } catch (CoreException e1) { + // do nothing + } + + if (autoconfPath == null) + autoconfPath = DEFAULT_AUTOCONF; + + fAutoconfPath.setText(autoconfPath); + + try { + autoheaderPath = project.getPersistentProperty(AutotoolsPropertyConstants.AUTOHEADER_TOOL); + } catch (CoreException e1) { + // do nothing + } + + if (autoheaderPath == null) + autoheaderPath = DEFAULT_AUTOHEADER; + + fAutoheaderPath.setText(autoheaderPath); + + try { + autoreconfPath = project.getPersistentProperty(AutotoolsPropertyConstants.AUTORECONF_TOOL); + } catch (CoreException e1) { + // do nothing + } + + if (autoreconfPath == null) + autoreconfPath = DEFAULT_AUTORECONF; + + fAutoreconfPath.setText(autoreconfPath); + + try { + libtoolizePath = project.getPersistentProperty(AutotoolsPropertyConstants.LIBTOOLIZE_TOOL); + } catch (CoreException e1) { + // do nothing + } + + if (libtoolizePath == null) + libtoolizePath = DEFAULT_LIBTOOLIZE; + + fLibtoolizePath.setText(libtoolizePath); + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/IProjectPropertyListener.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/IProjectPropertyListener.java new file mode 100644 index 0000000000..f9752307fb --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/IProjectPropertyListener.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.properties; + +import org.eclipse.core.resources.IProject; + +public interface IProjectPropertyListener { + + /** + * Handler for property changes + * + * @param project the project to which the property changed + * @param property the name of the property changed + */ + void handleProjectPropertyChanged(IProject project, String property); + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/IPropertyChangeManager.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/IPropertyChangeManager.java new file mode 100644 index 0000000000..65b4fada2d --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/cdt/autotools/ui/properties/IPropertyChangeManager.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2007 Red Hat Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.cdt.autotools.ui.properties; + +import org.eclipse.core.resources.IProject; + +public interface IPropertyChangeManager { + + /** + * Add a project property listener for given project. + * + * @param project the project to which the listener is interested + * @param listener the listener to notify + */ + void addProjectPropertyListener(IProject project, IProjectPropertyListener listener); + + /** + * Remove a project property listener. + * + * @param listener the listener to remove + */ + void removeProjectPropertyListener(IProject project, IProjectPropertyListener listener); + + /** + * Notify all listeners of project that a property has changed. + * + * @param project the project for which the property has changed + * @param property the property that has changed + */ + void notifyPropertyListeners(IProject project, String property); + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/MarkerGenerator.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/MarkerGenerator.java new file mode 100644 index 0000000000..c43f040b21 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/MarkerGenerator.java @@ -0,0 +1,155 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.internal.cdt.autotools; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.IMarkerGenerator; +import org.eclipse.cdt.core.ProblemMarkerInfo; +import org.eclipse.cdt.core.model.ICModelMarker; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.runtime.CoreException; + +public abstract class MarkerGenerator implements IMarkerGenerator { + + /** + * Constructor for MarkerGenerator + */ + public MarkerGenerator() { + super(); + } + + /* + * callback from Output Parser + */ + public void addMarker(IResource file, int lineNumber, String errorDesc, int severity, String errorVar) { + + try { + IMarker[] cur = file.findMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_ONE); + /* + * Try to find matching markers and don't put in duplicates + */ + if ((cur != null) && (cur.length > 0)) { + for (int i = 0; i < cur.length; i++) { + int line = ((Integer) cur[i].getAttribute(IMarker.LOCATION)).intValue(); + int sev = ((Integer) cur[i].getAttribute(IMarker.SEVERITY)).intValue(); + String mesg = (String) cur[i].getAttribute(IMarker.MESSAGE); + if (line == lineNumber && sev == mapMarkerSeverity(severity) && mesg.equals(errorDesc)) { + return; + } + } + } + + IMarker marker = file.createMarker(ICModelMarker.C_MODEL_PROBLEM_MARKER); + marker.setAttribute(IMarker.LOCATION, lineNumber); + marker.setAttribute(IMarker.MESSAGE, errorDesc); + marker.setAttribute(IMarker.SEVERITY, mapMarkerSeverity(severity)); + marker.setAttribute(IMarker.LINE_NUMBER, lineNumber); + marker.setAttribute(IMarker.CHAR_START, -1); + marker.setAttribute(IMarker.CHAR_END, -1); + if (errorVar != null) { + marker.setAttribute(ICModelMarker.C_MODEL_MARKER_VARIABLE, errorVar); + } + } + catch (CoreException e) { + CCorePlugin.log(e.getStatus()); + } + + } + + public abstract IProject getProject(); + + /* + * callback from Output Parser + */ + public void addMarker(ProblemMarkerInfo problemMarkerInfo) { + try { + IResource markerResource = problemMarkerInfo.file ; + if (markerResource==null) { + markerResource = getProject(); + } + IMarker[] cur = markerResource.findMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_ONE); + /* + * Try to find matching markers and don't put in duplicates + */ + if ((cur != null) && (cur.length > 0)) { + for (int i = 0; i < cur.length; i++) { + int line = ((Integer) cur[i].getAttribute(IMarker.LOCATION)).intValue(); + int sev = ((Integer) cur[i].getAttribute(IMarker.SEVERITY)).intValue(); + String mesg = (String) cur[i].getAttribute(IMarker.MESSAGE); + if (line == problemMarkerInfo.lineNumber && sev == mapMarkerSeverity(problemMarkerInfo.severity) && mesg.equals(problemMarkerInfo.description)) { + return; + } + } + } + + IMarker marker = markerResource.createMarker(ICModelMarker.C_MODEL_PROBLEM_MARKER); + marker.setAttribute(IMarker.LOCATION, problemMarkerInfo.lineNumber); + marker.setAttribute(IMarker.MESSAGE, problemMarkerInfo.description); + marker.setAttribute(IMarker.SEVERITY, mapMarkerSeverity(problemMarkerInfo.severity)); + marker.setAttribute(IMarker.LINE_NUMBER, problemMarkerInfo.lineNumber); + marker.setAttribute(IMarker.CHAR_START, -1); + marker.setAttribute(IMarker.CHAR_END, -1); + if (problemMarkerInfo.variableName != null) { + marker.setAttribute(ICModelMarker.C_MODEL_MARKER_VARIABLE, problemMarkerInfo.variableName); + } + if (problemMarkerInfo.externalPath != null) { + marker.setAttribute(ICModelMarker.C_MODEL_MARKER_EXTERNAL_LOCATION, problemMarkerInfo.externalPath.toOSString()); + } + } + catch (CoreException e) { + CCorePlugin.log(e.getStatus()); + } + } + + private int mapMarkerSeverity(int severity) { + switch (severity) { + case SEVERITY_ERROR_BUILD : + case SEVERITY_ERROR_RESOURCE : + return IMarker.SEVERITY_ERROR; + case SEVERITY_INFO : + return IMarker.SEVERITY_INFO; + case SEVERITY_WARNING : + return IMarker.SEVERITY_WARNING; + } + return IMarker.SEVERITY_ERROR; + } + + /* (non-Javadoc) + * Removes the IMarkers for the project specified in the argument if the + * project exists, and is open. + * + * @param project + */ + public void removeAllMarkers(IProject project) { + if (project == null || !project.isAccessible()) return; + + // Clear out the problem markers + IWorkspace workspace = project.getWorkspace(); + IMarker[] markers; + try { + markers = project.findMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); + } catch (CoreException e) { + // Handled just about every case in the sanity check + return; + } + if (markers != null) { + try { + workspace.deleteMarkers(markers); + } catch (CoreException e) { + // The only situation that might cause this is some sort of resource change event + return; + } + } + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/AutotoolsConsole.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/AutotoolsConsole.java new file mode 100644 index 0000000000..982764a120 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/AutotoolsConsole.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2002, 2004, 2009 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + * Red Hat Inc - Adapted for Autotools usage + *******************************************************************************/ +package org.eclipse.linuxtools.internal.cdt.autotools.ui; + +import org.eclipse.cdt.ui.IBuildConsoleManager; +import org.eclipse.core.resources.IProject; + +public class AutotoolsConsole extends Console { + IProject project; + IBuildConsoleManager fConsoleManager; + + private static final String CONTEXT_MENU_ID = "CAutotoolsConsole"; //$NON-NLS-1$ + private static final String CONSOLE_NAME = ConsoleMessages.getString("AutotoolsConsole.name"); //$NON-NLS-1$ + + public AutotoolsConsole() { + super(CONSOLE_NAME, CONTEXT_MENU_ID); + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/CBuildStepsConsole.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/CBuildStepsConsole.java new file mode 100644 index 0000000000..5ba325974f --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/CBuildStepsConsole.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2002, 2004, 2009 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + * Red Hat Inc - Adapted for Autotools usage + *******************************************************************************/ +package org.eclipse.linuxtools.internal.cdt.autotools.ui; + +import org.eclipse.cdt.ui.IBuildConsoleManager; +import org.eclipse.core.resources.IProject; + +public class CBuildStepsConsole extends Console { + IProject project; + IBuildConsoleManager fConsoleManager; + + private static final String CONTEXT_MENU_ID = "CAutotoolsBuildStepsConsole"; //$NON-NLS-1$ + private static final String CONSOLE_NAME = ConsoleMessages.getString("BuildStepsConsole.name"); //$NON-NLS-1$ + + public CBuildStepsConsole() { + super(CONSOLE_NAME, CONTEXT_MENU_ID); + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/CConfigureConsole.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/CConfigureConsole.java new file mode 100644 index 0000000000..1925fcd7c2 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/CConfigureConsole.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2002, 2004, 2009 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.internal.cdt.autotools.ui; + +import org.eclipse.cdt.ui.IBuildConsoleManager; +import org.eclipse.core.resources.IProject; + +public class CConfigureConsole extends Console { + IProject project; + IBuildConsoleManager fConsoleManager; + + private static final String CONTEXT_MENU_ID = "CAutotoolsConfigureConsole"; //$NON-NLS-1$ + private static final String CONSOLE_NAME = ConsoleMessages.getString("ConfigureConsole.name"); //$NON-NLS-1$ + + public CConfigureConsole() { + super(CONSOLE_NAME, CONTEXT_MENU_ID); + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/CWordFinder.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/CWordFinder.java new file mode 100644 index 0000000000..cc28694b10 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/CWordFinder.java @@ -0,0 +1,283 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.internal.cdt.autotools.ui; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Region; + + +/** + * This is a helper class for the text editor to be able to determine, given a + * particular offset in a document, various candidates segments for things like + * context help, proposals and hovering. + */ +public class CWordFinder { + + private static final char CBRACE_L = '{'; + private static final char CBRACE_R = '}'; + private static final char BRACE_R = ')'; + + /** + * This method determines for a given offset into a given document what the + * region is which defines the current word. A word is defined as the set of + * non "C" identifiers. So assuming that ! indicated the current cursor + * postion: !afunction(int a, int b) --> word = length 0 afunc!tion(int a, + * int b) --> word = afunction afunction!(int a, int b) --> word = afunction + * afunction(!int a, int b) --> word = length 0 afunction(int a,! int b) --> + * word = length 0 afunction(!) --> word = length 0 + * + * @param document + * The document to be examined + * @param offset + * The offset into the document where a word should be + * idendified. + * @return The region defining the current word, which may be a region of + * length 0 if the offset is not in a word, or null if there is an + * error accessing the docment data. + */ + public static IRegion findWord(IDocument document, int offset) { + int start = -1; + int end = -1; + + try { + int pos = offset; + char c; + + while (pos >= 0) { + c = document.getChar(pos); + if (!Character.isJavaIdentifierPart(c)) + break; + --pos; + } + + start = pos + 1; + + pos = offset; + int length = document.getLength(); + + while (pos < length) { + c = document.getChar(pos); + if (!Character.isJavaIdentifierPart(c)) + break; + ++pos; + } + + end = pos; + + } catch (BadLocationException x) { + } + + if (start > -1 && end > -1) { + if (start >= offset && end == offset) + return new Region(offset, 0); + else + return new Region(start, end - start); + } + + return null; + } + + /** + * This method will determine the region for the name of the function within + * which the current offset is contained. + * + * @param document + * The document to be examined + * @param offset + * The offset into the document where a word should be + * idendified. + * @return The region defining the current word, which may be a region of + * length 0 if the offset is not in a function, or null if there is + * an error accessing the docment data. + */ + public static IRegion findFunction(IDocument document, int offset) { + int leftbracket = -1; + int leftbracketcount = 0; + int rightbracket = -1; + int rightbracketcount = 0; + int functionstart = -1; + int functionend = -1; + + try { + int length = document.getLength(); + int pos; + char c; + + //Find most relevant right bracket from our position + pos = offset; + rightbracketcount = leftbracketcount = 0; + while (pos < length) { + c = document.getChar(pos); + + if (c == ')') { + rightbracketcount++; + if (rightbracketcount >= leftbracketcount) { + rightbracket = pos; + break; + } + } + + if (c == '(') { + leftbracketcount++; + } + + if (c == ';') { + break; + } + + pos++; + } + + if (rightbracket == -1) { + return new Region(offset, 0); + } + + //Now backtrack our way from the rightbracket to the left + pos = rightbracket; + rightbracketcount = leftbracketcount = 0; + while (pos >= 0) { + c = document.getChar(pos); + + if (c == ')') { + rightbracketcount++; + } + + if (c == '(') { + leftbracketcount++; + if (leftbracketcount >= rightbracketcount) { + leftbracket = pos; + break; + } + } + + if (c == ';') { + break; + } + + pos--; + } + + if (leftbracket == -1) { + return new Region(offset, 0); + } + + //Now work our way to the function name + pos = leftbracket - 1; + while (pos >= 0) { + c = document.getChar(pos); + if (functionend == -1 && c == ' ') { + pos--; + continue; + } + + if (!Character.isJavaIdentifierPart(c)) { + break; + } + + functionstart = pos; + if (functionend == -1) { + functionend = pos; + } + + pos--; + } + } catch (BadLocationException x) { + /* Ignore */ + } + + if (functionstart > -1 && functionend > -1) { + return new Region(functionstart, functionend - functionstart + 1); + } + + return null; + } + + /** + * This method will determine whether current offset is contained + * in any function's body or it's outside it. + * + * @param document + * The document to be examined + * @param offset + * The offset into the document + * @return + * <code>true</code> if there is no function body around offset + * <code>false</code> otherwise + */ + public static boolean isGlobal(IDocument document, int offset) { + try { + int pos = offset; + int bracketcount = 0; + char c; + + //Find left curled bracket from our position + while (pos > 0) { + c = document.getChar(pos--); + + if (c == CBRACE_R) { + bracketcount++; // take into account nested blocks + } else if (c == CBRACE_L) { + if (bracketcount-- == 0) { + do { + c = document.getChar(pos--); + if (c == BRACE_R) return false; + } while (Character.isWhitespace(c)); + // container block seems to be not a function or statement body + pos++; // step back one symbol + bracketcount = 0; // let's search for upper block + } + } + } + + } catch (BadLocationException x) { /* Ignore */ } + // return true in case of unknown result or exception + return true; + } + + /** + * Searches for line feed symbols in string. + * First met '\r' or '\n' is treated as LF symbol + * + * @param s + * string to search in. + * @return number of LFs met. + */ + public static int countLFs (String s) { + int counter = 0; + char lf = 0; + char c; + for (int i=0; i<s.length(); i++) { + c = s.charAt(i); + if (lf == 0) { + if (c == '\n' || c == '\r') { + lf = c; + counter++; + } + } else if (lf == c) counter++; + } + return counter; + } + + /** + * Checks whether the string contains any C-block delimiters ( { } ) + * + * @param s + * text to check + * @return true if curled brace found. + */ + public static boolean hasCBraces (String s) { + if (s.indexOf(CBRACE_L) > -1 || s.indexOf(CBRACE_R) > -1) return true; + else return false; + } +} + diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/Console.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/Console.java new file mode 100644 index 0000000000..695e489a1b --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/Console.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2002, 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.internal.cdt.autotools.ui; + +import org.eclipse.cdt.core.ConsoleOutputStream; +import org.eclipse.cdt.core.resources.IConsole; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.IBuildConsoleManager; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; + +public class Console implements IConsole { + IProject project; + IBuildConsoleManager fConsoleManager; + + public Console(String consoleName, String contextId) { + fConsoleManager = CUIPlugin.getDefault().getConsoleManager(consoleName, + contextId); + } + +// /** +// * Constructor for ConfigureConsole. +// */ +// public CConfigureConsole() { +// fConsoleManager = AutotoolsPlugin.getDefault().getConsoleManager(); +// } +// + + public void start(IProject project ) { + this.project = project; + fConsoleManager.getConsole(project).start(project); + } + + /** + * @throws CoreException + * @see org.eclipse.cdt.core.resources.IConsole#getOutputStream() + */ + public ConsoleOutputStream getOutputStream() throws CoreException { + return fConsoleManager.getConsole(project).getOutputStream(); + } + + public ConsoleOutputStream getInfoStream() throws CoreException { + return fConsoleManager.getConsole(project).getInfoStream(); + } + + public ConsoleOutputStream getErrorStream() throws CoreException { + return fConsoleManager.getConsole(project).getErrorStream(); + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/ConsoleMessages.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/ConsoleMessages.java new file mode 100644 index 0000000000..a9b3d21ef0 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/ConsoleMessages.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2002, 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.internal.cdt.autotools.ui; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class ConsoleMessages { + + public static final String BUNDLE_NAME = "org.eclipse.linuxtools.internal.cdt.autotools.ui.ConsoleMessages";//$NON-NLS-1$ + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME); + + private ConsoleMessages() { + + } + public static String getString(String key) { + try { + return RESOURCE_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/ConsoleMessages.properties b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/ConsoleMessages.properties new file mode 100644 index 0000000000..7c4510df87 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/ConsoleMessages.properties @@ -0,0 +1,25 @@ +############################################################################### +# Copyright (c) 2003, 2004 QNX Software Systems and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# QNX Software Systems - Initial API and implementation +############################################################################### +ConfigureConsole.name=Configure +BuildStepsConsole.name=Build Steps +AutotoolsConsole.name=Autotools + +find_replace_action.label=&Find/Replace...@Ctrl+F +find_replace_action.tooltip=Find/Replace +find_replace_action.image= +find_replace_action.description=Find/Replace + +ConfigureConsolePage.&Copy@Ctrl+C_6=&Copy@Ctrl+C +ConfigureConsolePage.Copy_7=Copy +ConfigureConsolePage.Select_&All@Ctrl+A_12=Select &All@Ctrl+A +ConfigureConsolePage.Select_All=Select All + +ScrollLockAction.Scroll_Lock_1=Scroll Lock diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/HTMLPrinter.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/HTMLPrinter.java new file mode 100644 index 0000000000..a9de7d1159 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/HTMLPrinter.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2000 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * QNX Software System + *******************************************************************************/ +package org.eclipse.linuxtools.internal.cdt.autotools.ui; + +import java.io.IOException; +import java.io.Reader; + + +/** + * Provides a set of convenience methods for creating HTML pages. + */ +public class HTMLPrinter { + + private HTMLPrinter() { + } + + private static String replace(String text, char c, String s) { + + int previous= 0; + int current= text.indexOf(c, previous); + + if (current == -1) + return text; + + StringBuffer buffer= new StringBuffer(); + while (current > -1) { + buffer.append(text.substring(previous, current)); + buffer.append(s); + previous= current + 1; + current= text.indexOf(c, previous); + } + buffer.append(text.substring(previous)); + + return buffer.toString(); + } + + public static String convertToHTMLContent(String content) { + content= replace(content, '<', "<"); //$NON-NLS-1$ + return replace(content, '>', ">"); //$NON-NLS-1$ + } + + public static String read(Reader rd) { + + StringBuffer buffer= new StringBuffer(); + char[] readBuffer= new char[2048]; + + try { + int n= rd.read(readBuffer); + while (n > 0) { + buffer.append(readBuffer, 0, n); + n= rd.read(readBuffer); + } + return buffer.toString(); + } catch (IOException x) { + } + + return null; + } + + public static void insertPageProlog(StringBuffer buffer, int position) { + buffer.insert(position, "<html><body text=\"#000000\" bgcolor=\"#FFFF88\"><font size=-1>"); //$NON-NLS-1$ + } + + public static void addPageProlog(StringBuffer buffer) { + insertPageProlog(buffer, buffer.length()); + } + + public static void addPageEpilog(StringBuffer buffer) { + buffer.append("</font></body></html>"); //$NON-NLS-1$ + } + + public static void startBulletList(StringBuffer buffer) { + buffer.append("<ul>"); //$NON-NLS-1$ + } + + public static void endBulletList(StringBuffer buffer) { + buffer.append("</ul>"); //$NON-NLS-1$ + } + + public static void addBullet(StringBuffer buffer, String bullet) { + if (bullet != null) { + buffer.append("<li>"); //$NON-NLS-1$ + buffer.append(bullet); + buffer.append("</li>"); //$NON-NLS-1$ + } + } + + public static void addSmallHeader(StringBuffer buffer, String header) { + if (header != null) { + buffer.append("<h5>"); //$NON-NLS-1$ + buffer.append(header); + buffer.append("</h5>"); //$NON-NLS-1$ + } + } + + public static void addParagraph(StringBuffer buffer, String paragraph) { + if (paragraph != null) { + buffer.append("<p>"); //$NON-NLS-1$ + buffer.append(paragraph); + } + } + + public static void addParagraph(StringBuffer buffer, Reader paragraphReader) { + if (paragraphReader != null) + addParagraph(buffer, read(paragraphReader)); + } +}
\ No newline at end of file diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/LineBreakingReader.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/LineBreakingReader.java new file mode 100644 index 0000000000..52fb3e31e5 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/LineBreakingReader.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2000 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * QNX Software System + *******************************************************************************/ +package org.eclipse.linuxtools.internal.cdt.autotools.ui; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; + +import java.text.BreakIterator; +import org.eclipse.swt.graphics.GC; + +/* + * Not a real reader. Could change if requested + */ +public class LineBreakingReader { + + private BufferedReader fReader; + private GC fGC; + private int fMaxWidth; + + private String fLine; + private int fOffset; + + private BreakIterator fLineBreakIterator; + private int findNextBreakOffset(int currOffset) { + int currWidth= 0; + int nextOffset= fLineBreakIterator.following(currOffset); + while (nextOffset != BreakIterator.DONE) { + String word= fLine.substring(currOffset, nextOffset); + int wordWidth= fGC.textExtent(word).x; + int nextWidth= wordWidth + currWidth; + if (nextWidth > fMaxWidth) { + if (currWidth > 0) { + return currOffset; + } + return nextOffset; + } + currWidth= nextWidth; + currOffset= nextOffset; + nextOffset= fLineBreakIterator.next(); + } + return nextOffset; + } + private int findWordBegin(int idx) { + while (idx < fLine.length() && Character.isWhitespace(fLine.charAt(idx))) { + idx++; + } + return idx; + } + /** + * Creates a reader that breaks an input text to fit in a given width. + * @param reader Reader of the input text + * @param gc The graphic context that defines the currently used font sizes + * @param maxLineWidth The max width (pixes) where the text has to fit in + */ + public LineBreakingReader(Reader reader, GC gc, int maxLineWidth) { + fReader= new BufferedReader(reader); + fGC= gc; + fMaxWidth= maxLineWidth; + fOffset= 0; + fLine= null; + fLineBreakIterator= BreakIterator.getLineInstance(); + } + + public boolean isFormattedLine() { + return fLine != null; + } + + /** + * Reads the next line. The lengths of the line will not exceed the gived maximum + * width. + */ + public String readLine() throws IOException { + if (fLine == null) { + String line= fReader.readLine(); + if (line == null) { + return null; + } + + int lineLen= fGC.textExtent(line).x; + if (lineLen < fMaxWidth) { + return line; + } + fLine= line; + fLineBreakIterator.setText(line); + fOffset= 0; + } + int breakOffset= findNextBreakOffset(fOffset); + String res; + if (breakOffset != BreakIterator.DONE) { + res= fLine.substring(fOffset, breakOffset); + fOffset= findWordBegin(breakOffset); + if (fOffset == fLine.length()) { + fLine= null; + } + } else { + res= fLine.substring(fOffset); + fLine= null; + } + return res; + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/SingleCharReader.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/SingleCharReader.java new file mode 100644 index 0000000000..1d48fcc21b --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/SingleCharReader.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2000 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * QNX Software System + *******************************************************************************/ +package org.eclipse.linuxtools.internal.cdt.autotools.ui; + +import java.io.IOException; +import java.io.Reader; + + +public abstract class SingleCharReader extends Reader { + + /** + * @see Reader#read(char) + */ + public abstract int read() throws IOException; + + + /** + * @see Reader#read(char[],int,int) + */ + public int read(char cbuf[], int off, int len) throws IOException { + int end= off + len; + for (int i= off; i < end; i++) { + int ch= read(); + if (ch == -1) { + if (i == off) { + return -1; + } + return i - off; + } + cbuf[i]= (char)ch; + } + return len; + } + + /** + * @see Reader#ready() + */ + public boolean ready() throws IOException { + return true; + } + + /** + * Gets the content as a String + */ + public String getString() throws IOException { + StringBuffer buf= new StringBuffer(); + int ch; + while ((ch= read()) != -1) { + buf.append((char)ch); + } + return buf.toString(); + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/SubstitutionTextReader.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/SubstitutionTextReader.java new file mode 100644 index 0000000000..16d8400b98 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/SubstitutionTextReader.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2000 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * QNX Software System + *******************************************************************************/ +package org.eclipse.linuxtools.internal.cdt.autotools.ui; + + +import java.io.IOException; +import java.io.Reader; + + +/** + * Reads the text contents from a reader and computes for each character + * a potential substitution. The substitution may eat more characters than + * only the one passed into the computation routine. + */ +public abstract class SubstitutionTextReader extends SingleCharReader { + + protected static final String LINE_DELIM= System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ + + private Reader fReader; + private boolean fWasWhiteSpace; + private int fCharAfterWhiteSpace; + + private boolean fReadFromBuffer; + private StringBuffer fBuffer; + private int fIndex; + + + protected SubstitutionTextReader(Reader reader) { + fReader= reader; + fBuffer= new StringBuffer(); + fIndex= 0; + fReadFromBuffer= false; + fCharAfterWhiteSpace= -1; + fWasWhiteSpace= true; + } + + /** + * Implement to compute the substitution for the given character and + * if necessary subsequent characters. Use <code>nextChar</code> + * to read subsequent characters. + */ + protected abstract String computeSubstitution(int c) throws IOException; + + /** + * Returns the internal reader. + */ + protected Reader getReader() { + return fReader; + } + + /** + * Returns the next character. + */ + protected int nextChar() throws IOException { + fReadFromBuffer= (fBuffer.length() > 0); + if (fReadFromBuffer) { + char ch= fBuffer.charAt(fIndex++); + if (fIndex >= fBuffer.length()) { + fBuffer.setLength(0); + fIndex= 0; + } + return ch; + } + int ch= fCharAfterWhiteSpace; + if (ch == -1) { + ch= fReader.read(); + } + if (Character.isWhitespace((char)ch)) { + do { + ch= fReader.read(); + } while (Character.isWhitespace((char)ch)); + if (ch != -1) { + fCharAfterWhiteSpace= ch; + return ' '; + } + } else { + fCharAfterWhiteSpace= -1; + } + return ch; + } + + /** + * @see Reader#read() + */ + public int read() throws IOException { + int c; + do { + + c= nextChar(); + while (!fReadFromBuffer) { + String s= computeSubstitution(c); + if (s == null) + break; + if (s.length() > 0) + fBuffer.insert(0, s); + c= nextChar(); + } + + } while (fWasWhiteSpace && (c == ' ')); + + fWasWhiteSpace= (c == ' ' || c == '\r' || c == '\n'); + return c; + } + + /** + * @see Reader#ready() + */ + public boolean ready() throws IOException { + return fReader.ready(); + } + + /** + * @see Reader#close() + */ + public void close() throws IOException { + fReader.close(); + } + + /** + * @see Reader#reset() + */ + public void reset() throws IOException { + fReader.reset(); + fWasWhiteSpace= true; + fCharAfterWhiteSpace= -1; + fBuffer.setLength(0); + fIndex= 0; + } +}
\ No newline at end of file diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/preferences/AutotoolsEditorPreferenceConstants.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/preferences/AutotoolsEditorPreferenceConstants.java new file mode 100644 index 0000000000..5fbd71076a --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/preferences/AutotoolsEditorPreferenceConstants.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2002, 2005, 2007, 2009 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + * Red Hat Inc. - rename to use with Autotools editors + *******************************************************************************/ + +package org.eclipse.linuxtools.internal.cdt.autotools.ui.preferences; + +import org.eclipse.jface.preference.IPreferenceStore; + +/** + * MakefileEditorPreferenceConstants + */ +public class AutotoolsEditorPreferenceConstants { + + /** + * + */ + private AutotoolsEditorPreferenceConstants() { + } + + /** + * The symbolic names for colors for displaying code assist proposals + * @see org.eclipse.jface.resource.ColorRegistry + */ + public static final String CURRENT_LINE_COLOR = "org.eclipse.linuxtools.cdt.autotools.automake.ui.currentLineHightlightColor"; //$NON-NLS-1$ + public static final String LINE_NUMBER_RULER_COLOR = "org.eclipse.linuxtools.cdt.autotools.automake.ui.lineNumberForegroundColor"; //$NON-NLS-1$ + public static final String PRINT_MARGIN_COLOR = "org.eclipse.linuxtools.cdt.autotools.automake.ui.printMarginColor"; //$NON-NLS-1$ + + /** + * Preference key suffix for bold text style preference keys. + * + */ + public static final String EDITOR_BOLD_SUFFIX= "_bold"; //$NON-NLS-1$ + + /** + * Preference key suffix for italic text style preference keys. + */ + public static final String EDITOR_ITALIC_SUFFIX= "_italic"; //$NON-NLS-1$ + + + public static final String EDITOR_FOLDING_MACRODEF = "editor_folding_default_macrodef"; //$NON-NLS-1$ + + public static final String EDITOR_FOLDING_RULE = "editor_folding_default_rule"; //$NON-NLS-1$ + + public static final String EDITOR_FOLDING_CASE = "editor_folding_default_case"; //$NON-NLS-1$ + + public static final String EDITOR_FOLDING_CONDITIONAL = "editor_folding_default_conditional"; //$NON-NLS-1$ + + public static final String EDITOR_FOLDING_LOOP = "editor_folding_default_loop"; //$NON-NLS-1$ + + public static final String EDITOR_FOLDING_ENABLED = "editor_folding_enabled"; //$NON-NLS-1$ + + public static final String AUTOCONF_VERSION = "autoconf_version"; //$NON-NLS-1$ + + public static final String AUTOMAKE_VERSION = "automake_version"; //$NON-NLS-1$ + + public static final String LATEST_AC_VERSION = "2.61"; //$NON-NLS-1$ + + public static final String LATEST_AM_VERSION = "1.9.6"; //$NON-NLS-1$ + + public static void initializeDefaultValues(IPreferenceStore store) { + + store.setDefault(AutotoolsEditorPreferenceConstants.EDITOR_FOLDING_ENABLED, false); + store.setDefault(AutotoolsEditorPreferenceConstants.EDITOR_FOLDING_MACRODEF, false); + store.setDefault(AutotoolsEditorPreferenceConstants.EDITOR_FOLDING_RULE, true); + store.setDefault(AutotoolsEditorPreferenceConstants.EDITOR_FOLDING_CASE, true); + store.setDefault(AutotoolsEditorPreferenceConstants.EDITOR_FOLDING_CONDITIONAL, true); + store.setDefault(AutotoolsEditorPreferenceConstants.EDITOR_FOLDING_LOOP, true); + store.setDefault(AutotoolsEditorPreferenceConstants.AUTOCONF_VERSION, LATEST_AC_VERSION); + store.setDefault(AutotoolsEditorPreferenceConstants.AUTOMAKE_VERSION, LATEST_AM_VERSION); + } + +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/preferences/OverlayPreferenceStore.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/preferences/OverlayPreferenceStore.java new file mode 100644 index 0000000000..3c6a672572 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/preferences/OverlayPreferenceStore.java @@ -0,0 +1,455 @@ +/******************************************************************************* + * Copyright (c) 2002, 2006 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.internal.cdt.autotools.ui.preferences; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; + +/** + * OverlayPreferenceStore + */ +/** + * An overlaying preference store. + */ +class OverlayPreferenceStore implements IPreferenceStore { + + + public static final class TypeDescriptor { + TypeDescriptor() { + } + } + + public static final TypeDescriptor BOOLEAN= new TypeDescriptor(); + public static final TypeDescriptor DOUBLE= new TypeDescriptor(); + public static final TypeDescriptor FLOAT= new TypeDescriptor(); + public static final TypeDescriptor INT= new TypeDescriptor(); + public static final TypeDescriptor LONG= new TypeDescriptor(); + public static final TypeDescriptor STRING= new TypeDescriptor(); + + public static class OverlayKey { + + TypeDescriptor fDescriptor; + String fKey; + + public OverlayKey(TypeDescriptor descriptor, String key) { + fDescriptor= descriptor; + fKey= key; + } + } + + private class PropertyListener implements IPropertyChangeListener { + + /* + * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + OverlayKey key= findOverlayKey(event.getProperty()); + if (key != null) + propagateProperty(fParent, key, fStore); + } + } + + + IPreferenceStore fParent; + IPreferenceStore fStore; + private OverlayKey[] fOverlayKeys; + + private PropertyListener fPropertyListener; + + + public OverlayPreferenceStore(IPreferenceStore parent, OverlayKey[] overlayKeys) { + fParent= parent; + fOverlayKeys= overlayKeys; + fStore= new PreferenceStore(); + } + + OverlayKey findOverlayKey(String key) { + for (int i= 0; i < fOverlayKeys.length; i++) { + if (fOverlayKeys[i].fKey.equals(key)) + return fOverlayKeys[i]; + } + return null; + } + + private boolean covers(String key) { + return (findOverlayKey(key) != null); + } + + void propagateProperty(IPreferenceStore orgin, OverlayKey key, IPreferenceStore target) { + + if (orgin.isDefault(key.fKey)) { + if (!target.isDefault(key.fKey)) + target.setToDefault(key.fKey); + return; + } + + TypeDescriptor d= key.fDescriptor; + if (BOOLEAN == d) { + + boolean originValue= orgin.getBoolean(key.fKey); + boolean targetValue= target.getBoolean(key.fKey); + if (targetValue != originValue) + target.setValue(key.fKey, originValue); + + } else if (DOUBLE == d) { + + double originValue= orgin.getDouble(key.fKey); + double targetValue= target.getDouble(key.fKey); + if (targetValue != originValue) + target.setValue(key.fKey, originValue); + + } else if (FLOAT == d) { + + float originValue= orgin.getFloat(key.fKey); + float targetValue= target.getFloat(key.fKey); + if (targetValue != originValue) + target.setValue(key.fKey, originValue); + + } else if (INT == d) { + + int originValue= orgin.getInt(key.fKey); + int targetValue= target.getInt(key.fKey); + if (targetValue != originValue) + target.setValue(key.fKey, originValue); + + } else if (LONG == d) { + + long originValue= orgin.getLong(key.fKey); + long targetValue= target.getLong(key.fKey); + if (targetValue != originValue) + target.setValue(key.fKey, originValue); + + } else if (STRING == d) { + + String originValue= orgin.getString(key.fKey); + String targetValue= target.getString(key.fKey); + if (targetValue != null && originValue != null && !targetValue.equals(originValue)) + target.setValue(key.fKey, originValue); + + } + } + + public void propagate() { + for (int i= 0; i < fOverlayKeys.length; i++) + propagateProperty(fStore, fOverlayKeys[i], fParent); + } + + private void loadProperty(IPreferenceStore orgin, OverlayKey key, IPreferenceStore target, boolean forceInitialization) { + TypeDescriptor d= key.fDescriptor; + if (BOOLEAN == d) { + + if (forceInitialization) + target.setValue(key.fKey, true); + target.setValue(key.fKey, orgin.getBoolean(key.fKey)); + target.setDefault(key.fKey, orgin.getDefaultBoolean(key.fKey)); + + } else if (DOUBLE == d) { + + if (forceInitialization) + target.setValue(key.fKey, 1.0D); + target.setValue(key.fKey, orgin.getDouble(key.fKey)); + target.setDefault(key.fKey, orgin.getDefaultDouble(key.fKey)); + + } else if (FLOAT == d) { + + if (forceInitialization) + target.setValue(key.fKey, 1.0F); + target.setValue(key.fKey, orgin.getFloat(key.fKey)); + target.setDefault(key.fKey, orgin.getDefaultFloat(key.fKey)); + + } else if (INT == d) { + + if (forceInitialization) + target.setValue(key.fKey, 1); + target.setValue(key.fKey, orgin.getInt(key.fKey)); + target.setDefault(key.fKey, orgin.getDefaultInt(key.fKey)); + + } else if (LONG == d) { + + if (forceInitialization) + target.setValue(key.fKey, 1L); + target.setValue(key.fKey, orgin.getLong(key.fKey)); + target.setDefault(key.fKey, orgin.getDefaultLong(key.fKey)); + + } else if (STRING == d) { + + if (forceInitialization) + target.setValue(key.fKey, "1"); //$NON-NLS-1$ + target.setValue(key.fKey, orgin.getString(key.fKey)); + target.setDefault(key.fKey, orgin.getDefaultString(key.fKey)); + + } + } + + public void load() { + for (int i= 0; i < fOverlayKeys.length; i++) + loadProperty(fParent, fOverlayKeys[i], fStore, true); + } + + public void loadDefaults() { + for (int i= 0; i < fOverlayKeys.length; i++) + setToDefault(fOverlayKeys[i].fKey); + } + + public void start() { + if (fPropertyListener == null) { + fPropertyListener= new PropertyListener(); + fParent.addPropertyChangeListener(fPropertyListener); + } + } + + public void stop() { + if (fPropertyListener != null) { + fParent.removePropertyChangeListener(fPropertyListener); + fPropertyListener= null; + } + } + + /* + * @see IPreferenceStore#addPropertyChangeListener(IPropertyChangeListener) + */ + public void addPropertyChangeListener(IPropertyChangeListener listener) { + fStore.addPropertyChangeListener(listener); + } + + /* + * @see IPreferenceStore#removePropertyChangeListener(IPropertyChangeListener) + */ + public void removePropertyChangeListener(IPropertyChangeListener listener) { + fStore.removePropertyChangeListener(listener); + } + + /* + * @see IPreferenceStore#firePropertyChangeEvent(String, Object, Object) + */ + public void firePropertyChangeEvent(String name, Object oldValue, Object newValue) { + fStore.firePropertyChangeEvent(name, oldValue, newValue); + } + + /* + * @see IPreferenceStore#contains(String) + */ + public boolean contains(String name) { + return fStore.contains(name); + } + + /* + * @see IPreferenceStore#getBoolean(String) + */ + public boolean getBoolean(String name) { + return fStore.getBoolean(name); + } + + /* + * @see IPreferenceStore#getDefaultBoolean(String) + */ + public boolean getDefaultBoolean(String name) { + return fStore.getDefaultBoolean(name); + } + + /* + * @see IPreferenceStore#getDefaultDouble(String) + */ + public double getDefaultDouble(String name) { + return fStore.getDefaultDouble(name); + } + + /* + * @see IPreferenceStore#getDefaultFloat(String) + */ + public float getDefaultFloat(String name) { + return fStore.getDefaultFloat(name); + } + + /* + * @see IPreferenceStore#getDefaultInt(String) + */ + public int getDefaultInt(String name) { + return fStore.getDefaultInt(name); + } + + /* + * @see IPreferenceStore#getDefaultLong(String) + */ + public long getDefaultLong(String name) { + return fStore.getDefaultLong(name); + } + + /* + * @see IPreferenceStore#getDefaultString(String) + */ + public String getDefaultString(String name) { + return fStore.getDefaultString(name); + } + + /* + * @see IPreferenceStore#getDouble(String) + */ + public double getDouble(String name) { + return fStore.getDouble(name); + } + + /* + * @see IPreferenceStore#getFloat(String) + */ + public float getFloat(String name) { + return fStore.getFloat(name); + } + + /* + * @see IPreferenceStore#getInt(String) + */ + public int getInt(String name) { + return fStore.getInt(name); + } + + /* + * @see IPreferenceStore#getLong(String) + */ + public long getLong(String name) { + return fStore.getLong(name); + } + + /* + * @see IPreferenceStore#getString(String) + */ + public String getString(String name) { + return fStore.getString(name); + } + + /* + * @see IPreferenceStore#isDefault(String) + */ + public boolean isDefault(String name) { + return fStore.isDefault(name); + } + + /* + * @see IPreferenceStore#needsSaving() + */ + public boolean needsSaving() { + return fStore.needsSaving(); + } + + /* + * @see IPreferenceStore#putValue(String, String) + */ + public void putValue(String name, String value) { + if (covers(name)) + fStore.putValue(name, value); + } + + /* + * @see IPreferenceStore#setDefault(String, double) + */ + public void setDefault(String name, double value) { + if (covers(name)) + fStore.setDefault(name, value); + } + + /* + * @see IPreferenceStore#setDefault(String, float) + */ + public void setDefault(String name, float value) { + if (covers(name)) + fStore.setDefault(name, value); + } + + /* + * @see IPreferenceStore#setDefault(String, int) + */ + public void setDefault(String name, int value) { + if (covers(name)) + fStore.setDefault(name, value); + } + + /* + * @see IPreferenceStore#setDefault(String, long) + */ + public void setDefault(String name, long value) { + if (covers(name)) + fStore.setDefault(name, value); + } + + /* + * @see IPreferenceStore#setDefault(String, String) + */ + public void setDefault(String name, String value) { + if (covers(name)) + fStore.setDefault(name, value); + } + + /* + * @see IPreferenceStore#setDefault(String, boolean) + */ + public void setDefault(String name, boolean value) { + if (covers(name)) + fStore.setDefault(name, value); + } + + /* + * @see IPreferenceStore#setToDefault(String) + */ + public void setToDefault(String name) { + fStore.setToDefault(name); + } + + /* + * @see IPreferenceStore#setValue(String, double) + */ + public void setValue(String name, double value) { + if (covers(name)) + fStore.setValue(name, value); + } + + /* + * @see IPreferenceStore#setValue(String, float) + */ + public void setValue(String name, float value) { + if (covers(name)) + fStore.setValue(name, value); + } + + /* + * @see IPreferenceStore#setValue(String, int) + */ + public void setValue(String name, int value) { + if (covers(name)) + fStore.setValue(name, value); + } + + /* + * @see IPreferenceStore#setValue(String, long) + */ + public void setValue(String name, long value) { + if (covers(name)) + fStore.setValue(name, value); + } + + /* + * @see IPreferenceStore#setValue(String, String) + */ + public void setValue(String name, String value) { + if (covers(name)) + fStore.setValue(name, value); + } + + /* + * @see IPreferenceStore#setValue(String, boolean) + */ + public void setValue(String name, boolean value) { + if (covers(name)) + fStore.setValue(name, value); + } +} diff --git a/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/preferences/StatusInfo.java b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/preferences/StatusInfo.java new file mode 100644 index 0000000000..3ae395a617 --- /dev/null +++ b/autotools/org.eclipse.linuxtools.cdt.autotools/src/org/eclipse/linuxtools/internal/cdt/autotools/ui/preferences/StatusInfo.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) 2002, 2006 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.internal.cdt.autotools.ui.preferences; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.linuxtools.cdt.autotools.AutotoolsPlugin; + + +/** + * A settable IStatus. + * Can be an error, warning, info or ok. For error, info and warning states, + * a message describes the problem. + */ +public class StatusInfo implements IStatus { + + private String fStatusMessage; + private int fSeverity; + + /** + * Creates a status set to OK (no message) + */ + public StatusInfo() { + this(OK, null); + } + + /** + * Creates a status . + * @param severity The status severity: ERROR, WARNING, INFO and OK. + * @param message The message of the status. Applies only for ERROR, + * WARNING and INFO. + */ + public StatusInfo(int severity, String message) { + fStatusMessage= message; + fSeverity= severity; + } + + /** + * Returns if the status' severity is OK. + */ + public boolean isOK() { + return fSeverity == IStatus.OK; + } + + /** + * Returns if the status' severity is WARNING. + */ + public boolean isWarning() { + return fSeverity == IStatus.WARNING; + } + + /** + * Returns if the status' severity is INFO. + */ + public boolean isInfo() { + return fSeverity == IStatus.INFO; + } + + /** + * Returns if the status' severity is ERROR. + */ + public boolean isError() { + return fSeverity == IStatus.ERROR; + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.IStatus#getMessage() + */ + public String getMessage() { + return fStatusMessage; + } + + /** + * Sets the status to ERROR. + * @param errorMessage The error message (can be empty, but not null) + */ + public void setError(String errorMessage) { + Assert.isNotNull(errorMessage); + fStatusMessage= errorMessage; + fSeverity= IStatus.ERROR; + } + + /** + * Sets the status to WARNING. + * @param warningMessage The warning message (can be empty, but not null) + */ + public void setWarning(String warningMessage) { + Assert.isNotNull(warningMessage); + fStatusMessage= warningMessage; + fSeverity= IStatus.WARNING; + } + + /** + * Sets the status to INFO. + * @param infoMessage The info message (can be empty, but not null) + */ + public void setInfo(String infoMessage) { + Assert.isNotNull(infoMessage); + fStatusMessage= infoMessage; + fSeverity= IStatus.INFO; + } + + /** + * Sets the status to OK. + */ + public void setOK() { + fStatusMessage= null; + fSeverity= IStatus.OK; + } + + /* + * @see IStatus#matches(int) + */ + public boolean matches(int severityMask) { + return (fSeverity & severityMask) != 0; + } + + /** + * Returns always <code>false</code>. + * @see IStatus#isMultiStatus() + */ + public boolean isMultiStatus() { + return false; + } + + /* + * @see IStatus#getSeverity() + */ + public int getSeverity() { + return fSeverity; + } + + /* + * @see IStatus#getPlugin() + */ + public String getPlugin() { + return AutotoolsPlugin.getPluginId(); + } + + /** + * Returns always <code>null</code>. + * @see IStatus#getException() + */ + public Throwable getException() { + return null; + } + + /** + * Returns always the error severity. + * @see IStatus#getCode() + */ + public int getCode() { + return fSeverity; + } + + /** + * Returns always <code>null</code>. + * @see IStatus#getChildren() + */ + public IStatus[] getChildren() { + return new IStatus[0]; + } + +} |