| author | blanchet | 
| Wed, 18 Jul 2012 08:44:03 +0200 | |
| changeset 48300 | 9910021c80a7 | 
| parent 48278 | 2b737f639ad4 | 
| child 48353 | bcce872202b3 | 
| permissions | -rw-r--r-- | 
| 30175 | 1 | /* Title: Pure/System/isabelle_system.scala | 
| 27919 | 2 | Author: Makarius | 
| 3 | ||
| 43695 
5130dfe1b7be
simplified Symbol based on lazy Symbol.Interpretation -- reduced odd "functorial style";
 wenzelm parents: 
43670diff
changeset | 4 | Fundamental Isabelle system environment: quasi-static module with | 
| 
5130dfe1b7be
simplified Symbol based on lazy Symbol.Interpretation -- reduced odd "functorial style";
 wenzelm parents: 
43670diff
changeset | 5 | optional init operation. | 
| 27919 | 6 | */ | 
| 7 | ||
| 8 | package isabelle | |
| 9 | ||
| 43520 
cec9b95fa35d
explicit import java.lang.System to prevent odd scope problems;
 wenzelm parents: 
43514diff
changeset | 10 | import java.lang.System | 
| 31520 
0a99c8716312
simplified IsabelleSystem.platform_path for cygwin;
 wenzelm parents: 
31500diff
changeset | 11 | import java.util.regex.Pattern | 
| 31820 | 12 | import java.util.Locale | 
| 45027 
f459e93a038e
more abstract wrapping of fifos as System_Channel;
 wenzelm parents: 
44184diff
changeset | 13 | import java.io.{InputStream, OutputStream, File, BufferedReader, InputStreamReader,
 | 
| 
f459e93a038e
more abstract wrapping of fifos as System_Channel;
 wenzelm parents: 
44184diff
changeset | 14 | BufferedWriter, OutputStreamWriter, IOException} | 
| 34024 | 15 | import java.awt.{GraphicsEnvironment, Font}
 | 
| 37367 | 16 | import java.awt.font.TextAttribute | 
| 28063 | 17 | |
| 18 | import scala.io.Source | |
| 31520 
0a99c8716312
simplified IsabelleSystem.platform_path for cygwin;
 wenzelm parents: 
31500diff
changeset | 19 | import scala.util.matching.Regex | 
| 34163 | 20 | import scala.collection.mutable | 
| 27936 | 21 | |
| 27919 | 22 | |
| 43514 
45cf8d5e109a
lazy Isabelle_System.default supports implicit boot;
 wenzelm parents: 
43484diff
changeset | 23 | object Isabelle_System | 
| 
45cf8d5e109a
lazy Isabelle_System.default supports implicit boot;
 wenzelm parents: 
