1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Improve on the GNU makefile parser

This commit is contained in:
Alain Magloire 2003-09-19 05:03:27 +00:00
parent 5484799800
commit 0de973e3c5
68 changed files with 2793 additions and 949 deletions

View file

@ -10,6 +10,7 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.core; package org.eclipse.cdt.make.core;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.Map; import java.util.Map;
@ -17,8 +18,11 @@ import java.util.MissingResourceException;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.make.core.makefile.IMakefile;
import org.eclipse.cdt.make.internal.core.BuildInfoFactory; import org.eclipse.cdt.make.internal.core.BuildInfoFactory;
import org.eclipse.cdt.make.internal.core.MakeTargetManager; import org.eclipse.cdt.make.internal.core.MakeTargetManager;
import org.eclipse.cdt.make.internal.core.makefile.gnu.GNUMakefile;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
@ -147,6 +151,25 @@ public class MakeCorePlugin extends Plugin {
} }
return fTargetManager; return fTargetManager;
} }
public IMakefile createMakefile(IFile file) {
GNUMakefile gnu = new GNUMakefile();
try {
gnu.parse(file.getLocation().toOSString());
String[] dirs = gnu.getIncludeDirectories();
String[] includes = new String[dirs.length + 1];
System.arraycopy(dirs, 0, includes, 0, dirs.length);
String cwd = file.getLocation().removeLastSegments(1).toOSString();
includes[dirs.length] = cwd;
gnu.setIncludeDirectories(includes);
} catch (IOException e) {
}
return gnu;
//
// base on a preference to chose GNU vs Posix
//return PosixMakefile(file.getLocation);
}
public void shutdown() throws CoreException { public void shutdown() throws CoreException {
super.shutdown(); super.shutdown();
if ( fTargetManager != null) { if ( fTargetManager != null) {
@ -154,4 +177,5 @@ public class MakeCorePlugin extends Plugin {
fTargetManager = null; fTargetManager = null;
} }
} }
} }

View file

@ -0,0 +1,19 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.core.makefile;
/**
* IArchiveTarget
*/
public interface IArchiveTarget extends ITarget {
String getMember();
}

View file

