| author | wenzelm | 
| Thu, 07 Aug 2008 13:44:42 +0200 | |
| changeset 27764 | e0ee3cc240fe | 
| parent 27604 | 6c347b96d941 | 
| child 27844 | 86f0f91471d0 | 
| permissions | -rw-r--r-- | 
| 25528 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 1 | (* Title: Pure/Tools/isabelle_process.ML | 
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 2 | ID: $Id$ | 
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 3 | Author: Makarius | 
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 4 | |
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 5 | Isabelle process wrapper -- interaction via external program. | 
| 25631 | 6 | |
| 7 | General format of process output: | |
| 8 | ||
| 9 | (a) unmarked stdout/stderr, no line structure (output should be | |
| 25842 | 10 | processed immediately as it arrives); | 
| 25631 | 11 | |
| 25841 | 12 | (b) properly marked-up messages, e.g. for writeln channel | 
| 25810 | 13 | |
| 14 | "\002A" ^ props ^ "\002,\n" ^ text ^ "\002.\n" | |
| 15 | ||
| 25841 | 16 | where the props consist of name=value lines terminated by "\002,\n" | 
| 25810 | 17 | each, and the remaining text is any number of lines (output is | 
| 25842 | 18 | supposed to be processed in one piece); | 
| 25841 | 19 | |
| 25842 | 20 | (c) special init message holds "pid" and "session" property. | 
| 25528 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 21 | *) | 
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 22 | |
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 23 | signature ISABELLE_PROCESS = | 
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 24 | sig | 
| 26574 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 25 | val isabelle_processN: string | 
| 26208 | 26 | val full_markupN: string | 
| 26574 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 27 | val yxmlN: string | 
| 25528 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 28 | val init: unit -> unit | 
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 29 | end; | 
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 30 | |
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 31 | structure IsabelleProcess: ISABELLE_PROCESS = | 
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 32 | struct | 
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 33 | |
| 26550 | 34 | (* print modes *) | 
| 25554 | 35 | |
| 25748 | 36 | val isabelle_processN = "isabelle_process"; | 
| 26550 | 37 | val full_markupN = "full_markup"; | 
| 26574 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 38 | val yxmlN = "YXML"; | 
| 25748 | 39 | |
| 26550 | 40 | val _ = Output.add_mode isabelle_processN Output.default_output Output.default_escape; | 
| 25554 | 41 | |
| 26550 | 42 | val _ = Markup.add_mode isabelle_processN (fn (name, props) => | 
| 43 | if print_mode_active full_markupN orelse name = Markup.positionN | |
| 44 |   then YXML.output_markup (name, props) else ("", ""));
 | |
| 25841 | 45 | |
| 46 | ||
| 47 | (* message markup *) | |
| 48 | ||
| 26527 | 49 | fun special ch = Symbol.STX ^ ch; | 
| 25810 | 50 | val special_sep = special ","; | 
| 25576 | 51 | val special_end = special "."; | 
| 25554 | 52 | |
| 25841 | 53 | local | 
| 25810 | 54 | |
| 26574 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 55 | fun clean_string bad str = | 
| 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 56 | if exists_string (member (op =) bad) str then | 
| 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 57 | translate_string (fn c => if member (op =) bad c then Symbol.DEL else c) str | 
| 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 58 | else str; | 
| 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 59 | |
| 26550 | 60 | fun message_props props = | 
| 26574 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 61 | let val clean = clean_string [Symbol.STX, "\n", "\r"] | 
| 25841 | 62 | in implode (map (fn (x, y) => clean x ^ "=" ^ clean y ^ special_sep ^ "\n") props) end; | 
| 63 | ||
| 26550 | 64 | fun message_text ts = | 
| 26574 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 65 | let | 
| 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 66 |     val doc = XML.Elem ("message", [], ts);
 | 
| 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 67 | val msg = | 
| 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 68 | if not (print_mode_active full_markupN) then | 
| 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 69 | Buffer.content (fold XML.add_content ts Buffer.empty) | 
| 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 70 | else if print_mode_active yxmlN then YXML.string_of doc | 
| 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 71 | else XML.header ^ XML.string_of doc; | 
| 
560d07845442
support "YXML" mode for output transfer notation;
 wenzelm parents: 
26550diff
changeset | 72 | in clean_string [Symbol.STX] msg end; | 
| 26550 | 73 | |
| 74 | fun message_pos ts = get_first get_pos ts | |
| 75 | and get_pos (elem as XML.Elem (name, atts, ts)) = | |
| 25841 | 76 | if name = Markup.positionN then SOME (Position.of_properties atts) | 
| 26550 | 77 | else message_pos ts | 
| 27434 | 78 | | get_pos _ = NONE; | 
| 25554 | 79 | |
| 80 | in | |
| 81 | ||
| 26550 | 82 | fun message ch body = | 
| 25841 | 83 | let | 
| 84 | val (txt, pos) = | |
| 26550 | 85 | let val ts = YXML.parse_body body | 
| 86 | in (message_text ts, the_default Position.none (message_pos ts)) end | |
| 87 |       handle Fail msg => ("*** MALFORMED MESSAGE ***\n" ^ msg, Position.none);
 | |
| 25841 | 88 | val props = | 
| 26053 | 89 | Position.properties_of (Position.thread_data ()) | 
| 90 | |> Position.default_properties pos; | |
| 26550 | 91 | in Output.writeln_default (special ch ^ message_props props ^ txt ^ special_end) end; | 
| 25554 | 92 | |
| 25841 | 93 | fun init_message () = | 
| 94 | let | |
| 25849 | 95 |     val pid = ("pid", string_of_pid (Posix.ProcEnv.getpid ()));
 | 
| 96 |     val session = ("session", List.last (Session.id ()) handle List.Empty => "unknown");
 | |
| 25841 | 97 | val welcome = Session.welcome (); | 
| 26550 | 98 | in Output.writeln_default (special "H" ^ message_props [pid, session] ^ welcome ^ special_end) end; | 
| 25748 | 99 | |
| 25554 | 100 | end; | 
| 101 | ||
| 102 | ||
| 25841 | 103 | (* channels *) | 
| 104 | ||
| 105 | fun setup_channels () = | |
| 25849 | 106 | (Output.writeln_fn := message "A"; | 
| 107 | Output.priority_fn := message "B"; | |
| 108 | Output.tracing_fn := message "C"; | |
| 109 | Output.warning_fn := message "D"; | |
| 110 | Output.error_fn := message "E"; | |
| 111 | Output.debug_fn := message "F"; | |
| 27604 | 112 | Output.prompt_fn := message "G"; | 
| 113 | Output.status_fn := message "I"); | |
| 25841 | 114 | |
| 115 | ||
| 25554 | 116 | (* init *) | 
| 117 | ||
| 25528 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 118 | fun init () = | 
| 25841 | 119 | (change print_mode (update (op =) isabelle_processN); | 
| 25554 | 120 | setup_channels (); | 
| 25841 | 121 | init_message (); | 
| 26643 | 122 |   Isar.toplevel_loop {init = true, welcome = false, sync = true, secure = true});
 | 
| 25528 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 123 | |
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 124 | end; | 
| 
e67230c2b952
Isabelle process wrapper -- interaction via external program.
 wenzelm parents: diff
changeset | 125 |