43484diff
changeset | 24 | {
 | 
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 25 | /** implicit state **/ | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 26 | |
| 43695 
5130dfe1b7be
simplified Symbol based on lazy Symbol.Interpretation -- reduced odd "functorial style";
 wenzelm parents: 
43670diff
changeset | 27 | private case class State(standard_system: Standard_System, settings: Map[String, String]) | 
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 28 | |
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 29 | @volatile private var _state: Option[State] = None | 
| 43514 
45cf8d5e109a
lazy Isabelle_System.default supports implicit boot;
 wenzelm parents: 
43484diff
changeset | 30 | |
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 31 | private def check_state(): State = | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 32 |   {
 | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 33 | if (_state.isEmpty) init() // unsynchronized check | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 34 | _state.get | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 35 | } | 
| 37013 
641923374eba
Isabelle_System: allow explicit isabelle_home argument;
 wenzelm parents: 
36991diff
changeset | 36 | |
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 37 | def standard_system: Standard_System = check_state().standard_system | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 38 | def settings: Map[String, String] = check_state().settings | 
| 31796 | 39 | |
| 37013 
641923374eba
Isabelle_System: allow explicit isabelle_home argument;
 wenzelm parents: 
36991diff
changeset | 40 | /* | 
| 
641923374eba
Isabelle_System: allow explicit isabelle_home argument;
 wenzelm parents: 
36991diff
changeset | 41 | isabelle_home precedence: | 
| 
641923374eba
Isabelle_System: allow explicit isabelle_home argument;
 wenzelm parents: 
36991diff
changeset | 42 | (1) this_isabelle_home as explicit argument | 
| 
641923374eba
Isabelle_System: allow explicit isabelle_home argument;
 wenzelm parents: 
36991diff
changeset | 43 | (2) ISABELLE_HOME process environment variable (e.g. inherited from running isabelle tool) | 
| 
641923374eba
Isabelle_System: allow explicit isabelle_home argument;
 wenzelm parents: 
36991diff
changeset | 44 | (3) isabelle.home system property (e.g. via JVM application boot process) | 
| 
641923374eba
Isabelle_System: allow explicit isabelle_home argument;
 wenzelm parents: 
36991diff
changeset | 45 | */ | 
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 46 |   def init(this_isabelle_home: String = null) = synchronized {
 | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 47 |     if (_state.isEmpty) {
 | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 48 | import scala.collection.JavaConversions._ | 
| 37013 
641923374eba
Isabelle_System: allow explicit isabelle_home argument;
 wenzelm parents: 
36991diff
changeset | 49 | |
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 50 | val standard_system = new Standard_System | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 51 | val settings = | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 52 |       {
 | 
| 48193 | 53 |         val env0 = sys.env + ("ISABELLE_JDK_HOME" -> standard_system.this_jdk_home())
 | 
| 27919 | 54 | |
| 47725 
447b635bcea5
cold-start HOME is user.home, in accordance with Cygwin-Terminal.bat;
 wenzelm parents: 
47674diff
changeset | 55 |         val user_home = System.getProperty("user.home")
 | 
| 
447b635bcea5
cold-start HOME is user.home, in accordance with Cygwin-Terminal.bat;
 wenzelm parents: 
47674diff
changeset | 56 | val env = | 
| 
447b635bcea5
cold-start HOME is user.home, in accordance with Cygwin-Terminal.bat;
 wenzelm parents: 
47674diff
changeset | 57 |           if (user_home == null || env0.isDefinedAt("HOME")) env0
 | 
| 
447b635bcea5
cold-start HOME is user.home, in accordance with Cygwin-Terminal.bat;
 wenzelm parents: 
47674diff
changeset | 58 |           else env0 + ("HOME" -> user_home)
 | 
| 
447b635bcea5
cold-start HOME is user.home, in accordance with Cygwin-Terminal.bat;
 wenzelm parents: 
47674diff
changeset | 59 | |
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 60 | val isabelle_home = | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 61 | if (this_isabelle_home != null) this_isabelle_home | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 62 | else | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 63 |             env.get("ISABELLE_HOME") match {
 | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 64 |               case None | Some("") =>
 | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 65 |                 val path = System.getProperty("isabelle.home")
 | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 66 |                 if (path == null || path == "") error("Unknown Isabelle home directory")
 | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 67 | else path | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 68 | case Some(path) => path | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 69 | } | 
| 29177 | 70 | |
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 71 |           Standard_System.with_tmp_file("settings") { dump =>
 | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 72 | val shell_prefix = | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 73 | if (Platform.is_windows) List(standard_system.platform_root + "\\bin\\bash", "-l") | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 74 | else Nil | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 75 | val cmdline = | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 76 | shell_prefix ::: List(isabelle_home + "/bin/isabelle", "getenv", "-d", dump.toString) | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 77 | val (output, rc) = Standard_System.raw_exec(null, env, true, cmdline: _*) | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 78 | if (rc != 0) error(output) | 
| 31498 | 79 | |
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 80 | val entries = | 
| 48278 
2b737f639ad4
avoid Source.fromFile, which does not necessarily close its input;
 wenzelm parents: 
48193diff
changeset | 81 |                 (for (entry <- Standard_System.read_file(dump) split "\0" if entry != "") yield {
 | 
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 82 |                   val i = entry.indexOf('=')
 | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 83 | if (i <= 0) (entry -> "") | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 84 | else (entry.substring(0, i) -> entry.substring(i + 1)) | 
| 47674 
cdf95042e09c
more robust handling of PATH vs PATH_JVM -- required for cold start of Cygwin from Windows (e.g. Isabelle.exe);
 wenzelm parents: 
47661diff
changeset | 85 | }).toMap | 
| 
cdf95042e09c
more robust handling of PATH vs PATH_JVM -- required for cold start of Cygwin from Windows (e.g. Isabelle.exe);
 wenzelm parents: 
47661diff
changeset | 86 |               entries + ("PATH" -> entries("PATH_JVM")) - "PATH_JVM"
 | 
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 87 | } | 
| 34201 
c95dcd12f48a
separate Standard_System (Cygwin/Posix compatibility) vs. Isabelle_System (settings environment etc.);
 wenzelm parents: 
34200diff
changeset | 88 | } | 
| 43695 
5130dfe1b7be
simplified Symbol based on lazy Symbol.Interpretation -- reduced odd "functorial style";
 wenzelm parents: 
43670diff
changeset | 89 | _state = Some(State(standard_system, settings)) | 
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 90 | } | 
| 27953 | 91 | } | 
| 27919 | 92 | |
| 31796 | 93 | |
| 94 | /* getenv */ | |
| 95 | ||
| 47661 
012a887997f3
USER_HOME settings variable points to cross-platform user home directory;
 wenzelm parents: 
47113diff
changeset | 96 | def getenv(name: String): String = settings.getOrElse(name, "") | 
| 31498 | 97 | |
| 98 | def getenv_strict(name: String): String = | |
| 99 |   {
 | |
| 31234 
6ce6801129de
getenv_strict needs to be based on getenv (accidentally broken in 0e88d33e8d19);
 wenzelm parents: 
30175diff
changeset | 100 | val value = getenv(name) | 
| 27993 
6dd90ef9f927
simplified exceptions: use plain error function / RuntimeException;
 wenzelm parents: 
27974diff
changeset | 101 |     if (value != "") value else error("Undefined environment variable: " + name)
 | 
| 27919 | 102 | } | 
| 103 | ||
| 31796 | 104 | |
| 43606 | 105 | /** file-system operations **/ | 
| 31796 | 106 | |
| 43606 | 107 | /* path specifications */ | 
| 36136 
89b1a136edef
more precise treatment of UNC server prefix, e.g. //foo;
 wenzelm parents: 
36012diff
changeset | 108 | |
| 43664 | 109 | def standard_path(path: Path): String = path.expand.implode | 
| 31796 | 110 | |
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 111 | def platform_path(path: Path): String = standard_system.jvm_path(standard_path(path)) | 
| 45027 
f459e93a038e
more abstract wrapping of fifos as System_Channel;
 wenzelm parents: 
44184diff
changeset | 112 | def platform_file(path: Path): File = new File(platform_path(path)) | 
| 29152 | 113 | |
| 45100 | 114 | def platform_file_url(raw_path: Path): String = | 
| 115 |   {
 | |
| 116 | val path = raw_path.expand | |
| 117 | require(path.is_absolute) | |
| 45101 
6317e969fb30
proper platform_file_url for Windows UNC paths (server shares);
 wenzelm parents: 
45100diff
changeset | 118 |     val s = platform_path(path).replaceAll(" ", "%20")
 | 
| 
6317e969fb30
proper platform_file_url for Windows UNC paths (server shares);
 wenzelm parents: 
45100diff
changeset | 119 | if (!Platform.is_windows) "file://" + s | 
| 
6317e969fb30
proper platform_file_url for Windows UNC paths (server shares);
 wenzelm parents: 
45100diff
changeset | 120 |     else if (s.startsWith("\\\\")) "file:" + s.replace('\\', '/')
 | 
| 
6317e969fb30
proper platform_file_url for Windows UNC paths (server shares);
 wenzelm parents: 
45100diff
changeset | 121 |     else "file:///" + s.replace('\\', '/')
 | 
| 45100 | 122 | } | 
| 123 | ||
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 124 | def posix_path(jvm_path: String): String = standard_system.posix_path(jvm_path) | 
| 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 125 | |
| 27953 | 126 | |
| 36991 | 127 | /* try_read */ | 
| 128 | ||
| 43606 | 129 | def try_read(paths: Seq[Path]): String = | 
| 36991 | 130 |   {
 | 
| 37058 
c47653f3ec14
rendering information and style sheets via settings;
 wenzelm parents: 
37013diff
changeset | 131 | val buf = new StringBuilder | 
| 
c47653f3ec14
rendering information and style sheets via settings;
 wenzelm parents: 
37013diff
changeset | 132 |     for {
 | 
| 
c47653f3ec14
rendering information and style sheets via settings;
 wenzelm parents: 
37013diff
changeset | 133 | path <- paths | 
| 
c47653f3ec14
rendering information and style sheets via settings;
 wenzelm parents: 
37013diff
changeset | 134 | file = platform_file(path) if file.isFile | 
| 48278 
2b737f639ad4
avoid Source.fromFile, which does not necessarily close its input;
 wenzelm parents: 
48193diff
changeset | 135 |     } { buf.append(Standard_System.read_file(file)); buf.append('\n') }
 | 
| 37058 
c47653f3ec14
rendering information and style sheets via settings;
 wenzelm parents: 
37013diff
changeset | 136 | buf.toString | 
| 36991 | 137 | } | 
| 138 | ||
| 139 | ||
| 31436 | 140 | /* source files */ | 
| 141 | ||
| 142 | private def try_file(file: File) = if (file.isFile) Some(file) else None | |
| 143 | ||
| 43606 | 144 | def source_file(path: Path): Option[File] = | 
| 31498 | 145 |   {
 | 
| 43606 | 146 | if (path.is_absolute || path.is_current) | 
| 31436 | 147 | try_file(platform_file(path)) | 
| 148 |     else {
 | |
| 43606 | 149 |       val pure_file = platform_file(Path.explode("~~/src/Pure") + path)
 | 
| 31436 | 150 | if (pure_file.isFile) Some(pure_file) | 
| 151 |       else if (getenv("ML_SOURCES") != "")
 | |
| 43606 | 152 |         try_file(platform_file(Path.explode("$ML_SOURCES") + path))
 | 
| 31436 | 153 | else None | 
| 154 | } | |
| 155 | } | |
| 156 | ||
| 157 | ||
| 32450 | 158 | |
| 39583 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 159 | /** external processes **/ | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 160 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 161 | /* plain execute */ | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 162 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 163 | def execute(redirect: Boolean, args: String*): Process = | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 164 |   {
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 165 | val cmdline = | 
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 166 | if (Platform.is_windows) List(standard_system.platform_root + "\\bin\\env.exe") ++ args | 
| 39583 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 167 | else args | 
| 43661 
39fdbd814c7f
quasi-static Isabelle_System -- reduced tendency towards "functorial style";
 wenzelm parents: 
43660diff
changeset | 168 | Standard_System.raw_execute(null, settings, redirect, cmdline: _*) | 
| 39583 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 169 | } | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 170 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 171 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 172 | /* managed process */ | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 173 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 174 | class Managed_Process(redirect: Boolean, args: String*) | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 175 |   {
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 176 | private val params = | 
| 43606 | 177 |       List(standard_path(Path.explode("~~/lib/scripts/process")), "group", "-", "no_script")
 | 
| 39583 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 178 | private val proc = execute(redirect, (params ++ args):_*) | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 179 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 180 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 181 | // channels | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 182 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 183 | val stdin: BufferedWriter = | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 184 | new BufferedWriter(new OutputStreamWriter(proc.getOutputStream, Standard_System.charset)) | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 185 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 186 | val stdout: BufferedReader = | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 187 | new BufferedReader(new InputStreamReader(proc.getInputStream, Standard_System.charset)) | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 188 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 189 | val stderr: BufferedReader = | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 190 | new BufferedReader(new InputStreamReader(proc.getErrorStream, Standard_System.charset)) | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 191 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 192 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 193 | // signals | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 194 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 195 | private val pid = stdout.readLine | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 196 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 197 | private def kill(signal: String): Boolean = | 
| 39584 
f2a10986e85a
more robust Managed_Process.kill: check after sending signal;
 wenzelm parents: 
39583diff
changeset | 198 |     {
 | 
| 
f2a10986e85a
more robust Managed_Process.kill: check after sending signal;
 wenzelm parents: 
39583diff
changeset | 199 | execute(true, "kill", "-" + signal, "-" + pid).waitFor | 
| 
f2a10986e85a
more robust Managed_Process.kill: check after sending signal;
 wenzelm parents: 
39583diff
changeset | 200 | execute(true, "kill", "-0", "-" + pid).waitFor == 0 | 
| 
f2a10986e85a
more robust Managed_Process.kill: check after sending signal;
 wenzelm parents: 
39583diff
changeset | 201 | } | 
| 39583 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 202 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 203 | private def multi_kill(signal: String): Boolean = | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 204 |     {
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 205 | var running = true | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 206 | var count = 10 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 207 |       while (running && count > 0) {
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 208 |         if (kill(signal)) {
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 209 | Thread.sleep(100) | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 210 | count -= 1 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 211 | } | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 212 | else running = false | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 213 | } | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 214 | running | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 215 | } | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 216 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 217 |     def interrupt() { multi_kill("INT") }
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 218 |     def terminate() { multi_kill("INT") && multi_kill("TERM") && kill("KILL"); proc.destroy }
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 219 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 220 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 221 | // JVM shutdown hook | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 222 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 223 |     private val shutdown_hook = new Thread { override def run = terminate() }
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 224 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 225 |     try { Runtime.getRuntime.addShutdownHook(shutdown_hook) }
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 226 |     catch { case _: IllegalStateException => }
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 227 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 228 | private def cleanup() = | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 229 |       try { Runtime.getRuntime.removeShutdownHook(shutdown_hook) }
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 230 |       catch { case _: IllegalStateException => }
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 231 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 232 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 233 | /* result */ | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 234 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 235 |     def join: Int = { val rc = proc.waitFor; cleanup(); rc }
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 236 | } | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 237 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 238 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 239 | /* bash */ | 
| 31796 | 240 | |
| 39581 
430ff865089b
refined Isabelle_System.bash_output: pass pid via stdout, separate stdout/stderr;
 wenzelm parents: 
39576diff
changeset | 241 | def bash(script: String): (String, String, Int) = | 
| 34198 
ff5486262cd6
moved Library.decode_permissive_utf8 to Isabelle_System;
 wenzelm parents: 
34196diff
changeset | 242 |   {
 | 
| 34201 
c95dcd12f48a
separate Standard_System (Cygwin/Posix compatibility) vs. Isabelle_System (settings environment etc.);
 wenzelm parents: 
34200diff
changeset | 243 |     Standard_System.with_tmp_file("isabelle_script") { script_file =>
 | 
| 39581 
430ff865089b
refined Isabelle_System.bash_output: pass pid via stdout, separate stdout/stderr;
 wenzelm parents: 
39576diff
changeset | 244 | Standard_System.write_file(script_file, script) | 
| 39583 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 245 | val proc = new Managed_Process(false, "bash", posix_path(script_file.getPath)) | 
| 39581 
430ff865089b
refined Isabelle_System.bash_output: pass pid via stdout, separate stdout/stderr;
 wenzelm parents: 
39576diff
changeset | 246 | |
| 39583 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 247 | proc.stdin.close | 
| 39586 
ea8f3ea13a95
eliminated Simple_Thread shorthands that can overlap with full version;
 wenzelm parents: 
39584diff
changeset | 248 |       val stdout = Simple_Thread.future("bash_stdout") { Standard_System.slurp(proc.stdout) }
 | 
| 
ea8f3ea13a95
eliminated Simple_Thread shorthands that can overlap with full version;
 wenzelm parents: 
39584diff
changeset | 249 |       val stderr = Simple_Thread.future("bash_stderr") { Standard_System.slurp(proc.stderr) }
 | 
| 34198 
ff5486262cd6
moved Library.decode_permissive_utf8 to Isabelle_System;
 wenzelm parents: 
34196diff
changeset | 250 | |
| 39581 
430ff865089b
refined Isabelle_System.bash_output: pass pid via stdout, separate stdout/stderr;
 wenzelm parents: 
39576diff
changeset | 251 | val rc = | 
| 39583 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 252 |         try { proc.join }
 | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 253 |         catch { case e: InterruptedException => Thread.interrupted; proc.terminate; 130 }
 | 
| 39581 
430ff865089b
refined Isabelle_System.bash_output: pass pid via stdout, separate stdout/stderr;
 wenzelm parents: 
39576diff
changeset | 254 | (stdout.join, stderr.join, rc) | 
| 34198 
ff5486262cd6
moved Library.decode_permissive_utf8 to Isabelle_System;
 wenzelm parents: 
34196diff
changeset | 255 | } | 
| 
ff5486262cd6
moved Library.decode_permissive_utf8 to Isabelle_System;
 wenzelm parents: 
34196diff
changeset | 256 | } | 
| 
ff5486262cd6
moved Library.decode_permissive_utf8 to Isabelle_System;
 wenzelm parents: 
34196diff
changeset | 257 | |
| 39583 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 258 | |
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 259 | /* system tools */ | 
| 
c1e9c6dfeff8
more robust lib/scripts/process, with explicit script/no_script mode;
 wenzelm parents: 
39581diff
changeset | 260 | |
| 31818 
f698f76a3713
builtin isabelle_tool for ML and Scala -- avoids excessive shell script (especially important for Cygwin);
 wenzelm parents: 
31803diff
changeset | 261 | def isabelle_tool(name: String, args: String*): (String, Int) = | 
| 31498 | 262 |   {
 | 
| 43669 | 263 |     Path.split(getenv_strict("ISABELLE_TOOLS")).find { dir =>
 | 
| 264 | val file = platform_file(dir + Path.basic(name)) | |
| 42124 | 265 |       try {
 | 
| 266 | file.isFile && file.canRead && file.canExecute && | |
| 267 |           !name.endsWith("~") && !name.endsWith(".orig")
 | |
| 268 | } | |
| 31818 
f698f76a3713
builtin isabelle_tool for ML and Scala -- avoids excessive shell script (especially important for Cygwin);
 wenzelm parents: 
31803diff
changeset | 269 |       catch { case _: SecurityException => false }
 | 
| 34200 | 270 |     } match {
 | 
| 31818 
f698f76a3713
builtin isabelle_tool for ML and Scala -- avoids excessive shell script (especially important for Cygwin);
 wenzelm parents: 
31803diff
changeset | 271 | case Some(dir) => | 
| 43669 | 272 | val file = standard_path(dir + Path.basic(name)) | 
| 43606 | 273 | Standard_System.process_output(execute(true, (List(file) ++ args): _*)) | 
| 31818 
f698f76a3713
builtin isabelle_tool for ML and Scala -- avoids excessive shell script (especially important for Cygwin);
 wenzelm parents: 
31803diff
changeset | 274 |       case None => ("Unknown Isabelle tool: " + name, 2)
 | 
| 
f698f76a3713
builtin isabelle_tool for ML and Scala -- avoids excessive shell script (especially important for Cygwin);
 wenzelm parents: 
31803diff
changeset | 275 | } | 
| 28063 | 276 | } | 
| 277 | ||
| 278 | ||
| 32450 | 279 | |
| 31796 | 280 | /** Isabelle resources **/ | 
| 281 | ||
| 32328 | 282 | /* components */ | 
| 283 | ||
| 43669 | 284 | def components(): List[Path] = | 
| 285 |     Path.split(getenv_strict("ISABELLE_COMPONENTS"))
 | |
| 32328 | 286 | |
| 287 | ||
| 29152 | 288 | /* find logics */ | 
| 289 | ||
| 31498 | 290 | def find_logics(): List[String] = | 
| 291 |   {
 | |
| 29152 | 292 |     val ml_ident = getenv_strict("ML_IDENTIFIER")
 | 
| 34163 | 293 | val logics = new mutable.ListBuffer[String] | 
| 43669 | 294 |     for (dir <- Path.split(getenv_strict("ISABELLE_PATH"))) {
 | 
| 295 | val files = platform_file(dir + Path.explode(ml_ident)).listFiles() | |
| 29152 | 296 |       if (files != null) {
 | 
| 297 | for (file <- files if file.isFile) logics += file.getName | |
| 298 | } | |
| 299 | } | |
| 45900 | 300 | logics.toList.sorted | 
| 29152 | 301 | } | 
| 29570 | 302 | |
| 303 | ||
| 34024 | 304 | /* fonts */ | 
| 305 | ||
| 43484 | 306 | def get_font(family: String = "IsabelleText", size: Int = 1, bold: Boolean = false): Font = | 
| 307 | new Font(family, if (bold) Font.BOLD else Font.PLAIN, size) | |
| 37367 | 308 | |
| 34044 
09afb1d49fe7
slightly more robust and less ambitious version of install_fonts;
 wenzelm parents: 
34027diff
changeset | 309 | def install_fonts() | 
| 
09afb1d49fe7
slightly more robust and less ambitious version of install_fonts;
 wenzelm parents: 
34027diff
changeset | 310 |   {
 | 
| 37367 | 311 | val ge = GraphicsEnvironment.getLocalGraphicsEnvironment() | 
| 43669 | 312 |     for (font <- Path.split(getenv_strict("ISABELLE_FONTS")))
 | 
| 313 | ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, platform_file(font))) | |
| 34024 | 314 | } | 
| 27919 | 315 | } |