138 lines | 3826 chars
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 |