summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build.xml27
-rw-r--r--etc/build.properties2
-rw-r--r--etc/targets/global-jar.xml3
-rw-r--r--src/input/test0.c2
-rw-r--r--src/java/org/anarres/cpp/CppTask.java155
-rw-r--r--src/java/org/anarres/cpp/Main.java262
-rw-r--r--src/resources/org/anarres/cpp/taskdef.properties2
7 files changed, 299 insertions, 154 deletions
diff --git a/build.xml b/build.xml
index 728c55e..4657aa1 100644
--- a/build.xml
+++ b/build.xml
@@ -16,4 +16,31 @@
<target name="findbugs" depends="global-findbugs,global-findbugs-gui" />
+ <target name="test-ant">
+ <delete dir="${global.dir.build}/output" />
+ <mkdir dir="${global.dir.build}/output" />
+
+ <path id="cpp-classpath">
+ <path refid="runtime-classpath" />
+ <pathelement path="${global.dir.src.resources}" />
+ </path>
+
+ <taskdef
+ resource="org/anarres/cpp/taskdef.properties"
+ classpathref="cpp-classpath"
+ loaderref="ant" />
+
+ <cpp todir="${global.dir.build}/output">
+ <fileset file="${global.dir.src}/input/test0.c" />
+ <fileset file="${global.dir.src}/input/test1.c" />
+ <systemincludepath>
+ <pathelement path="${global.dir.src}/input" />
+ </systemincludepath>
+ <localincludepath>
+ <pathelement path="${global.dir.src}/input" />
+ </localincludepath>
+ </cpp>
+ </target>
+
+
</project>
diff --git a/etc/build.properties b/etc/build.properties
index 06251b6..a07cd9c 100644
--- a/etc/build.properties
+++ b/etc/build.properties
@@ -1,4 +1,4 @@
-global.version = 1.2.7
+global.version = 1.2.8
global.name = anarres-cpp
global.dir.arch = ${global.dir.root}/arch
diff --git a/etc/targets/global-jar.xml b/etc/targets/global-jar.xml
index 045e85a..c84dd2a 100644
--- a/etc/targets/global-jar.xml
+++ b/etc/targets/global-jar.xml
@@ -15,6 +15,9 @@
<fileset dir="${global.dir.build.classes}">
<include name="**" />
</fileset>
+ <fileset dir="${global.dir.src.resources}">
+ <include name="org/**" />
+ </fileset>
<!--
<fileset dir="${global.dir.src.resources}">
<include name="log4j.properties" />
diff --git a/src/input/test0.c b/src/input/test0.c
index 150b759..7e91637 100644
--- a/src/input/test0.c
+++ b/src/input/test0.c
@@ -55,7 +55,7 @@ one /* one */
#define foo(x) foo(x, b)
foo(1) -> _foo(1, b) without the _
foo(foo(2)) -> _foo(_foo(2, b), b) without the _
-foo(y, z)
+// foo(y, z)
#define var(x...) a x b
var(e, f, g) -> a e, f, g b
diff --git a/src/java/org/anarres/cpp/CppTask.java b/src/java/org/anarres/cpp/CppTask.java
index f86c2d1..05fc1f9 100644
--- a/src/java/org/anarres/cpp/CppTask.java
+++ b/src/java/org/anarres/cpp/CppTask.java
@@ -20,20 +20,37 @@ package org.anarres.cpp;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.Copy;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.FilterChain;
+import org.apache.tools.ant.types.FilterSet;
+import org.apache.tools.ant.types.FilterSetCollection;
+import org.apache.tools.ant.types.Path;
import org.anarres.cpp.LexerException;
import org.anarres.cpp.Preprocessor;
+import org.anarres.cpp.PreprocessorListener;
import org.anarres.cpp.Token;
/**
* An ant task for jcpp.
*/
-public class CppTask extends Task {
+public class CppTask extends Copy {
- private static class Macro {
+ private class Listener extends PreprocessorListener {
+ protected void print(String msg) {
+ log(msg);
+ }
+ }
+
+ public static class Macro {
private String name;
private String value;
@@ -54,32 +71,28 @@ public class CppTask extends Task {
}
}
- private File input;
- private File output;
- private Preprocessor cpp;
+ private final Listener listener = new Listener();
+ private final List<Macro> macros = new ArrayList<Macro>();
+ private Path systemincludepath;
+ private Path localincludepath;
- public CppTask() {
- super();
- cpp = new Preprocessor();
+ public void addMacro(Macro macro) {
+ macros.add(macro);
}
- public void setInput(File input) {
- this.input = input;
+ public void addSystemincludepath(Path path) {
+ if (systemincludepath == null)
+ systemincludepath = new Path(getProject());
+ systemincludepath.add(path);
}
- public void setOutput(File output) {
- this.output = output;
- }
-
- public void addMacro(Macro macro) {
- try {
- cpp.addMacro(macro.getName(), macro.getValue());
- }
- catch (LexerException e) {
- throw new BuildException(e);
- }
+ public void addLocalincludepath(Path path) {
+ if (localincludepath == null)
+ localincludepath = new Path(getProject());
+ localincludepath.add(path);
}
+/*
public void execute() {
FileWriter writer = null;
try {
@@ -109,5 +122,105 @@ public class CppTask extends Task {
}
}
}
+*/
+
+ private void preprocess(File input, File output) throws Exception {
+ Preprocessor cpp = new Preprocessor();
+ cpp.setListener(listener);
+ for (Macro macro : macros)
+ cpp.addMacro(macro.getName(), macro.getValue());
+ if (systemincludepath != null)
+ cpp.setSystemIncludePath(Arrays.asList(systemincludepath.list()));
+ if (localincludepath != null)
+ cpp.setQuoteIncludePath(Arrays.asList(localincludepath.list()));
+
+ File dir = output.getParentFile();
+ if (!dir.exists()) {
+ if (!dir.mkdirs())
+ throw new BuildException("Failed to make parent directory " + dir);
+ } else if (!dir.isDirectory()) {
+ throw new BuildException("Parent directory of output file " + output + " exists, but is not a directory.");
+ }
+ FileWriter writer = null;
+ try {
+ if (input == null)
+ throw new BuildException("Input not specified");
+ if (output == null)
+ throw new BuildException("Output not specified");
+ cpp.addInput(input);
+ writer = new FileWriter(output);
+ for (;;) {
+ Token tok = cpp.token();
+ if (tok != null && tok.getType() == Token.EOF)
+ break;
+ writer.write(tok.getText());
+ }
+ }
+ finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ }
+ catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ protected void doFileOperations() {
+ if(fileCopyMap.size() > 0) {
+ log("Copying " + fileCopyMap.size()
+ + " file" + (fileCopyMap.size() == 1 ? "" : "s")
+ + " to " + destDir.getAbsolutePath());
+
+ Enumeration e = fileCopyMap.keys();
+
+ while (e.hasMoreElements()) {
+ String fromFile = (String)e.nextElement();
+ String[] toFiles = (String[])fileCopyMap.get(fromFile);
+
+ for(int i = 0; i < toFiles.length; i++) {
+ String toFile = toFiles[i];
+
+ if(fromFile.equals(toFile)) {
+ log("Skipping self-copy of " + fromFile, verbosity);
+ continue;
+ }
+
+ try {
+ log("Copying " + fromFile + " to " + toFile, verbosity);
+
+ FilterSetCollection executionFilters =
+ new FilterSetCollection();
+ if(filtering) {
+ executionFilters
+ .addFilterSet(getProject().getGlobalFilterSet());
+ }
+ for(Enumeration filterEnum = getFilterSets().elements();
+ filterEnum.hasMoreElements();) {
+ executionFilters
+ .addFilterSet((FilterSet)filterEnum.nextElement());
+ }
+
+ File srcFile = new File(fromFile);
+ File dstFile = new File(toFile);
+ preprocess(srcFile, dstFile);
+ }
+ catch(Exception ioe) {
+ ioe.printStackTrace();
+ String msg = "Failed to copy " + fromFile + " to " + toFile
+ + " due to " + ioe.getMessage();
+ File targetFile = new File(toFile);
+ if(targetFile.exists() && !targetFile.delete()) {
+ msg += " and I couldn't delete the corrupt " + toFile;
+ }
+ throw new BuildException(msg, ioe, getLocation());
+ }
+ }
+ }
+ }
+
+ }
+
}
diff --git a/src/java/org/anarres/cpp/Main.java b/src/java/org/anarres/cpp/Main.java
index 00f47f0..da9d3d6 100644
--- a/src/java/org/anarres/cpp/Main.java
+++ b/src/java/org/anarres/cpp/Main.java
@@ -41,16 +41,16 @@ import static org.anarres.cpp.Token.*;
*/
public class Main {
- private static class Option extends LongOpt {
- private String eg;
- private String help;
- public Option(String word, int arg, int ch,
- String eg, String help) {
- super(word, arg, null, ch);
- this.eg = eg;
- this.help = help;
- }
- }
+ private static class Option extends LongOpt {
+ private String eg;
+ private String help;
+ public Option(String word, int arg, int ch,
+ String eg, String help) {
+ super(word, arg, null, ch);
+ this.eg = eg;
+ this.help = help;
+ }
+ }
private static final Option[] OPTS = new Option[] {
new Option("help", LongOpt.NO_ARGUMENT, 'h', null,
@@ -94,8 +94,8 @@ public class Main {
public void run(String[] args) throws Exception {
Option[]opts = OPTS;
- String sopts = getShortOpts(opts);
- Getopt g = new Getopt("jcpp", args, sopts, opts);
+ String sopts = getShortOpts(opts);
+ Getopt g = new Getopt("jcpp", args, sopts, opts);
int c;
String arg;
int idx;
@@ -113,8 +113,8 @@ public class Main {
pp.getFrameworksPath().add("/Library/Frameworks");
pp.getFrameworksPath().add("/Local/Library/Frameworks");
- GETOPT: while ((c = g.getopt()) != -1) {
- switch (c) {
+ GETOPT: while ((c = g.getopt()) != -1) {
+ switch (c) {
case 'D':
arg = g.getOptarg();
idx = arg.indexOf('=');
@@ -141,7 +141,7 @@ public class Main {
else
pp.addWarning(Enum.valueOf(Warning.class, arg));
break;
- case 'w':
+ case 'w':
pp.getWarnings().clear();
break;
case 1: // --include=
@@ -160,12 +160,12 @@ public class Main {
case 3:
pp.addFeature(Feature.DEBUG);
break;
- case 'h':
- usage(getClass().getName(), opts);
+ case 'h':
+ usage(getClass().getName(), opts);
return;
- default:
- throw new Exception("Illegal option " + (char)c);
- case '?':
+ default:
+ throw new Exception("Illegal option " + (char)c);
+ case '?':
continue; /* Make failure-proof. */
}
}
@@ -214,123 +214,123 @@ public class Main {
}
- private static String getShortOpts(Option[] opts)
- throws Exception {
- StringBuilder buf = new StringBuilder();
- for (int i = 0; i < opts.length; i++) {
- char c = (char)opts[i].getVal();
+ private static String getShortOpts(Option[] opts)
+ throws Exception {
+ StringBuilder buf = new StringBuilder();
+ for (int i = 0; i < opts.length; i++) {
+ char c = (char)opts[i].getVal();
if (!Character.isLetterOrDigit(c))
continue;
- for (int j = 0; j < buf.length(); j++)
- if (buf.charAt(j) == c)
- throw new Exception(
- "Duplicate short option " + c
- );
- buf.append(c);
- switch (opts[i].getHasArg()) {
- case LongOpt.NO_ARGUMENT:
- break;
- case LongOpt.OPTIONAL_ARGUMENT:
- buf.append("::");
- break;
- case LongOpt.REQUIRED_ARGUMENT:
- buf.append(":");
- break;
- }
- }
- return buf.toString();
- }
-
- /* This is incomplete but nearly there. */
- /**
- * Wraps a string.
- *
- * The output form is:
- * <pre>
- * prefix in[0]
- * &lt;--indent-&gt; in[1]
- * &lt;--indent-&gt; in[2]
- * &lt;-----width----&gt;
- * </pre>
- */
- /* XXX There's some of this in commons. */
- private static String wrap(String in, String prefix,
- int indent, int width) {
- StringBuilder buf = new StringBuilder(prefix);
-
- while (buf.length() < indent)
- buf.append(' ');
-
- int start = 0;
-
- while (start < in.length()) {
- while (start < in.length() &&
- Character.isWhitespace(in.charAt(start)))
- start++;
-
- int end = start + width - indent;
-
- if (end > in.length()) {
- buf.append(in.substring(start));
- break;
- }
-
- int idx = end;
- while (!Character.isWhitespace(in.charAt(idx)))
- idx--;
-
- if (idx == start) {
- idx = end - 1;
- buf.append(in.substring(start, idx));
- buf.append('-');
- }
- else {
- buf.append(in.substring(start, idx));
- start = idx;
- }
-
- start = idx;
- }
-
- return buf.toString();
+ for (int j = 0; j < buf.length(); j++)
+ if (buf.charAt(j) == c)
+ throw new Exception(
+ "Duplicate short option " + c
+ );
+ buf.append(c);
+ switch (opts[i].getHasArg()) {
+ case LongOpt.NO_ARGUMENT:
+ break;
+ case LongOpt.OPTIONAL_ARGUMENT:
+ buf.append("::");
+ break;
+ case LongOpt.REQUIRED_ARGUMENT:
+ buf.append(":");
+ break;
+ }
+ }
+ return buf.toString();
+ }
+
+ /* This is incomplete but nearly there. */
+ /**
+ * Wraps a string.
+ *
+ * The output form is:
+ * <pre>
+ * prefix in[0]
+ * &lt;--indent-&gt; in[1]
+ * &lt;--indent-&gt; in[2]
+ * &lt;-----width----&gt;
+ * </pre>
+ */
+ /* XXX There's some of this in commons. */
+ private static String wrap(String in, String prefix,
+ int indent, int width) {
+ StringBuilder buf = new StringBuilder(prefix);
+
+ while (buf.length() < indent)
+ buf.append(' ');
+
+ int start = 0;
+
+ while (start < in.length()) {
+ while (start < in.length() &&
+ Character.isWhitespace(in.charAt(start)))
+ start++;
+
+ int end = start + width - indent;
+
+ if (end > in.length()) {
+ buf.append(in.substring(start));
+ break;
+ }
+
+ int idx = end;
+ while (!Character.isWhitespace(in.charAt(idx)))
+ idx--;
+
+ if (idx == start) {
+ idx = end - 1;
+ buf.append(in.substring(start, idx));
+ buf.append('-');
+ }
+ else {
+ buf.append(in.substring(start, idx));
+ start = idx;
+ }
+
+ start = idx;
+ }
+
+ return buf.toString();
}
- private static void usage(String command, Option[] options) {
- StringBuilder text = new StringBuilder("Usage: ");
- text.append(command).append('\n');
- for (int i = 0; i < options.length; i++) {
- StringBuilder line = new StringBuilder();
- Option opt = options[i];
- line.append(" --").append(opt.getName());
- switch (opt.getHasArg()) {
- case LongOpt.NO_ARGUMENT:
- break;
- case LongOpt.OPTIONAL_ARGUMENT:
- line.append("[=").append(opt.eg).append(']');
- break;
- case LongOpt.REQUIRED_ARGUMENT:
- line.append('=').append(opt.eg);
- break;
- }
+ private static void usage(String command, Option[] options) {
+ StringBuilder text = new StringBuilder("Usage: ");
+ text.append(command).append('\n');
+ for (int i = 0; i < options.length; i++) {
+ StringBuilder line = new StringBuilder();
+ Option opt = options[i];
+ line.append(" --").append(opt.getName());
+ switch (opt.getHasArg()) {
+ case LongOpt.NO_ARGUMENT:
+ break;
+ case LongOpt.OPTIONAL_ARGUMENT:
+ line.append("[=").append(opt.eg).append(']');
+ break;
+ case LongOpt.REQUIRED_ARGUMENT:
+ line.append('=').append(opt.eg);
+ break;
+ }
if (Character.isLetterOrDigit(opt.getVal()))
line.append(" (-").append((char)opt.getVal()).append(")");
- if (line.length() < 30) {
- while (line.length() < 30)
- line.append(' ');
- }
- else {
- line.append('\n');
- for (int j = 0; j < 30; j++)
- line.append(' ');
- }
- /* This should use wrap. */
- line.append(opt.help);
- line.append('\n');
- text.append(line);
- }
-
- System.out.println(text);
- }
+ if (line.length() < 30) {
+ while (line.length() < 30)
+ line.append(' ');
+ }
+ else {
+ line.append('\n');
+ for (int j = 0; j < 30; j++)
+ line.append(' ');
+ }
+ /* This should use wrap. */
+ line.append(opt.help);
+ line.append('\n');
+ text.append(line);
+ }
+
+ System.out.println(text);
+ }
diff --git a/src/resources/org/anarres/cpp/taskdef.properties b/src/resources/org/anarres/cpp/taskdef.properties
new file mode 100644
index 0000000..6d575d7
--- /dev/null
+++ b/src/resources/org/anarres/cpp/taskdef.properties
@@ -0,0 +1,2 @@
+# Taskdefs for JCPP
+cpp=org.anarres.cpp.CppTask