diff options
author | Burak Emir <emir@epfl.ch> | 2006-09-21 17:50:41 +0000 |
---|---|---|
committer | Burak Emir <emir@epfl.ch> | 2006-09-21 17:50:41 +0000 |
commit | 920e6a2e5ab9834e0a034199960201d40569e011 (patch) | |
tree | 19dc21d51a2f6f76c0ddccb4d883701529e1b152 /src/compiler | |
parent | 9a45bd5bdb246e19912a46aed6a672d6119d428f (diff) | |
download | scala-920e6a2e5ab9834e0a034199960201d40569e011.tar.gz scala-920e6a2e5ab9834e0a034199960201d40569e011.tar.bz2 scala-920e6a2e5ab9834e0a034199960201d40569e011.zip |
reorganized scala.tools.nsc.io!
Diffstat (limited to 'src/compiler')
20 files changed, 262 insertions, 216 deletions
diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala index c88f412948..8d940f39c3 100644 --- a/src/compiler/scala/tools/nsc/CompileServer.scala +++ b/src/compiler/scala/tools/nsc/CompileServer.scala @@ -7,7 +7,7 @@ package scala.tools.nsc import scala.tools.util.SocketServer -import scala.tools.nsc.util.Position +import scala.tools.nsc.util.FakePos //Position import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} import scala.tools.nsc.doc.DocGenerator import scala.concurrent.Process.spawn @@ -95,7 +95,7 @@ object CompileServer extends SocketServer { override def displayPrompt = {} } def error(msg: String): unit = - reporter.error(new Position(PRODUCT), + reporter.error(/*new Position*/ FakePos(PRODUCT), msg + "\n " + PRODUCT + " -help gives more information") val command = new CompilerCommand(args, error, false) { override val cmdName = "fsc" diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 385c687eff..399e6802d6 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -531,7 +531,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable if (settings.Xscript.value && filenames.length != 1) error("can only compile one script at a time") val sources = filenames map ( - if (settings.Xscript.value) ScriptRunner.wrappedScript else getSourceFile) + if (settings.Xscript.value) {x => ScriptRunner.wrappedScript(x, &Global.this.getSourceFile)} else getSourceFile) compileSources(sources) } catch { case ex: IOException => error(ex.getMessage()) diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala index c6ea239f1d..749a5ef1d8 100644 --- a/src/compiler/scala/tools/nsc/Interpreter.scala +++ b/src/compiler/scala/tools/nsc/Interpreter.scala @@ -188,7 +188,8 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter) reporter.error(null, "no such file: " + filename) } else { val cr = new compiler.Run - cr.compileSources(List(new SourceFile(PlainFile.fromFile(jfile)))) + val sf = compiler.getSourceFile(new PlainFile(jfile)) + cr.compileSources(List(sf)) } } diff --git a/src/compiler/scala/tools/nsc/Main.scala b/src/compiler/scala/tools/nsc/Main.scala index 169c90e306..85db0730f0 100644 --- a/src/compiler/scala/tools/nsc/Main.scala +++ b/src/compiler/scala/tools/nsc/Main.scala @@ -5,7 +5,7 @@ // $Id$ package scala.tools.nsc -import scala.tools.nsc.util.{Position} +import scala.tools.nsc.util.FakePos //{Position} import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} import scala.tools.nsc.doc.DocGenerator @@ -27,7 +27,7 @@ object Main extends Object with EvalLoop { var reporter: ConsoleReporter = _ def error(msg: String): unit = - reporter.error(new Position(PRODUCT), + reporter.error(/*new Position */FakePos(PRODUCT), msg + "\n " + PRODUCT + " -help gives more information") def errors() = reporter.errors diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala index dad15d4960..9f51af40e3 100644 --- a/src/compiler/scala/tools/nsc/ScriptRunner.scala +++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala @@ -123,7 +123,7 @@ object ScriptRunner { /** Wrap a script file into a runnable object named * scala.scripting.Main . */ - def wrappedScript(filename: String): SourceFile = { + def wrappedScript(filename: String, getSourceFile: PlainFile => SourceFile): SourceFile = { val preamble = new SourceFile("<script preamble>", ("package $scalascript\n" + @@ -134,7 +134,7 @@ object ScriptRunner { val middle = { val f = new File(filename) new SourceFileFragment( - new SourceFile(new PlainFile(f)), + getSourceFile(new PlainFile(f)), headerLength(filename), f.length.asInstanceOf[Int]) } @@ -222,7 +222,7 @@ object ScriptRunner { val reporter = new ConsoleReporter val compiler = new Global(settings, reporter) val cr = new compiler.Run - cr.compileSources(List(wrappedScript(scriptFile))) + cr.compileSources(List(wrappedScript(scriptFile, &compiler.getSourceFile))) Pair(compiledPath, reporter.errors == 0) } else { val compok = compileWithDaemon(settings, scriptFile) diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala index 6c28cf436f..21798d1e8a 100644 --- a/src/compiler/scala/tools/nsc/Settings.scala +++ b/src/compiler/scala/tools/nsc/Settings.scala @@ -67,8 +67,9 @@ class Settings(error: String => unit) { } private val encodingDefault = - new java.io.OutputStreamWriter( - new java.io.ByteArrayOutputStream()).getEncoding + java.nio.charset.Charset.defaultCharset.name() + //new java.io.OutputStreamWriter( + // new java.io.ByteArrayOutputStream()).getEncoding private val windowtitleDefault = "Scala Library Documentation" private val documenttitleDefault = "Scala 2" diff --git a/src/compiler/scala/tools/nsc/io/AbstractFile.scala b/src/compiler/scala/tools/nsc/io/AbstractFile.scala index d50647a4be..c496aee84e 100644 --- a/src/compiler/scala/tools/nsc/io/AbstractFile.scala +++ b/src/compiler/scala/tools/nsc/io/AbstractFile.scala @@ -46,11 +46,11 @@ object AbstractFile { } /** - * This class implements an abstract representation of files and - * directories. These files and directories may have some real counter - * part within the file system but that is not necessarily true. For - * example, there exist abstract files that represent files within a - * zip archive or files that exist only in memory. + * This class and its children serve to unify handling of files and + * directories. These files and directories may or may not have some + * real counter part within the file system. For example, some file + * handles reference files within a zip archive or virtual ones + * that exist only in memory. * * Every abstract file has a path (i.e. a full name) and a name * (i.e. a short name) and may be backed by some real File. There are @@ -58,6 +58,14 @@ object AbstractFile { * directories. Regular files may be read and have a last modification * time. Directories may list their content and look for subfiles with * a specified name or path and of a specified kind. + * + * bq: The interface allows to access the content as bytes and as chars. + * In fact, only the ClassFileParser should access bytes, because + * only there we know that the charset of the file is UTF-8. For + * all other cases, the global.settings.encoding.value must be + * respected. @todo it would be better if reading chars from sources + * was exclusively done in SourceFile and reading bytes for classfiles + * was done in symtab.classfile.AbstractFileReader */ abstract class AbstractFile extends Object with Iterable[AbstractFile] { @@ -80,7 +88,10 @@ abstract class AbstractFile extends Object with Iterable[AbstractFile] { def lastModified: Long; /** Reads the content of this abstract file into a byte array. */ - def read: Array[Byte]; + //def getBytes: Array[Byte] = error("getBytes not supported by "+this.getClass()) + + /** Reads the content of this abstract file into a char array. */ + //def getChars: Array[Char] = error("getChars not supported by "+this.getClass()) /** Returns all abstract subfiles of this abstract directory. */ def elements: Iterator[AbstractFile]; diff --git a/src/compiler/scala/tools/nsc/io/AbstractFileReader.scala b/src/compiler/scala/tools/nsc/io/AbstractFileReader.scala deleted file mode 100644 index 0f0a65f54b..0000000000 --- a/src/compiler/scala/tools/nsc/io/AbstractFileReader.scala +++ /dev/null @@ -1,83 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002-2006, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - - -package scala.tools.nsc.io; - - -class AbstractFileReader(val file: AbstractFile) { - - /** the buffer containing the file - */ - val buf: Array[Byte] = file.read; - - /** the current input pointer - */ - var bp: Int = 0; - - /** return byte at offset 'pos' - */ - def byteAt(pos: Int): Byte = return buf(pos); - - /** read a byte - */ - def nextByte: Byte = { - val b = buf(bp); - bp = bp + 1; - b - } - - /** read some bytes - */ - def nextBytes(len: Int): Array[Byte] = { - bp = bp + len; - buf.subArray(bp - len, bp); - } - - /** read a character - */ - def nextChar: Char = { - (((nextByte & 0xff) << 8) + (nextByte & 0xff)).toChar; - } - - /** read an integer - */ - def nextInt: Int = - ((nextByte & 0xff) << 24) + ((nextByte & 0xff) << 16) + - ((nextByte & 0xff) << 8) + (nextByte & 0xff); - - - /** extract a character at position bp from buf - */ - def getChar(mybp: Int): Char = - (((buf(mybp) & 0xff) << 8) + (buf(mybp+1) & 0xff)).toChar; - - /** extract an integer at position bp from buf - */ - def getInt(mybp: Int): Int = - ((buf(mybp ) & 0xff) << 24) + ((buf(mybp+1) & 0xff) << 16) + - ((buf(mybp+2) & 0xff) << 8) + (buf(mybp+3) & 0xff); - - /** extract a long integer at position bp from buf - */ - def getLong(mybp: Int): Long = - (getInt(mybp).toLong << 32) + (getInt(mybp + 4) & 0xffffffffL); - - /** extract a float at position bp from buf - */ - def getFloat(mybp: Int): Float = Float.intBitsToFloat(getInt(mybp)); - - /** extract a double at position bp from buf - */ - def getDouble(mybp: Int): Double = Double.longBitsToDouble(getLong(mybp)); - - /** skip next 'n' bytes - */ - def skip(n: Int): Unit = bp = bp + n; - -} diff --git a/src/compiler/scala/tools/nsc/io/CharArrayFile.scala b/src/compiler/scala/tools/nsc/io/CharArrayFile.scala deleted file mode 100644 index aaa7b70193..0000000000 --- a/src/compiler/scala/tools/nsc/io/CharArrayFile.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002-2006, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - - -package scala.tools.nsc.io; - - -/** - * This class implements an abstract regular file backed by a - * character array. - */ -class CharArrayFile(name: String, path: String, chars: Array[Char]) - extends VirtualFile(name, path) -{ - - def this(name: String, chars: Array[Char]) = this(name, name, chars); - - /** Reads the content of this abstract file into a byte array. */ - override def read: Array[Byte] = { - //Why was this marked as not an implementation? It looks - //great to me. -Lex - //Predef.error("!!! not yet implemented"); - new String(chars).getBytes(); // !!! - } - -} diff --git a/src/compiler/scala/tools/nsc/io/PlainFile.scala b/src/compiler/scala/tools/nsc/io/PlainFile.scala index 60f8ad4f7f..eb1852666f 100644 --- a/src/compiler/scala/tools/nsc/io/PlainFile.scala +++ b/src/compiler/scala/tools/nsc/io/PlainFile.scala @@ -15,7 +15,7 @@ import java.io.{File, FileInputStream, IOException}; object PlainFile { /** Returns "fromFile(new File(path))". */ - def fromPath(path: String): AbstractFile = fromFile(new File(path)); + //def fromPath(path: String): AbstractFile = fromFile(new File(path)); /** * If the specified File exists, returns an abstract file backed @@ -26,7 +26,8 @@ object PlainFile { } -/** This class implements an abstract file backed by a File. */ +/** This class implements an abstract file backed by a File. + */ class PlainFile(val file: File) extends AbstractFile { assert(file != null); @@ -62,8 +63,8 @@ class PlainFile(val file: File) extends AbstractFile { /** Returns the time that this abstract file was last modified. */ def lastModified: Long = file.lastModified(); - /** Reads the content of this abstract file into a byte array. */ - def read: Array[Byte] = { + /** Reads the content of this abstract file into a byte array. + override def getBytes: Array[Byte] = { assert(!isDirectory, "cannot read directory '" + this + "'"); val in = new FileInputStream(file); var rest: Int = file.length().toInt; @@ -77,6 +78,7 @@ class PlainFile(val file: File) extends AbstractFile { in.close(); return buf; } + */ /** Returns all abstract subfiles of this abstract directory. */ def elements: Iterator[AbstractFile] = { diff --git a/src/compiler/scala/tools/nsc/io/SourceReader.scala b/src/compiler/scala/tools/nsc/io/SourceReader.scala index f5be1da58a..6835aa7cde 100644 --- a/src/compiler/scala/tools/nsc/io/SourceReader.scala +++ b/src/compiler/scala/tools/nsc/io/SourceReader.scala @@ -29,6 +29,11 @@ class SourceReader(decoder: CharsetDecoder) { /** The output character buffer */ private var chars: CharBuffer = CharBuffer.allocate(0x4000); + private def reportEncodingError(filename:String) = { + Console println "IO error while decoding "+filename+" with "+decoder.charset(); + Console println "Please try specifying another one using the -encoding option" + } + //######################################################################## // Public Methods @@ -40,6 +45,10 @@ class SourceReader(decoder: CharsetDecoder) { val channel: FileChannel = new FileInputStream(file).getChannel(); try { read(channel); + } catch { + case e:Exception => + reportEncodingError(file.toString()) + new Array[Char](0) } finally { channel.close(); } @@ -47,14 +56,26 @@ class SourceReader(decoder: CharsetDecoder) { /** Reads the specified file. */ def read(file: AbstractFile): Array[Char] = { + file match { + case p:PlainFile => read(p.file) + case _ => throw new IOException(file.toString()+" is not a plain file") + } + /* val decoder: CharsetDecoder = this.decoder.reset(); val bytes: ByteBuffer = ByteBuffer.wrap(file.read); val chars: CharBuffer = this.chars; chars.clear(); - terminate(flush(decoder, decode(decoder, bytes, chars, true))); + try { + terminate(flush(decoder, decode(decoder, bytes, chars, true))); + } catch { + case e:Exception => + reportEncodingError(file.toString()) + new Array[Char](0) + } + */ } /** Reads the specified byte channel. */ - def read(input: ReadableByteChannel): Array[Char] = { + protected def read(input: ReadableByteChannel): Array[Char] = { val decoder: CharsetDecoder = this.decoder.reset(); val bytes: ByteBuffer = this.bytes; bytes.clear(); var chars: CharBuffer = this.chars; chars.clear(); diff --git a/src/compiler/scala/tools/nsc/io/VirtualFile.scala b/src/compiler/scala/tools/nsc/io/VirtualFile.scala index 02ce3b0f81..9e453b66c6 100644 --- a/src/compiler/scala/tools/nsc/io/VirtualFile.scala +++ b/src/compiler/scala/tools/nsc/io/VirtualFile.scala @@ -40,12 +40,6 @@ class VirtualFile(val name: String, _path: String) extends AbstractFile { /** Returns the time that this abstract file was last modified. */ def lastModified: Long = Long.MIN_VALUE; - /** Reads the content of this abstract file into a byte array. */ - def read: Array[Byte] = { - assert(!isDirectory, "cannot read directory '" + this + "'"); - new Array[Byte](0); - } - /** Returns all abstract subfiles of this abstract directory. */ def elements: Iterator[AbstractFile] = { assert(isDirectory, "not a directory '" + this + "'"); diff --git a/src/compiler/scala/tools/nsc/io/ZipArchive.scala b/src/compiler/scala/tools/nsc/io/ZipArchive.scala index 84bc7752f8..99694b73fa 100644 --- a/src/compiler/scala/tools/nsc/io/ZipArchive.scala +++ b/src/compiler/scala/tools/nsc/io/ZipArchive.scala @@ -39,7 +39,8 @@ object ZipArchive { /** * This class implements an abstract directory backed by a zip - * archive. + * archive. We let the encoding be null, because we behave like + * a directory */ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file) { @@ -133,7 +134,7 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file) { final override def path = ZipArchive.this.toString() + "(" + super.path + ")"; - + final def getArchive = ZipArchive.this.archive } //######################################################################## @@ -172,7 +173,8 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file) override def lastModified: Long = entry.getTime(); - override def read: Array[Byte] = { + /** in zip archives, we assume class files conform to Java spec by using UTF-8 * / + def getBytes: Array[Byte] = { val in: InputStream = archive.getInputStream(entry); var rest: Int = entry.getSize().toInt; val buf = new Array[Byte](rest); @@ -185,6 +187,7 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file) in.close(); buf } + */ } } diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala index 0e401fa270..8713947d68 100644 --- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala @@ -6,13 +6,13 @@ // $Id$ -package scala.tools.nsc.reporters; -import scala.tools.nsc.util.Position; +package scala.tools.nsc.reporters +import scala.tools.nsc.util.{FakePos, Position} -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.IOException; -import java.io.PrintWriter; +import java.io.BufferedReader +import java.io.InputStreamReader +import java.io.IOException +import java.io.PrintWriter /** * This class implements a Reporter that displays messages on a text @@ -23,16 +23,16 @@ class ConsoleReporter(reader : BufferedReader, writer : PrintWriter) extends Abs // Public Fields /** Whether a short file name should be displayed before errors */ - var shortname : Boolean = false; + var shortname : Boolean = false def label(severity : Severity): String = severity match { - case ERROR => "error"; - case WARNING => "warning"; - case INFO => null; - }; + case ERROR => "error" + case WARNING => "warning" + case INFO => null + } def clabel(severity : Severity) = { - val label0 = label(severity); - if (label0 == null) ""; else label0 + ": "; + val label0 = label(severity) + if (label0 == null) "" else label0 + ": " } @@ -41,23 +41,23 @@ class ConsoleReporter(reader : BufferedReader, writer : PrintWriter) extends Abs // Public Constructors def this() = this( new BufferedReader(new InputStreamReader(System.in)), - new PrintWriter(System.err, true)); + new PrintWriter(System.err, true)) //######################################################################## // Public Methods - Count /** Returns the number of errors issued totally as a string */ - def getCountString(severity : Severity) : String = getCountString0(count(severity), label(severity));; + def getCountString(severity : Severity) : String = getCountString0(count(severity), label(severity)) /** Returns a string meaning "n elements". */ def getCountString0(n : Int, elements : String) : String = n match { - case 0 => "no " + elements + "s"; - case 1 => "one " + elements; - case 2 => "two " + elements + "s"; - case 3 => "three " + elements + "s"; - case 4 => "four " + elements + "s"; - case _ => "" + n + " " + elements + "s"; + case 0 => "no " + elements + "s" + case 1 => "one " + elements + case 2 => "two " + elements + "s" + case 3 => "three " + elements + "s" + case 4 => "four " + elements + "s" + case _ => "" + n + " " + elements + "s" } @@ -65,70 +65,75 @@ class ConsoleReporter(reader : BufferedReader, writer : PrintWriter) extends Abs // Public Methods - Print /** Prints the message. */ - def printMessage(msg : String) = writer.println(msg); + def printMessage(msg : String) = writer.println(msg) /** Prints the message with the given position indication. */ def printMessage(posIn : Position, msg : String) : Unit = { if (posIn != null) { val pos = posIn.inUltimateSource - val buf = new StringBuffer(msg); - buf.insert(0, " "); + val buf = new StringBuffer(msg) + buf.insert(0, " ") if (pos.line != Position.NOLINE) - buf.insert(0, ":" + pos.line); - val file = pos.source.file; - buf.insert(0, if (shortname) file.name else file.path); - printMessage(buf.toString()); - printSourceLine(pos); - } else printMessage(msg); + buf.insert(0, ":" + pos.line) + pos match { + case FakePos(msg) => + buf.insert(0,msg) + case _ => + val file = pos.source.file + buf.insert(0, if (shortname) file.name else file.path) + } + printMessage(buf.toString()) + printSourceLine(pos) + } else printMessage(msg) } - def print(pos : Position, msg : String, severity : Severity) = printMessage(pos, clabel(severity) + msg); + def print(pos : Position, msg : String, severity : Severity) = printMessage(pos, clabel(severity) + msg) def printSourceLine(pos : Position) = if (pos != null && pos.offset != Position.NOPOS) { - printMessage(pos.lineContent.stripLineEnd); - printColumnMarker(pos); + printMessage(pos.lineContent.stripLineEnd) + printColumnMarker(pos) } /** Prints the column marker of the given position. */ def printColumnMarker(pos : Position) = if (pos != null) { - val buffer = new StringBuffer(pos.column); - var i = 1; + val buffer = new StringBuffer(pos.column) + var i = 1 while (i < pos.column) { - buffer.append(' '); - i = i + 1; + buffer.append(' ') + i = i + 1 } - if (pos.column > 0) buffer.append('^'); - printMessage(buffer.toString()); + if (pos.column > 0) buffer.append('^') + printMessage(buffer.toString()) } /** Prints the number of errors and warnings if their are non-zero. */ def printSummary() = { - if (warnings > 0) printMessage(getCountString(WARNING) + " found"); - if ( errors > 0) printMessage(getCountString(ERROR ) + " found"); + if (warnings > 0) printMessage(getCountString(WARNING) + " found") + if ( errors > 0) printMessage(getCountString(ERROR ) + " found") } //######################################################################## // Public Methods - Display def display(pos : Position, msg : String, severity : Severity) : Unit = { - incr(severity); - print(pos, msg, severity); - }; + incr(severity) + print(pos, msg, severity) + } def displayPrompt : Unit = try { - var continue = true; + var continue = true while (continue) { - writer.print("r)esume, a)bort: "); - writer.flush(); - var line = reader.readLine(); + writer.print("r)esume, a)bort: ") + writer.flush() + var line = reader.readLine() if (line != null) { - line = line.toLowerCase(); + line = line.toLowerCase() if ("abort".startsWith(line)) - throw new Error("user abort"); - if ("resume".startsWith(line)) continue = false; + throw new Error("user abort") + if ("resume".startsWith(line)) continue = false } } } catch { case ex: IOException => { - ex.printStackTrace(); - throw new Error("input read error"); + ex.printStackTrace() + throw new Error("input read error") } } } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/AbstractFileReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/AbstractFileReader.scala new file mode 100644 index 0000000000..684ecb3d9e --- /dev/null +++ b/src/compiler/scala/tools/nsc/symtab/classfile/AbstractFileReader.scala @@ -0,0 +1,116 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002-2006, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id$ + + +package scala.tools.nsc.symtab.classfile + +import scala.tools.nsc.io.{AbstractFile, PlainFile, ZipArchive} + +import java.io.{File, FileInputStream, IOException}; + +/** this class reads files byte per byte. Only used by ClassFileParser + */ +class AbstractFileReader(val file: AbstractFile) { + + /** the buffer containing the file + */ + val buf: Array[Byte] = file match { + case p:PlainFile => + assert(!file.isDirectory, "cannot read directory '" + this + "'"); + val in = new FileInputStream(p.file); + var rest: Int = p.file.length().toInt; + val bbuf: Array[Byte] = new Array[Byte](rest); + while (rest > 0) { + val res = in.read(bbuf, bbuf.length - rest, rest); + if (res == -1) + throw new IOException("read error"); + rest = rest - res; + } + in.close(); + bbuf + case z:ZipArchive#FileEntry => // zipfileentry + val in = z.getArchive.getInputStream(z.entry) + var rest: Int = z.entry.getSize().toInt; + val buf = new Array[Byte](rest); + while (rest > 0) { + val res = in.read(buf, buf.length - rest, rest); + if (res == -1) + throw new IOException("read error"); + rest = rest - res; + } + in.close(); + buf + case _ => + error("internal error: do not know how to get bytes of "+file) + } + + /** the current input pointer + */ + var bp: Int = 0 + + /** return byte at offset 'pos' + */ + def byteAt(pos: Int): Byte = return buf(pos) + + /** read a byte + */ + def nextByte: Byte = { + val b = buf(bp) + bp = bp + 1 + b + } + + /** read some bytes + */ + def nextBytes(len: Int): Array[Byte] = { + bp = bp + len + buf.subArray(bp - len, bp) + } + + /** read a character + */ + def nextChar: Char = { + (((nextByte & 0xff) << 8) + (nextByte & 0xff)).toChar + } + + /** read an integer + */ + def nextInt: Int = + ((nextByte & 0xff) << 24) + ((nextByte & 0xff) << 16) + + ((nextByte & 0xff) << 8) + (nextByte & 0xff) + + + /** extract a character at position bp from buf + */ + def getChar(mybp: Int): Char = + (((buf(mybp) & 0xff) << 8) + (buf(mybp+1) & 0xff)).toChar + + /** extract an integer at position bp from buf + */ + def getInt(mybp: Int): Int = + ((buf(mybp ) & 0xff) << 24) + ((buf(mybp+1) & 0xff) << 16) + + ((buf(mybp+2) & 0xff) << 8) + (buf(mybp+3) & 0xff) + + /** extract a long integer at position bp from buf + */ + def getLong(mybp: Int): Long = + (getInt(mybp).toLong << 32) + (getInt(mybp + 4) & 0xffffffffL) + + /** extract a float at position bp from buf + */ + def getFloat(mybp: Int): Float = Float.intBitsToFloat(getInt(mybp)) + + /** extract a double at position bp from buf + */ + def getDouble(mybp: Int): Double = Double.longBitsToDouble(getLong(mybp)) + + /** skip next 'n' bytes + */ + def skip(n: Int): Unit = bp = bp + n + +} diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index e16d602d4f..8a29f31912 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -17,7 +17,7 @@ package scala.tools.nsc.symtab.classfile import scala.tools.nsc.util.Position -import scala.tools.nsc.io.{AbstractFile, AbstractFileReader} +import scala.tools.nsc.io.AbstractFile import scala.collection.mutable.{ListBuffer, ArrayBuffer} import scala.collection.immutable.{Map, ListMap} diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/SymblfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/SymblfileParser.scala index c17e41e88f..a9af8bb794 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/SymblfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/SymblfileParser.scala @@ -6,7 +6,7 @@ package scala.tools.nsc.symtab.classfile -import scala.tools.nsc.io.{AbstractFile, AbstractFileReader} +import scala.tools.nsc.io.AbstractFile /** This abstract class implements .. * @@ -27,11 +27,11 @@ abstract class SymblfileParser { def parse(file: AbstractFile, root: Symbol): unit = { assert(current == null, current) current = file - val in = new AbstractFileReader(file) + val bytes = new AbstractFileReader(file).buf if (root.isModule) - unpickler.unpickle(in.buf, 0, root.linkedClassOfModule, root, file.toString()) + unpickler.unpickle(bytes, 0, root.linkedClassOfModule, root, file.toString()) else - unpickler.unpickle(in.buf, 0, root, root.linkedModuleOfClass, file.toString()) + unpickler.unpickle(bytes, 0, root, root.linkedModuleOfClass, file.toString()) current = null } } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala index 664d60a0a4..a0ac83d82c 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala @@ -25,6 +25,10 @@ abstract class UnPickler { import global._ import RequiresIntsAsPositions._; + /** + * @param bytes bytearray from which we unpickle + * @param filename filename associated with bytearray, only used for error messages + */ def unpickle(bytes: Array[byte], offset: int, classRoot: Symbol, moduleRoot: Symbol, filename: String): unit = try { new UnPickle(bytes, offset, classRoot, moduleRoot) } catch { diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala index efa139876c..d3a9edde4f 100644 --- a/src/compiler/scala/tools/nsc/util/Position.scala +++ b/src/compiler/scala/tools/nsc/util/Position.scala @@ -30,14 +30,13 @@ object Position { } } - class Position( val source : SourceFile, val offset: Int) { import Position._; private val tabInc = 8; - def this(sourceName : String) = this(new SourceFile(sourceName, new Array[Char](0)), Position.NOPOS); - def this(sourceName : String, _offset : Int) = this(new SourceFile(sourceName, new Array[Char](0)), _offset); + //def this(sourceName : String) = this(new SourceFile(sourceName, new Array[Char](0)), Position.NOPOS); + //def this(sourceName : String, _offset : Int) = this(new SourceFile(sourceName, new Array[Char](0)), _offset); private def hasOffset = offset > NOPOS; private def isLine = offset < NOPOS; @@ -104,3 +103,9 @@ class Position( val source : SourceFile, val offset: Int) { sb.toString(); } } + +/** this class merely serves to communicate a string to ConsoleReporter + */ +case class FakePos(msg: String) extends Position(null,Position.NOPOS) { + override def inUltimateSource = this +} diff --git a/src/compiler/scala/tools/nsc/util/SourceFile.scala b/src/compiler/scala/tools/nsc/util/SourceFile.scala index bbad817896..e10f0e903c 100644 --- a/src/compiler/scala/tools/nsc/util/SourceFile.scala +++ b/src/compiler/scala/tools/nsc/util/SourceFile.scala @@ -11,7 +11,7 @@ package scala.tools.nsc.util -import scala.tools.nsc.io.{AbstractFile, CharArrayFile} +import scala.tools.nsc.io.{AbstractFile,VirtualFile} /** Uses positions that are offsets rather than line/column pairs. * @@ -26,23 +26,20 @@ object SourceFile { } -class SourceFile(_file: AbstractFile, _content: Array[Char]) { +class SourceFile(val file: AbstractFile, _content: Array[Char]) { import SourceFile._ - def this(_file: AbstractFile) = { - this(_file, (new String(_file.read)).toCharArray) - } + //def this(_file: AbstractFile) = this(_file, _file.getChars) + + def this(sourceName: String, content: Array[Char]) = + this(new VirtualFile(sourceName), content) - val file = _file val content = normalize(_content) def getContent() = content def getFile() = file - def this(sourceName: String, content: Array[Char]) = - this(new CharArrayFile(sourceName, content), content) - def isLineBreak(idx: Int) = if (!SourceFile.isLineBreak(content(idx))) false else if (content(idx) == CR && idx + 1 < content.length && content(idx + 1) == LF) false; |