diff options
-rw-r--r-- | build.xml | 27 | ||||
-rw-r--r-- | etc/build.properties | 2 | ||||
-rw-r--r-- | etc/targets/global-jar.xml | 3 | ||||
-rw-r--r-- | src/input/test0.c | 2 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/CppTask.java | 155 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/Main.java | 262 | ||||
-rw-r--r-- | src/resources/org/anarres/cpp/taskdef.properties | 2 |
7 files changed, 299 insertions, 154 deletions
@@ -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] - * <--indent-> in[1] - * <--indent-> in[2] - * <-----width----> - * </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] + * <--indent-> in[1] + * <--indent-> in[2] + * <-----width----> + * </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 |