wenzelm@30176
|
1 |
/* Title: Pure/System/isabelle_system.scala
|
wenzelm@27919
|
2 |
Author: Makarius
|
wenzelm@27919
|
3 |
|
wenzelm@27974
|
4 |
Isabelle system support -- basic Cygwin/Posix compatibility.
|
wenzelm@27919
|
5 |
*/
|
wenzelm@27919
|
6 |
|
wenzelm@27919
|
7 |
package isabelle
|
wenzelm@27919
|
8 |
|
wenzelm@27936
|
9 |
import java.util.regex.{Pattern, Matcher}
|
wenzelm@28063
|
10 |
import java.io.{BufferedReader, InputStreamReader, FileInputStream, File, IOException}
|
wenzelm@28063
|
11 |
|
wenzelm@28063
|
12 |
import scala.io.Source
|
wenzelm@27936
|
13 |
|
wenzelm@27919
|
14 |
|
wenzelm@29174
|
15 |
class IsabelleSystem {
|
wenzelm@27919
|
16 |
|
wenzelm@28057
|
17 |
val charset = "UTF-8"
|
wenzelm@28057
|
18 |
|
wenzelm@28057
|
19 |
|
wenzelm@28046
|
20 |
/* Isabelle environment settings */
|
wenzelm@27919
|
21 |
|
wenzelm@29177
|
22 |
private val environment = System.getenv
|
wenzelm@29177
|
23 |
|
wenzelm@27953
|
24 |
def getenv(name: String) = {
|
wenzelm@29177
|
25 |
val value = environment.get(if (name == "HOME") "HOME_JVM" else name)
|
wenzelm@27953
|
26 |
if (value != null) value else ""
|
wenzelm@27953
|
27 |
}
|
wenzelm@27919
|
28 |
|
wenzelm@27953
|
29 |
def getenv_strict(name: String) = {
|
wenzelm@31234
|
30 |
val value = getenv(name)
|
wenzelm@27993
|
31 |
if (value != "") value else error("Undefined environment variable: " + name)
|
wenzelm@27919
|
32 |
}
|
wenzelm@27919
|
33 |
|
wenzelm@29177
|
34 |
val is_cygwin = Pattern.matches(".*-cygwin", getenv_strict("ML_PLATFORM"))
|
wenzelm@28046
|
35 |
|
wenzelm@27919
|
36 |
|
wenzelm@27974
|
37 |
/* file path specifications */
|
wenzelm@27936
|
38 |
|
wenzelm@27936
|
39 |
private val cygdrive_pattern = Pattern.compile("/cygdrive/([a-zA-Z])($|/.*)")
|
wenzelm@27936
|
40 |
|
wenzelm@27936
|
41 |
def platform_path(source_path: String) = {
|
wenzelm@27936
|
42 |
val result_path = new StringBuilder
|
wenzelm@27936
|
43 |
|
wenzelm@27936
|
44 |
def init(path: String) = {
|
wenzelm@27936
|
45 |
val cygdrive = cygdrive_pattern.matcher(path)
|
wenzelm@27936
|
46 |
if (cygdrive.matches) {
|
wenzelm@27953
|
47 |
result_path.length = 0
|
wenzelm@27936
|
48 |
result_path.append(cygdrive.group(1))
|
wenzelm@27936
|
49 |
result_path.append(":")
|
wenzelm@27936
|
50 |
result_path.append(File.separator)
|
wenzelm@27936
|
51 |
cygdrive.group(2)
|
wenzelm@27936
|
52 |
}
|
wenzelm@27936
|
53 |
else if (path.startsWith("/")) {
|
wenzelm@27953
|
54 |
result_path.length = 0
|
wenzelm@27953
|
55 |
result_path.append(getenv_strict("ISABELLE_ROOT_JVM"))
|
wenzelm@27936
|
56 |
path.substring(1)
|
wenzelm@27936
|
57 |
}
|
wenzelm@27936
|
58 |
else path
|
wenzelm@27936
|
59 |
}
|
wenzelm@27936
|
60 |
def append(path: String) = {
|
wenzelm@27936
|
61 |
for (p <- init(path).split("/")) {
|
wenzelm@27936
|
62 |
if (p != "") {
|
wenzelm@27936
|
63 |
val len = result_path.length
|
wenzelm@27936
|
64 |
if (len > 0 && result_path(len - 1) != File.separatorChar)
|
wenzelm@27936
|
65 |
result_path.append(File.separator)
|
wenzelm@27936
|
66 |
result_path.append(p)
|
wenzelm@27936
|
67 |
}
|
wenzelm@27936
|
68 |
}
|
wenzelm@27936
|
69 |
}
|
wenzelm@27936
|
70 |
for (p <- init(source_path).split("/")) {
|
wenzelm@27953
|
71 |
if (p.startsWith("$")) append(getenv_strict(p.substring(1)))
|
wenzelm@27953
|
72 |
else if (p == "~") append(getenv_strict("HOME"))
|
wenzelm@27953
|
73 |
else if (p == "~~") append(getenv_strict("ISABELLE_HOME"))
|
wenzelm@27936
|
74 |
else append(p)
|
wenzelm@27936
|
75 |
}
|
wenzelm@27936
|
76 |
result_path.toString
|
wenzelm@27936
|
77 |
}
|
wenzelm@27953
|
78 |
|
wenzelm@29152
|
79 |
def platform_file(path: String) =
|
wenzelm@29152
|
80 |
new File(platform_path(path))
|
wenzelm@29152
|
81 |
|
wenzelm@27953
|
82 |
|
wenzelm@31440
|
83 |
/* source files */
|
wenzelm@31440
|
84 |
|
wenzelm@31440
|
85 |
private def try_file(file: File) = if (file.isFile) Some(file) else None
|
wenzelm@31440
|
86 |
|
wenzelm@31440
|
87 |
def source_file(path: String): Option[File] = {
|
wenzelm@31440
|
88 |
if (path == "ML") None
|
wenzelm@31440
|
89 |
else if (path.startsWith("/") || path == "")
|
wenzelm@31440
|
90 |
try_file(platform_file(path))
|
wenzelm@31440
|
91 |
else {
|
wenzelm@31440
|
92 |
val pure_file = platform_file("~~/src/Pure/" + path)
|
wenzelm@31440
|
93 |
if (pure_file.isFile) Some(pure_file)
|
wenzelm@31440
|
94 |
else if (getenv("ML_SOURCES") != "")
|
wenzelm@31440
|
95 |
try_file(platform_file("$ML_SOURCES/" + path))
|
wenzelm@31440
|
96 |
else None
|
wenzelm@31440
|
97 |
}
|
wenzelm@31440
|
98 |
}
|
wenzelm@31440
|
99 |
|
wenzelm@31440
|
100 |
|
wenzelm@31440
|
101 |
/* shell processes */
|
wenzelm@27953
|
102 |
|
wenzelm@29177
|
103 |
def execute(redirect: Boolean, args: String*): Process = {
|
wenzelm@29177
|
104 |
val cmdline = new java.util.LinkedList[String]
|
wenzelm@29177
|
105 |
if (is_cygwin) cmdline.add(platform_path("/bin/env"))
|
wenzelm@29177
|
106 |
for (s <- args) cmdline.add(s)
|
wenzelm@27953
|
107 |
|
wenzelm@29177
|
108 |
val proc = new ProcessBuilder(cmdline)
|
wenzelm@29180
|
109 |
proc.environment.clear
|
wenzelm@29180
|
110 |
proc.environment.putAll(environment)
|
wenzelm@29180
|
111 |
proc.redirectErrorStream(redirect)
|
wenzelm@29180
|
112 |
proc.start
|
wenzelm@28046
|
113 |
}
|
wenzelm@28046
|
114 |
|
wenzelm@28063
|
115 |
|
wenzelm@28063
|
116 |
/* Isabelle tools (non-interactive) */
|
wenzelm@28063
|
117 |
|
wenzelm@28496
|
118 |
def isabelle_tool(args: String*) = {
|
wenzelm@28063
|
119 |
val proc =
|
wenzelm@29177
|
120 |
try { execute(true, (List(getenv_strict("ISABELLE_TOOL")) ++ args): _*) }
|
wenzelm@28063
|
121 |
catch { case e: IOException => error(e.getMessage) }
|
wenzelm@28063
|
122 |
proc.getOutputStream.close
|
wenzelm@29174
|
123 |
val output = Source.fromInputStream(proc.getInputStream, charset).mkString
|
wenzelm@28063
|
124 |
val rc = proc.waitFor
|
wenzelm@28063
|
125 |
(output, rc)
|
wenzelm@28063
|
126 |
}
|
wenzelm@28063
|
127 |
|
wenzelm@28063
|
128 |
|
wenzelm@28063
|
129 |
/* named pipes */
|
wenzelm@28063
|
130 |
|
wenzelm@28063
|
131 |
def mk_fifo() = {
|
wenzelm@28496
|
132 |
val (result, rc) = isabelle_tool("mkfifo")
|
wenzelm@28063
|
133 |
if (rc == 0) result.trim
|
wenzelm@28063
|
134 |
else error(result)
|
wenzelm@28063
|
135 |
}
|
wenzelm@28063
|
136 |
|
wenzelm@28063
|
137 |
def rm_fifo(fifo: String) = {
|
wenzelm@28496
|
138 |
val (result, rc) = isabelle_tool("rmfifo", fifo)
|
wenzelm@28063
|
139 |
if (rc != 0) error(result)
|
wenzelm@28063
|
140 |
}
|
wenzelm@28063
|
141 |
|
wenzelm@29177
|
142 |
def fifo_reader(fifo: String) = {
|
wenzelm@29177
|
143 |
// blocks until writer is ready
|
wenzelm@29177
|
144 |
val stream =
|
wenzelm@29177
|
145 |
if (is_cygwin) execute(false, "cat", fifo).getInputStream
|
wenzelm@29177
|
146 |
else new FileInputStream(fifo)
|
wenzelm@29177
|
147 |
new BufferedReader(new InputStreamReader(stream, charset))
|
wenzelm@29177
|
148 |
}
|
wenzelm@28063
|
149 |
|
wenzelm@29152
|
150 |
|
wenzelm@29152
|
151 |
/* find logics */
|
wenzelm@29152
|
152 |
|
wenzelm@29152
|
153 |
def find_logics() = {
|
wenzelm@29152
|
154 |
val ml_ident = getenv_strict("ML_IDENTIFIER")
|
wenzelm@29152
|
155 |
var logics: Set[String] = Set()
|
wenzelm@29152
|
156 |
for (dir <- getenv_strict("ISABELLE_PATH").split(":")) {
|
wenzelm@29152
|
157 |
val files = platform_file(dir + "/" + ml_ident).listFiles()
|
wenzelm@29152
|
158 |
if (files != null) {
|
wenzelm@29152
|
159 |
for (file <- files if file.isFile) logics += file.getName
|
wenzelm@29152
|
160 |
}
|
wenzelm@29152
|
161 |
}
|
wenzelm@29152
|
162 |
logics.toList.sort(_ < _)
|
wenzelm@29152
|
163 |
}
|
wenzelm@29570
|
164 |
|
wenzelm@29570
|
165 |
|
wenzelm@29570
|
166 |
/* symbols */
|
wenzelm@29570
|
167 |
|
wenzelm@29570
|
168 |
private def read_symbols(path: String) = {
|
wenzelm@29570
|
169 |
val file = new File(platform_path(path))
|
wenzelm@31440
|
170 |
if (file.isFile) Source.fromFile(file).getLines
|
wenzelm@29570
|
171 |
else Iterator.empty
|
wenzelm@29570
|
172 |
}
|
wenzelm@29570
|
173 |
val symbols = new Symbol.Interpretation(
|
wenzelm@29570
|
174 |
read_symbols("$ISABELLE_HOME/etc/symbols") ++
|
wenzelm@29570
|
175 |
read_symbols("$ISABELLE_HOME_USER/etc/symbols"))
|
wenzelm@27919
|
176 |
}
|