summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/CompileClient.scala
blob: 013ce2a8231f1636e9f0c846a2467123366f0ab3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* NSC -- new Scala compiler
 * Copyright 2005-2009 LAMP/EPFL
 * @author  Martin Odersky
 */
// $Id$

package scala.tools.nsc

import java.io.{BufferedReader, File, InputStreamReader, PrintWriter}

/** The client part of the fsc offline compiler.  Instead of compiling
 *  things itself, it send requests to a CompileServer.
 */
class StandardCompileClient {
  def compileSocket: CompileSocket = CompileSocket  // todo: should be lazy val

  val versionMsg = "Fast Scala Compiler " +
    Properties.versionString + " -- " +
    Properties.copyrightString

  var verbose = false
  var version = false
  var shutdown = false

  /** Convert a filename to an absolute path */
  def absFileName(path: String) = new File(path).getAbsolutePath()

  /** Convert a sequence of filenames, separated by <code>File.pathSeparator</code>,
    * into absolute filenames.
    */
  def absFileNames(paths: String) = {
    val sep = File.pathSeparator
    val pathsList = paths.split(sep).toList
    pathsList.map(absFileName).mkString("", sep, "")
  }

  val fileEnding = Properties.fileEndingString

  protected def normalize(args: Array[String]): (String, String) = {
     var i = 0
    val vmArgs = new StringBuilder
    var serverAdr = ""
    while (i < args.length) {
      val arg = args(i)
      if (fileEnding split ("\\|") exists (arg endsWith _)) {
        args(i) = absFileName(arg)
      } else if (arg startsWith "-J") {
        //see http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/javac.html#J
        vmArgs append " "+arg.substring(2)
        args(i) = ""
      } else if (arg == "-verbose") {
        verbose = true
      } else if (arg == "-version") {
        version = true
      } else if (arg == "-shutdown") {
        shutdown = true
      }
      i += 1
      if (i < args.length) {
        if (arg == "-classpath" ||
            arg == "-sourcepath" ||
            arg == "-bootclasspath" ||
            arg == "-extdirs" ||
            arg == "-d") {
          args(i) = absFileNames(args(i))
          i += 1
        } else if (arg == "-server") {
          serverAdr = args(i)
          args(i-1) = ""
          args(i) = ""
        }
      }
    }
    (vmArgs.toString, serverAdr)
  }

  // used by class ant.FastScalac to skip exit statement in Ant.
  def main0(args0: Array[String]): Int = {
    val args =
      if (args0.exists(arg => arg == "-d"))
        args0
      else
        ("-d" :: "." :: args0.toList).toArray

    val (vmArgs, serverAdr) = normalize(args)
    if (version) {
      Console.println(versionMsg)
      return 0
    }
    if (verbose) {
      Console.println("[Server arguments: " + args.mkString("", " ", "]"))
      Console.println("[VM arguments: " + vmArgs + "]")
    }
    val socket = if (serverAdr == "") compileSocket.getOrCreateSocket(vmArgs, !shutdown)
                 else compileSocket.getSocket(serverAdr)
    var sawerror = false
    if (socket eq null) {
      if (shutdown) {
        Console.println("[No compilation server running.]")
      } else {
        Console.println("Compilation failed.")
        sawerror = true
      }
    } else {
      val out = new PrintWriter(socket.getOutputStream(), true)
      val in = new BufferedReader(new InputStreamReader(socket.getInputStream()))
      out.println(compileSocket.getPassword(socket.getPort()))
      out.println(args.mkString("", "\0", ""))
      var fromServer = in.readLine()
      while (fromServer ne null) {
        if (compileSocket.errorPattern.matcher(fromServer).matches)
          sawerror = true
        Console.println(fromServer)
        fromServer = in.readLine()
      }
      in.close()
      out.close()
      socket.close()
    }
    if (sawerror) 1 else 0
  }

  def main(args: Array[String]) {
    try {
      val status = main0(args)
      exit(status)
    } catch {
      case e: Exception => exit(1)
    }
  }
}


object CompileClient extends StandardCompileClient