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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
/* NSC -- new Scala compiler
* Copyright 2005-2006 LAMP/EPFL
* @author Martin Odersky
*/
// $Id: $
package scala.tools.nsc
import java.io.{BufferedReader,FileReader}
/** A main routine to support putting Scala code into scripts.
*
* An shell script example on Unix would look like this:
*
* #!/bin/sh
* exec scalascript "$0" "$@"
* !#
* Console.println("Hello, world!")
* argv.toList foreach Console.println
*
* A batch file example on Windows XP would look like this:
*
* ::#!
* @echo off
* call scalascript %0 %*
* goto :eof
* ::!#
* Console.println("Hello, world!")
* argv.toList foreach Console.println
*
* TODO: It would be better if error output went to stderr instead
* of stdout....
*/
object MainScript {
/** Read the contents of the specified file, skipping the header
* part if there is one. The header part starts with "#!"
* and ends with a line that begins with "!#".
*/
val startRegexp = "^(::)?#!.*"
val endRegexp = "^(::)?!#.*"
def readFileSkippingHeader(filename: String): String = {
val file =
new BufferedReader(
new FileReader(filename))
val contents = new StringBuffer
// skip the header, if there is one
val firstLine = file.readLine
if (firstLine == null)
return ""
else if (firstLine.matches(startRegexp)) {
// skip until !# is seen
def lp: Unit = {
val line = file.readLine
if (line == null)
()
else if (!line.matches(endRegexp))
lp
}
lp
}
else
contents.append(firstLine)
// now read the rest of the file
def lp: Unit = {
val line = file.readLine
if (line == null)
return ()
contents.append(line)
contents.append("\n")
lp
}
lp
contents.toString
}
/** Print a usage message and then exit. */
def usageExit: Nothing = {
Console.println(
"scalascript [ compiler arguments... - ] scriptfile " +
"[ script arguments... ]")
Console.println
Console.println(
"Note that if you do specify compiler arguments, you \n" +
"must put an explicit hyphen (\"-\") at the end of them.")
System.exit(1).asInstanceOf[Nothing]
}
/** Parse an argument list into three portions:
*
* Arguments to the compiler
* The filename of the script to run
* Arguments to pass to the script
*/
def parseArgs(args: List[String])
:Tuple3[List[String], String, List[String]] =
{
if (args.length == 0)
usageExit
if (args(0).startsWith("-")) {
// the line includes compiler arguments
val hyphenIndex = args.indexOf("-")
if (hyphenIndex < 0)
usageExit
if (hyphenIndex == (args.length - 1))
usageExit
Tuple3(
args.subseq(0, hyphenIndex).toList,
args(hyphenIndex + 1),
args.subseq(hyphenIndex + 2, args.length - hyphenIndex - 2).toList)
} else {
Tuple3(
Nil,
args(0),
args.subseq(1, args.length-1).toList)
}
}
def main(args: Array[String]): Unit = {
val parsedArgs = parseArgs(args.toList)
val compilerArgs = parsedArgs._1
val scriptFile = parsedArgs._2
val scriptArgs = parsedArgs._3.toArray
val command =
new CompilerCommand(
compilerArgs,
Console.println,
false)
if (!command.ok || command.settings.help.value) {
// either the command line is wrong, or the user
// explicitly requested a help listing
if (!command.ok)
Console.println
usageExit
}
val scriptContents = readFileSkippingHeader(scriptFile)
val toRun =
"package scala.scripting\n" +
"object Main {\n" +
" def main(argv: Array[String]): Unit = {\n" +
scriptContents +
"\n} }\n"
val interpreter = new Interpreter(command.settings)
interpreter.beQuiet
if (!interpreter.compileString(toRun))
return () // compilation error
interpreter.bind("argv", "Array[String]", scriptArgs)
interpreter.interpret("scala.scripting.Main.main(argv)")
}
}
|