aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/org/anarres/cpp
diff options
context:
space:
mode:
authorShevek <[email protected]>2014-09-10 23:02:35 -0700
committerShevek <[email protected]>2014-09-10 23:02:35 -0700
commit8880128db2660d6a9494911fbd14bcc5aaa39c60 (patch)
tree5b9aa05de370750089e7f8eaae374bde3dbc3add /src/main/java/org/anarres/cpp
parentbcc3a2b96b0e8b8b03dad0babd7103903cc9df3f (diff)
Modernize: Use slf4j and joptsimple.
Diffstat (limited to 'src/main/java/org/anarres/cpp')
-rw-r--r--src/main/java/org/anarres/cpp/CppReader.java17
-rw-r--r--src/main/java/org/anarres/cpp/DefaultPreprocessorListener.java12
-rw-r--r--src/main/java/org/anarres/cpp/Feature.java1
-rw-r--r--src/main/java/org/anarres/cpp/Main.java333
-rw-r--r--src/main/java/org/anarres/cpp/Preprocessor.java18
-rw-r--r--src/main/java/org/anarres/cpp/PreprocessorListener.java12
-rw-r--r--src/main/java/org/anarres/cpp/Warning.java2
7 files changed, 139 insertions, 256 deletions
diff --git a/src/main/java/org/anarres/cpp/CppReader.java b/src/main/java/org/anarres/cpp/CppReader.java
index 9157a93..5517f47 100644
--- a/src/main/java/org/anarres/cpp/CppReader.java
+++ b/src/main/java/org/anarres/cpp/CppReader.java
@@ -19,6 +19,7 @@ package org.anarres.cpp;
import java.io.Closeable;
import java.io.IOException;
import java.io.Reader;
+import javax.annotation.Nonnull;
import static org.anarres.cpp.Token.CCOMMENT;
import static org.anarres.cpp.Token.CPPCOMMENT;
import static org.anarres.cpp.Token.EOF;
@@ -34,11 +35,11 @@ import static org.anarres.cpp.Token.EOF;
*/
public class CppReader extends Reader implements Closeable {
- private Preprocessor cpp;
+ private final Preprocessor cpp;
private String token;
private int idx;
- public CppReader(final Reader r) {
+ public CppReader(@Nonnull final Reader r) {
cpp = new Preprocessor(new LexerSource(r, true) {
@Override
public String getName() {
@@ -50,7 +51,7 @@ public class CppReader extends Reader implements Closeable {
idx = 0;
}
- public CppReader(Preprocessor p) {
+ public CppReader(@Nonnull Preprocessor p) {
cpp = p;
token = "";
idx = 0;
@@ -59,6 +60,7 @@ public class CppReader extends Reader implements Closeable {
/**
* Returns the Preprocessor used by this CppReader.
*/
+ @Nonnull
public Preprocessor getPreprocessor() {
return cpp;
}
@@ -68,7 +70,7 @@ public class CppReader extends Reader implements Closeable {
*
* This is a convnience method.
*/
- public void addMacro(String name)
+ public void addMacro(@Nonnull String name)
throws LexerException {
cpp.addMacro(name);
}
@@ -78,7 +80,7 @@ public class CppReader extends Reader implements Closeable {
*
* This is a convnience method.
*/
- public void addMacro(String name, String value)
+ public void addMacro(@Nonnull String name, @Nonnull String value)
throws LexerException {
cpp.addMacro(name, value);
}
@@ -138,10 +140,7 @@ public class CppReader extends Reader implements Closeable {
@Override
public void close()
throws IOException {
- if (cpp != null) {
- cpp.close();
- cpp = null;
- }
+ cpp.close();
token = null;
}
diff --git a/src/main/java/org/anarres/cpp/DefaultPreprocessorListener.java b/src/main/java/org/anarres/cpp/DefaultPreprocessorListener.java
index 6d3929d..68f6e89 100644
--- a/src/main/java/org/anarres/cpp/DefaultPreprocessorListener.java
+++ b/src/main/java/org/anarres/cpp/DefaultPreprocessorListener.java
@@ -17,6 +17,9 @@ package org.anarres.cpp;
* permissions and limitations under the License.
*/
import javax.annotation.Nonnegative;
+import javax.annotation.Nonnull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A handler for preprocessor events, primarily errors and warnings.
@@ -27,6 +30,8 @@ import javax.annotation.Nonnegative;
*/
public class DefaultPreprocessorListener implements PreprocessorListener {
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultPreprocessorListener.class);
+
private int errors;
private int warnings;
@@ -49,8 +54,8 @@ public class DefaultPreprocessorListener implements PreprocessorListener {
return warnings;
}
- protected void print(String msg) {
- System.err.println(msg);
+ protected void print(@Nonnull String msg) {
+ LOG.info(msg);
}
/**
@@ -60,6 +65,7 @@ public class DefaultPreprocessorListener implements PreprocessorListener {
* implementation. It may simply record the error message, or
* it may throw an exception.
*/
+ @Override
public void handleWarning(Source source, int line, int column,
String msg)
throws LexerException {
@@ -75,6 +81,7 @@ public class DefaultPreprocessorListener implements PreprocessorListener {
* implementation. It may simply record the error message, or
* it may throw an exception.
*/
+ @Override
public void handleError(Source source, int line, int column,
String msg)
throws LexerException {
@@ -83,6 +90,7 @@ public class DefaultPreprocessorListener implements PreprocessorListener {
+ ": error: " + msg);
}
+ @Override
public void handleSourceChange(Source source, String event) {
}
diff --git a/src/main/java/org/anarres/cpp/Feature.java b/src/main/java/org/anarres/cpp/Feature.java
index cc7f818..369d79c 100644
--- a/src/main/java/org/anarres/cpp/Feature.java
+++ b/src/main/java/org/anarres/cpp/Feature.java
@@ -33,7 +33,6 @@ public enum Feature {
KEEPCOMMENTS,
/** Preserves comments in the lexed output, even when inactive. */
KEEPALLCOMMENTS,
- VERBOSE,
DEBUG,
/** Supports lexing of objective-C. */
OBJCSYNTAX,
diff --git a/src/main/java/org/anarres/cpp/Main.java b/src/main/java/org/anarres/cpp/Main.java
index 3bc02eb..5a3e113 100644
--- a/src/main/java/org/anarres/cpp/Main.java
+++ b/src/main/java/org/anarres/cpp/Main.java
@@ -16,54 +16,27 @@
*/
package org.anarres.cpp;
-import gnu.getopt.Getopt;
-import gnu.getopt.LongOpt;
import java.io.File;
import java.io.PrintStream;
+import java.util.Arrays;
import java.util.EnumSet;
+import java.util.List;
+import javax.annotation.Nonnull;
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+import joptsimple.ValueConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* (Currently a simple test class).
*/
public class Main {
- private static class Option extends LongOpt {
-
- private final String eg;
- private final String help;
-
- public Option(String word, int arg, int ch,
- String eg, String help) {
- super(word, arg, null, ch);
- this.eg = eg;
- this.help = help;
- }
- }
-
- private static final Option[] OPTS = new Option[]{
- new Option("help", LongOpt.NO_ARGUMENT, 'h', null,
- "Displays help and usage information."),
- new Option("define", LongOpt.REQUIRED_ARGUMENT, 'D', "name=definition",
- "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, 1, "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("iquote", LongOpt.REQUIRED_ARGUMENT, 0, "dir",
- "Adds the directory dir to the list of directories to be searched for header files included using \"\"."),
- new Option("warning", LongOpt.REQUIRED_ARGUMENT, 'W', "type",
- "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() + ")"),};
+ private static final Logger LOG = LoggerFactory.getLogger(Main.class);
+ @Nonnull
private static CharSequence getWarnings() {
StringBuilder buf = new StringBuilder();
for (Warning w : Warning.values()) {
@@ -80,12 +53,52 @@ public class Main {
}
public void run(String[] args) throws Exception {
- Option[] opts = OPTS;
- String sopts = getShortOpts(opts);
- Getopt g = new Getopt("jcpp", args, sopts, opts);
- int c;
- String arg;
- int idx;
+
+ OptionParser parser = new OptionParser();
+ OptionSpec<?> helpOption = parser.accepts("help",
+ "Displays command-line help.")
+ .forHelp();
+ OptionSpec<?> versionOption = parser.acceptsAll(Arrays.asList("version"),
+ "Displays the product version (" + Version.getVersion() + ") and exits.")
+ .forHelp();
+
+ OptionSpec<?> debugOption = parser.acceptsAll(Arrays.asList("debug"),
+ "Enables debug output.");
+
+ OptionSpec<String> defineOption = parser.acceptsAll(Arrays.asList("define", "D"),
+ "Defines the given macro.")
+ .withRequiredArg().ofType(String.class).describedAs("name[=definition]");
+ OptionSpec<String> undefineOption = parser.acceptsAll(Arrays.asList("undefine", "U"),
+ "Undefines the given macro, previously either builtin or defined using -D.")
+ .withRequiredArg().describedAs("name");
+ OptionSpec<File> includeOption = parser.accepts("include",
+ "Process file as if \"#" + "include \"file\"\" appeared as the first line of the primary source file.")
+ .withRequiredArg().ofType(File.class).describedAs("file");
+ OptionSpec<File> incdirOption = parser.acceptsAll(Arrays.asList("incdir", "I"),
+ "Adds the directory dir to the list of directories to be searched for header files.")
+ .withRequiredArg().ofType(File.class).describedAs("dir");
+ OptionSpec<File> iquoteOption = parser.acceptsAll(Arrays.asList("iquote"),
+ "Adds the directory dir to the list of directories to be searched for header files included using \"\".")
+ .withRequiredArg().ofType(File.class).describedAs("dir");
+ OptionSpec<String> warningOption = parser.acceptsAll(Arrays.asList("warning", "W"),
+ "Enables the named warning class (" + getWarnings() + ").")
+ .withRequiredArg().ofType(String.class).describedAs("warning");
+ OptionSpec<Void> noWarningOption = parser.acceptsAll(Arrays.asList("no-warnings", "w"),
+ "Disables ALL warnings.");
+ OptionSpec<File> inputsOption = parser.nonOptions()
+ .ofType(File.class).describedAs("Files to process.");
+
+ OptionSet options = parser.parse(args);
+
+ if (options.has(helpOption)) {
+ parser.printHelpOn(System.out);
+ return;
+ }
+
+ if (options.has(versionOption)) {
+ version(System.out);
+ return;
+ }
Preprocessor pp = new Preprocessor();
pp.addFeature(Feature.DIGRAPHS);
@@ -100,78 +113,56 @@ public class Main {
pp.getFrameworksPath().add("/Library/Frameworks");
pp.getFrameworksPath().add("/Local/Library/Frameworks");
- GETOPT:
- while ((c = g.getopt()) != -1) {
- switch (c) {
- case 'D':
- arg = g.getOptarg();
- idx = arg.indexOf('=');
- if (idx == -1)
- pp.addMacro(arg);
- else
- pp.addMacro(arg.substring(0, idx),
- arg.substring(idx + 1));
- break;
- case 'U':
- pp.getMacros().remove(g.getOptarg());
- break;
- case 'I':
- pp.getSystemIncludePath().add(g.getOptarg());
- break;
- case 0: // --iquote=
- pp.getQuoteIncludePath().add(g.getOptarg());
- break;
- case 'W':
- arg = g.getOptarg().toUpperCase();
- arg = arg.replace('-', '_');
- if (arg.equals("ALL"))
- pp.addWarnings(EnumSet.allOf(Warning.class));
- else
- pp.addWarning(Enum.valueOf(Warning.class, arg));
- break;
- case 'w':
- pp.getWarnings().clear();
- break;
- case 1: // --include=
- // pp.addInput(new File(g.getOptarg()));
- // Comply exactly with spec.
- pp.addInput(new StringLexerSource(
- "#" + "include \"" + g.getOptarg() + "\"\n"
- ));
- break;
- case 2: // --version
- 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 '?':
- continue; /* Make failure-proof. */
+ if (options.has(debugOption))
+ pp.addFeature(Feature.DEBUG);
- }
+ if (options.has(noWarningOption))
+ pp.getWarnings().clear();
+
+ for (String warning : options.valuesOf(warningOption)) {
+ warning = warning.toUpperCase();
+ warning = warning.replace('-', '_');
+ if (warning.equals("ALL"))
+ pp.addWarnings(EnumSet.allOf(Warning.class));
+ else
+ pp.addWarning(Enum.valueOf(Warning.class, warning));
+ }
+
+ for (String arg : options.valuesOf(defineOption)) {
+ int idx = arg.indexOf('=');
+ if (idx == -1)
+ pp.addMacro(arg);
+ else
+ pp.addMacro(arg.substring(0, idx), arg.substring(idx + 1));
}
+ for (String arg : options.valuesOf(undefineOption)) {
+ pp.getMacros().remove(arg);
+ }
+
+ for (File dir : options.valuesOf(incdirOption))
+ pp.getSystemIncludePath().add(dir.getAbsolutePath());
+ for (File dir : options.valuesOf(iquoteOption))
+ pp.getQuoteIncludePath().add(dir.getAbsolutePath());
+ for (File file : options.valuesOf(includeOption))
+ // Comply exactly with spec.
+ pp.addInput(new StringLexerSource("#" + "include \"" + file + "\"\n"));
- for (int i = g.getOptind(); i < args.length; i++)
- pp.addInput(new FileLexerSource(new File(args[i])));
- if (g.getOptind() == args.length)
+ List<File> inputs = options.valuesOf(inputsOption);
+ if (inputs.isEmpty()) {
pp.addInput(new InputLexerSource(System.in));
+ } else {
+ for (File input : inputs)
+ pp.addInput(new FileLexerSource(input));
+ }
- if (pp.getFeature(Feature.VERBOSE)) {
- System.err.println("#" + "include \"...\" search starts here:");
+ if (pp.getFeature(Feature.DEBUG)) {
+ LOG.info("#" + "include \"...\" search starts here:");
for (String dir : pp.getQuoteIncludePath())
- System.err.println(" " + dir);
- System.err.println("#" + "include <...> search starts here:");
+ LOG.info(" " + dir);
+ LOG.info("#" + "include <...> search starts here:");
for (String dir : pp.getSystemIncludePath())
- System.err.println(" " + dir);
- System.err.println("End of search list.");
+ LOG.info(" " + dir);
+ LOG.info("End of search list.");
}
try {
@@ -184,137 +175,21 @@ public class Main {
System.out.print(tok.getText());
}
} catch (Exception e) {
- e.printStackTrace(System.err);
+ StringBuilder buf = new StringBuilder("Preprocessor failed:\n");
Source s = pp.getSource();
while (s != null) {
- System.err.println(" -> " + s);
+ buf.append(" -> ").append(s).append("\n");
s = s.getParent();
}
+ LOG.error(buf.toString(), e);
}
}
- private void version(PrintStream out) {
+ private static void version(@Nonnull PrintStream out) {
out.println("Anarres Java C Preprocessor version " + Version.getVersion());
out.println("Copyright (C) 2008-2014 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 {
- StringBuilder buf = new StringBuilder();
- for (Option opt : opts) {
- char c = (char) opt.getVal();
- if (!Character.isLetterOrDigit(c))
- continue;
- for (int j = 0; j < buf.length(); j++)
- if (buf.charAt(j) == c)
- throw new Exception(
- "Duplicate short option " + c
- );
- buf.append(c);
- switch (opt.getHasArg()) {
- case LongOpt.NO_ARGUMENT:
- break;
- case LongOpt.OPTIONAL_ARGUMENT:
- buf.append("::");
- break;
- case LongOpt.REQUIRED_ARGUMENT:
- buf.append(":");
- break;
- }
- }
- return buf.toString();
- }
-
- /* This is incomplete but nearly there. */
- /**
- * Wraps a string.
- *
- * The output form is:
- * <pre>
- * prefix in[0]
- * &lt;--indent-&gt; in[1]
- * &lt;--indent-&gt; in[2]
- * &lt;-----width----&gt;
- * </pre>
- */
- /* XXX There's some of this in commons. */
- private static String wrap(String in, String prefix,
- int indent, int width) {
- StringBuilder buf = new StringBuilder(prefix);
-
- while (buf.length() < indent)
- buf.append(' ');
-
- int start = 0;
-
- while (start < in.length()) {
- while (start < in.length()
- && Character.isWhitespace(in.charAt(start)))
- start++;
-
- int end = start + width - indent;
-
- if (end > in.length()) {
- buf.append(in.substring(start));
- break;
- }
-
- int idx = end;
- while (!Character.isWhitespace(in.charAt(idx)))
- idx--;
-
- if (idx == start) {
- idx = end - 1;
- buf.append(in.substring(start, idx));
- buf.append('-');
- } else {
- buf.append(in.substring(start, idx));
- start = idx;
- }
-
- start = idx;
- }
-
- return buf.toString();
- }
-
- private static void usage(String command, Option[] options) {
- StringBuilder text = new StringBuilder("Usage: ");
- text.append(command).append('\n');
- for (Option option : options) {
- StringBuilder line = new StringBuilder();
- Option opt = option;
- line.append(" --").append(opt.getName());
- switch (opt.getHasArg()) {
- case LongOpt.NO_ARGUMENT:
- break;
- case LongOpt.OPTIONAL_ARGUMENT:
- line.append("[=").append(opt.eg).append(']');
- break;
- case LongOpt.REQUIRED_ARGUMENT:
- line.append('=').append(opt.eg);
- break;
- }
- if (Character.isLetterOrDigit(opt.getVal()))
- line.append(" (-").append((char) opt.getVal()).append(")");
- if (line.length() < 30) {
- while (line.length() < 30)
- line.append(' ');
- } else {
- line.append('\n');
- for (int j = 0; j < 30; j++)
- line.append(' ');
- }
- /* This should use wrap. */
- line.append(opt.help);
- line.append('\n');
- text.append(line);
- }
-
- System.out.println(text);
- }
-
}
diff --git a/src/main/java/org/anarres/cpp/Preprocessor.java b/src/main/java/org/anarres/cpp/Preprocessor.java
index 43fba89..6bcf3fb 100644
--- a/src/main/java/org/anarres/cpp/Preprocessor.java
+++ b/src/main/java/org/anarres/cpp/Preprocessor.java
@@ -33,6 +33,8 @@ import java.util.Stack;
import java.util.TreeMap;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import static org.anarres.cpp.PreprocessorCommand.*;
import static org.anarres.cpp.Token.*;
@@ -73,6 +75,8 @@ import static org.anarres.cpp.Token.*;
*/
public class Preprocessor implements Closeable {
+ private static final Logger LOG = LoggerFactory.getLogger(Preprocessor.class);
+
private static final Source INTERNAL = new Source() {
@Override
public Token token()
@@ -600,7 +604,7 @@ public class Preprocessor implements Closeable {
Token tok = source_token;
source_token = null;
if (getFeature(Feature.DEBUG))
- System.err.println("Returning unget token " + tok);
+ LOG.debug("Returning unget token " + tok);
return tok;
}
@@ -622,7 +626,7 @@ public class Preprocessor implements Closeable {
continue;
}
if (getFeature(Feature.DEBUG))
- System.err.println("Returning fresh token " + tok);
+ LOG.debug("Returning fresh token " + tok);
return tok;
}
}
@@ -1064,7 +1068,7 @@ public class Preprocessor implements Closeable {
}
if (getFeature(Feature.DEBUG))
- System.err.println("Defined macro " + m);
+ LOG.debug("Defined macro " + m);
addMacro(m);
return tok; /* NL or EOF. */
@@ -1104,7 +1108,7 @@ public class Preprocessor implements Closeable {
if (!file.isFile())
return false;
if (getFeature(Feature.DEBUG))
- System.err.println("pp: including " + file);
+ LOG.debug("pp: including " + file);
includes.add(file);
push_source(file.getSource(), true);
return true;
@@ -1497,9 +1501,7 @@ public class Preprocessor implements Closeable {
throws IOException,
LexerException {
/*
- * System.out.flush();
* (new Exception("expr(" + priority + ") called")).printStackTrace();
- * System.err.flush();
*/
Token tok = expr_token();
@@ -1638,9 +1640,7 @@ public class Preprocessor implements Closeable {
}
/*
- * System.out.flush();
* (new Exception("expr returning " + lhs)).printStackTrace();
- * System.err.flush();
*/
// System.out.println("expr returning " + lhs);
return lhs;
@@ -2059,7 +2059,7 @@ public class Preprocessor implements Closeable {
LexerException {
Token tok = _token();
if (getFeature(Feature.DEBUG))
- System.err.println("pp: Returning " + tok);
+ LOG.debug("pp: Returning " + tok);
return tok;
}
diff --git a/src/main/java/org/anarres/cpp/PreprocessorListener.java b/src/main/java/org/anarres/cpp/PreprocessorListener.java
index 6a4cb22..3443714 100644
--- a/src/main/java/org/anarres/cpp/PreprocessorListener.java
+++ b/src/main/java/org/anarres/cpp/PreprocessorListener.java
@@ -16,6 +16,8 @@
*/
package org.anarres.cpp;
+import javax.annotation.Nonnull;
+
/**
* A handler for preprocessor events, primarily errors and warnings.
*
@@ -32,8 +34,8 @@ public interface PreprocessorListener {
* implementation. It may simply record the error message, or
* it may throw an exception.
*/
- public void handleWarning(Source source, int line, int column,
- String msg)
+ public void handleWarning(@Nonnull Source source, int line, int column,
+ @Nonnull String msg)
throws LexerException;
/**
@@ -43,10 +45,10 @@ public interface PreprocessorListener {
* implementation. It may simply record the error message, or
* it may throw an exception.
*/
- public void handleError(Source source, int line, int column,
- String msg)
+ public void handleError(@Nonnull Source source, int line, int column,
+ @Nonnull String msg)
throws LexerException;
- public void handleSourceChange(Source source, String event);
+ public void handleSourceChange(@Nonnull Source source, @Nonnull String event);
}
diff --git a/src/main/java/org/anarres/cpp/Warning.java b/src/main/java/org/anarres/cpp/Warning.java
index da2b2c6..80d184a 100644
--- a/src/main/java/org/anarres/cpp/Warning.java
+++ b/src/main/java/org/anarres/cpp/Warning.java
@@ -28,5 +28,5 @@ public enum Warning {
UNUSED_MACROS,
ENDIF_LABELS,
ERROR,
- // SYSTEM_HEADERS
+ // SYSTEM_HEADERS
}