src/Pure/System/isabelle_process.ML
changeset 45028 d608dd8cd409
parent 44988 33aa6da101d8
child 45029 63144ea111f7
--- a/src/Pure/System/isabelle_process.ML	Wed Sep 21 20:35:50 2011 +0200
+++ b/src/Pure/System/isabelle_process.ML	Wed Sep 21 22:18:17 2011 +0200
@@ -21,7 +21,8 @@
   val add_command: string -> (string list -> unit) -> unit
   val command: string -> string list -> unit
   val crashes: exn list Synchronized.var
-  val init: string -> string -> unit
+  val init_socket: string -> unit
+  val init_fifos: string -> string -> unit
 end;
 
 structure Isabelle_Process: ISABELLE_PROCESS =
@@ -81,11 +82,11 @@
 
 fun message_output mbox out_stream =
   let
-    fun flush () = ignore (try TextIO.flushOut out_stream);
+    fun flush () = ignore (try BinIO.flushOut out_stream);
     fun loop receive =
       (case receive mbox of
         SOME (msg, do_flush) =>
-         (List.app (fn s => TextIO.output (out_stream, s)) msg;
+         (List.app (fn s => BinIO.output (out_stream, Byte.stringToBytes s)) msg;
           if do_flush then flush () else ();
           loop (Mailbox.receive_timeout (seconds 0.02)))
       | NONE => (flush (); loop (SOME o Mailbox.receive)));
@@ -93,12 +94,8 @@
 
 in
 
-fun setup_channels in_fifo out_fifo =
+fun setup_channels out_stream =
   let
-    (*rendezvous*)
-    val in_stream = TextIO.openIn in_fifo;
-    val out_stream = TextIO.openOut out_fifo;
-
     val _ = TextIO.StreamIO.setBufferMode (TextIO.getOutstream TextIO.stdOut, IO.LINE_BUF);
     val _ = TextIO.StreamIO.setBufferMode (TextIO.getOutstream TextIO.stdErr, IO.LINE_BUF);
 
@@ -114,8 +111,7 @@
     Output.Private_Hooks.raw_message_fn := message true mbox "H";
     Output.Private_Hooks.urgent_message_fn := ! Output.Private_Hooks.writeln_fn;
     Output.Private_Hooks.prompt_fn := ignore;
-    message true mbox "A" [] (Session.welcome ());
-    in_stream
+    message true mbox "A" [] (Session.welcome ())
   end;
 
 end;
@@ -131,13 +127,25 @@
   (Synchronized.change crashes (cons crash);
     warning "Recovering from Isabelle process crash -- see also Isabelle_Process.crashes");
 
+fun read_line stream =
+  let
+    val content = String.implode o rev;
+    fun read cs =
+      (case BinIO.input1 stream of
+        NONE => (content cs, null cs)
+      | SOME b =>
+          (case Byte.byteToChar b of
+            #"\n" => (content cs, false)
+          | c => read (c :: cs)));
+  in case read [] of ("", true) => NONE | (s, _) => SOME s end;
+
 fun read_chunk stream len =
   let
     val n =
       (case Int.fromString len of
         SOME n => n
       | NONE => error ("Isabelle process: malformed chunk header " ^ quote len));
-    val chunk = TextIO.inputN (stream, n);
+    val chunk = Byte.bytesToString (BinIO.inputN (stream, n));
     val m = size chunk;
   in
     if m = n then chunk
@@ -145,7 +153,7 @@
   end;
 
 fun read_command stream =
-  (case TextIO.inputLine stream of
+  (case read_line stream of
     NONE => raise Runtime.TERMINATE
   | SOME line => map (read_chunk stream) (space_explode "," line));
 
@@ -170,7 +178,7 @@
 
 (* init *)
 
-fun init in_fifo out_fifo = ignore (Simple_Thread.fork false (fn () =>
+fun init make_streams = ignore (Simple_Thread.fork false (fn () =>
   let
     val _ = OS.Process.sleep (seconds 0.5);  (*yield to raw ML toplevel*)
     val _ = Output.physical_stdout Symbol.STX;
@@ -186,11 +194,18 @@
         (fold (update op =)
           [Symbol.xsymbolsN, isabelle_processN, Keyword.keyword_statusN, Pretty.symbolicN]);
 
-    val in_stream = setup_channels in_fifo out_fifo;
+    val (in_stream, out_stream) = make_streams ();
+    val _ = setup_channels out_stream;
+
     val _ = Keyword.status ();
     val _ = Thy_Info.status ();
     val _ = Output.status (Markup.markup Markup.ready "process ready");
   in loop in_stream end));
 
+fun rendezvous fifo1 fifo2 = (BinIO.openIn fifo1, BinIO.openOut fifo2);
+fun init_fifos fifo1 fifo2 = init (fn () => rendezvous fifo1 fifo2);
+
+fun init_socket socket_name = init (fn () => Socket_IO.open_streams socket_name);
+
 end;