summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/java/org/anarres/cpp/Feature.java7
-rw-r--r--src/java/org/anarres/cpp/FileLexerSource.java5
-rw-r--r--src/java/org/anarres/cpp/LexerSource.java22
-rw-r--r--src/java/org/anarres/cpp/Main.java40
-rw-r--r--src/java/org/anarres/cpp/Preprocessor.java93
-rw-r--r--src/tests/org/anarres/cpp/CppReaderTestCase.java2
-rw-r--r--src/tests/org/anarres/cpp/LexerSourceTestCase.java32
-rw-r--r--src/tests/org/anarres/cpp/MainTestCase.java15
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" });
+ }
+
+}