summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/list/meta.lst4
-rw-r--r--sources/meta/util/AbstractFileExpander.java126
-rw-r--r--sources/meta/util/TextExpander.java275
-rw-r--r--sources/meta/util/TextWriter.java248
4 files changed, 653 insertions, 0 deletions
diff --git a/config/list/meta.lst b/config/list/meta.lst
index 25f932474f..0438674c3a 100644
--- a/config/list/meta.lst
+++ b/config/list/meta.lst
@@ -3,4 +3,8 @@
##############################################################################
# $Id$
+util/AbstractFileExpander.java
+util/TextExpander.java
+util/TextWriter.java
+
##############################################################################
diff --git a/sources/meta/util/AbstractFileExpander.java b/sources/meta/util/AbstractFileExpander.java
new file mode 100644
index 0000000000..580fa08bd8
--- /dev/null
+++ b/sources/meta/util/AbstractFileExpander.java
@@ -0,0 +1,126 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package meta.util;
+
+import java.io.File;
+
+/** A base class for file expanders. */
+public abstract class AbstractFileExpander {
+
+ //########################################################################
+ // Private Constants
+
+ /** The meta package */
+ private static final String meta = "meta";
+
+ /** The meta name prefix */
+ private static final String Meta = "Meta";
+
+ //########################################################################
+ // Public Methods
+
+ /** Returns the TextWriter in which this expander writes. */
+ public abstract TextWriter getTextWriter();
+
+ /**
+ * Returns the package associated with this expander or null if
+ * there no such package. The default implementation returns the
+ * package of this instance's class. If the outermost package is
+ * named "meta", this package is omitted.
+ */
+ public String getPackage() {
+ String fullname = getClass().getName();
+ int end = fullname.lastIndexOf('.');
+ if (end < 0) return null;
+ int start = fullname.startsWith(meta + ".") ? meta.length() + 1 : 0;
+ return fullname.substring(start, end);
+ }
+
+ /**
+ * Returns the name associated with this expander. The default
+ * implementation returns the name of this instance's class. If
+ * that name starts with "Meta", this prefix is omitted.
+ */
+ public String getName() {
+ String fullname = getClass().getName();
+ int index = fullname.lastIndexOf('.');
+ String name = index < 0 ? fullname : fullname.substring(index + 1);
+ return name.startsWith(Meta) ? name.substring(Meta.length()) : name;
+ }
+
+ /**
+ * Returns the directory of the target file. The default
+ * implementation returns the directory corresponding to the
+ * this instance's associated package.
+ */
+ public String getTargetDirectory() {
+ String peckage = getPackage();
+ return peckage == null ? "." : peckage.replace('.',File.separatorChar);
+ }
+
+ /**
+ * Returns the base name of the target file. The default
+ * implementation returns this instance's associated name.
+ */
+ public String getTargetBaseName() {
+ return getName();
+ }
+
+ /**
+ * Returns the suffix of the target file or null if it has no
+ * suffix. The default implementation returns null.
+ */
+ public String getTargetSuffix() {
+ return null;
+ }
+
+ /** Returns the target file. */
+ public File getTargetFile(File root) {
+ String suffix = getTargetSuffix();
+ String name = getTargetBaseName();
+ if (suffix != null) name = name + "." + suffix;
+ return new File(new File(root, getTargetDirectory()), name);
+ }
+
+ /**
+ * Returns the directory of the source file. The default
+ * implementation returns the directory of the target file.
+ */
+ public String getSourceDirectory() {
+ return getTargetDirectory();
+ }
+
+ /**
+ * Returns the base name of the source file. The default
+ * implementation returns the target base name.
+ */
+ public String getSourceBaseName() {
+ return getTargetBaseName();
+ }
+
+ /**
+ * Returns the suffix of the source file or null if it has no
+ * suffix. The default implementation returns the target suffix
+ * suffixed with ".tmpl".
+ */
+ public String getSourceSuffix() {
+ String suffix = getTargetSuffix();
+ return (suffix == null ? "" : suffix + ".") + "tmpl";
+ }
+
+ /** Returns the source file. */
+ public File getSourceFile(File root) {
+ String suffix = getSourceSuffix();
+ String name = getSourceBaseName();
+ if (suffix != null) name = name + "." + suffix;
+ return new File(new File(root, getSourceDirectory()), name);
+ }
+
+ //########################################################################
+}
diff --git a/sources/meta/util/TextExpander.java b/sources/meta/util/TextExpander.java
new file mode 100644
index 0000000000..5fe7fbdb38
--- /dev/null
+++ b/sources/meta/util/TextExpander.java
@@ -0,0 +1,275 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package meta.util;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.BufferedReader;
+import java.io.IOException;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+/** A macro expander with support for indentation */
+public class TextExpander {
+
+ //########################################################################
+ // Public Constants
+
+ /** Default macro name prefix */
+ public static final String MACRO_PREFIX = "print";
+
+ /** Default macro left quote */
+ public static final String MACRO_LQUOTE = "{#";
+
+ /** Default macro right quote */
+ public static final String MACRO_RQUOTE = "#}";
+
+ /** Do not edit warning */
+ public static final String DO_NOT_EDIT =
+ "DO NOT EDIT. Automatically generated file!";
+
+ //########################################################################
+ // Private Constants
+
+ /** An empty array of Classes */
+ private static final Class [] NO_PARAMS = new Class[0];
+
+ /** An empty array of Objects */
+ private static final Object[] NO_ARGS = new Object[0];
+
+ //########################################################################
+ // Private Fields
+
+ /** The output text writer */
+ private final TextWriter writer;
+
+ /** The macro expander */
+ private final Object expander;
+
+ /** The current macro name prefix */
+ private String prefix;
+
+ /** The current macro left quote */
+ private String lquote;
+
+ /** The current macro right quote */
+ private String rquote;
+
+ /** The current input name */
+ private String name;
+
+ /** The current input line number */
+ private int line;
+
+ /** The current error count */
+ private int errors;
+
+ //########################################################################
+ // Public Constructors
+
+ /** Creates a new TextExpander. */
+ public TextExpander(TextWriter writer, Object expander) {
+ this.writer = writer;
+ this.expander = expander;
+ this.prefix = MACRO_PREFIX;
+ this.lquote = MACRO_LQUOTE;
+ this.rquote = MACRO_RQUOTE;
+ }
+
+ //########################################################################
+ // Public Methods - Text expansion
+
+ /** Expands the text from the given file. */
+ public void expandText(File file) {
+ setInputName(file.toString());
+ setInputLine(0);
+ try {
+ BufferedReader reader = new BufferedReader(new FileReader(file));
+ expandText(reader);
+ reader.close();
+ } catch (IOException exception) {
+ error("input error", exception);
+ }
+ }
+
+ /** Expands the text from the given character stream. */
+ public void expandText(BufferedReader reader) {
+ try {
+ for (String line; (line = reader.readLine()) != null;) {
+ this.line++;
+ expandLine(line);
+ }
+ } catch (IOException exception) {
+ error("input error", exception);
+ }
+ }
+
+ /** Expands the given line. */
+ public void expandLine(String line) {
+ int index = 0;
+ int column = 0;
+ for (; index < line.length(); index++) {
+ switch (line.charAt(index)) {
+ case ' ' : column += 1; continue;
+ case '\t': column += 8 - (column % 8); continue;
+ }
+ break;
+ }
+ if (index < line.length()) {
+ int width = writer.getIndentWidth();
+ writer.setIndentLevel(column / width);
+ for (int i = 0; i < column % width; i++) writer.print(' ');
+ line = line.substring(index);
+ if (line.indexOf("$Id") >= 0)
+ line = line.replaceFirst("[$]Id.*[$]", DO_NOT_EDIT);
+ expand(line);
+ }
+ writer.println();
+ }
+
+ /** Expands the given string. */
+ public void expand(String input) {
+ int start = 0;
+ while (true) {
+ int lindex = input.indexOf(lquote, start);
+ if (lindex < 0) break;
+ int rindex = input.indexOf(rquote, lindex + lquote.length());
+ if (rindex < 0) { error("unclosed macro"); break; }
+ String macro = input.substring(lindex + lquote.length(), rindex);
+ if (macro.indexOf(lquote) >= 0) { error("unclosed macro"); break; }
+ if (start < lindex) writer.print(input.substring(start, lindex));
+ expandMacro(macro);
+ start = rindex + rquote.length();
+ }
+ if (start < input.length()) writer.print(input.substring(start));
+ }
+
+ //########################################################################
+ // Public Methods - Macro expansion
+
+ /** Expands the given macro. */
+ public void expandMacro(String macro) {
+ String member = prefix + macro;
+ Class clasz = expander.getClass();
+ try {
+ expandMacro(macro, clasz.getMethod(member, NO_PARAMS));
+ } catch (NoSuchMethodException exception) {
+ error("macro '" + macro + "' is undefined");
+ writer.print(lquote + macro + rquote);
+ }
+ }
+
+ /** Expands the given macro by invoking the given method. */
+ public void expandMacro(String macro, Method method) {
+ try {
+ method.invoke(expander, NO_ARGS);
+ } catch (IllegalAccessException exception) {
+ error("macro '" + macro + "' could not access method " + method);
+ writer.print(lquote + macro + rquote);
+ } catch (InvocationTargetException exception) {
+ error("macro '" + macro + "' raised an exception");
+ exception.getTargetException().printStackTrace();
+ }
+ }
+
+ //########################################################################
+ // Public Methods - Error messages
+
+ /** Prints an error message. */
+ public void error(String error) {
+ String prefix = name != null ? name + ":" : "error:";
+ if (line > 0) prefix = prefix + line + ":";
+ System.err.println(prefix + " " + error);
+ errors++;
+ }
+
+ /** Prints an error message. */
+ public void error(String error, Throwable exception) {
+ if (exception.getMessage() != null)
+ error(exception.getMessage());
+ else
+ error(error + " (" + exception.getClass().getName() + ")");
+ }
+
+ //########################################################################
+ // Public Methods - Getters
+
+ /** Returns the output text writer. */
+ public TextWriter getOutputWriter() {
+ return writer;
+ }
+
+ /** Returns the macro expander. */
+ public Object getMacroExpander() {
+ return expander;
+ }
+
+ /** Returns the current macro name prefix. */
+ public String getMacroPrefix() {
+ return prefix;
+ }
+
+ /** Returns the current macro left quote. */
+ public String getMacroLeftQuote() {
+ return lquote;
+ }
+
+ /** Returns the current macro right quote. */
+ public String getMacroRightQuote() {
+ return lquote;
+ }
+
+ /** Returns the current input name. */
+ public String getInputName() {
+ return name;
+ }
+
+ /** Returns the current input line. */
+ public int getInputLine() {
+ return line;
+ }
+
+ /** Returns the current error count. */
+ public int getErrorCount() {
+ return errors;
+ }
+
+ //########################################################################
+ // Public Methods - Setters
+
+ /** Sets the current macro name prefix. */
+ public void setMacroPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+
+ /** Sets the current macro quotes. */
+ public void setMacroQuotes(String lquote, String rquote) {
+ this.lquote = lquote;
+ this.rquote = rquote;
+ }
+
+ /** Sets the current input name. */
+ public void setInputName(String name) {
+ this.name = name;
+ }
+
+ /** Sets the current input line. */
+ public void setInputLine(int line) {
+ this.line = line;
+ }
+
+ /** Sets the current error count. */
+ public void setErrorCount(int errors) {
+ this.errors = errors;
+ }
+
+ //########################################################################
+}
diff --git a/sources/meta/util/TextWriter.java b/sources/meta/util/TextWriter.java
new file mode 100644
index 0000000000..7d78f75b9c
--- /dev/null
+++ b/sources/meta/util/TextWriter.java
@@ -0,0 +1,248 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package meta.util;
+
+/** A string generator with support for indentation and spacing. */
+public class TextWriter {
+
+ //########################################################################
+ // Private Constants
+
+ /** The line separator */
+ private static final String LINE = System.getProperty("line.separator");
+
+ /** The default width of an indentation level */
+ private static final String STEP = " ";
+
+ //########################################################################
+ // Private Fields
+
+ /** The output buffer */
+ private final StringBuffer buffer;
+
+ /** The width of an indentation level */
+ private final String step;
+
+ /** The current indentation level */
+ private int level;
+
+ /** Do we need to align? */
+ private boolean align;
+
+ /** Do we need to print a white space? */
+ private boolean space;
+
+ /** Is there already a empty line? */
+ private boolean line;
+
+ //########################################################################
+ // Public Constructors
+
+ /** Creates a new TextWriter. */
+ public TextWriter() {
+ this(new StringBuffer());
+ }
+
+ /** Creates a new TextWriter. */
+ public TextWriter(String step) {
+ this(new StringBuffer(), step);
+ }
+
+ /** Creates a new TextWriter. */
+ public TextWriter(String step, int level) {
+ this(new StringBuffer(), step, level);
+ }
+
+ /** Creates a new TextWriter. */
+ public TextWriter(StringBuffer buffer) {
+ this(buffer, STEP, 0);
+ }
+
+ /** Creates a new TextWriter. */
+ public TextWriter(StringBuffer buffer, String step) {
+ this(buffer, step, 0);
+ }
+
+ /** Creates a new TextWriter. */
+ public TextWriter(StringBuffer buffer, String step, int level) {
+ this.buffer = buffer;
+ this.step = step;
+ this.level = level;
+ this.align = false;
+ this.space = false;
+ this.line = false;
+ }
+
+ //########################################################################
+ // Public Methods - Printing
+
+ /** Prints a new line. */
+ public TextWriter println() {
+ return line();
+ }
+
+ /** Prints the boolean value followed by a new line. */
+ public TextWriter println(boolean value) {
+ return print(value).line();
+ }
+
+ /** Prints the byte value followed by a new line. */
+ public TextWriter println(byte value) {
+ return print(value).line();
+ }
+
+ /** Prints the short value followed by a new line. */
+ public TextWriter println(short value) {
+ return print(value).line();
+ }
+
+ /** Prints the char value followed by a new line. */
+ public TextWriter println(char value) {
+ return print(value).line();
+ }
+
+ /** Prints the int value followed by a new line. */
+ public TextWriter println(int value) {
+ return print(value).line();
+ }
+
+ /** Prints the long value followed by a new line. */
+ public TextWriter println(long value) {
+ return print(value).line();
+ }
+
+ /** Prints the float value followed by a new line. */
+ public TextWriter println(float value) {
+ return print(value).line();
+ }
+
+ /** Prints the double value followed by a new line. */
+ public TextWriter println(double value) {
+ return print(value).line();
+ }
+
+ /** Prints the string followed by a new line. */
+ public TextWriter println(String value) {
+ return print(value).line();
+ }
+
+ /** Prints the boolean value. */
+ public TextWriter print(boolean value) {
+ return print(String.valueOf(value));
+ }
+
+ /** Prints the byte value. */
+ public TextWriter print(byte value) {
+ return print(String.valueOf(value));
+ }
+
+ /** Prints the short value. */
+ public TextWriter print(short value) {
+ return print(String.valueOf(value));
+ }
+
+ /** Prints the char value. */
+ public TextWriter print(char value) {
+ return print(String.valueOf(value));
+ }
+
+ /** Prints the int value. */
+ public TextWriter print(int value) {
+ return print(String.valueOf(value));
+ }
+
+ /** Prints the long value. */
+ public TextWriter print(long value) {
+ return print(String.valueOf(value));
+ }
+
+ /** Prints the float value. */
+ public TextWriter print(float value) {
+ return print(String.valueOf(value));
+ }
+
+ /** Prints the long value. */
+ public TextWriter print(double value) {
+ return print(String.valueOf(value));
+ }
+
+ /** Prints the string. */
+ public TextWriter print(String value) {
+ if (align) for (int i = 0; i < level; i++) buffer.append(step);
+ if (space) buffer.append(' ');
+ buffer.append(value);
+ align = false;
+ space = false;
+ line = false;
+ return this;
+ }
+
+ //########################################################################
+ // Public Methods - Formating
+
+ /** Returns the indentation width. */
+ public int getIndentWidth() {
+ return step == null ? -1 : step.length();
+ }
+
+ /** Returns the indentation level. */
+ public int getIndentLevel() {
+ return level;
+ }
+
+ /** Returns the indentation level. */
+ public TextWriter setIndentLevel(int level) {
+ this.level = level;
+ return this;
+ }
+
+ /** Increases the indentation level by one. */
+ public TextWriter indent() {
+ level++;
+ return this;
+ }
+
+ /** Decreases the indentation level by one. */
+ public TextWriter undent() {
+ level--;
+ return this;
+ }
+
+ /** Starts a new line. */
+ public TextWriter line() {
+ if (step == null) return space();
+ if (line) return this;
+ buffer.append(LINE);
+ line = align;
+ align = true;
+ space = false;
+ return this;
+ }
+
+ /** Inserts a white space. */
+ public TextWriter space() {
+ space = !align;
+ return this;
+ }
+
+ //########################################################################
+ // Public Methods - Accessing
+
+ /** Returns the underlying StringBuffer. */
+ public StringBuffer getBuffer() {
+ return buffer;
+ }
+
+ /** Returns the generated string. */
+ public String toString() {
+ return buffer.toString();
+ }
+
+ //########################################################################
+}