diff options
-rw-r--r-- | src/java/org/anarres/cpp/Main.java | 8 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/Preprocessor.java | 146 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/Source.java | 41 | ||||
-rw-r--r-- | src/java/org/anarres/cpp/Warning.java | 4 | ||||
-rw-r--r-- | src/scripts/release.sh | 4 |
5 files changed, 181 insertions, 22 deletions
diff --git a/src/java/org/anarres/cpp/Main.java b/src/java/org/anarres/cpp/Main.java index 7ca260c..8a3df27 100644 --- a/src/java/org/anarres/cpp/Main.java +++ b/src/java/org/anarres/cpp/Main.java @@ -86,10 +86,11 @@ public class Main { } public static void main(String[] args) throws Exception { - (new Main()).run(OPTS, args); + (new Main()).run(args); } - public void run(Option[] opts, String[] args) throws Exception { + public void run(String[] args) throws Exception { + Option[]opts = OPTS; String sopts = getShortOpts(opts); Getopt g = new Getopt("jcpp", args, sopts, opts); int c; @@ -100,6 +101,7 @@ public class Main { pp.addFeature(Feature.DIGRAPHS); pp.addFeature(Feature.TRIGRAPHS); pp.addFeature(Feature.LINEMARKERS); + pp.addWarning(Warning.IMPORT); pp.setListener(new PreprocessorListener()); pp.addMacro("__JCPP__"); @@ -127,7 +129,7 @@ public class Main { case 'W': arg = g.getOptarg().toUpperCase(); arg = arg.replace('-', '_'); - if (arg.equals("all")) + if (arg.equals("ALL")) pp.addWarnings(EnumSet.allOf(Warning.class)); else pp.addWarning(Enum.valueOf(Warning.class, arg)); diff --git a/src/java/org/anarres/cpp/Preprocessor.java b/src/java/org/anarres/cpp/Preprocessor.java index 9e32973..c6e98cb 100644 --- a/src/java/org/anarres/cpp/Preprocessor.java +++ b/src/java/org/anarres/cpp/Preprocessor.java @@ -86,6 +86,13 @@ public class Preprocessor { this(new FileLexerSource(file)); } + /** + * Sets the PreprocessorListener which handles events for + * this Preprocessor. + * + * The listener is notified of warnings, errors and source + * changes, amongst other things. + */ public void setListener(PreprocessorListener listener) { this.listener = listener; Source s = source; @@ -96,42 +103,84 @@ public class Preprocessor { } } + /** + * Returns the PreprocessorListener which handles events for + * this Preprocessor. + */ public PreprocessorListener getListener() { return listener; } + /** + * Returns the feature-set for this Preprocessor. + * + * This set may be freely modified by user code. + */ public Set<Feature> getFeatures() { return features; } + /** + * Adds a feature to the feature-set of this Preprocessor. + */ public void addFeature(Feature f) { features.add(f); } + /** + * Adds features to the feature-set of this Preprocessor. + */ public void addFeatures(Collection<Feature> f) { features.addAll(f); } + /** + * Returns true if the given feature is in + * the feature-set of this Preprocessor. + */ public boolean getFeature(Feature f) { return features.contains(f); } + /** + * Returns the warning-set for this Preprocessor. + * + * This set may be freely modified by user code. + */ public Set<Warning> getWarnings() { return warnings; } + /** + * Adds a warning to the warning-set of this Preprocessor. + */ public void addWarning(Warning w) { warnings.add(w); } + /** + * Adds warnings to the warning-set of this Preprocessor. + */ public void addWarnings(Collection<Warning> w) { warnings.addAll(w); } + /** + * Returns true if the given warning is in + * the warning-set of this Preprocessor. + */ public boolean getWarning(Warning w) { return warnings.contains(w); } + /** + * Adds input for the Preprocessor. + * + * XXX Inputs should be maintained off the source stack. + * <p> + * + * Inputs are processed in the order in which they are added. + */ public void addInput(Source source) { source.init(this); if (this.source == null) { @@ -151,6 +200,11 @@ public class Preprocessor { } } + /** + * Adds input for the Preprocessor. + * + * @see #addInput(Source) + */ public void addInput(File file) throws IOException { addInput(new FileLexerSource(file)); @@ -161,7 +215,7 @@ public class Preprocessor { * Handles an error. * * If a PreprocessorListener is installed, it receives the - * error. Otherwise, it is ignored. + * error. Otherwise, an exception is thrown. */ protected void error(int line, int column, String msg) throws LexerException { @@ -171,6 +225,14 @@ public class Preprocessor { throw new LexerException("Error at " + line + ":" + column + ": " + msg); } + /** + * Handles an error. + * + * If a PreprocessorListener is installed, it receives the + * error. Otherwise, an exception is thrown. + * + * @see #error(int, int, String) + */ protected void error(Token tok, String msg) throws LexerException { error(tok.getLine(), tok.getColumn(), msg); @@ -180,16 +242,26 @@ public class Preprocessor { * Handles a warning. * * If a PreprocessorListener is installed, it receives the - * warning. Otherwise, it is ignored. + * warning. Otherwise, an exception is thrown. */ protected void warning(int line, int column, String msg) throws LexerException { - if (listener != null) + if (warnings.contains(Warning.ERROR)) + error(line, column, msg); + else if (listener != null) listener.handleWarning(source, line, column, msg); else throw new LexerException("Warning at " + line + ":" + column + ": " + msg); } + /** + * Handles a warning. + * + * If a PreprocessorListener is installed, it receives the + * warning. Otherwise, an exception is thrown. + * + * @see #warning(int, int, String) + */ protected void warning(Token tok, String msg) throws LexerException { warning(tok.getLine(), tok.getColumn(), msg); @@ -201,6 +273,12 @@ public class Preprocessor { } */ + /** + * Adds a Macro to this Preprocessor. + * + * The given {@link Macro} object encapsulates both the name + * and the expansion. + */ public void addMacro(Macro m) throws LexerException { String name = m.getName(); /* Already handled as a source error in macro(). */ @@ -212,7 +290,8 @@ public class Preprocessor { /** * Defines the given name as a macro. * - * This is a convnience method. + * The String value is lexed into a token stream, which is + * used as the macro expansion. */ public void addMacro(String name, String value) throws LexerException { @@ -233,9 +312,10 @@ public class Preprocessor { } /** - * Defines the given name as a macro. + * Defines the given name as a macro, with the value <code>1</code>. * - * This is a convnience method. + * This is a convnience method, and is equivalent to + * <code>addMacro(name, "1")</code>. */ public void addMacro(String name) throws LexerException { @@ -250,6 +330,11 @@ public class Preprocessor { this.quoteincludepath = path; } + /** + * Returns the user include-path of this Preprocessor. + * + * This list may be freely modified by user code. + */ public List<String> getQuoteIncludePath() { return quoteincludepath; } @@ -262,6 +347,11 @@ public class Preprocessor { this.sysincludepath = path; } + /** + * Returns the system include-path of this Preprocessor. + * + * This list may be freely modified by user code. + */ public List<String> getSystemIncludePath() { return sysincludepath; } @@ -274,6 +364,12 @@ public class Preprocessor { return macros; } + /** + * Returns the named macro. + * + * While you can modify the returned object, unexpected things + * might happen if you do. + */ public Macro getMacro(String name) { return macros.get(name); } @@ -345,7 +441,15 @@ public class Preprocessor { } /** - * Pushes a source into the input stack. + * Pushes a source onto the input stack. + * + * The top source on the input stack is the one which is + * currently being processed. + * + * It is unlikely that you will want to call this method. It is more + * likely that you want {@link #addInput(Source)}. + * + * @see #addInput(Source) */ public void addSource(Source source) { push_source(source, true); @@ -834,6 +938,15 @@ public class Preprocessor { return source_skipline(true); } + /** + * Includes the given file. + * + * User code may override this method to implement a virtual + * file system. + * + * XXX This API subject to change, using File makes no sense + * here. + */ protected boolean include(File file) throws IOException, LexerException { @@ -846,6 +959,12 @@ public class Preprocessor { return true; } + /** + * Includes a file from an include path, by name. + * + * XXX This API subject to change, using File makes no sense + * here. + */ protected boolean include(Iterable<String> path, String name) throws IOException, LexerException { @@ -871,7 +990,7 @@ public class Preprocessor { if (quoted) { File dir = parent.getAbsoluteFile().getParentFile(); if (dir == null) - dir = new File("/"); + dir = new File("/"); // XXX bleh. File file = new File(dir, name); if (include(file)) return; @@ -1223,7 +1342,9 @@ public class Preprocessor { lhs = (long)((Character)tok.getValue()).charValue(); break; case IDENTIFIER: - /* XXX warn */ + if (warnings.contains(Warning.UNDEF)) + warning(tok, "Undefined token '" + tok.getText() + + "' encountered in conditional."); lhs = 0; break; @@ -1557,7 +1678,7 @@ public class Preprocessor { else { state.setSawElse(); state.setActive(! state.isActive()); - return source_skipline(true); + return source_skipline(warnings.contains(Warning.ENDIF_LABELS)); } // break; @@ -1610,7 +1731,7 @@ public class Preprocessor { case PP_ENDIF: pop_state(); - return source_skipline(true); + return source_skipline(warnings.contains(Warning.ENDIF_LABELS)); // break; case PP_LINE: @@ -1620,8 +1741,7 @@ public class Preprocessor { case PP_PRAGMA: if (!isActive()) return source_skipline(false); - else - return pragma(); + return pragma(); // break; default: diff --git a/src/java/org/anarres/cpp/Source.java b/src/java/org/anarres/cpp/Source.java index e7a6d2d..f89b1f8 100644 --- a/src/java/org/anarres/cpp/Source.java +++ b/src/java/org/anarres/cpp/Source.java @@ -48,6 +48,7 @@ public abstract class Source implements Iterable<Token> { private Source parent; private boolean autopop; private PreprocessorListener listener; + private boolean werror; /* LineNumberReader */ @@ -89,11 +90,21 @@ public abstract class Source implements Iterable<Token> { this.autopop = false; } + /** + * Sets the parent source of this source. + * + * Sources form a singly linked list. + */ /* pp */ void setParent(Source parent, boolean autopop) { this.parent = parent; this.autopop = autopop; } + /** + * Returns the parent source of this source. + * + * Sources form a singly linked list. + */ /* pp */ final Source getParent() { return parent; } @@ -101,9 +112,16 @@ public abstract class Source implements Iterable<Token> { // @OverrideMustInvoke /* pp */ void init(Preprocessor pp) { setListener(pp.getListener()); + this.werror = pp.getWarnings().contains(Warning.ERROR); } - /* Actually just used for testing. */ + /** + * Sets the listener for this Source. + * + * Normally this is set by the Preprocessor when a Source is + * used, but if you are using a Source as a standalone object, + * you may wish to call this. + */ public void setListener(PreprocessorListener pl) { this.listener = pl; } @@ -137,6 +155,9 @@ public abstract class Source implements Iterable<Token> { return null; } + /** + * Returns the current line number within this Source. + */ public int getLine() { Source parent = getParent(); if (parent == null) @@ -144,6 +165,9 @@ public abstract class Source implements Iterable<Token> { return parent.getLine(); } + /** + * Returns the current column number within this Source. + */ public int getColumn() { Source parent = getParent(); if (parent == null) @@ -151,6 +175,11 @@ public abstract class Source implements Iterable<Token> { return parent.getColumn(); } + /** + * Returns true if this Source is expanding the given macro. + * + * This is used to prevent macro recursion. + */ /* pp */ boolean isExpanding(Macro m) { Source parent = getParent(); if (parent != null) @@ -168,6 +197,9 @@ public abstract class Source implements Iterable<Token> { return autopop; } + /** + * Returns true if this source has line numbers. + */ /* pp */ boolean isNumbered() { return false; } @@ -181,6 +213,9 @@ public abstract class Source implements Iterable<Token> { throws IOException, LexerException; + /** + * Returns a token iterator for this Source. + */ public Iterator<Token> iterator() { return new SourceIterator(this); } @@ -231,7 +266,9 @@ public abstract class Source implements Iterable<Token> { protected void warning(int line, int column, String msg) throws LexerException { - if (listener != null) + if (werror) + error(line, column, msg); + else if (listener != null) listener.handleWarning(this, line, column, msg); else throw new LexerException("Warning at " + line + ":" + column + ": " + msg); diff --git a/src/java/org/anarres/cpp/Warning.java b/src/java/org/anarres/cpp/Warning.java index 53badee..0937236 100644 --- a/src/java/org/anarres/cpp/Warning.java +++ b/src/java/org/anarres/cpp/Warning.java @@ -21,11 +21,11 @@ package org.anarres.cpp; public enum Warning { TRIGRAPHS, - TRADITIONAL, + // TRADITIONAL, IMPORT, UNDEF, UNUSED_MACROS, ENDIF_LABELS, ERROR, - SYSTEM_HEADERS + // SYSTEM_HEADERS } diff --git a/src/scripts/release.sh b/src/scripts/release.sh index 7904468..7196d36 100644 --- a/src/scripts/release.sh +++ b/src/scripts/release.sh @@ -1,4 +1,4 @@ -scp build/dist/anarres-cpp-*.tar.gz [email protected]:public_html/projects/jcpp/ -scp -r build/javadoc/ [email protected]:public_html/projects/jcpp/ +rsync -avP build/dist/anarres-cpp-*.tar.gz [email protected]:public_html/projects/jcpp/ +rsync -avP --exclude=.svn --exclude=autohandler build/javadoc [email protected]:public_html/projects/jcpp/ cp build/tar/lib/anarres-cpp.jar /home/shevek/java/iengine/trunk/lib/runtime/jcpp/ cp build/tar/lib/anarres-cpp.jar /home/shevek/java/karma/trunk/lib/dp/ |