1 /* Title: Pure/System/isabelle_system.scala
4 Isabelle system support -- basic Cygwin/Posix compatibility.
9 import java.util.regex.{Pattern, Matcher}
10 import java.io.{BufferedReader, InputStreamReader, FileInputStream, File, IOException}
12 import scala.io.Source
15 class IsabelleSystem {
20 /* Isabelle environment settings */
22 private val environment = System.getenv
24 def getenv(name: String) = {
25 val value = environment.get(if (name == "HOME") "HOME_JVM" else name)
26 if (value != null) value else ""
29 def getenv_strict(name: String) = {
30 val value = getenv(name)
31 if (value != "") value else error("Undefined environment variable: " + name)
34 val is_cygwin = Pattern.matches(".*-cygwin", getenv_strict("ML_PLATFORM"))
37 /* file path specifications */
39 private val cygdrive_pattern = Pattern.compile("/cygdrive/([a-zA-Z])($|/.*)")
41 def platform_path(source_path: String) = {
42 val result_path = new StringBuilder
44 def init(path: String) = {
45 val cygdrive = cygdrive_pattern.matcher(path)
46 if (cygdrive.matches) {
47 result_path.length = 0
48 result_path.append(cygdrive.group(1))
49 result_path.append(":")
50 result_path.append(File.separator)
53 else if (path.startsWith("/")) {
54 result_path.length = 0
55 result_path.append(getenv_strict("ISABELLE_ROOT_JVM"))
60 def append(path: String) = {
61 for (p <- init(path).split("/")) {
63 val len = result_path.length
64 if (len > 0 && result_path(len - 1) != File.separatorChar)
65 result_path.append(File.separator)
70 for (p <- init(source_path).split("/")) {
71 if (p.startsWith("$")) append(getenv_strict(p.substring(1)))
72 else if (p == "~") append(getenv_strict("HOME"))
73 else if (p == "~~") append(getenv_strict("ISABELLE_HOME"))
79 def platform_file(path: String) =
80 new File(platform_path(path))
85 private def try_file(file: File) = if (file.isFile) Some(file) else None
87 def source_file(path: String): Option[File] = {
88 if (path == "ML") None
89 else if (path.startsWith("/") || path == "")
90 try_file(platform_file(path))
92 val pure_file = platform_file("~~/src/Pure/" + path)
93 if (pure_file.isFile) Some(pure_file)
94 else if (getenv("ML_SOURCES") != "")
95 try_file(platform_file("$ML_SOURCES/" + path))
101 /* shell processes */
103 def execute(redirect: Boolean, args: String*): Process = {
104 val cmdline = new java.util.LinkedList[String]
105 if (is_cygwin) cmdline.add(platform_path("/bin/env"))
106 for (s <- args) cmdline.add(s)
108 val proc = new ProcessBuilder(cmdline)
109 proc.environment.clear
110 proc.environment.putAll(environment)
111 proc.redirectErrorStream(redirect)
116 /* Isabelle tools (non-interactive) */
118 def isabelle_tool(args: String*) = {
120 try { execute(true, (List(getenv_strict("ISABELLE_TOOL")) ++ args): _*) }
121 catch { case e: IOException => error(e.getMessage) }
122 proc.getOutputStream.close
123 val output = Source.fromInputStream(proc.getInputStream, charset).mkString
124 val rc = proc.waitFor
132 val (result, rc) = isabelle_tool("mkfifo")
133 if (rc == 0) result.trim
137 def rm_fifo(fifo: String) = {
138 val (result, rc) = isabelle_tool("rmfifo", fifo)
139 if (rc != 0) error(result)
142 def fifo_reader(fifo: String) = {
143 // blocks until writer is ready
145 if (is_cygwin) execute(false, "cat", fifo).getInputStream
146 else new FileInputStream(fifo)
147 new BufferedReader(new InputStreamReader(stream, charset))
153 def find_logics() = {
154 val ml_ident = getenv_strict("ML_IDENTIFIER")
155 var logics: Set[String] = Set()
156 for (dir <- getenv_strict("ISABELLE_PATH").split(":")) {
157 val files = platform_file(dir + "/" + ml_ident).listFiles()
159 for (file <- files if file.isFile) logics += file.getName
162 logics.toList.sort(_ < _)
168 private def read_symbols(path: String) = {
169 val file = new File(platform_path(path))
170 if (file.isFile) Source.fromFile(file).getLines
173 val symbols = new Symbol.Interpretation(
174 read_symbols("$ISABELLE_HOME/etc/symbols") ++
175 read_symbols("$ISABELLE_HOME_USER/etc/symbols"))