diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/java/org/anarres/cpp/Feature.java | 7 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/FileLexerSource.java | 5 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/LexerSource.java | 22 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/Main.java | 40 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/Preprocessor.java | 93 | ||||
-rw-r--r-- | src/tests/org/anarres/cpp/CppReaderTestCase.java | 2 | ||||
-rw-r--r-- | src/tests/org/anarres/cpp/LexerSourceTestCase.java | 32 | ||||
-rw-r--r-- | src/tests/org/anarres/cpp/MainTestCase.java | 15 |
8 files changed, 167 insertions, 49 deletions
diff --git a/src/java/org/anarres/cpp/Feature.java b/src/java/org/anarres/cpp/Feature.java new file mode 100644 index 0000000..a27df59 --- /dev/null +++ b/src/java/org/anarres/cpp/Feature.java @@ -0,0 +1,7 @@ +package org.anarres.cpp; + +public enum Feature { + DIGRAPHS, + TRIGRAPHS, + LINEMARKERS, +} diff --git a/src/java/org/anarres/cpp/FileLexerSource.java b/src/java/org/anarres/cpp/FileLexerSource.java index 9f574a0..3cf8604 100644 --- a/src/java/org/anarres/cpp/FileLexerSource.java +++ b/src/java/org/anarres/cpp/FileLexerSource.java @@ -58,6 +58,11 @@ public class FileLexerSource extends LexerSource { this.file = file; } + public FileLexerSource(String path) + throws IOException { + this(new File(path)); + } + @Override /* pp */ File getFile() { return file; diff --git a/src/java/org/anarres/cpp/LexerSource.java b/src/java/org/anarres/cpp/LexerSource.java index 51b5c07..8561c04 100644 --- a/src/java/org/anarres/cpp/LexerSource.java +++ b/src/java/org/anarres/cpp/LexerSource.java @@ -479,7 +479,7 @@ public class LexerSource extends Source { int _c = column; int c = read(); - int d, e; + int d; switch (c) { case '\n': @@ -561,9 +561,23 @@ public class LexerSource extends Source { tok = new Token(MOD_EQ); else if (d == '>') tok = new Token('}'); // digraph - else if (d == ':') - tok = new Token('#'); // digraph - else // XXX Deal with %:%: -> ## + else if (d == ':') PASTE: { + d = read(); + if (d != '%') { + unread(d); + tok = new Token('#'); // digraph + break PASTE; + } + d = read(); + if (d != ':') { + unread(d); + unread('%'); + tok = new Token('#'); // digraph + break PASTE; + } + tok = new Token(PASTE); // digraph + } + else unread(d); break; diff --git a/src/java/org/anarres/cpp/Main.java b/src/java/org/anarres/cpp/Main.java index cf61ecd..c2a4dfb 100644 --- a/src/java/org/anarres/cpp/Main.java +++ b/src/java/org/anarres/cpp/Main.java @@ -69,6 +69,8 @@ public class Main { "Defines the given macro."), new Option("undefine", LongOpt.REQUIRED_ARGUMENT, 'U', "name", "Undefines the given macro, previously either builtin or defined using -D."), + new Option("include", LongOpt.REQUIRED_ARGUMENT, 'i', "file", + "Process file as if \"#" + "include \"file\"\" appeared as the first line of the primary source file."), new Option("incdir", LongOpt.REQUIRED_ARGUMENT, 'I', "dir", "Adds the directory dir to the list of directories to be searched for header files."), new Option("warning", LongOpt.REQUIRED_ARGUMENT, 'W', "type", @@ -101,7 +103,6 @@ public class Main { i_quote = new ArrayList<String>(); d_default = new HashMap<String,String>(); d_user = new HashMap<String,String>(); - warnings = EnumSet.noneOf(Warning.class); } public void run(Option[] opts, String[] args) throws Exception { @@ -111,6 +112,9 @@ public class Main { String arg; int idx; + Preprocessor pp = new Preprocessor(); + pp.addFeature(Feature.LINEMARKERS); + GETOPT: while ((c = g.getopt()) != -1) { switch (c) { case 'D': @@ -133,38 +137,33 @@ public class Main { arg = g.getOptarg().toUpperCase(); arg = arg.replace('-', '_'); if (arg.equals("all")) - warnings = EnumSet.allOf(Warning.class); + pp.addWarnings(EnumSet.allOf(Warning.class)); else - warnings.add(Enum.valueOf(Warning.class, arg)); + pp.addWarning(Enum.valueOf(Warning.class, arg)); break; case 'w': - warnings = EnumSet.noneOf(Warning.class); + pp.getWarnings().clear(); + break; + case 'i': + // pp.addInput(new File(g.getOptarg())); + // Comply exactly with spec. + pp.addInput(new StringLexerSource( + "#" + "include \"" + g.getOptarg() + "\"\n" + )); break; case 'V': System.out.println("Anarres Java C Preprocessor version " + Version.getVersion()); - System.exit(0); - throw new Exception("Exited"); + return; case 'h': usage(getClass().getName(), opts); - System.exit(1); - throw new Exception("Exited"); + return; default: case '?': throw new Exception("Illegal option " + c); } } - File file = new File(args[g.getOptind()]); - Source source = new FileLexerSource(file); - Preprocessor pp = new Preprocessor(source); - - /* XXX Warnings, include-path, include-files. */ - - for (int i = g.getOptind() + 1; i < args.length; i++) { - /* XXX Wrong, needs to concat them not push them. */ - /* XXX Reverse this list. */ - pp.addSource(new FileLexerSource(new File(args[i]))); - } + /* XXX include-path, include-files. */ for (Map.Entry<String,String> e : d_default.entrySet()) pp.addMacro(e.getKey(), e.getValue()); @@ -173,6 +172,9 @@ public class Main { /* XXX Include paths. */ + for (int i = g.getOptind(); i < args.length; i++) + pp.addInput(new FileLexerSource(new File(args[i]))); + try { for (;;) { Token tok = pp.token(); diff --git a/src/java/org/anarres/cpp/Preprocessor.java b/src/java/org/anarres/cpp/Preprocessor.java index 17d6c04..63304b0 100644 --- a/src/java/org/anarres/cpp/Preprocessor.java +++ b/src/java/org/anarres/cpp/Preprocessor.java @@ -22,13 +22,16 @@ package org.anarres.cpp; import java.io.File; import java.io.IOException; -import java.util.Arrays; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.Collections; +import java.util.EnumSet; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.Stack; import static org.anarres.cpp.Token.*; @@ -44,8 +47,6 @@ import static org.anarres.cpp.Token.*; public class Preprocessor { private static final boolean DEBUG = false; - public static final int FL_LINEMARKER = 1; - private static final Macro __LINE__ = new Macro("__LINE__"); private static final Macro __FILE__ = new Macro("__FILE__"); @@ -54,11 +55,11 @@ public class Preprocessor { private Source source; private List<String> path; + private Set<Feature> features; + private Set<Warning> warnings; private PreprocessorListener listener; - private int flags; - - public Preprocessor(Source initial, int flags) { + public Preprocessor() { this.macros = new HashMap<String,Macro>(); macros.put(__LINE__.getName(), __LINE__); macros.put(__FILE__.getName(), __FILE__); @@ -66,17 +67,16 @@ public class Preprocessor { states.push(new State()); this.source = null; this.path = null; + this.features = EnumSet.noneOf(Feature.class); + features.add(Feature.DIGRAPHS); + features.add(Feature.TRIGRAPHS); + this.warnings = EnumSet.noneOf(Warning.class); setListener(new PreprocessorListener()); - setFlags(flags); - - push_source(initial, false); - /* We need to get a \n onto the end of this somehow. */ - if ((flags & FL_LINEMARKER) != 0) - source_untoken(line_token(1, source.getName(), "\n")); } public Preprocessor(Source initial) { - this(initial, 0); + this(); + addInput(initial); } /** Equivalent to @@ -84,7 +84,7 @@ public class Preprocessor { */ public Preprocessor(File file) throws IOException { - this(new FileLexerSource(file), 0); + this(new FileLexerSource(file)); } public void setListener(PreprocessorListener listener) { @@ -96,10 +96,54 @@ public class Preprocessor { } } - public void setFlags(int flags) { - this.flags = flags; + public Set<Feature> getFeatures() { + return features; + } + + public void addFeature(Feature f) { + features.add(f); + } + + public void addFeatures(Collection<Feature> f) { + features.addAll(f); + } + + public Set<Warning> getWarnings() { + return warnings; + } + + public void addWarning(Warning w) { + warnings.add(w); + } + + public void addWarnings(Collection<Warning> w) { + warnings.addAll(w); + } + + public void addInput(Source source) { + if (this.source == null) { + this.source = source; + /* We need to get a \n onto the end of this somehow. */ + if (features.contains(Feature.LINEMARKERS)) + source_untoken(line_token(1, source.getName(), "\n")); + } + else { + Source s = this.source; + Source p = source.getParent(); + while (p != null) { + s = p; + p = s.getParent(); + } + s.setParent(source, true); + } + } + + public void addInput(File file) + throws IOException { + addInput(new FileLexerSource(file)); } + /** * Handles an error. * @@ -249,6 +293,8 @@ public class Preprocessor { protected void push_source(Source source, boolean autopop) { source.setParent(this.source, autopop); source.setListener(listener); + if (listener != null) + listener.handleSourceChange(this.source, "suspend"); this.source = source; if (listener != null) listener.handleSourceChange(this.source, "push"); @@ -261,9 +307,11 @@ public class Preprocessor { * @see #push_source(Source,boolean) */ protected void pop_source() { - this.source = this.source.getParent(); if (listener != null) listener.handleSourceChange(this.source, "pop"); + this.source = this.source.getParent(); + if (listener != null && this.source != null) + listener.handleSourceChange(this.source, "resume"); } /** @@ -295,12 +343,15 @@ public class Preprocessor { } for (;;) { + if (source == null) + return new Token(EOF); Token tok = source.token(); if (tok.getType() == EOF && source.isAutopop()) { // System.out.println("Autopop " + source); Source s = source; pop_source(); - if ((flags & FL_LINEMARKER) != 0 && s.isNumbered()) { + if (features.contains(Feature.LINEMARKERS) + && s.isNumbered()) { /* Not perfect, but ... */ source_untoken(new Token(NL, source.getLine(), 0, "\n")); return line_token(source.getLine(), source.getName(), ""); @@ -490,6 +541,8 @@ public class Preprocessor { else if (m == __FILE__) { StringBuilder buf = new StringBuilder("\""); String name = source.getName(); + if (name == null) + name = "<no file>"; for (int i = 0; i < name.length(); i++) { char c = name.charAt(i); switch (c) { @@ -846,7 +899,7 @@ public class Preprocessor { /* 'tok' is the 'nl' after the include. We use it after the * #line directive. */ - if ((flags & FL_LINEMARKER) != 0) { + if (features.contains(Feature.LINEMARKERS)) { source_untoken(tok); return line_token(1, name, ""); } @@ -1332,7 +1385,7 @@ public class Preprocessor { return tok; case P_LINE: - if ((flags & FL_LINEMARKER) != 0) + if (features.contains(Feature.LINEMARKERS)) return tok; break; diff --git a/src/tests/org/anarres/cpp/CppReaderTestCase.java b/src/tests/org/anarres/cpp/CppReaderTestCase.java index 5aeee06..6097436 100644 --- a/src/tests/org/anarres/cpp/CppReaderTestCase.java +++ b/src/tests/org/anarres/cpp/CppReaderTestCase.java @@ -17,7 +17,7 @@ public class CppReaderTestCase extends BaseTestCase implements Test { p.getPreprocessor().setIncludePath( Collections.singletonList("src/input") ); - p.getPreprocessor().setFlags(Preprocessor.FL_LINEMARKER); + p.getPreprocessor().getFeatures().add(Feature.LINEMARKERS); BufferedReader b = new BufferedReader(p); String line; diff --git a/src/tests/org/anarres/cpp/LexerSourceTestCase.java b/src/tests/org/anarres/cpp/LexerSourceTestCase.java index e8fb410..2d61e28 100644 --- a/src/tests/org/anarres/cpp/LexerSourceTestCase.java +++ b/src/tests/org/anarres/cpp/LexerSourceTestCase.java @@ -12,7 +12,7 @@ import static org.anarres.cpp.Token.*; public class LexerSourceTestCase extends BaseTestCase implements Test { - private void testLexerSource(String in, int[] out) + private void testLexerSource(String in, int... out) throws Exception { System.out.println("Testing '" + in + "' => " + Arrays.toString(out)); @@ -29,14 +29,36 @@ public class LexerSourceTestCase extends BaseTestCase implements Test { public void testJoinReader() throws Exception { - testLexerSource("int a = 5;", new int[] { + testLexerSource("int a = 5;", IDENTIFIER, WHITESPACE, IDENTIFIER, WHITESPACE, '=', WHITESPACE, INTEGER, ';', EOF - }); + ); - testLexerSource("# # foo", new int[] { + // \n is WHITESPACE because ppvalid = false + testLexerSource("# # \r\n\n\r \rfoo", HASH, WHITESPACE, '#', WHITESPACE, IDENTIFIER - }); + ); + + testLexerSource("%:%:", PASTE); + testLexerSource("%:?", '#', '?'); + testLexerSource("%:%=", '#', MOD_EQ); + testLexerSource("0x1234ffdUL 0765I", + INTEGER, WHITESPACE, INTEGER); + + testLexerSource("+= -= *= /= %= <= >= >>= <<= &= |= ^= x", + PLUS_EQ, WHITESPACE, + SUB_EQ, WHITESPACE, + MULT_EQ, WHITESPACE, + DIV_EQ, WHITESPACE, + MOD_EQ, WHITESPACE, + LE, WHITESPACE, + GE, WHITESPACE, + RSH_EQ, WHITESPACE, + LSH_EQ, WHITESPACE, + AND_EQ, WHITESPACE, + OR_EQ, WHITESPACE, + XOR_EQ, WHITESPACE, + IDENTIFIER); } diff --git a/src/tests/org/anarres/cpp/MainTestCase.java b/src/tests/org/anarres/cpp/MainTestCase.java new file mode 100644 index 0000000..a42f3d2 --- /dev/null +++ b/src/tests/org/anarres/cpp/MainTestCase.java @@ -0,0 +1,15 @@ +package org.anarres.cpp; + +import java.io.*; + +import junit.framework.Test; + +import static org.anarres.cpp.Token.*; + +public class MainTestCase extends BaseTestCase { + + public void testMain() throws Exception { + Main.main(new String[] { "-V" }); + } + +} |