author | wenzelm |
Sat, 05 Jan 2008 21:37:24 +0100 | |
changeset 25841 | af7566faaa0f |
parent 25820 | 8228b198c49e |
child 25842 | fdabeed7ccd9 |
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 |
|
10 |
processed immediately as it arrives) |
|
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 |
18 |
supposed to be processed in one piece). |
|
25841 | 19 |
|
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 |
25554 | 25 |
val test_markupN: string |
26 |
val test_markup: Markup.T -> output * output |
|
25748 | 27 |
val isabelle_processN: 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 |
|
25748 | 34 |
(* test_markup *) |
25554 | 35 |
|
36 |
val test_markupN = "test_markup"; |
|
37 |
||
38 |
fun test_markup (name, props) = |
|
39 |
(enclose "<" ">" (space_implode " " (name :: map XML.attribute props)), |
|
40 |
enclose "</" ">" name); |
|
41 |
||
42 |
val _ = Markup.add_mode test_markupN test_markup; |
|
43 |
||
44 |
||
25841 | 45 |
(* symbol output *) |
25554 | 46 |
|
25748 | 47 |
val isabelle_processN = "isabelle_process"; |
48 |
||
25554 | 49 |
local |
50 |
||
25841 | 51 |
fun output str = |
52 |
let |
|
53 |
fun out s = if Symbol.is_raw s then Symbol.decode_raw s else XML.text s; |
|
54 |
val syms = Symbol.explode str; |
|
55 |
in (implode (map out syms), Symbol.length syms) end; |
|
56 |
||
57 |
in |
|
58 |
||
59 |
val _ = Output.add_mode isabelle_processN output Symbol.encode_raw; |
|
60 |
||
61 |
end; |
|
62 |
||
63 |
||
64 |
(* message markup *) |
|
65 |
||
66 |
val STX = chr 2; |
|
67 |
val DEL = chr 127; |
|
68 |
||
69 |
fun special ch = STX ^ ch; |
|
25810 | 70 |
val special_sep = special ","; |
25576 | 71 |
val special_end = special "."; |
25554 | 72 |
|
25841 | 73 |
local |
25810 | 74 |
|
25841 | 75 |
fun print_props props = |
76 |
let |
|
77 |
val clean = translate_string (fn c => |
|
78 |
if c = STX orelse c = "\n" orelse c = "\r" then DEL else c); |
|
79 |
in implode (map (fn (x, y) => clean x ^ "=" ^ clean y ^ special_sep ^ "\n") props) end; |
|
80 |
||
81 |
fun get_pos (elem as XML.Elem (name, atts, ts)) = |
|
82 |
if name = Markup.positionN then SOME (Position.of_properties atts) |
|
83 |
else get_first get_pos ts |
|
84 |
| get_pos _ = NONE; |
|
25554 | 85 |
|
86 |
in |
|
87 |
||
25841 | 88 |
fun message ch markup raw_txt = |
89 |
let |
|
90 |
val (txt, pos) = |
|
91 |
(case try XML.tree_of_string (XML.element "message" [] [raw_txt]) of |
|
92 |
NONE => (raw_txt, Position.none) |
|
93 |
| SOME xml => (XML.plain_content xml, the_default Position.none (get_pos xml))) |
|
94 |
|>> translate_string (fn c => if c = STX then DEL else c); |
|
95 |
val props = |
|
96 |
(case Position.properties_of (Position.thread_data ()) of |
|
97 |
[] => Position.properties_of pos |
|
98 |
| props => props); |
|
99 |
val s = special ch ^ print_props props ^ Markup.enclose markup txt ^ special_end; |
|
100 |
in Output.writeln_default s end; |
|
25554 | 101 |
|
25841 | 102 |
fun init_message () = |
103 |
let |
|
104 |
val pid = string_of_pid (Posix.ProcEnv.getpid ()); |
|
105 |
val session = List.last (Session.id ()) handle List.Empty => "unknown"; |
|
106 |
val welcome = Session.welcome (); |
|
107 |
val s = special "H" ^ print_props [("pid", pid), ("session", session)] ^ welcome ^ special_end; |
|
108 |
in Output.writeln_default s end; |
|
25748 | 109 |
|
25554 | 110 |
end; |
111 |
||
112 |
||
25841 | 113 |
(* channels *) |
114 |
||
115 |
fun setup_channels () = |
|
116 |
(Output.writeln_fn := message "A" Markup.writeln; |
|
117 |
Output.priority_fn := message "B" Markup.priority; |
|
118 |
Output.tracing_fn := message "C" Markup.tracing; |
|
119 |
Output.warning_fn := message "D" Markup.warning; |
|
120 |
Output.error_fn := message "E" Markup.error; |
|
121 |
Output.debug_fn := message "F" Markup.debug); |
|
122 |
||
123 |
val _ = Markup.add_mode isabelle_processN (fn (name, props) => |
|
124 |
if name = Markup.promptN then (special "G", special_end ^ "\n") |
|
125 |
else if name = Markup.positionN then test_markup (name, props) |
|
126 |
else ("", "")); |
|
127 |
||
128 |
||
25554 | 129 |
(* init *) |
130 |
||
25528
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
131 |
fun init () = |
25841 | 132 |
(change print_mode (update (op =) isabelle_processN); |
25554 | 133 |
setup_channels (); |
25841 | 134 |
init_message (); |
25528
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
135 |
Isar.secure_main ()); |
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
136 |
|
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
137 |
end; |
e67230c2b952
Isabelle process wrapper -- interaction via external program.
wenzelm
parents:
diff
changeset
|
138 |