diff options
-rw-r--r-- | src/java/org/anarres/cpp/ChrootFileSystem.java | 1 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/CppReader.java | 9 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/Feature.java | 2 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/InputLexerSource.java | 68 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/JavaFileSystem.java | 8 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/LexerSource.java | 16 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/Main.java | 42 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/Preprocessor.java | 54 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/Source.java | 23 |
9 files changed, 185 insertions, 38 deletions
diff --git a/src/java/org/anarres/cpp/ChrootFileSystem.java b/src/java/org/anarres/cpp/ChrootFileSystem.java index f917c9e..bce2cfe 100644 --- a/src/java/org/anarres/cpp/ChrootFileSystem.java +++ b/src/java/org/anarres/cpp/ChrootFileSystem.java @@ -55,6 +55,7 @@ public class ChrootFileSystem implements VirtualFileSystem { super(dir, name); } + @Override public ChrootFile getParentFile() { return new ChrootFile(getParent()); } diff --git a/src/java/org/anarres/cpp/CppReader.java b/src/java/org/anarres/cpp/CppReader.java index a429fd4..fbe3545 100644 --- a/src/java/org/anarres/cpp/CppReader.java +++ b/src/java/org/anarres/cpp/CppReader.java @@ -110,6 +110,10 @@ public class CppReader extends Reader { return true; } catch (LexerException e) { + /* Never happens. + if (e.getCause() instanceof IOException) + throw (IOException)e.getCause(); + */ IOException ie = new IOException(String.valueOf(e)); ie.initCause(e); throw ie; @@ -139,7 +143,10 @@ public class CppReader extends Reader { public void close() throws IOException { - cpp = null; + if (cpp != null) { + cpp.close(); + cpp = null; + } token = null; } diff --git a/src/java/org/anarres/cpp/Feature.java b/src/java/org/anarres/cpp/Feature.java index 2f80245..935a94b 100644 --- a/src/java/org/anarres/cpp/Feature.java +++ b/src/java/org/anarres/cpp/Feature.java @@ -31,4 +31,6 @@ public enum Feature { CSYNTAX, /** Preserves comments in the lexed output. */ KEEPCOMMENTS, + VERBOSE, + DEBUG } diff --git a/src/java/org/anarres/cpp/InputLexerSource.java b/src/java/org/anarres/cpp/InputLexerSource.java new file mode 100644 index 0000000..0931dc4 --- /dev/null +++ b/src/java/org/anarres/cpp/InputLexerSource.java @@ -0,0 +1,68 @@ +/* + * Anarres C Preprocessor + * Copyright (c) 2007-2008, Shevek + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package org.anarres.cpp; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; + +import java.util.List; +import java.util.Iterator; + +import static org.anarres.cpp.Token.*; + +/** + * A {@link Source} which lexes a file. + * + * The input is buffered. + * + * @see Source + */ +public class InputLexerSource extends LexerSource { + /** + * Creates a new Source for lexing the given Reader. + * + * Preprocessor directives are honoured within the file. + */ + public InputLexerSource(InputStream input) + throws IOException { + super( + new BufferedReader( + new InputStreamReader( + input + ) + ), + true + ); + } + + @Override + /* pp */ String getPath() { + return "<standard-input>"; + } + + @Override + /* pp */ String getName() { + return "standard input"; + } + + public String toString() { + return getPath(); + } +} diff --git a/src/java/org/anarres/cpp/JavaFileSystem.java b/src/java/org/anarres/cpp/JavaFileSystem.java index 3b1b5ee..fab7721 100644 --- a/src/java/org/anarres/cpp/JavaFileSystem.java +++ b/src/java/org/anarres/cpp/JavaFileSystem.java @@ -46,6 +46,14 @@ public class JavaFileSystem implements VirtualFileSystem { super(dir, name); } +/* + @Override + public String getPath() { + return getCanonicalPath(); + } +*/ + + @Override public JavaFile getParentFile() { return new JavaFile(getParent()); } diff --git a/src/java/org/anarres/cpp/LexerSource.java b/src/java/org/anarres/cpp/LexerSource.java index 0eea1c3..22df78f 100644 --- a/src/java/org/anarres/cpp/LexerSource.java +++ b/src/java/org/anarres/cpp/LexerSource.java @@ -161,6 +161,9 @@ public class LexerSource extends Source { return u0; } + if (reader == null) + return -1; + int c = reader.read(); switch (c) { case '\r': @@ -208,6 +211,7 @@ public class LexerSource extends Source { /* You can unget AT MOST one newline. */ private void unread(int c) throws IOException { + /* XXX Must unread newlines. */ if (c != -1) { if (isLineSeparator(c)) { line--; @@ -583,8 +587,8 @@ public class LexerSource extends Source { else { int nls = 0; do { - d = read(); nls++; + d = read(); } while (d == '\n'); unread(d); char[] text = new char[nls]; @@ -767,6 +771,7 @@ public class LexerSource extends Source { break; case -1: + close(); tok = new Token(EOF, _l, _c, "<eof>"); break; } @@ -795,4 +800,13 @@ public class LexerSource extends Source { return tok; } + public void close() + throws IOException { + if (reader != null) { + reader.close(); + reader = null; + } + super.close(); + } + } diff --git a/src/java/org/anarres/cpp/Main.java b/src/java/org/anarres/cpp/Main.java index 0b97f4e..4fa17f1 100644 --- a/src/java/org/anarres/cpp/Main.java +++ b/src/java/org/anarres/cpp/Main.java @@ -19,6 +19,7 @@ package org.anarres.cpp; import java.io.File; import java.io.IOException; +import java.io.PrintStream; import java.util.ArrayList; import java.util.Collections; @@ -68,6 +69,10 @@ public class Main { "Enables the named warning class (" + getWarnings() + ")."), new Option("no-warnings", LongOpt.NO_ARGUMENT, 'w', null, "Disables ALL warnings."), + new Option("verbose", LongOpt.NO_ARGUMENT, 'v', null, + "Operates incredibly verbosely."), + new Option("debug", LongOpt.NO_ARGUMENT, 3, null, + "Operates incredibly verbosely."), new Option("version", LongOpt.NO_ARGUMENT, 2, null, "Prints jcpp's version number (" + Version.getVersion() + ")"), }; @@ -144,22 +149,38 @@ public class Main { )); break; case 2: // --version - System.out.println("Anarres Java C Preprocessor version " + Version.getVersion()); - System.out.println("Copyright (C) 2008 Shevek (http://www.anarres.org/)."); - System.out.println("This is free software; see the source for copying conditions. There is NO"); - System.out.println("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."); + version(System.out); return; + case 'v': + pp.addFeature(Feature.VERBOSE); + break; + case 3: + pp.addFeature(Feature.DEBUG); + break; case 'h': usage(getClass().getName(), opts); return; default: + throw new Exception("Illegal option " + (char)c); case '?': - throw new Exception("Illegal option " + c); + continue; /* Make failure-proof. */ } } for (int i = g.getOptind(); i < args.length; i++) pp.addInput(new FileLexerSource(new File(args[i]))); + if (g.getOptind() == args.length) + pp.addInput(new InputLexerSource(System.in)); + + if (pp.getFeature(Feature.VERBOSE)) { + System.err.println("#"+"include \"...\" search starts here:"); + for (String dir : pp.getQuoteIncludePath()) + System.err.println(" " + dir); + System.err.println("#"+"include <...> search starts here:"); + for (String dir : pp.getSystemIncludePath()) + System.err.println(" " + dir); + System.err.println("End of search list."); + } try { for (;;) { @@ -172,16 +193,23 @@ public class Main { } } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace(System.err); Source s = pp.getSource(); while (s != null) { - System.out.println(" -> " + s); + System.err.println(" -> " + s); s = s.getParent(); } } } + private void version(PrintStream out) { + out.println("Anarres Java C Preprocessor version " + Version.getVersion()); + out.println("Copyright (C) 2008 Shevek (http://www.anarres.org/)."); + out.println("This is free software; see the source for copying conditions. There is NO"); + out.println("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."); + } + private static String getShortOpts(Option[] opts) throws Exception { diff --git a/src/java/org/anarres/cpp/Preprocessor.java b/src/java/org/anarres/cpp/Preprocessor.java index 82e636b..195a822 100644 --- a/src/java/org/anarres/cpp/Preprocessor.java +++ b/src/java/org/anarres/cpp/Preprocessor.java @@ -17,6 +17,7 @@ package org.anarres.cpp; +import java.io.Closeable; import java.io.File; import java.io.IOException; @@ -72,9 +73,7 @@ is what the flags mean: wrapped in an implicit extern "C" block. */ -public class Preprocessor { - private static final boolean DEBUG = false; - +public class Preprocessor implements Closeable { private static final Macro __LINE__ = new Macro("__LINE__"); private static final Macro __FILE__ = new Macro("__FILE__"); @@ -459,10 +458,14 @@ public class Preprocessor { * @see #getSource() * @see #push_source(Source,boolean) */ - protected void pop_source() { + protected void pop_source() + throws IOException { if (listener != null) listener.handleSourceChange(this.source, "pop"); - this.source = this.source.getParent(); + Source s = this.source; + this.source = s.getParent(); + /* Always a noop unless called externally. */ + s.close(); if (listener != null && this.source != null) listener.handleSourceChange(this.source, "resume"); } @@ -487,6 +490,8 @@ public class Preprocessor { if (source_token != null) { Token tok = source_token; source_token = null; + if (getFeature(Feature.DEBUG)) + System.err.println("Returning unget token " + tok); return tok; } @@ -509,12 +514,15 @@ public class Preprocessor { if (getFeature(Feature.LINEMARKERS) && s.isNumbered() && t != null) { - /* XXX Don't we mean t.isNumbered() as well? */ - /* Not perfect, but ... */ - return line_token(t.getLine(), t.getName(), " 2"); + /* We actually want 'did the nested source + * contain a newline token', which isNumbered() + * approximates. This is not perfect, but works. */ + return line_token(t.getLine() + 1, t.getName(), " 2"); } continue; } + if (getFeature(Feature.DEBUG)) + System.err.println("Returning fresh token " + tok); return tok; } } @@ -739,7 +747,7 @@ public class Preprocessor { /** * Expands an argument. */ - /* I'd rather this were done lazily. */ + /* I'd rather this were done lazily, but doing so breaks spec. */ /* pp */ List<Token> expand(List<Token> arg) throws IOException, LexerException { @@ -747,6 +755,7 @@ public class Preprocessor { boolean space = false; push_source(new FixedTokenSource(arg), false); + EXPANSION: for (;;) { Token tok = expanded_token(); switch (tok.getType()) { @@ -872,6 +881,7 @@ public class Preprocessor { case CCOMMENT: case CPPCOMMENT: + /* XXX This is where we implement GNU's cpp -CC. */ // break; case WHITESPACE: if (!paste) @@ -933,10 +943,8 @@ public class Preprocessor { tok = source_token(); } - /* - if (DEBUG) - System.out.println("Defined macro " + m); - */ + if (getFeature(Feature.DEBUG)) + System.err.println("Defined macro " + m); addMacro(m); return tok; /* NL or EOF. */ @@ -1023,7 +1031,7 @@ public class Preprocessor { } for (String dir : sysincludepath) buf.append(" ").append(dir); - error(line, 0, "File not found: " + name + " in" + buf); + error(line, 0, buf.toString()); } private Token include() @@ -1810,8 +1818,8 @@ public class Preprocessor { throws IOException, LexerException { Token tok = _token(); - if (DEBUG) - System.out.println("pp: Returning " + tok); + if (getFeature(Feature.DEBUG)) + System.err.println("pp: Returning " + tok); return tok; } @@ -1856,4 +1864,18 @@ public class Preprocessor { return buf.toString(); } + public void close() + throws IOException { + { + Source s = source; + while (s != null) { + s.close(); + s = s.getParent(); + } + } + for (Source s : inputs) { + s.close(); + } + } + } diff --git a/src/java/org/anarres/cpp/Source.java b/src/java/org/anarres/cpp/Source.java index f6cd3b8..d69a5c2 100644 --- a/src/java/org/anarres/cpp/Source.java +++ b/src/java/org/anarres/cpp/Source.java @@ -18,6 +18,7 @@ package org.anarres.cpp; import java.io.BufferedReader; +import java.io.Closeable; import java.io.File; import java.io.FileReader; import java.io.IOException; @@ -42,7 +43,7 @@ import static org.anarres.cpp.Token.*; * * BUG: Error messages are not handled properly. */ -public abstract class Source implements Iterable<Token> { +public abstract class Source implements Iterable<Token>, Closeable { private Source parent; private boolean autopop; private PreprocessorListener listener; @@ -137,23 +138,15 @@ public abstract class Source implements Iterable<Token> { */ /* pp */ String getPath() { Source parent = getParent(); - while (parent != null) { - String path = parent.getPath(); - if (path != null) - return path; - parent = parent.getParent(); - } + if (parent != null) + return parent.getPath(); return null; } /* pp */ String getName() { Source parent = getParent(); - while (parent != null) { - String name = parent.getName(); - if (name != null) - return name; - parent = parent.getParent(); - } + if (parent != null) + return parent.getName(); return null; } @@ -287,4 +280,8 @@ public abstract class Source implements Iterable<Token> { throw new LexerException("Warning at " + line + ":" + column + ": " + msg); } + public void close() + throws IOException { + } + } |