@ -10,11 +10,14 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.core.makefile; package org.eclipse.cdt.make.core.makefile;
import java.io.File;
import java.io.IOException;
/** /**
* ICommand * ICommand
*/ */
public interface ICommand extends IStatement { public interface ICommand extends IDirective {
final public static char HYPHEN = '-'; final public static char HYPHEN = '-';
@ -54,4 +57,11 @@ public interface ICommand extends IStatement {
*/ */
boolean shouldExecute(); boolean shouldExecute();
}
/**
* Executes the command in a separate process with the
* specified environment and working directory.
*
*/
Process execute(String shell, String[] envp, File dir) throws IOException;
}

View file

@ -13,7 +13,7 @@ package org.eclipse.cdt.make.core.makefile;
/** /**
* IComment * IComment
*/ */
public interface IComment extends IStatement { public interface IComment extends IDirective {
final public static char POUND = '#'; final public static char POUND = '#';

View file

@ -0,0 +1,20 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.core.makefile;
/**
* .DEFAULT
* If the makefile uses this special target, the application shall ensure that it is
* specified with commands, but without prerequisites.
* The commands shall be used by make if there are no other rules available to build a target.
*/
public interface IDefaultRule extends ISpecialRule {
}

View file

@ -12,7 +12,7 @@ package org.eclipse.cdt.make.core.makefile;
/** /**
*/ */
public interface IStatement { public interface IDirective {
int getStartLine(); int getStartLine();

View file

@ -13,5 +13,5 @@ package org.eclipse.cdt.make.core.makefile;
/** /**
* IEmptyLine * IEmptyLine
*/ */
public interface IEmptyLine extends IStatement { public interface IEmptyLine extends IDirective {
} }

View file

@ -0,0 +1,19 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.core.makefile;
/**
* .IGNORE
* Prerequisites of this special target are targets themselves; this shall cause errors
* from commands associated with them to be ignored in the same manner as specified by the -i option.
*/
public interface IIgnoreRule extends ISpecialRule {
}

View file

@ -13,9 +13,19 @@ package org.eclipse.cdt.make.core.makefile;
/** /**
* IMacroDefinition * IMacroDefinition
*/ */
public interface IMacroDefinition extends IStatement { public interface IMacroDefinition extends IDirective {
public abstract String getName(); String getName();
public abstract String getValue(); StringBuffer getValue();
boolean isFromDefault();
boolean isFromMakefile();
boolean isFromEnviroment();
boolean isFromEnvironmentOverride();
boolean isFromCommand();
} }

View file

@ -10,12 +10,14 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.core.makefile; package org.eclipse.cdt.make.core.makefile;
import java.io.IOException;
import java.io.Reader;
/** /**
* IMakefile * IMakefile
*/ */
public interface IMakefile { public interface IMakefile extends IParent {
IStatement[] getStatements();
IRule[] getRules(); IRule[] getRules();
IRule[] getRule(String target); IRule[] getRule(String target);
IInferenceRule[] getInferenceRules(); IInferenceRule[] getInferenceRules();
@ -24,5 +26,6 @@ public interface IMakefile {
ITargetRule[] getTargetRule(String target); ITargetRule[] getTargetRule(String target);
IMacroDefinition[] getMacroDefinitions(); IMacroDefinition[] getMacroDefinitions();
IMacroDefinition[] getMacroDefinition(String name); IMacroDefinition[] getMacroDefinition(String name);
IStatement[] getBuiltins(); IDirective[] getBuiltins();
} void parse(Reader makefile) throws IOException;
}

View file

@ -0,0 +1,19 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.core.makefile;
/**
* IParent
*/
public interface IParent extends IDirective {
IDirective[] getStatements();
}

View file

@ -0,0 +1,19 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.core.makefile;
/**
* .POSIX
* The application shall ensure that this special target is specified without
* prerequisites or commands.
*/
public interface IPosixRule extends ISpecialRule {
}

View file

@ -0,0 +1,19 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.core.makefile;
/**
* .PRECIOUS
* Prerequisites of this special target shall not be removed if make recieves an
* asynchronous events.
*/
public interface IPreciousRule extends ISpecialRule {
}

View file

@ -13,7 +13,7 @@ package org.eclipse.cdt.make.core.makefile;
/** /**
* There are two kinds of rules: Inference rules and target rules * There are two kinds of rules: Inference rules and target rules
*/ */
public interface IRule extends IStatement { public interface IRule extends IParent {
/** /**
* Array of command for the rule. * Array of command for the rule.
* @return * @return
@ -26,4 +26,4 @@ public interface IRule extends IStatement {
*/ */
ITarget getTarget(); ITarget getTarget();
} }

View file

@ -0,0 +1,20 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.core.makefile;
/**
* .SCCS_GET
* The application shall ensure that this special target is specified without prerequesites.
* The commands specified with this target shall replace the default
* commands associated with this special target.
*/
public interface ISccsGetRule extends ISpecialRule {
}

View file

@ -0,0 +1,20 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.core.makefile;
/**
* .SILENT
* Prerequisites of this special target are targets themselves; this shall case
* commands associated with them not to be written to the standard output before
* they are executed.
*/
public interface ISilentRule extends ISpecialRule {
}

View file

@ -0,0 +1,23 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.core.makefile;
/**
* Target rule that have special meaning for Make.
*/
public interface ISpecialRule extends IRule {
/**
* The meaning of the prerequistes are specific to
* each rules.
*/
String[] getPrerequisites();
}

View file

@ -0,0 +1,19 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.core.makefile;
/**
* .SUFFIXES
* Prerequesites of .SUFFIXES shall be appended to the list of known suffixes and are
* used in conjunction with the inference rules.
*/
public interface ISuffixesRule extends ISpecialRule {
}

View file

@ -14,6 +14,7 @@ package org.eclipse.cdt.make.core.makefile;
* ITarget * ITarget
*/ */
public interface ITarget { public interface ITarget {
String toString(); String toString();
boolean isUptodate();
} }

View file

@ -14,5 +14,6 @@ package org.eclipse.cdt.make.core.makefile;
* ITargetRule * ITargetRule
*/ */
public interface ITargetRule extends IRule { public interface ITargetRule extends IRule {
ITarget[] getDependencies();
} String[] getPrerequisites();
}

View file

@ -17,7 +17,7 @@ import org.eclipse.cdt.make.core.makefile.IInferenceRule;
import org.eclipse.cdt.make.core.makefile.IMacroDefinition; import org.eclipse.cdt.make.core.makefile.IMacroDefinition;
import org.eclipse.cdt.make.core.makefile.IMakefile; import org.eclipse.cdt.make.core.makefile.IMakefile;
import org.eclipse.cdt.make.core.makefile.IRule; import org.eclipse.cdt.make.core.makefile.IRule;
import org.eclipse.cdt.make.core.makefile.IStatement; import org.eclipse.cdt.make.core.makefile.IDirective;
import org.eclipse.cdt.make.core.makefile.ITargetRule; import org.eclipse.cdt.make.core.makefile.ITargetRule;
/** /**
@ -36,17 +36,15 @@ import org.eclipse.cdt.make.core.makefile.ITargetRule;
* internal_macro : "$<" | "$*" | "$@" | "$?" | "$%" * internal_macro : "$<" | "$*" | "$@" | "$?" | "$%"
*/ */
public abstract class AbstractMakefile implements IMakefile { public abstract class AbstractMakefile extends Parent implements IMakefile {
public AbstractMakefile() { public AbstractMakefile() {
} }
public abstract IStatement[] getStatements(); public abstract IDirective[] getBuiltins();
public abstract IStatement[] getBuiltins();
public abstract void addStatement(IStatement statement);
public IRule[] getRules() { public IRule[] getRules() {
IStatement[] stmts = getStatements(); IDirective[] stmts = getStatements();
List array = new ArrayList(stmts.length); List array = new ArrayList(stmts.length);
for (int i = 0; i < stmts.length; i++) { for (int i = 0; i < stmts.length; i++) {
if (stmts[i] instanceof IRule) { if (stmts[i] instanceof IRule) {
@ -112,7 +110,7 @@ public abstract class AbstractMakefile implements IMakefile {
} }
public IMacroDefinition[] getMacroDefinitions() { public IMacroDefinition[] getMacroDefinitions() {
IStatement[] stmts = getStatements(); IDirective[] stmts = getStatements();
List array = new ArrayList(stmts.length); List array = new ArrayList(stmts.length);
for (int i = 0; i < stmts.length; i++) { for (int i = 0; i < stmts.length; i++) {
if (stmts[i] instanceof IMacroDefinition) { if (stmts[i] instanceof IMacroDefinition) {
@ -134,7 +132,7 @@ public abstract class AbstractMakefile implements IMakefile {
} }
public IMacroDefinition[] getBuiltinMacroDefinitions() { public IMacroDefinition[] getBuiltinMacroDefinitions() {
IStatement[] stmts = getBuiltins(); IDirective[] stmts = getBuiltins();
List array = new ArrayList(stmts.length); List array = new ArrayList(stmts.length);
for (int i = 0; i < stmts.length; i++) { for (int i = 0; i < stmts.length; i++) {
if (stmts[i] instanceof IMacroDefinition) { if (stmts[i] instanceof IMacroDefinition) {
@ -156,7 +154,7 @@ public abstract class AbstractMakefile implements IMakefile {
} }
public IInferenceRule[] getBuiltinInferenceRules() { public IInferenceRule[] getBuiltinInferenceRules() {
IStatement[] stmts = getBuiltins(); IDirective[] stmts = getBuiltins();
List array = new ArrayList(stmts.length); List array = new ArrayList(stmts.length);
for (int i = 0; i < stmts.length; i++) { for (int i = 0; i < stmts.length; i++) {
if (stmts[i] instanceof IInferenceRule) { if (stmts[i] instanceof IInferenceRule) {
@ -177,9 +175,4 @@ public abstract class AbstractMakefile implements IMakefile {
return (IInferenceRule[]) array.toArray(new IInferenceRule[0]); return (IInferenceRule[]) array.toArray(new IInferenceRule[0]);
} }
public void addStatements(IStatement[] stmts) {
for (int i = 0; i < stmts.length; i++) {
addStatement(stmts[i]);
}
}
} }

View file

@ -0,0 +1,33 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile;
/**
* IArchiveTarget
*/
public class ArchiveTarget extends Target {
String member;
public ArchiveTarget(String lib, String obj) {
super(lib);
member = obj;
}
public String getMember() {
return member;
}
public String getLibaryName() {
return toString();
}
}

View file

@ -10,6 +10,9 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile; package org.eclipse.cdt.make.internal.core.makefile;
import java.io.File;
import java.io.IOException;
import org.eclipse.cdt.make.core.makefile.ICommand; import org.eclipse.cdt.make.core.makefile.ICommand;
/** /**
@ -73,16 +76,16 @@ public class Command extends Statement implements ICommand {
public String toString() { public String toString() {
StringBuffer cmd = new StringBuffer(); StringBuffer cmd = new StringBuffer();
cmd.append((char) '\t'); cmd.append( '\t');
if (getPrefix() != 0) { if (getPrefix() != 0) {
cmd.append(getPrefix()); cmd.append(getPrefix());
} }
cmd.append(command).append((char) '\n'); cmd.append(command).append('\n');
return cmd.toString(); return cmd.toString();
} }
public boolean equals(Command cmd) { public boolean equals(Command cmd) {
return cmd.getPrefix() == getPrefix() && cmd.toString().equals(toString()); return cmd.toString().equals(toString());
} }
char getPrefix() { char getPrefix() {
@ -96,7 +99,16 @@ public class Command extends Statement implements ICommand {
command = cmd.trim(); command = cmd.trim();
if (command.startsWith(HYPHEN_STRING) || command.startsWith(AT_STRING) || command.startsWith(PLUS_STRING)) { if (command.startsWith(HYPHEN_STRING) || command.startsWith(AT_STRING) || command.startsWith(PLUS_STRING)) {
prefix = command.charAt(0); prefix = command.charAt(0);
command = command.substring(1); command = command.substring(1).trim();
} }
} }
/* (non-Javadoc)
* @see org.eclipse.cdt.make.core.makefile.ICommand#execute(java.lang.String[], java.io.File)
*/
public Process execute(String shell, String[] envp, File dir) throws IOException {
String[] cmdArray = new String[] { shell, "-c", command};
return Runtime.getRuntime().exec(cmdArray, envp, dir);
}
} }

View file

@ -0,0 +1,27 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile;
import org.eclipse.cdt.make.core.makefile.ICommand;
import org.eclipse.cdt.make.core.makefile.IDefaultRule;
/**
* .DEFAULT
* If the makefile uses this special target, the application shall ensure that it is
* specified with commands, but without prerequisites.
*/
public class DefaultRule extends SpecialRule implements IDefaultRule {
public DefaultRule(ICommand[] cmds) {
super(new Target(".DEFAULT"), new String[0], cmds);
}
}

View file

@ -0,0 +1,28 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile;
import org.eclipse.cdt.make.core.makefile.IIgnoreRule;
import org.eclipse.cdt.make.core.makefile.ICommand;
/**
* .IGNORE
* Prerequistes of this special target are targets themselves; this shall cause errors
* from commands associated with them to be ignored in the same manner as
* specified by the -i option.
*/
public class IgnoreRule extends SpecialRule implements IIgnoreRule {
public IgnoreRule(String[] reqs) {
super(new Target(".IGNORE"), reqs, new ICommand[0]);
}
}

View file

@ -15,20 +15,16 @@ import org.eclipse.cdt.make.core.makefile.ITarget;
public class InferenceRule extends Rule { public class InferenceRule extends Rule {
public InferenceRule(String tgt) {
this (new Target(tgt));
}
public InferenceRule(ITarget target) { public InferenceRule(ITarget target) {
this(target, new Command[0]); this(target, new Command[0]);
} }
public InferenceRule(String tgt, ICommand[] commands) { public InferenceRule(String tgt, ICommand[] cmds) {
this(new Target(tgt), commands); this(new Target(tgt), cmds);
} }
public InferenceRule(ITarget target, ICommand[] commands) { public InferenceRule(ITarget target, ICommand[] cmds) {
super(target, commands); super(target, cmds);
} }
/** /**
@ -36,8 +32,7 @@ public class InferenceRule extends Rule {
*/ */
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append(target).append(':'); buffer.append(getTarget().toString()).append(":\n");
buffer.append('\n');
ICommand[] cmds = getCommands(); ICommand[] cmds = getCommands();
for (int i = 0; i < cmds.length; i++) { for (int i = 0; i < cmds.length; i++) {
buffer.append(cmds[i].toString()); buffer.append(cmds[i].toString());

View file

@ -17,30 +17,19 @@ import org.eclipse.cdt.make.core.makefile.IMacroDefinition;
public class MacroDefinition extends Statement implements IMacroDefinition { public class MacroDefinition extends Statement implements IMacroDefinition {
String name; String name;
StringBuffer value; StringBuffer value;
char sepChar; boolean fromCommand;
boolean fromDefault;
public MacroDefinition(String line) { boolean fromMakefile;
value = new StringBuffer(); boolean fromEnvironment;
int index = line.indexOf('='); boolean fromEnvironmentOverride;
if (index != -1) {
int separator = index;
// Check for "+=", ":="
if (index > 0) {
sepChar = line.charAt(index - 1);
if (sepChar == ':' || sepChar =='+' || sepChar == '?') {
separator = index - 1;
}
}
name = line.substring(0, separator).trim();
value.append(line.substring(index + 1));
} else {
name = line;
}
}
public MacroDefinition(String n, String v) { public MacroDefinition(String n, String v) {
this(n, new StringBuffer(v));
}
public MacroDefinition(String n, StringBuffer v) {
name = n; name = n;
value = new StringBuffer(v); value = v;
} }
public String getName() { public String getName() {
@ -51,16 +40,8 @@ public class MacroDefinition extends Statement implements IMacroDefinition {
name = (n == null) ? "" : n.trim() ; name = (n == null) ? "" : n.trim() ;
} }
public String getValue() { public StringBuffer getValue() {
return value.toString().trim(); return value;
}
public void setValue(String val) {
value = new StringBuffer(val);
}
public void append(String val) {
value.append(' ').append(val);
} }
/** /**
@ -75,4 +56,60 @@ public class MacroDefinition extends Statement implements IMacroDefinition {
public boolean equals(MacroDefinition v) { public boolean equals(MacroDefinition v) {
return v.getName().equals(getName()); return v.getName().equals(getName());
} }
public void setFromCommand(boolean from) {
fromCommand = from;
}
public void setFromDefault(boolean from) {
fromDefault = from;
}
public void setFromEnviroment(boolean from) {
fromEnvironment = from;
}
public void setFromEnviromentOverride(boolean from) {
fromEnvironmentOverride = from;
}
public void setFromMakefile(boolean from) {
fromMakefile = from;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.make.core.makefile.IMacroDefinition#isFromCommand()
*/
public boolean isFromCommand() {
return fromCommand;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.make.core.makefile.IMacroDefinition#isFromDefault()
*/
public boolean isFromDefault() {
return fromDefault;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.make.core.makefile.IMacroDefinition#isFromEnviroment()
*/
public boolean isFromEnviroment() {
return fromEnvironment;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.make.core.makefile.IMacroDefinition#isFromEnviroment()
*/
public boolean isFromEnvironmentOverride() {
return fromEnvironmentOverride;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.make.core.makefile.IMacroDefinition#isFromMakefile()
*/
public boolean isFromMakefile() {
return fromMakefile;
}
} }

View file

@ -1,95 +0,0 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import org.eclipse.cdt.make.core.makefile.*;
/**
* Makefile : ( statement ) *
* statement : rule | macro_definition | comments | empty
* rule : inference_rule | target_rule
* inference_rule : target ':' <nl> ( <tab> command <nl> ) +
* target_rule : target [ ( target ) * ] ':' [ ( prerequisite ) * ] [ ';' command ] <nl>
[ ( command ) * ]
* macro_definition : string '=' (string)*
* comments : ('#' (string) <nl>) *
* empty : <nl>
* command : <tab> prefix_command string <nl>
* target : string
* prefix_command : '-' | '@' | '+'
* internal_macro : "$<" | "$*" | "$@" | "$?" | "$%"
*/
public abstract class Makefile {
String filename;
public Makefile(String name) throws FileNotFoundException, IOException {
filename = name;
}
public abstract List getStatements();
public abstract List getBuiltins();
public String getFileName() {
return filename;
}
public IInferenceRule[] getRules() {
return null;
}
public IInferenceRule getRule(String target) {
return null;
}
public InferenceRule[] getInferenceRules() {
return null;
}
public InferenceRule getInferenceRule(String target) {
return null;
}
public ITargetRule[] getTargetRules() {
return null;
}
public ITargetRule getTargetRule(String target) {
return null;
}
public IInferenceRule[] getBuiltinRules() {
return null;
}
public IInferenceRule getBuiltinRule(String target) {
return null;
}
public IInferenceRule[] getBuiltinInferenceRules() {
return null;
}
public IInferenceRule getBuiltinInferenceRule(String target) {
return null;
}
public MacroDefinition[] getMacros() {
return null;
}
public MacroDefinition getMacro(String name) {
return null;
}
public MacroDefinition[] getBuiltinMacros() {
return null;
}
public MacroDefinition getBuiltinMacro(String name) {
return null;
}
}

View file

@ -42,7 +42,7 @@ public class MakefileReader extends LineNumberReader {
if (escapedLine && line.length() > 0) { if (escapedLine && line.length() > 0) {
// Eat the spaces at the beginning. // Eat the spaces at the beginning.
int i = 0; int i = 0;
while (i < line.length() && (MakefileUtil.isSpace(line.charAt(i)))) { while (i < line.length() && (Util.isSpace(line.charAt(i)))) {
i++ ; i++ ;
} }
line = line.substring(i); line = line.substring(i);
@ -61,10 +61,10 @@ public class MakefileReader extends LineNumberReader {
// When an escaped <newline> is found in a command line in a makefile, // When an escaped <newline> is found in a command line in a makefile,
// the command line shall contain the backslash, the <newline>, and the next line, // the command line shall contain the backslash, the <newline>, and the next line,
// except that the first character of the next line shall not be included if it is a <tab> // except that the first character of the next line shall not be included if it is a <tab>
if (MakefileUtil.isEscapedLine(line)) { if (Util.isEscapedLine(line)) {
int index = line.lastIndexOf('\\'); int index = line.lastIndexOf('\\');
if (index > 0) { if (index > 0) {
if (!escapedLine && MakefileUtil.isCommand(line)) { if (!escapedLine && Util.isCommand(line)) {
escapedCommand = true; escapedCommand = true;
buffer.append(line); buffer.append(line);
} else { } else {

View file

@ -1,161 +0,0 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile;
import java.util.ArrayList;
import java.util.List;
/**
*/
public class MakefileUtil {
private MakefileUtil() {
}
public static String[] findPrerequisites(String line) {
return findTargets(line);
}
public static String[] findTargets(String line) {
List aList = new ArrayList();
int space;
// Trim away trailing and prepending spaces.
line = line.trim();
while ((space = indexOf(line, ' ')) != -1) {
aList.add(line.substring(0, space).trim());
line = line.substring(space + 1).trim();
}
// The last target.
if (line.length() > 0) {
aList.add(line);
}
return (String[]) aList.toArray(new String[0]);
}
public static boolean isMacroDefinition(String line) {
return isMacroDefinition(line.toCharArray());
}
public static boolean isMacroDefinition(char[] line) {
return indexOf(line, '=') != -1;
}
public static boolean isTargetRule(String line) {
return isTargetRule(line.toCharArray());
}
public static boolean isTargetRule(char[] line) {
int colon = indexOf(line, ':');
if (colon != -1) {
colon++;
// Things like := are not targets but :: is
if (colon < line.length) {
char c = line[colon];
if (c == '=') {
return false;
}
}
return true;
}
return false;
}
public static boolean isCommand(String line) {
return line.length() > 1 && line.startsWith("\t");
}
public static boolean isCommand(char[] line) {
return (line.length > 1 && line[0] == '\t');
}
public static boolean isEscapedLine(String line) {
return (line.endsWith("\\") && !line.endsWith("\\\\"));
}
public static boolean isEmptyLine(String line) {
return isEmptyLine(line.toCharArray());
}
public static boolean isEmptyLine(char[] line) {
boolean empty = true;
for (int i = 0; i < line.length; i++) {
if (!isSpace(line[i])) {
empty = false;
break;
}
}
return empty;
}
public static boolean isInferenceRule(String line) {
return line.startsWith(".") && line.indexOf(':') != -1;
}
public static boolean isInferenceRule(char[] line) {
boolean period = false;
boolean colon = false;
for (int i = 0; i < line.length; i++) {
if (line[0] == '.') {
period = true;
}
if (line[i] == ':') {
colon = true;
}
}
return period && colon;
}
public static boolean isSpace(char c) {
return (c == ' ' || c == '\t' || c == '\r' || c == '\n');
}
public static int indexOfComment(String line) {
return indexOfComment(line.toCharArray());
}
public static int indexOfComment(char[] line) {
boolean escaped = false;
for (int i = 0; i < line.length; i++) {
if (line[i] == '#' && !escaped) {
return i;
}
escaped = line[i] == '\\';
}
return -1;
}
public static int indexOf(String line, char c) {
return indexOf(line.toCharArray(), c);
}
/**
* Special indexOf() method that makes sure that what we are searching
* is not between parentheses, brackets or quotes
*/
public static int indexOf(char[] line, char c) {
int paren = 0;
int bracket = 0;
boolean escaped = false;
for (int i = 0; i < line.length; i++) {
if (line[i] == '(' && !escaped) {
paren++;
} else if (line[i] == '{' && !escaped) {
bracket++;
} else if (line[i] == ')' && !escaped) {
paren--;
} else if (line[i] == '}' && !escaped) {
bracket--;
} else if (line[i] == c) {
if (paren == 0 && bracket == 0) {
return i;
}
}
escaped = line[i] == '\\';
}
return -1;
}
}

View file

@ -10,7 +10,10 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile; package org.eclipse.cdt.make.internal.core.makefile;
import org.eclipse.cdt.make.core.makefile.IStatement; import java.io.IOException;
import java.io.Reader;
import org.eclipse.cdt.make.core.makefile.IDirective;
/** /**
* Makefile : ( statement ) * * Makefile : ( statement ) *
@ -30,19 +33,30 @@ import org.eclipse.cdt.make.core.makefile.IStatement;
public class NullMakefile extends AbstractMakefile { public class NullMakefile extends AbstractMakefile {
public static IStatement[] empty = new IStatement[0]; public static IDirective[] empty = new IDirective[0];
public NullMakefile() { public NullMakefile() {
} }
public IStatement[] getStatements() { public IDirective[] getStatements() {
return empty; return empty;
} }
public IStatement[] getBuiltins() { public IDirective[] getBuiltins() {
return empty; return empty;
} }
public void addStatement(IStatement statement) { public void addStatement(IDirective statement) {
} }
public String toString() {
return new String();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.make.core.makefile.IMakefile#parse(java.io.Reader)
*/
public void parse(Reader makefile) throws IOException {
}
} }

View file

@ -0,0 +1,56 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile;
import java.util.ArrayList;
import java.util.Arrays;
import org.eclipse.cdt.make.core.makefile.IParent;
import org.eclipse.cdt.make.core.makefile.IDirective;
/**
* IParent
*/
public abstract class Parent extends Statement implements IParent {
ArrayList children = new ArrayList();
public IDirective[] getStatements() {
children.trimToSize();
return (IDirective[]) children.toArray(new IDirective[0]);
}
public void addStatement(IDirective statement) {
children.add(statement);
}
public void addStatements(IDirective[] statements) {
children.addAll(Arrays.asList(statements));
}
public void clearStatements() {
children.clear();
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
StringBuffer sb = new StringBuffer();
IDirective[] stmts = getStatements();
for (int i = 0; i < stmts.length; i++) {
sb.append(stmts[i]);
}
return sb.toString();
}
}

View file

@ -0,0 +1,26 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile;
import org.eclipse.cdt.make.core.makefile.IPosixRule;
import org.eclipse.cdt.make.core.makefile.ICommand;
/**
* .POSIX
* The appliation shall ensure that this special target is specified without
* prerequisites or commands.
*/
public class PosixRule extends SpecialRule implements IPosixRule {
public PosixRule() {
super(new Target(".POSIX:"), new String[0], new ICommand[0]);
}
}

View file

@ -0,0 +1,27 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile;
import org.eclipse.cdt.make.core.makefile.IPreciousRule;
import org.eclipse.cdt.make.core.makefile.ICommand;
/**
* .PRECIOUS
* Prerequisites of this special target shall not be removed if make recieves an
* asynchronous events.
*/
public class PreciousRule extends SpecialRule implements IPreciousRule {
public PreciousRule(String[] targets) {
super(new Target(".PRECIOUS:"), targets, new ICommand[0]);
}
}

View file

@ -11,13 +11,12 @@
package org.eclipse.cdt.make.internal.core.makefile; package org.eclipse.cdt.make.internal.core.makefile;
import org.eclipse.cdt.make.core.makefile.ICommand; import org.eclipse.cdt.make.core.makefile.ICommand;
import org.eclipse.cdt.make.core.makefile.IInferenceRule;
import org.eclipse.cdt.make.core.makefile.IRule; import org.eclipse.cdt.make.core.makefile.IRule;
import org.eclipse.cdt.make.core.makefile.IDirective;
import org.eclipse.cdt.make.core.makefile.ITarget; import org.eclipse.cdt.make.core.makefile.ITarget;
public abstract class Rule extends Statement implements IRule, IInferenceRule { public abstract class Rule extends Parent implements IRule {
ICommand[] commands;
ITarget target; ITarget target;
public Rule(ITarget tgt) { public Rule(ITarget tgt) {
@ -26,15 +25,14 @@ public abstract class Rule extends Statement implements IRule, IInferenceRule {
public Rule(ITarget tgt, ICommand[] cmds) { public Rule(ITarget tgt, ICommand[] cmds) {
target = tgt; target = tgt;
commands = cmds; addStatements(cmds);
} }
public ICommand[] getCommands() { public ICommand[] getCommands() {
return commands; IDirective[] stmts = getStatements();
} ICommand[] cmds = new ICommand[stmts.length];
System.arraycopy(stmts, 0, cmds, 0, stmts.length);
public void setCommand(ICommand[] cmds) { return cmds;
commands = cmds;
} }
public ITarget getTarget() { public ITarget getTarget() {
@ -45,20 +43,6 @@ public abstract class Rule extends Statement implements IRule, IInferenceRule {
target = tgt; target = tgt;
} }
public void addCommand(ICommand cmd) {
ICommand[] newCmds = new ICommand[commands.length + 1];
System.arraycopy(commands, 0, newCmds, 0, commands.length);
newCmds[commands.length] = cmd;
commands = newCmds;
}
public void addCommands(ICommand[] cmds) {
ICommand[] newCmds = new ICommand[commands.length + cmds.length];
System.arraycopy(commands, 0, newCmds, 0, commands.length);
System.arraycopy(cmds, 0, newCmds, commands.length, cmds.length);
commands = newCmds;
}
public boolean equals(Rule r) { public boolean equals(Rule r) {
return r.getTarget().equals(getTarget()); return r.getTarget().equals(getTarget());
} }

View file

@ -0,0 +1,29 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile;
import org.eclipse.cdt.make.core.makefile.ICommand;
import org.eclipse.cdt.make.core.makefile.ISccsGetRule;
/**
* .SCCS_GET
* The application shall ensure that this special target is specified without
* prerequesites.
* The commands specifeied with this target shall replace the default
* commands associated with this special target.
*/
public class SccsGetRule extends SpecialRule implements ISccsGetRule {
public SccsGetRule(ICommand[] cmds) {
super(new Target(".SCCS_GET"), new String[0], cmds);
}
}

View file

@ -0,0 +1,28 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile;
import org.eclipse.cdt.make.core.makefile.ISilentRule;
import org.eclipse.cdt.make.core.makefile.ICommand;
/**
* .SILENT
* Prerequisties of this special target are targets themselves; this shall cause
* commands associated with them not to be written to the standard output before
* they are executed.
*/
public class SilentRule extends SpecialRule implements ISilentRule {
public SilentRule(String[] reqs) {
super(new Target(".SILENT"), reqs, new ICommand[0]);
}
}

View file

@ -0,0 +1,48 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile;
import org.eclipse.cdt.make.core.makefile.ISpecialRule;
import org.eclipse.cdt.make.core.makefile.ITarget;
import org.eclipse.cdt.make.core.makefile.ICommand;
/**
* Targets that have special meaning for Make.
*/
public abstract class SpecialRule extends Rule implements ISpecialRule {
String[] prerequisites;
public SpecialRule(ITarget target, String[] reqs, ICommand[] cmds) {
super(target, cmds);
prerequisites = reqs;
}
public String[] getPrerequisites() {
return prerequisites;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(target).append(":");
String[] reqs = getPrerequisites();
for (int i = 0; i < reqs.length; i++) {
sb.append(' ').append(reqs[i]);
}
sb.append('\n');
ICommand[] cmds = getCommands();
for (int i = 0; i < cmds.length; i++) {
sb.append(cmds[i]);
}
return sb.toString();
}
}

View file

@ -10,9 +10,9 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile; package org.eclipse.cdt.make.internal.core.makefile;
import org.eclipse.cdt.make.core.makefile.IStatement; import org.eclipse.cdt.make.core.makefile.IDirective;
public abstract class Statement implements IStatement { public abstract class Statement implements IDirective {
int endLine; int endLine;
int startLine; int startLine;
@ -20,10 +20,14 @@ public abstract class Statement implements IStatement {
public Statement() { public Statement() {
} }
public Statement(int start, int end) {
setLines(start, end);
}
public abstract String toString(); public abstract String toString();
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.cdt.make.core.makefile.IStatement#getEndLine() * @see org.eclipse.cdt.make.core.makefile.IDirective#getEndLine()
*/ */
public int getEndLine() { public int getEndLine() {
return endLine; return endLine;
@ -34,7 +38,7 @@ public abstract class Statement implements IStatement {
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.cdt.make.core.makefile.IStatement#getStartLine() * @see org.eclipse.cdt.make.core.makefile.IDirective#getStartLine()
*/ */
public int getStartLine() { public int getStartLine() {
return startLine; return startLine;

View file

@ -0,0 +1,28 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile;
import org.eclipse.cdt.make.core.makefile.ISuffixesRule;
import org.eclipse.cdt.make.core.makefile.ICommand;
/**
* .SUFFIXES
* Prerequesites of .SUFFIXES shall be appended tothe list of known suffixes and are
* used inconjucntion with the inference rules.
*
*/
public class SuffixesRule extends SpecialRule implements ISuffixesRule {
public SuffixesRule(String[] suffixes) {
super(new Target(".SUFFIXES:"), suffixes, new ICommand[0]);
}
}

View file

@ -30,14 +30,6 @@ public class Target implements ITarget {
return new File(target).exists(); return new File(target).exists();
} }
public int make(boolean echo) {
return 0;
}
public boolean isUptodate() {
return false;
}
public long lastModified() { public long lastModified() {
return new File(target).lastModified(); return new File(target).lastModified();
} }

View file

@ -32,27 +32,27 @@ import org.eclipse.cdt.make.core.makefile.ITargetRule;
public class TargetRule extends Rule implements ITargetRule { public class TargetRule extends Rule implements ITargetRule {
ITarget[] dependencies; String[] prerequisites;
public TargetRule(ITarget target) { public TargetRule(ITarget target) {
this(target, new ITarget[0]); this(target, new String[0], new ICommand[0]);
} }
public TargetRule(ITarget target, ITarget[] deps) { public TargetRule(ITarget target, String[] deps) {
this(target, deps, new ICommand[0]); this(target, deps, new ICommand[0]);
} }
public TargetRule(ITarget target, ITarget[] deps, ICommand[] commands) { public TargetRule(ITarget target, String[] reqs, ICommand[] commands) {
super(target, commands); super(target, commands);
dependencies = deps; prerequisites = reqs;
} }
public ITarget[] getDependencies() { public String[] getPrerequisites() {
return dependencies; return prerequisites;
} }
public void setDependecies(ITarget[] reqs) { public void setDependecies(String[] reqs) {
dependencies = reqs; prerequisites = reqs;
} }
/** /**
@ -60,17 +60,16 @@ public class TargetRule extends Rule implements ITargetRule {
*/ */
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append(target); buffer.append(getTarget().toString());
if (buffer.length() > 0) { buffer.append(':');
buffer.append(": "); String[] reqs = getPrerequisites();
for (int i = 0; i < dependencies.length; i++) { for (int i = 0; i < reqs.length; i++) {
buffer.append(dependencies[i]).append(' '); buffer.append(' ').append(reqs[i]);
} }
buffer.append('\n'); buffer.append('\n');
ICommand[] cmds = getCommands(); ICommand[] cmds = getCommands();
for (int i = 0; i < cmds.length; i++) { for (int i = 0; i < cmds.length; i++) {
buffer.append(cmds[i].toString()); buffer.append(cmds[i].toString());
}
} }
return buffer.toString(); return buffer.toString();
} }

View file

@ -0,0 +1,86 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile;
/**
* Utility methods.
*/
public class Util {
private Util() {
}
public static boolean isCommand(String line) {
return line.length() > 1 && line.startsWith("\t");
}
public static boolean isEscapedLine(String line) {
return (line.endsWith("\\") && !line.endsWith("\\\\"));
}
public static boolean isEmptyLine(String line) {
return line.trim().length() == 0;
}
public static int indexOfComment(String line) {
boolean escaped = false;
for (int i = 0; i < line.length(); i++) {
if (line.charAt(i) == '#' && !escaped) {
return i;
}
escaped = line.charAt(i) == '\\';
}
return -1;
}
public static boolean isSpace(char c) {
return (c == ' ' || c == '\t' || c == '\r' || c == '\n');
}
public static int indexOf(String line, char c) {
return indexOf(line, Character.toString(c));
}
/**
* Special indexOf() method that makes sure that what we are searching
* is not between parentheses and brackets like a macro $(foo) ${bar}
*/
public static int indexOf(String line, String tokens) {
int paren = 0;
int bracket = 0;
char prev = 0;
char pprev = 0;
for (int i = 0; i < line.length(); i++) {
char ch = line.charAt(i);
if (ch == '(' && prev == '$' && pprev != '\\') {
paren++;
} else if (ch == '{' && prev == '$' && pprev != '\\') {
bracket++;
} else if (ch == ')' && prev != '\\') {
if (paren > 0) {
paren--;
}
} else if (ch == '}' && prev != '\\') {
if (bracket > 0) {
bracket--;
}
} else if (tokens.indexOf(ch) != -1) {
if (paren == 0 && bracket == 0) {
return i;
}
}
pprev = prev;
prev = ch;
}
return -1;
}
}

View file

@ -0,0 +1,124 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.internal.core.makefile.Parent;
public abstract class Conditional extends Parent {
String cond;
String arg1;
String arg2;
public Conditional(String conditional) {
cond = conditional;
parse();
}
public Conditional() {
this("", "", "");
}
public Conditional(String conditional, String argument1, String argument2) {
arg1 = argument1;
arg2 = argument2;
cond = conditional;
}
public String getConditional() {
return cond;
}
public String getArg1() {
return arg1;
}
public String getArg2() {
return arg2;
}
/**
* Formats of the contional.
* ifeq (ARG1, ARG2)
* ifeq 'ARG1' 'ARG2'
* ifeq "ARG1" "ARG2"
* ifeq "ARG1" 'ARG2'
* ifeq 'ARG1' "ARG2"
*/
void parse() {
String line = getConditional().trim();
char terminal = line.charAt(0) == '(' ? ',' : line.charAt(0);
if (line.length() < 5 && terminal != ',' && terminal != '"' && terminal != '\'') {
arg1 = arg2 = "";
return;
}
// Find the end of the first string.
int count = 0;
// For the (ARG1, ARG2) format.
if (terminal == ',') {
int paren = 0;
for (count = 0; count < line.length(); count++) {
char ch = line.charAt(count);
if (ch == '(') {
paren++;
} else if (ch == ')') {
paren--;
} else if (ch == terminal && paren <= 0) {
break;
}
}
} else {
for (count = 1; count < line.length(); count++) {
if (line.charAt(count) == terminal) {
break;
}
}
}
arg1 = line.substring(1, count);
/* Find the start of the second string. */
line = line.substring(count + 1).trim();
terminal = terminal == ',' ? ')' : line.charAt(0);
if (terminal != ')' && terminal != '"' && terminal != '\'') {
arg2 = "";
return;
}
count = 0;
/* Find the end of the second string. */
if (terminal == ')') {
int paren = 0;
for (count = 0; count < line.length(); count++) {
char ch = line.charAt(count);
if (ch == '(') {
paren++;
} else if (ch == ')') {
paren--;
} else if (ch == terminal && paren <= 0) {
break;
}
}
} else {
for (count = 1; count < line.length(); count++) {
if (line.charAt(count) == terminal) {
break;
}
}
}
arg2 = line.substring(1, count);
}
}

View file

@ -10,40 +10,23 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu; package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.internal.core.makefile.MakefileUtil;
import org.eclipse.cdt.make.internal.core.makefile.Statement;
public class Define extends Statement { public class DefineVariable extends VariableDefinition {
String variable; public DefineVariable(String name, StringBuffer value) {
super(name, value);
}
public Define(String line) { public boolean isMultiline() {
parse(line); return true;
} }
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer("define"); StringBuffer sb = new StringBuffer("define");
sb.append(' ').append(variable); sb.append(getName()).append('\n');
sb.append(getValue());
sb.append("endef");
return sb.toString(); return sb.toString();
} }
public String getVariable() {
return variable;
}
/**
* Format of the include directive:
* export Variabe ...
*/
protected void parse(String line) {
line = line.trim();
for (int i = 0; i < line.length(); i++) {
if (MakefileUtil.isSpace(line.charAt(i))) {
line = line.substring(i).trim();
break;
}
}
variable = line;
}
} }

View file

@ -10,13 +10,11 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu; package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.internal.core.makefile.Statement; public class Else extends Conditional {
public class Else extends Statement {
public Else() { public Else() {
super();
} }
public String toString() { public String toString() {

View file

@ -10,13 +10,10 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu; package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.internal.core.makefile.Statement; public class Endif extends Conditional {
public class Endif extends Statement {
public Endif() { public Endif() {
super();
} }
public String toString() { public String toString() {

View file

@ -1,55 +0,0 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu;
import java.util.StringTokenizer;
import org.eclipse.cdt.make.internal.core.makefile.Statement;
public class Export extends Statement {
String variable;
public Export(String line) {
parse(line);
}
public String toString() {
StringBuffer sb = new StringBuffer("export");
sb.append(' ').append(variable);
return sb.toString();
}
public String getVariable() {
return variable;
}
/**
* Format of the include directive:
* export Variabe ...
*/
protected void parse(String line) {
StringTokenizer st = new StringTokenizer(line);
int count = st.countTokens();
if (count > 0) {
for (int i = 0; i < count; i++) {
if (i == 0) {
// ignore the "export" keyword.
continue;
}
variable = st.nextToken();
}
}
if (variable == null) {
variable = new String();
}
}
}

View file

@ -0,0 +1,23 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu;
public class ExportVariable extends VariableDefinition {
public ExportVariable(String name, StringBuffer value, int type) {
super(name, value, type);
}
public boolean isExport() {
return true;
}
}

View file

@ -13,31 +13,862 @@ package org.eclipse.cdt.make.internal.core.makefile.gnu;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.StringTokenizer;
import org.eclipse.cdt.make.core.makefile.IStatement; import org.eclipse.cdt.make.core.makefile.ICommand;
import org.eclipse.cdt.make.core.makefile.IDirective;
import org.eclipse.cdt.make.internal.core.makefile.AbstractMakefile;
import org.eclipse.cdt.make.internal.core.makefile.BadStatement;
import org.eclipse.cdt.make.internal.core.makefile.Command;
import org.eclipse.cdt.make.internal.core.makefile.Comment;
import org.eclipse.cdt.make.internal.core.makefile.DefaultRule;
import org.eclipse.cdt.make.internal.core.makefile.EmptyLine;
import org.eclipse.cdt.make.internal.core.makefile.IgnoreRule;
import org.eclipse.cdt.make.internal.core.makefile.InferenceRule;
import org.eclipse.cdt.make.internal.core.makefile.MakefileReader; import org.eclipse.cdt.make.internal.core.makefile.MakefileReader;
import org.eclipse.cdt.make.internal.core.makefile.posix.PosixMakefile; import org.eclipse.cdt.make.internal.core.makefile.Parent;
import org.eclipse.cdt.make.internal.core.makefile.PosixRule;
import org.eclipse.cdt.make.internal.core.makefile.PreciousRule;
import org.eclipse.cdt.make.internal.core.makefile.Rule;
import org.eclipse.cdt.make.internal.core.makefile.SccsGetRule;
import org.eclipse.cdt.make.internal.core.makefile.SilentRule;
import org.eclipse.cdt.make.internal.core.makefile.Statement;
import org.eclipse.cdt.make.internal.core.makefile.SuffixesRule;
import org.eclipse.cdt.make.internal.core.makefile.Target;
import org.eclipse.cdt.make.internal.core.makefile.TargetRule;
import org.eclipse.cdt.make.internal.core.makefile.Util;
import org.eclipse.cdt.make.internal.core.makefile.posix.PosixBuiltinMacroDefinitions;
import org.eclipse.cdt.make.internal.core.makefile.posix.PosixBuiltinRules;
import org.eclipse.cdt.make.internal.core.makefile.posix.PosixMakefileUtil;
/** /**
* GNUMakefile * Makefile : ( statement ) *
* statement : rule | macro_definition | comments | empty
* rule : inference_rule | target_rule
* inference_rule : target ':' <nl> ( <tab> command <nl> ) +
* target_rule : target [ ( target ) * ] ':' [ ( prerequisite ) * ] [ ';' command ] <nl>
[ ( command ) * ]
* macro_definition : string '=' (string)*
* comments : ('#' (string) <nl>) *
* empty : <nl>
* command : <tab> prefix_command string <nl>
* target : string
* prefix_command : '-' | '@' | '+'
* internal_macro : "$<" | "$*" | "$@" | "$?" | "$%"
*/ */
public class GNUMakefile extends PosixMakefile {
public class GNUMakefile extends AbstractMakefile {
public static String PATH_SEPARATOR = System.getProperty("path.separator", ":"); public static String PATH_SEPARATOR = System.getProperty("path.separator", ":");
public static String FILE_SEPARATOR = System.getProperty("file.separator", "/");
public GNUMakefile(String name) throws IOException { String[] includeDirectories = new String[0];
this(new FileReader(name));
public GNUMakefile() {
super();
} }
public GNUMakefile(Reader reader) throws IOException { public void parse(String name) throws IOException {
this(new MakefileReader(reader)); parse(new FileReader(name));
} }
public GNUMakefile(MakefileReader reader) throws IOException { public void parse(Reader reader) throws IOException {
super(reader); parse(new MakefileReader(reader));
} }
protected IStatement processLine(String line, int startLine, int endLine) { protected void parse(MakefileReader reader) throws IOException {
return null; String line;
Rule[] rules = null;
Stack conditions = new Stack();
Stack defines = new Stack();
int startLine = 0;
int endLine = 0;
// Clear any old statements.
clearStatements();
while ((line = reader.readLine()) != null) {
startLine = endLine + 1;
endLine = reader.getLineNumber();
// Check if we enter in "define"
if (GNUMakefileUtil.isEndef(line)) {
// We should have a "define" for a "endef".
if (!defines.empty()) {
DefineVariable def = (DefineVariable) defines.pop();
def.setEndLine(endLine);
}
Endef endef = createEndef();
endef.setLines(startLine, endLine);
addStatement(conditions, endef);
continue;
} else if (GNUMakefileUtil.isDefine(line)) {
VariableDefinition def = createVariableDefinition(line);
def.setLines(startLine, endLine);
addStatement(conditions, def);
defines.push(def);
continue;
} else if (GNUMakefileUtil.isOverrideDefine(line)) {
VariableDefinition oDef = createVariableDefinition(line);
oDef.setLines(startLine, endLine);
addStatement(conditions, oDef);
defines.push(oDef);
continue;
}
// We still in a define.
if (!defines.empty()) {
DefineVariable def = (DefineVariable) defines.peek();
StringBuffer sb = def.getValue();
if (sb.length() > 0) {
sb.append('\n');
}
sb.append(line);
continue;
}
// 1- Try command first, since we can not strip '#' in command line
if (GNUMakefileUtil.isCommand(line)) {
Command cmd = createCommand(line);
cmd.setLines(startLine, endLine);
if (!conditions.empty()) {
addStatement(conditions, cmd);
continue;
} else if (rules != null) {
// The command is added to the rules
for (int i = 0; i < rules.length; i++) {
rules[i].addStatement(cmd);
rules[i].setEndLine(endLine);
}
continue;
}
// If we have no rules/condition for the command,
// give the other statements a chance by falling through
}
// 2- Strip away any comments.
int pound = Util.indexOfComment(line);
if (pound != -1) {
Comment cmt = createComment(line.substring(pound + 1));
cmt.setLines(startLine, endLine);
addStatement(conditions, cmt);
line = line.substring(0, pound);
// If all we have left are spaces continue
if (Util.isEmptyLine(line)) {
continue;
}
// The rest of the line maybe a valid statement.
// keep on trying by falling through.
}
// 3- Empty lines ?
if (Util.isEmptyLine(line)) {
Statement empty = createEmptyLine();
empty.setLines(startLine, endLine);
addStatement(conditions, empty);
continue;
}
// 4- reset the rules to null
// The first non empty line that does not begin with a <TAB> or '#'
// shall begin a new entry.
rules = null;
if (GNUMakefileUtil.isElse(line)) {
Statement elseDirective = createConditional(line);
elseDirective.setLines(startLine, endLine);
// Are we missing a if condition ?
if (!conditions.empty()) {
Statement cond = (Statement) conditions.pop();
cond.setEndLine(endLine - 1);
}
addStatement(conditions, elseDirective);
conditions.push(elseDirective);
continue;
} else if (GNUMakefileUtil.isEndif(line)) {
Conditional endif = createConditional(line);
endif.setLines(startLine, endLine);
// Are we missing a if/else condition ?
if (!conditions.empty()) {
Statement cond = (Statement) conditions.pop();
cond.setEndLine(endLine - 1);
}
addStatement(conditions, endif);
continue;
}
// 5- Check for the conditionnals.
Statement statement = processConditions(line);
if (statement != null) {
statement.setLines(startLine, endLine);
addStatement(conditions, statement);
conditions.push(statement);
continue;
}
// 6- Check for other special gnu directives.
statement = processGNUDirectives(line);
if (statement != null) {
statement.setLines(startLine, endLine);
addStatement(conditions, statement);
continue;
}
// 7- Check for GNU special rules.
Rule rule = processSpecialRules(line);
if (rule != null) {
rules = new Rule[] { rule };
rule.setLines(startLine, endLine);
addStatement(conditions, rule);
continue;
}
// - Check for inference rule.
if (GNUMakefileUtil.isInferenceRule(line)) {
InferenceRule irule = createInferenceRule(line);
irule.setLines(startLine, endLine);
addStatement(conditions, irule);
rules = new Rule[] { irule };
continue;
}
// - Variable Definiton ?
if (GNUMakefileUtil.isVariableDefinition(line)) {
Statement stmt = createVariableDefinition(line);
stmt.setLines(startLine, endLine);
addStatement(conditions, stmt);
continue;
}
if (GNUMakefileUtil.isStaticTargetRule(line)) {
StaticTargetRule[] srules = createStaticTargetRule(line);
for (int i = 0; i < srules.length; i++) {
srules[i].setLines(startLine, endLine);
addStatement(conditions, srules[i]);
}
rules = srules;
continue;
}
// - Target Rule ?
if (GNUMakefileUtil.isGNUTargetRule(line)) {
TargetRule[] trules = createGNUTargetRules(line);
for (int i = 0; i < trules.length; i++) {
trules[i].setLines(startLine, endLine);
addStatement(conditions, trules[i]);
}
rules = trules;
continue;
}
// XXX ?? Should not be here.
BadStatement stmt = new BadStatement(line);
stmt.setLines(startLine, endLine);
addStatement(conditions, stmt);
}
setLines(1, endLine);
} }
protected void addStatement(Stack conditions, IDirective statement) {
if (conditions.empty()) {
addStatement(statement);
} else {
Parent p = (Parent) conditions.peek();
p.addStatement(statement);
p.setEndLine(statement.getEndLine());
}
}
protected Statement processConditions(String line) {
Statement stmt = null;
if (GNUMakefileUtil.isIfdef(line)) {
stmt = createConditional(line);
} else if (GNUMakefileUtil.isIfndef(line)) {
stmt = createConditional(line);
} else if (GNUMakefileUtil.isIfeq(line)) {
stmt = createConditional(line);
} else if (GNUMakefileUtil.isIfneq(line)) {
stmt = createConditional(line);
}
return stmt;
}
protected Statement processGNUDirectives(String line) {
Statement stmt = null;
if (GNUMakefileUtil.isUnExport(line)) {
stmt = createUnExport(line);
} else if (GNUMakefileUtil.isVPath(line)) {
stmt = createVPath(line);
} else if (GNUMakefileUtil.isInclude(line)) {
stmt = createInclude(line);
}
return stmt;
}
protected Rule processSpecialRules(String line) {
Rule stmt = null;
if (GNUMakefileUtil.isIgnoreRule(line)) {
stmt = createIgnoreRule(line);
} else if (GNUMakefileUtil.isPosixRule(line)) {
stmt = createPosixRule();
} else if (GNUMakefileUtil.isPreciousRule(line)) {
stmt = createPreciousRule(line);
} else if (GNUMakefileUtil.isSilentRule(line)) {
stmt = createSilentRule(line);
} else if (GNUMakefileUtil.isSuffixesRule(line)) {
stmt = createSuffixesRule(line);
} else if (GNUMakefileUtil.isDefaultRule(line)) {
stmt = createDefaultRule(line);
} else if (GNUMakefileUtil.isSccsGetRule(line)) {
stmt = createSccsGetRule(line);
}
return stmt;
}
/**
* @param line
* @return
*/
protected Rule createSuffixesRule(String line) {
int index = Util.indexOf(line, ':');
if (index != -1) {
String req = line.substring(index + 1);
String[] reqs = PosixMakefileUtil.findPrerequisites(req);
return new SuffixesRule(reqs);
}
return new SuffixesRule(new String[0]);
}
/**
* @param line
* @return
*/
protected Rule createSilentRule(String line) {
int index = Util.indexOf(line, ':');
if (index != -1) {
String req = line.substring(index + 1);
String[] reqs = GNUMakefileUtil.findPrerequisites(req);
return new SilentRule(reqs);
}
return new SilentRule(new String[0]);
}
/**
* @param line
* @return
*/
protected Rule createPreciousRule(String line) {
int index = Util.indexOf(line, ':');
if (index != -1) {
String req = line.substring(index + 1);
String[] reqs = GNUMakefileUtil.findPrerequisites(req);
return new PreciousRule(reqs);
}
return new PreciousRule(new String[0]);
}
/**
* @param line
* @return
*/
protected Rule createIgnoreRule(String line) {
int index = Util.indexOf(line, ':');
if (index != -1) {
String req = line.substring(index + 1);
String[] reqs = GNUMakefileUtil.findPrerequisites(req);
return new IgnoreRule(reqs);
}
return new IgnoreRule(new String[0]);
}
/**
*
* ifdef CONDITIONAL
* ifeq CONDITIONAL
* ifneq CONDITIONAL
* else
* endif
*
* @param line
* @return
*/
public Conditional createConditional(String line) {
Conditional condition = null;
line = line.trim();
String keyword = null;
// Move pass the keyword
for (int i = 0; i < line.length(); i++) {
if (Util.isSpace(line.charAt(i))) {
keyword = line.substring(0, i);
line = line.substring(i).trim();
break;
}
}
if (keyword == null) {
keyword = line;
}
if (keyword.equals("ifdef")) {
condition = new Ifdef(line);
} else if (keyword.equals("ifndef")) {
condition = new Ifndef(line);
} else if (keyword.equals("ifeq")) {
condition = new Ifeq(line);
} else if (keyword.equals("ifneq")) {
condition = new Ifneq(line);
} else if (keyword.equals("else")) {
condition = new Else();
} else if (keyword.equals("endif")) {
condition = new Endif();
}
return condition;
}
/**
* Format of the include directive:
* include filename1 filename2 ...
*/
protected Include createInclude(String line) {
String[] filenames;
StringTokenizer st = new StringTokenizer(line);
int count = st.countTokens();
if (count > 0) {
filenames = new String[count - 1];
for (int i = 0; i < count; i++) {
if (i == 0) {
st.nextToken();
// ignore the "include" keyword.
continue;
}
filenames[i - 1] = st.nextToken();
}
} else {
filenames = new String[0];
}
return new Include(filenames, getIncludeDirectories());
}
/**
* There are three forms of the "vpath" directive:
* "vpath PATTERN DIRECTORIES"
* Specify the search path DIRECTORIES for file names that match PATTERN.
*
* The search path, DIRECTORIES, is a list of directories to be
* searched, separated by colons (semi-colons on MS-DOS and
* MS-Windows) or blanks, just like the search path used in the `VPATH' variable.
*
* "vpath PATTERN"
* Clear out the search path associated with PATTERN.
*
* "vpath"
* Clear all search paths previously specified with `vpath' directives.
*/
public VPath createVPath(String line) {
String pattern = null;
String[] directories;
StringTokenizer st = new StringTokenizer(line);
int count = st.countTokens();
List dirs = new ArrayList(count);
if (count > 0) {
for (int i = 0; i < count; i++) {
if (count == 0) {
// ignore the "vpath" directive
st.nextToken();
} else if (count == 1) {
pattern = st.nextToken();
} else if (count == 3) {
String delim = " \t\n\r\f" + GNUMakefile.PATH_SEPARATOR;
dirs.add(st.nextToken(delim));
} else {
dirs.add(st.nextToken());
}
}
}
directories = (String[]) dirs.toArray(new String[0]);
if (pattern == null) {
pattern = new String();
}
return new VPath(pattern, directories);
}
public Endef createEndef() {
return new Endef();
}
/**
* @param line
* @return
*/
protected UnExport createUnExport(String line) {
// Pass over "unexport"
for (int i = 0; i < line.length(); i++) {
if (Util.isSpace(line.charAt(i))) {
line = line.substring(i).trim();
break;
}
}
return new UnExport(line);
}
protected Command createCommand(String line) {
return new Command(line);
}
protected Comment createComment(String line) {
return new Comment(line);
}
protected EmptyLine createEmptyLine() {
return new EmptyLine();
}
protected InferenceRule[] createInferenceRules(String line) {
// Inference Rule
String tgt;
int index = Util.indexOf(line, ':');
if (index != -1) {
tgt = line.substring(0, index);
} else {
tgt = line;
}
return new InferenceRule[] { new InferenceRule(new Target(tgt))};
}
protected GNUTargetRule[] createGNUTargetRules(String line) {
String[] targetNames;
String[] normalReqs;
String[] orderReqs;
String cmd = null;
boolean doubleColon = false;
int index = Util.indexOf(line, ':');
if (index != -1) {
// Break the targets
String target = line.substring(0, index);
targetNames = GNUMakefileUtil.findTargets(target.trim());
// Some TargetRule have "::" for separator
String req = line.substring(index + 1);
doubleColon = req.startsWith(":");
if (doubleColon) {
// move pass the second ':'
req = req.substring(1);
}
// Check for command
int semicolon = Util.indexOf(req, ';');
if (semicolon != -1) {
cmd = req.substring(semicolon + 1);
req = req.substring(0, semicolon);
}
// Check for Normal and order prerequisites
String normalReq = null;
String orderReq = null;
int pipe = Util.indexOf(req, '|');
if (pipe != -1) {
normalReq = req.substring(0, pipe);
orderReq = req.substring(pipe + 1);
} else {
normalReq = req;
orderReq = "";
}
normalReqs = GNUMakefileUtil.findPrerequisites(normalReq.trim());
orderReqs = GNUMakefileUtil.findPrerequisites(orderReq.trim());
} else {
targetNames = GNUMakefileUtil.findTargets(line);
normalReqs = new String[0];
orderReqs = new String[0];
}
GNUTargetRule[] rules = new GNUTargetRule[targetNames.length];
for (int i = 0; i < targetNames.length; i++) {
rules[i] = new GNUTargetRule(createTarget(targetNames[i]), doubleColon, normalReqs, orderReqs, new ICommand[0]);
if (cmd != null) {
rules[i].addStatement(createCommand(cmd));
}
}
return rules;
}
protected VariableDefinition createVariableDefinition(String line) {
line = line.trim();
VariableDefinition vd;
// the default type.
int type = VariableDefinition.TYPE_RECURSIVE_EXPAND;
boolean isDefine = false;
boolean isOverride = false;
boolean isTargetVariable = false;
boolean isExport = false;
String targetName = "";
String name;
StringBuffer value = new StringBuffer();
// Check for Target: Variable-assignment
if (GNUMakefileUtil.isTargetVariable(line)) {
// move to the first ':'
int colon = Util.indexOf(line, ':');
if (colon != -1) {
targetName = line.substring(0, colon).trim();
line = line.substring(colon + 1).trim();
} else {
targetName = "";
}
}
// Check for Override condition.
if (GNUMakefileUtil.isOverride(line)) {
isOverride = true;
// Move pass the keyword override.
for (int i = 0; i < line.length(); i++) {
if (Util.isSpace(line.charAt(i))) {
line = line.substring(i).trim();
break;
}
}
}
// Check for "define"
if (GNUMakefileUtil.isOverrideDefine(line)) {
isDefine = true;
// Move pass the keyword define.
for (int i = 0; i < line.length(); i++) {
if (Util.isSpace(line.charAt(i))) {
line = line.substring(i).trim();
break;
}
}
}
// Check for Override condition.
if (GNUMakefileUtil.isExport(line)) {
isExport = true;
// Move pass the keyword export.
for (int i = 0; i < line.length(); i++) {
if (Util.isSpace(line.charAt(i))) {
line = line.substring(i).trim();
break;
}
}
}
// Check for Target-variable
int index = line.indexOf('=');
if (index != -1) {
int separator = index;
// Check for "+=", ":=", "?="
if (index > 0) {
type = line.charAt(index - 1);
if (type == VariableDefinition.TYPE_SIMPLE_EXPAND
|| type == VariableDefinition.TYPE_APPEND
|| type == VariableDefinition.TYPE_CONDITIONAL) {
separator = index - 1;
} else {
type = VariableDefinition.TYPE_RECURSIVE_EXPAND;
}
}
name = line.substring(0, separator).trim();
value.append(line.substring(index + 1).trim());
} else {
name = line;
}
if (isTargetVariable) {
vd = new TargetVariable(targetName, name, value, isOverride, type);
}
if (isOverride && isDefine) {
vd = new OverrideDefine(name, value);
} else if (isDefine) {
vd = new DefineVariable(name, value);
} else if (isOverride) {
vd = new OverrideVariable(name, value, type);
} else if (isExport) {
vd = new ExportVariable(name, value, type);
} else {
vd = new VariableDefinition(name, value, type);
}
return vd;
}
protected Target createTarget(String line) {
return new Target(line);
}
protected StaticTargetRule[] createStaticTargetRule(String line) {
// first colon: the Targets
String targetPattern;
String[] prereqPatterns;
String[] targets;
int colon = Util.indexOf(line, ':');
if (colon > 1) {
String targetLine = line.substring(0, colon).trim();
targets = GNUMakefileUtil.findTargets(targetLine);
// second colon: Target-Pattern
line = line.substring(colon + 1);
colon = Util.indexOf(line, ':');
if (colon != -1) {
targetPattern = line.substring(0, colon).trim();
line = line.substring(colon + 1);
StringTokenizer st = new StringTokenizer(line);
int count = st.countTokens();
prereqPatterns = new String[count];
for (int i = 0; i < count; i++) {
prereqPatterns[i] = st.nextToken();
}
} else {
targetPattern = "";
prereqPatterns = new String[0];
}
} else {
targets = new String[0];
targetPattern = "";
prereqPatterns = new String[0];
}
StaticTargetRule[] staticRules = new StaticTargetRule[targets.length];
for (int i = 0; i < targets.length; i++) {
staticRules[i] = new StaticTargetRule(createTarget(targets[i]), targetPattern, prereqPatterns, new ICommand[0]);
}
return staticRules;
}
/**
* @param line
* @return
*/
private TargetRule[] createTargetRule(String line) {
String[] targets;
String[] reqs;
String cmd = null;
int index = Util.indexOf(line, ':');
if (index != -1) {
String target = line.substring(0, index);
// Tokenize the targets
targets = GNUMakefileUtil.findTargets(target);
String req = line.substring(index + 1);
int semicolon = Util.indexOf(req, ';');
if (semicolon != -1) {
String c = req.substring(semicolon + 1).trim();
if (c.length() > 0) {
cmd = c;
}
req = req.substring(0, semicolon);
}
reqs = GNUMakefileUtil.findPrerequisites(req);
} else {
targets = GNUMakefileUtil.findTargets(line);
reqs = new String[0];
}
TargetRule[] targetRules = new TargetRule[targets.length];
for (int i = 0; i < targets.length; i++) {
targetRules[i] = new TargetRule(new Target(targets[i]), reqs);
if (cmd != null) {
Command command = createCommand(cmd);
targetRules[i].addStatement(command);
}
}
return targetRules;
}
/**
* @param line
* @return
*/
private InferenceRule createInferenceRule(String line) {
String tgt;
int index = Util.indexOf(line, ':');
if (index != -1) {
tgt = line.substring(0, index);
} else {
tgt = line;
}
return new InferenceRule(new Target(tgt));
}
/**
* @param line
* @return
*/
private SccsGetRule createSccsGetRule(String line) {
int semicolon = Util.indexOf(line, ';');
if (semicolon != -1) {
String cmd = line.substring(semicolon + 1).trim();
if (cmd.length() > 0) {
ICommand[] cmds = new ICommand[] { new Command(cmd)};
return new SccsGetRule(cmds);
}
}
return new SccsGetRule(new ICommand[0]);
}
/**
* @param line
* @return
*/
private DefaultRule createDefaultRule(String line) {
int semicolon = Util.indexOf(line, ';');
if (semicolon > 0) {
String cmd = line.substring(semicolon + 1).trim();
if (cmd.length() > 0) {
ICommand[] cmds = new ICommand[] { new Command(cmd)};
return new DefaultRule(cmds);
}
}
return new DefaultRule(new ICommand[0]);
}
/**
* @return
*/
private PosixRule createPosixRule() {
return new PosixRule();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.make.internal.core.makefile.AbstractMakefile#getBuiltins()
*/
public IDirective[] getBuiltins() {
IDirective[] macros = new PosixBuiltinMacroDefinitions().getMacroDefinitions();
IDirective[] rules = new PosixBuiltinRules().getInferenceRules();
IDirective[] stmts = new IDirective[macros.length + rules.length];
System.arraycopy(macros, 0, stmts, 0, macros.length);
System.arraycopy(rules, 0, stmts, macros.length, rules.length);
return stmts;
}
public void setIncludeDirectories(String[] dirs) {
includeDirectories = dirs;
}
public String[] getIncludeDirectories() {
return includeDirectories;
}
public static void main(String[] args) {
try {
String filename = "Makefile";
if (args.length == 1) {
filename = args[0];
}
GNUMakefile makefile = new GNUMakefile();
makefile.parse(filename);
IDirective[] statements = makefile.getStatements();
for (int i = 0; i < statements.length; i++) {
//System.out.println("Rule[" + i +"]");
System.out.print(statements[i]);
}
} catch (IOException e) {
System.out.println(e);
}
}
} }

View file

@ -10,12 +10,15 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu; package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.internal.core.makefile.Util;
import org.eclipse.cdt.make.internal.core.makefile.posix.PosixMakefileUtil;
/** /**
* GNUMakefile * GNUMakefile
*/ */
public class GNUMakefileUtil { public class GNUMakefileUtil extends PosixMakefileUtil {
public static boolean isIncludeDirective(String line) { public static boolean isInclude(String line) {
line = line.trim(); line = line.trim();
boolean isInclude = line.startsWith("include") && line.length() > 7 && Character.isWhitespace(line.charAt(7)); boolean isInclude = line.startsWith("include") && line.length() > 7 && Character.isWhitespace(line.charAt(7));
boolean isDashInclude = line.startsWith("-include") && line.length() > 8 && Character.isWhitespace(line.charAt(8)); boolean isDashInclude = line.startsWith("-include") && line.length() > 8 && Character.isWhitespace(line.charAt(8));
@ -23,76 +26,130 @@ public class GNUMakefileUtil {
return isInclude || isDashInclude || isSInclude; return isInclude || isDashInclude || isSInclude;
} }
public static boolean isVPathDirective(String line) { public static boolean isVPath(String line) {
line = line.trim(); line = line.trim();
return line.equals("vpath") || return line.equals("vpath") || line.startsWith("vpath") && line.length() > 5 && Character.isWhitespace(line.charAt(5));
line.startsWith("vpath") && line.length() > 5 && Character.isWhitespace(line.charAt(5));
} }
public static boolean isExport(String line) { public static boolean isExport(String line) {
line = line.trim(); line = line.trim();
return line.equals("export") || return line.equals("export") || line.startsWith("export") && line.length() > 6 && Character.isWhitespace(line.charAt(6));
line.startsWith("export") && line.length() > 6 && Character.isWhitespace(line.charAt(6));
} }
public static boolean isUnExport(String line) { public static boolean isUnExport(String line) {
line = line.trim(); line = line.trim();
return line.equals("unexport") || return line.startsWith("unexport") && line.length() > 8 && Character.isWhitespace(line.charAt(8));
line.startsWith("unexport") && line.length() > 8 && Character.isWhitespace(line.charAt(8));
} }
public static boolean isDefine(String line) { public static boolean isDefine(String line) {
line = line.trim(); line = line.trim();
return line.equals("define") || return line.startsWith("define") && line.length() > 6 && Character.isWhitespace(line.charAt(6));
line.startsWith("define") && line.length() > 6 && Character.isWhitespace(line.charAt(6));
} }
public static boolean isEndef(String line) { public static boolean isEndef(String line) {
line = line.trim(); return line.trim().equals("endef");
return line.equals("endef") ||
line.startsWith("endef") && line.length() > 5 && Character.isWhitespace(line.charAt(5));
} }
public static boolean isOverride(String line) { public static boolean isOverride(String line) {
line = line.trim(); line = line.trim();
return line.equals("override") || return line.startsWith("override") && line.length() > 8 && Character.isWhitespace(line.charAt(8));
line.startsWith("override") && line.length() > 8 && Character.isWhitespace(line.charAt(8));
} }
public static boolean isIfeq(String line) { public static boolean isIfeq(String line) {
line = line.trim(); line = line.trim();
return line.equals("ifeq") || return line.startsWith("ifeq") && line.length() > 4 && Character.isWhitespace(line.charAt(4));
line.startsWith("ifeq") && line.length() > 4 && Character.isWhitespace(line.charAt(4));
} }
public static boolean isIfneq(String line) { public static boolean isIfneq(String line) {
line = line.trim(); line = line.trim();
return line.equals("ifneq") || return line.startsWith("ifneq") && line.length() > 5 && Character.isWhitespace(line.charAt(5));
line.startsWith("ifneq") && line.length() > 5 && Character.isWhitespace(line.charAt(5));
} }
public static boolean isIfdef(String line) { public static boolean isIfdef(String line) {
line = line.trim(); line = line.trim();
return line.equals("ifdef") || return line.startsWith("ifdef") && line.length() > 5 && Character.isWhitespace(line.charAt(5));
line.startsWith("ifdef") && line.length() > 5 && Character.isWhitespace(line.charAt(5));
} }
public static boolean isIfndef(String line) { public static boolean isIfndef(String line) {
line = line.trim(); line = line.trim();
return line.equals("ifndef") || return line.startsWith("ifndef") && line.length() > 5 && Character.isWhitespace(line.charAt(5));
line.startsWith("ifndef") && line.length() > 5 && Character.isWhitespace(line.charAt(5));
} }
public static boolean isElse(String line) { public static boolean isElse(String line) {
line = line.trim(); return line.trim().equals("else");
return line.equals("else") ||
line.startsWith("else") && line.length() > 4 && Character.isWhitespace(line.charAt(4));
} }
public static boolean isEndif(String line) { public static boolean isEndif(String line) {
return line.trim().equals("endif");
}
public static boolean isOverrideDefine(String line) {
line = line.trim(); line = line.trim();
return line.equals("endif") || if (line.startsWith("override")) {
line.startsWith("endif") && line.length() > 5 && Character.isWhitespace(line.charAt(5)); int i = 8;
for (; i < line.length() && Character.isWhitespace(line.charAt(i)); i++);
if (line.startsWith("define", i)) {
return true;
}
}
return false;
}
public static boolean isTargetVariable(String line) {
line = line.trim();
int index = Util.indexOf(line, ':');
if (index > 1) {
line = line.substring(index + 1).trim();
int equal = Util.indexOf(line, '=');
if (equal > 1) {
return true;
}
}
return false;
}
public static boolean isVariableDefinition(String line) {
return isOverrideDefine(line)
|| isTargetVariable(line)
|| isDefine(line)
|| isOverride(line)
|| isExport(line)
|| isMacroDefinition(line);
}
/**
* @param line
* @return
*/
public static boolean isStaticTargetRule(String line) {
line = line.trim();
int colon1 = Util.indexOf(line, ':');
if (colon1 > 0) {
// move pass colon1
line = line.substring(colon1 + 1);
int colon2 = Util.indexOf(line, ':');
// Catch operator "::" not a static pattern rule
return (colon2 > 0);
}
return false;
}
/**
* @param line
* @return
*/
public static boolean isGNUTargetRule(String line) {
line = line.trim();
int colon = Util.indexOf(line, ':');
if (colon > 0) {
colon++;
// Catch VariableDefiniton with operator ":="
if (colon < line.length()) {
return line.charAt(colon) != '=';
}
return true;
}
return false;
} }
} }

View file

@ -0,0 +1,69 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.core.makefile.ICommand;
import org.eclipse.cdt.make.core.makefile.ITarget;
import org.eclipse.cdt.make.internal.core.makefile.TargetRule;
/**
*/
public class GNUTargetRule extends TargetRule {
String[] orderOnlyPrerequisites;
boolean doubleColon;
public GNUTargetRule(ITarget target, boolean double_colon, String[] normal_prereqs, String[] order_prereqs, ICommand[] commands) {
super(target, normal_prereqs, commands);
orderOnlyPrerequisites = order_prereqs;
doubleColon = double_colon;
}
public boolean isDoubleColon() {
return doubleColon;
}
public String[] getNormalPrerequisites() {
return getPrerequisites();
}
public String[] getOrderOnlyPrerequisites() {
return orderOnlyPrerequisites;
}
/**
* @see java.lang.Object#toString()
*/
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(getTarget().toString());
buffer.append(':');
String[] reqs = getNormalPrerequisites();
for (int i = 0; i < reqs.length; i++) {
buffer.append(' ').append(reqs[i]);
}
reqs = getOrderOnlyPrerequisites();
if (reqs.length > 0) {
buffer.append(" |");
for (int i = 0; i < reqs.length; i++) {
buffer.append(' ').append(reqs[i]);
}
}
buffer.append('\n');
ICommand[] cmds = getCommands();
for (int i = 0; i < cmds.length; i++) {
buffer.append(cmds[i].toString());
}
return buffer.toString();
}
}

View file

@ -10,40 +10,20 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu; package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.internal.core.makefile.MakefileUtil; public class Ifdef extends Conditional {
import org.eclipse.cdt.make.internal.core.makefile.Statement;
public Ifdef(String var) {
public class Ifdef extends Statement { super(var, "", "");
String variable;
public Ifdef(String line) {
parse(line);
} }
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer("ifdef"); StringBuffer sb = new StringBuffer("ifdef");
sb.append(' ').append(variable); sb.append(' ').append(getVariable());
return sb.toString(); return sb.toString();
} }
public String getVariable() { public String getVariable() {
return variable; return getConditional();
} }
/**
* Format of the include directive:
* ifeq condional-directive
*/
protected void parse(String line) {
line = line.trim();
for (int i = 0; i < line.length(); i++) {
if (MakefileUtil.isSpace(line.charAt(i))) {
line = line.substring(i).trim();
break;
}
}
variable = line;
}
} }

View file

@ -10,41 +10,16 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu; package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.internal.core.makefile.MakefileUtil; public class Ifeq extends Conditional {
import org.eclipse.cdt.make.internal.core.makefile.Statement;
public Ifeq(String cond) {
public class Ifeq extends Statement { super(cond);
String conditional;
public Ifeq(String line) {
parse(line);
} }
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer("ifeq"); StringBuffer sb = new StringBuffer("ifeq");
sb.append(' ').append(conditional); sb.append(' ').append(getConditional());
return sb.toString(); return sb.toString();
} }
public String getConditional() {
return conditional;
}
/**
* Format of the include directive:
* ifeq condional-directive
*/
protected void parse(String line) {
line = line.trim();
for (int i = 0; i < line.length(); i++) {
if (MakefileUtil.isSpace(line.charAt(i))) {
line = line.substring(i).trim();
break;
}
}
conditional = line;
}
} }

View file

@ -10,40 +10,20 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu; package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.internal.core.makefile.MakefileUtil; public class Ifndef extends Conditional {
import org.eclipse.cdt.make.internal.core.makefile.Statement;
public Ifndef(String var) {
public class Ifndef extends Statement { super(var, "", "");
String variable;
public Ifndef(String line) {
parse(line);
} }
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer("ifndef"); StringBuffer sb = new StringBuffer("ifndef");
sb.append(' ').append(variable); sb.append(' ').append(getVariable());
return sb.toString(); return sb.toString();
} }
public String getVariable() { public String getVariable() {
return variable; return getConditional();
} }
/**
* Format of the include directive:
* ifeq condional-directive
*/
protected void parse(String line) {
line = line.trim();
for (int i = 0; i < line.length(); i++) {
if (MakefileUtil.isSpace(line.charAt(i))) {
line = line.substring(i).trim();
break;
}
}
variable = line;
}
} }

View file

@ -10,40 +10,16 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu; package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.internal.core.makefile.MakefileUtil; public class Ifneq extends Conditional {
import org.eclipse.cdt.make.internal.core.makefile.Statement;
public Ifneq(String cond) {
public class Ifneq extends Statement { super(cond);
String conditional;
public Ifneq(String line) {
parse(line);
} }
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer("ifneq"); StringBuffer sb = new StringBuffer("ifneq");
sb.append(' ').append(conditional); sb.append(' ').append(getConditional());
return sb.toString(); return sb.toString();
} }
public String getConditional() {
return conditional;
}
/**
* Format of the include directive:
* ifeq condional-directive
*/
protected void parse(String line) {
line = line.trim();
for (int i = 0; i < line.length(); i++) {
if (MakefileUtil.isSpace(line.charAt(i))) {
line = line.substring(i).trim();
break;
}
}
conditional = line;
}
} }

View file

@ -10,16 +10,19 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu; package org.eclipse.cdt.make.internal.core.makefile.gnu;
import java.util.StringTokenizer; import java.io.IOException;
import org.eclipse.cdt.make.internal.core.makefile.Statement; import org.eclipse.cdt.make.core.makefile.IDirective;
import org.eclipse.cdt.make.internal.core.makefile.Parent;
public class Include extends Statement { public class Include extends Parent {
String[] filenames; String[] filenames;
String[] dirs;
public Include(String line) { public Include(String[] files, String[] directories) {
parse(line); filenames = files;
dirs = directories;
} }
public String toString() { public String toString() {
@ -34,24 +37,29 @@ public class Include extends Statement {
return filenames; return filenames;
} }
/** public IDirective[] getStatements() {
* Format of the include directive: GNUMakefile gnu = new GNUMakefile();
* include filename1 filename2 ... clearStatements();
*/ for (int i = 0; i < filenames.length; i++) {
protected void parse(String line) { // Try the current directory.
StringTokenizer st = new StringTokenizer(line); try {
int count = st.countTokens(); gnu.parse(filenames[i]);
if (count > 0) { addStatements(gnu.getStatements());
filenames = new String[count - 1]; continue;
for (int i = 0; i < count; i++) { } catch (IOException e) {
if (i == 0) { }
// ignore the "include" keyword. if (!filenames[i].startsWith(GNUMakefile.FILE_SEPARATOR) && dirs != null) {
continue; for (int j = 0; j < dirs.length; j++) {
} try {
filenames[i] = st.nextToken(); String filename = dirs[j] + GNUMakefile.FILE_SEPARATOR + filenames[i];
gnu.parse(filename);
addStatements(gnu.getStatements());
break;
} catch (IOException e) {
}
}
} }
} else {
filenames = new String[0];
} }
return super.getStatements();
} }
} }

View file

@ -1,54 +0,0 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.internal.core.makefile.MakefileUtil;
import org.eclipse.cdt.make.internal.core.makefile.Statement;
public class Override extends Statement {
String variable;
public Override(String line) {
parse(line);
}
public String toString() {
StringBuffer sb = new StringBuffer("override");
sb.append(' ').append(variable);
return sb.toString();
}
public String getVariable() {
return variable;
}
/**
* Format:
* override VARIABLE := VALUE
*/
protected void parse(String line) {
int i = 0;
line = line.trim();
for (; i < line.length(); i++) {
if (MakefileUtil.isSpace(line.charAt(i))) {
break;
}
}
if (i < line.length()) {
variable = line.substring(i).trim();
} else {
variable = new String();
}
}
}

View file

@ -10,51 +10,25 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu; package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.internal.core.makefile.MakefileUtil;
import org.eclipse.cdt.make.internal.core.makefile.Statement;
public class OverrideDefine extends Statement { public class OverrideDefine extends DefineVariable {
String variable;
public OverrideDefine(String line) { public OverrideDefine(String name, StringBuffer value) {
parse(line); super(name, value);
} }
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer("override define"); StringBuffer sb = new StringBuffer("override define ");
sb.append(' ').append(variable); sb.append(getName()).append('\n');
sb.append(getValue());
sb.append("endef");
return sb.toString(); return sb.toString();
} }
public String getVariable() { public boolean isOverride() {
return variable; return true;
} }
/**
* Format:
* override define VARIABLE
*/
protected void parse(String line) {
line = line.trim();
// Pass over "override"
for (int i = 0; i < line.length(); i++) {
if (MakefileUtil.isSpace(line.charAt(i))) {
line = line.substring(i).trim();
break;
}
}
// Pass over "define"
for (int i = 0; i < line.length(); i++) {
if (MakefileUtil.isSpace(line.charAt(i))) {
line = line.substring(i).trim();
break;
}
}
variable = line;
}
} }

View file

@ -0,0 +1,25 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu;
public class OverrideVariable extends VariableDefinition {
public OverrideVariable(String name, StringBuffer value, int type) {
super(name, value, type);
}
public boolean isOverride() {
return true;
}
}

View file

@ -0,0 +1,74 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.core.makefile.ICommand;
import org.eclipse.cdt.make.core.makefile.IInferenceRule;
import org.eclipse.cdt.make.core.makefile.ITarget;
import org.eclipse.cdt.make.internal.core.makefile.InferenceRule;
/**
* Here is the syntax of a static pattern rule:
*
* TARGETS ...: TARGET-PATTERN: DEP-PATTERNS ...
* COMMANDS
* ...
*/
public class StaticTargetRule extends InferenceRule implements IInferenceRule {
String targetPattern;
String[] prereqPatterns;
public StaticTargetRule(ITarget target, String target_pattern, String[] prereq_patterns, ICommand[] commands) {
super(target, commands);
targetPattern = target_pattern;
prereqPatterns = prereq_patterns;
}
public String[] getPrerequisitePatterns() {
return prereqPatterns;
}
public void setPrerequesitePatterns(String[] prereqs) {
prereqPatterns = prereqs;
}
public String getTargetPattern() {
return targetPattern;
}
public void setTargetPattern(String target_pattern) {
targetPattern = target_pattern;
}
/**
* @see java.lang.Object#toString()
*/
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(getTarget()).append(':');
String pattern = getTargetPattern();
if (pattern != null && pattern.length() > 0) {
buffer.append(' ').append(targetPattern);
}
buffer.append(':');
for (int i = 0; i < prereqPatterns.length; i++) {
buffer.append(' ').append(prereqPatterns[i]);
}
buffer.append('\n');
ICommand[] cmds = getCommands();
for (int i = 0; i < cmds.length; i++) {
buffer.append(cmds[i].toString());
}
return buffer.toString();
}
}

View file

@ -0,0 +1,34 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu;
/**
* Here is the syntax of a static pattern rule:
*
* TARGETS ...: VARIABLE-ASSIGNMENT
* TARGETS ...: override VARIABLE-ASSIGNMENT
*/
public class TargetVariable extends VariableDefinition {
boolean override;
public TargetVariable(String target, String name, StringBuffer value, boolean override, int type) {
super(target, name, value, type);
this.override = override;
}
public boolean isOverride() {
return override;
}
}

View file

@ -10,16 +10,14 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu; package org.eclipse.cdt.make.internal.core.makefile.gnu;
import java.util.StringTokenizer;
import org.eclipse.cdt.make.internal.core.makefile.Statement; import org.eclipse.cdt.make.internal.core.makefile.Statement;
public class UnExport extends Statement { public class UnExport extends Statement {
String variable; String variable;
public UnExport(String line) { public UnExport(String var) {
parse(line); variable = var;
} }
public String toString() { public String toString() {
@ -32,24 +30,4 @@ public class UnExport extends Statement {
return variable; return variable;
} }
/**
* Format of the include directive:
* export Variabe ...
*/
protected void parse(String line) {
StringTokenizer st = new StringTokenizer(line);
int count = st.countTokens();
if (count > 0) {
for (int i = 0; i < count; i++) {
if (i == 0) {
// ignore the "unexport" keyword.
continue;
}
variable = st.nextToken();
}
}
if (variable == null) {
variable = new String();
}
}
} }

View file

@ -10,10 +10,6 @@
***********************************************************************/ ***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu; package org.eclipse.cdt.make.internal.core.makefile.gnu;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.eclipse.cdt.make.internal.core.makefile.Statement; import org.eclipse.cdt.make.internal.core.makefile.Statement;
public class VPath extends Statement { public class VPath extends Statement {
@ -21,8 +17,9 @@ public class VPath extends Statement {
String pattern; String pattern;
String[] directories; String[] directories;
public VPath(String line) { public VPath(String pat, String[] dirs) {
parse(line); pattern = pat;
directories = dirs;
} }
public String toString() { public String toString() {
@ -43,44 +40,4 @@ public class VPath extends Statement {
public String getPattern() { public String getPattern() {
return pattern; return pattern;
} }
/**
* There are three forms of the "vpath" directive:
* "vpath PATTERN DIRECTORIES"
* Specify the search path DIRECTORIES for file names that match PATTERN.
*
* The search path, DIRECTORIES, is a list of directories to be
* searched, separated by colons (semi-colons on MS-DOS and
* MS-Windows) or blanks, just like the search path used in the `VPATH' variable.
*
* "vpath PATTERN"
* Clear out the search path associated with PATTERN.
*
* "vpath"
* Clear all search paths previously specified with `vpath' directives.
*/
protected void parse(String line) {
StringTokenizer st = new StringTokenizer(line);
int count = st.countTokens();
List dirs = new ArrayList(count);
if (count > 0) {
for (int i = 0; i < count; i++) {
if (count == 0) {
// ignore the "vpath" directive
st.nextToken();
} else if (count == 1) {
pattern = st.nextToken();
} else if (count == 3) {
String delim = " \t\n\r\f" + GNUMakefile.PATH_SEPARATOR;
dirs.add(st.nextToken(delim));
} else {
dirs.add(st.nextToken());
}
}
}
directories = (String[]) dirs.toArray(new String[0]);
if (pattern == null) {
pattern = new String();
}
}
} }

View file

@ -0,0 +1,132 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu;
import org.eclipse.cdt.make.internal.core.makefile.MacroDefinition;
/**
*/
public class VariableDefinition extends MacroDefinition {
/**
* ? is Conditional
* : is Simply-expanded
* + is append
* 0 is recusively-expanded.
*/
final static int TYPE_RECURSIVE_EXPAND = 0;
final static int TYPE_SIMPLE_EXPAND = ':';
final static int TYPE_CONDITIONAL = '?';
final static int TYPE_APPEND = '+';
int type;
String varTarget;
public VariableDefinition(String name, StringBuffer value) {
this(name, value, TYPE_RECURSIVE_EXPAND);
}
public VariableDefinition(String name, StringBuffer value, int type) {
this("", name, value, type);
}
public VariableDefinition(String target, String name, StringBuffer value, int type) {
super(name, value);
varTarget = target;
this.type = type;
}
/**
* @see java.lang.Object#toString()
*/
public String toString() {
StringBuffer sb = new StringBuffer();
if (isTargetSpecific()) {
sb.append(getTarget()).append(": ");
}
if (isOverride()) {
sb.append("override ");
}
if (isMultiLine()) {
sb.append("define ");
sb.append(getName()).append('\n');
sb.append(getValue()).append('\n');
sb.append("endef\n");
} else {
if (isExport()) {
sb.append("export ");
}
sb.append(getName());
if (isRecursivelyExpanded()) {
sb.append(" = ");
} else if (isSimplyExpanded()) {
sb.append(" := ");
} else if (isConditional()) {
sb.append(" ?= ");
} else if (isAppend()) {
sb.append(" += ");
}
sb.append(getValue()).append('\n');
}
return sb.toString();
}
public boolean equals(VariableDefinition v) {
return v.getName().equals(getName());
}
public boolean isRecursivelyExpanded() {
return type == TYPE_RECURSIVE_EXPAND;
}
public boolean isSimplyExpanded() {
return type == TYPE_SIMPLE_EXPAND;
}
public boolean isConditional() {
return type == TYPE_CONDITIONAL;
}
public boolean isAppend() {
return type == TYPE_APPEND;
}
public boolean isTargetSpecific() {
String t = getTarget();
return t == null || t.length() == 0;
}
public boolean isExport() {
return false;
}
public boolean isMultiLine() {
return false;
}
/**
* Variable from an `override' directive.
*/
public boolean isOverride() {
return false;
}
/**
* Automatic variable -- cannot be set.
*/
public boolean isAutomatic() {
return false;
}
public String getTarget() {
return varTarget;
}
}

View file

@ -15,22 +15,22 @@ import org.eclipse.cdt.make.internal.core.makefile.MacroDefinition;
public class PosixBuiltinMacroDefinitions { public class PosixBuiltinMacroDefinitions {
MacroDefinition[] macros = MacroDefinition[] macros =
new MacroDefinition[] { new MacroDefinition[] {
new MacroDefinition("MAKE=make"), new MacroDefinition("MAKE", "make"),
new MacroDefinition("AR=ar"), new MacroDefinition("AR", "ar"),
new MacroDefinition("ARFLAGS=-rv"), new MacroDefinition("ARFLAGS", "-rv"),
new MacroDefinition("YACC=yacc"), new MacroDefinition("YACC", "yacc"),
new MacroDefinition("YFLAGS="), new MacroDefinition("YFLAGS", ""),
new MacroDefinition("LEX=lex"), new MacroDefinition("LEX", "lex"),
new MacroDefinition("LFLAGS="), new MacroDefinition("LFLAGS", ""),
new MacroDefinition("LDFLAGS="), new MacroDefinition("LDFLAGS", ""),
new MacroDefinition("CC=c89"), new MacroDefinition("CC", "c89"),
new MacroDefinition("CFLAGS=-O"), new MacroDefinition("CFLAGS", "-O"),
new MacroDefinition("FC=fort77"), new MacroDefinition("FC", "fort77"),
new MacroDefinition("FFLAGS=-O 1"), new MacroDefinition("FFLAGS", "-O 1"),
new MacroDefinition("GET=get"), new MacroDefinition("GET", "get"),
new MacroDefinition("GFLAGS="), new MacroDefinition("GFLAGS", ""),
new MacroDefinition("SCCSFLAGS="), new MacroDefinition("SCCSFLAGS", ""),
new MacroDefinition("SCCSGETFLAGS=-s")}; new MacroDefinition("SCCSGETFLAGS", "-s")};
public MacroDefinition getMacroDefinition(String name) { public MacroDefinition getMacroDefinition(String name) {
for (int i = 0; i < macros.length; i++) { for (int i = 0; i < macros.length; i++) {

View file

@ -16,30 +16,39 @@ import java.io.Reader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.eclipse.cdt.make.core.makefile.IStatement; import org.eclipse.cdt.make.core.makefile.ICommand;
import org.eclipse.cdt.make.core.makefile.IDirective;
import org.eclipse.cdt.make.internal.core.makefile.AbstractMakefile; import org.eclipse.cdt.make.internal.core.makefile.AbstractMakefile;
import org.eclipse.cdt.make.internal.core.makefile.BadStatement; import org.eclipse.cdt.make.internal.core.makefile.BadStatement;
import org.eclipse.cdt.make.internal.core.makefile.Command; import org.eclipse.cdt.make.internal.core.makefile.Command;
import org.eclipse.cdt.make.internal.core.makefile.Comment; import org.eclipse.cdt.make.internal.core.makefile.Comment;
import org.eclipse.cdt.make.internal.core.makefile.DefaultRule;
import org.eclipse.cdt.make.internal.core.makefile.EmptyLine; import org.eclipse.cdt.make.internal.core.makefile.EmptyLine;
import org.eclipse.cdt.make.internal.core.makefile.IgnoreRule;
import org.eclipse.cdt.make.internal.core.makefile.InferenceRule; import org.eclipse.cdt.make.internal.core.makefile.InferenceRule;
import org.eclipse.cdt.make.internal.core.makefile.MacroDefinition; import org.eclipse.cdt.make.internal.core.makefile.MacroDefinition;
import org.eclipse.cdt.make.internal.core.makefile.MakefileReader; import org.eclipse.cdt.make.internal.core.makefile.MakefileReader;
import org.eclipse.cdt.make.internal.core.makefile.MakefileUtil; import org.eclipse.cdt.make.internal.core.makefile.PosixRule;
import org.eclipse.cdt.make.internal.core.makefile.PreciousRule;
import org.eclipse.cdt.make.internal.core.makefile.Rule; import org.eclipse.cdt.make.internal.core.makefile.Rule;
import org.eclipse.cdt.make.internal.core.makefile.SccsGetRule;
import org.eclipse.cdt.make.internal.core.makefile.SilentRule;
import org.eclipse.cdt.make.internal.core.makefile.Statement; import org.eclipse.cdt.make.internal.core.makefile.Statement;
import org.eclipse.cdt.make.internal.core.makefile.SuffixesRule;
import org.eclipse.cdt.make.internal.core.makefile.Target; import org.eclipse.cdt.make.internal.core.makefile.Target;
import org.eclipse.cdt.make.internal.core.makefile.TargetRule; import org.eclipse.cdt.make.internal.core.makefile.TargetRule;
import org.eclipse.cdt.make.internal.core.makefile.Util;
/** /**
* Makefile : ( statement ) * * Makefile : ( statement ) *
* statement : rule | macro_definition | comments | empty * statement : rule | macro_definition | comments | empty
* rule : inference_rule | target_rule * rule : inference_rule | target_rule | special_rule
* inference_rule : target ':' <nl> ( <tab> command <nl> ) + * inference_rule : target ':' [ ';' command ] <nl>
* target_rule : target [ ( target ) * ] ':' [ ( prerequisite ) * ] [ ';' command ] <nl> [ ( command ) * ]
[ ( command ) * ] * target_rule : [ ( target ) + ] ':' [ ( prerequisite ) * ] [ ';' command ] <nl>
* macro_definition : string '=' (string)* [ ( command ) * ]
* comments : ('#' (string) <nl>) * * macro_definition : string '=' ( string )*
* comments : ('#' ( string ) <nl>) *
* empty : <nl> * empty : <nl>
* command : <tab> prefix_command string <nl> * command : <tab> prefix_command string <nl>
* target : string * target : string
@ -51,21 +60,19 @@ public class PosixMakefile extends AbstractMakefile {
List statements; List statements;
public PosixMakefile(String name) throws IOException { public PosixMakefile() {
this(new FileReader(name));
}
public PosixMakefile(Reader reader) throws IOException {
this(new MakefileReader(reader));
}
public PosixMakefile(MakefileReader reader) throws IOException {
super();
statements = new ArrayList(); statements = new ArrayList();
parse(reader);
} }
void parse(MakefileReader reader) throws IOException { public void parse(String name) throws IOException {
parse(new FileReader(name));
}
public void parse(Reader reader) throws IOException {
parse(new MakefileReader(reader));
}
protected void parse(MakefileReader reader) throws IOException {
String line; String line;
Rule[] rules = null; Rule[] rules = null;
int startLine = 0; int startLine = 0;
@ -74,143 +81,324 @@ public class PosixMakefile extends AbstractMakefile {
startLine = endLine + 1; startLine = endLine + 1;
endLine = reader.getLineNumber(); endLine = reader.getLineNumber();
// 1- Try command first, since we do not strip '#' in commands // 1- Try command first, since we can not strip '#' in command line
if (MakefileUtil.isCommand(line)) { if (PosixMakefileUtil.isCommand(line)) {
Command cmd = new Command(line); Command cmd = createCommand(line);
cmd.setLines(startLine, endLine); cmd.setLines(startLine, endLine);
// The commands are added to a Rule // The command is added to the rules
if (rules != null) { if (rules != null) {
for (int i = 0; i < rules.length; i++) { for (int i = 0; i < rules.length; i++) {
rules[i].addCommand(cmd); rules[i].addStatement(cmd);
rules[i].setEndLine(endLine); rules[i].setEndLine(endLine);
} }
continue; continue;
} }
// If it is not a command give the other rules a chance a fallthrough // If we have no rules for the command,
// give the other statements a chance by falling through
} }
// 2- Strip away any comments. // 2- Strip away any comments.
int pound = MakefileUtil.indexOfComment(line); int pound = Util.indexOfComment(line);
if (pound != -1) { if (pound != -1) {
// Comment. Comment cmt = createComment(line.substring(pound + 1));
Statement stmt = new Comment(line.substring(pound + 1)); cmt.setLines(startLine, endLine);
stmt.setLines(startLine, endLine); addStatement(cmt);
addStatement(stmt);
line = line.substring(0, pound); line = line.substring(0, pound);
// If all we have left are spaces continue // If all we have left are spaces continue
if (MakefileUtil.isEmptyLine(line)) { if (Util.isEmptyLine(line)) {
continue; continue;
} }
// The rest of the line maybe a valid statement.
// keep on trying by falling through.
} }
// 3- Empty lines ? // 3- Empty lines ?
if (MakefileUtil.isEmptyLine(line)) { if (Util.isEmptyLine(line)) {
// Empty Line. Statement empty = createEmptyLine();
Statement stmt = new EmptyLine(); empty.setLines(startLine, endLine);
stmt.setLines(startLine, endLine); addStatement(empty);
addStatement(stmt);
continue; continue;
} }
// 4- Check for inference rule. // 4- reset the rules to null
if (MakefileUtil.isInferenceRule(line)) { // The first non empty line that does not begin with a <TAB> or '#'
// Inference Rule // shall begin a new entry.
String tgt; rules = null;
int index = MakefileUtil.indexOf(line, ':');
if (index != -1) { // 5- Check for the special targets.
tgt = line.substring(0, index); if (PosixMakefileUtil.isDefaultRule(line)) {
} else { DefaultRule dRule = createDefaultRule(line);
tgt = line; rules = new Rule[] { dRule };
} dRule.setLines(startLine, endLine);
InferenceRule irule = new InferenceRule(new Target(tgt)); addStatement(dRule);
continue;
} else if (PosixMakefileUtil.isIgnoreRule(line)) {
IgnoreRule ignore = createIgnoreRule(line);
ignore.setLines(startLine, endLine);
addStatement(ignore);
continue;
} else if (PosixMakefileUtil.isPosixRule(line)) {
PosixRule pRule = createPosixRule();
pRule.setLines(startLine, endLine);
addStatement(pRule);
continue;
} else if (PosixMakefileUtil.isPreciousRule(line)) {
PreciousRule precious = createPreciousRule(line);
precious.setLines(startLine, endLine);
addStatement(precious);
continue;
} else if (PosixMakefileUtil.isSccsGetRule(line)) {
SccsGetRule sccs = createSccsGetRule(line);
rules = new Rule[] { sccs };
sccs.setLines(startLine, endLine);
addStatement(sccs);
continue;
} else if (PosixMakefileUtil.isSilentRule(line)) {
SilentRule silent = createSilentRule(line);
silent.setLines(startLine, endLine);
addStatement(silent);
continue;
} else if (PosixMakefileUtil.isSuffixesRule(line)) {
SuffixesRule suffixes = createSuffixesRule(line);
suffixes.setLines(startLine, endLine);
addStatement(suffixes);
continue;
}
// 6- Check for inference rule.
if (PosixMakefileUtil.isInferenceRule(line)) {
InferenceRule irule = createInferenceRule(line);
irule.setLines(startLine, endLine); irule.setLines(startLine, endLine);
addStatement(irule); addStatement(irule);
rules = new Rule[]{irule}; rules = new Rule[]{irule};
continue; continue;
} }
// 5- Macro Definiton ? // 7- Macro Definiton ?
if (MakefileUtil.isMacroDefinition(line)) { if (PosixMakefileUtil.isMacroDefinition(line)) {
// MacroDefinition Statement stmt = createMacroDefinition(line);
Statement stmt = new MacroDefinition(line);
stmt.setLines(startLine, endLine); stmt.setLines(startLine, endLine);
addStatement(stmt); addStatement(stmt);
continue; continue;
} }
// 6- Target Rule ? // 8- Target Rule ?
if (MakefileUtil.isTargetRule(line)) { if (PosixMakefileUtil.isTargetRule(line)) {
String[] targets; TargetRule[] trules = createTargetRule(line);
String[] reqs = new String[0]; for (int i = 0; i < trules.length; i++) {
String cmd = null; trules[i].setLines(startLine, endLine);
int index = MakefileUtil.indexOf(line.toCharArray(), ':'); addStatement(trules[i]);
if (index != -1) {
String target = line.substring(0, index);
// Break the targets, some target have "::" for separator
if (target.startsWith(":")) {
target = target.substring(1);
}
targets = MakefileUtil.findTargets(target.trim());
String req = line.substring(index + 1);
int semicolon = MakefileUtil.indexOf(req, ';');
if (semicolon != -1) {
cmd = req.substring(semicolon + 1);
req = req.substring(0, semicolon);
}
reqs = MakefileUtil.findPrerequisites(req.trim());
} else {
targets = MakefileUtil.findTargets(line);
}
Target[] preqs = new Target[reqs.length];
for (int i = 0; i < reqs.length; i++) {
preqs[i] = new Target(reqs[i]);
}
rules = new Rule[targets.length];
for (int i = 0; i < targets.length; i++) {
Rule rule = new TargetRule(new Target(targets[i]), preqs);
rule.setLines(startLine, endLine);
addStatement(rule);
if (cmd != null) {
rule.addCommand(new Command(cmd));
}
rules[i] = rule;
} }
rules = trules;
continue; continue;
} }
// Other type of processing ? // XXX ?? Should not be here.
Statement stmt = processLine(line); BadStatement stmt = new BadStatement(line);
if (stmt == null) {
// Should not be here.
stmt = new BadStatement(line);
}
stmt.setLines(startLine, endLine); stmt.setLines(startLine, endLine);
addStatement(stmt); addStatement(stmt);
} }
setLines(1, endLine);
} }
protected Statement processLine(String line) { public IDirective[] getStatements() {
return null; return (IDirective[]) statements.toArray(new IDirective[0]);
} }
public IStatement[] getStatements() { public IDirective[] getBuiltins() {
return (IStatement[]) statements.toArray(new IStatement[0]); IDirective[] macros = new PosixBuiltinMacroDefinitions().getMacroDefinitions();
} IDirective[] rules = new PosixBuiltinRules().getInferenceRules();
IDirective[] stmts = new IDirective[macros.length + rules.length];
public IStatement[] getBuiltins() {
IStatement[] macros = new PosixBuiltinMacroDefinitions().getMacroDefinitions();
IStatement[] rules = new PosixBuiltinRules().getInferenceRules();
IStatement[] stmts = new IStatement[macros.length + rules.length];
System.arraycopy(macros, 0, stmts, 0, macros.length); System.arraycopy(macros, 0, stmts, 0, macros.length);
System.arraycopy(rules, 0, stmts, macros.length, rules.length); System.arraycopy(rules, 0, stmts, macros.length, rules.length);
return stmts; return stmts;
} }
public void addStatement(Statement stmt) { /**
statements.add(stmt); * Comment
*/
public Comment createComment(String line) {
return new Comment(line);
}
/**
* EmptyLine
*/
public EmptyLine createEmptyLine() {
return new EmptyLine();
}
/**
* Command
*/
public Command createCommand(String line) {
return new Command(line);
}
/**
* Inference Rule
*/
public InferenceRule createInferenceRule(String line) {
String tgt;
int index = Util.indexOf(line, ':');
if (index != -1) {
tgt = line.substring(0, index);
} else {
tgt = line;
}
return new InferenceRule(new Target(tgt));
}
/**
* MacroDefinition
*/
public MacroDefinition createMacroDefinition(String line) {
String name;
String value;
int index = Util.indexOf(line, '=');
if (index != -1) {
name = line.substring(0, index).trim();
value = line.substring(index + 1).trim();
} else {
name = line;
value = "";
}
return new MacroDefinition(name, value);
}
/**
* TargetRule
*/
public TargetRule[] createTargetRule(String line) {
String[] targets;
String[] reqs;
String cmd = null;
int index = Util.indexOf(line, ':');
if (index != -1) {
String target = line.substring(0, index);
// Tokenize the targets
targets = PosixMakefileUtil.findTargets(target);
String req = line.substring(index + 1);
int semicolon = Util.indexOf(req, ';');
if (semicolon != -1) {
String c = req.substring(semicolon + 1).trim();
if (c.length() > 0) {
cmd = c;
}
req = req.substring(0, semicolon);
}
reqs = PosixMakefileUtil.findPrerequisites(req);
} else {
targets = PosixMakefileUtil.findTargets(line);
reqs = new String[0];
}
TargetRule[] targetRules = new TargetRule[targets.length];
for (int i = 0; i < targets.length; i++) {
targetRules[i] = new TargetRule(new Target(targets[i]), reqs);
if (cmd != null) {
Command command = createCommand(cmd);
targetRules[i].addStatement(command);
}
}
return targetRules;
}
/**
* .DEFAULT
*/
public DefaultRule createDefaultRule(String line) {
int semicolon = Util.indexOf(line, ';');
if (semicolon > 0) {
String cmd = line.substring(semicolon + 1).trim();
if (cmd.length() > 0) {
ICommand[] cmds = new ICommand[] { new Command(cmd)};
return new DefaultRule(cmds);
}
}
return new DefaultRule(new ICommand[0]);
}
/**
* .IGNORE
*/
public IgnoreRule createIgnoreRule(String line) {
int index = Util.indexOf(line, ':');
if (index != -1) {
String req = line.substring(index + 1);
String[] reqs = PosixMakefileUtil.findPrerequisites(req);
return new IgnoreRule(reqs);
}
return new IgnoreRule(new String[0]);
}
/**
* .POSIX
*/
public PosixRule createPosixRule() {
return new PosixRule();
}
/**
* .PRECIOUS
*/
public PreciousRule createPreciousRule(String line) {
int index = Util.indexOf(line, ':');
if (index != -1) {
String req = line.substring(index + 1);
String[] reqs = PosixMakefileUtil.findPrerequisites(req);
return new PreciousRule(reqs);
}
return new PreciousRule(new String[0]);
}
/**
* .SCCS_GET
*/
public SccsGetRule createSccsGetRule(String line) {
int semicolon = Util.indexOf(line, ';');
if (semicolon != -1) {
String cmd = line.substring(semicolon + 1).trim();
if (cmd.length() > 0) {
ICommand[] cmds = new ICommand[] { new Command(cmd)};
return new SccsGetRule(cmds);
}
}
return new SccsGetRule(new ICommand[0]);
}
/**
* .SILENT
*/
public SilentRule createSilentRule(String line) {
int index = Util.indexOf(line, ':');
if (index != -1) {
String req = line.substring(index + 1);
String[] reqs = PosixMakefileUtil.findPrerequisites(req);
return new SilentRule(reqs);
}
return new SilentRule(new String[0]);
}
/**
* .SUFFIXES
*/
public SuffixesRule createSuffixesRule(String line) {
int index = Util.indexOf(line, ':');
if (index != -1) {
String req = line.substring(index + 1);
String[] reqs = PosixMakefileUtil.findPrerequisites(req);
return new SuffixesRule(reqs);
}
return new SuffixesRule(new String[0]);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.make.internal.core.makefile.AbstractMakefile#addStatement(org.eclipse.cdt.make.core.makefile.IDirective)
*/
public void addStatement(IDirective statement) {
statements.add(statement);
} }
public static void main(String[] args) { public static void main(String[] args) {
@ -219,8 +407,9 @@ public class PosixMakefile extends AbstractMakefile {
if (args.length == 1) { if (args.length == 1) {
filename = args[0]; filename = args[0];
} }
PosixMakefile makefile = new PosixMakefile(filename); PosixMakefile makefile = new PosixMakefile();
IStatement[] statements = makefile.getStatements(); makefile.parse(filename);
IDirective[] statements = makefile.getStatements();
for (int i = 0; i < statements.length; i++) { for (int i = 0; i < statements.length; i++) {
//System.out.println("Rule[" + i +"]"); //System.out.println("Rule[" + i +"]");
System.out.print(statements[i]); System.out.print(statements[i]);
@ -230,11 +419,4 @@ public class PosixMakefile extends AbstractMakefile {
} }
} }
/* (non-Javadoc)
* @see org.eclipse.cdt.make.internal.core.makefile.AbstractMakefile#addStatement(org.eclipse.cdt.make.core.makefile.IStatement)
*/
public void addStatement(IStatement statement) {
statements.add(statement);
}
} }

View file

@ -0,0 +1,160 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.posix;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.make.internal.core.makefile.Util;
/**
*/
public class PosixMakefileUtil {
public static String[] findPrerequisites(String line) {
return findTargets(line);
}
public static String[] findTargets(String line) {
List aList = new ArrayList();
int space;
// Trim away trailing and prepending spaces.
line = line.trim();
while ((space = Util.indexOf(line, " \t")) != -1) {
aList.add(line.substring(0, space).trim());
line = line.substring(space + 1).trim();
}
// The last target.
if (line.length() > 0) {
aList.add(line);
}
return (String[]) aList.toArray(new String[0]);
}
public static boolean isMacroDefinition(String line) {
return Util.indexOf(line, '=') != -1;
}
public static boolean isTargetRule(String line) {
return Util.indexOf(line, ':') != -1;
}
public static boolean isCommand(String line) {
return line.length() > 1 && line.charAt(0) == '\t';
}
public static boolean isEmptyLine(String line) {
return line.trim().length() == 0;
}
public static boolean isInferenceRule(String line) {
line = line.trim();
if (line.startsWith(".")) {
int index = Util.indexOf(line, ':');
if (index > 1) {
line = line.substring(index + 1).trim();
if (line.length() == 0 || line.equals(";")) {
return true;
}
}
}
return false;
}
public static boolean isDefaultRule(String line) {
line = line.trim();
int colon = Util.indexOf(line, ':');
if (colon > 0) {
line = line.substring(0, colon).trim();
return line.equals(".DEFAULT");
}
return false;
}
public static boolean isIgnoreRule(String line) {
line = line.trim();
int colon = Util.indexOf(line, ':');
if (colon > 0) {
line = line.substring(0, colon).trim();
return line.equals(".IGNORE");
}
return false;
}
public static boolean isPosixRule(String line) {
line = line.trim();
int colon = Util.indexOf(line, ':');
if (colon > 0) {
line = line.substring(0, colon).trim();
return line.equals(".POSIX");
}
return false;
}
public static boolean isPreciousRule(String line) {
line = line.trim();
int colon = Util.indexOf(line, ':');
if (colon > 0) {
line = line.substring(0, colon).trim();
return line.equals(".PRECIOUS");
}
return false;
}
public static boolean isSccsGetRule(String line) {
line = line.trim();
int colon = Util.indexOf(line, ':');
if (colon > 0) {
line = line.substring(0, colon).trim();
return line.equals(".SCCS_GET");
}
return false;
}
public static boolean isSilentRule(String line) {
line = line.trim();
int colon = Util.indexOf(line, ':');
if (colon > 0) {
line = line.substring(0, colon).trim();
return line.equals(".SILENT");
}
return false;
}
public static boolean isSuffixesRule(String line) {
line = line.trim();
int colon = Util.indexOf(line, ':');
if (colon > 0) {
line = line.substring(0, colon).trim();
return line.equals(".SUFFIXES");
}
return false;
}
public static boolean isLibraryTarget(String line) {
char prev = 0;
int paren = 0;
for (int i = 0; i < line.length(); i++) {
char ch = line.charAt(i);
if (ch == '(' && prev != '$' && prev != '\\') {
paren++;
} else if (ch == ')' && prev != '\\') {
if (paren > 0) {
return true;
}
}
prev = ch;
}
return false;
}
}