diff options
author | Sven Gothel <[email protected]> | 2015-03-23 22:20:11 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2015-03-23 22:20:11 +0100 |
commit | 0bb7cf5586f08c00de051036427de36e2b1601f4 (patch) | |
tree | 52e807d3c452d619a942379e3ef8768a2407b020 /src/main/java/org | |
parent | e3b1d17a2f2b4070c1080fa6f78cfc1bcd28c78c (diff) |
Relocate JCPP package: org/anarres/cpp -> com/jogamp/gluegen/jcpp
Diffstat (limited to 'src/main/java/org')
33 files changed, 0 insertions, 6419 deletions
diff --git a/src/main/java/org/anarres/cpp/Argument.java b/src/main/java/org/anarres/cpp/Argument.java deleted file mode 100644 index 31d9e93..0000000 --- a/src/main/java/org/anarres/cpp/Argument.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import javax.annotation.Nonnull; - -/** - * A macro argument. - * - * This encapsulates a raw and preprocessed token stream. - */ -/* pp */ class Argument extends ArrayList<Token> { - - private List<Token> expansion; - - public Argument() { - this.expansion = null; - } - - public void addToken(@Nonnull Token tok) { - add(tok); - } - - /* pp */ void expand(@Nonnull Preprocessor p) - throws IOException, - LexerException { - /* Cache expansion. */ - if (expansion == null) { - this.expansion = p.expand(this); - // System.out.println("Expanded arg " + this); - } - } - - @Nonnull - public Iterator<Token> expansion() { - return expansion.iterator(); - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append("Argument("); - // buf.append(super.toString()); - buf.append("raw=[ "); - for (int i = 0; i < size(); i++) - buf.append(get(i).getText()); - buf.append(" ];expansion=[ "); - if (expansion == null) - buf.append("null"); - else - for (Token token : expansion) - buf.append(token.getText()); - buf.append(" ])"); - return buf.toString(); - } - -} diff --git a/src/main/java/org/anarres/cpp/BuildMetadata.java b/src/main/java/org/anarres/cpp/BuildMetadata.java deleted file mode 100644 index 79de407..0000000 --- a/src/main/java/org/anarres/cpp/BuildMetadata.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.anarres.cpp; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import javax.annotation.Nonnull; - -/** - * Returns information about the build. - * - * @author shevek - */ -public class BuildMetadata { - - public static final String RESOURCE = "/META-INF/jcpp.properties"; - private static BuildMetadata INSTANCE; - - /** @throws RuntimeException if the properties file cannot be found on the classpath. */ - @Nonnull - public static synchronized BuildMetadata getInstance() { - try { - if (INSTANCE == null) - INSTANCE = new BuildMetadata(); - return INSTANCE; - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private final Properties properties = new Properties(); - - private BuildMetadata() throws IOException { - URL url = BuildMetadata.class.getResource(RESOURCE); - InputStream in = url.openStream(); - try { - properties.load(in); - } finally { - in.close(); - } - } - - @Nonnull - public Map<? extends String, ? extends String> asMap() { - Map<String, String> out = new HashMap<String, String>(); - for (Map.Entry<Object, Object> e : properties.entrySet()) - out.put(String.valueOf(e.getKey()), String.valueOf(e.getValue())); - return out; - } - - @Nonnull - public com.github.zafarkhaja.semver.Version getVersion() { - return com.github.zafarkhaja.semver.Version.valueOf(properties.getProperty("Implementation-Version")); - } - - @Nonnull - public Date getBuildDate() throws ParseException { - // Build-Date=2015-01-01_10:09:09 - String text = properties.getProperty("Build-Date"); - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss"); - return format.parse(text); - } - - public String getChangeId() { - return properties.getProperty("Change"); - } -} diff --git a/src/main/java/org/anarres/cpp/ChrootFileSystem.java b/src/main/java/org/anarres/cpp/ChrootFileSystem.java deleted file mode 100644 index 1cec184..0000000 --- a/src/main/java/org/anarres/cpp/ChrootFileSystem.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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.File; -import java.io.IOException; - -/** - * A virtual filesystem implementation using java.io in a virtual - * chroot. - */ -public class ChrootFileSystem implements VirtualFileSystem { - - private File root; - - public ChrootFileSystem(File root) { - this.root = root; - } - - @Override - public VirtualFile getFile(String path) { - return new ChrootFile(path); - } - - @Override - public VirtualFile getFile(String dir, String name) { - return new ChrootFile(dir, name); - } - - private class ChrootFile extends File implements VirtualFile { - - private File rfile; - - public ChrootFile(String path) { - super(path); - } - - public ChrootFile(String dir, String name) { - super(dir, name); - } - - /* private */ - public ChrootFile(File dir, String name) { - super(dir, name); - } - - @Override - public ChrootFile getParentFile() { - return new ChrootFile(getParent()); - } - - @Override - public ChrootFile getChildFile(String name) { - return new ChrootFile(this, name); - } - - @Override - public boolean isFile() { - File real = new File(root, getPath()); - return real.isFile(); - } - - @Override - public Source getSource() throws IOException { - return new FileLexerSource(new File(root, getPath()), - getPath()); - } - } - -} diff --git a/src/main/java/org/anarres/cpp/CppReader.java b/src/main/java/org/anarres/cpp/CppReader.java deleted file mode 100644 index 5517f47..0000000 --- a/src/main/java/org/anarres/cpp/CppReader.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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.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; - -/** - * A Reader wrapper around the Preprocessor. - * - * This is a utility class to provide a transparent {@link Reader} - * which preprocesses the input text. - * - * @see Preprocessor - * @see Reader - */ -public class CppReader extends Reader implements Closeable { - - private final Preprocessor cpp; - private String token; - private int idx; - - public CppReader(@Nonnull final Reader r) { - cpp = new Preprocessor(new LexerSource(r, true) { - @Override - public String getName() { - return "<CppReader Input@" - + System.identityHashCode(r) + ">"; - } - }); - token = ""; - idx = 0; - } - - public CppReader(@Nonnull Preprocessor p) { - cpp = p; - token = ""; - idx = 0; - } - - /** - * Returns the Preprocessor used by this CppReader. - */ - @Nonnull - public Preprocessor getPreprocessor() { - return cpp; - } - - /** - * Defines the given name as a macro. - * - * This is a convnience method. - */ - public void addMacro(@Nonnull String name) - throws LexerException { - cpp.addMacro(name); - } - - /** - * Defines the given name as a macro. - * - * This is a convnience method. - */ - public void addMacro(@Nonnull String name, @Nonnull String value) - throws LexerException { - cpp.addMacro(name, value); - } - - private boolean refill() - throws IOException { - try { - assert cpp != null : "cpp is null : was it closed?"; - if (token == null) - return false; - while (idx >= token.length()) { - Token tok = cpp.token(); - switch (tok.getType()) { - case EOF: - token = null; - return false; - case CCOMMENT: - case CPPCOMMENT: - if (!cpp.getFeature(Feature.KEEPCOMMENTS)) { - token = " "; - break; - } - default: - token = tok.getText(); - break; - } - idx = 0; - } - return true; - } catch (LexerException e) { - throw new IOException(String.valueOf(e), e); - } - } - - @Override - public int read() - throws IOException { - if (!refill()) - return -1; - return token.charAt(idx++); - } - - /* XXX Very slow and inefficient. */ - public int read(char cbuf[], int off, int len) - throws IOException { - if (token == null) - return -1; - for (int i = 0; i < len; i++) { - int ch = read(); - if (ch == -1) - return i; - cbuf[off + i] = (char) ch; - } - return len; - } - - @Override - public void close() - throws IOException { - cpp.close(); - token = null; - } - -} diff --git a/src/main/java/org/anarres/cpp/CppTask.java b/src/main/java/org/anarres/cpp/CppTask.java deleted file mode 100644 index 66df1a6..0000000 --- a/src/main/java/org/anarres/cpp/CppTask.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * 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.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.List; -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.taskdefs.Copy; -import org.apache.tools.ant.types.FilterSet; -import org.apache.tools.ant.types.FilterSetCollection; -import org.apache.tools.ant.types.Path; - -/** - * An ant task for jcpp. - */ -public class CppTask extends Copy { - - private class Listener extends DefaultPreprocessorListener { - - @Override - protected void print(String msg) { - log(msg); - } - } - - public static class Macro { - - private String name; - private String value; - - public void setName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setValue(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - } - - private final Listener listener = new Listener(); - private final List<Macro> macros = new ArrayList<Macro>(); - private Path systemincludepath; - private Path localincludepath; - - public void addMacro(Macro macro) { - macros.add(macro); - } - - public void addSystemincludepath(Path path) { - if (systemincludepath == null) - systemincludepath = new Path(getProject()); - systemincludepath.add(path); - } - - public void addLocalincludepath(Path path) { - if (localincludepath == null) - localincludepath = new Path(getProject()); - localincludepath.add(path); - } - - /* - public void execute() { - FileWriter writer = null; - try { - if (input == null) - throw new BuildException("Input not specified"); - if (output == null) - throw new BuildException("Output not specified"); - cpp.addInput(this.input); - writer = new FileWriter(this.output); - for (;;) { - Token tok = cpp.token(); - if (tok != null && tok.getType() == Token.EOF) - break; - writer.write(tok.getText()); - } - } - catch (Exception e) { - throw new BuildException(e); - } - finally { - if (writer != null) { - try { - writer.close(); - } - catch (IOException e) { - } - } - } - } - */ - private void preprocess(File input, File output) throws Exception { - Preprocessor cpp = new Preprocessor(); - cpp.setListener(listener); - for (Macro macro : macros) - cpp.addMacro(macro.getName(), macro.getValue()); - if (systemincludepath != null) - cpp.setSystemIncludePath(Arrays.asList(systemincludepath.list())); - if (localincludepath != null) - cpp.setQuoteIncludePath(Arrays.asList(localincludepath.list())); - - File dir = output.getParentFile(); - if (!dir.exists()) { - if (!dir.mkdirs()) - throw new BuildException("Failed to make parent directory " + dir); - } else if (!dir.isDirectory()) { - throw new BuildException("Parent directory of output file " + output + " exists, but is not a directory."); - } - FileWriter writer = null; - try { - if (input == null) - throw new BuildException("Input not specified"); - if (output == null) - throw new BuildException("Output not specified"); - cpp.addInput(input); - writer = new FileWriter(output); - for (;;) { - Token tok = cpp.token(); - if (tok == null) - break; - if (tok.getType() == Token.EOF) - break; - writer.write(tok.getText()); - } - } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException e) { - } - } - } - } - - @Override - protected void doFileOperations() { - if (fileCopyMap.size() > 0) { - log("Copying " + fileCopyMap.size() - + " file" + (fileCopyMap.size() == 1 ? "" : "s") - + " to " + destDir.getAbsolutePath()); - - Enumeration<String> e = fileCopyMap.keys(); - - while (e.hasMoreElements()) { - String fromFile = e.nextElement(); - String[] toFiles = (String[]) fileCopyMap.get(fromFile); - - for (String toFile : toFiles) { - if (fromFile.equals(toFile)) { - log("Skipping self-copy of " + fromFile, verbosity); - continue; - } - - try { - log("Copying " + fromFile + " to " + toFile, verbosity); - - FilterSetCollection executionFilters - = new FilterSetCollection(); - if (filtering) { - executionFilters - .addFilterSet(getProject().getGlobalFilterSet()); - } - for (Enumeration filterEnum = getFilterSets().elements(); - filterEnum.hasMoreElements();) { - executionFilters - .addFilterSet((FilterSet) filterEnum.nextElement()); - } - - File srcFile = new File(fromFile); - File dstFile = new File(toFile); - preprocess(srcFile, dstFile); - } catch (Exception ioe) { - // ioe.printStackTrace(); - String msg = "Failed to copy " + fromFile + " to " + toFile - + " due to " + ioe.getMessage(); - File targetFile = new File(toFile); - if (targetFile.exists() && !targetFile.delete()) { - msg += " and I couldn't delete the corrupt " + toFile; - } - throw new BuildException(msg, ioe, getLocation()); - } - } - } - } - - } - -} diff --git a/src/main/java/org/anarres/cpp/DefaultPreprocessorListener.java b/src/main/java/org/anarres/cpp/DefaultPreprocessorListener.java deleted file mode 100644 index 4d6ee7e..0000000 --- a/src/main/java/org/anarres/cpp/DefaultPreprocessorListener.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.anarres.cpp; - -/* - * 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. - */ -import javax.annotation.Nonnegative; -import javax.annotation.Nonnull; - -import com.jogamp.gluegen.Logging; -import com.jogamp.gluegen.Logging.LoggerIf; - -/** - * A handler for preprocessor events, primarily errors and warnings. - * - * If no PreprocessorListener is installed in a Preprocessor, all - * error and warning events will throw an exception. Installing a - * listener allows more intelligent handling of these events. - */ -public class DefaultPreprocessorListener implements PreprocessorListener { - - private static final LoggerIf LOG = Logging.getLogger(DefaultPreprocessorListener.class); - - private int errors; - private int warnings; - - public DefaultPreprocessorListener() { - clear(); - } - - public void clear() { - errors = 0; - warnings = 0; - } - - @Nonnegative - public int getErrors() { - return errors; - } - - @Nonnegative - public int getWarnings() { - return warnings; - } - - protected void print(@Nonnull final String msg) { - LOG.info(msg); - } - - /** - * Handles a warning. - * - * The behaviour of this method is defined by the - * implementation. It may simply record the error message, or - * it may throw an exception. - */ - @Override - public void handleWarning(final Source source, final int line, final int column, - final String msg) - throws LexerException { - warnings++; - print(source.getName() + ":" + line + ":" + column - + ": warning: " + msg); - } - - /** - * Handles an error. - * - * The behaviour of this method is defined by the - * implementation. It may simply record the error message, or - * it may throw an exception. - */ - @Override - public void handleError(final Source source, final int line, final int column, - final String msg) - throws LexerException { - errors++; - print(source.getName() + ":" + line + ":" + column - + ": error: " + msg); - } - - @Override - public void handleSourceChange(final Source source, final SourceChangeEvent event) { - } - -} diff --git a/src/main/java/org/anarres/cpp/Feature.java b/src/main/java/org/anarres/cpp/Feature.java deleted file mode 100644 index 369d79c..0000000 --- a/src/main/java/org/anarres/cpp/Feature.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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; - -/** - * Features of the Preprocessor, which may be enabled or disabled. - */ -public enum Feature { - - /** Supports ANSI digraphs. */ - DIGRAPHS, - /** Supports ANSI trigraphs. */ - TRIGRAPHS, - /** Outputs linemarker tokens. */ - LINEMARKERS, - /** Reports tokens of type INVALID as errors. */ - CSYNTAX, - /** Preserves comments in the lexed output. */ - KEEPCOMMENTS, - /** Preserves comments in the lexed output, even when inactive. */ - KEEPALLCOMMENTS, - DEBUG, - /** Supports lexing of objective-C. */ - OBJCSYNTAX, - INCLUDENEXT, - /** Random extensions. */ - PRAGMA_ONCE -} diff --git a/src/main/java/org/anarres/cpp/FileLexerSource.java b/src/main/java/org/anarres/cpp/FileLexerSource.java deleted file mode 100644 index bdc411f..0000000 --- a/src/main/java/org/anarres/cpp/FileLexerSource.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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.File; -import java.io.FileReader; -import java.io.IOException; -import javax.annotation.Nonnull; - -/** - * A {@link Source} which lexes a file. - * - * The input is buffered. - * - * @see Source - */ -public class FileLexerSource extends LexerSource { - - private final String path; - private final File file; - - /** - * Creates a new Source for lexing the given File. - * - * Preprocessor directives are honoured within the file. - */ - public FileLexerSource(@Nonnull File file, String path) - throws IOException { - super( - new BufferedReader( - new FileReader( - file - ) - ), - true - ); - - this.file = file; - this.path = path; - } - - public FileLexerSource(@Nonnull File file) - throws IOException { - this(file, file.getPath()); - } - - public FileLexerSource(@Nonnull String path) - throws IOException { - this(new File(path), path); - } - - @Nonnull - public File getFile() { - return file; - } - - /** - * This is not necessarily the same as getFile().getPath() in case we are in a chroot. - */ - @Override - public String getPath() { - return path; - } - - @Override - public String getName() { - return getPath(); - } - - @Override - public String toString() { - return "file " + getPath(); - } -} diff --git a/src/main/java/org/anarres/cpp/FixedTokenSource.java b/src/main/java/org/anarres/cpp/FixedTokenSource.java deleted file mode 100644 index 4d9f41f..0000000 --- a/src/main/java/org/anarres/cpp/FixedTokenSource.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.IOException; -import java.util.Arrays; -import java.util.List; - -/* pp */ class FixedTokenSource extends Source { - - private static final Token EOF - = new Token(Token.EOF, "<ts-eof>"); - - private final List<Token> tokens; - private int idx; - - /* pp */ FixedTokenSource(Token... tokens) { - this.tokens = Arrays.asList(tokens); - this.idx = 0; - } - - /* pp */ FixedTokenSource(List<Token> tokens) { - this.tokens = tokens; - this.idx = 0; - } - - @Override - public Token token() - throws IOException, - LexerException { - if (idx >= tokens.size()) - return EOF; - return tokens.get(idx++); - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append("constant token stream ").append(tokens); - Source parent = getParent(); - if (parent != null) - buf.append(" in ").append(String.valueOf(parent)); - return buf.toString(); - } -} diff --git a/src/main/java/org/anarres/cpp/InputLexerSource.java b/src/main/java/org/anarres/cpp/InputLexerSource.java deleted file mode 100644 index 93cda54..0000000 --- a/src/main/java/org/anarres/cpp/InputLexerSource.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; - -/** - * 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 - public String getPath() { - return "<standard-input>"; - } - - @Override - public String getName() { - return "standard input"; - } - - @Override - public String toString() { - return String.valueOf(getPath()); - } -} diff --git a/src/main/java/org/anarres/cpp/InternalException.java b/src/main/java/org/anarres/cpp/InternalException.java deleted file mode 100644 index fc3b650..0000000 --- a/src/main/java/org/anarres/cpp/InternalException.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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; - -/** - * An internal exception. - * - * This exception is thrown when an internal state violation is - * encountered. This should never happen. If it ever happens, please - * report it as a bug. - */ -public class InternalException extends RuntimeException { - - public InternalException(String msg) { - super(msg); - } -} diff --git a/src/main/java/org/anarres/cpp/JavaFileSystem.java b/src/main/java/org/anarres/cpp/JavaFileSystem.java deleted file mode 100644 index a60271d..0000000 --- a/src/main/java/org/anarres/cpp/JavaFileSystem.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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.File; -import java.io.IOException; - -/** - * A virtual filesystem implementation using java.io. - */ -public class JavaFileSystem implements VirtualFileSystem { - - @Override - public VirtualFile getFile(String path) { - return new JavaFile(path); - } - - @Override - public VirtualFile getFile(String dir, String name) { - return new JavaFile(dir, name); - } - - private class JavaFile extends File implements VirtualFile { - - public JavaFile(String path) { - super(path); - } - - public JavaFile(String dir, String name) { - super(dir, name); - } - - /* private */ - public JavaFile(File dir, String name) { - super(dir, name); - } - - /* - @Override - public String getPath() { - return getCanonicalPath(); - } - */ - @Override - public JavaFile getParentFile() { - String parent = getParent(); - if (parent != null) - return new JavaFile(parent); - File absolute = getAbsoluteFile(); - parent = absolute.getParent(); - /* - if (parent == null) - return null; - */ - return new JavaFile(parent); - } - - @Override - public JavaFile getChildFile(String name) { - return new JavaFile(this, name); - } - - @Override - public Source getSource() throws IOException { - return new FileLexerSource(this); - } - - } - -} diff --git a/src/main/java/org/anarres/cpp/JoinReader.java b/src/main/java/org/anarres/cpp/JoinReader.java deleted file mode 100644 index c39ee79..0000000 --- a/src/main/java/org/anarres/cpp/JoinReader.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * 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.Closeable; -import java.io.IOException; -import java.io.Reader; - -/* pp */ class JoinReader /* extends Reader */ implements Closeable { - - private final Reader in; - - private PreprocessorListener listener; - private LexerSource source; - private boolean trigraphs; - private boolean warnings; - - private int newlines; - private boolean flushnl; - private int[] unget; - private int uptr; - - public JoinReader(Reader in, boolean trigraphs) { - this.in = in; - this.trigraphs = trigraphs; - this.newlines = 0; - this.flushnl = false; - this.unget = new int[2]; - this.uptr = 0; - } - - public JoinReader(Reader in) { - this(in, false); - } - - public void setTrigraphs(boolean enable, boolean warnings) { - this.trigraphs = enable; - this.warnings = warnings; - } - - /* pp */ void init(Preprocessor pp, LexerSource s) { - this.listener = pp.getListener(); - this.source = s; - setTrigraphs(pp.getFeature(Feature.TRIGRAPHS), - pp.getWarning(Warning.TRIGRAPHS)); - } - - private int __read() throws IOException { - if (uptr > 0) - return unget[--uptr]; - return in.read(); - } - - private void _unread(int c) { - if (c != -1) - unget[uptr++] = c; - assert uptr <= unget.length : - "JoinReader ungets too many characters"; - } - - protected void warning(String msg) - throws LexerException { - if (source != null) - source.warning(msg); - else - throw new LexerException(msg); - } - - private char trigraph(char raw, char repl) - throws IOException, LexerException { - if (trigraphs) { - if (warnings) - warning("trigraph ??" + raw + " converted to " + repl); - return repl; - } else { - if (warnings) - warning("trigraph ??" + raw + " ignored"); - _unread(raw); - _unread('?'); - return '?'; - } - } - - private int _read() - throws IOException, LexerException { - int c = __read(); - if (c == '?' && (trigraphs || warnings)) { - int d = __read(); - if (d == '?') { - int e = __read(); - switch (e) { - case '(': - return trigraph('(', '['); - case ')': - return trigraph(')', ']'); - case '<': - return trigraph('<', '{'); - case '>': - return trigraph('>', '}'); - case '=': - return trigraph('=', '#'); - case '/': - return trigraph('/', '\\'); - case '\'': - return trigraph('\'', '^'); - case '!': - return trigraph('!', '|'); - case '-': - return trigraph('-', '~'); - } - _unread(e); - } - _unread(d); - } - return c; - } - - public int read() - throws IOException, LexerException { - if (flushnl) { - if (newlines > 0) { - newlines--; - return '\n'; - } - flushnl = false; - } - - for (;;) { - int c = _read(); - switch (c) { - case '\\': - int d = _read(); - switch (d) { - case '\n': - newlines++; - continue; - case '\r': - newlines++; - int e = _read(); - if (e != '\n') - _unread(e); - continue; - default: - _unread(d); - return c; - } - case '\r': - case '\n': - case '\u2028': - case '\u2029': - case '\u000B': - case '\u000C': - case '\u0085': - flushnl = true; - return c; - case -1: - if (newlines > 0) { - newlines--; - return '\n'; - } - default: - return c; - } - } - } - - public int read(char cbuf[], int off, int len) - throws IOException, LexerException { - for (int i = 0; i < len; i++) { - int ch = read(); - if (ch == -1) - return i; - cbuf[off + i] = (char) ch; - } - return len; - } - - @Override - public void close() - throws IOException { - in.close(); - } - - @Override - public String toString() { - return "JoinReader(nl=" + newlines + ")"; - } - - /* - public static void main(String[] args) throws IOException { - FileReader f = new FileReader(new File(args[0])); - BufferedReader b = new BufferedReader(f); - JoinReader r = new JoinReader(b); - BufferedWriter w = new BufferedWriter( - new java.io.OutputStreamWriter(System.out) - ); - int c; - while ((c = r.read()) != -1) { - w.write((char)c); - } - w.close(); - } - */ -} diff --git a/src/main/java/org/anarres/cpp/LexerException.java b/src/main/java/org/anarres/cpp/LexerException.java deleted file mode 100644 index d4b2e9c..0000000 --- a/src/main/java/org/anarres/cpp/LexerException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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; - -/** - * A preprocessor exception. - * - * Note to users: I don't really like the name of this class. S. - */ -public class LexerException extends Exception { - - public LexerException(String msg) { - super(msg); - } - - public LexerException(Throwable cause) { - super(cause); - } -} diff --git a/src/main/java/org/anarres/cpp/LexerSource.java b/src/main/java/org/anarres/cpp/LexerSource.java deleted file mode 100644 index 82d76b6..0000000 --- a/src/main/java/org/anarres/cpp/LexerSource.java +++ /dev/null @@ -1,985 +0,0 @@ -/* - * 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.IOException; -import java.io.Reader; -import javax.annotation.Nonnull; -import static org.anarres.cpp.Token.*; - -/** Does not handle digraphs. */ -public class LexerSource extends Source { - - private static final boolean DEBUG = false; - - private JoinReader reader; - private final boolean ppvalid; - private boolean bol; - private boolean include; - - private boolean digraphs; - - /* Unread. */ - private int u0, u1; - private int ucount; - - private int line; - private int column; - private int lastcolumn; - private boolean cr; - - /* ppvalid is: - * false in StringLexerSource, - * true in FileLexerSource */ - public LexerSource(Reader r, boolean ppvalid) { - this.reader = new JoinReader(r); - this.ppvalid = ppvalid; - this.bol = true; - this.include = false; - - this.digraphs = true; - - this.ucount = 0; - - this.line = 1; - this.column = 0; - this.lastcolumn = -1; - this.cr = false; - } - - @Override - /* pp */ void init(Preprocessor pp) { - super.init(pp); - this.digraphs = pp.getFeature(Feature.DIGRAPHS); - this.reader.init(pp, this); - } - - @Override - public int getLine() { - return line; - } - - @Override - public int getColumn() { - return column; - } - - @Override - /* pp */ boolean isNumbered() { - return true; - } - - /* Error handling. */ - private void _error(String msg, boolean error) - throws LexerException { - int _l = line; - int _c = column; - if (_c == 0) { - _c = lastcolumn; - _l--; - } else { - _c--; - } - if (error) - super.error(_l, _c, msg); - else - super.warning(_l, _c, msg); - } - - /* Allow JoinReader to call this. */ - /* pp */ final void error(String msg) - throws LexerException { - _error(msg, true); - } - - /* Allow JoinReader to call this. */ - /* pp */ final void warning(String msg) - throws LexerException { - _error(msg, false); - } - - /* A flag for string handling. */ - - /* pp */ void setInclude(boolean b) { - this.include = b; - } - - /* - * private boolean _isLineSeparator(int c) { - * return Character.getType(c) == Character.LINE_SEPARATOR - * || c == -1; - * } - */ - - /* XXX Move to JoinReader and canonicalise newlines. */ - private static boolean isLineSeparator(int c) { - switch ((char) c) { - case '\r': - case '\n': - case '\u2028': - case '\u2029': - case '\u000B': - case '\u000C': - case '\u0085': - return true; - default: - return (c == -1); - } - } - - private int read() - throws IOException, - LexerException { - int c; - assert ucount <= 2 : "Illegal ucount: " + ucount; - switch (ucount) { - case 2: - ucount = 1; - c = u1; - break; - case 1: - ucount = 0; - c = u0; - break; - default: - if (reader == null) - c = -1; - else - c = reader.read(); - break; - } - - switch (c) { - case '\r': - cr = true; - line++; - lastcolumn = column; - column = 0; - break; - case '\n': - if (cr) { - cr = false; - break; - } - /* fallthrough */ - case '\u2028': - case '\u2029': - case '\u000B': - case '\u000C': - case '\u0085': - cr = false; - line++; - lastcolumn = column; - column = 0; - break; - case -1: - cr = false; - break; - default: - cr = false; - column++; - break; - } - - /* - * if (isLineSeparator(c)) { - * line++; - * lastcolumn = column; - * column = 0; - * } - * else { - * column++; - * } - */ - return c; - } - - /* 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--; - column = lastcolumn; - cr = false; - } else { - column--; - } - switch (ucount) { - case 0: - u0 = c; - ucount = 1; - break; - case 1: - u1 = c; - ucount = 2; - break; - default: - throw new IllegalStateException( - "Cannot unget another character!" - ); - } - // reader.unread(c); - } - } - - /* Consumes the rest of the current line into an invalid. */ - @Nonnull - private Token invalid(StringBuilder text, String reason) - throws IOException, - LexerException { - int d = read(); - while (!isLineSeparator(d)) { - text.append((char) d); - d = read(); - } - unread(d); - return new Token(INVALID, text.toString(), reason); - } - - @Nonnull - private Token ccomment() - throws IOException, - LexerException { - StringBuilder text = new StringBuilder("/*"); - int d; - do { - do { - d = read(); - if (d == -1) - return new Token(INVALID, text.toString(), - "Unterminated comment"); - text.append((char) d); - } while (d != '*'); - do { - d = read(); - if (d == -1) - return new Token(INVALID, text.toString(), - "Unterminated comment"); - text.append((char) d); - } while (d == '*'); - } while (d != '/'); - return new Token(CCOMMENT, text.toString()); - } - - @Nonnull - private Token cppcomment() - throws IOException, - LexerException { - StringBuilder text = new StringBuilder("//"); - int d = read(); - while (!isLineSeparator(d)) { - text.append((char) d); - d = read(); - } - unread(d); - return new Token(CPPCOMMENT, text.toString()); - } - - private int escape(StringBuilder text) - throws IOException, - LexerException { - int d = read(); - switch (d) { - case 'a': - text.append('a'); - return 0x07; - case 'b': - text.append('b'); - return '\b'; - case 'f': - text.append('f'); - return '\f'; - case 'n': - text.append('n'); - return '\n'; - case 'r': - text.append('r'); - return '\r'; - case 't': - text.append('t'); - return '\t'; - case 'v': - text.append('v'); - return 0x0b; - case '\\': - text.append('\\'); - return '\\'; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - int len = 0; - int val = 0; - do { - val = (val << 3) + Character.digit(d, 8); - text.append((char) d); - d = read(); - } while (++len < 3 && Character.digit(d, 8) != -1); - unread(d); - return val; - - case 'x': - text.append((char) d); - len = 0; - val = 0; - while (len++ < 2) { - d = read(); - if (Character.digit(d, 16) == -1) { - unread(d); - break; - } - val = (val << 4) + Character.digit(d, 16); - text.append((char) d); - } - return val; - - /* Exclude two cases from the warning. */ - case '"': - text.append('"'); - return '"'; - case '\'': - text.append('\''); - return '\''; - - default: - warning("Unnecessary escape character " + (char) d); - text.append((char) d); - return d; - } - } - - @Nonnull - private Token character() - throws IOException, - LexerException { - StringBuilder text = new StringBuilder("'"); - int d = read(); - if (d == '\\') { - text.append('\\'); - d = escape(text); - } else if (isLineSeparator(d)) { - unread(d); - return new Token(INVALID, text.toString(), - "Unterminated character literal"); - } else if (d == '\'') { - text.append('\''); - return new Token(INVALID, text.toString(), - "Empty character literal"); - } else if (!Character.isDefined(d)) { - text.append('?'); - return invalid(text, "Illegal unicode character literal"); - } else { - text.append((char) d); - } - - int e = read(); - if (e != '\'') { - // error("Illegal character constant"); - /* We consume up to the next ' or the rest of the line. */ - for (;;) { - if (isLineSeparator(e)) { - unread(e); - break; - } - text.append((char) e); - if (e == '\'') - break; - e = read(); - } - return new Token(INVALID, text.toString(), - "Illegal character constant " + text); - } - text.append('\''); - /* XXX It this a bad cast? */ - return new Token(CHARACTER, - text.toString(), Character.valueOf((char) d)); - } - - @Nonnull - private Token string(char open, char close) - throws IOException, - LexerException { - StringBuilder text = new StringBuilder(); - text.append(open); - - StringBuilder buf = new StringBuilder(); - - for (;;) { - int c = read(); - if (c == close) { - break; - } else if (c == '\\') { - text.append('\\'); - if (!include) { - char d = (char) escape(text); - buf.append(d); - } - } else if (c == -1) { - unread(c); - // error("End of file in string literal after " + buf); - return new Token(INVALID, text.toString(), - "End of file in string literal after " + buf); - } else if (isLineSeparator(c)) { - unread(c); - // error("Unterminated string literal after " + buf); - return new Token(INVALID, text.toString(), - "Unterminated string literal after " + buf); - } else { - text.append((char) c); - buf.append((char) c); - } - } - text.append(close); - switch (close) { - case '"': - return new Token(STRING, - text.toString(), buf.toString()); - case '>': - return new Token(HEADER, - text.toString(), buf.toString()); - case '\'': - if (buf.length() == 1) - return new Token(CHARACTER, - text.toString(), buf.toString()); - return new Token(SQSTRING, - text.toString(), buf.toString()); - default: - throw new IllegalStateException( - "Unknown closing character " + String.valueOf(close)); - } - } - - @Nonnull - private Token _number_suffix(StringBuilder text, NumericValue value, int d) - throws IOException, - LexerException { - int flags = 0; // U, I, L, LL, F, D, MSB - for (;;) { - if (d == 'U' || d == 'u') { - if ((flags & NumericValue.F_UNSIGNED) != 0) - warning("Duplicate unsigned suffix " + d); - flags |= NumericValue.F_UNSIGNED; - text.append((char) d); - d = read(); - } else if (d == 'L' || d == 'l') { - if ((flags & NumericValue.FF_SIZE) != 0) - warning("Multiple length suffixes after " + text); - text.append((char) d); - int e = read(); - if (e == d) { // Case must match. Ll is Welsh. - flags |= NumericValue.F_LONGLONG; - text.append((char) e); - d = read(); - } else { - flags |= NumericValue.F_LONG; - d = e; - } - } else if (d == 'I' || d == 'i') { - if ((flags & NumericValue.FF_SIZE) != 0) - warning("Multiple length suffixes after " + text); - flags |= NumericValue.F_INT; - text.append((char) d); - d = read(); - } else if (d == 'F' || d == 'f') { - if ((flags & NumericValue.FF_SIZE) != 0) - warning("Multiple length suffixes after " + text); - flags |= NumericValue.F_FLOAT; - text.append((char) d); - d = read(); - } else if (d == 'D' || d == 'd') { - if ((flags & NumericValue.FF_SIZE) != 0) - warning("Multiple length suffixes after " + text); - flags |= NumericValue.F_DOUBLE; - text.append((char) d); - d = read(); - } - else if (Character.isUnicodeIdentifierPart(d)) { - String reason = "Invalid suffix \"" + (char) d + "\" on numeric constant"; - // We've encountered something initially identified as a number. - // Read in the rest of this token as an identifer but return it as an invalid. - while (Character.isUnicodeIdentifierPart(d)) { - text.append((char) d); - d = read(); - } - unread(d); - return new Token(INVALID, text.toString(), reason); - } else { - unread(d); - value.setFlags(flags); - return new Token(NUMBER, - text.toString(), value); - } - } - } - - /* Either a decimal part, or a hex exponent. */ - @Nonnull - private String _number_part(StringBuilder text, int base, boolean sign) - throws IOException, - LexerException { - StringBuilder part = new StringBuilder(); - int d = read(); - if (sign && d == '-') { - text.append((char) d); - part.append((char) d); - d = read(); - } - while (Character.digit(d, base) != -1) { - text.append((char) d); - part.append((char) d); - d = read(); - } - unread(d); - return part.toString(); - } - - /* We do not know whether know the first digit is valid. */ - @Nonnull - private Token number_hex(char x) - throws IOException, - LexerException { - StringBuilder text = new StringBuilder("0"); - text.append(x); - String integer = _number_part(text, 16, false); - NumericValue value = new NumericValue(16, integer); - int d = read(); - if (d == '.') { - text.append((char) d); - String fraction = _number_part(text, 16, false); - value.setFractionalPart(fraction); - d = read(); - } - if (d == 'P' || d == 'p') { - text.append((char) d); - String exponent = _number_part(text, 10, true); - value.setExponent(2, exponent); - d = read(); - } - // XXX Make sure it's got enough parts - return _number_suffix(text, value, d); - } - - private static boolean is_octal(@Nonnull String text) { - if (!text.startsWith("0")) - return false; - for (int i = 0; i < text.length(); i++) - if (Character.digit(text.charAt(i), 8) == -1) - return false; - return true; - } - - /* We know we have at least one valid digit, but empty is not - * fine. */ - @Nonnull - private Token number_decimal() - throws IOException, - LexerException { - StringBuilder text = new StringBuilder(); - String integer = _number_part(text, 10, false); - String fraction = null; - String exponent = null; - int d = read(); - if (d == '.') { - text.append((char) d); - fraction = _number_part(text, 10, false); - d = read(); - } - if (d == 'E' || d == 'e') { - text.append((char) d); - exponent = _number_part(text, 10, true); - d = read(); - } - int base = 10; - if (fraction == null && exponent == null && integer.startsWith("0")) { - if (!is_octal(integer)) - warning("Decimal constant starts with 0, but not octal: " + integer); - else - base = 8; - } - NumericValue value = new NumericValue(base, integer); - if (fraction != null) - value.setFractionalPart(fraction); - if (exponent != null) - value.setExponent(10, exponent); - // XXX Make sure it's got enough parts - return _number_suffix(text, value, d); - } - - /** - * Section 6.4.4.1 of C99 - * - * (Not pasted here, but says that the initial negation is a separate token.) - * - * Section 6.4.4.2 of C99 - * - * A floating constant has a significand part that may be followed - * by an exponent part and a suffix that specifies its type. The - * components of the significand part may include a digit sequence - * representing the whole-number part, followed by a period (.), - * followed by a digit sequence representing the fraction part. - * - * The components of the exponent part are an e, E, p, or P - * followed by an exponent consisting of an optionally signed digit - * sequence. Either the whole-number part or the fraction part has to - * be present; for decimal floating constants, either the period or - * the exponent part has to be present. - * - * The significand part is interpreted as a (decimal or hexadecimal) - * rational number; the digit sequence in the exponent part is - * interpreted as a decimal integer. For decimal floating constants, - * the exponent indicates the power of 10 by which the significand - * part is to be scaled. For hexadecimal floating constants, the - * exponent indicates the power of 2 by which the significand part is - * to be scaled. - * - * For decimal floating constants, and also for hexadecimal - * floating constants when FLT_RADIX is not a power of 2, the result - * is either the nearest representable value, or the larger or smaller - * representable value immediately adjacent to the nearest representable - * value, chosen in an implementation-defined manner. For hexadecimal - * floating constants when FLT_RADIX is a power of 2, the result is - * correctly rounded. - */ - @Nonnull - private Token number() - throws IOException, - LexerException { - Token tok; - int c = read(); - if (c == '0') { - int d = read(); - if (d == 'x' || d == 'X') { - tok = number_hex((char) d); - } else { - unread(d); - unread(c); - tok = number_decimal(); - } - } else if (Character.isDigit(c) || c == '.') { - unread(c); - tok = number_decimal(); - } else { - throw new LexerException("Asked to parse something as a number which isn't: " + (char) c); - } - return tok; - } - - @Nonnull - private Token identifier(int c) - throws IOException, - LexerException { - StringBuilder text = new StringBuilder(); - int d; - text.append((char) c); - for (;;) { - d = read(); - if (Character.isIdentifierIgnorable(d)) - ; else if (Character.isJavaIdentifierPart(d)) - text.append((char) d); - else - break; - } - unread(d); - return new Token(IDENTIFIER, text.toString()); - } - - @Nonnull - private Token whitespace(int c) - throws IOException, - LexerException { - StringBuilder text = new StringBuilder(); - int d; - text.append((char) c); - for (;;) { - d = read(); - if (ppvalid && isLineSeparator(d)) /* XXX Ugly. */ - - break; - if (Character.isWhitespace(d)) - text.append((char) d); - else - break; - } - unread(d); - return new Token(WHITESPACE, text.toString()); - } - - /* No token processed by cond() contains a newline. */ - @Nonnull - private Token cond(char c, int yes, int no) - throws IOException, - LexerException { - int d = read(); - if (c == d) - return new Token(yes); - unread(d); - return new Token(no); - } - - @Override - public Token token() - throws IOException, - LexerException { - Token tok = null; - - int _l = line; - int _c = column; - - int c = read(); - int d; - - switch (c) { - case '\n': - if (ppvalid) { - bol = true; - if (include) { - tok = new Token(NL, _l, _c, "\n"); - } else { - int nls = 0; - do { - nls++; - d = read(); - } while (d == '\n'); - unread(d); - char[] text = new char[nls]; - for (int i = 0; i < text.length; i++) - text[i] = '\n'; - // Skip the bol = false below. - tok = new Token(NL, _l, _c, new String(text)); - } - if (DEBUG) - System.out.println("lx: Returning NL: " + tok); - return tok; - } - /* Let it be handled as whitespace. */ - break; - - case '!': - tok = cond('=', NE, '!'); - break; - - case '#': - if (bol) - tok = new Token(HASH); - else - tok = cond('#', PASTE, '#'); - break; - - case '+': - d = read(); - if (d == '+') - tok = new Token(INC); - else if (d == '=') - tok = new Token(PLUS_EQ); - else - unread(d); - break; - case '-': - d = read(); - if (d == '-') - tok = new Token(DEC); - else if (d == '=') - tok = new Token(SUB_EQ); - else if (d == '>') - tok = new Token(ARROW); - else - unread(d); - break; - - case '*': - tok = cond('=', MULT_EQ, '*'); - break; - case '/': - d = read(); - if (d == '*') - tok = ccomment(); - else if (d == '/') - tok = cppcomment(); - else if (d == '=') - tok = new Token(DIV_EQ); - else - unread(d); - break; - - case '%': - d = read(); - if (d == '=') - tok = new Token(MOD_EQ); - else if (digraphs && d == '>') - tok = new Token('}'); // digraph - else if (digraphs && d == ':') - PASTE: - { - d = read(); - if (d != '%') { - unread(d); - tok = new Token('#'); // digraph - break PASTE; - } - d = read(); - if (d != ':') { - unread(d); // Unread 2 chars here. - unread('%'); - tok = new Token('#'); // digraph - break PASTE; - } - tok = new Token(PASTE); // digraph - } - else - unread(d); - break; - - case ':': - /* :: */ - d = read(); - if (digraphs && d == '>') - tok = new Token(']'); // digraph - else - unread(d); - break; - - case '<': - if (include) { - tok = string('<', '>'); - } else { - d = read(); - if (d == '=') - tok = new Token(LE); - else if (d == '<') - tok = cond('=', LSH_EQ, LSH); - else if (digraphs && d == ':') - tok = new Token('['); // digraph - else if (digraphs && d == '%') - tok = new Token('{'); // digraph - else - unread(d); - } - break; - - case '=': - tok = cond('=', EQ, '='); - break; - - case '>': - d = read(); - if (d == '=') - tok = new Token(GE); - else if (d == '>') - tok = cond('=', RSH_EQ, RSH); - else - unread(d); - break; - - case '^': - tok = cond('=', XOR_EQ, '^'); - break; - - case '|': - d = read(); - if (d == '=') - tok = new Token(OR_EQ); - else if (d == '|') - tok = cond('=', LOR_EQ, LOR); - else - unread(d); - break; - case '&': - d = read(); - if (d == '&') - tok = cond('=', LAND_EQ, LAND); - else if (d == '=') - tok = new Token(AND_EQ); - else - unread(d); - break; - - case '.': - d = read(); - if (d == '.') - tok = cond('.', ELLIPSIS, RANGE); - else - unread(d); - if (Character.isDigit(d)) { - unread('.'); - tok = number(); - } - /* XXX decimal fraction */ - break; - - case '\'': - tok = string('\'', '\''); - break; - - case '"': - tok = string('"', '"'); - break; - - case -1: - close(); - tok = new Token(EOF, _l, _c, "<eof>"); - break; - } - - if (tok == null) { - if (Character.isWhitespace(c)) { - tok = whitespace(c); - } else if (Character.isDigit(c)) { - unread(c); - tok = number(); - } else if (Character.isJavaIdentifierStart(c)) { - tok = identifier(c); - } else { - tok = new Token(c); - } - } - - if (bol) { - switch (tok.getType()) { - case WHITESPACE: - case CCOMMENT: - break; - default: - bol = false; - break; - } - } - - tok.setLocation(_l, _c); - if (DEBUG) - System.out.println("lx: Returning " + tok); - // (new Exception("here")).printStackTrace(System.out); - return tok; - } - - @Override - public void close() - throws IOException { - if (reader != null) { - reader.close(); - reader = null; - } - super.close(); - } - -} diff --git a/src/main/java/org/anarres/cpp/Macro.java b/src/main/java/org/anarres/cpp/Macro.java deleted file mode 100644 index ce00930..0000000 --- a/src/main/java/org/anarres/cpp/Macro.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * A macro object. - * - * This encapsulates a name, an argument count, and a token stream - * for replacement. The replacement token stream may contain the - * extra tokens {@link Token#M_ARG} and {@link Token#M_STRING}. - */ -public class Macro { - - private Source source; - private final String name; - /* It's an explicit decision to keep these around here. We don't - * need to; the argument token type is M_ARG and the value - * is the index. The strings themselves are only used in - * stringification of the macro, for debugging. */ - private List<String> args; - private boolean variadic; - private List<Token> tokens; - - public Macro(final Source source, final String name) { - this.source = source; - this.name = name; - this.args = null; - this.variadic = false; - this.tokens = new ArrayList<Token>(); - } - - public Macro(final String name) { - this(null, name); - } - - /** - * Sets the Source from which this macro was parsed. - */ - public void setSource(final Source s) { - this.source = s; - } - - /** - * Returns the Source from which this macro was parsed. - * - * This method may return null if the macro was not parsed - * from a regular file. - */ - public Source getSource() { - return source; - } - - /** - * Returns the name of this macro. - */ - public String getName() { - return name; - } - - /** - * Sets the arguments to this macro. - */ - public void setArgs(final List<String> args) { - this.args = args; - } - - /** - * Returns true if this is a function-like macro. - */ - public boolean isFunctionLike() { - return args != null; - } - - /** - * Returns the number of arguments to this macro. - */ - public int getArgs() { - return args.size(); - } - - /** - * Sets the variadic flag on this Macro. - */ - public void setVariadic(final boolean b) { - this.variadic = b; - } - - /** - * Returns true if this is a variadic function-like macro. - */ - public boolean isVariadic() { - return variadic; - } - - /** - * Adds a token to the expansion of this macro. - */ - public void addToken(final Token tok) { - this.tokens.add(tok); - } - - /** - * Adds a "paste" operator to the expansion of this macro. - * - * A paste operator causes the next token added to be pasted - * to the previous token when the macro is expanded. - * It is an error for a macro to end with a paste token. - */ - public void addPaste(final Token tok) { - /* - * Given: tok0 ## tok1 - * We generate: M_PASTE, tok0, tok1 - * This extends as per a stack language: - * tok0 ## tok1 ## tok2 -> - * M_PASTE, tok0, M_PASTE, tok1, tok2 - */ - this.tokens.add(tokens.size() - 1, tok); - } - - /* pp */ List<Token> getTokens() { - return tokens; - } - /* pp */ void setTokens(final List<Token> tokens) { - this.tokens = tokens; - } - - /* Paste tokens are inserted before the first of the two pasted - * tokens, so it's a kind of bytecode notation. This method - * swaps them around again. We know that there will never be two - * sequential paste tokens, so a boolean is sufficient. */ - public String getText() { - final StringBuilder buf = new StringBuilder(); - boolean paste = false; - for (final Token tok : tokens) { - if (tok.getType() == Token.M_PASTE) { - assert paste == false : "Two sequential pastes."; - paste = true; - continue; - } else { - buf.append(tok.getText()); - } - if (paste) { - buf.append(" #" + "# "); - paste = false; - } - // buf.append(tokens.get(i)); - } - return buf.toString(); - } - - @Override - public String toString() { - final StringBuilder buf = new StringBuilder(name); - if (args != null) { - buf.append('('); - final Iterator<String> it = args.iterator(); - while (it.hasNext()) { - buf.append(it.next()); - if (it.hasNext()) - buf.append(", "); - else if (isVariadic()) - buf.append("..."); - } - buf.append(')'); - } - if (!tokens.isEmpty()) { - buf.append(" => ").append(getText()); - } - return buf.toString(); - } - -} diff --git a/src/main/java/org/anarres/cpp/MacroTokenSource.java b/src/main/java/org/anarres/cpp/MacroTokenSource.java deleted file mode 100644 index b512c3d..0000000 --- a/src/main/java/org/anarres/cpp/MacroTokenSource.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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.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 - * in any inactive context. */ -/* pp */ class MacroTokenSource extends Source { - - private final Macro macro; - private final Iterator<Token> tokens; /* Pointer into the macro. */ - - private final List<Argument> args; /* { unexpanded, expanded } */ - - private Iterator<Token> arg; /* "current expansion" */ - - /* pp */ MacroTokenSource(@Nonnull Macro m, @Nonnull List<Argument> args) { - this.macro = m; - this.tokens = m.getTokens().iterator(); - this.args = args; - this.arg = null; - } - - @Override - /* pp */ boolean isExpanding(@Nonnull Macro m) { - /* When we are expanding an arg, 'this' macro is not - * being expanded, and thus we may re-expand it. */ - if (/* XXX this.arg == null && */this.macro == m) - return true; - return super.isExpanding(m); - } - - /* XXX Called from Preprocessor [ugly]. */ - /* 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) { - case '\\': - buf.append("\\\\"); - break; - case '"': - buf.append("\\\""); - break; - case '\n': - buf.append("\\n"); - break; - case '\r': - buf.append("\\r"); - break; - default: - buf.append(c); - } - } - } - - private void concat(@Nonnull StringBuilder buf, @Nonnull Argument arg) { - for (Token tok : arg) { - buf.append(tok.getText()); - } - } - - @Nonnull - private Token stringify(@Nonnull Token pos, @Nonnull Argument arg) { - StringBuilder buf = new StringBuilder(); - concat(buf, arg); - // System.out.println("Concat: " + arg + " -> " + buf); - StringBuilder str = new StringBuilder("\""); - escape(str, buf); - str.append("\""); - // System.out.println("Escape: " + buf + " -> " + str); - return new Token(STRING, - pos.getLine(), pos.getColumn(), - str.toString(), buf.toString()); - } - - - /* At this point, we have consumed the first M_PASTE. - * @see Macro#addPaste(Token) */ - private void paste(@Nonnull Token ptok) - throws IOException, - LexerException { - StringBuilder buf = new StringBuilder(); - // Token err = null; - /* We know here that arg is null or expired, - * since we cannot paste an expanded arg. */ - - int count = 2; - for (int i = 0; i < count; i++) { - if (!tokens.hasNext()) { - /* XXX This one really should throw. */ - error(ptok.getLine(), ptok.getColumn(), - "Paste at end of expansion"); - buf.append(' ').append(ptok.getText()); - break; - } - Token tok = tokens.next(); - // System.out.println("Paste " + tok); - switch (tok.getType()) { - case M_PASTE: - /* One extra to paste, plus one because the - * paste token didn't count. */ - count += 2; - ptok = tok; - break; - case M_ARG: - int idx = ((Integer) tok.getValue()).intValue(); - concat(buf, args.get(idx)); - break; - /* XXX Test this. */ - case CCOMMENT: - case CPPCOMMENT: - break; - default: - buf.append(tok.getText()); - break; - } - } - - /* Push and re-lex. */ - /* - StringBuilder src = new StringBuilder(); - escape(src, buf); - StringLexerSource sl = new StringLexerSource(src.toString()); - */ - StringLexerSource sl = new StringLexerSource(buf.toString()); - - /* XXX Check that concatenation produces a valid token. */ - arg = new SourceIterator(sl); - } - - @Override - public Token token() - throws IOException, - LexerException { - for (;;) { - /* Deal with lexed tokens first. */ - - if (arg != null) { - if (arg.hasNext()) { - Token tok = arg.next(); - /* XXX PASTE -> INVALID. */ - assert tok.getType() != M_PASTE : - "Unexpected paste token"; - return tok; - } - arg = null; - } - - if (!tokens.hasNext()) - return new Token(EOF, -1, -1, ""); /* End of macro. */ - - Token tok = tokens.next(); - int idx; - switch (tok.getType()) { - case M_STRING: - /* Use the nonexpanded arg. */ - idx = ((Integer) tok.getValue()).intValue(); - return stringify(tok, args.get(idx)); - case M_ARG: - /* Expand the arg. */ - idx = ((Integer) tok.getValue()).intValue(); - // System.out.println("Pushing arg " + args.get(idx)); - arg = args.get(idx).expansion(); - break; - case M_PASTE: - paste(tok); - break; - default: - return tok; - } - } /* for */ - - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append("expansion of ").append(macro.getName()); - Source parent = getParent(); - if (parent != null) - buf.append(" in ").append(String.valueOf(parent)); - return buf.toString(); - } -} diff --git a/src/main/java/org/anarres/cpp/Main.java b/src/main/java/org/anarres/cpp/Main.java deleted file mode 100644 index acf2436..0000000 --- a/src/main/java/org/anarres/cpp/Main.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * 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.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 org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * (Currently a simple test class). - */ -public class Main { - - private static final Logger LOG = LoggerFactory.getLogger(Main.class); - - @Nonnull - private static CharSequence getWarnings() { - StringBuilder buf = new StringBuilder(); - for (Warning w : Warning.values()) { - if (buf.length() > 0) - buf.append(", "); - String name = w.name().toLowerCase(); - buf.append(name.replace('_', '-')); - } - return buf; - } - - public static void main(String[] args) throws Exception { - (new Main()).run(args); - } - - public void run(String[] args) throws Exception { - - 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 (" + BuildMetadata.getInstance().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); - pp.addFeature(Feature.TRIGRAPHS); - pp.addFeature(Feature.LINEMARKERS); - pp.addWarning(Warning.IMPORT); - pp.setListener(new DefaultPreprocessorListener()); - pp.addMacro("__JCPP__"); - pp.getSystemIncludePath().add("/usr/local/include"); - pp.getSystemIncludePath().add("/usr/include"); - pp.getFrameworksPath().add("/System/Library/Frameworks"); - pp.getFrameworksPath().add("/Library/Frameworks"); - pp.getFrameworksPath().add("/Local/Library/Frameworks"); - - 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")); - - 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.DEBUG)) { - LOG.info("#" + "include \"...\" search starts here:"); - for (String dir : pp.getQuoteIncludePath()) - LOG.info(" " + dir); - LOG.info("#" + "include <...> search starts here:"); - for (String dir : pp.getSystemIncludePath()) - LOG.info(" " + dir); - LOG.info("End of search list."); - } - - try { - for (;;) { - Token tok = pp.token(); - if (tok == null) - break; - if (tok.getType() == Token.EOF) - break; - System.out.print(tok.getText()); - } - } catch (Exception e) { - StringBuilder buf = new StringBuilder("Preprocessor failed:\n"); - Source s = pp.getSource(); - while (s != null) { - buf.append(" -> ").append(s).append("\n"); - s = s.getParent(); - } - LOG.error(buf.toString(), e); - } - - } - - private static void version(@Nonnull PrintStream out) { - BuildMetadata metadata = BuildMetadata.getInstance(); - out.println("Anarres Java C Preprocessor version " + metadata.getVersion() + " change-id " + metadata.getChangeId()); - 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."); - } -} diff --git a/src/main/java/org/anarres/cpp/NumericValue.java b/src/main/java/org/anarres/cpp/NumericValue.java deleted file mode 100644 index e4235d3..0000000 --- a/src/main/java/org/anarres/cpp/NumericValue.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * 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.math.BigDecimal; -import java.math.BigInteger; -import javax.annotation.CheckForNull; -import javax.annotation.CheckForSigned; -import javax.annotation.Nonnegative; -import javax.annotation.Nonnull; - -public class NumericValue extends Number { - - public static final int F_UNSIGNED = 1; - public static final int F_INT = 2; - public static final int F_LONG = 4; - public static final int F_LONGLONG = 8; - public static final int F_FLOAT = 16; - public static final int F_DOUBLE = 32; - - public static final int FF_SIZE = F_INT | F_LONG | F_LONGLONG | F_FLOAT | F_DOUBLE; - - private final int base; - private final String integer; - private String fraction; - private int expbase = 0; - private String exponent; - private int flags; - - public NumericValue(int base, String integer) { - this.base = base; - this.integer = integer; - } - - @Nonnegative - public int getBase() { - return base; - } - - @Nonnull - public String getIntegerPart() { - return integer; - } - - @CheckForNull - public String getFractionalPart() { - return fraction; - } - - /* pp */ void setFractionalPart(String fraction) { - this.fraction = fraction; - } - - @CheckForSigned - public int getExponentBase() { - return expbase; - } - - @CheckForNull - public String getExponent() { - return exponent; - } - - /* pp */ void setExponent(int expbase, String exponent) { - this.expbase = expbase; - this.exponent = exponent; - } - - public int getFlags() { - return flags; - } - - /* pp */ void setFlags(int flags) { - this.flags = flags; - } - - /** - * So, it turns out that parsing arbitrary bases into arbitrary - * precision numbers is nontrivial, and this routine gets it wrong - * in many important cases. - */ - @Nonnull - public BigDecimal toBigDecimal() { - int scale = 0; - String text = getIntegerPart(); - String t_fraction = getFractionalPart(); - if (t_fraction != null) { - text += getFractionalPart(); - // XXX Wrong for anything but base 10. - scale += t_fraction.length(); - } - String t_exponent = getExponent(); - if (t_exponent != null) - scale -= Integer.parseInt(t_exponent); - BigInteger unscaled = new BigInteger(text, getBase()); - return new BigDecimal(unscaled, scale); - } - - @Nonnull - public Number toJavaLangNumber() { - int flags = getFlags(); - if ((flags & F_DOUBLE) != 0) - return doubleValue(); - else if ((flags & F_FLOAT) != 0) - return floatValue(); - else if ((flags & (F_LONG | F_LONGLONG)) != 0) - return longValue(); - else if ((flags & F_INT) != 0) - return intValue(); - else if (getFractionalPart() != null) - return doubleValue(); // .1 is a double in Java. - else if (getExponent() != null) - return doubleValue(); - else - return intValue(); - } - - private int exponentValue() { - return Integer.parseInt(exponent, 10); - } - - @Override - public int intValue() { - int v = integer.isEmpty() ? 0 : Integer.parseInt(integer, base); - if (expbase == 2) - v = v << exponentValue(); - else if (expbase != 0) - v = (int) (v * Math.pow(expbase, exponentValue())); - return v; - } - - @Override - public long longValue() { - long v = integer.isEmpty() ? 0 : Long.parseLong(integer, base); - if (expbase == 2) - v = v << exponentValue(); - else if (expbase != 0) - v = (long) (v * Math.pow(expbase, exponentValue())); - return v; - } - - @Override - public float floatValue() { - if (getBase() != 10) - return longValue(); - return Float.parseFloat(toString()); - } - - @Override - public double doubleValue() { - if (getBase() != 10) - return longValue(); - return Double.parseDouble(toString()); - } - - private boolean appendFlags(StringBuilder buf, String suffix, int flag) { - if ((getFlags() & flag) != flag) - return false; - buf.append(suffix); - return true; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - switch (base) { - case 8: - buf.append('0'); - break; - case 10: - break; - case 16: - buf.append("0x"); - break; - case 2: - buf.append('b'); - break; - default: - buf.append("[base-").append(base).append("]"); - break; - } - buf.append(getIntegerPart()); - if (getFractionalPart() != null) - buf.append('.').append(getFractionalPart()); - if (getExponent() != null) { - buf.append(base > 10 ? 'p' : 'e'); - buf.append(getExponent()); - } - /* - if (appendFlags(buf, "ui", F_UNSIGNED | F_INT)); - else if (appendFlags(buf, "ul", F_UNSIGNED | F_LONG)); - else if (appendFlags(buf, "ull", F_UNSIGNED | F_LONGLONG)); - else if (appendFlags(buf, "i", F_INT)); - else if (appendFlags(buf, "l", F_LONG)); - else if (appendFlags(buf, "ll", F_LONGLONG)); - else if (appendFlags(buf, "f", F_FLOAT)); - else if (appendFlags(buf, "d", F_DOUBLE)); - */ - return buf.toString(); - } -} diff --git a/src/main/java/org/anarres/cpp/Preprocessor.java b/src/main/java/org/anarres/cpp/Preprocessor.java deleted file mode 100644 index c7a106a..0000000 --- a/src/main/java/org/anarres/cpp/Preprocessor.java +++ /dev/null @@ -1,2154 +0,0 @@ -/* - * 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.Closeable; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Stack; -import java.util.TreeMap; - -import javax.annotation.CheckForNull; -import javax.annotation.Nonnull; - -import static org.anarres.cpp.PreprocessorCommand.*; - -import org.anarres.cpp.PreprocessorListener.SourceChangeEvent; - -import com.jogamp.gluegen.Logging; -import com.jogamp.gluegen.Logging.LoggerIf; - -import static org.anarres.cpp.Token.*; - -/** - * A C Preprocessor. - * The Preprocessor outputs a token stream which does not need - * re-lexing for C or C++. Alternatively, the output text may be - * reconstructed by concatenating the {@link Token#getText() text} - * values of the returned {@link Token Tokens}. (See - * {@link CppReader}, which does this.) - */ -/* - * Source file name and line number information is conveyed by lines of the form - * - * # linenum filename flags - * - * These are called linemarkers. They are inserted as needed into - * the output (but never within a string or character constant). They - * mean that the following line originated in file filename at line - * linenum. filename will never contain any non-printing characters; - * they are replaced with octal escape sequences. - * - * After the file name comes zero or more flags, which are `1', `2', - * `3', or `4'. If there are multiple flags, spaces separate them. Here - * is what the flags mean: - * - * `1' - * This indicates the start of a new file. - * `2' - * This indicates returning to a file (after having included another - * file). - * `3' - * This indicates that the following text comes from a system header - * file, so certain warnings should be suppressed. - * `4' - * This indicates that the following text should be treated as being - * wrapped in an implicit extern "C" block. - */ -public class Preprocessor implements Closeable { - - private static final LoggerIf LOG = Logging.getLogger(Preprocessor.class); - - private static final Source INTERNAL = new Source() { - @Override - public Token token() - throws IOException, - LexerException { - throw new LexerException("Cannot read from " + getName()); - } - - @Override - public String getPath() { - return "<internal-data>"; - } - - @Override - public String getName() { - return "internal data"; - } - }; - private static final Macro __LINE__ = new Macro(INTERNAL, "__LINE__"); - private static final Macro __FILE__ = new Macro(INTERNAL, "__FILE__"); - private static final Macro __COUNTER__ = new Macro(INTERNAL, "__COUNTER__"); - - private final List<Source> inputs; - - /* The fundamental engine. */ - private final Map<String, Macro> macros; - private final Stack<State> states; - private Source source; - - /* Miscellaneous support. */ - private int counter; - private final Set<String> onceseenpaths = new HashSet<String>(); - private final List<VirtualFile> includes = new ArrayList<VirtualFile>(); - - /* Support junk to make it work like cpp */ - private List<String> quoteincludepath; /* -iquote */ - - private List<String> sysincludepath; /* -I */ - - private List<String> frameworkspath; - private final Set<Feature> features; - private final Set<Warning> warnings; - private VirtualFileSystem filesystem; - private PreprocessorListener listener; - - public Preprocessor() { - this.inputs = new ArrayList<Source>(); - - this.macros = new HashMap<String, Macro>(); - macros.put(__LINE__.getName(), __LINE__); - macros.put(__FILE__.getName(), __FILE__); - macros.put(__COUNTER__.getName(), __COUNTER__); - this.states = new Stack<State>(); - states.push(new State()); - this.source = null; - - this.counter = 0; - - this.quoteincludepath = new ArrayList<String>(); - this.sysincludepath = new ArrayList<String>(); - this.frameworkspath = new ArrayList<String>(); - this.features = EnumSet.noneOf(Feature.class); - this.warnings = EnumSet.noneOf(Warning.class); - this.filesystem = new JavaFileSystem(); - this.listener = null; - } - - public Preprocessor(@Nonnull final Source initial) { - this(); - addInput(initial); - } - - /** Equivalent to - * 'new Preprocessor(new {@link FileLexerSource}(file))' - */ - public Preprocessor(@Nonnull final File file) - throws IOException { - this(new FileLexerSource(file)); - } - - /** - * Sets the VirtualFileSystem used by this Preprocessor. - */ - public void setFileSystem(@Nonnull final VirtualFileSystem filesystem) { - this.filesystem = filesystem; - } - - /** - * Returns the VirtualFileSystem used by this Preprocessor. - */ - @Nonnull - public VirtualFileSystem getFileSystem() { - return filesystem; - } - - /** - * 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(@Nonnull final PreprocessorListener listener) { - this.listener = listener; - Source s = source; - while (s != null) { - // s.setListener(listener); - s.init(this); - s = s.getParent(); - } - } - - /** - * Returns the PreprocessorListener which handles events for - * this Preprocessor. - */ - @Nonnull - public PreprocessorListener getListener() { - return listener; - } - - /** - * Returns the feature-set for this Preprocessor. - * - * This set may be freely modified by user code. - */ - @Nonnull - public Set<Feature> getFeatures() { - return features; - } - - /** - * Adds a feature to the feature-set of this Preprocessor. - */ - public void addFeature(@Nonnull final Feature f) { - features.add(f); - } - - /** - * Adds features to the feature-set of this Preprocessor. - */ - public void addFeatures(@Nonnull final Collection<Feature> f) { - features.addAll(f); - } - - /** - * Adds features to the feature-set of this Preprocessor. - */ - public void addFeatures(final Feature... f) { - addFeatures(Arrays.asList(f)); - } - - /** - * Returns true if the given feature is in - * the feature-set of this Preprocessor. - */ - public boolean getFeature(@Nonnull final Feature f) { - return features.contains(f); - } - - /** - * Returns the warning-set for this Preprocessor. - * - * This set may be freely modified by user code. - */ - @Nonnull - public Set<Warning> getWarnings() { - return warnings; - } - - /** - * Adds a warning to the warning-set of this Preprocessor. - */ - public void addWarning(@Nonnull final Warning w) { - warnings.add(w); - } - - /** - * Adds warnings to the warning-set of this Preprocessor. - */ - public void addWarnings(@Nonnull final Collection<Warning> w) { - warnings.addAll(w); - } - - /** - * Returns true if the given warning is in - * the warning-set of this Preprocessor. - */ - public boolean getWarning(@Nonnull final Warning w) { - return warnings.contains(w); - } - - /** - * Adds input for the Preprocessor. - * - * Inputs are processed in the order in which they are added. - */ - public void addInput(@Nonnull final Source source) { - source.init(this); - inputs.add(source); - } - - /** - * Adds input for the Preprocessor. - * - * @see #addInput(Source) - */ - public void addInput(@Nonnull final File file) - throws IOException { - addInput(new FileLexerSource(file)); - } - - /** - * Handles an error. - * - * If a PreprocessorListener is installed, it receives the - * error. Otherwise, an exception is thrown. - */ - protected void error(final int line, final int column, @Nonnull final String msg) - throws LexerException { - if (listener != null) - listener.handleError(source, line, column, msg); - else - 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(@Nonnull final Token tok, @Nonnull final String msg) - throws LexerException { - error(tok.getLine(), tok.getColumn(), msg); - } - - /** - * Handles a warning. - * - * If a PreprocessorListener is installed, it receives the - * warning. Otherwise, an exception is thrown. - */ - protected void warning(final int line, final int column, @Nonnull final String msg) - throws LexerException { - 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(@Nonnull final Token tok, @Nonnull final String msg) - throws LexerException { - warning(tok.getLine(), tok.getColumn(), msg); - } - - /** - * Adds a Macro to this Preprocessor. - * - * The given {@link Macro} object encapsulates both the name - * and the expansion. - * @throws IOException - */ - public void addMacro(@Nonnull final Macro m) throws LexerException, IOException { - // System.out.println("Macro " + m); - final String name = m.getName(); - /* Already handled as a source error in macro(). */ - if ("defined".equals(name)) - throw new LexerException("Cannot redefine name 'defined'"); - - if ( isActive() && null != source && !source.isExpanding(m) ) { - m.setTokens( expand( m.getTokens() ) ); - } - macros.put(m.getName(), m); - } - - /** - * Defines the given name as a macro. - * - * The String value is lexed into a token stream, which is - * used as the macro expansion. - */ - public void addMacro(@Nonnull final String name, @Nonnull final String value) - throws LexerException { - try { - final Macro m = new Macro(name); - final StringLexerSource s = new StringLexerSource(value); - for (;;) { - final Token tok = s.token(); - if (tok.getType() == EOF) - break; - m.addToken(tok); - } - addMacro(m); - } catch (final IOException e) { - throw new LexerException(e); - } - } - - /** - * Defines the given name as a macro, with the value <code>1</code>. - * - * This is a convnience method, and is equivalent to - * <code>addMacro(name, "1")</code>. - */ - public void addMacro(@Nonnull final String name) - throws LexerException { - addMacro(name, "1"); - } - - /** - * Sets the user include path used by this Preprocessor. - */ - /* Note for future: Create an IncludeHandler? */ - public void setQuoteIncludePath(@Nonnull final List<String> path) { - this.quoteincludepath = path; - } - - /** - * Returns the user include-path of this Preprocessor. - * - * This list may be freely modified by user code. - */ - @Nonnull - public List<String> getQuoteIncludePath() { - return quoteincludepath; - } - - /** - * Sets the system include path used by this Preprocessor. - */ - /* Note for future: Create an IncludeHandler? */ - public void setSystemIncludePath(@Nonnull final List<String> path) { - this.sysincludepath = path; - } - - /** - * Returns the system include-path of this Preprocessor. - * - * This list may be freely modified by user code. - */ - @Nonnull - public List<String> getSystemIncludePath() { - return sysincludepath; - } - - /** - * Sets the Objective-C frameworks path used by this Preprocessor. - */ - /* Note for future: Create an IncludeHandler? */ - public void setFrameworksPath(@Nonnull final List<String> path) { - this.frameworkspath = path; - } - - /** - * Returns the Objective-C frameworks path used by this - * Preprocessor. - * - * This list may be freely modified by user code. - */ - @Nonnull - public List<String> getFrameworksPath() { - return frameworkspath; - } - - /** - * Returns the Map of Macros parsed during the run of this - * Preprocessor. - */ - @Nonnull - public Map<String, Macro> getMacros() { - return macros; - } - - /** - * Returns the named macro. - * - * While you can modify the returned object, unexpected things - * might happen if you do. - */ - @CheckForNull - public Macro getMacro(final String name) { - return macros.get(name); - } - - /** - * Returns the list of {@link VirtualFile VirtualFiles} which have been - * included by this Preprocessor. - * - * This does not include any {@link Source} provided to the constructor - * or {@link #addInput(java.io.File)} or {@link #addInput(Source)}. - */ - @Nonnull - public List<? extends VirtualFile> getIncludes() { - return includes; - } - - /* States */ - private void push_state() { - final State top = states.peek(); - states.push(new State(top)); - } - - private void pop_state() - throws LexerException { - final State s = states.pop(); - if (states.isEmpty()) { - error(0, 0, "#" + "endif without #" + "if"); - states.push(s); - } - } - - private boolean isActive() { - final State state = states.peek(); - return state.isParentActive() && state.isActive(); - } - - - /* Sources */ - /** - * Returns the top Source on the input stack. - * - * @see Source - * @see #push_source(Source,boolean) - * @see #pop_source() - */ - // @CheckForNull - public Source getSource() { - return source; - } - - /** - * Pushes a Source onto the input stack. - * - * @see #getSource() - * @see #pop_source() - */ - protected void push_source(@Nonnull final Source source, final boolean autopop) { - source.init(this); - source.setParent(this.source, autopop); - // source.setListener(listener); - if (listener != null) - listener.handleSourceChange(this.source, SourceChangeEvent.SUSPEND); - this.source = source; - if (listener != null) - listener.handleSourceChange(this.source, SourceChangeEvent.PUSH); - } - - /** - * Pops a Source from the input stack. - * - * @see #getSource() - * @see #push_source(Source,boolean) - */ - @CheckForNull - protected Token pop_source(final boolean linemarker) - throws IOException { - if (listener != null) - listener.handleSourceChange(this.source, SourceChangeEvent.POP); - final 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, SourceChangeEvent.RESUME); - - final Source t = getSource(); - if (getFeature(Feature.LINEMARKERS) - && s.isNumbered() - && t != null) { - /* We actually want 'did the nested source - * contain a newline token', which isNumbered() - * approximates. This is not perfect, but works. - * FIXME: Removed the '+ 1', since all lines were off by one. - * This solves this case, but I don't know _why_ this was here in the first place. - */ - return line_token(t.getLine() /* SEE ABOVE: + 1 */, t.getName(), " 2"); - } - - return null; - } - - protected void pop_source() - throws IOException { - pop_source(false); - } - - @Nonnull - private Token next_source() { - if (inputs.isEmpty()) - return new Token(EOF); - final 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(final int line, @CheckForNull final String name, @Nonnull final String extra) { - final StringBuilder buf = new StringBuilder(); - buf.append("#line ").append(line) - .append(" \""); - /* XXX This call to escape(name) is correct but ugly. */ - if (name == null) - buf.append("<no file>"); - else - MacroTokenSource.escape(buf, name); - buf.append("\"").append(extra).append("\n"); - return new Token(P_LINE, line, 0, buf.toString(), null); - } - - @Nonnull - private Token source_token() - throws IOException, - LexerException { - if (source_token != null) { - final Token tok = source_token; - source_token = null; - if (getFeature(Feature.DEBUG)) - LOG.debug("Returning unget token " + tok); - return tok; - } - - for (;;) { - final Source s = getSource(); - if (s == null) { - final Token t = next_source(); - if (t.getType() == P_LINE && !getFeature(Feature.LINEMARKERS)) - continue; - return t; - } - final Token tok = s.token(); - /* XXX Refactor with skipline() */ - if (tok.getType() == EOF && s.isAutopop()) { - // System.out.println("Autopop " + s); - final Token mark = pop_source(true); - if (mark != null) - return mark; - continue; - } - if (getFeature(Feature.DEBUG)) - LOG.debug("Returning fresh token " + tok); - return tok; - } - } - - private void source_untoken(final Token tok) { - if (this.source_token != null) - throw new IllegalStateException("Cannot return two tokens"); - this.source_token = tok; - } - - private boolean isWhite(final Token tok) { - final int type = tok.getType(); - return (type == WHITESPACE) - || (type == CCOMMENT) - || (type == CPPCOMMENT); - } - - private Token source_token_nonwhite() - throws IOException, - LexerException { - Token tok; - do { - tok = source_token(); - } while (isWhite(tok)); - return tok; - } - - /** - * Returns an NL or an EOF token. - * - * The metadata on the token will be correct, which is better - * than generating a new one. - * - * This method can, as of recent patches, return a P_LINE token. - */ - private Token source_skipline(final boolean white) - throws IOException, - LexerException { - // (new Exception("skipping line")).printStackTrace(System.out); - final Source s = getSource(); - final Token tok = s.skipline(white); - /* XXX Refactor with source_token() */ - if (tok.getType() == EOF && s.isAutopop()) { - // System.out.println("Autopop " + s); - final Token mark = pop_source(true); - if (mark != null) - return mark; - } - return tok; - } - - /* processes and expands a macro. */ - private boolean macro(final Macro m, final Token orig) - throws IOException, - LexerException { - Token tok; - List<Argument> args; - - // System.out.println("pp: expanding " + m); - if (m.isFunctionLike()) { - OPEN: - for (;;) { - tok = source_token(); - // System.out.println("pp: open: token is " + tok); - switch (tok.getType()) { - case WHITESPACE: /* XXX Really? */ - - case CCOMMENT: - case CPPCOMMENT: - case NL: - break; /* continue */ - - case '(': - break OPEN; - default: - source_untoken(tok); - return false; - } - } - - // tok = expanded_token_nonwhite(); - tok = source_token_nonwhite(); - - /* We either have, or we should have args. - * This deals elegantly with the case that we have - * one empty arg. */ - if (tok.getType() != ')' || m.getArgs() > 0) { - args = new ArrayList<Argument>(); - - Argument arg = new Argument(); - int depth = 0; - boolean space = false; - - ARGS: - for (;;) { - // System.out.println("pp: arg: token is " + tok); - switch (tok.getType()) { - case EOF: - error(tok, "EOF in macro args"); - return false; - - case ',': - if (depth == 0) { - if (m.isVariadic() - && /* We are building the last arg. */ args.size() == m.getArgs() - 1) { - /* Just add the comma. */ - arg.addToken(tok); - } else { - args.add(arg); - arg = new Argument(); - } - } else { - arg.addToken(tok); - } - space = false; - break; - case ')': - if (depth == 0) { - args.add(arg); - break ARGS; - } else { - depth--; - arg.addToken(tok); - } - space = false; - break; - case '(': - depth++; - arg.addToken(tok); - space = false; - break; - - case WHITESPACE: - case CCOMMENT: - case CPPCOMMENT: - case NL: - /* Avoid duplicating spaces. */ - space = true; - break; - - default: - /* Do not put space on the beginning of - * an argument token. */ - if (space && !arg.isEmpty()) - arg.addToken(Token.space); - arg.addToken(tok); - space = false; - break; - - } - // tok = expanded_token(); - tok = source_token(); - } - /* space may still be true here, thus trailing space - * is stripped from arguments. */ - - if (args.size() != m.getArgs()) { - if (m.isVariadic()) { - if (args.size() == m.getArgs() - 1) { - args.add(new Argument()); - } else { - error(tok, - "variadic macro " + m.getName() - + " has at least " + (m.getArgs() - 1) + " parameters " - + "but given " + args.size() + " args"); - return false; - } - } else { - error(tok, - "macro " + m.getName() - + " has " + m.getArgs() + " parameters " - + "but given " + args.size() + " args"); - /* We could replay the arg tokens, but I - * note that GNU cpp does exactly what we do, - * i.e. output the macro name and chew the args. - */ - return false; - } - } - - for (final Argument a : args) { - a.expand(this); - } - - // System.out.println("Macro " + m + " args " + args); - } else { - /* nargs == 0 and we (correctly) got () */ - args = null; - } - - } else { - /* Macro without args. */ - args = null; - } - - if (m == __LINE__) { - push_source(new FixedTokenSource( - new Token[]{new Token(NUMBER, - orig.getLine(), orig.getColumn(), - Integer.toString(orig.getLine()), - new NumericValue(10, Integer.toString(orig.getLine())))} - ), true); - } else if (m == __FILE__) { - final StringBuilder buf = new StringBuilder("\""); - String name = getSource().getName(); - if (name == null) - name = "<no file>"; - for (int i = 0; i < name.length(); i++) { - final char c = name.charAt(i); - switch (c) { - case '\\': - buf.append("\\\\"); - break; - case '"': - buf.append("\\\""); - break; - default: - buf.append(c); - break; - } - } - buf.append("\""); - final String text = buf.toString(); - push_source(new FixedTokenSource( - new Token[]{new Token(STRING, - orig.getLine(), orig.getColumn(), - text, text)} - ), true); - } else if (m == __COUNTER__) { - /* This could equivalently have been done by adding - * a special Macro subclass which overrides getTokens(). */ - final int value = this.counter++; - push_source(new FixedTokenSource( - new Token[]{new Token(NUMBER, - orig.getLine(), orig.getColumn(), - Integer.toString(value), - new NumericValue(10, Integer.toString(value)))} - ), true); - } else { - push_source(new MacroTokenSource(m, args), true); - } - - return true; - } - - /** - * Expands an argument. - */ - /* I'd rather this were done lazily, but doing so breaks spec. */ - @Nonnull - /* pp */ List<Token> expand(@Nonnull final List<Token> arg) - throws IOException, - LexerException { - final List<Token> expansion = new ArrayList<Token>(); - boolean space = false; - - push_source(new FixedTokenSource(arg), false); - - EXPANSION: - for (;;) { - final Token tok = expanded_token(); - switch (tok.getType()) { - case EOF: - break EXPANSION; - - case WHITESPACE: - case CCOMMENT: - case CPPCOMMENT: - space = true; - break; - - default: - if (space && !expansion.isEmpty()) - expansion.add(Token.space); - expansion.add(tok); - space = false; - break; - } - } - - // Always returns null. - pop_source(false); - - return expansion; - } - - /* processes a #define directive */ - private Token define() - throws IOException, - LexerException { - Token tok = source_token_nonwhite(); - if (tok.getType() != IDENTIFIER) { - error(tok, "Expected identifier"); - return source_skipline(false); - } - /* if predefined */ - final String name = tok.getText(); - if ("defined".equals(name)) { - error(tok, "Cannot redefine name 'defined'"); - return source_skipline(false); - } - - final Macro m = new Macro(getSource(), name); - List<String> args; - - tok = source_token(); - if (tok.getType() == '(') { - tok = source_token_nonwhite(); - if (tok.getType() != ')') { - args = new ArrayList<String>(); - ARGS: - for (;;) { - switch (tok.getType()) { - case IDENTIFIER: - args.add(tok.getText()); - break; - case ELLIPSIS: - // Unnamed Variadic macro - args.add("__VA_ARGS__"); - // We just named the ellipsis, but we unget the token - // to allow the ELLIPSIS handling below to process it. - source_untoken(tok); - break; - case NL: - case EOF: - error(tok, - "Unterminated macro parameter list"); - return tok; - default: - error(tok, - "error in macro parameters: " - + tok.getText()); - return source_skipline(false); - } - tok = source_token_nonwhite(); - switch (tok.getType()) { - case ',': - break; - case ELLIPSIS: - tok = source_token_nonwhite(); - if (tok.getType() != ')') - error(tok, - "ellipsis must be on last argument"); - m.setVariadic(true); - break ARGS; - case ')': - break ARGS; - - case NL: - case EOF: - /* Do not skip line. */ - error(tok, - "Unterminated macro parameters"); - return tok; - default: - error(tok, - "Bad token in macro parameters: " - + tok.getText()); - return source_skipline(false); - } - tok = source_token_nonwhite(); - } - } else { - assert tok.getType() == ')' : "Expected ')'"; - args = Collections.emptyList(); - } - - m.setArgs(args); - } else { - /* For searching. */ - args = Collections.emptyList(); - source_untoken(tok); - } - - /* Get an expansion for the macro, using indexOf. */ - boolean space = false; - boolean paste = false; - int idx; - - /* Ensure no space at start. */ - tok = source_token_nonwhite(); - EXPANSION: - for (;;) { - switch (tok.getType()) { - case EOF: - break EXPANSION; - case NL: - break EXPANSION; - - case CCOMMENT: - case CPPCOMMENT: - /* XXX This is where we implement GNU's cpp -CC. */ - // break; - case WHITESPACE: - if (!paste) - space = true; - break; - - /* Paste. */ - case PASTE: - space = false; - paste = true; - m.addPaste(new Token(M_PASTE, - tok.getLine(), tok.getColumn(), - "#" + "#", null)); - break; - - /* Stringify. */ - case '#': - if (space) - m.addToken(Token.space); - space = false; - final Token la = source_token_nonwhite(); - if (la.getType() == IDENTIFIER - && ((idx = args.indexOf(la.getText())) != -1)) { - m.addToken(new Token(M_STRING, - la.getLine(), la.getColumn(), - "#" + la.getText(), - Integer.valueOf(idx))); - } else { - m.addToken(tok); - /* Allow for special processing. */ - source_untoken(la); - } - break; - - case IDENTIFIER: - if (space) - m.addToken(Token.space); - space = false; - paste = false; - idx = args.indexOf(tok.getText()); - if (idx == -1) - m.addToken(tok); - else - m.addToken(new Token(M_ARG, - tok.getLine(), tok.getColumn(), - tok.getText(), - Integer.valueOf(idx))); - break; - - default: - if (space) - m.addToken(Token.space); - space = false; - paste = false; - m.addToken(tok); - break; - } - tok = source_token(); - } - - if (getFeature(Feature.DEBUG)) - LOG.debug("Defined macro " + m); - addMacro(m); - - return tok; /* NL or EOF. */ - - } - - @Nonnull - private Token undef() - throws IOException, - LexerException { - final Token tok = source_token_nonwhite(); - if (tok.getType() != IDENTIFIER) { - error(tok, - "Expected identifier, not " + tok.getText()); - if (tok.getType() == NL || tok.getType() == EOF) - return tok; - } else { - final Macro m = getMacro(tok.getText()); - if (m != null) { - /* XXX error if predefined */ - macros.remove(m.getName()); - } - } - return source_skipline(true); - } - - /** - * Attempts to include the given file. - * - * User code may override this method to implement a virtual - * file system. - */ - protected boolean include(@Nonnull final VirtualFile file) - throws IOException, - LexerException { - // System.out.println("Try to include " + ((File)file).getAbsolutePath()); - if (!file.isFile()) - return false; - if (getFeature(Feature.DEBUG)) - LOG.debug("pp: including " + file); - includes.add(file); - push_source(file.getSource(), true); - return true; - } - - /** - * Includes a file from an include path, by name. - */ - protected boolean include(@Nonnull final Iterable<String> path, @Nonnull final String name) - throws IOException, - LexerException { - for (final String dir : path) { - final VirtualFile file = getFileSystem().getFile(dir, name); - if (include(file)) - return true; - } - return false; - } - - /** - * Handles an include directive. - */ - private void include( - @CheckForNull final String parent, final int line, - @Nonnull final String name, final boolean quoted, final boolean next) - throws IOException, - LexerException { - if (name.startsWith("/")) { - final VirtualFile file = filesystem.getFile(name); - if (include(file)) - return; - final StringBuilder buf = new StringBuilder(); - buf.append("File not found: ").append(name); - error(line, 0, buf.toString()); - return; - } - - VirtualFile pdir = null; - if (quoted) { - if (parent != null) { - final VirtualFile pfile = filesystem.getFile(parent); - pdir = pfile.getParentFile(); - } - if (pdir != null) { - final VirtualFile ifile = pdir.getChildFile(name); - if (include(ifile)) - return; - } - if (include(quoteincludepath, name)) - return; - } else { - final int idx = name.indexOf('/'); - if (idx != -1) { - final String frameworkName = name.substring(0, idx); - final String headerName = name.substring(idx + 1); - final String headerPath = frameworkName + ".framework/Headers/" + headerName; - if (include(frameworkspath, headerPath)) - return; - } - } - - if (include(sysincludepath, name)) - return; - - final StringBuilder buf = new StringBuilder(); - buf.append("File not found: ").append(name); - buf.append(" in"); - if (quoted) { - buf.append(" .").append('(').append(pdir).append(')'); - for (final String dir : quoteincludepath) - buf.append(" ").append(dir); - } - for (final String dir : sysincludepath) - buf.append(" ").append(dir); - error(line, 0, buf.toString()); - } - - @Nonnull - private Token include(final boolean next) - throws IOException, - LexerException { - final LexerSource lexer = (LexerSource) source; - try { - lexer.setInclude(true); - Token tok = token_nonwhite(); - - String name; - boolean quoted; - - if (tok.getType() == STRING) { - /* XXX Use the original text, not the value. - * Backslashes must not be treated as escapes here. */ - final StringBuilder buf = new StringBuilder((String) tok.getValue()); - HEADER: - for (;;) { - tok = token_nonwhite(); - switch (tok.getType()) { - case STRING: - buf.append((String) tok.getValue()); - break; - case NL: - case EOF: - break HEADER; - default: - warning(tok, - "Unexpected token on #" + "include line"); - return source_skipline(false); - } - } - name = buf.toString(); - quoted = true; - } else if (tok.getType() == HEADER) { - name = (String) tok.getValue(); - quoted = false; - tok = source_skipline(true); - } else { - error(tok, - "Expected string or header, not " + tok.getText()); - switch (tok.getType()) { - case NL: - case EOF: - return tok; - default: - /* Only if not a NL or EOF already. */ - return source_skipline(false); - } - } - - /* Do the inclusion. */ - include(source.getPath(), tok.getLine(), name, quoted, next); - - /* 'tok' is the 'nl' after the include. We use it after the - * #line directive. */ - if (getFeature(Feature.LINEMARKERS)) - return line_token(1, source.getName(), " 1"); - return tok; - } finally { - lexer.setInclude(false); - } - } - - protected void pragma_once(@Nonnull final Token name) - throws IOException, LexerException { - final Source s = this.source; - if (!onceseenpaths.add(s.getPath())) { - final Token mark = pop_source(true); - // FixedTokenSource should never generate a linemarker on exit. - if (mark != null) - push_source(new FixedTokenSource(Arrays.asList(mark)), true); - } - } - - protected void pragma(@Nonnull final Token name, @Nonnull final List<Token> value) - throws IOException, - LexerException { - if (getFeature(Feature.PRAGMA_ONCE)) { - if ("once".equals(name.getText())) { - pragma_once(name); - return; - } - } - warning(name, "Unknown #" + "pragma: " + name.getText()); - } - - @Nonnull - private Token pragma() - throws IOException, - LexerException { - Token name; - - NAME: - for (;;) { - final Token tok = token(); - switch (tok.getType()) { - case EOF: - /* There ought to be a newline before EOF. - * At least, in any skipline context. */ - /* XXX Are we sure about this? */ - warning(tok, - "End of file in #" + "pragma"); - return tok; - case NL: - /* This may contain one or more newlines. */ - warning(tok, - "Empty #" + "pragma"); - return tok; - case CCOMMENT: - case CPPCOMMENT: - case WHITESPACE: - continue NAME; - case IDENTIFIER: - name = tok; - break NAME; - default: - return source_skipline(false); - } - } - - Token tok; - final List<Token> value = new ArrayList<Token>(); - VALUE: - for (;;) { - tok = token(); - switch (tok.getType()) { - case EOF: - /* There ought to be a newline before EOF. - * At least, in any skipline context. */ - /* XXX Are we sure about this? */ - warning(tok, - "End of file in #" + "pragma"); - break VALUE; - case NL: - /* This may contain one or more newlines. */ - break VALUE; - case CCOMMENT: - case CPPCOMMENT: - break; - case WHITESPACE: - value.add(tok); - break; - default: - value.add(tok); - break; - } - } - - pragma(name, value); - - return tok; /* The NL. */ - - } - - /* For #error and #warning. */ - private void error(@Nonnull final Token pptok, final boolean is_error) - throws IOException, - LexerException { - final StringBuilder buf = new StringBuilder(); - buf.append('#').append(pptok.getText()).append(' '); - /* Peculiar construction to ditch first whitespace. */ - Token tok = source_token_nonwhite(); - ERROR: - for (;;) { - switch (tok.getType()) { - case NL: - case EOF: - break ERROR; - default: - buf.append(tok.getText()); - break; - } - tok = source_token(); - } - if (is_error) - error(pptok, buf.toString()); - else - warning(pptok, buf.toString()); - } - - /* This bypasses token() for #elif expressions. - * If we don't do this, then isActive() == false - * causes token() to simply chew the entire input line. */ - @Nonnull - private Token expanded_token() - throws IOException, - LexerException { - for (;;) { - final Token tok = source_token(); - // System.out.println("Source token is " + tok); - if (tok.getType() == IDENTIFIER) { - final Macro m = getMacro(tok.getText()); - if (m == null) - return tok; - if (source.isExpanding(m)) - return tok; - if (macro(m, tok)) - continue; - } - return tok; - } - } - - @Nonnull - private Token expanded_token_nonwhite() - throws IOException, - LexerException { - Token tok; - do { - tok = expanded_token(); - // System.out.println("expanded token is " + tok); - } while (isWhite(tok)); - return tok; - } - - @CheckForNull - private Token expr_token = null; - - @Nonnull - private Token expr_token() - throws IOException, - LexerException { - Token tok = expr_token; - - if (tok != null) { - // System.out.println("ungetting"); - expr_token = null; - } else { - tok = expanded_token_nonwhite(); - // System.out.println("expt is " + tok); - - if (tok.getType() == IDENTIFIER - && tok.getText().equals("defined")) { - Token la = source_token_nonwhite(); - boolean paren = false; - if (la.getType() == '(') { - paren = true; - la = source_token_nonwhite(); - } - - // System.out.println("Core token is " + la); - if (la.getType() != IDENTIFIER) { - error(la, - "defined() needs identifier, not " - + la.getText()); - tok = new Token(NUMBER, - la.getLine(), la.getColumn(), - "0", new NumericValue(10, "0")); - } else if (macros.containsKey(la.getText())) { - // System.out.println("Found macro"); - tok = new Token(NUMBER, - la.getLine(), la.getColumn(), - "1", new NumericValue(10, "1")); - } else { - // System.out.println("Not found macro"); - tok = new Token(NUMBER, - la.getLine(), la.getColumn(), - "0", new NumericValue(10, "0")); - } - - if (paren) { - la = source_token_nonwhite(); - if (la.getType() != ')') { - expr_untoken(la); - error(la, "Missing ) in defined(). Got " + la.getText()); - } - } - } - } - - // System.out.println("expr_token returns " + tok); - return tok; - } - - private void expr_untoken(@Nonnull final Token tok) - throws LexerException { - if (expr_token != null) - throw new InternalException( - "Cannot unget two expression tokens." - ); - expr_token = tok; - } - - private int expr_priority(@Nonnull final Token op) { - switch (op.getType()) { - case '/': - return 11; - case '%': - return 11; - case '*': - return 11; - case '+': - return 10; - case '-': - return 10; - case LSH: - return 9; - case RSH: - return 9; - case '<': - return 8; - case '>': - return 8; - case LE: - return 8; - case GE: - return 8; - case EQ: - return 7; - case NE: - return 7; - case '&': - return 6; - case '^': - return 5; - case '|': - return 4; - case LAND: - return 3; - case LOR: - return 2; - case '?': - return 1; - default: - // System.out.println("Unrecognised operator " + op); - return 0; - } - } - - private long expr(final int priority) - throws IOException, - LexerException { - /* - * (new Exception("expr(" + priority + ") called")).printStackTrace(); - */ - - Token tok = expr_token(); - long lhs, rhs; - - // System.out.println("Expr lhs token is " + tok); - switch (tok.getType()) { - case '(': - lhs = expr(0); - tok = expr_token(); - if (tok.getType() != ')') { - expr_untoken(tok); - error(tok, "Missing ) in expression. Got " + tok.getText()); - return 0; - } - break; - - case '~': - lhs = ~expr(11); - break; - case '!': - lhs = expr(11) == 0 ? 1 : 0; - break; - case '-': - lhs = -expr(11); - break; - case NUMBER: - final NumericValue value = (NumericValue) tok.getValue(); - lhs = value.longValue(); - break; - case CHARACTER: - lhs = ((Character) tok.getValue()).charValue(); - break; - case IDENTIFIER: - if (warnings.contains(Warning.UNDEF)) - warning(tok, "Undefined token '" + tok.getText() - + "' encountered in conditional."); - lhs = 0; - break; - - default: - expr_untoken(tok); - error(tok, - "Bad token in expression: " + tok.getText()); - return 0; - } - - EXPR: - for (;;) { - // System.out.println("expr: lhs is " + lhs + ", pri = " + priority); - final Token op = expr_token(); - final int pri = expr_priority(op); /* 0 if not a binop. */ - - if (pri == 0 || priority >= pri) { - expr_untoken(op); - break EXPR; - } - rhs = expr(pri); - // System.out.println("rhs token is " + rhs); - switch (op.getType()) { - case '/': - if (rhs == 0) { - error(op, "Division by zero"); - lhs = 0; - } else { - lhs = lhs / rhs; - } - break; - case '%': - if (rhs == 0) { - error(op, "Modulus by zero"); - lhs = 0; - } else { - lhs = lhs % rhs; - } - break; - case '*': - lhs = lhs * rhs; - break; - case '+': - lhs = lhs + rhs; - break; - case '-': - lhs = lhs - rhs; - break; - case '<': - lhs = lhs < rhs ? 1 : 0; - break; - case '>': - lhs = lhs > rhs ? 1 : 0; - break; - case '&': - lhs = lhs & rhs; - break; - case '^': - lhs = lhs ^ rhs; - break; - case '|': - lhs = lhs | rhs; - break; - - case LSH: - lhs = lhs << rhs; - break; - case RSH: - lhs = lhs >> rhs; - break; - case LE: - lhs = lhs <= rhs ? 1 : 0; - break; - case GE: - lhs = lhs >= rhs ? 1 : 0; - break; - case EQ: - lhs = lhs == rhs ? 1 : 0; - break; - case NE: - lhs = lhs != rhs ? 1 : 0; - break; - case LAND: - lhs = (lhs != 0) && (rhs != 0) ? 1 : 0; - break; - case LOR: - lhs = (lhs != 0) || (rhs != 0) ? 1 : 0; - break; - - case '?': { - tok = expr_token(); - if (tok.getType() != ':') { - expr_untoken(tok); - error(tok, "Missing : in conditional expression. Got " + tok.getText()); - return 0; - } - final long falseResult = expr(0); - lhs = (lhs != 0) ? rhs : falseResult; - } - break; - - default: - error(op, - "Unexpected operator " + op.getText()); - return 0; - - } - } - - /* - * (new Exception("expr returning " + lhs)).printStackTrace(); - */ - // System.out.println("expr returning " + lhs); - return lhs; - } - - @Nonnull - private Token toWhitespace(@Nonnull final Token tok) { - final String text = tok.getText(); - final int len = text.length(); - boolean cr = false; - int nls = 0; - - for (int i = 0; i < len; i++) { - final char c = text.charAt(i); - - switch (c) { - case '\r': - cr = true; - nls++; - break; - case '\n': - if (cr) { - cr = false; - break; - } - /* fallthrough */ - case '\u2028': - case '\u2029': - case '\u000B': - case '\u000C': - case '\u0085': - cr = false; - nls++; - break; - } - } - - final char[] cbuf = new char[nls]; - Arrays.fill(cbuf, '\n'); - return new Token(WHITESPACE, - tok.getLine(), tok.getColumn(), - new String(cbuf)); - } - - @Nonnull - private Token _token() - throws IOException, - LexerException { - - for (;;) { - Token tok; - if (!isActive()) { - final Source s = getSource(); - if (s == null) { - final Token t = next_source(); - if (t.getType() == P_LINE && !getFeature(Feature.LINEMARKERS)) - continue; - return t; - } - - try { - /* XXX Tell lexer to ignore warnings. */ - s.setActive(false); - tok = source_token(); - } finally { - /* XXX Tell lexer to stop ignoring warnings. */ - s.setActive(true); - } - switch (tok.getType()) { - case HASH: - case NL: - case EOF: - /* The preprocessor has to take action here. */ - break; - case WHITESPACE: - return tok; - case CCOMMENT: - case CPPCOMMENT: - // Patch up to preserve whitespace. - if (getFeature(Feature.KEEPALLCOMMENTS)) - return tok; - if (!isActive()) - return toWhitespace(tok); - if (getFeature(Feature.KEEPCOMMENTS)) - return tok; - return toWhitespace(tok); - default: - // Return NL to preserve whitespace. - /* XXX This might lose a comment. */ - return source_skipline(false); - } - } else { - tok = source_token(); - } - - LEX: - switch (tok.getType()) { - case EOF: - /* Pop the stacks. */ - return tok; - - case WHITESPACE: - case NL: - return tok; - - case CCOMMENT: - case CPPCOMMENT: - return tok; - - case '!': - case '%': - case '&': - case '(': - case ')': - case '*': - case '+': - case ',': - case '-': - case '/': - case ':': - case ';': - case '<': - case '=': - case '>': - case '?': - case '[': - case ']': - case '^': - case '{': - case '|': - case '}': - case '~': - case '.': - - /* From Olivier Chafik for Objective C? */ - case '@': - /* The one remaining ASCII, might as well. */ - case '`': - - // case '#': - case AND_EQ: - case ARROW: - case CHARACTER: - case DEC: - case DIV_EQ: - case ELLIPSIS: - case EQ: - case GE: - case HEADER: /* Should only arise from include() */ - - case INC: - case LAND: - case LE: - case LOR: - case LSH: - case LSH_EQ: - case SUB_EQ: - case MOD_EQ: - case MULT_EQ: - case NE: - case OR_EQ: - case PLUS_EQ: - case RANGE: - case RSH: - case RSH_EQ: - case STRING: - case SQSTRING: - case XOR_EQ: - return tok; - - case NUMBER: - return tok; - - case IDENTIFIER: - final Macro m = getMacro(tok.getText()); - if (m == null) - return tok; - if (source.isExpanding(m)) - return tok; - if (macro(m, tok)) - break; - return tok; - - case P_LINE: - if (getFeature(Feature.LINEMARKERS)) - return tok; - break; - - case INVALID: - if (getFeature(Feature.CSYNTAX)) - error(tok, String.valueOf(tok.getValue())); - return tok; - - default: - throw new InternalException("Bad token " + tok); - // break; - - case HASH: - tok = source_token_nonwhite(); - // (new Exception("here")).printStackTrace(); - switch (tok.getType()) { - case NL: - break LEX; /* Some code has #\n */ - - case IDENTIFIER: - break; - default: - error(tok, - "Preprocessor directive not a word " - + tok.getText()); - return source_skipline(false); - } - final PreprocessorCommand ppcmd = PreprocessorCommand.forText(tok.getText()); - if (ppcmd == null) { - error(tok, - "Unknown preprocessor directive " - + tok.getText()); - return source_skipline(false); - } - - PP: - switch (ppcmd) { - - case PP_DEFINE: - if (!isActive()) - return source_skipline(false); - else - return define(); - // break; - - case PP_UNDEF: - if (!isActive()) - return source_skipline(false); - else - return undef(); - // break; - - case PP_INCLUDE: - if (!isActive()) - return source_skipline(false); - else - return include(false); - // break; - case PP_INCLUDE_NEXT: - if (!isActive()) - return source_skipline(false); - if (!getFeature(Feature.INCLUDENEXT)) { - error(tok, - "Directive include_next not enabled" - ); - return source_skipline(false); - } - return include(true); - // break; - - case PP_WARNING: - case PP_ERROR: - if (!isActive()) - return source_skipline(false); - else - error(tok, ppcmd == PP_ERROR); - break; - - case PP_IF: - push_state(); - if (!isActive()) { - return source_skipline(false); - } - expr_token = null; - states.peek().setActive(expr(0) != 0); - tok = expr_token(); /* unget */ - - if (tok.getType() == NL) - return tok; - return source_skipline(true); - // break; - - case PP_ELIF: - State state = states.peek(); - if (false) { - /* Check for 'if' */; - } else if (state.sawElse()) { - error(tok, - "#elif after #" + "else"); - return source_skipline(false); - } else if (!state.isParentActive()) { - /* Nested in skipped 'if' */ - return source_skipline(false); - } else if (state.isActive()) { - /* The 'if' part got executed. */ - state.setParentActive(false); - /* This is like # else # if but with - * only one # end. */ - state.setActive(false); - return source_skipline(false); - } else { - expr_token = null; - state.setActive(expr(0) != 0); - tok = expr_token(); /* unget */ - - if (tok.getType() == NL) - return tok; - return source_skipline(true); - } - // break; - - case PP_ELSE: - state = states.peek(); - if (false) - /* Check for 'if' */ ; else if (state.sawElse()) { - error(tok, - "#" + "else after #" + "else"); - return source_skipline(false); - } else { - state.setSawElse(); - state.setActive(!state.isActive()); - return source_skipline(warnings.contains(Warning.ENDIF_LABELS)); - } - // break; - - case PP_IFDEF: - push_state(); - if (!isActive()) { - return source_skipline(false); - } else { - tok = source_token_nonwhite(); - // System.out.println("ifdef " + tok); - if (tok.getType() != IDENTIFIER) { - error(tok, - "Expected identifier, not " - + tok.getText()); - return source_skipline(false); - } else { - final String text = tok.getText(); - final boolean exists - = macros.containsKey(text); - states.peek().setActive(exists); - return source_skipline(true); - } - } - // break; - - case PP_IFNDEF: - push_state(); - if (!isActive()) { - return source_skipline(false); - } else { - tok = source_token_nonwhite(); - if (tok.getType() != IDENTIFIER) { - error(tok, - "Expected identifier, not " - + tok.getText()); - return source_skipline(false); - } else { - final String text = tok.getText(); - final boolean exists - = macros.containsKey(text); - states.peek().setActive(!exists); - return source_skipline(true); - } - } - // break; - - case PP_ENDIF: - pop_state(); - return source_skipline(warnings.contains(Warning.ENDIF_LABELS)); - // break; - - case PP_LINE: - return source_skipline(false); - // break; - - case PP_PRAGMA: - if (!isActive()) - return source_skipline(false); - return pragma(); - // break; - - default: - /* Actual unknown directives are - * processed above. If we get here, - * we succeeded the map lookup but - * failed to handle it. Therefore, - * this is (unconditionally?) fatal. */ - // if (isActive()) /* XXX Could be warning. */ - throw new InternalException( - "Internal error: Unknown directive " - + tok); - // return source_skipline(false); - } - - } - } - } - - @Nonnull - private Token token_nonwhite() - throws IOException, - LexerException { - Token tok; - do { - tok = _token(); - } while (isWhite(tok)); - return tok; - } - - /** - * Returns the next preprocessor token. - * - * @see Token - * @throws LexerException if a preprocessing error occurs. - * @throws InternalException if an unexpected error condition arises. - */ - @Nonnull - public Token token() - throws IOException, - LexerException { - final Token tok = _token(); - if (getFeature(Feature.DEBUG)) - LOG.debug("pp: Returning " + tok); - return tok; - } - - @Override - public String toString() { - final StringBuilder buf = new StringBuilder(); - - Source s = getSource(); - while (s != null) { - buf.append(" -> ").append(String.valueOf(s)).append("\n"); - s = s.getParent(); - } - - final Map<String, Macro> macros = new TreeMap<String, Macro>(getMacros()); - for (final Macro macro : macros.values()) { - buf.append("#").append("macro ").append(macro).append("\n"); - } - - return buf.toString(); - } - - @Override - public void close() - throws IOException { - { - Source s = source; - while (s != null) { - s.close(); - s = s.getParent(); - } - } - for (final Source s : inputs) { - s.close(); - } - } - -} diff --git a/src/main/java/org/anarres/cpp/PreprocessorCommand.java b/src/main/java/org/anarres/cpp/PreprocessorCommand.java deleted file mode 100644 index 3938360..0000000 --- a/src/main/java/org/anarres/cpp/PreprocessorCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.anarres.cpp; - -import javax.annotation.CheckForNull; -import javax.annotation.Nonnull; - -/** - * - * @author shevek - */ -public enum PreprocessorCommand { - - PP_DEFINE("define"), - PP_ELIF("elif"), - PP_ELSE("else"), - PP_ENDIF("endif"), - PP_ERROR("error"), - PP_IF("if"), - PP_IFDEF("ifdef"), - PP_IFNDEF("ifndef"), - PP_INCLUDE("include"), - PP_LINE("line"), - PP_PRAGMA("pragma"), - PP_UNDEF("undef"), - PP_WARNING("warning"), - PP_INCLUDE_NEXT("include_next"), - PP_IMPORT("import"); - private final String text; - /* pp */ PreprocessorCommand(String text) { - this.text = text; - } - - @CheckForNull - public static PreprocessorCommand forText(@Nonnull String text) { - for (PreprocessorCommand ppcmd : PreprocessorCommand.values()) - if (ppcmd.text.equals(text)) - return ppcmd; - return null; - } -} diff --git a/src/main/java/org/anarres/cpp/PreprocessorListener.java b/src/main/java/org/anarres/cpp/PreprocessorListener.java deleted file mode 100644 index 0d3f7fc..0000000 --- a/src/main/java/org/anarres/cpp/PreprocessorListener.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 javax.annotation.Nonnull; - -/** - * A handler for preprocessor events, primarily errors and warnings. - * - * If no PreprocessorListener is installed in a Preprocessor, all - * error and warning events will throw an exception. Installing a - * listener allows more intelligent handling of these events. - */ -public interface PreprocessorListener { - - /** - * Handles a warning. - * - * The behaviour of this method is defined by the - * implementation. It may simply record the error message, or - * it may throw an exception. - */ - public void handleWarning(@Nonnull Source source, int line, int column, - @Nonnull String msg) - throws LexerException; - - /** - * Handles an error. - * - * The behaviour of this method is defined by the - * implementation. It may simply record the error message, or - * it may throw an exception. - */ - public void handleError(@Nonnull Source source, int line, int column, - @Nonnull String msg) - throws LexerException; - - public enum SourceChangeEvent { - - SUSPEND, PUSH, POP, RESUME; - } - - public void handleSourceChange(@Nonnull Source source, @Nonnull SourceChangeEvent event); - -} diff --git a/src/main/java/org/anarres/cpp/ResourceFileSystem.java b/src/main/java/org/anarres/cpp/ResourceFileSystem.java deleted file mode 100644 index 7efd664..0000000 --- a/src/main/java/org/anarres/cpp/ResourceFileSystem.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.anarres.cpp; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import javax.annotation.Nonnull; - -/** - * - * @author shevek - */ -public class ResourceFileSystem implements VirtualFileSystem { - - private final ClassLoader loader; - - public ResourceFileSystem(@Nonnull ClassLoader loader) { - this.loader = loader; - } - - @Override - public VirtualFile getFile(String path) { - return new ResourceFile(loader, path); - } - - @Override - public VirtualFile getFile(String dir, String name) { - return getFile(dir + "/" + name); - } - - private class ResourceFile implements VirtualFile { - - private final ClassLoader loader; - private final String path; - - public ResourceFile(ClassLoader loader, String path) { - this.loader = loader; - this.path = path; - } - - @Override - public boolean isFile() { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - - @Override - public String getPath() { - return path; - } - - @Override - public String getName() { - return path.substring(path.lastIndexOf('/') + 1); - } - - @Override - public ResourceFile getParentFile() { - int idx = path.lastIndexOf('/'); - if (idx < 1) - return null; - return new ResourceFile(loader, path.substring(0, idx)); - } - - @Override - public ResourceFile getChildFile(String name) { - return new ResourceFile(loader, path + "/" + name); - } - - @Override - public Source getSource() throws IOException { - InputStream stream = loader.getResourceAsStream(path); - BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); - return new LexerSource(reader, true); - } - } -} diff --git a/src/main/java/org/anarres/cpp/Source.java b/src/main/java/org/anarres/cpp/Source.java deleted file mode 100644 index 817c162..0000000 --- a/src/main/java/org/anarres/cpp/Source.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * 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.Closeable; -import java.io.IOException; -import java.util.Iterator; -import javax.annotation.CheckForNull; -import javax.annotation.Nonnegative; -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; -import static org.anarres.cpp.Token.NL; -import static org.anarres.cpp.Token.WHITESPACE; - -/** - * An input to the Preprocessor. - * - * Inputs may come from Files, Strings or other sources. The - * preprocessor maintains a stack of Sources. Operations such as - * file inclusion or token pasting will push a new source onto - * the Preprocessor stack. Sources pop from the stack when they - * are exhausted; this may be transparent or explicit. - * - * BUG: Error messages are not handled properly. - */ -public abstract class Source implements Iterable<Token>, Closeable { - - private Source parent; - private boolean autopop; - private PreprocessorListener listener; - private boolean active; - private boolean werror; - - /* LineNumberReader */ - - /* - // We can't do this, since we would lose the LexerException - private class Itr implements Iterator { - private Token next = null; - private void advance() { - try { - if (next != null) - next = token(); - } - catch (IOException e) { - throw new UnsupportedOperationException( - "Failed to advance token iterator: " + - e.getMessage() - ); - } - } - public boolean hasNext() { - return next.getType() != EOF; - } - public Token next() { - advance(); - Token t = next; - next = null; - return t; - } - public void remove() { - throw new UnsupportedOperationException( - "Cannot remove tokens from a Source." - ); - } - } - */ - public Source() { - this.parent = null; - this.autopop = false; - this.listener = null; - this.active = true; - this.werror = false; - } - - /** - * Sets the parent source of this source. - * - * Sources form a singly linked list. - */ - /* pp */ void setParent(final Source parent, final boolean autopop) { - this.parent = parent; - this.autopop = autopop; - } - - /** - * Returns the parent source of this source. - * - * Sources form a singly linked list. - */ - public final Source getParent() { - return parent; - } - - - // @OverrideMustInvoke - /* pp */ void init(final Preprocessor pp) { - setListener(pp.getListener()); - this.werror = pp.getWarnings().contains(Warning.ERROR); - } - - /** - * 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(final PreprocessorListener pl) { - this.listener = pl; - } - - /** - * Returns the File currently being lexed. - * - * If this Source is not a {@link FileLexerSource}, then - * it will ask the parent Source, and so forth recursively. - * If no Source on the stack is a FileLexerSource, returns null. - */ - @CheckForNull - public String getPath() { - final Source parent = getParent(); - if (parent != null) - return parent.getPath(); - return null; - } - - /** - * Returns the human-readable name of the current Source. - */ - @CheckForNull - public String getName() { - final Source parent = getParent(); - if (parent != null) - return parent.getName(); - return null; - } - - /** - * Returns the current line number within this Source. - */ - @Nonnegative - public int getLine() { - final Source parent = getParent(); - if (parent == null) - return 0; - return parent.getLine(); - } - - /** - * Returns the current column number within this Source. - */ - public int getColumn() { - final Source parent = getParent(); - if (parent == null) - return 0; - return parent.getColumn(); - } - - /** - * Returns true if this Source is expanding the given macro. - * - * This is used to prevent macro recursion. - */ - /* pp */ boolean isExpanding(@Nonnull final Macro m) { - final Source parent = getParent(); - if (parent != null) - return parent.isExpanding(m); - return false; - } - - /** - * Returns true if this Source should be transparently popped - * from the input stack. - * - * Examples of such sources are macro expansions. - */ - /* pp */ boolean isAutopop() { - return autopop; - } - - /** - * Returns true if this source has line numbers. - */ - /* pp */ boolean isNumbered() { - return false; - } - - /* This is an incredibly lazy way of disabling warnings when - * the source is not active. */ - /* pp */ void setActive(final boolean b) { - this.active = b; - } - - /* pp */ boolean isActive() { - return active; - } - - /** - * Returns the next Token parsed from this input stream. - * - * @see Token - */ - @Nonnull - public abstract Token token() - throws IOException, - LexerException; - - /** - * Returns a token iterator for this Source. - */ - @Override - public Iterator<Token> iterator() { - return new SourceIterator(this); - } - - /** - * Skips tokens until the end of line. - * - * @param white true if only whitespace is permitted on the - * remainder of the line. - * @return the NL token. - */ - @Nonnull - public Token skipline(final boolean white) - throws IOException, - LexerException { - for (;;) { - final Token tok = token(); - switch (tok.getType()) { - case EOF: - /* There ought to be a newline before EOF. - * At least, in any skipline context. */ - /* XXX Are we sure about this? */ - warning(tok.getLine(), tok.getColumn(), - "No newline before end of file"); - return new Token(NL, - tok.getLine(), tok.getColumn(), - "\n"); - // return tok; - case NL: - /* This may contain one or more newlines. */ - return tok; - case CCOMMENT: - case CPPCOMMENT: - case WHITESPACE: - break; - default: - /* XXX Check white, if required. */ - if (white) - warning(tok.getLine(), tok.getColumn(), - "Unexpected nonwhite token"); - break; - } - } - } - - protected void error(final int line, final int column, final String msg) - throws LexerException { - if (listener != null) - listener.handleError(this, line, column, msg); - else - throw new LexerException("Error at " + line + ":" + column + ": " + msg); - } - - protected void warning(final int line, final int column, final String msg) - throws LexerException { - 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); - } - - public void close() - throws IOException { - } - -} diff --git a/src/main/java/org/anarres/cpp/SourceIterator.java b/src/main/java/org/anarres/cpp/SourceIterator.java deleted file mode 100644 index 82e36d9..0000000 --- a/src/main/java/org/anarres/cpp/SourceIterator.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.IOException; -import java.util.Iterator; -import java.util.NoSuchElementException; -import static org.anarres.cpp.Token.EOF; - -/** - * An Iterator for {@link Source Sources}, - * returning {@link Token Tokens}. - */ -public class SourceIterator implements Iterator<Token> { - - private final Source source; - private Token tok; - - public SourceIterator(Source s) { - this.source = s; - this.tok = null; - } - - /** - * Rethrows IOException inside IllegalStateException. - */ - private void advance() { - try { - if (tok == null) - tok = source.token(); - } catch (LexerException e) { - throw new IllegalStateException(e); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - /** - * Returns true if the enclosed Source has more tokens. - * - * The EOF token is never returned by the iterator. - * @throws IllegalStateException if the Source - * throws a LexerException or IOException - */ - public boolean hasNext() { - advance(); - return tok.getType() != EOF; - } - - /** - * Returns the next token from the enclosed Source. - * - * The EOF token is never returned by the iterator. - * @throws IllegalStateException if the Source - * throws a LexerException or IOException - */ - public Token next() { - if (!hasNext()) - throw new NoSuchElementException(); - Token t = this.tok; - this.tok = null; - return t; - } - - /** - * Not supported. - * - * @throws UnsupportedOperationException. - */ - public void remove() { - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/org/anarres/cpp/State.java b/src/main/java/org/anarres/cpp/State.java deleted file mode 100644 index e24195d..0000000 --- a/src/main/java/org/anarres/cpp/State.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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; - -/* pp */ class State { - - boolean parent; - boolean active; - boolean sawElse; - - /* pp */ State() { - this.parent = true; - this.active = true; - this.sawElse = false; - } - - /* pp */ State(State parent) { - this.parent = parent.isParentActive() && parent.isActive(); - this.active = true; - this.sawElse = false; - } - - /* Required for #elif */ - /* pp */ void setParentActive(boolean b) { - this.parent = b; - } - - /* pp */ boolean isParentActive() { - return parent; - } - - /* pp */ void setActive(boolean b) { - this.active = b; - } - - /* pp */ boolean isActive() { - return active; - } - - /* pp */ void setSawElse() { - sawElse = true; - } - - /* pp */ boolean sawElse() { - return sawElse; - } - - @Override - public String toString() { - return "parent=" + parent - + ", active=" + active - + ", sawelse=" + sawElse; - } -} diff --git a/src/main/java/org/anarres/cpp/StringLexerSource.java b/src/main/java/org/anarres/cpp/StringLexerSource.java deleted file mode 100644 index 8640bc8..0000000 --- a/src/main/java/org/anarres/cpp/StringLexerSource.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.StringReader; - -/** - * A Source for lexing a String. - * - * This class is used by token pasting, but can be used by user - * code. - */ -public class StringLexerSource extends LexerSource { - - /** - * Creates a new Source for lexing the given String. - * - * @param ppvalid true if preprocessor directives are to be - * honoured within the string. - */ - public StringLexerSource(String string, boolean ppvalid) { - super(new StringReader(string), ppvalid); - } - - /** - * Creates a new Source for lexing the given String. - * - * By default, preprocessor directives are not honoured within - * the string. - */ - public StringLexerSource(String string) { - this(string, false); - } - - @Override - public String toString() { - return "string literal"; - } -} diff --git a/src/main/java/org/anarres/cpp/Token.java b/src/main/java/org/anarres/cpp/Token.java deleted file mode 100644 index 3e6eb3e..0000000 --- a/src/main/java/org/anarres/cpp/Token.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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; - -/** - * A Preprocessor token. - * - * @see Preprocessor - */ -public final class Token { - - // public static final int EOF = -1; - private final int type; - private int line; - private int column; - private final Object value; - private final String text; - - public Token(int type, int line, int column, - String text, Object value) { - this.type = type; - this.line = line; - this.column = column; - this.text = text; - this.value = value; - } - - public Token(int type, int line, int column, String text) { - this(type, line, column, text, null); - } - - /* pp */ Token(int type, String text, Object value) { - this(type, -1, -1, text, value); - } - - /* pp */ Token(int type, String text) { - this(type, text, null); - } - - /* pp */ Token(int type) { - this(type, TokenType.getTokenText(type)); - } - - /** - * Returns the semantic type of this token. - */ - public int getType() { - return type; - } - - /* pp */ void setLocation(int line, int column) { - this.line = line; - this.column = column; - } - - /** - * Returns the line at which this token started. - * - * Lines are numbered from zero. - */ - public int getLine() { - return line; - } - - /** - * Returns the column at which this token started. - * - * Columns are numbered from zero. - */ - public int getColumn() { - return column; - } - - /** - * Returns the original or generated text of this token. - * - * This is distinct from the semantic value of the token. - * - * @see #getValue() - */ - public String getText() { - return text; - } - - /** - * Returns the semantic value of this token. - * - * For strings, this is the parsed String. - * For integers, this is an Integer object. - * For other token types, as appropriate. - * - * @see #getText() - */ - public Object getValue() { - return value; - } - - /** - * Returns a description of this token, for debugging purposes. - */ - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - - buf.append('[').append(getTokenName(type)); - if (line != -1) { - buf.append('@').append(line); - if (column != -1) - buf.append(',').append(column); - } - buf.append("]:"); - if (text != null) - buf.append('"').append(text).append('"'); - else if (type > 3 && type < 256) - buf.append((char) type); - else - buf.append('<').append(type).append('>'); - if (value != null) - buf.append('=').append(value); - return buf.toString(); - } - - /** - * Returns the descriptive name of the given token type. - * - * This is mostly used for stringification and debugging. - */ - public static String getTokenName(int type) { - return TokenType.getTokenName(type); - } - - public static final int AND_EQ = 257; - public static final int ARROW = 258; - public static final int CHARACTER = 259; - public static final int CCOMMENT = 260; - public static final int CPPCOMMENT = 261; - public static final int DEC = 262; - public static final int DIV_EQ = 263; - public static final int ELLIPSIS = 264; - public static final int EOF = 265; - public static final int EQ = 266; - public static final int GE = 267; - public static final int HASH = 268; - public static final int HEADER = 269; - public static final int IDENTIFIER = 270; - public static final int INC = 271; - public static final int NUMBER = 272; - public static final int LAND = 273; - public static final int LAND_EQ = 274; - public static final int LE = 275; - public static final int LITERAL = 276; - public static final int LOR = 277; - public static final int LOR_EQ = 278; - public static final int LSH = 279; - public static final int LSH_EQ = 280; - public static final int MOD_EQ = 281; - public static final int MULT_EQ = 282; - public static final int NE = 283; - public static final int NL = 284; - public static final int OR_EQ = 285; - public static final int PASTE = 286; - public static final int PLUS_EQ = 287; - public static final int RANGE = 288; - public static final int RSH = 289; - public static final int RSH_EQ = 290; - public static final int SQSTRING = 291; - public static final int STRING = 292; - public static final int SUB_EQ = 293; - public static final int WHITESPACE = 294; - public static final int XOR_EQ = 295; - public static final int M_ARG = 296; - public static final int M_PASTE = 297; - public static final int M_STRING = 298; - public static final int P_LINE = 299; - public static final int INVALID = 300; - - /** The position-less space token. */ - /* pp */ static final Token space = new Token(WHITESPACE, -1, -1, " "); -} diff --git a/src/main/java/org/anarres/cpp/TokenSnifferSource.java b/src/main/java/org/anarres/cpp/TokenSnifferSource.java deleted file mode 100644 index 21e1cb8..0000000 --- a/src/main/java/org/anarres/cpp/TokenSnifferSource.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.IOException; -import java.util.List; -import static org.anarres.cpp.Token.EOF; - -@Deprecated -/* pp */ class TokenSnifferSource extends Source { - - private final List<Token> target; - - /* pp */ TokenSnifferSource(List<Token> target) { - this.target = target; - } - - public Token token() - throws IOException, - LexerException { - Token tok = getParent().token(); - if (tok.getType() != EOF) - target.add(tok); - return tok; - } - - @Override - public String toString() { - return getParent().toString(); - } -} diff --git a/src/main/java/org/anarres/cpp/TokenType.java b/src/main/java/org/anarres/cpp/TokenType.java deleted file mode 100644 index 86df097..0000000 --- a/src/main/java/org/anarres/cpp/TokenType.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.anarres.cpp; - -import java.util.ArrayList; -import java.util.List; -import javax.annotation.CheckForNull; -import javax.annotation.Nonnegative; -import javax.annotation.Nonnull; -import static org.anarres.cpp.Token.*; - -/** - * - * @author shevek - */ -/* pp */ class TokenType { - - private static final List<TokenType> TYPES = new ArrayList<TokenType>(); - - private static void addTokenType(@Nonnegative int type, @Nonnull String name, @CheckForNull String text) { - while (TYPES.size() <= type) - TYPES.add(null); - TYPES.set(type, new TokenType(name, text)); - } - - private static void addTokenType(@Nonnegative int type, @Nonnull String name) { - addTokenType(type, name, null); - } - - @CheckForNull - public static TokenType getTokenType(@Nonnegative int type) { - try { - return TYPES.get(type); - } catch (IndexOutOfBoundsException e) { - return null; - } - } - - @Nonnull - public static String getTokenName(@Nonnegative int type) { - if (type < 0) - return "Invalid" + type; - TokenType tokenType = getTokenType(type); - if (tokenType == null) - return "Unknown" + type; - return tokenType.getName(); - } - - @CheckForNull - public static String getTokenText(@Nonnegative int type) { - TokenType tokenType = getTokenType(type); - if (tokenType == null) - return null; - return tokenType.getText(); - } - - static { - for (int i = 0; i < 255; i++) { - String text = String.valueOf((char) i); - addTokenType(i, text, text); - } - addTokenType(AND_EQ, "AND_EQ", "&="); - addTokenType(ARROW, "ARROW", "->"); - addTokenType(CHARACTER, "CHARACTER"); - addTokenType(CCOMMENT, "CCOMMENT"); - addTokenType(CPPCOMMENT, "CPPCOMMENT"); - addTokenType(DEC, "DEC", "--"); - addTokenType(DIV_EQ, "DIV_EQ", "/="); - addTokenType(ELLIPSIS, "ELLIPSIS", "..."); - addTokenType(EOF, "EOF"); - addTokenType(EQ, "EQ", "=="); - addTokenType(GE, "GE", ">="); - addTokenType(HASH, "HASH", "#"); - addTokenType(HEADER, "HEADER"); - addTokenType(IDENTIFIER, "IDENTIFIER"); - addTokenType(INC, "INC", "++"); - addTokenType(NUMBER, "NUMBER"); - addTokenType(LAND, "LAND", "&&"); - addTokenType(LAND_EQ, "LAND_EQ", "&&="); - addTokenType(LE, "LE", "<="); - addTokenType(LITERAL, "LITERAL"); - addTokenType(LOR, "LOR", "||"); - addTokenType(LOR_EQ, "LOR_EQ", "||="); - addTokenType(LSH, "LSH", "<<"); - addTokenType(LSH_EQ, "LSH_EQ", "<<="); - addTokenType(MOD_EQ, "MOD_EQ", "%="); - addTokenType(MULT_EQ, "MULT_EQ", "*="); - addTokenType(NE, "NE", "!="); - addTokenType(NL, "NL"); - addTokenType(OR_EQ, "OR_EQ", "|="); - addTokenType(PASTE, "PASTE", "##"); - addTokenType(PLUS_EQ, "PLUS_EQ", "+="); - addTokenType(RANGE, "RANGE", ".."); - addTokenType(RSH, "RSH", ">>"); - addTokenType(RSH_EQ, "RSH_EQ", ">>="); - addTokenType(SQSTRING, "SQSTRING"); - addTokenType(STRING, "STRING"); - addTokenType(SUB_EQ, "SUB_EQ", "-="); - addTokenType(WHITESPACE, "WHITESPACE"); - addTokenType(XOR_EQ, "XOR_EQ", "^="); - addTokenType(M_ARG, "M_ARG"); - addTokenType(M_PASTE, "M_PASTE"); - addTokenType(M_STRING, "M_STRING"); - addTokenType(P_LINE, "P_LINE"); - addTokenType(INVALID, "INVALID"); - } - - private final String name; - private final String text; - - /* pp */ TokenType(@Nonnull String name, @CheckForNull String text) { - this.name = name; - this.text = text; - } - - @Nonnull - public String getName() { - return name; - } - - @CheckForNull - public String getText() { - return text; - } -} diff --git a/src/main/java/org/anarres/cpp/VirtualFile.java b/src/main/java/org/anarres/cpp/VirtualFile.java deleted file mode 100644 index aee1cad..0000000 --- a/src/main/java/org/anarres/cpp/VirtualFile.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.IOException; -import javax.annotation.CheckForNull; -import javax.annotation.Nonnull; - -/** - * An extremely lightweight virtual file interface. - */ -public interface VirtualFile { - - // public String getParent(); - public boolean isFile(); - - @Nonnull - public String getPath(); - - @Nonnull - public String getName(); - - @CheckForNull - public VirtualFile getParentFile(); - - @Nonnull - public VirtualFile getChildFile(String name); - - @Nonnull - public Source getSource() throws IOException; -} diff --git a/src/main/java/org/anarres/cpp/VirtualFileSystem.java b/src/main/java/org/anarres/cpp/VirtualFileSystem.java deleted file mode 100644 index 9c77d30..0000000 --- a/src/main/java/org/anarres/cpp/VirtualFileSystem.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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 javax.annotation.Nonnull; - -/** - * An extremely lightweight virtual file system interface. - */ -public interface VirtualFileSystem { - - @Nonnull - public VirtualFile getFile(@Nonnull String path); - - @Nonnull - public VirtualFile getFile(@Nonnull String dir, @Nonnull String name); -} diff --git a/src/main/java/org/anarres/cpp/Warning.java b/src/main/java/org/anarres/cpp/Warning.java deleted file mode 100644 index 80d184a..0000000 --- a/src/main/java/org/anarres/cpp/Warning.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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; - -/** - * Warning classes which may optionally be emitted by the Preprocessor. - */ -public enum Warning { - - TRIGRAPHS, - // TRADITIONAL, - IMPORT, - UNDEF, - UNUSED_MACROS, - ENDIF_LABELS, - ERROR, - // SYSTEM_HEADERS -} |