diff options
author | Shevek <[email protected]> | 2014-09-09 04:16:03 -0700 |
---|---|---|
committer | Shevek <[email protected]> | 2014-09-09 04:16:03 -0700 |
commit | b6a44c31015a71f4624b3ab0b36503a90023c244 (patch) | |
tree | 70e953547493a674053926a1c2895678474bb3c0 /src/main/java/org/anarres/cpp | |
parent | 09e951892e640874756690d3e9f7d07613b4f67b (diff) |
Fix #16: NPE on unterminated ifdef.
Diffstat (limited to 'src/main/java/org/anarres/cpp')
-rw-r--r-- | src/main/java/org/anarres/cpp/MacroTokenSource.java | 7 | ||||
-rw-r--r-- | src/main/java/org/anarres/cpp/Preprocessor.java | 40 |
2 files changed, 35 insertions, 12 deletions
diff --git a/src/main/java/org/anarres/cpp/MacroTokenSource.java b/src/main/java/org/anarres/cpp/MacroTokenSource.java index 516e4f2..92317eb 100644 --- a/src/main/java/org/anarres/cpp/MacroTokenSource.java +++ b/src/main/java/org/anarres/cpp/MacroTokenSource.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.util.Iterator; import java.util.List; +import javax.annotation.Nonnull; import static org.anarres.cpp.Token.*; /* This source should always be active, since we don't expand macros @@ -50,7 +51,11 @@ import static org.anarres.cpp.Token.*; } /* XXX Called from Preprocessor [ugly]. */ - /* pp */ static void escape(StringBuilder buf, CharSequence cs) { + /* pp */ static void escape(@Nonnull StringBuilder buf, @Nonnull CharSequence cs) { + if (buf == null) + throw new NullPointerException("Buffer was null."); + if (cs == null) + throw new NullPointerException("CharSequence was null."); for (int i = 0; i < cs.length(); i++) { char c = cs.charAt(i); switch (c) { diff --git a/src/main/java/org/anarres/cpp/Preprocessor.java b/src/main/java/org/anarres/cpp/Preprocessor.java index 0ad1538..f96eb4a 100644 --- a/src/main/java/org/anarres/cpp/Preprocessor.java +++ b/src/main/java/org/anarres/cpp/Preprocessor.java @@ -495,6 +495,7 @@ public class Preprocessor implements Closeable { * @see #push_source(Source,boolean) * @see #pop_source() */ + @CheckForNull protected Source getSource() { return source; } @@ -552,18 +553,30 @@ public class Preprocessor implements Closeable { pop_source(false); } + @Nonnull + private Token next_source() { + if (inputs.isEmpty()) + return new Token(EOF); + Source s = inputs.remove(0); + push_source(s, true); + return line_token(s.getLine(), s.getName(), " 1"); + } + /* Source tokens */ private Token source_token; /* XXX Make this include the NL, and make all cpp directives eat * their own NL. */ @Nonnull - private Token line_token(int line, String name, String extra) { + private Token line_token(int line, @CheckForNull String name, @Nonnull String extra) { StringBuilder buf = new StringBuilder(); buf.append("#line ").append(line) .append(" \""); /* XXX This call to escape(name) is correct but ugly. */ - MacroTokenSource.escape(buf, name); + if (name == null) + buf.append("<unnamed-source>"); + else + MacroTokenSource.escape(buf, name); buf.append("\"").append(extra).append("\n"); return new Token(P_LINE, line, 0, buf.toString(), null); } @@ -583,13 +596,10 @@ public class Preprocessor implements Closeable { for (;;) { Source s = getSource(); if (s == null) { - if (inputs.isEmpty()) - return new Token(EOF); - Source t = inputs.remove(0); - push_source(t, true); - if (getFeature(Feature.LINEMARKERS)) - return line_token(t.getLine(), t.getName(), " 1"); - continue; + Token t = next_source(); + if (t.getType() == P_LINE && !getFeature(Feature.LINEMARKERS)) + continue; + return t; } Token tok = s.token(); /* XXX Refactor with skipline() */ @@ -1675,13 +1685,21 @@ public class Preprocessor implements Closeable { for (;;) { Token tok; if (!isActive()) { + Source s = getSource(); + if (s == null) { + Token t = next_source(); + if (t.getType() == P_LINE && !getFeature(Feature.LINEMARKERS)) + continue; + return t; + } + try { /* XXX Tell lexer to ignore warnings. */ - source.setActive(false); + s.setActive(false); tok = source_token(); } finally { /* XXX Tell lexer to stop ignoring warnings. */ - source.setActive(true); + s.setActive(true); } switch (tok.getType()) { case HASH: |