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

« back to all changes in this revision

Viewing changes to lib/pp.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: pp.ml4 10803 2008-04-16 09:30:05Z cek $ *)
 
10
 
 
11
open Pp_control
 
12
 
 
13
(* This should not be used outside of this file. Use
 
14
   Flags.print_emacs instead. This one is updated when reading
 
15
   command line options. This was the only way to make [Pp] depend on
 
16
   an option without creating a circularity: [Flags. -> [Util] ->
 
17
   [Pp] -> [Flags. *)
 
18
let print_emacs = ref false
 
19
let make_pp_emacs() = print_emacs:=true
 
20
let make_pp_nonemacs() = print_emacs:=false
 
21
 
 
22
(* The different kinds of blocks are: 
 
23
   \begin{description}
 
24
   \item[hbox:] Horizontal block no line breaking;
 
25
   \item[vbox:] Vertical block each break leads to a new line;
 
26
   \item[hvbox:] Horizontal-vertical block: same as vbox, except if
 
27
      this block is small enough to fit on a single line
 
28
   \item[hovbox:] Horizontal or Vertical block: breaks lead to new line
 
29
      only when necessary to print the content of the block
 
30
   \item[tbox:] Tabulation block: go to tabulation marks and no line breaking
 
31
      (except if no mark yet on the reste of the line)
 
32
   \end{description}
 
33
 *)
 
34
 
 
35
let comments = ref []
 
36
  
 
37
let rec split_com comacc acc pos = function
 
38
    [] -> comments := List.rev acc; comacc
 
39
  | ((b,e),c as com)::coms ->
 
40
      (* Take all comments that terminates before pos, or begin exactly
 
41
         at pos (used to print comments attached after an expression) *)
 
42
      if e<=pos || pos=b then split_com (c::comacc) acc pos coms
 
43
      else  split_com comacc (com::acc) pos coms
 
44
 
 
45
 
 
46
type block_type =
 
47
  | Pp_hbox of int
 
48
  | Pp_vbox of int
 
49
  | Pp_hvbox of int
 
50
  | Pp_hovbox of int
 
51
  | Pp_tbox
 
52
 
 
53
type 'a ppcmd_token =
 
54
  | Ppcmd_print of 'a
 
55
  | Ppcmd_box of block_type * ('a ppcmd_token Stream.t)
 
56
  | Ppcmd_print_break of int * int
 
57
  | Ppcmd_set_tab
 
58
  | Ppcmd_print_tbreak of int * int
 
59
  | Ppcmd_white_space of int
 
60
  | Ppcmd_force_newline
 
61
  | Ppcmd_print_if_broken
 
62
  | Ppcmd_open_box of block_type
 
63
  | Ppcmd_close_box
 
64
  | Ppcmd_close_tbox
 
65
  | Ppcmd_comment of int
 
66
 
 
67
type 'a ppdir_token =
 
68
  | Ppdir_ppcmds of 'a ppcmd_token Stream.t
 
69
  | Ppdir_print_newline
 
70
  | Ppdir_print_flush
 
71
 
 
72
type ppcmd = (int*string) ppcmd_token
 
73
 
 
74
type std_ppcmds = ppcmd Stream.t
 
75
 
 
76
type 'a ppdirs = 'a ppdir_token Stream.t
 
77
 
 
78
(* Compute length of an UTF-8 encoded string
 
79
   Rem 1 : utf8_length <= String.length (equal if pure ascii)
 
80
   Rem 2 : if used for an iso8859_1 encoded string, the result is
 
81
   wrong in very rare cases. Such a wrong case corresponds to any
 
82
   sequence of a character in range 192..253 immediately followed by a
 
83
   character in range 128..191 (typical case in french is "d��u" which
 
84
   is counted 3 instead of 4); then no real harm to use always
 
85
   utf8_length even if using an iso8859_1 encoding *)
 
86
 
 
87
let utf8_length s =
 
88
  let len = String.length s
 
89
  and cnt = ref 0
 
90
  and nc = ref 0
 
91
  and p = ref 0 in
 
92
  while !p < len do
 
93
    begin
 
94
      match s.[!p] with
 
95
      | '\000'..'\127' -> nc := 0 (* ascii char *)
 
96
      | '\128'..'\191' -> nc := 0 (* cannot start with a continuation byte *)
 
97
      | '\192'..'\223' -> nc := 1 (* expect 1 continuation byte *)
 
98
      | '\224'..'\239' -> nc := 2 (* expect 2 continuation bytes *)
 
99
      | '\240'..'\247' -> nc := 3 (* expect 3 continuation bytes *)
 
100
      | '\248'..'\251' -> nc := 4 (* expect 4 continuation bytes *)
 
101
      | '\252'..'\253' -> nc := 5 (* expect 5 continuation bytes *)
 
102
      | '\254'..'\255' -> nc := 0 (* invalid byte *)
 
103
    end ;
 
104
    incr p ;
 
105
    while !p < len && !nc > 0 do
 
106
      match s.[!p] with
 
107
      | '\128'..'\191' (* next continuation byte *) -> incr p ; decr nc
 
108
      | _ (* not a continuation byte *) -> nc := 0
 
109
    done ;
 
110
    incr cnt
 
111
  done ;
 
112
  !cnt
 
113
 
 
114
(* formatting commands *)
 
115
let str s = [< 'Ppcmd_print (utf8_length s,s) >]
 
116
let stras (i,s) = [< 'Ppcmd_print (i,s) >]
 
117
let brk (a,b) = [< 'Ppcmd_print_break (a,b) >]
 
118
let tbrk (a,b) = [< 'Ppcmd_print_tbreak (a,b) >]
 
119
let tab () = [< 'Ppcmd_set_tab >]
 
120
let fnl () = [< 'Ppcmd_force_newline >]
 
121
let pifb () = [< 'Ppcmd_print_if_broken >]
 
122
let ws n = [< 'Ppcmd_white_space n >]
 
123
let comment n = [< ' Ppcmd_comment n >]
 
124
 
 
125
(* derived commands *)
 
126
let mt () = [< >]
 
127
let spc () = [< 'Ppcmd_print_break (1,0) >]
 
128
let cut () = [< 'Ppcmd_print_break (0,0) >]
 
129
let align () = [< 'Ppcmd_print_break (0,0) >]
 
130
let int n = str (string_of_int n)
 
131
let real r = str (string_of_float r)
 
132
let bool b = str (string_of_bool b)
 
133
let strbrk s =
 
134
  let rec aux p n =
 
135
    if n < String.length s then 
 
136
      if s.[n] = ' ' then
 
137
        if p=n then [< spc (); aux (n+1) (n+1) >]
 
138
        else [< str (String.sub s p (n-p)); spc (); aux (n+1) (n+1) >]
 
139
      else aux p (n+1)
 
140
    else if p=n then [< >] else [< str (String.sub s p (n-p)) >]
 
141
  in aux 0 0
 
142
 
 
143
let ismt s = try let _ = Stream.empty s in true with Stream.Failure -> false
 
144
 
 
145
(* boxing commands *)
 
146
let h n s = [< 'Ppcmd_box(Pp_hbox n,s) >]
 
147
let v n s = [< 'Ppcmd_box(Pp_vbox n,s) >]
 
148
let hv n s = [< 'Ppcmd_box(Pp_hvbox n,s) >]
 
149
let hov n s = [< 'Ppcmd_box(Pp_hovbox n,s) >]
 
150
let t s = [< 'Ppcmd_box(Pp_tbox,s) >]
 
151
 
 
152
(* Opening and closing of boxes *)
 
153
let hb n = [< 'Ppcmd_open_box(Pp_hbox n) >]
 
154
let vb n = [< 'Ppcmd_open_box(Pp_vbox n) >]
 
155
let hvb n = [< 'Ppcmd_open_box(Pp_hvbox n) >]
 
156
let hovb n = [< 'Ppcmd_open_box(Pp_hovbox n) >]
 
157
let tb () = [< 'Ppcmd_open_box Pp_tbox >]
 
158
let close () = [< 'Ppcmd_close_box >]
 
159
let tclose () = [< 'Ppcmd_close_tbox >]
 
160
 
 
161
let (++) = Stream.iapp
 
162
 
 
163
(* In new syntax only double quote char is escaped by repeating it *)
 
164
let rec escape_string s =
 
165
  let rec escape_at s i =
 
166
    if i<0 then s
 
167
    else if s.[i] == '"' then
 
168
      let s' = String.sub s 0 i^"\""^String.sub s i (String.length s - i) in
 
169
      escape_at s' (i-1)
 
170
    else escape_at s (i-1) in
 
171
  escape_at s (String.length s - 1)
 
172
 
 
173
let qstring s = str ("\""^escape_string s^"\"")
 
174
let qs = qstring
 
175
let quote s = h 0 (str "\"" ++ s ++ str "\"")
 
176
 
 
177
let rec xmlescape ppcmd =
 
178
  let rec escape what withwhat (len, str) =
 
179
    try
 
180
      let pos = String.index str what in
 
181
      let (tlen, tail) =
 
182
        escape what withwhat ((len - pos - 1),
 
183
          (String.sub str (pos + 1) (len - pos - 1)))
 
184
      in
 
185
      (pos + tlen + String.length withwhat, String.sub str 0 pos ^ withwhat ^ tail)
 
186
    with Not_found -> (len, str)
 
187
  in
 
188
  match ppcmd with
 
189
    | Ppcmd_print (len, str) ->
 
190
        Ppcmd_print (escape '"' "&quot;"
 
191
          (escape '<' "&lt;" (escape '&' "&amp;" (len, str))))
 
192
      (* In XML we always print whole content so we can npeek the whole stream *)
 
193
    | Ppcmd_box (x, str) -> Ppcmd_box (x, Stream.of_list
 
194
        (List.map xmlescape (Stream.npeek max_int str)))
 
195
    | x -> x
 
196
 
 
197
 
 
198
(* This flag tells if the last printed comment ends with a newline, to
 
199
  avoid empty lines *)
 
200
let com_eol = ref false
 
201
 
 
202
let com_brk ft = com_eol := false
 
203
let com_if ft f =
 
204
  if !com_eol then (com_eol := false; Format.pp_force_newline ft ())
 
205
  else Lazy.force f
 
206
 
 
207
let rec pr_com ft s =
 
208
  let (s1,os) =
 
209
    try
 
210
      let n = String.index s '\n' in
 
211
      String.sub s 0 n, Some (String.sub s (n+1) (String.length s - n - 1))
 
212
    with Not_found -> s,None in
 
213
  com_if ft (Lazy.lazy_from_val());
 
214
(*  let s1 =
 
215
    if String.length s1 <> 0 && s1.[0] = ' ' then
 
216
      (Format.pp_print_space ft (); String.sub s1 1 (String.length s1 - 1))
 
217
    else s1 in*)
 
218
  Format.pp_print_as ft (utf8_length s1) s1;
 
219
  match os with
 
220
      Some s2 ->
 
221
        if String.length s2 = 0 then (com_eol := true)
 
222
        else
 
223
          (Format.pp_force_newline ft (); pr_com ft s2)
 
224
    | None -> ()
 
225
 
 
226
(* pretty printing functions *)
 
227
let pp_dirs ft = 
 
228
  let pp_open_box = function
 
229
    | Pp_hbox n   -> Format.pp_open_hbox ft ()
 
230
    | Pp_vbox n   -> Format.pp_open_vbox ft n
 
231
    | Pp_hvbox n  -> Format.pp_open_hvbox ft n
 
232
    | Pp_hovbox n -> Format.pp_open_hovbox ft n
 
233
    | Pp_tbox     -> Format.pp_open_tbox ft () 
 
234
  in
 
235
  let rec pp_cmd = function
 
236
    | Ppcmd_print(n,s)        ->
 
237
        com_if ft (Lazy.lazy_from_val()); Format.pp_print_as ft n s
 
238
    | Ppcmd_box(bty,ss)       -> (* Prevent evaluation of the stream! *)
 
239
        com_if ft (Lazy.lazy_from_val());
 
240
        pp_open_box bty ;
 
241
        if not (Format.over_max_boxes ()) then Stream.iter pp_cmd ss;
 
242
        Format.pp_close_box ft ()
 
243
    | Ppcmd_open_box bty      -> com_if ft (Lazy.lazy_from_val()); pp_open_box bty
 
244
    | Ppcmd_close_box         -> Format.pp_close_box ft ()
 
245
    | Ppcmd_close_tbox        -> Format.pp_close_tbox ft ()
 
246
    | Ppcmd_white_space n     ->
 
247
        com_if ft (Lazy.lazy_from_fun (fun()->Format.pp_print_break ft n 0))
 
248
    | Ppcmd_print_break(m,n)  ->
 
249
        com_if ft (Lazy.lazy_from_fun(fun()->Format.pp_print_break ft m n))
 
250
    | Ppcmd_set_tab           -> Format.pp_set_tab ft ()
 
251
    | Ppcmd_print_tbreak(m,n) ->
 
252
        com_if ft (Lazy.lazy_from_fun(fun()->Format.pp_print_tbreak ft m n))
 
253
    | Ppcmd_force_newline     ->
 
254
        com_brk ft; Format.pp_force_newline ft ()
 
255
    | Ppcmd_print_if_broken   ->
 
256
        com_if ft (Lazy.lazy_from_fun(fun()->Format.pp_print_if_newline ft ()))
 
257
    | Ppcmd_comment i         ->
 
258
        let coms = split_com [] [] i !comments in
 
259
(*        Format.pp_open_hvbox ft 0;*)
 
260
        List.iter (pr_com ft) coms(*;
 
261
        Format.pp_close_box ft ()*)
 
262
  in
 
263
  let pp_dir = function
 
264
    | Ppdir_ppcmds cmdstream -> Stream.iter pp_cmd cmdstream
 
265
    | Ppdir_print_newline    ->
 
266
        com_brk ft; Format.pp_print_newline ft ()
 
267
    | Ppdir_print_flush      -> Format.pp_print_flush ft () 
 
268
  in
 
269
  fun dirstream ->
 
270
    try  
 
271
      Stream.iter pp_dir dirstream; com_brk ft
 
272
    with 
 
273
      | e -> Format.pp_print_flush ft () ; raise e
 
274
 
 
275
 
 
276
(* pretty print on stdout and stderr *)
 
277
 
 
278
let pp_std_dirs = pp_dirs !std_ft
 
279
let pp_err_dirs = pp_dirs !err_ft
 
280
 
 
281
let ppcmds x = Ppdir_ppcmds x
 
282
 
 
283
(* Special chars for emacs, to detect warnings inside goal output *)
 
284
let emacs_warning_start_string = String.make 1 (Char.chr 254)
 
285
let emacs_warning_end_string = String.make 1 (Char.chr 255)
 
286
 
 
287
let warnstart() = 
 
288
  if not !print_emacs then mt() else str emacs_warning_start_string
 
289
 
 
290
let warnend() = 
 
291
  if not !print_emacs then mt() else str emacs_warning_end_string
 
292
 
 
293
let warnbody strm =
 
294
  [< warnstart() ; hov 0 (str "Warning: " ++ strm) ; warnend() >]
 
295
 
 
296
(* pretty printing functions WITHOUT FLUSH *)
 
297
let pp_with ft strm =
 
298
  pp_dirs ft [< 'Ppdir_ppcmds strm >]
 
299
 
 
300
let ppnl_with ft strm =
 
301
  pp_dirs ft [< 'Ppdir_ppcmds [< strm ; 'Ppcmd_force_newline >] >]
 
302
 
 
303
let default_warn_with ft strm = ppnl_with ft (warnbody strm)
 
304
 
 
305
let pp_warn_with = ref default_warn_with
 
306
 
 
307
let set_warning_function pp_warn = pp_warn_with := pp_warn
 
308
 
 
309
let warn_with ft strm = !pp_warn_with ft strm
 
310
 
 
311
let warning_with ft string = warn_with ft (str string)
 
312
 
 
313
let pp_flush_with ft = Format.pp_print_flush ft
 
314
 
 
315
(* pretty printing functions WITH FLUSH *)
 
316
let msg_with ft strm =
 
317
  pp_dirs ft [< 'Ppdir_ppcmds strm ; 'Ppdir_print_flush >]
 
318
 
 
319
let msgnl_with ft strm =
 
320
  pp_dirs ft [< 'Ppdir_ppcmds strm ; 'Ppdir_print_newline >]
 
321
 
 
322
let msg_warning_with ft strm =
 
323
  msgnl_with ft (warnbody strm)
 
324
 
 
325
(* pretty printing functions WITHOUT FLUSH *)
 
326
let pp        x = pp_with   !std_ft x
 
327
let ppnl      x = ppnl_with !std_ft x
 
328
let pperr     x = pp_with   !err_ft x
 
329
let pperrnl   x = ppnl_with !err_ft x
 
330
let message   s = ppnl      (str s)
 
331
let warning   x = warning_with !err_ft x
 
332
let warn      x = warn_with    !err_ft x
 
333
let pp_flush  x = Format.pp_print_flush !std_ft x
 
334
let flush_all() = flush stderr; flush stdout; pp_flush()
 
335
 
 
336
(* pretty printing functions WITH FLUSH *)
 
337
let msg x = msg_with !std_ft x
 
338
let msgnl x = msgnl_with !std_ft x
 
339
let msgerr x = msg_with !err_ft x
 
340
let msgerrnl x = msgnl_with !err_ft x
 
341
let msg_warning x = msg_warning_with !err_ft x