From 5c99a8cdca04fc85016aed8d45018e96f9c352ea Mon Sep 17 00:00:00 2001
From: Alain Magloire <alain@qnx.com>
Date: Tue, 2 Sep 2003 02:01:36 +0000
Subject: [PATCH] First draft of a Makefile parser.

---
 .../core/makefile/AbstractMakefile.java       | 129 +++++++++++++++
 .../make/internal/core/makefile/Command.java  | 108 +++++++++++++
 .../make/internal/core/makefile/Comment.java  |  37 +++++
 .../internal/core/makefile/EmptyLine.java     |  28 ++++
 .../internal/core/makefile/InferenceRule.java |  37 +++++
 .../core/makefile/MacroDefinition.java        |  67 ++++++++
 .../make/internal/core/makefile/Makefile.java |  93 +++++++++++
 .../cdt/make/internal/core/makefile/Rule.java |  61 +++++++
 .../internal/core/makefile/Statement.java     |  16 ++
 .../make/internal/core/makefile/Target.java   |  40 +++++
 .../internal/core/makefile/TargetRule.java    |  73 +++++++++
 .../cdt/make/internal/core/makefile/Util.java | 109 +++++++++++++
 .../posix/PosixBuiltinMacroDefinitions.java   |  47 ++++++
 .../makefile/posix/PosixBuiltinRules.java     | 123 ++++++++++++++
 .../core/makefile/posix/PosixMakefile.java    | 153 ++++++++++++++++++
 15 files changed, 1121 insertions(+)
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/AbstractMakefile.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Command.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Comment.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/EmptyLine.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/InferenceRule.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/MacroDefinition.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Makefile.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Rule.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Statement.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Target.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/TargetRule.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Util.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixBuiltinMacroDefinitions.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixBuiltinRules.java
 create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixMakefile.java

diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/AbstractMakefile.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/AbstractMakefile.java
new file mode 100644
index 00000000000..ff6e0f9d538
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/AbstractMakefile.java
@@ -0,0 +1,129 @@
+/**********************************************************************
+ * 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;
+
+/**
+ * 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 AbstractMakefile {
+
+	public AbstractMakefile() {
+	}
+
+	public abstract Statement[] getStatements();
+	public abstract void addStatement(Statement statement);
+
+	public Rule[] getRules() {
+		Statement[] stmts = getStatements();
+		List array = new ArrayList(stmts.length);
+		for (int i = 0; i < stmts.length; i++) {
+			if (stmts[i] instanceof Rule) {
+				array.add(stmts[i]);
+			}
+		}
+		return (Rule[]) array.toArray(new Rule[0]);
+	}
+
+	public Rule getRule(String target) {
+		Rule[] rules = getRules();
+		for (int i = 0; i < rules.length; i++) {
+			if (rules[i].getTarget().equals(target)) {
+				return rules[i];
+			}
+		}
+		return null;
+	}
+
+	public InferenceRule[] getInferenceRules() {
+		Rule[] rules = getRules();
+		List array = new ArrayList(rules.length);
+		for (int i = 0; i < rules.length; i++) {
+			if (rules[i] instanceof InferenceRule) {
+				array.add(rules[i]);
+			}
+		}
+		return (InferenceRule[]) array.toArray(new InferenceRule[0]);
+	}
+
+	public InferenceRule getInferenceRule(String target) {
+		InferenceRule[] irules = getInferenceRules();
+		for (int i = 0; i < irules.length; i++) {
+			if (irules[i].getTarget().equals(target)) {
+				return irules[i];
+			}
+		}
+		return null;
+	}
+
+	public TargetRule[] getTargetRules() {
+		Rule[] rules = getRules();
+		List array = new ArrayList(rules.length);
+		for (int i = 0; i < rules.length; i++) {
+			if (rules[i] instanceof TargetRule) {
+				array.add(rules[i]);
+			}
+		}
+		return (TargetRule[]) array.toArray(new TargetRule[0]);
+	}
+
+	public TargetRule getTargetRule(String target) {
+		TargetRule[] trules = getTargetRules();
+		for (int i = 0; i < trules.length; i++) {
+			if (trules[i].getTarget().equals(target)) {
+				return trules[i];
+			}
+		}
+		return null;
+	}
+
+	public MacroDefinition[] getMacroDefinitions() {
+		Statement[] stmts = getStatements();
+		List array = new ArrayList(stmts.length);
+		for (int i = 0; i < stmts.length; i++) {
+			if (stmts[i] instanceof MacroDefinition) {
+				array.add(stmts[i]);
+			}
+		}
+		return (MacroDefinition[]) array.toArray(new MacroDefinition[0]);
+	}
+
+	public MacroDefinition getMacroDefinition(String name) {
+		MacroDefinition[] variables = getMacroDefinitions();
+		for (int i = 0; i < variables.length; i++) {
+			if (variables[i].getName().equals(name)) {
+				return variables[i];
+			}
+		}
+		return null;
+	}
+
+	public void addStatements(Statement[] stmts) {
+		for (int i = 0; i < stmts.length; i++) {
+			addStatement(stmts[i]);
+		}
+	}
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Command.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Command.java
new file mode 100644
index 00000000000..564b12bbbe5
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Command.java
@@ -0,0 +1,108 @@
+/**********************************************************************
+ * 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;
+
+/**
+ * Makefile : ( statement ) *
+ * statement : command | ..  
+ * command : <tab> prefix_command string <nl>
+ * prefix_command : '-' | '@' | '+'
+ */
+
+public class Command extends Statement {
+
+	final public static char HYPHEN = '-';
+	final public static String HYPHEN_STRING = "-";
+	final public static char AT = '@';
+	final public static String AT_STRING = "@";
+	final public static char PLUS = '+';
+	final public static String PLUS_STRING = "+";
+	final public static char TAB = '\t';
+	final public static char NL = '\n';
+
+	String command = "";
+	char prefix = '\0';
+
+	public Command(String cmd) {
+		parse(cmd);
+	}
+
+	/**
+	 *   -    If the command prefix contains a hyphen, or the -i option is
+	 * present, or the special target .IGNORE has either the current
+	 * target as a prerequisite or has no prerequisites, any error
+	 * found while executing the command will be ignored.
+	 */
+	public boolean shouldIgnoreError() {
+		// Check for the prefix hyphen in the command.
+		if (getPrefix() == HYPHEN) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * @    If the command prefix contains an at sign and the
+	 * command-line -n option is not specified, or the -s option is
+	 * present, or the special target .SILENT has either the current
+	 * target as a prerequisite or has no prerequisites, the command
+	 * will not be written to standard output before it is executed.
+	 */
+	public boolean shouldBeSilent() {
+		// Check for the prefix at sign
+		if (getPrefix() == AT) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * +    If the command prefix contains a plus sign, this indicates a
+	 * command line that will be executed even if -n, -q or -t is
+	 * specified.
+	 */
+	public boolean shouldExecute() {
+		// Check for the prefix at sign
+		if (getPrefix() == PLUS) {
+			return true;
+		}
+		return false;
+	}
+
+	public String toString() {
+		StringBuffer cmd = new StringBuffer();
+		cmd.append((char) '\t');
+		if (getPrefix() != 0) {
+			cmd.append(getPrefix());
+		}
+		cmd.append(command).append((char) '\n');
+		return cmd.toString();
+	}
+
+	public boolean equals(Command cmd) {
+		return cmd.getPrefix() == getPrefix() && cmd.toString().equals(toString());
+	}
+
+	char getPrefix() {
+		return prefix;
+	}
+
+	/**
+	* command : <tab> prefix_command string <nl>
+	*/
+	void parse(String cmd) {
+		command = cmd.trim();
+		if (command.startsWith(HYPHEN_STRING) || command.startsWith(AT_STRING) || command.startsWith(PLUS_STRING)) {
+			prefix = command.charAt(0);
+			command = command.substring(1);
+		}
+	}
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Comment.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Comment.java
new file mode 100644
index 00000000000..8bf5f33a2e3
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Comment.java
@@ -0,0 +1,37 @@
+/**********************************************************************
+ * 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;
+
+public class Comment extends Statement {
+
+	final public static char pound = '#';
+	final public static String square = "#";
+
+	String comment;
+
+	public Comment(String cmt) {
+		if (cmt.startsWith(square)) {
+			comment = cmt.substring(1);
+		} else {
+			comment = cmt;
+		}
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(square).append(comment).append('\n');
+		return buffer.toString();
+	}
+
+	public boolean equals(Comment cmt) {
+		return cmt.toString().equals(toString());
+	}
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/EmptyLine.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/EmptyLine.java
new file mode 100644
index 00000000000..c5c6c95c08c
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/EmptyLine.java
@@ -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;
+
+public class EmptyLine extends Statement {
+
+	final public static String newline = "\n";
+	final public static char nl = '\n';
+
+	public EmptyLine() {
+	}
+
+	public String toString() {
+		return newline;
+	}
+
+	public boolean equals(EmptyLine stmt) {
+		return true;
+	}
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/InferenceRule.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/InferenceRule.java
new file mode 100644
index 00000000000..7dd436cbdbd
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/InferenceRule.java
@@ -0,0 +1,37 @@
+/**********************************************************************
+ * 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;
+
+public class InferenceRule extends Rule {
+
+	public InferenceRule(String target) {
+		this(target, new Command[0]);
+	}
+
+	public InferenceRule(String target, Command[] commands) {
+		super(target, commands);
+	}
+
+	/**
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(target).append(':');
+		buffer.append('\n');
+		Command[] cmds = getCommands();
+		for (int i = 0; i < cmds.length; i++) {
+			buffer.append(cmds[i].toString());
+		}
+		return buffer.toString();
+	}
+
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/MacroDefinition.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/MacroDefinition.java
new file mode 100644
index 00000000000..c119786ed2f
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/MacroDefinition.java
@@ -0,0 +1,67 @@
+/**********************************************************************
+ * 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;
+
+/**
+ */
+public class MacroDefinition extends Statement {
+	String name;
+	StringBuffer value;
+
+	public MacroDefinition(String line) {
+		value = new StringBuffer();
+		int index = line.indexOf('=');
+		if (index != -1) {
+			name = line.substring(0, index);
+			value.append(line.substring(index + 1));
+		} else {
+			name = line;
+		}
+	}
+
+	public MacroDefinition(String n, String v) {
+		name = n;
+		value = new StringBuffer(v);
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String n) {
+		name = n;
+	}
+
+	public String getValue() {
+		return value.toString();
+	}
+
+	public void setValue(String val) {
+		value = new StringBuffer(val);
+	}
+
+	public void append(String val) {
+		value.append(' ').append(val);
+	}
+
+	/**
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(name).append(" = ").append(value).append('\n');
+		return buffer.toString();
+	}
+
+	public boolean equals(MacroDefinition v) {
+		return v.getName().equals(getName());
+	}
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Makefile.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Makefile.java
new file mode 100644
index 00000000000..00ffcd2a371
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Makefile.java
@@ -0,0 +1,93 @@
+/**********************************************************************
+ * 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;
+
+/**
+ * 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 Rule[] getRules() {
+		return null;
+	}
+	public Rule getRule(String target) {
+		return null;
+	}
+	public InferenceRule[] getInferenceRules() {
+		return null;
+	}
+	public InferenceRule getInferenceRule(String target) {
+		return null;
+	}
+	public TargetRule[] getTargetRules() {
+		return null;
+	}
+	public TargetRule getTargetRule(String target) {
+		return null;
+	}
+
+	public Rule[] getBuiltinRules() {
+		return null;
+	}
+	public Rule getBuiltinRule(String target) {
+		return null;
+	}
+	public Rule[] getBuiltinInferenceRules() {
+		return null;
+	}
+	public Rule 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;
+	}
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Rule.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Rule.java
new file mode 100644
index 00000000000..57f8ae6e6f5
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Rule.java
@@ -0,0 +1,61 @@
+/**********************************************************************
+ * 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;
+
+public abstract class Rule extends Statement {
+
+	Command[] commands;
+	String target;
+
+	public Rule(String target) {
+		this(target, new Command[0]);
+	}
+
+	public Rule(String tgt, Command[] cmds) {
+		target = tgt;
+		commands = cmds;
+	}
+
+	public Command[] getCommands() {
+		return commands;
+	}
+
+	public void setCommand(Command[] cmds) {
+		commands = cmds;
+	}
+
+	public String getTarget() {
+		return target;
+	}
+
+	public void setTarget(String tgt) {
+		target = tgt;
+	}
+
+	public void addCommand(Command cmd) {
+		Command[] newCmds = new Command[commands.length + 1];
+		System.arraycopy(commands, 0, newCmds, 0, commands.length);
+		newCmds[commands.length] = cmd;
+		commands = newCmds;
+	}
+
+	public void addCommands(Command[] cmds) {
+		Command[] newCmds = new Command[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) {
+		return r.getTarget().equals(getTarget());
+	}
+
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Statement.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Statement.java
new file mode 100644
index 00000000000..cbf846a5ec6
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Statement.java
@@ -0,0 +1,16 @@
+/**********************************************************************
+ * 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;
+
+public abstract class Statement {
+
+	public abstract String toString();
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Target.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Target.java
new file mode 100644
index 00000000000..399c9bd42d5
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Target.java
@@ -0,0 +1,40 @@
+/**********************************************************************
+ * 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.File;
+
+public class Target {
+
+	File file;
+	TargetRule rule;
+
+	public Target(TargetRule r) {
+		rule = r;
+		file = new File(rule.getTarget());
+	}
+
+	public boolean exits() {
+		return file.exists();
+	}
+
+	public int make(boolean echo) {
+		return 0;
+	}
+
+	public boolean isUptodate() {
+		return false;
+	}
+
+	public long lastModified() {
+		return file.lastModified();
+	}
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/TargetRule.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/TargetRule.java
new file mode 100644
index 00000000000..0c20d488da8
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/TargetRule.java
@@ -0,0 +1,73 @@
+/**********************************************************************
+ * 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;
+
+/**
+ * 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> 
+                 [ ( <tab> prefix_command command ) * ]
+ * macro_definition : string '=' (string)* 
+ * comments : '#' (string) *
+ * empty : <nl>
+ * command : string <nl>
+ * target : string
+ * prefix_command : '-' | '@' | '+'
+ * internal_macro :  "$<" | "$*" | "$@" | "$?" | "$%" 
+ */
+
+public class TargetRule extends Rule {
+
+	String[] dependencies;
+
+	public TargetRule(String target) {
+		this(target, new String[0]);
+	}
+
+	public TargetRule(String target, String[] pres) {
+		this(target, pres, new Command[0]);
+	}
+
+	public TargetRule(String target, String[] deps, Command[] commands) {
+		super(target, commands);
+		dependencies = deps;
+	}
+
+	public String[] getDependencies() {
+		return dependencies;
+	}
+
+	public void setDependecies(String[] reqs) {
+		dependencies = reqs;
+	}
+
+	/**
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(target);
+		if (buffer.length() > 0) {
+			buffer.append(": ");
+			for (int i = 0; i < dependencies.length; i++) {
+				buffer.append(dependencies[i]).append(' ');
+			}
+			buffer.append('\n');
+			Command[] cmds = getCommands();
+			for (int i = 0; i < cmds.length; i++) {
+				buffer.append(cmds[i].toString());
+			}
+		}
+		return buffer.toString();
+	}
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Util.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Util.java
new file mode 100644
index 00000000000..e251109388e
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/Util.java
@@ -0,0 +1,109 @@
+/**********************************************************************
+ * 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.BufferedReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ */
+public class Util {
+
+	private Util() {
+	}
+
+	public static String readLine(BufferedReader br) throws IOException {
+		boolean done = false;
+		StringBuffer buffer = new StringBuffer();
+		boolean escaped = false;
+		while (!done) {
+			String line = br.readLine();
+			if (line == null) {
+				return null;
+			}
+
+			if (escaped) {
+				line = line.trim();
+			}
+
+			// Eat the spaces at the beginning.
+			if (line.length() > 0 && line.charAt(0) == ' ') {
+				int i = 1;
+				while (i < line.length() && line.charAt(i) == ' ') {
+					i++;
+				}
+				line = line.substring(i);
+			}
+
+			if (line.endsWith("\\")) {
+				escaped = true;
+				int index = line.indexOf('\\');
+				if (index > 0) {
+					buffer.append(line.substring(0, index));
+					buffer.append(' ');
+				}
+			} else {
+				done = true;
+				escaped = false;
+				buffer.append(line);
+			}
+		}
+		return buffer.toString();
+	}
+
+	public static String[] findTargets(String line) {
+		List aList = new ArrayList();
+		int space;
+		while ((space = indexOf(line, ' ')) != -1) {
+			aList.add(line.substring(0, space).trim());
+			line = line.substring(space + 1).trim();
+		}
+		if (line.length() > 0) {
+			aList.add(line);
+		}
+		return (String[]) aList.toArray(new String[0]);
+	}
+
+	public static String[] findPrerequisites(String line) {
+		return findTargets(line);
+	}
+
+	public static boolean isMacroDefinition(char[] line) {
+		return indexOf(line, '=') != -1;
+	}
+
+	public static boolean isRule(char[] line) {
+		return indexOf(line, ':') != -1;
+	}
+
+	public static int indexOf(String s, char c) {
+		return indexOf(s.toCharArray(), c);
+	}
+
+	public static int indexOf(char[] line, char c) {
+		int level = 0;
+		for (int i = 0; i < line.length; i++) {
+			if (line[i] == '(' || line[i] == '{') {
+				level++;
+			} else if (line[i] == ')' || line[i] == '}') {
+				level--;
+			} else if (line[i] == c) {
+				if (level == 0) {
+					return i;
+				}
+			}
+		}
+		return -1;
+	}
+
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixBuiltinMacroDefinitions.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixBuiltinMacroDefinitions.java
new file mode 100644
index 00000000000..01113fda100
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixBuiltinMacroDefinitions.java
@@ -0,0 +1,47 @@
+/**********************************************************************
+ * 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 org.eclipse.cdt.make.internal.core.makefile.MacroDefinition;
+
+public class PosixBuiltinMacroDefinitions {
+	MacroDefinition[] macros =
+		new MacroDefinition[] {
+			new MacroDefinition("MAKE=make"),
+			new MacroDefinition("AR=ar"),
+			new MacroDefinition("ARFLAGS=-rv"),
+			new MacroDefinition("YACC=yacc"),
+			new MacroDefinition("YFLAGS="),
+			new MacroDefinition("LEX=lex"),
+			new MacroDefinition("LFLAGS="),
+			new MacroDefinition("LDFLAGS="),
+			new MacroDefinition("CC=c89"),
+			new MacroDefinition("CFLAGS=-O"),
+			new MacroDefinition("FC=fort77"),
+			new MacroDefinition("FFLAGS=-O 1"),
+			new MacroDefinition("GET=get"),
+			new MacroDefinition("GFLAGS="),
+			new MacroDefinition("SCCSFLAGS="),
+			new MacroDefinition("SCCSGETFLAGS=-s")};
+
+	MacroDefinition getMacroDefinition(String name) {
+		for (int i = 0; i < macros.length; i++) {
+			if (name.equals(macros[i].getName())) {
+				return macros[i];
+			}
+		}
+		return null;
+	}
+
+	MacroDefinition[] getMacroDefinitions() {
+		return macros;
+	}
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixBuiltinRules.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixBuiltinRules.java
new file mode 100644
index 00000000000..991660d6218
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixBuiltinRules.java
@@ -0,0 +1,123 @@
+/**********************************************************************
+ * 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 org.eclipse.cdt.make.internal.core.makefile.Command;
+import org.eclipse.cdt.make.internal.core.makefile.InferenceRule;
+
+public class PosixBuiltinRules {
+	InferenceRule[] rules = new InferenceRule[] {
+		// Special Targets
+		new InferenceRule(".SCCS_GET", new Command[] { new Command("sccs $(SCCSFLAGS) get $(SCCSGETFLAGS) $@")}),
+			new InferenceRule(".SUFFIXES", new Command[] { new Command(" .o .c .y .l .a .sh .f .c~ .y~ .l~ .sh~ .f~")}),
+		//  Single Suffix Rules
+		new InferenceRule(".c", new Command[] { new Command("$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<")}),
+			new InferenceRule(".f", new Command[] { new Command("$(FC) $(FFLAGS) $(LDFLAGS) -o $@ $<")}),
+			new InferenceRule(".sh", new Command[] { new Command("cp $< $@"), new Command("chmod a+x $@")}),
+			new InferenceRule(
+				".c~",
+				new Command[] {
+					new Command("$(GET) $(GFLAGS) -p $< > $*.c"),
+					new Command("$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $*.c")}),
+			new InferenceRule(
+				".f~",
+				new Command[] {
+					new Command("$(GET) $(GFLAGS) -p $< > $*.f"),
+					new Command("$(FC) $(FFLAGS) $(LDFLAGS) -o $@ $*.f")}),
+			new InferenceRule(
+				".sh~",
+				new Command[] {
+					new Command("$(GET) $(GFLAGS) -p $< > $*.sh"),
+					new Command("cp $*.sh $@"),
+					new Command("chmod a+x $@")}),
+
+		// DOUBLE SUFFIX RULES
+
+		new InferenceRule(".c.o", new Command[] { new Command("$(CC) $(CFLAGS) -c $<")}),
+			new InferenceRule(".f.o", new Command[] { new Command("$(FC) $(FFLAGS) -c $<")}),
+			new InferenceRule(
+				".y.o",
+				new Command[] {
+					new Command("$(YACC) $(YFLAGS) $<"),
+					new Command("$(CC) $(CFLAGS) -c y.tab.c"),
+					new Command("rm -f y.tab.c"),
+					new Command("mv y.tab.o $@")}),
+			new InferenceRule(
+				".l.o",
+				new Command[] {
+					new Command("$(LEX) $(LFLAGS) $<"),
+					new Command("$(CC) $(CFLAGS) -c lex.yy.c"),
+					new Command("rm -f lex.yy.c"),
+					new Command("mv lex.yy.o $@"),
+					}),
+			new InferenceRule(".y.c", new Command[] { new Command("$(YACC) $(YFLAGS) $<"), new Command("mv y.tab.c $@")}),
+			new InferenceRule(".l.c", new Command[] { new Command("$(LEX) $(LFLAGS) $<"), new Command("mv lex.yy.c $@")}),
+			new InferenceRule(
+				".c~.o",
+				new Command[] { new Command("$(GET) $(GFLAGS) -p $< > $*.c"), new Command("$(CC) $(CFLAGS) -c $*.c")}),
+			new InferenceRule(
+				".f~.o",
+				new Command[] { new Command("$(GET) $(GFLAGS) -p $< > $*.f"), new Command("$(FC) $(FFLAGS) -c $*.f")}),
+			new InferenceRule(
+				".y~.o",
+				new Command[] {
+					new Command("$(GET) $(GFLAGS) -p $< > $*.y"),
+					new Command("$(YACC) $(YFLAGS) $*.y"),
+					new Command("$(CC) $(CFLAGS) -c y.tab.c"),
+					new Command("rm -f y.tab.c"),
+					new Command("mv y.tab.o $@")}),
+			new InferenceRule(
+				".l~.o",
+				new Command[] {
+					new Command("$(GET) $(GFLAGS) -p $< > $*.l"),
+					new Command("$(LEX) $(LFLAGS) $*.l"),
+					new Command("$(CC) $(CFLAGS) -c lex.yy.c"),
+					new Command("rm -f lex.yy.c"),
+					new Command("mv lex.yy.o $@")}),
+			new InferenceRule(
+				".y~.c",
+				new Command[] {
+					new Command("$(GET) $(GFLAGS) -p $< > $*.y"),
+					new Command("$(YACC) $(YFLAGS) $*.y"),
+					new Command("mv y.tab.c $@")}),
+			new InferenceRule(
+				".l~.c",
+				new Command[] {
+					new Command("$(GET) $(GFLAGS) -p $< > $*.l"),
+					new Command("$(LEX) $(LFLAGS) $*.l"),
+					new Command("mv lex.yy.c $@")}),
+			new InferenceRule(
+				".c.a",
+				new Command[] {
+					new Command("$(CC) -c $(CFLAGS) $<"),
+					new Command("$(AR) $(ARFLAGS) $@ $*.o"),
+					new Command("rm -f $*.o")}),
+			new InferenceRule(
+				".f.a",
+				new Command[] {
+					new Command("$(FC) -c $(FFLAGS) $<"),
+					new Command("$(AR) $(ARFLAGS) $@ $*.o"),
+					new Command("rm -f $*.o")})
+		};
+
+	InferenceRule getInferenceRule(String name) {
+		for (int i = 0; i < rules.length; i++) {
+			if (name.equals(rules[i].getTarget())) {
+				return rules[i];
+			}
+		}
+		return null;
+	}
+
+	InferenceRule[] getInferenceRules() {
+		return rules;
+	}
+}
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixMakefile.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixMakefile.java
new file mode 100644
index 00000000000..e7f8c84cd71
--- /dev/null
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixMakefile.java
@@ -0,0 +1,153 @@
+/**********************************************************************
+ * 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.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.make.internal.core.makefile.AbstractMakefile;
+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.EmptyLine;
+import org.eclipse.cdt.make.internal.core.makefile.InferenceRule;
+import org.eclipse.cdt.make.internal.core.makefile.Rule;
+import org.eclipse.cdt.make.internal.core.makefile.Statement;
+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.MacroDefinition;
+
+/**
+ * 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 PosixMakefile extends AbstractMakefile {
+
+	List statements;
+
+	public PosixMakefile(String name) throws IOException {
+		this(new BufferedReader(new FileReader(name)));
+	}
+
+	public PosixMakefile(BufferedReader reader) throws IOException {
+		super();
+		statements = new ArrayList();
+		parse(reader);
+	}
+
+	void parse(BufferedReader br) throws IOException {
+		String line;
+		Rule rule = null;
+		while ((line = Util.readLine(br)) != null) {
+			if (line.length() == 0) {
+				// Empty Line.
+				statements.add(new EmptyLine());
+			} else if (line.startsWith("#")) {
+				// Comment.
+				statements.add(new Comment(line));
+			} else if (line.startsWith("\t")) {
+				// Command.
+				Command cmd = new Command(line);
+				if (rule != null) {
+					rule.addCommand(cmd);
+				} else {
+					throw new IOException("Error Parsing");
+				}
+			} else if (line.startsWith(".")) {
+				// Inference Rule
+				String tgt;
+				int index = Util.indexOf(line, ':');
+				if (index != -1) {
+					tgt = line.substring(0, index);
+				} else {
+					tgt = line;
+				}
+				rule = new InferenceRule(tgt);
+				statements.add(rule);
+			} else {
+				char[] array = line.toCharArray();
+				if (Util.isMacroDefinition(array)) {
+					// MacroDefinition
+					statements.add(new MacroDefinition(line));
+				} else if (Util.isRule(array)) {
+					String[] targets;
+					String[] reqs = new String[0];
+					String cmd = null;
+					int index = Util.indexOf(array, ':');
+					if (index != -1) {
+						String target = line.substring(0, index);
+						// Break the targets
+						targets = Util.findTargets(target.trim());
+
+						String req = line.substring(index + 1);
+						int semicolon = Util.indexOf(req, ';');
+						if (semicolon != -1) {
+							cmd = req.substring(semicolon + 1);
+							req = req.substring(0, semicolon);
+						}
+						reqs = Util.findPrerequisites(req.trim());
+					} else {
+						targets = new String[] { line };
+					}
+
+					for (int i = 0; i < targets.length; i++) {
+						rule = new TargetRule(targets[i], reqs);
+						statements.add(rule);
+						if (cmd != null) {
+							rule.addCommand(new Command(cmd));
+						}
+					}
+				} else {
+				}
+			}
+		}
+	}
+
+	public Statement[] getStatements() {
+		return (Statement[]) statements.toArray(new Statement[0]);
+	}
+
+	public void addStatement(Statement stmt) {
+		statements.add(stmt);
+	}
+
+	public static void main(String[] args) {
+		try {
+			String filename = "Makefile";
+			if (args.length == 1) {
+				filename = args[0];
+			}
+			PosixMakefile makefile = new PosixMakefile(filename);
+			Statement[] 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);
+		}
+	}
+
+}