summaryrefslogtreecommitdiffstats
path: root/src/java/org/anarres
diff options
context:
space:
mode:
authorShevek <[email protected]>2008-06-14 22:42:09 +0000
committerShevek <[email protected]>2008-06-14 22:42:09 +0000
commitaba944f23747fdf35e890020cdbbca722bbaaacf (patch)
treeba247d276402039f5c75d00312a40bf5581715a2 /src/java/org/anarres
parent0e479d174065605b32892be1a7fc5f789ea2e255 (diff)
remove quadratic getName; close lexers; add debug flags
Diffstat (limited to 'src/java/org/anarres')
-rw-r--r--src/java/org/anarres/cpp/ChrootFileSystem.java1
-rw-r--r--src/java/org/anarres/cpp/CppReader.java9
-rw-r--r--src/java/org/anarres/cpp/Feature.java2
-rw-r--r--src/java/org/anarres/cpp/InputLexerSource.java68
-rw-r--r--src/java/org/anarres/cpp/JavaFileSystem.java8
-rw-r--r--src/java/org/anarres/cpp/LexerSource.java16
-rw-r--r--src/java/org/anarres/cpp/Main.java42
-rw-r--r--src/java/org/anarres/cpp/Preprocessor.java54
-rw-r--r--src/java/org/anarres/cpp/Source.java23
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 {
+ }
+
}