summaryrefslogtreecommitdiff
path: root/sources/scalac/util
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-02-13 14:41:36 +0000
committerMartin Odersky <odersky@gmail.com>2003-02-13 14:41:36 +0000
commit4177daab2f54bdb20c71f623296a8bb32616fd12 (patch)
tree23f08b43f3758e825d5965b336030603a65bbcf7 /sources/scalac/util
parent33d6e170c97ca7b2f991896a0729941a7240b6d6 (diff)
downloadscala-4177daab2f54bdb20c71f623296a8bb32616fd12.tar.gz
scala-4177daab2f54bdb20c71f623296a8bb32616fd12.tar.bz2
scala-4177daab2f54bdb20c71f623296a8bb32616fd12.zip
Initial version.
Diffstat (limited to 'sources/scalac/util')
-rw-r--r--sources/scalac/util/AbstractFile.java557
-rw-r--r--sources/scalac/util/AbstractFileReader.java107
-rw-r--r--sources/scalac/util/ArrayApply.java54
-rw-r--r--sources/scalac/util/ClassPath.java161
-rw-r--r--sources/scalac/util/Debug.java465
-rw-r--r--sources/scalac/util/FreshNameCreator.java59
-rw-r--r--sources/scalac/util/Name.java391
-rw-r--r--sources/scalac/util/NameTransformer.java111
-rw-r--r--sources/scalac/util/Names.java98
-rw-r--r--sources/scalac/util/OptionParser.java546
-rw-r--r--sources/scalac/util/Position.java54
-rw-r--r--sources/scalac/util/PrefixMatcher.java114
-rw-r--r--sources/scalac/util/Reporter.java192
-rw-r--r--sources/scalac/util/SourceRepresentation.java205
-rw-r--r--sources/scalac/util/Strings.java102
-rw-r--r--sources/scalac/util/UniqueID.java30
16 files changed, 3246 insertions, 0 deletions
diff --git a/sources/scalac/util/AbstractFile.java b/sources/scalac/util/AbstractFile.java
new file mode 100644
index 0000000000..2487e07ca3
--- /dev/null
+++ b/sources/scalac/util/AbstractFile.java
@@ -0,0 +1,557 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scalac.util;
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import java.util.jar.*;
+
+public abstract class AbstractFile {
+
+ /** separator
+ */
+ protected char separator = File.separatorChar;
+
+ /** table of all opened jar-files
+ */
+ protected static Hashtable opened = new Hashtable();
+
+ /** get name of the file
+ */
+ public abstract String getName();
+
+ /** get path of the file
+ */
+ public abstract String getPath();
+
+ /** does the file exist?
+ */
+ public abstract boolean exists();
+
+ /** is the file a directory?
+ */
+ public abstract boolean isDirectory();
+
+ /** read content of the file into a byte[] buffer
+ */
+ public abstract byte[] read() throws IOException;
+
+ /** list contents of a directory
+ */
+ public abstract String[] list() throws IOException;
+
+ /** open a new file
+ */
+ public abstract AbstractFile open(String name);
+
+ /** return an input stream for the file
+ */
+ public InputStream getInputStream() throws IOException {
+ return new ByteArrayInputStream(read());
+ }
+
+ /** open file 'name' in directory 'dirname'
+ */
+ public static AbstractFile open(String dirname, String name) {
+ AbstractFile res;
+ if (dirname == null)
+ res = new PlainFile(new File(name));
+ else if (dirname.endsWith(".zip")) {
+ AbstractFile dir = (AbstractFile)opened.get(dirname);
+ if (dir == null) {
+ dir = new ZipDir(new File(dirname));
+ if (dir.isDirectory())
+ opened.put(dirname, dir);
+ }
+ res = (name == null) ? dir : dir.open(name);
+ } else if (dirname.endsWith(".jar")) {
+ AbstractFile dir = (AbstractFile)opened.get(dirname);
+ if (dir == null) {
+ dir = new JarArchive(new File(dirname));
+ if (dir.isDirectory())
+ opened.put(dirname, dir);
+ }
+ res = (name == null) ? dir : dir.open(name);
+ } else if (name == null)
+ res = new PlainFile(new File(dirname));
+ else
+ res = new PlainFile(new File(dirname, name));
+ if (!res.exists())
+ res = null;
+ return res;
+ }
+
+ /** create file given by a fully qualified name from root directory `outdir';
+ * create intermediate directories if they do not exist already
+ */
+ public static File create(File outdir, String name,
+ String suffix) throws IOException {
+ int start = 0;
+ int end = name.indexOf('.');
+ while (end >= start) {
+ outdir = new File(outdir, name.substring(start, end));
+ if (!outdir.exists())
+ outdir.mkdir();
+ start = end + 1;
+ end = name.indexOf('.', start);
+ }
+ return new File(outdir, name.substring(start) + suffix);
+ }
+}
+
+class PlainFile extends AbstractFile {
+ File f;
+
+ PlainFile(File f) {
+ this.f = f;
+ }
+
+ public String getName() {
+ return f.getName();
+ }
+
+ public String getPath() {
+ return f.getPath();
+ }
+
+ public boolean exists() {
+ return f.exists();
+ }
+
+ public boolean isDirectory() {
+ return f.isDirectory();
+ }
+
+ public byte[] read() throws IOException {
+ FileInputStream in = new FileInputStream(f);
+ int rest = (int)f.length();
+ byte[] buf = new byte[rest];
+ do {
+ int res = in.read(buf, buf.length - rest, rest);
+ if (res == -1)
+ throw new IOException("read error");
+ rest -= res;
+ } while (rest > 0);
+ in.close();
+ return buf;
+ }
+
+ public String[] list() throws IOException {
+ File[] fs = f.listFiles();
+ if (fs == null)
+ return new String[0];
+ String[] res = new String[fs.length];
+ for (int i = 0; i < fs.length; i++) {
+ res[i] = fs[i].getName();
+ if (fs[i].isDirectory() &&
+ !res[i].endsWith("/"))
+ res[i] = res[i] + "/";
+ }
+ return res;
+ }
+
+ public AbstractFile open(String name) {
+ return new PlainFile(new File(f, name));
+ }
+}
+
+class ZippedFile extends AbstractFile {
+ ZipDir dir;
+ ZipEntry zipEntry;
+
+ {
+ separator = '/';
+ }
+
+ ZippedFile(ZipDir dir, String name) {
+ this.dir = dir;
+ if (dir.zipFile != null) {
+ name = name.replace(File.separatorChar, separator);
+ zipEntry = this.dir.zipFile.getEntry(name);
+ if (zipEntry == null)
+ zipEntry = this.dir.zipFile.getEntry(name + separator);
+ }
+ }
+
+ public String getName() {
+ return zipEntry.getName();
+ }
+
+ public String getPath() {
+ return dir.getPath() + "(" + zipEntry.getName() + ")";
+ }
+
+ public boolean exists() {
+ return (zipEntry != null);
+ }
+
+ public boolean isDirectory() {
+ return zipEntry.isDirectory();
+ }
+
+ public byte[] read() throws IOException {
+ InputStream in = dir.zipFile.getInputStream(zipEntry);
+ int rest = (int)zipEntry.getSize();
+ byte[] buf = new byte[rest];
+ do {
+ int res = in.read(buf, buf.length - rest, rest);
+ if (res == -1)
+ throw new IOException("read error");
+ rest -= res;
+ } while (rest > 0);
+ in.close();
+ return buf;
+ }
+
+ public String[] list() throws IOException {
+ if (!isDirectory())
+ throw new IOException("not a directory");
+ return dir.list(zipEntry.getName());
+ }
+
+ public AbstractFile open(String name) {
+ String pathname = zipEntry.getName();
+ return new ZippedFile(dir, pathname + name);
+ }
+}
+
+class ZipDir extends AbstractFile {
+ File f;
+ ZipFile zipFile;
+
+ {
+ separator = '/';
+ }
+
+ ZipDir(File f) {
+ this.f = f;
+ try {
+ zipFile = new ZipFile(f);
+ } catch (ZipException e) {
+ } catch (IOException e) {}
+ }
+
+ public String getName() {
+ return f.getName();
+ }
+
+ public String getPath() {
+ return f.getPath();
+ }
+
+ public boolean exists() {
+ return (zipFile != null);
+ }
+
+ public boolean isDirectory() {
+ return (zipFile != null);
+ }
+
+ public byte[] read() throws IOException {
+ throw new IOException("cannot read directory");
+ }
+
+ public String[] list(String prefix) {
+ int n = 0;
+ for (Enumeration enum = zipFile.entries(); enum.hasMoreElements();) {
+ ZipEntry e = (ZipEntry)enum.nextElement();
+ if (e.getName().startsWith(prefix)) {
+ String candidate = e.getName().substring(prefix.length());
+ if (candidate.indexOf(separator) < 0)
+ n++;
+ }
+ }
+ String[] filenames = new String[n];
+ n = 0;
+ for (Enumeration enum = zipFile.entries(); enum.hasMoreElements();) {
+ ZipEntry e = (ZipEntry)enum.nextElement();
+ if (e.getName().startsWith(prefix)) {
+ String candidate = e.getName().substring(prefix.length());
+ if (candidate.indexOf(separator) < 0)
+ filenames[n++] = candidate;
+ }
+ }
+ return filenames;
+ }
+
+ public String[] list() throws IOException {
+ return list("");
+ }
+
+ public AbstractFile open(String name) {
+ return new ZippedFile(this, name);
+ }
+}
+
+final class JarArchive extends AbstractFile {
+ File f;
+ JarFile jarFile;
+ HashMap entries;
+
+ public final static String[] EMPTY = new String[0];
+
+
+ JarArchive(File f) {
+ try {
+ jarFile = new JarFile(this.f = f);
+ }
+ catch (ZipException e) {}
+ catch (IOException e) {}
+ }
+
+ public String getName() {
+ return f.getName();
+ }
+
+ public String getPath() {
+ return f.getPath();
+ }
+
+ public boolean exists() {
+ return jarFile != null;
+ }
+
+ public boolean isDirectory() {
+ return jarFile != null;
+ }
+
+ public byte[] read() throws IOException {
+ throw new IOException("cannot read archive");
+ }
+
+ private void load() {
+ entries = new HashMap();
+ if (jarFile == null)
+ return;
+ Enumeration enum = jarFile.entries();
+ while (enum.hasMoreElements()) {
+ String candidate = ((JarEntry)enum.nextElement()).getName();
+ int i = candidate.indexOf('/');
+ int j = 0;
+ HashMap files = entries;
+ while (i >= 0) {
+ String dirname = candidate.substring(j, j = (i + 1));
+ JarDirEntry dir = (JarDirEntry)files.get(dirname);
+ if (dir == null)
+ files.put(dirname, dir = new JarDirEntry(
+ candidate.substring(0, j)));
+ files = dir.entries;
+ i = candidate.indexOf('/', j);
+ }
+ if (j < (candidate.length() - 1)) {
+ String filename = candidate.substring(j);
+ JarFileEntry file = (JarFileEntry)files.get(filename);
+ if (file == null)
+ files.put(filename, new JarFileEntry(candidate));
+ }
+ }
+ }
+
+ public String[] list(String prefix) {
+ prefix = prefix.replace(File.separatorChar, '/');
+ if (entries == null)
+ load();
+ int i = prefix.indexOf('/');
+ int j = 0;
+ HashMap files = entries;
+ while (i >= 0) {
+ String dirname = prefix.substring(j, j = (i + 1));
+ JarDirEntry dir = (JarDirEntry)files.get(dirname);
+ if (dir == null)
+ return EMPTY;
+ files = dir.entries;
+ i = prefix.indexOf('/', j);
+ }
+ if (j < (prefix.length() - 1)) {
+ String filename = prefix.substring(j);
+ return (files.get(filename) != null) ? new String[]{prefix}
+ : EMPTY;
+ } else
+ return (String[])files.keySet().toArray(new String[files.size()]);
+ }
+
+ public String[] list() throws IOException {
+ return list("");
+ }
+
+ public AbstractFile open(String name) {
+ if (entries == null)
+ load();
+ name = name.replace(File.separatorChar, '/');
+ int i = name.indexOf('/');
+ int j = 0;
+ int namelen = name.length();
+ HashMap files = entries;
+ while (i >= 0) {
+ String dirname = name.substring(j, j = (i + 1));
+ if (files != null) {
+ JarDirEntry dir = (JarDirEntry)files.get(dirname);
+ if (dir == null)
+ files = null;
+ else if (j == namelen)
+ return dir;
+ else
+ files = dir.entries;
+ }
+ i = name.indexOf('/', j);
+ }
+ if (j < (namelen - 1)) {
+ String filename = name.substring(j);
+ if (files == null)
+ return new NoJarFileEntry(name);
+ JarFileEntry file = (JarFileEntry)files.get(filename);
+ if (file == null)
+ return new NoJarFileEntry(name);
+ else
+ return file;
+ } else
+ return new NoJarDirEntry(name);
+ }
+
+ static class NoJarDirEntry extends AbstractFile {
+ String name;
+
+ NoJarDirEntry(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name.substring(
+ name.lastIndexOf('/', name.length() - 2) + 1);
+ }
+
+ public String getPath() {
+ return name;
+ }
+
+ public String getFullName() {
+ return name;
+ }
+
+ public boolean exists() {
+ return false;
+ }
+
+ public boolean isDirectory() {
+ return true;
+ }
+
+ public String[] list() throws IOException {
+ throw new IOException("not a directory");
+ }
+
+ public byte[] read() throws IOException {
+ throw new IOException("cannot read archive");
+ }
+
+ public AbstractFile open(String fname) {
+ throw new Error("cannot open archive entry");
+ }
+ }
+
+ final class JarDirEntry extends NoJarDirEntry {
+ HashMap entries;
+
+ JarDirEntry(String name) {
+ super(name);
+ this.entries = new HashMap();
+ }
+
+ public String getPath() {
+ return JarArchive.this.getPath() + "(" + name + ")";
+ }
+
+ public boolean exists() {
+ return true;
+ }
+
+ public String[] list() throws IOException {
+ return JarArchive.this.list(name);
+ }
+
+ public AbstractFile open(String fname) {
+ fname = fname.replace(File.separatorChar, '/');
+ return JarArchive.this.open(name + fname);
+ }
+ }
+
+ static class NoJarFileEntry extends AbstractFile {
+ String name;
+
+ NoJarFileEntry(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name.substring(
+ name.lastIndexOf('/', name.length() - 1) + 1);
+ }
+
+ public String getFullName() {
+ return name;
+ }
+
+ public String getPath() {
+ return name;
+ }
+
+ public boolean exists() {
+ return false;
+ }
+
+ public boolean isDirectory() {
+ return false;
+ }
+
+ public String[] list() throws IOException {
+ throw new IOException("not a directory");
+ }
+
+ public byte[] read() throws IOException {
+ throw new IOException("cannot read archive");
+ }
+
+ public AbstractFile open(String fname) {
+ throw new Error("not a directory");
+ }
+ }
+
+ final class JarFileEntry extends NoJarFileEntry {
+
+ JarFileEntry(String name) {
+ super(name);
+ }
+
+ public String getPath() {
+ return JarArchive.this.getPath() + "(" + name + ")";
+ }
+
+ public boolean exists() {
+ return true;
+ }
+
+ public byte[] read() throws IOException {
+ JarEntry jarEntry = jarFile.getJarEntry(name);
+ if (jarEntry == null)
+ throw new IOException("unable to read " + name);
+ InputStream in = jarFile.getInputStream(jarEntry);
+ int rest = (int)jarEntry.getSize();
+ byte[] buf = new byte[rest];
+ do {
+ int res = in.read(buf, buf.length - rest, rest);
+ if (res == -1)
+ throw new IOException("read error");
+ rest -= res;
+ } while (rest > 0);
+ in.close();
+ return buf;
+ }
+ }
+}
diff --git a/sources/scalac/util/AbstractFileReader.java b/sources/scalac/util/AbstractFileReader.java
new file mode 100644
index 0000000000..0d18292838
--- /dev/null
+++ b/sources/scalac/util/AbstractFileReader.java
@@ -0,0 +1,107 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scalac.util;
+
+import java.io.*;
+
+
+public class AbstractFileReader {
+
+ /** the buffer containing the file
+ */
+ public byte[] buf;
+
+ /** the current input pointer
+ */
+ public int bp;
+
+ /** constructor
+ */
+ public AbstractFileReader(AbstractFile f) throws IOException {
+ buf = f.read();
+ bp = 0;
+ }
+
+ /** return byte at offset 'pos'
+ */
+ public byte byteAt(int pos) {
+ return buf[pos];
+ }
+
+ /** read a byte
+ */
+ public byte nextByte() {
+ return buf[bp++];
+ }
+
+ /** read some bytes
+ */
+ public byte[] nextBytes(int len) {
+ byte[] res = new byte[len];
+ System.arraycopy(buf, bp, res, 0, len);
+ bp += len;
+ return res;
+ }
+
+ /** read a character
+ */
+ public char nextChar() {
+ return
+ (char)(((buf[bp++] & 0xff) << 8) +
+ (buf[bp++] & 0xff));
+ }
+
+ /** read an integer
+ */
+ public int nextInt() {
+ return ((buf[bp++] & 0xff) << 24) +
+ ((buf[bp++] & 0xff) << 16) +
+ ((buf[bp++] & 0xff) << 8) +
+ (buf[bp++] & 0xff);
+ }
+
+ /** extract a character at position bp from buf
+ */
+ public char getChar(int bp) {
+ return (char)(((buf[bp] & 0xff) << 8) + (buf[bp+1] & 0xff));
+ }
+
+ /** extract an integer at position bp from buf
+ */
+ public int getInt(int bp) {
+ return ((buf[bp ] & 0xff) << 24) +
+ ((buf[bp+1] & 0xff) << 16) +
+ ((buf[bp+2] & 0xff) << 8) +
+ (buf[bp+3] & 0xff);
+ }
+
+ /** extract a long integer at position bp from buf
+ */
+ public long getLong(int bp) {
+ return ((long)(getInt(bp)) << 32) + (getInt(bp + 4) & 0xffffffffL);
+ }
+
+ /** extract a float at position bp from buf
+ */
+ public strictfp float getFloat(int bp) {
+ return Float.intBitsToFloat(getInt(bp));
+ }
+
+ /** extract a double at position bp from buf
+ */
+ public strictfp double getDouble(int bp) {
+ return Double.longBitsToDouble(getLong(bp));
+ }
+
+ /** skip next 'n' bytes
+ */
+ public void skip(int n) {
+ bp += n;
+ }
+}
diff --git a/sources/scalac/util/ArrayApply.java b/sources/scalac/util/ArrayApply.java
new file mode 100644
index 0000000000..087278af5b
--- /dev/null
+++ b/sources/scalac/util/ArrayApply.java
@@ -0,0 +1,54 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scalac.util;
+
+public abstract class ArrayApply {
+
+ //########################################################################
+ // Arrays interface - Object
+
+ public static String toString(Object[] src) {
+ return append(new StringBuffer(), src).toString();
+ }
+
+ public static String toString(Object[] src, String infix) {
+ return append(new StringBuffer(), src, infix).toString();
+ }
+
+ public static String toString(Object[] src, String prefix, String infix,
+ String suffix)
+ {
+ return append(new StringBuffer(), src, prefix,infix,suffix).toString();
+ }
+
+ //########################################################################
+ // Arrays interface - StringBuffer
+
+ public static StringBuffer append(StringBuffer buffer, Object[] src) {
+ return append(buffer, src, "[", ",", "]");
+ }
+
+ public static StringBuffer append(StringBuffer buffer, Object[] src,
+ String infix)
+ {
+ return append(buffer, src, "", infix, "");
+ }
+
+ public static StringBuffer append(StringBuffer buffer, Object[] src,
+ String prefix, String infix, String suffix)
+ {
+ buffer.append(prefix);
+ for (int i = 0; i < src.length; i++) {
+ if (i > 0) buffer.append(infix);
+ buffer.append(src[i]);
+ }
+ buffer.append(suffix);
+ return buffer;
+ }
+}
diff --git a/sources/scalac/util/ClassPath.java b/sources/scalac/util/ClassPath.java
new file mode 100644
index 0000000000..b083c5485b
--- /dev/null
+++ b/sources/scalac/util/ClassPath.java
@@ -0,0 +1,161 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scalac.util;
+
+import java.io.*;
+import java.util.*;
+
+
+public class ClassPath {
+
+ /** the character separating files
+ */
+ protected static String FILE_SEP = File.separator;
+
+ /** the separator in class path specifications
+ */
+ protected static String PATH_SEP =
+ System.getProperty("path.separator");
+
+ /** the default class path
+ */
+ public static String CLASS_PATH =
+ System.getProperty("scala.class.path",
+ System.getProperty("java.class.path"));
+
+ /** the default source path
+ */
+ public static String SOURCE_PATH = null;
+
+ /** the default boot class path
+ */
+ public static String BOOT_PATH =
+ appendPath(appendPath("", System.getProperty("sun.boot.class.path")),
+ System.getProperty("scala.boot.class.path")).substring(1);
+
+ /** the default extension path
+ */
+ public static String EXTENSION_PATH =
+ System.getProperty("java.ext.dirs");
+
+ /** the various class path roots
+ */
+ protected String[] root;
+
+ /** print searches in the class path
+ */
+ public boolean printSearch;
+
+
+ /** classpath constructor
+ */
+ public ClassPath() {
+ this(CLASS_PATH);
+ }
+
+ public ClassPath(String classpath) {
+ this(classpath, SOURCE_PATH, BOOT_PATH, EXTENSION_PATH);
+ }
+
+ public ClassPath(String classpath, String sourcepath,
+ String bootclasspath, String extdirs)
+ {
+ String path = "";
+ path = appendPath(path, bootclasspath);
+ path = appendExtDirs(path, extdirs);
+ path = appendPath(path, classpath);
+ path = appendPath(path, sourcepath);
+ root = parse(path.substring(1));
+ }
+
+ /** append an additional path
+ */
+ protected static String appendPath(String path, String addpath) {
+ return addpath == null ? path : path + PATH_SEP + addpath;
+ }
+
+ /** append files from the extension directories
+ */
+ protected String appendExtDirs(String path, String extdirs) {
+ if (extdirs != null) {
+ extdirs += PATH_SEP;
+ int length = extdirs.length();
+ int i = 0;
+ while (i < length) {
+ int k = extdirs.indexOf(PATH_SEP, i);
+ String dirname = extdirs.substring(i, k);
+ String[] ext;
+ if ((dirname != null) &&
+ (dirname.length() > 0) &&
+ ((ext = new File(dirname).list()) != null)) {
+ if (!dirname.endsWith(FILE_SEP))
+ dirname += FILE_SEP;
+ for (int j = 0; j < ext.length; j++)
+ if (ext[j].endsWith(".jar") ||
+ ext[j].endsWith(".zip"))
+ path = appendPath(path, dirname + ext[j]);
+ }
+ i = k + 1;
+ }
+ }
+ return path;
+ }
+
+ /** parse a class path specification and return an array
+ * of existing class file locations
+ */
+ protected String[] parse(String path) {
+ path += PATH_SEP;
+ Vector components = new Vector();
+ int i = 0;
+ while (i < path.length()) {
+ int j = path.indexOf(PATH_SEP, i);
+ String subpath = path.substring(i, j);
+ if (new File(subpath).exists())
+ components.add(subpath);
+ i = j + 1;
+ }
+ return (String[])components.toArray(
+ new String[components.size()]);
+ }
+
+ /** find file with given name in class path and return an abstract
+ * file representation
+ */
+ public AbstractFile openFile(String name) throws FileNotFoundException {
+ if (printSearch)
+ System.out.println("looking for " + name);
+ for (int i = 0; i < root.length; i++) {
+ if (printSearch)
+ System.out.println(" in " + root[i]);
+ AbstractFile f = AbstractFile.open(root[i], name);
+ if (f != null)
+ return f;
+ }
+ throw new FileNotFoundException("file '" + name +
+ "' not found in classpath");
+ }
+
+ public String[] components() {
+ return root;
+ }
+
+ /** return a textual representation of this class path
+ */
+ public String toString() {
+ if (root.length == 0)
+ return "";
+ else if (root.length == 1)
+ return root[0];
+ String path = root[0];
+ for (int i = 1; i < root.length; i++)
+ path += PATH_SEP + root[i];
+ return path;
+ }
+}
diff --git a/sources/scalac/util/Debug.java b/sources/scalac/util/Debug.java
new file mode 100644
index 0000000000..4597463aab
--- /dev/null
+++ b/sources/scalac/util/Debug.java
@@ -0,0 +1,465 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+\* */
+
+// $Id$
+
+package scalac.util;
+
+import java.util.HashMap;
+
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Method;
+import java.lang.reflect.Field;
+
+import scalac.Global;
+import scalac.ApplicationError;
+import scalac.symtab.Type;
+import scalac.symtab.Symbol;
+import scalac.symtab.Scope;
+
+/**
+ * Debugging class, used e.g. to obtain string representations of
+ * compiler data structures that are not "pretty-printed" and thus
+ * easier to relate to the source code.
+ *
+ * All methods are static to be easily useable in any context.
+ *
+ * @author Michel Schinz
+ * @version 1.0
+ */
+
+public abstract class Debug {
+
+ //########################################################################
+ // Debug interface - abort
+
+ public static Error abort() {
+ return new ApplicationError();
+ }
+
+ public static Error abort(String message) {
+ return new ApplicationError(message);
+ }
+
+ public static Error abort(Object object) {
+ return new ApplicationError(object);
+ }
+
+ public static Error abort(Throwable cause) {
+ return new ApplicationError(cause);
+ }
+
+ public static Error abort(String message, Object object) {
+ return new ApplicationError(message, object);
+ }
+
+ public static Error abort(String message, Throwable cause) {
+ return new ApplicationError(message, cause);
+ }
+
+ public static Error abort(Object object, Throwable cause) {
+ return new ApplicationError(object, cause);
+ }
+
+ public static Error abort(String message, Object object, Throwable cause) {
+ return new ApplicationError(message, object, cause);
+ }
+
+ //########################################################################
+ // Debug interface - log
+
+ public static boolean log(String message) {
+ return Global.instance.log(message);
+ }
+
+ public static boolean log(String message, Object object) {
+ return log(message + ": " + show(object));
+ }
+
+ //########################################################################
+ // Debug interface - handlers
+
+ public static final HashMap/*<Class,DebugHandler>*/ handlers;
+
+ static {
+ handlers = new HashMap();
+ handlers.put(String.class, DebugToStringHandler.instance);
+ handlers.put(Type.class, DebugType.instance);
+ handlers.put(Symbol.class, DebugSymbol.instance);
+ handlers.put(Scope.class, DebugScope.instance);
+ }
+
+ public static DebugHandler getHandler(Object that) {
+ if (that == null) return DebugDefaultHandler.instance;
+ return getHandler(that.getClass());
+ }
+
+ public static DebugHandler getHandler(Class clasz) {
+ if (clasz == null) return DebugDefaultHandler.instance;
+ Object handler = handlers.get(clasz);
+ if (handler != null) return (DebugHandler)handler;
+ return getHandler(clasz.getSuperclass());
+ }
+
+ //########################################################################
+ // Debug interface - toString
+
+ public static String toString(Object that) {
+ return show(that);
+ }
+
+ //########################################################################
+ // Debug interface - show
+
+ public static String show(Object that) {
+ return show(that, getHandler(that));
+ }
+
+ public static String show(Object that, DebugHandler handler) {
+ StringBuffer buffer = new StringBuffer();
+ handler.append0(buffer, that);
+ return buffer.toString();
+ }
+
+ //########################################################################
+ // Debug interface - append
+
+ public static void append(StringBuffer buffer, Object that) {
+ getHandler(that).append0(buffer, that);
+ }
+
+ public static void appendDefault(StringBuffer buffer, Object that) {
+ if (that == null) { buffer.append("null"); return; }
+ if (!that.getClass().isArray()) {
+ appendObject(buffer, that);
+ } else {
+ appendArray(buffer, (Object[])that);
+ }
+ }
+
+ public static void appendObject(StringBuffer buffer, Object that) {
+ if (that == null) { buffer.append("null"); return; }
+ buffer.append(getClassName(that));
+ Class owner = null;
+ if (hasToString(that.getClass())) {
+ buffer.append('(');
+ buffer.append(that);
+ buffer.append(')');
+ } else {
+ int code = System.identityHashCode(that);
+ buffer.append('@');
+ buffer.append(Integer.toHexString(code));
+ }
+ }
+
+ public static void appendArray(StringBuffer buffer, Object[] that) {
+ if (that == null) { buffer.append("null"); return; }
+ buffer.append('[');
+ for (int i = 0; i < that.length; i++) {
+ if (i > 0) buffer.append(',');
+ append(buffer, that[i]);
+ }
+ buffer.append(']');
+ }
+
+ //########################################################################
+ // Debug interface - utils
+
+ public static final Class OBJECT_CLASS = Object.class;
+
+ public static boolean hasToString(Class clasz) {
+ try {
+ Method toString = clasz.getMethod("toString", new Class[0]);
+ return toString.getDeclaringClass() != OBJECT_CLASS;
+ } catch (NoSuchMethodException excpetion) {
+ return false;
+ } catch (SecurityException excpetion) {
+ return false;
+ }
+ }
+
+ public static String getClassName(Object object) {
+ if (object == null) return "null";
+ Class clasz = object.getClass();
+ String name = clasz.getName();
+ if (!name.endsWith("$$Var")) return name;
+ Class superclass = clasz.getSuperclass();
+ Field[] fields = superclass.getDeclaredFields();
+ for (int i = 0; i < fields.length; i++) {
+ try {
+ Field field = fields[i];
+ if (field.getType() != clasz) continue;
+ if (!Modifier.isStatic(field.getModifiers())) continue;
+ Object value = field.get(null);
+ if (value != object) continue;
+ return name + "[" + field.getName() + "]";
+ } catch (IllegalAccessException exception) {
+ // continue
+ }
+ }
+ return name;
+ }
+
+ //########################################################################
+}
+
+public interface DebugHandler {
+
+ //########################################################################
+ // DebugHandler interface
+
+ public void append0(StringBuffer buffer, Object that);
+
+ //########################################################################
+}
+
+public abstract class DebugAbstractHandler implements DebugHandler {
+
+ //########################################################################
+ // DebugAbstractHandler interface
+
+ public String show(Object that) {
+ return Debug.show(that, this);
+ }
+
+ //########################################################################
+}
+
+public class DebugDefaultHandler extends DebugAbstractHandler {
+
+ //########################################################################
+ // DebugDefaultHandler interface
+
+ public static DebugDefaultHandler instance = new DebugDefaultHandler();
+
+ //########################################################################
+ // DebugHandler interface
+
+ public void append0(StringBuffer buffer, Object that) {
+ Debug.appendDefault(buffer, that);
+ }
+
+ //########################################################################
+}
+
+public class DebugToStringHandler extends DebugAbstractHandler {
+
+ //########################################################################
+ // DebugToStringHandler interface
+
+ public static DebugToStringHandler instance = new DebugToStringHandler();
+
+ //########################################################################
+ // DebugHandler interface
+
+ public void append0(StringBuffer buffer, Object that) {
+ buffer.append(that);
+ }
+
+ //########################################################################
+}
+
+public class DebugObject extends DebugAbstractHandler {
+
+ //########################################################################
+ // DebugObject interface
+
+ public static DebugObject instance = new DebugObject();
+
+ public void append1(StringBuffer buffer, Object that) {
+ Debug.appendObject(buffer, that);
+ }
+
+ //########################################################################
+ // DebugHandler interface
+
+ public void append0(StringBuffer buffer, Object that) {
+ append1(buffer, (Object)that);
+ }
+
+ //########################################################################
+}
+
+public class DebugArray extends DebugAbstractHandler {
+
+ //########################################################################
+ // DebugArray interface
+
+ public static DebugArray instance = new DebugArray();
+
+ public void append1(StringBuffer buffer, Object[] that) {
+ Debug.appendArray(buffer, that);
+ }
+
+ //########################################################################
+ // DebugHandler interface
+
+ public void append0(StringBuffer buffer, Object that) {
+ append1(buffer, (Object[])that);
+ }
+
+ //########################################################################
+}
+
+public class DebugType extends DebugAbstractHandler {
+
+ //########################################################################
+ // DebugType interface
+
+ public static DebugType instance = new DebugType();
+
+ public void append1(StringBuffer buffer, Type that) {
+ switch (that) {
+
+ case ErrorType:
+ buffer.append("ErrorType");
+ return;
+
+ case AnyType:
+ buffer.append("AnyType");
+ return;
+
+ case NoType:
+ buffer.append("NoType");
+ return;
+
+ case ThisType(Symbol symbol):
+ buffer.append("ThisType(");
+ Debug.append(buffer, symbol);
+ buffer.append(')');
+ return;
+
+ case TypeRef(Type prefix, Symbol symbol, Type[] args) :
+ buffer.append("TypeRef(");
+ Debug.append(buffer, prefix);
+ buffer.append(',');
+ Debug.append(buffer, symbol);
+ buffer.append(',');
+ Debug.append(buffer, args);
+ buffer.append(')');
+ return;
+
+ case SingleType(Type prefix, Symbol symbol):
+ buffer.append("SingleType(");
+ Debug.append(buffer, prefix);
+ buffer.append(',');
+ Debug.append(buffer, symbol);
+ buffer.append(')');
+ return;
+
+ case CompoundType(Type[] basetypes, Scope members):
+ buffer.append("CompoundType(");
+ Debug.append(buffer, basetypes);
+ buffer.append(',');
+ Debug.append(buffer, members);
+ buffer.append(')');
+ return;
+
+ case MethodType(Symbol[] vparams, Type result):
+ buffer.append("MethodType(");
+ Debug.append(buffer, vparams);
+ buffer.append(',');
+ Debug.append(buffer, result);
+ buffer.append(')');
+ return;
+
+ case PolyType(Symbol[] tparams, Type result):
+ buffer.append("PolyType(");
+ Debug.append(buffer, tparams);
+ buffer.append(',');
+ Debug.append(buffer, result);
+ buffer.append(')');
+ return;
+
+ case CovarType(Type tp):
+ buffer.append("CovarType(");
+ Debug.append(buffer, tp);
+ buffer.append(')');
+ return;
+
+ case OverloadedType(Symbol[] alts, Type[] alttypes):
+ buffer.append("OverloadedType(");
+ Debug.append(buffer, alts);
+ buffer.append(',');
+ Debug.append(buffer, alttypes);
+ buffer.append(')');
+ return;
+
+ default:
+ Debug.appendDefault(buffer, that);
+ return;
+ }
+ }
+
+ //########################################################################
+ // DebugHandler interface
+
+ public void append0(StringBuffer buffer, Object that) {
+ append1(buffer, (Type)that);
+ }
+
+ //########################################################################
+}
+
+public class DebugSymbol extends DebugAbstractHandler {
+
+ //########################################################################
+ // DebugSymbol interface
+
+ public static DebugSymbol instance = new DebugSymbol();
+
+ public void append1(StringBuffer buffer, Symbol that) {
+ if (that != Symbol.NONE && that != Symbol.ERROR) {
+ buffer.append(that.kindString()).append(' ');
+ if (that.owner() != Global.instance.definitions.ROOT_CLASS) {
+ buffer.append(that.owner().fullName());
+ buffer.append("::");
+ }
+ }
+ buffer.append(that.name);
+ if (Global.instance.uniqid) {
+ buffer.append('#');
+ buffer.append(Global.instance.uniqueID.id(that));
+ }
+ }
+
+ //########################################################################
+ // DebugHandler interface
+
+ public void append0(StringBuffer buffer, Object that) {
+ append1(buffer, (Symbol)that);
+ }
+
+ //########################################################################
+}
+
+public class DebugScope extends DebugAbstractHandler {
+
+ //########################################################################
+ // DebugScope interface
+
+ public static DebugScope instance = new DebugScope();
+
+ public void append1(StringBuffer buffer, Scope that) {
+ buffer.append('{');
+ for (Scope.SymbolIterator i = that.iterator(); i.hasNext();) {
+ Debug.append(buffer, i.next());
+ if (i.hasNext()) buffer.append(',');
+ }
+ buffer.append('}');
+ }
+
+ //########################################################################
+ // DebugHandler interface
+
+ public void append0(StringBuffer buffer, Object that) {
+ append1(buffer, (Scope)that);
+ }
+
+ //########################################################################
+}
+
diff --git a/sources/scalac/util/FreshNameCreator.java b/sources/scalac/util/FreshNameCreator.java
new file mode 100644
index 0000000000..fb69ad5c33
--- /dev/null
+++ b/sources/scalac/util/FreshNameCreator.java
@@ -0,0 +1,59 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scalac.util;
+
+import java.util.HashMap;
+
+public class FreshNameCreator {
+
+ protected int counter = 0;
+ protected HashMap counters = new HashMap();
+
+ /**
+ * Create a fresh name with the given prefix. It is guaranteed
+ * that the returned name has never been returned by a previous
+ * call to this function with the same separator character (which
+ * has to be a non-digit).
+ */
+ public Name newName(String prefix, char separator) {
+ prefix += separator;
+ Integer ival = (Integer)counters.get(prefix);
+ if (ival == null)
+ counters.put(prefix, ival = new Integer(0));
+ else
+ counters.put(prefix, ival = new Integer(ival.intValue() + 1));
+ return Name.fromString(prefix + ival);
+ }
+
+ /** Same, with `$' as the separator character
+ */
+ public Name newName(String prefix) {
+ return newName(prefix, '$');
+ }
+
+ /** Same, but with a name as prefix. The new name is a type
+ * (respectively, constructor) name if the prefix is one.
+ */
+ public Name newName(Name prefixName, char separator) {
+ Name name = newName(prefixName.toString(), separator);
+ if (prefixName.isTypeName()) return name.toTypeName();
+ else if (prefixName.isConstrName()) return name.toConstrName();
+ else return name;
+ }
+
+ /** Same, with `$' as the separator character
+ */
+ public Name newName(Name prefix) {
+ return newName(prefix, '$');
+ }
+
+ public Name newName() {
+ return Name.fromString("$" + (counter++) + "$");
+ }
+}
diff --git a/sources/scalac/util/Name.java b/sources/scalac/util/Name.java
new file mode 100644
index 0000000000..0c04fe2dcb
--- /dev/null
+++ b/sources/scalac/util/Name.java
@@ -0,0 +1,391 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scalac.util;
+
+public final class Name {
+
+/** address in the name memory
+ */
+ public int index;
+
+/** length of the name
+ */
+ private int len;
+
+/** next name in the same hash bucket
+ */
+ private Name next;
+
+ private final static int HASH_SIZE = 0x8000;
+ private final static int HASH_MASK = 0x7FFF;
+ private final static int NAME_SIZE = 0x20000;
+
+/** memory to store all names sequentially
+ */
+ public static byte[] names = new byte[NAME_SIZE];
+ private static int nc = 0;
+
+/** hashtable for finding term names quickly
+ */
+ private static Name[] termHashtable = new Name[HASH_SIZE];
+
+/** hashtable for finding type names quickly
+ */
+ private static Name[] typeHashtable = new Name[HASH_SIZE];
+
+/** hashtable for finding constructor names quickly
+ */
+ private static Name[] constrHashtable = new Name[HASH_SIZE];
+
+/** Constructor
+ */
+ Name(int index, int len, Name[] table, int hash) {
+ this.index = index;
+ this.len = len;
+ this.next = table[hash];
+ table[hash] = this;
+ }
+
+/** the hashcode of a name
+ */
+ private static int hashValue(byte cs[], int offset, int len) {
+ if (len > 0)
+ return
+ len * (41 * 41 * 41) +
+ cs[offset] * (41 * 41) +
+ cs[offset + len - 1] * 41 +
+ cs[offset + (len >> 1)];
+ else
+ return 0;
+ }
+
+/** is (the ascii representation of) name equal to
+ * cs[offset..offset+len-1]?
+ */
+ private static boolean equals(int index, byte cs[], int offset, int len) {
+ int i = 0;
+ while ((i < len) && (names[index + i] == cs[offset + i]))
+ i++;
+ return i == len;
+ }
+
+/** the empty name
+ */
+ public static final Name EMPTY = fromString("");
+
+/** create a term name from the bytes in cs[offset..offset+len-1].
+ * assume that bytes are in ascii format.
+ */
+ public static Name fromAscii(byte cs[], int offset, int len) {
+ int h = hashValue(cs, offset, len) & HASH_MASK;
+ Name n = termHashtable[h];
+ while ((n != null) && (n.len != len || !equals(n.index, cs, offset, len)))
+ n = n.next;
+ if (n == null) {
+ n = new Name(nc, len, termHashtable, h);
+ for (int i = 0; i < len; i++)
+ {
+ if (nc == names.length)
+ {
+ byte[] newnames = new byte[names.length * 2];
+ System.arraycopy(names, 0, newnames, 0, names.length);
+ names = newnames;
+ }
+ names[nc++] = cs[offset + i];
+ }
+ if (len == 0)
+ nc++;
+ }
+ return n;
+ }
+
+/** create a name from the bytes in cs[offset..offset+len-1];
+ * assume that characters are in source format
+ */
+ public static Name fromSource(byte cs[], int offset, int len) {
+ byte[] ascii = new byte[len * 2];
+ int alen = SourceRepresentation.source2ascii(cs, offset, len, ascii);
+ return fromAscii(ascii, 0, alen);
+ }
+
+/** create a name from the characters in string s
+ */
+ public static Name fromString(String s) {
+ byte[] source = SourceRepresentation.string2source(s);
+ return fromSource(source, 0, source.length);
+ }
+
+/** copy bytes of this name to buffer cs, starting at offset
+ */
+ public void copyAscii(byte cs[], int offset) {
+ System.arraycopy(names, index, cs, offset, len);
+ }
+
+/** return the ascii representation of this name
+ */
+ public byte[] toAscii() {
+ byte[] ascii = new byte[len];
+ System.arraycopy(names, index, ascii, 0, len);
+ return ascii;
+ }
+
+/** return the source representation of this name
+ */
+ public byte[] toSource() {
+ return SourceRepresentation.string2source(toString());
+ }
+
+/** return the string representation of this name
+ */
+ public String toString() {
+ return SourceRepresentation.ascii2string(names, index, len);
+ }
+
+/** is this name a term name?
+ */
+ public boolean isTermName() {
+ int h = hashValue(names, index, len) & HASH_MASK;
+ Name n = termHashtable[h];
+ while (n != null && n != this)
+ n = n.next;
+ return n == this;
+ }
+
+/** is this name a type name?
+ */
+ public boolean isTypeName() {
+ int h = hashValue(names, index, len) & HASH_MASK;
+ Name n = typeHashtable[h];
+ while (n != null && n != this)
+ n = n.next;
+ return n == this;
+ }
+
+/** is this name a type name?
+ */
+ public boolean isConstrName() {
+ int h = hashValue(names, index, len) & HASH_MASK;
+ Name n = constrHashtable[h];
+ while (n != null && n != this)
+ n = n.next;
+ return n == this;
+ }
+
+/** create a term name corresponding to this name
+ */
+ public Name toTermName() {
+ int h = hashValue(names, index, len) & HASH_MASK;
+ Name n = termHashtable[h];
+ while (n != null && n.index != index)
+ n = n.next;
+ if (n == null) {
+ n = new Name(index, len, termHashtable, h);
+ }
+ return n;
+ }
+
+/** create a type name corresponding to this name
+ */
+ public Name toTypeName() {
+ int h = hashValue(names, index, len) & HASH_MASK;
+ Name n = typeHashtable[h];
+ while (n != null && n.index != index)
+ n = n.next;
+ if (n == null) {
+ n = new Name(index, len, typeHashtable, h);
+ }
+ return n;
+ }
+
+/** create a constructor name corresponding to this name
+ */
+ public Name toConstrName() {
+ int h = hashValue(names, index, len) & HASH_MASK;
+ Name n = constrHashtable[h];
+ while (n != null && n.index != index)
+ n = n.next;
+ if (n == null) {
+ n = new Name(index, len, constrHashtable, h);
+ }
+ return n;
+ }
+
+/** return the string hash value of this name
+ */
+ public int hashCode() {
+ return index;
+ }
+
+/** returns the length of this name
+ */
+ public int length() {
+ return len;
+ }
+
+/** returns i'th byte of this name
+ */
+ public byte sub(int i) {
+ return names[index + i];
+ }
+
+/** returns first occurrence of byte b in this name, len if not found
+ */
+ public int pos(byte b) {
+ return pos(b, 0);
+ }
+
+/** returns first occurrence of byte b in this name from `start', len if not found
+ */
+ public int pos(byte b, int start) {
+ int i = start;
+ while (i < len && names[index + i] != b)
+ i++;
+ return i;
+ }
+
+/** returns last occurrence of byte b in this name, -1 if not found.
+ */
+ public int lastPos(byte b) {
+ int i = len - 1;
+ while (i >= 0 && names[index + i] != b)
+ i--;
+ return i;
+ }
+
+/** does this name start with prefix?
+ */
+ public boolean startsWith(Name prefix) {
+ int i = 0;
+ while ((i < prefix.len) &&
+ (i < len) &&
+ (names[index + i] == names[prefix.index + i]))
+ i++;
+ return i == prefix.len;
+ }
+
+/** does this name end with suffix?
+ */
+ public boolean endsWith(Name suffix) {
+ int i = len - 1;
+ int j = suffix.len - 1;
+ while ((j >= 0) && (i >= 0) &&
+ (names[index + i] == names[suffix.index + j])) {
+ i--;
+ j--;
+ }
+ return j < 0;
+ }
+
+/** returns the subName starting at position start, excluding position end
+ */
+ public Name subName(int start, int end) {
+ if (end < start)
+ end = start;
+ byte[] ascii = new byte[end - start];
+ System.arraycopy(names, index + start, ascii, 0, end - start);
+ return fromAscii(ascii, 0, ascii.length);
+ }
+
+/** replace all `from' characters with `to'
+ */
+ public Name replace(byte from, byte to) {
+ byte[] ascii = new byte[len];
+ copyAscii(ascii, 0);
+ for (int i = 0; i < len; i++)
+ if (ascii[i] == from) ascii[i] = to;
+ return fromAscii(ascii, 0, len);
+ }
+
+/** returns the concatenation of this name and n
+ */
+ public Name append(Name n) {
+ byte[] ascii = new byte[len + n.len];
+ copyAscii(ascii, 0);
+ n.copyAscii(ascii, len);
+ return fromAscii(ascii, 0, ascii.length);
+ }
+
+/** returns the concatenation of all names in ns
+ */
+ public static Name concat(Name ns[]) {
+ int len = 0;
+ for (int i = 0; i < ns.length; i++)
+ len = len + ns[i].len;
+ byte[] ascii = new byte[len];
+ len = 0;
+ for (int i = 0; i < ns.length; i++) {
+ ns[i].copyAscii(ascii, len);
+ len = len + ns[i].len;
+ }
+ return fromAscii(ascii, 0, len);
+ }
+
+/** is this name an operator?
+ */
+ public boolean isOperator() {
+ return !(((names[index] >= 'a') && (names[index] <= 'z')) ||
+ ((names[index] >= 'A') && (names[index] <= 'Z')) ||
+ (names[index] == '$') ||
+ (names[index] == '_'));
+ }
+
+/** is this name a variable identifier?
+ */
+ public boolean isVariable() {
+ return ((names[index] >= 'a') && (names[index] <= 'z')) ||
+ (names[index] == '_') &&
+ this != Names.null_;
+ }
+
+ public static final Name ERROR = Name.fromString("<error>");
+
+/** precedence of this name
+ */
+ public int precedence() {
+ if (this == ERROR)
+ return -1;
+ byte ch = names[index];
+ if (((ch >= 'A') && (ch <= 'Z')) ||
+ ((ch >= 'a') && (ch <= 'z')))
+ return 1;
+ switch (ch) {
+ case '|':
+ return 2;
+ case '^':
+ return 3;
+ case '&':
+ return 4;
+ case '<':
+ case '>':
+ return 5;
+ case '=':
+ case '!':
+ return 6;
+ case ':':
+ return 7;
+ case '+':
+ case '-':
+ return 8;
+ case '*':
+ case '/':
+ case '%':
+ return 9;
+ default:
+ return 10;
+ }
+ }
+
+ public static final int TOP_PRECEDENCE = 11;
+
+/** is this operator left associative
+ */
+ public boolean leftAssoc() {
+ return names[index] != ':';
+ }
+}
diff --git a/sources/scalac/util/NameTransformer.java b/sources/scalac/util/NameTransformer.java
new file mode 100644
index 0000000000..c9b5e2183f
--- /dev/null
+++ b/sources/scalac/util/NameTransformer.java
@@ -0,0 +1,111 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scalac.util;
+
+/** A name transformer for replacing operator symbols in names by predefined
+ * names of the form $opname.
+ *
+ * @author Martin Odersky, Christine Roeckl
+ * @version 1.1
+ */
+public class NameTransformer {
+
+ public static String[] operatorName = new String[128];
+
+ static {
+ operatorName['~'] = "$tilde";
+ operatorName['='] = "$eq";
+ operatorName['<'] = "$less";
+ operatorName['>'] = "$greater";
+ operatorName['!'] = "$bang";
+ operatorName['#'] = "$hash";
+ operatorName['%'] = "$percent";
+ operatorName['^'] = "$up";
+ operatorName['&'] = "$amp";
+ operatorName['|'] = "$bar";
+ operatorName['*'] = "$times";
+ operatorName['/'] = "$div";
+ operatorName['+'] = "$plus";
+ operatorName['-'] = "$minus";
+ operatorName[':'] = "$colon";
+ }
+
+ /** Replace operator symbols by corresponding "$op_name" in names.
+ */
+ public static Name encode(Name name) {
+ int i = name.index;
+ int len = i + name.length();
+ StringBuffer res = new StringBuffer();
+ while (i < len) {
+ byte c = Name.names[i++];
+ String nop = operatorName[c];
+ if (nop == null)
+ res.append((char)c);
+ else
+ res.append(nop);
+ }
+ return Name.fromString(res.toString());
+ }
+
+ /** Replace "$op_name" by corresponding operator symbols in names.
+ */
+ public static Name decode(Name name) {
+ int i = name.index;
+ int length = i + name.length();
+ StringBuffer res = new StringBuffer();
+ while (i < length) {
+ byte c = Name.names[i++];
+ if ((char)c == '$') {
+ String op = cutOut(i, length);
+ res.append(decode("$" + op));
+ i = i + op.length();
+ }
+ else res.append((char)c);
+ }
+ return Name.fromString(res.toString());
+ }
+
+ /** Decodes (a prefix of) a string.
+ */
+ public static String decode(String string) {
+ for (int i = string.length(); i > 0; i--) {
+ String prefix = string.substring(0, i);
+ String c = lookup(prefix);
+ if (c != null) {
+ String suffix = string.substring(i, string.length());
+ return c + suffix;
+ }
+ }
+ return string;
+ }
+
+ /** Cuts out the name of an operator plus succeeding characters.
+ * Does NOT return the preceeding '$' symbol.
+ */
+ private static String cutOut(int pos, int length) {
+ int i = pos; // avoid side-effects
+ StringBuffer res = new StringBuffer();
+ while (i < length) {
+ char c = (char)Name.names[i++];
+ if (c == '$') return res.toString();
+ else res.append(c);
+ }
+ return res.toString();
+ }
+
+ /** Looks up the array entry for the operator name.
+ */
+ private static String lookup(String string) {
+ for (int i = 0; i < 128; i++) {
+ if ((operatorName[i] != null) && (string.compareTo(operatorName[i]) == 0))
+ return String.valueOf((char)i);
+ }
+ return null;
+ }
+}
diff --git a/sources/scalac/util/Names.java b/sources/scalac/util/Names.java
new file mode 100644
index 0000000000..a05aad45de
--- /dev/null
+++ b/sources/scalac/util/Names.java
@@ -0,0 +1,98 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+**
+** $Id$
+\* */
+package scalac.util;
+
+public class Names {
+
+ public static final Name ERROR = Name.ERROR;
+ public static final Name EMPTY = Name.EMPTY;
+ public static final Name WILDCARD = Name.fromString("_");
+ public static final Name COMPOUND_NAME = Name.fromString("<ct>");
+ public static final Name ANON_CLASS_NAME = Name.fromString("$class");
+
+ public static final Name _EQ = NameTransformer.encode(Name.fromString("_="));
+ public static final Name MINUS = NameTransformer.encode(Name.fromString("-"));
+ public static final Name PLUS = NameTransformer.encode(Name.fromString("+"));
+ public static final Name BANG = NameTransformer.encode(Name.fromString("!"));
+ public static final Name TILDE = NameTransformer.encode(Name.fromString("~"));
+ public static final Name EQEQ = NameTransformer.encode(Name.fromString("=="));
+ public static final Name BANGEQ = NameTransformer.encode(Name.fromString("!="));
+ public static final Name BARBAR = NameTransformer.encode(Name.fromString("||"));
+ public static final Name AMPAMP = NameTransformer.encode(Name.fromString("&&"));
+ public static final Name COLONCOLON = NameTransformer.encode(Name.fromString("::"));
+
+ public static final Name Any = Name.fromString("Any");
+ public static final Name AnyVal = Name.fromString("AnyVal");
+ public static final Name AnyRef = Name.fromString("AnyRef");
+ public static final Name Array = Name.fromString("Array");
+ public static final Name Byte = Name.fromString("Byte");
+ public static final Name Char = Name.fromString("Char");
+ public static final Name Boolean = Name.fromString("Boolean");
+ public static final Name Double = Name.fromString("Double");
+ public static final Name False = Name.fromString("False");
+ public static final Name Float = Name.fromString("Float");
+ public static final Name Function = Name.fromString("Function");
+ public static final Name Int = Name.fromString("Int");
+ public static final Name Long = Name.fromString("Long");
+ public static final Name Nil = Name.fromString("Nil");
+ public static final Name Object = Name.fromString("Object");
+ public static final Name Predef = Name.fromString("Predef");
+ public static final Name Short = Name.fromString("Short");
+ public static final Name String = Name.fromString("String");
+ public static final Name Throwable = Name.fromString("Throwable");
+ public static final Name True = Name.fromString("True");
+ public static final Name Tuple = Name.fromString("Tuple");
+ public static final Name Unit = Name.fromString("Unit");
+ public static final Name apply = Name.fromString("apply");
+ public static final Name as = Name.fromString("as");
+ public static final Name elem = Name.fromString("elem");
+ public static final Name filter = Name.fromString("filter");
+ public static final Name flatmap = Name.fromString("flatMap");
+ public static final Name foreach = Name.fromString("foreach");
+ public static final Name hashCode = Name.fromString("hashCode");
+ public static final Name is = Name.fromString("is");
+ public static final Name java = Name.fromString("java");
+ public static final Name java_lang = Name.fromString("java.lang");
+ public static final Name java_lang_Object = Name.fromString("java.lang.Object");
+ public static final Name java_lang_String = Name.fromString("java.lang.String");
+ public static final Name java_lang_Throwable = Name.fromString("java.lang.Throwable");
+ public static final Name lang = Name.fromString("lang");
+ public static final Name match = Name.fromString("match");
+ public static final Name map = Name.fromString("map");
+ public static final Name null_ = Name.fromString("null");
+ public static final Name predef = Name.fromString("predef");
+ public static final Name runtime = Name.fromString("runtime");
+ public static final Name scala = Name.fromString("scala");
+ public static final Name scala_Algebraic = Name.fromString("scala.Algebraic");
+ public static final Name scala_Any = Name.fromString("scala.Any");
+ public static final Name scala_AnyRef = Name.fromString("scala.AnyRef");
+ public static final Name scala_AnyVal = Name.fromString("scala.AnyVal");
+ public static final Name scala_Array = Name.fromString("scala.Array");
+ public static final Name scala_Boolean = Name.fromString("scala.Boolean");
+ public static final Name scala_Byte = Name.fromString("scala.Byte");
+ public static final Name scala_Case = Name.fromString("scala.Case");
+ public static final Name scala_Char = Name.fromString("scala.Char");
+ public static final Name scala_Double = Name.fromString("scala.Double");
+ public static final Name scala_Float = Name.fromString("scala.Float");
+ public static final Name scala_Function = Name.fromString("scala.Function");
+ public static final Name scala_Int = Name.fromString("scala.Int");
+ public static final Name scala_Long = Name.fromString("scala.Long");
+ public static final Name scala_Nil = Name.fromString("scala.Nil");
+ public static final Name scala_Object = Name.fromString("scala.Object");
+ public static final Name scala_Predef = Name.fromString("scala.Predef");
+ public static final Name scala_Ref = Name.fromString("scala.Ref");
+ public static final Name scala_Short = Name.fromString("scala.Short");
+ public static final Name scala_Tuple = Name.fromString("scala.Tuple");
+ public static final Name scala_Unit = Name.fromString("scala.Unit");
+ public static final Name scala_runtime = Name.fromString("scala.runtime");
+ public static final Name toString = Name.fromString("toString");
+ public static final Name this_ = Name.fromString("this");
+ public static final Name throw_ = Name.fromString("throw");
+ public static final Name update = Name.fromString("update");
+}
+
diff --git a/sources/scalac/util/OptionParser.java b/sources/scalac/util/OptionParser.java
new file mode 100644
index 0000000000..01eecb2208
--- /dev/null
+++ b/sources/scalac/util/OptionParser.java
@@ -0,0 +1,546 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scalac.util;
+
+import java.text.Format;
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import scalac.Main;
+import scalac.PhaseDescriptor;
+//import scalac.optimizer.OptimizePhase;
+
+public class CommandParser {
+
+ private final String product;
+ private final String version;
+ private final String syntax;
+ private final Reporter reporter;
+ private final List/*<ArgumentParser>*/ parsers;
+
+ public CommandParser(String product, String version, String syntax,
+ Reporter reporter)
+ {
+ this.product = product;
+ this.version = version;
+ this.syntax = syntax;
+ this.reporter = reporter;
+ this.parsers = new ArrayList();
+ }
+
+ public String product() {
+ return product;
+ }
+
+ public String version() {
+ return version;
+ }
+
+ public String syntax() {
+ return syntax;
+ }
+
+ public Reporter reporter() {
+ return reporter;
+ }
+
+ public boolean add(ArgumentParser parser) {
+ return parsers.add(parser);
+ }
+
+ public void add(int index, ArgumentParser parser) {
+ parsers.add(index, parser);
+ }
+
+ public boolean remove(ArgumentParser parser) {
+ return parsers.remove(parser);
+ }
+
+ public List parsers() {
+ return parsers;
+ }
+
+ public boolean parse(String[] args) {
+ int errors = reporter.errors();
+ for (int i = 0; i < args.length; ) {
+ for (int j = 0; j < parsers.size(); j++) {
+ ArgumentParser parser = (ArgumentParser)parsers.get(j);
+ if (parser.matches(args, i)) {
+ i = parser.consume(args, i);
+ break;
+ }
+ }
+ }
+ return reporter.errors() == errors;
+ }
+
+ public String getHelpMessage() {
+ Format format = new MessageFormat(" {0}\t {1}");
+ List options = new ArrayList(parsers.size());
+ for (int i = 0; i < parsers.size(); i++) {
+ if (!(parsers.get(i) instanceof OptionParser)) continue;
+ OptionParser parser = (OptionParser)parsers.get(i);
+ String option = parser.getHelpMessage(format);
+ if (option != null) options.add(option);
+ }
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("usage: ").append(product());
+ if (options.size() > 0) buffer.append(" <options>");
+ if (syntax != null) buffer.append(' ').append(syntax);
+ buffer.append(Strings.EOL);
+ if (options.size() > 0) {
+ buffer.append("where possible options include:");
+ buffer.append(Strings.EOL);
+ buffer.append(Strings.format(options));
+ }
+ return buffer.toString();
+ }
+
+ public void error(String message) {
+ reporter.error(product + ": " + message);
+ }
+
+ public void warning(String message) {
+ reporter.warning(product + ": " + message);
+ }
+
+ public void note(String message) {
+ reporter.note(product + ": " + message);
+ }
+}
+
+public abstract class ArgumentParser {
+
+ public final CommandParser command;
+
+ public ArgumentParser(CommandParser command) {
+ this.command = command;
+ }
+
+ public abstract boolean matches(String[] args, int index);
+ public abstract int consume(String[] args, int index);
+
+}
+
+public class UnknownArgumentParser extends ArgumentParser {
+
+ public UnknownArgumentParser(CommandParser command) {
+ super(command);
+ }
+
+ public boolean matches(String[] args, int index) {
+ return true;
+ }
+
+ public int consume(String[] args, int index) {
+ command.error("don't known what to do with '" + args[index] + "'");
+ return index + 1;
+ }
+}
+
+public class ScalaFileArgumentParser extends ArgumentParser {
+
+ public final List list;
+
+ public ScalaFileArgumentParser(CommandParser command) {
+ super(command);
+ this.list = new ArrayList();
+ }
+
+ public boolean matches(String[] args, int index) {
+ return args[index].endsWith(".scala");
+ }
+
+ public int consume(String[] args, int index) {
+ list.add(args[index]);
+ return index + 1;
+ }
+
+ public String[] toArray() {
+ return (String[])list.toArray(new String[list.size()]);
+ }
+}
+
+public class ScalaProgramArgumentParser extends ArgumentParser {
+
+ public String main;
+ public String[] args;
+
+ public ScalaProgramArgumentParser(CommandParser command) {
+ super(command);
+ }
+
+ public boolean matches(String[] args, int index) {
+ return args[index].equals("--");
+ }
+
+ public int consume(String[] args, int index) {
+ if (index + 1 < args.length) {
+ this.main = args[index + 1];
+ this.args = new String[args.length - index - 2];
+ System.arraycopy(args, index + 2, this.args, 0, this.args.length);
+ return args.length;
+ } else {
+ command.error("option --: missing module name");
+ return args.length;
+ }
+ }
+}
+
+public abstract class OptionParser extends ArgumentParser {
+
+ public final String option;
+ public final String description;
+
+ public OptionParser(CommandParser command, String option,
+ String description)
+ {
+ super(command);
+ this.option = option;
+ this.description = description;
+ }
+
+ public String getHelpSyntax() {
+ return "-" + option;
+ }
+
+ public String getHelpDescription() {
+ return description;
+ }
+
+ public void getHelpMessageArgs(List args) {
+ args.add(getHelpSyntax());
+ args.add(getHelpDescription());
+ }
+
+ public String getHelpMessage(Format format) {
+ if (description == null) return null;
+ List args = new ArrayList();
+ getHelpMessageArgs(args);
+ return format.format(args.toArray());
+ }
+
+ public void error(String message) {
+ command.error("option -" + option + ": " + message);
+ }
+
+ public void warning(String message) {
+ command.warning("option -" + option + ": " + message);
+ }
+
+ public void note(String message) {
+ command.note("option -" + option + ": " + message);
+ }
+}
+/*
+public class OptimizeOptionParser extends OptionParser {
+
+ private final OptimizePhase optimizer;
+ public boolean optimize;
+
+ public OptimizeOptionParser(CommandParser command,
+ String option, String description, OptimizePhase optimizer)
+ {
+ super(command, option, description);
+ this.optimizer = optimizer;
+ this.optimize = false;
+ }
+
+ public boolean matches(String[] args, int index) {
+ return args[index].equals("-" + option);
+ }
+
+ public int consume(String[] args, int index) {
+ optimizer.setOptions(args[index].substring(1 + option.length()));
+ optimize = true;
+ return index + 1;
+ }
+
+ public String getHelpSyntax() {
+ return super.getHelpSyntax() + "[:<options>]";
+ }
+}
+*/
+public class VersionOptionParser extends OptionParser {
+
+ private final String version;
+
+ public VersionOptionParser(CommandParser command,
+ String option, String description, String version)
+ {
+ super(command, option, description);
+ this.version = version;
+ }
+
+ public boolean matches(String[] args, int index) {
+ return args[index].equals("-" + option);
+ }
+
+ public int consume(String[] args, int index) {
+ System.out.println(version);
+ System.exit(0);
+ return index + 1;
+ }
+}
+
+public class HelpOptionParser extends OptionParser {
+
+ public HelpOptionParser(CommandParser command,
+ String option, String description)
+ {
+ super(command, option, description);
+ }
+
+ public boolean matches(String[] args, int index) {
+ return args[index].equals("-?") ||
+ args[index].equals("-" + option) ||
+ args[index].equals("--" + option);
+ }
+
+ public int consume(String[] args, int index) {
+ System.out.println(command.getHelpMessage());
+ System.exit(0);
+ return index + 1;
+ }
+
+ public String getHelpSyntax() {
+ return "-? " + super.getHelpSyntax();
+ }
+}
+
+public class UnknownOptionParser extends OptionParser {
+
+ public UnknownOptionParser(CommandParser command) {
+ super(command, "", null);
+ }
+
+ public boolean matches(String[] args, int index) {
+ return args[index].startsWith("-");
+ }
+
+ public int consume(String[] args, int index) {
+ command.error("unknown option " + args[index]);
+ return index + 1;
+ }
+}
+
+public class BooleanOptionParser extends OptionParser {
+
+ public boolean value;
+
+ public BooleanOptionParser(CommandParser command,
+ String option, String description, boolean value)
+ {
+ super(command, option, description);
+ this.value = value;
+ }
+
+ public boolean matches(String[] args, int index) {
+ return args[index].equals("-" + option);
+ }
+
+ public int consume(String[] args, int index) {
+ value = true;
+ return index + 1;
+ }
+}
+
+public class StringOptionParser extends OptionParser {
+
+ public String value;
+ public String argument;
+
+ public StringOptionParser(CommandParser command,
+ String option, String description, String argument, String value)
+ {
+ super(command, option, description);
+ this.argument = argument;
+ this.value = value;
+ }
+
+ public boolean matches(String[] args, int index) {
+ return args[index].equals("-" + option);
+ }
+
+ public int consume(String[] args, int index) {
+ if (index + 1 < args.length) {
+ value = args[index + 1];
+ return index + 2;
+ } else {
+ error("missing argument");
+ return index + 1;
+ }
+ }
+
+ public String getHelpSyntax() {
+ String syntax = super.getHelpSyntax();
+ if (argument != null) syntax = syntax + " <" + argument + ">";
+ return syntax;
+ }
+}
+
+public class PhaseSetOptionParser extends OptionParser {
+
+ private final PhaseDescriptor[] phases;
+ private final int flag;
+ private final PrefixMatcher matcher;
+
+ public PhaseSetOptionParser(CommandParser command,
+ String option, String description, PhaseDescriptor[] phases, int flag)
+ {
+ super(command, option, description);
+ this.phases = phases;
+ this.flag = flag;
+ this.matcher = new PrefixMatcher();
+ for (int i = 0; i < phases.length; i++) {
+ PhaseDescriptor phase = phases[i];
+ matcher.insert(phase.name(), phase, phase.description());
+ }
+ }
+
+ public boolean matches(String[] args, int index) {
+ return args[index].startsWith("-" + option + ":");
+ }
+
+ public int consume(String[] args, int index) {
+ StringTokenizer tokens = new StringTokenizer(
+ args[index].substring(option.length() + 2), ",");
+ while (tokens.hasMoreTokens()) consumePhase(tokens.nextToken());
+ return index + 1;
+ }
+
+ public void consumePhase(String token) {
+ if (token.equals("all")) {
+ for (int i = 0; i < phases.length; i++) phases[i].flags |= flag;
+ return;
+ }
+ PhaseDescriptor phase = lookup(getPhaseName(token));
+ if (phase != null) {
+ boolean before = getBeforeFlag(token);
+ boolean after = getAfterFlag(token) || !before;
+ if (before) phase.flags |= flag << 16;
+ if (after) phase.flags |= flag;
+ }
+ }
+
+ public PhaseDescriptor lookup(String name) {
+ if (name.length() == 0) {
+ error("illegal zero-length phase name");
+ return null;
+ }
+ PrefixMatcher.Entry[] entries = matcher.lookup(name);
+ if (entries.length == 1) return (PhaseDescriptor)entries[0].value;
+ error(matcher.getErrorMessage(name, entries, "phase name"));
+ return null;
+ }
+
+ public boolean getBeforeFlag(String token) {
+ for (int i = token.length(); 0 < i--; ) {
+ switch (token.charAt(i)) {
+ case '-': return true;
+ case '+': continue;
+ default : return false;
+ }
+ }
+ return false;
+ }
+
+ public boolean getAfterFlag(String token) {
+ for (int i = token.length(); 0 < i--; ) {
+ switch (token.charAt(i)) {
+ case '-': continue;
+ case '+': return true;
+ default : return false;
+ }
+ }
+ return false;
+ }
+
+ public String getPhaseName(String token) {
+ for (int i = token.length(); 0 < i--; ) {
+ switch (token.charAt(i)) {
+ case '-': continue;
+ case '+': continue;
+ default : return token.substring(0, i + 1);
+ }
+ }
+ return "";
+ }
+
+ public String getHelpSyntax() {
+ return super.getHelpSyntax() + ":<phases>";
+ }
+}
+
+public class PrintOptionParser extends PhaseSetOptionParser {
+
+ public boolean tokens;
+
+ public PrintOptionParser(CommandParser command,
+ String option, String description, PhaseDescriptor[] phases, int flag)
+ {
+ super(command, option, description, phases, flag);
+ this.tokens = false;
+ }
+
+ public void consumePhase(String token) {
+ if ("tokens".equals(token))
+ tokens = true;
+ else
+ super.consumePhase(token);
+ }
+
+}
+
+public class ChoiceOptionParser extends OptionParser {
+
+ public final String argument;
+ public final String[] choices;
+
+ public String value;
+
+ public ChoiceOptionParser(CommandParser command,
+ String option, String description, String argument, String[] choices,
+ String value)
+ {
+ super(command, option, description);
+ this.argument = argument;
+ this.choices = choices;
+ this.value = value;
+ }
+
+ public boolean matches(String[] args, int index) {
+ return args[index].startsWith("-" + option + ":");
+ }
+
+ public int consume(String[] args, int index) {
+ String choice = args[index].substring(option.length() + 2);
+ boolean found = false;
+ for (int i = 0; i < choices.length; i++) {
+ if (choices[i].equals(choice)) { found = true; break; }
+ }
+ if (found) {
+ value = choice;
+ } else if (choice.length() > 0) {
+ error("unknown " + argument + " '" + choice + "'");
+ } else {
+ error("missing " + argument);
+ }
+ return index + 1;
+ }
+
+ public String getHelpSyntax() {
+ String syntax = super.getHelpSyntax();
+ if (argument != null) syntax = syntax + ":<" + argument + ">";
+ return syntax;
+ }
+}
diff --git a/sources/scalac/util/Position.java b/sources/scalac/util/Position.java
new file mode 100644
index 0000000000..c2cd7f72d3
--- /dev/null
+++ b/sources/scalac/util/Position.java
@@ -0,0 +1,54 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scalac.util;
+
+
+public final class Position {
+
+/** source file positions are integers in the format:
+ * line-number << LINESHIFT + column-number
+ * NOPOS represents an undefined position.
+ */
+ public static final int LINESHIFT = 10;
+ public static final int FILESHIFT = 26;
+ public static final int COLUMNMASK = 1023;
+ public static final int LINEMASK = 0xffff;
+
+/** predefined positions
+ */
+ public static final int NOPOS = 0;
+
+/** first position in a source file
+ */
+ public static final int FIRSTPOS = (1 << LINESHIFT) + 1;
+
+/** encode a line and column number into a single int
+ */
+ public static int encode(int line, int col, int file) {
+ return (file << FILESHIFT) | (line << LINESHIFT) | col;
+ }
+
+/** get the file id of an encoded position
+ */
+ public static int file(int pos) {
+ return pos >>> FILESHIFT;
+ }
+
+/** get the line number out of an encoded position
+ */
+ public static int line(int pos) {
+ return (pos >>> LINESHIFT) & LINEMASK;
+ }
+
+/** return the column number of an encoded position
+ */
+ public static int column(int pos) {
+ return pos & COLUMNMASK;
+ }
+}
diff --git a/sources/scalac/util/PrefixMatcher.java b/sources/scalac/util/PrefixMatcher.java
new file mode 100644
index 0000000000..1b0acd8d7a
--- /dev/null
+++ b/sources/scalac/util/PrefixMatcher.java
@@ -0,0 +1,114 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scalac.util;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+
+public class PrefixMatcher {
+
+ public static class Entry {
+
+ private Entry prev;
+ private Entry next;
+
+ public final String key;
+ public final Object value;
+ public final String argument;
+ public final String description;
+
+ public Entry(String key, Object value, String argument,
+ String description)
+ {
+ this.key = key;
+ this.value = value;
+ this.argument = argument;
+ this.description = description;
+ }
+ }
+
+ private final Map entries;
+ private Entry first;
+ private Entry last;
+
+ public PrefixMatcher() {
+ this.entries = new HashMap();
+ }
+
+ public void insert(String key, Object value) {
+ insert(key, value, null, null);
+ }
+
+ public void insert(String key, Object value, String description) {
+ insert(key, value, null, description);
+ }
+
+ public void insert(String key, Object value, String argument,
+ String description)
+ {
+ assert key != null && !entries.containsKey(key) : key;
+ Entry entry = new Entry(key, value, argument, description);
+ if (first == null) {
+ first = last = entry;
+ } else {
+ last.next = entry;
+ entry.prev = last;
+ last = entry;
+ }
+ entries.put(key, entry);
+ }
+
+ public Entry[] lookup(String key) {
+ Object value = entries.get(key);
+ if (value != null) return new Entry[] { (Entry)value };
+ List list = new ArrayList();
+ for (Entry i = first; i != null; i = i.next) {
+ if (i.key.startsWith(key)) list.add(i);
+ }
+ return (Entry[])list.toArray(new Entry[list.size()]);
+ }
+
+ public String getErrorMessage(String key, Entry[] entries, String what) {
+ switch (entries.length) {
+ case 0:
+ return "unknown " + what + " '" + key + "'";
+ case 1:
+ return null;
+ case 2:
+ return "ambigous " + what + " '" + key + "', both '" +
+ entries[0].key + "' and '" + entries[1].key + "' match";
+ default:
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("ambigous ").append(what);
+ buffer.append(" '").append(key).append("'");
+ for (int i = 0; i < entries.length; i++) {
+ buffer.append(i < entries.length - 1 ? ", " : " and ");
+ buffer.append('\'').append(entries[i].key).append('\'');
+ }
+ buffer.append(" match");
+ return buffer.toString();
+ }
+ }
+
+ public List getHelpStrings(String separator1, String separator2) {
+ List strings = new ArrayList();
+ for (Entry entry = first; entry != null; entry = entry.next) {
+ if (entry.description != null)
+ if (entry.argument != null)
+ strings.add(entry.key + separator1 + entry.argument +
+ separator2 + entry.description);
+ else
+ strings.add(entry.key + separator2 + entry.description);
+ }
+ return strings;
+ }
+
+}
diff --git a/sources/scalac/util/Reporter.java b/sources/scalac/util/Reporter.java
new file mode 100644
index 0000000000..a1fb832e28
--- /dev/null
+++ b/sources/scalac/util/Reporter.java
@@ -0,0 +1,192 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scalac.util;
+
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.io.PrintWriter;
+import java.io.IOException;
+import scalac.ApplicationError;
+
+public class Reporter {
+
+ //########################################################################
+ // Private state
+
+ private final BufferedReader reader;
+ private final PrintWriter writer;
+
+ /** Number of errors issued totally */
+ private int errors;
+ /** Number of warning issued totally */
+ private int warnings;
+ /** Number of notes issued totally */
+ private int notes;
+
+ //########################################################################
+ // Reporter constructors
+
+ public Reporter() {
+ this(
+ new BufferedReader(new InputStreamReader(System.in)),
+ new PrintWriter(System.err, true));
+ }
+
+ public Reporter(BufferedReader reader, PrintWriter writer) {
+ this.reader = reader;
+ this.writer = writer;
+ this.prompt = false;
+ this.nowarn = false;
+ this.verbose = false;
+ this.errors = 0;
+ this.notes = 0;
+ }
+
+ //########################################################################
+ // Reporter state
+
+ /** Whether warnings should be issued */
+ public boolean nowarn;
+ /** Whether notes and information messages should be issued */
+ public boolean verbose;
+ /** Whether a prompt should be displayed after errors and warnings */
+ public boolean prompt;
+
+ //########################################################################
+ // Reporter interface - query
+
+ /** Return the number of errors issued totally */
+ public int errors() {
+ return errors;
+ }
+
+ /** Return the number of warnings issued totally */
+ public int warnings() {
+ return warnings;
+ }
+
+ /** Return the number of notes issued totally */
+ public int notes() {
+ return notes;
+ }
+
+ /** Return the number of errors issued totally as a string */
+ public String getErrorCountString() {
+ return getCountString(errors, "error");
+ }
+
+ /** Return the number of warnings issued totally as a string */
+ public String getWarningCountString() {
+ return getCountString(warnings, "warning");
+ }
+
+ /** Return the number of notes issued totally as a string */
+ public String getNoteCountString() {
+ return getCountString(notes, "note");
+ }
+
+ public String getCountString(int count, String what) {
+ switch (count) {
+ case 0: return "no " + what + "s";
+ case 1: return "one " + what;
+ case 2: return "two " + what + "s";
+ case 3: return "three " + what + "s";
+ case 4: return "four " + what + "s";
+ default: return count + " " + what + "s";
+ }
+ }
+
+ //########################################################################
+ // Reporter interface - report
+
+ /** Reset all counters */
+ public void resetCounters() {
+ errors = 0;
+ warnings = 0;
+ notes = 0;
+ }
+
+ /** Issue a message */
+ public void report(String message) {
+ writer.println(message);
+ }
+
+ /** Issue a message */
+ public void inform(String message) {
+ if (verbose) report(message);
+ }
+
+ /** Issue an error */
+ public void error(String message) {
+ error(message, false);
+ }
+
+ /** Issue an error if it is not hidden */
+ public void error(String message, boolean hidden) {
+ if (!hidden || prompt) report(message);
+ if (!hidden) errors++;
+ if (prompt) failOnDemand();
+ }
+
+ /** Issue a warning */
+ public void warning(String message) {
+ warning(message, false);
+ }
+
+ /** Issue a warning if it is not hidden */
+ public void warning(String message, boolean hidden) {
+ if (nowarn) return;
+ if (!hidden || prompt) report(message);
+ if (!hidden) warnings++;
+ if (prompt) failOnDemand();
+ }
+
+ /** Issue a note */
+ public void note(String message) {
+ note(message, false);
+ }
+
+ /** Issue a note if it is not hidden */
+ public void note(String message, boolean hidden) {
+ if (!hidden) report(message);
+ if (!hidden) notes++;
+ }
+
+ public void printSummary() {
+ if (errors() > 0) report(getErrorCountString() + " found");
+ if (warnings() > 0) report(getWarningCountString() + " found");
+ if (notes() > 0) report(getNoteCountString() + " found");
+ }
+
+ //########################################################################
+ // Reporter interface - fail
+
+ /** Fail only if requested */
+ public void failOnDemand() {
+ failOnDemand("user abort");
+ }
+
+ /** Fail only if requested */
+ public void failOnDemand(String message) {
+ try {
+ while (true) {
+ writer.print("r)esume, a)bort: ");
+ String line = reader.readLine();
+ if (line == null) continue; else line = line.toLowerCase();
+ if ("abort".startsWith(line))
+ throw new ApplicationError(message);
+ if ("resume".startsWith(line)) return;
+ }
+ } catch (IOException e) {
+ throw new ApplicationError("input read error");
+ }
+ }
+
+ //########################################################################
+}
diff --git a/sources/scalac/util/SourceRepresentation.java b/sources/scalac/util/SourceRepresentation.java
new file mode 100644
index 0000000000..7c6ee44107
--- /dev/null
+++ b/sources/scalac/util/SourceRepresentation.java
@@ -0,0 +1,205 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id
+\* */
+
+package scalac.util;
+
+public final class SourceRepresentation {
+
+ public static int digit2int(byte ch, int base) {
+ if ('0' <= ch && ch <= '9' && ch < '0' + base)
+ return ch - '0';
+ else if ('A' <= ch && ch < 'A' + base - 10)
+ return ch - 'A' + 10;
+ else if ('a' <= ch && ch < 'a' + base - 10)
+ return ch - 'a' + 10;
+ else
+ return -1;
+ }
+
+ public static byte int2digit(int x) {
+ if (x <= 9)
+ return (byte)(x + '0');
+ else
+ return (byte)(x - 10 + 'A');
+ }
+
+/* the next 4 functions convert between three fundamental name
+ * representations:
+ * - string each character 16 bit,
+ * - source characters outside 0..127 are represented by
+ * unicode escapes, \ u X X X X
+ * - ascii characters outside 0..127 are represented by two or three
+ * byte sequences with high bit set (as in class file format).
+ */
+
+/** convert source bytes in source[offset..offset+len-1] to ascii.
+ */
+ public static int source2ascii(byte source[], int offset, int len, byte ascii[]) {
+ int j = 0;
+ int i = 0;
+ while (i < len) {
+ if (source[offset + i] == '\\' && i + 1 < len) {
+ i++;
+ switch (source[offset + i]) {
+ case 'n':
+ ascii[j++] = (byte)'\n'; i++; continue;
+ case 't':
+ ascii[j++] = (byte)'\t'; i++; continue;
+ case 'b':
+ ascii[j++] = (byte)'\b'; i++; continue;
+ case 'r':
+ ascii[j++] = (byte)'\r'; i++; continue;
+ case 'f':
+ ascii[j++] = (byte)'\f'; i++; continue;
+ case 'u':
+ if (i + 4 < len) {
+ int code = 0;
+ int k = 1;
+ int d = 0;
+ while (k <= 4 && d >= 0) {
+ d = digit2int(source[offset + i + k], 16);
+ code = code * 16 + d;
+ k++;
+ }
+ if (d >= 0) {
+ if (code <= 0x7F)
+ ascii[j++] = (byte)code;
+ else
+ if (code <= 0x3FF) {
+ ascii[j++] = (byte)(0xC0 | (code >> 6));
+ ascii[j++] = (byte)(0x80 | (code & 0x3F));
+ } else {
+ ascii[j++] = (byte)(0xE0 | (code >> 12));
+ ascii[j++] = (byte)(0x80 |
+ ((code >> 6) & 0x3F));
+ ascii[j++] = (byte)(0x80 | (code & 0x3F));
+ }
+ i = i + 5;
+ continue;
+ }
+ }
+ }
+ }
+ byte b = source[offset + i++];
+ if (b >= 0)
+ ascii[j++] = b;
+ else {
+ ascii[j++] = (byte)(0xC0 | ((b >> 6) & 0x3));
+ ascii[j++] = (byte)(0x80 | (b & 0x3F));
+ }
+ }
+ return j;
+ }
+
+/** convert ascii bytes in ascii[offset..offset+len-1] to a string
+ */
+ public static String ascii2string(byte ascii[], int offset, int len) {
+ char cs[] = new char[len];
+ int i = offset;
+ int j = 0;
+ len += offset;
+ while (i < len) {
+ int b = ascii[i++] & 0xFF;
+ if (b >= 0xE0) {
+ b = ((b & 0x0F) << 12) | (ascii[i++] & 0x3F) << 6;
+ b = b | (ascii[i++] & 0x3F);
+ }
+ else
+ if (b >= 0xC0)
+ b = ((b & 0x1F) << 6) | (ascii[i++] & 0x3F);
+ cs[j++] = (char)b;
+ }
+ return new String(cs, 0, j);
+ }
+
+/** convert string to array of source bytes
+ */
+ public static byte[] string2source(String s) {
+ byte[] source = new byte[s.length() * 6];
+ int j = 0;
+ for (int i = 0; i < s.length(); i++) {
+ char ch = s.charAt(i);
+ switch (ch) {
+ case '\n':
+ source[j++] = (byte)'\\';
+ source[j++] = (byte)'n';
+ break;
+ case '\t':
+ source[j++] = (byte)'\\';
+ source[j++] = (byte)'t';
+ break;
+ case '\b':
+ source[j++] = (byte)'\\';
+ source[j++] = (byte)'b';
+ break;
+ case '\r':
+ source[j++] = (byte)'\\';
+ source[j++] = (byte)'r';
+ break;
+ case '\f':
+ source[j++] = (byte)'\\';
+ source[j++] = (byte)'f';
+ break;
+ case '\"':
+ source[j++] = (byte)'\\';
+ source[j++] = (byte)'\"';
+ break;
+ case '\'':
+ source[j++] = (byte)'\\';
+ source[j++] = (byte)'\'';
+ break;
+ case '\\':
+ source[j++] = (byte)'\\';
+ source[j++] = (byte)'\\';
+ break;
+ default:
+ if ((' ' <= ch) && (ch <= 127))
+ source[j++] = (byte)ch;
+ else {
+ source[j++] = (byte)'\\';
+ source[j++] = (byte)'u';
+ source[j++] = int2digit((ch >> 12) & 0xF);
+ source[j++] = int2digit((ch >> 8) & 0xF);
+ source[j++] = int2digit((ch >> 4) & 0xF);
+ source[j++] = int2digit(ch & 0xF);
+ }
+ }
+ }
+ byte[] res = new byte[j];
+ System.arraycopy(source, 0, res, 0, j);
+ return res;
+ }
+
+/** convert string to array of ascii bytes
+ */
+ public static byte[] string2ascii(String s) {
+ byte[] source = string2source(s);
+ byte[] ascii = new byte[source.length * 2];
+ int alen = source2ascii(source, 0, source.length, ascii);
+ byte[] res = new byte[alen];
+ System.arraycopy(ascii, 0, res, 0, alen);
+ return res;
+ }
+
+/** escape all characters outside 32..127 in string s
+ */
+ public static String escape(String s) {
+ try {
+ return new String(string2source(s), "8859_1");
+ } catch (java.io.UnsupportedEncodingException e) {
+ throw new InternalError(e.getMessage());
+ }
+ }
+
+/** escape character c, if outside 32..127.
+ */
+ public static String escape(char c) {
+ char[] s = {c};
+ return escape(new String(s));
+ }
+}
diff --git a/sources/scalac/util/Strings.java b/sources/scalac/util/Strings.java
new file mode 100644
index 0000000000..540a61020e
--- /dev/null
+++ b/sources/scalac/util/Strings.java
@@ -0,0 +1,102 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scalac.util;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+public abstract class Strings {
+
+ //########################################################################
+ // Strings constants
+
+ final public static String[] NONE = new String[0];
+
+ //########################################################################
+ // Strings interface
+
+ /** The line separator */
+ public static String EOL = System.getProperty("line.separator", "\n");
+
+ /** Returns a string where all tabs have been replaced by white
+ * spaces to make the corresponding fields the same width.
+ */
+ public static String format(List strings) {
+ List[] lines = new List[strings.size()];
+ List widths = new ArrayList();
+ int height = 0;
+ for (Iterator iterator = strings.iterator(); iterator.hasNext(); ) {
+ String string = (String)iterator.next();
+ List line = lines[height++] = new ArrayList();
+ for (int last = 0; last < string.length(); ) {
+ int next = string.indexOf('\t', last);
+ if (next < 0) next = string.length();
+ String substring = string.substring(last, next);
+ int index = line.size();
+ if (index == widths.size()) widths.add(new Integer(0));
+ int width = ((Integer)widths.get(index)).intValue();
+ widths.set(
+ index, new Integer(Math.max(width, substring.length())));
+ line.add(substring);
+ last = next + 1;
+ }
+ }
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < lines.length; i++) {
+ List line = lines[i];
+ for (int j = 0; true; j++) {
+ String string = (String)line.get(j);
+ buffer.append(string);
+ if (j == line.size() - 1) break;
+ int width = ((Integer)widths.get(j)).intValue();
+ for (int k = string.length(); k<width; k++) buffer.append(' ');
+ }
+ buffer.append(EOL);
+ }
+ return buffer.toString();
+ }
+
+ /** Returns the first char of the string or -1 if the string is empty. */
+ public static int firstChar(String string) {
+ return string.length() == 0 ? -1 : string.charAt(0);
+ }
+
+ /** Returns the last char of the string or -1 if the string is empty. */
+ public static int lastChar(String string) {
+ return string.length() == 0 ? -1 : string.charAt(string.length() - 1);
+ }
+
+ /** Returns a copy of the string, with leading whitespace omitted. */
+ public static String trimLeading(String string) {
+ for (int i = 0; i < string.length(); i++)
+ if (string.charAt(i) > ' ') return string.substring(i);
+ return "";
+ }
+
+ /** Returns a copy of the string, with trailing whitespace omitted. */
+ public static String trimTrailing(String string) {
+ for (int i = string.length() - 1; i >= 0; i--)
+ if (string.charAt(i) > ' ') return string.substring(0, i + 1);
+ return "";
+ }
+
+ /** Returns the stack trace of the exception */
+ public static String stackTrace(Throwable exception) {
+ StringWriter buffer = new StringWriter();
+ PrintWriter writer = new PrintWriter(buffer);
+ exception.printStackTrace(writer);
+ writer.close();
+ return buffer.toString();
+ }
+
+ //########################################################################
+}
diff --git a/sources/scalac/util/UniqueID.java b/sources/scalac/util/UniqueID.java
new file mode 100644
index 0000000000..59e31a9de6
--- /dev/null
+++ b/sources/scalac/util/UniqueID.java
@@ -0,0 +1,30 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+\* */
+
+// $Id$
+
+package scalac.util;
+
+import java.util.*;
+
+/**
+ * Class to assign unique and small numbers to objects, based on their
+ * identity.
+ *
+ * @author Michel Schinz
+ * @version 1.0
+ */
+
+public class UniqueID {
+ protected Map ids = new HashMap();
+
+ public int id(Object obj) {
+ if (! ids.containsKey(obj))
+ ids.put(obj, new Integer(ids.size()));
+ return ((Integer)ids.get(obj)).intValue();
+ }
+}