1 type environment =
2 | Normal
3 | Caml
4 | Verbatim of string * string
5 | Verbatim_like
6
7 let in_quotes = ref false
8
9 let is_alpha c =
10 ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')
11
12 let is_prefix prefix str =
13 let length_prefix = String.length prefix in
14 let length_str = String.length str in
15 if length_prefix > length_str
16 then false
17 else (String.sub str 0 length_prefix) = prefix
18
19 let escape = function
20 | ' ' | '\n' -> "\\ "
21 | '{' -> "{\\char123}"
22 | '}' -> "{\\char125}"
23 | '^' -> "{\\char94}"
24 | '_' -> "{\\char95}"
25 | '\\' -> "{\\char92}"
26 | '~' -> "{\\char126}"
27 | '$' -> "\\$"
28 | '&' -> "{\\char38}"
29 | '#' -> "\\#"
30 | '%' -> "\\%"
31 | '\'' -> "{\\textquotesingle}"
32 | '`' -> "{\\textasciigrave}"
33 | _ -> ""
34
35 let process_normal_line line =
36 let (verb_mark : char option ref) = ref None in
37 let l = String.length line in
38 let i = ref 0 in
39 while !i<l do
40 match !verb_mark with
41 | None ->
42 (match line.[!i] with
43 | '"' ->
44 let r = if !in_quotes then "}}" else "{\\machine{" in
45 print_string r;
46 in_quotes := not !in_quotes;
47 incr i;
48 | '\\' ->
49 if !in_quotes
50 then begin
51 if (!i < l-1) && (line.[!i+1] = '"' || line.[!i+1] = '\\')
52 then incr i;
53 let t = escape line.[!i] in
54 if t<>"" then print_string t else print_char line.[!i];
55 incr i;
56 end else if is_prefix "\\verb" (String.sub line !i (l - !i))
57 && not (is_alpha line.[!i+5])
58 then begin
59 i := !i+5;
60 verb_mark := Some line.[!i];
61 print_string "\\verb";
62 print_char line.[!i];
63 incr i;
64 end else (print_char '\\'; incr i)
65 | _ ->
66 if !in_quotes && (escape line.[!i] <> "")
67 then print_string (escape line.[!i])
68 else print_char line.[!i];
69 incr i;
70 )
71 | Some mark ->
72 if line.[!i] = mark
73 then verb_mark := None
74 else if line.[!i] = '\'' || line.[!i] = '`'
75 then Printf.eprintf "Warning: %c found in \\verb\n" line.[!i];
76 print_char line.[!i];
77 incr i;
78 done
79
80 let process_line line = function
81 | Normal ->
82 if is_prefix "\\begin{caml_" line || is_prefix "\\begin{rawhtml}" line
83 then (print_string line; Verbatim_like)
84 else if is_prefix "\\begin{camlexample}" line
85 then (print_endline line; Caml)
86 else if is_prefix "\\begin{verbatim}" line
87 then begin
88 print_string "\\begin{machineenv}";
89 (Verbatim ("\\end{verbatim}", "\\end{machineenv}"))
90 end else if is_prefix "\\begin{ocamldoccode}" line
91 then begin
92 print_string "\\begin{ocamldoccode}";
93 (Verbatim ("\\end{ocamldoccode}", "\\end{ocamldoccode}"))
94 end else begin
95 process_normal_line line;
96 if !in_quotes
97 then print_string (escape '\n')
98 else print_newline();
99 Normal
100 end
101 | Caml ->
102 print_endline line;
103 if is_prefix "\\end{camlexample}" line then Normal else Caml
104 | Verbatim (verbatim_end_in, verbatim_end_out) as env ->
105 if is_prefix verbatim_end_in line
106 then begin
107 print_string verbatim_end_out;
108 Normal
109 end else begin
110 for i=0 to (String.length line) - 1 do
111 let c = line.[i] in
112 let t = escape c in
113 if c=' ' || c='\n' || t=""
114 then print_char c
115 else print_string t
116 done;
117 print_newline();
118 env
119 end
120 | Verbatim_like ->
121 print_endline line;
122 if is_prefix "\\end{caml_" line || is_prefix "\\end{rawhtml}" line
123 then Normal
124 else Verbatim_like
125
126 let rec process_input env = match input_line stdin with
127 | exception End_of_file -> ()
128 | line ->
129 let env = process_line line env in
130 process_input env
131
132 let main() =
133 print_endline "% THIS FILE IS GENERATED.";
134 print_newline();
135 process_input Normal
136
137 let _ = main()
138