~ubuntu-branches/ubuntu/wily/coq-doc/wily

« back to all changes in this revision

Viewing changes to tools/coq-tex.ml4

  • Committer: Bazaar Package Importer
  • Author(s): Stéphane Glondu, Stéphane Glondu, Samuel Mimram
  • Date: 2010-01-07 22:50:39 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100107225039-n3cq82589u0qt0s2
Tags: 8.2pl1-1
[ Stéphane Glondu ]
* New upstream release (Closes: #563669)
  - remove patches
* Packaging overhaul:
  - use git, advertise it in Vcs-* fields of debian/control
  - use debhelper 7 and dh with override
  - use source format 3.0 (quilt)
* debian/control:
  - set Maintainer to d-o-m, set Uploaders to Sam and myself
  - add Homepage field
  - bump Standards-Version to 3.8.3
* Register PDF documentation into doc-base
* Add debian/watch
* Update debian/copyright

[ Samuel Mimram ]
* Change coq-doc's description to mention that it provides documentation in
  pdf format, not postscript, closes: #543545.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(************************************************************************)
 
2
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
 
3
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
 
4
(*   \VV/  **************************************************************)
 
5
(*    //   *      This file is distributed under the terms of the       *)
 
6
(*         *       GNU Lesser General Public License Version 2.1        *)
 
7
(************************************************************************)
 
8
 
 
9
(* $Id: coq-tex.ml4 9532 2007-01-24 16:04:29Z bgregoir $ *)
 
10
 
 
11
(* coq-tex
 
12
 * JCF, 16/1/98
 
13
 * adapted from caml-tex (perl script written by Xavier Leroy)
 
14
 *
 
15
 * Perl isn't as portable as it pretends to be, and is quite difficult 
 
16
 * to read and maintain... Let us rewrite the stuff in Caml! *)
 
17
 
 
18
let _ =
 
19
  match Sys.os_type with
 
20
    | "Unix" -> ()
 
21
    | _ -> begin
 
22
        print_string "This program only runs under Unix !\n";
 
23
        flush stdout;
 
24
        exit 1
 
25
      end
 
26
 
 
27
let linelen = ref 72
 
28
let output = ref ""
 
29
let output_specified = ref false
 
30
let image = ref ""
 
31
let cut_at_blanks = ref false
 
32
let verbose = ref false
 
33
let slanted = ref false
 
34
let hrule = ref false
 
35
let small = ref false
 
36
 
 
37
let coq_prompt = Str.regexp "Coq < "
 
38
let any_prompt = Str.regexp "^[A-Z0-9a-z_\\$']* < "
 
39
 
 
40
let remove_prompt s = Str.replace_first any_prompt "" s
 
41
 
 
42
(* First pass: extract the Coq phrases to evaluate from [texfile]
 
43
 * and put them into the file [inputv] *)
 
44
 
 
45
let begin_coq = Str.regexp "\\\\begin{coq_\\(example\\|example\\*\\|example\\#\\|eval\\)}[ \t]*$"
 
46
let end_coq   = Str.regexp "\\\\end{coq_\\(example\\|example\\*\\|example\\#\\|eval\\)}[ \t]*$"
 
47
 
 
48
let extract texfile inputv =
 
49
  let chan_in = open_in texfile in
 
50
  let chan_out = open_out inputv in
 
51
  let rec inside () =
 
52
    let s = input_line chan_in in
 
53
    if Str.string_match end_coq s 0 then
 
54
      outside ()
 
55
    else begin
 
56
      output_string chan_out (s ^ "\n");
 
57
      inside ()
 
58
    end
 
59
  and outside () =
 
60
    let s = input_line chan_in in
 
61
    if Str.string_match begin_coq s 0 then
 
62
      inside ()
 
63
    else
 
64
      outside ()
 
65
  in
 
66
  try
 
67
    output_string chan_out 
 
68
      ("Set Printing Width " ^ (string_of_int !linelen) ^".\n");
 
69
    outside ()
 
70
  with End_of_file -> 
 
71
    begin close_in chan_in; close_out chan_out end
 
72
 
 
73
(* Second pass: insert the answers of Coq from [coq_output] into the
 
74
 * TeX file [texfile]. The result goes in file [result]. *)
 
75
 
 
76
let begin_coq_example =
 
77
  Str.regexp "\\\\begin{coq_\\(example\\|example\\*\\|example\\#\\)}[ \t]*$"
 
78
let begin_coq_eval = Str.regexp "\\\\begin{coq_eval}[ \t]*$"
 
79
let end_coq_example = Str.regexp "\\\\end{coq_\\(example\\|example\\*\\|example\\#\\)}[ \t]*$"
 
80
let end_coq_eval = Str.regexp "\\\\end{coq_eval}[ \t]*$"
 
81
let dot_end_line = Str.regexp "\\.[ \t]*\\((\\*.*\\*)\\)?[ \t]*$"
 
82
 
 
83
let has_match r s =
 
84
  try let _ = Str.search_forward r s 0 in true with Not_found -> false
 
85
 
 
86
let percent = Str.regexp "%"
 
87
let bang    = Str.regexp "!"
 
88
let expos   = Str.regexp "^"
 
89
 
 
90
let tex_escaped s =
 
91
  let rec trans = parser
 
92
    | [< s1 = (parser 
 
93
                 | [< ''_'|'$'|'{'|'}'|'&'|'%'|'#' as c >] -> 
 
94
                     "\\" ^ (String.make 1 c)
 
95
                 | [< ''\\' >] -> "{\\char'134}" 
 
96
                 | [< ''^'  >] -> "{\\char'136}" 
 
97
                 | [< ''~'  >] -> "{\\char'176}"
 
98
                 | [< '' '  >] -> "~"
 
99
                 | [< ''<'  >] -> "{<}"
 
100
                 | [< ''>'  >] -> "{>}"
 
101
                 | [< 'c >]    -> String.make 1 c);
 
102
         s2 = trans >] -> s1 ^ s2
 
103
    | [< >] -> ""
 
104
  in 
 
105
  trans (Stream.of_string s)
 
106
 
 
107
let encapsule sl c_out s =
 
108
  if sl then
 
109
    Printf.fprintf c_out "\\texttt{\\textit{%s}}\\\\\n" (tex_escaped s)
 
110
  else
 
111
    Printf.fprintf c_out "\\texttt{%s}\\\\\n" (tex_escaped s)
 
112
      
 
113
let print_block c_out bl =
 
114
  List.iter (fun s -> if s="" then () else encapsule !slanted c_out s) bl
 
115
 
 
116
let insert texfile coq_output result =
 
117
  let c_tex = open_in texfile in
 
118
  let c_coq = open_in coq_output in
 
119
  let c_out = open_out result in
 
120
  (* next_block k : this function reads the next block of Coq output
 
121
   * removing the k leading prompts.
 
122
   * it returns the block as a list of string) *)
 
123
  let last_read = ref "" in
 
124
  let next_block k =
 
125
    if !last_read = "" then last_read := input_line c_coq;
 
126
    (* skip k prompts *)
 
127
    for i = 1 to k do
 
128
      last_read := remove_prompt !last_read;
 
129
    done;
 
130
    (* read and return the following lines until a prompt is found *)
 
131
    let rec read_lines () =
 
132
      let s = input_line c_coq in
 
133
      if Str.string_match any_prompt s 0 then begin
 
134
        last_read := s; []
 
135
      end else
 
136
        s :: (read_lines ())
 
137
    in
 
138
    let first = !last_read in first :: (read_lines ())
 
139
  in
 
140
  (* we are just after \end{coq_...} block *)
 
141
  let rec just_after () = 
 
142
    let s = input_line c_tex in
 
143
    if Str.string_match begin_coq_example s 0 then begin
 
144
      inside (Str.matched_group 1 s <> "example*")
 
145
             (Str.matched_group 1 s <> "example#") 0 false
 
146
    end
 
147
    else begin
 
148
      if !hrule then output_string c_out "\\hrulefill\\\\\n";
 
149
      output_string c_out "\\end{flushleft}\n";
 
150
      if !small then output_string c_out "\\end{small}\n";
 
151
      if Str.string_match begin_coq_eval s 0 then
 
152
        eval 0     
 
153
      else begin
 
154
        output_string c_out (s ^ "\n");
 
155
        outside ()
 
156
      end         
 
157
    end
 
158
  (* we are outside of a \begin{coq_...} ... \end{coq_...} block *)
 
159
  and outside () =
 
160
    let s = input_line c_tex in
 
161
    if Str.string_match begin_coq_example s 0 then begin
 
162
      if !small then output_string c_out "\\begin{small}\n";
 
163
      output_string c_out "\\begin{flushleft}\n";
 
164
      if !hrule then output_string c_out "\\hrulefill\\\\\n";
 
165
      inside (Str.matched_group 1 s <> "example*")
 
166
             (Str.matched_group 1 s <> "example#") 0 true
 
167
    end else if Str.string_match begin_coq_eval s 0 then
 
168
      eval 0
 
169
    else begin
 
170
      output_string c_out (s ^ "\n");
 
171
      outside ()
 
172
    end
 
173
  (* we are inside a \begin{coq_example?} ... \end{coq_example?} block
 
174
   * show_answers tells what kind of block it is
 
175
   * k is the number of lines read until now *)
 
176
  and inside show_answers  show_questions k first_block = 
 
177
    let s = input_line c_tex in
 
178
    if Str.string_match end_coq_example s 0 then begin
 
179
      just_after ()
 
180
    end else begin
 
181
      if !verbose then Printf.printf "Coq < %s\n" s;
 
182
      if (not first_block) & k=0 then output_string c_out "\\medskip\n";
 
183
      if show_questions then encapsule false c_out ("Coq < " ^ s);
 
184
      if has_match dot_end_line s then begin
 
185
        let bl = next_block (succ k) in
 
186
        if !verbose then List.iter print_endline bl; 
 
187
        if show_answers then print_block c_out bl;
 
188
        inside show_answers  show_questions 0 false
 
189
      end else
 
190
        inside show_answers  show_questions (succ k) first_block
 
191
    end
 
192
  (* we are inside a \begin{coq_eval} ... \end{coq_eval} block
 
193
   * k is the number of lines read until now *)
 
194
  and eval k =
 
195
    let s = input_line c_tex in
 
196
    if Str.string_match end_coq_eval s 0 then
 
197
      outside ()
 
198
    else begin
 
199
      if !verbose then Printf.printf "Coq < %s\n" s;
 
200
      if has_match dot_end_line s then
 
201
        let bl = next_block (succ k) in
 
202
        if !verbose then List.iter print_endline bl;
 
203
        eval 0
 
204
      else
 
205
        eval (succ k)
 
206
    end
 
207
  in
 
208
  try
 
209
    let _ = next_block 0 in (* to skip the Coq banner *)
 
210
    let _ = next_block 0 in (* to skip the Coq answer to Set Printing Width *)
 
211
    outside ()
 
212
  with End_of_file -> begin
 
213
    close_in c_tex;
 
214
    close_in c_coq;
 
215
    close_out c_out
 
216
  end
 
217
 
 
218
(* Process of one TeX file *)
 
219
 
 
220
let rm f = try Sys.remove f with _ -> ()
 
221
 
 
222
let one_file texfile =
 
223
  let inputv = Filename.temp_file "coq_tex" ".v" in
 
224
  let coq_output = Filename.temp_file "coq_tex" ".coq_output"in
 
225
  let result =
 
226
    if !output_specified then
 
227
      !output
 
228
    else if Filename.check_suffix texfile ".tex" then
 
229
      (Filename.chop_suffix texfile ".tex") ^ ".v.tex"
 
230
    else
 
231
      texfile ^ ".v.tex" 
 
232
  in
 
233
  try
 
234
    (* 1. extract Coq phrases *)
 
235
    extract texfile inputv;
 
236
    (* 2. run Coq on input *)
 
237
    let _ = Sys.command (Printf.sprintf "%s < %s > %s 2>&1" !image inputv
 
238
                           coq_output) 
 
239
    in
 
240
    (* 3. insert Coq output into original file *)
 
241
    insert texfile coq_output result;
 
242
    (* 4. clean up *)
 
243
    rm inputv; rm coq_output
 
244
  with e -> begin
 
245
    rm inputv; rm coq_output;
 
246
    raise e
 
247
  end
 
248
 
 
249
(* Parsing of the command line, check of the Coq command and process
 
250
 * of all the files in the command line, one by one *)
 
251
 
 
252
let files = ref []
 
253
      
 
254
let parse_cl () =
 
255
  Arg.parse
 
256
      [ "-o", Arg.String (fun s -> output_specified := true; output := s),
 
257
        "output-file    Specifiy the resulting LaTeX file";
 
258
        "-n", Arg.Int (fun n -> linelen := n),
 
259
        "line-width     Set the line width";
 
260
        "-image", Arg.String (fun s -> image := s),
 
261
        "coq-image  Use coq-image as Coq command";
 
262
        "-w", Arg.Set cut_at_blanks,
 
263
        "               Try to cut lines at blanks";
 
264
        "-v", Arg.Set verbose,
 
265
        "               Verbose mode (show Coq answers on stdout)";
 
266
        "-sl", Arg.Set slanted,
 
267
        "              Coq answers in slanted font (only with LaTeX2e)";
 
268
        "-hrule", Arg.Set hrule,
 
269
        "           Coq parts are written between 2 horizontal lines";
 
270
        "-small", Arg.Set small,
 
271
        "           Coq parts are written in small font"
 
272
      ]
 
273
      (fun s -> files := s :: !files)
 
274
      "coq-tex [options] file ..."
 
275
 
 
276
let main () =
 
277
  parse_cl ();
 
278
  if !image = "" then begin
 
279
    Printf.printf "Warning: preprocessing with default image \"coqtop\"\n";
 
280
    image := "coqtop"
 
281
  end;
 
282
  if Sys.command (!image ^ " -batch > /dev/null 2>&1") <> 0 then begin
 
283
    Printf.printf "Error: ";
 
284
    let _ = Sys.command (!image ^ " -batch") in
 
285
    exit 1
 
286
  end else begin
 
287
    Printf.printf "Your version of coqtop seems OK\n";
 
288
    flush stdout
 
289
  end;
 
290
  List.iter one_file (List.rev !files)
 
291
 
 
292
let _ = Printexc.catch main ()