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

« back to all changes in this revision

Viewing changes to library/library.ml

  • 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: library.ml 11897 2009-02-09 19:28:02Z barras $ *)
 
10
 
 
11
open Pp
 
12
open Util
 
13
 
 
14
open Names
 
15
open Libnames
 
16
open Nameops
 
17
open Safe_typing
 
18
open Libobject
 
19
open Lib
 
20
open Nametab
 
21
 
 
22
(*************************************************************************)
 
23
(*s Load path. Mapping from physical to logical paths etc.*)
 
24
 
 
25
type logical_path = dir_path
 
26
 
 
27
let load_paths = ref ([] : (System.physical_path * logical_path * bool) list)
 
28
 
 
29
let get_load_paths () = List.map pi1 !load_paths
 
30
 
 
31
let find_logical_path phys_dir =
 
32
  let phys_dir = System.canonical_path_name phys_dir in
 
33
  match List.filter (fun (p,d,_) -> p = phys_dir) !load_paths with
 
34
  | [_,dir,_] -> dir
 
35
  | [] -> Nameops.default_root_prefix
 
36
  | l -> anomaly ("Two logical paths are associated to "^phys_dir)
 
37
 
 
38
let is_in_load_paths phys_dir =
 
39
  let dir = System.canonical_path_name phys_dir in
 
40
  let lp = get_load_paths () in
 
41
  let check_p = fun p -> (String.compare dir p) == 0 in
 
42
    List.exists check_p lp 
 
43
 
 
44
let remove_load_path dir =
 
45
  load_paths := List.filter (fun (p,d,_) -> p <> dir) !load_paths
 
46
 
 
47
let add_load_path isroot (phys_path,coq_path) =
 
48
  let phys_path = System.canonical_path_name phys_path in
 
49
    match List.filter (fun (p,d,_) -> p = phys_path) !load_paths with
 
50
      | [_,dir,_] ->
 
51
          if coq_path <> dir 
 
52
            (* If this is not the default -I . to coqtop *)
 
53
            && not
 
54
            (phys_path = System.canonical_path_name Filename.current_dir_name
 
55
                && coq_path = Nameops.default_root_prefix)
 
56
          then
 
57
            begin
 
58
              (* Assume the user is concerned by library naming *)
 
59
              if dir <> Nameops.default_root_prefix then
 
60
                Flags.if_warn msg_warning
 
61
                  (str phys_path ++ strbrk " was previously bound to " ++
 
62
                   pr_dirpath dir ++ strbrk "; it is remapped to " ++
 
63
                   pr_dirpath coq_path);
 
64
              remove_load_path phys_path;
 
65
              load_paths := (phys_path,coq_path,isroot) :: !load_paths;
 
66
            end
 
67
      | [] ->
 
68
          load_paths := (phys_path,coq_path,isroot) :: !load_paths;
 
69
      | _ -> anomaly ("Two logical paths are associated to "^phys_path)
 
70
 
 
71
let physical_paths (dp,lp) = dp
 
72
 
 
73
let extend_path_with_dirpath p dir =
 
74
  List.fold_left Filename.concat p 
 
75
    (List.map string_of_id (List.rev (repr_dirpath dir)))
 
76
 
 
77
let root_paths_matching_dir_path dir =
 
78
  let rec aux = function
 
79
  | [] -> []
 
80
  | (p,d,true) :: l when is_dirpath_prefix_of d dir ->
 
81
      let suffix = drop_dirpath_prefix d dir in
 
82
      extend_path_with_dirpath p suffix :: aux l
 
83
  | _ :: l -> aux l in
 
84
  aux !load_paths
 
85
 
 
86
(* Root p is bound to A.B.C.D and we require file C.D.E.F *)
 
87
(* We may mean A.B.C.D.E.F, or A.B.C.D.C.D.E.F *)
 
88
 
 
89
(* Root p is bound to A.B.C.C and we require file C.C.E.F *)
 
90
(* We may mean A.B.C.C.E.F, or A.B.C.C.C.E.F, or A.B.C.C.C.C.E.F *)
 
91
 
 
92
let intersections d1 d2 =
 
93
  let rec aux d1 =
 
94
    if d1 = empty_dirpath then [d2] else
 
95
      let rest = aux (snd (chop_dirpath 1 d1)) in
 
96
      if is_dirpath_prefix_of d1 d2 then drop_dirpath_prefix d1 d2 :: rest
 
97
      else rest in
 
98
  aux d1
 
99
 
 
100
let loadpaths_matching_dir_path dir =
 
101
  let rec aux = function
 
102
  | [] -> []
 
103
  | (p,d,true) :: l ->
 
104
      let inters = intersections d dir in
 
105
      List.map (fun tl -> (extend_path_with_dirpath p tl,append_dirpath d tl))
 
106
        inters @
 
107
        aux l
 
108
  | (p,d,_) :: l ->
 
109
      (extend_path_with_dirpath p dir,append_dirpath d dir) :: aux l in
 
110
  aux !load_paths
 
111
 
 
112
let get_full_load_paths () = List.map (fun (a,b,c) -> (a,b)) !load_paths
 
113
 
 
114
(************************************************************************)
 
115
(*s Modules on disk contain the following informations (after the magic 
 
116
    number, and before the digest). *)
 
117
 
 
118
type compilation_unit_name = dir_path
 
119
 
 
120
type library_disk = { 
 
121
  md_name : compilation_unit_name;
 
122
  md_compiled : compiled_library;
 
123
  md_objects : Declaremods.library_objects;
 
124
  md_deps : (compilation_unit_name * Digest.t) list;
 
125
  md_imports : compilation_unit_name list }
 
126
 
 
127
(*s Modules loaded in memory contain the following informations. They are
 
128
    kept in the global table [libraries_table]. *)
 
129
 
 
130
type library_t = {
 
131
  library_name : compilation_unit_name;
 
132
  library_compiled : compiled_library;
 
133
  library_objects : Declaremods.library_objects;
 
134
  library_deps : (compilation_unit_name * Digest.t) list;
 
135
  library_imports : compilation_unit_name list;
 
136
  library_digest : Digest.t }
 
137
 
 
138
module LibraryOrdered = 
 
139
  struct
 
140
    type t = dir_path
 
141
    let compare d1 d2 =
 
142
      Pervasives.compare
 
143
        (List.rev (repr_dirpath d1)) (List.rev (repr_dirpath d2))
 
144
  end
 
145
 
 
146
module LibraryMap = Map.Make(LibraryOrdered)
 
147
module LibraryFilenameMap = Map.Make(LibraryOrdered)
 
148
 
 
149
(* This is a map from names to loaded libraries *)
 
150
let libraries_table = ref LibraryMap.empty
 
151
 
 
152
(* This is the map of loaded libraries filename *)
 
153
(* (not synchronized so as not to be caught in the states on disk) *)
 
154
let libraries_filename_table = ref LibraryFilenameMap.empty
 
155
 
 
156
(* These are the _ordered_ sets of loaded, imported and exported libraries *)
 
157
let libraries_loaded_list = ref []
 
158
let libraries_imports_list = ref []
 
159
let libraries_exports_list = ref []
 
160
 
 
161
let freeze () =
 
162
  !libraries_table,
 
163
  !libraries_loaded_list,
 
164
  !libraries_imports_list,
 
165
  !libraries_exports_list
 
166
 
 
167
let unfreeze (mt,mo,mi,me) = 
 
168
  libraries_table := mt;
 
169
  libraries_loaded_list := mo;
 
170
  libraries_imports_list := mi;
 
171
  libraries_exports_list := me
 
172
 
 
173
let init () =
 
174
  libraries_table := LibraryMap.empty;
 
175
  libraries_loaded_list := [];
 
176
  libraries_imports_list := [];
 
177
  libraries_exports_list := []
 
178
 
 
179
let _ = 
 
180
  Summary.declare_summary "MODULES"
 
181
    { Summary.freeze_function = freeze;
 
182
      Summary.unfreeze_function = unfreeze;
 
183
      Summary.init_function = init;
 
184
      Summary.survive_module = false;
 
185
      Summary.survive_section = false }
 
186
 
 
187
(* various requests to the tables *)
 
188
 
 
189
let find_library dir =
 
190
  LibraryMap.find dir !libraries_table
 
191
 
 
192
let try_find_library dir =
 
193
  try find_library dir
 
194
  with Not_found ->
 
195
    error ("Unknown library " ^ (string_of_dirpath dir))
 
196
 
 
197
let register_library_filename dir f =
 
198
  (* Not synchronized: overwrite the previous binding if one existed *)
 
199
  (* from a previous play of the session *)
 
200
  libraries_filename_table := 
 
201
    LibraryFilenameMap.add dir f !libraries_filename_table
 
202
 
 
203
let library_full_filename dir =
 
204
  try LibraryFilenameMap.find dir !libraries_filename_table
 
205
  with Not_found -> "<unavailable filename>"
 
206
 
 
207
let overwrite_library_filenames f =
 
208
  let f =
 
209
    if Filename.is_relative f then Filename.concat (Sys.getcwd ()) f else f in
 
210
  LibraryMap.iter (fun dir _ -> register_library_filename dir f)
 
211
    !libraries_table
 
212
 
 
213
let library_is_loaded dir =
 
214
  try let _ = find_library dir in true
 
215
  with Not_found -> false
 
216
 
 
217
let library_is_opened dir = 
 
218
  List.exists (fun m -> m.library_name = dir) !libraries_imports_list
 
219
 
 
220
let library_is_exported dir =
 
221
  List.exists (fun m -> m.library_name = dir) !libraries_exports_list
 
222
 
 
223
let loaded_libraries () = 
 
224
  List.map (fun m -> m.library_name) !libraries_loaded_list
 
225
 
 
226
let opened_libraries () =
 
227
  List.map (fun m -> m.library_name) !libraries_imports_list
 
228
 
 
229
  (* If a library is loaded several time, then the first occurrence must
 
230
     be performed first, thus the libraries_loaded_list ... *)
 
231
 
 
232
let register_loaded_library m =
 
233
  let rec aux = function
 
234
    | [] -> [m]
 
235
    | m'::_ as l when m'.library_name = m.library_name -> l
 
236
    | m'::l' -> m' :: aux l' in
 
237
  libraries_loaded_list := aux !libraries_loaded_list;
 
238
  libraries_table := LibraryMap.add m.library_name m !libraries_table
 
239
 
 
240
  (* ... while if a library is imported/exported several time, then
 
241
     only the last occurrence is really needed - though the imported
 
242
     list may differ from the exported list (consider the sequence
 
243
     Export A; Export B; Import A which results in A;B for exports but
 
244
     in B;A for imports) *)
 
245
 
 
246
let rec remember_last_of_each l m =
 
247
  match l with
 
248
  | [] -> [m]
 
249
  | m'::l' when m'.library_name = m.library_name -> remember_last_of_each l' m
 
250
  | m'::l' -> m' :: remember_last_of_each l' m
 
251
 
 
252
let register_open_library export m =
 
253
  libraries_imports_list := remember_last_of_each !libraries_imports_list m;
 
254
  if export then 
 
255
    libraries_exports_list := remember_last_of_each !libraries_exports_list m
 
256
 
 
257
(************************************************************************)
 
258
(*s Opening libraries *)
 
259
 
 
260
(* [open_library export explicit m] opens library [m] if not already
 
261
   opened _or_ if explicitly asked to be (re)opened *)
 
262
 
 
263
let eq_lib_name m1 m2 = m1.library_name = m2.library_name
 
264
 
 
265
let open_library export explicit_libs m =
 
266
  if
 
267
    (* Only libraries indirectly to open are not reopen *)
 
268
    (* Libraries explicitly mentionned by the user are always reopen *)
 
269
    List.exists (eq_lib_name m) explicit_libs
 
270
    or not (library_is_opened m.library_name)
 
271
  then begin
 
272
    register_open_library export m;
 
273
    Declaremods.really_import_module (MPfile m.library_name)
 
274
  end
 
275
  else
 
276
    if export then 
 
277
      libraries_exports_list := remember_last_of_each !libraries_exports_list m
 
278
 
 
279
(* open_libraries recursively open a list of libraries but opens only once 
 
280
   a library that is re-exported many times *)
 
281
 
 
282
let open_libraries export modl =
 
283
  let to_open_list = 
 
284
    List.fold_left
 
285
      (fun l m ->
 
286
         let subimport =
 
287
           List.fold_left
 
288
             (fun l m -> remember_last_of_each l (try_find_library m))
 
289
             l m.library_imports
 
290
         in remember_last_of_each subimport m)
 
291
      [] modl in
 
292
  List.iter (open_library export modl) to_open_list
 
293
 
 
294
 
 
295
(**********************************************************************)
 
296
(* import and export  -  synchronous operations*)
 
297
 
 
298
let open_import i (_,(dir,export)) =
 
299
  if i=1 then
 
300
    (* even if the library is already imported, we re-import it *)
 
301
    (* if not (library_is_opened dir) then *)
 
302
      open_libraries export [try_find_library dir]
 
303
 
 
304
let cache_import obj = 
 
305
  open_import 1 obj
 
306
 
 
307
let subst_import (_,_,o) = o
 
308
 
 
309
let export_import o = Some o
 
310
 
 
311
let classify_import (_,(_,export as obj)) = 
 
312
  if export then Substitute obj else Dispose
 
313
 
 
314
 
 
315
let (in_import, out_import) =
 
316
  declare_object {(default_object "IMPORT LIBRARY") with 
 
317
       cache_function = cache_import;
 
318
       open_function = open_import;
 
319
       subst_function = subst_import;
 
320
       classify_function = classify_import }
 
321
 
 
322
 
 
323
(************************************************************************)
 
324
(*s Low-level interning/externing of libraries to files *)
 
325
 
 
326
(*s Loading from disk to cache (preparation phase) *)
 
327
 
 
328
let (raw_extern_library, raw_intern_library) =
 
329
  System.raw_extern_intern Coq_config.vo_magic_number ".vo"
 
330
 
 
331
let with_magic_number_check f a =
 
332
  try f a
 
333
  with System.Bad_magic_number fname ->
 
334
    errorlabstrm "with_magic_number_check"
 
335
    (str"File " ++ str fname ++ spc () ++ str"has bad magic number." ++
 
336
    spc () ++ str"It is corrupted" ++ spc () ++
 
337
    str"or was compiled with another version of Coq.")
 
338
 
 
339
(************************************************************************)
 
340
(*s Locate absolute or partially qualified library names in the path *)
 
341
 
 
342
exception LibUnmappedDir
 
343
exception LibNotFound
 
344
type library_location = LibLoaded | LibInPath
 
345
 
 
346
let locate_absolute_library dir =
 
347
  (* Search in loadpath *)
 
348
  let pref, base = split_dirpath dir in
 
349
  let loadpath = root_paths_matching_dir_path pref in
 
350
  if loadpath = [] then raise LibUnmappedDir;
 
351
  try
 
352
    let name = (string_of_id base)^".vo" in
 
353
    let _, file = System.where_in_path ~warn:false loadpath name in
 
354
    (dir, file)
 
355
  with Not_found ->
 
356
  (* Last chance, removed from the file system but still in memory *)
 
357
  if library_is_loaded dir then
 
358
    (dir, library_full_filename dir)
 
359
  else
 
360
    raise LibNotFound
 
361
 
 
362
let locate_qualified_library warn qid =
 
363
  try
 
364
    (* Search library in loadpath *)
 
365
    let dir, base = repr_qualid qid in
 
366
    let loadpath = loadpaths_matching_dir_path dir in
 
367
    if loadpath = [] then raise LibUnmappedDir;
 
368
    let name = string_of_id base ^ ".vo" in
 
369
    let lpath, file = System.where_in_path ~warn (List.map fst loadpath) name in
 
370
    let dir = extend_dirpath (List.assoc lpath loadpath) base in
 
371
    (* Look if loaded *)
 
372
    if library_is_loaded dir then (LibLoaded, dir, library_full_filename dir)
 
373
    (* Otherwise, look for it in the file system *)
 
374
    else (LibInPath, dir, file)
 
375
  with Not_found -> raise LibNotFound
 
376
 
 
377
let explain_locate_library_error qid = function
 
378
  | LibUnmappedDir ->
 
379
      let prefix, _ = repr_qualid qid in
 
380
      errorlabstrm "load_absolute_library_from"
 
381
      (str "Cannot load " ++ pr_qualid qid ++ str ":" ++ spc () ++ 
 
382
      str "no physical path bound to" ++ spc () ++ pr_dirpath prefix ++ fnl ())
 
383
  | LibNotFound ->
 
384
      errorlabstrm "load_absolute_library_from"
 
385
      (str"Cannot find library " ++ pr_qualid qid ++ str" in loadpath")
 
386
  | e -> raise e
 
387
 
 
388
let try_locate_absolute_library dir =
 
389
  try
 
390
    locate_absolute_library dir
 
391
  with e ->
 
392
    explain_locate_library_error (qualid_of_dirpath dir) e
 
393
 
 
394
let try_locate_qualified_library (loc,qid) =
 
395
  try
 
396
    let (_,dir,f) = locate_qualified_library (Flags.is_verbose()) qid in
 
397
    dir,f
 
398
  with e -> 
 
399
    explain_locate_library_error qid e
 
400
 
 
401
 
 
402
(************************************************************************)
 
403
(* Internalise libraries *)
 
404
 
 
405
let lighten_library m = 
 
406
  if !Flags.dont_load_proofs then lighten_library m else m
 
407
 
 
408
let mk_library md digest = {
 
409
  library_name = md.md_name;
 
410
  library_compiled = lighten_library md.md_compiled;
 
411
  library_objects = md.md_objects;
 
412
  library_deps = md.md_deps;
 
413
  library_imports = md.md_imports;
 
414
  library_digest = digest }
 
415
 
 
416
let intern_from_file f =
 
417
  let ch = with_magic_number_check raw_intern_library f in
 
418
  let md = System.marshal_in ch in
 
419
  let digest = System.marshal_in ch in
 
420
  close_in ch;
 
421
  register_library_filename md.md_name f;
 
422
  mk_library md digest
 
423
 
 
424
let rec intern_library needed (dir, f) =
 
425
  (* Look if in the current logical environment *)
 
426
  try find_library dir, needed
 
427
  with Not_found ->
 
428
  (* Look if already listed and consequently its dependencies too *)
 
429
  try List.assoc dir needed, needed
 
430
  with Not_found ->
 
431
  (* [dir] is an absolute name which matches [f] which must be in loadpath *)
 
432
  let m = intern_from_file f in
 
433
  if dir <> m.library_name then
 
434
    errorlabstrm "load_physical_library"
 
435
      (str ("The file " ^ f ^ " contains library") ++ spc () ++
 
436
       pr_dirpath m.library_name ++ spc () ++ str "and not library" ++
 
437
       spc() ++ pr_dirpath dir);
 
438
  m, intern_library_deps needed dir m
 
439
 
 
440
and intern_library_deps needed dir m =
 
441
  (dir,m)::List.fold_left (intern_mandatory_library dir) needed m.library_deps
 
442
 
 
443
and intern_mandatory_library caller needed (dir,d) =
 
444
  let m,needed = intern_library needed (try_locate_absolute_library dir) in
 
445
  if d <> m.library_digest then
 
446
    errorlabstrm "" (strbrk ("Compiled library "^(string_of_dirpath caller)^
 
447
           ".vo makes inconsistent assumptions over library "
 
448
           ^(string_of_dirpath dir)));
 
449
  needed
 
450
 
 
451
let rec_intern_library needed mref =
 
452
  let _,needed = intern_library needed mref in needed
 
453
 
 
454
let check_library_short_name f dir = function
 
455
  | Some id when id <> snd (split_dirpath dir) ->
 
456
      errorlabstrm "check_library_short_name"
 
457
      (str ("The file " ^ f ^ " contains library") ++ spc () ++
 
458
      pr_dirpath dir ++ spc () ++ str "and not library" ++ spc () ++
 
459
      pr_id id)
 
460
  | _ -> ()
 
461
 
 
462
let rec_intern_by_filename_only id f =
 
463
  let m = try intern_from_file f with Sys_error s -> error s in
 
464
  (* Only the base name is expected to match *)
 
465
  check_library_short_name f m.library_name id;
 
466
  (* We check no other file containing same library is loaded *)
 
467
  if library_is_loaded m.library_name then
 
468
    begin
 
469
      Flags.if_verbose warning 
 
470
        ((string_of_dirpath m.library_name)^" is already loaded from file "^
 
471
        library_full_filename m.library_name);
 
472
      m.library_name, []
 
473
    end
 
474
 else
 
475
    let needed = intern_library_deps [] m.library_name m in
 
476
    m.library_name, needed
 
477
 
 
478
let rec_intern_library_from_file idopt f =
 
479
  (* A name is specified, we have to check it contains library id *)
 
480
  let paths = get_load_paths () in
 
481
  let _, f = 
 
482
    System.find_file_in_path ~warn:(Flags.is_verbose()) paths (f^".vo") in
 
483
  rec_intern_by_filename_only idopt f
 
484
 
 
485
(**********************************************************************)
 
486
(*s [require_library] loads and possibly opens a library. This is a 
 
487
    synchronized operation. It is performed as follows:
 
488
 
 
489
  preparation phase: (functions require_library* ) the library and its 
 
490
    dependencies are read from to disk (using intern_* )
 
491
    [they are read from disk to ensure that at section/module
 
492
     discharging time, the physical library referred to outside the
 
493
     section/module is the one that was used at type-checking time in
 
494
     the section/module]
 
495
 
 
496
  execution phase: (through add_leaf and cache_require)
 
497
    the library is loaded in the environment and Nametab, the objects are 
 
498
    registered etc, using functions from Declaremods (via load_library, 
 
499
    which recursively loads its dependencies)
 
500
*)
 
501
 
 
502
type library_reference = dir_path list * bool option
 
503
 
 
504
let register_library (dir,m) =
 
505
  Declaremods.register_library
 
506
    m.library_name 
 
507
    m.library_compiled 
 
508
    m.library_objects 
 
509
    m.library_digest;
 
510
  register_loaded_library m
 
511
 
 
512
(* Follow the semantics of Anticipate object:
 
513
   - called at module or module type closing when a Require occurs in 
 
514
     the module or module type
 
515
   - not called from a library (i.e. a module identified with a file) *)
 
516
let load_require _ (_,(needed,modl,_)) =
 
517
  List.iter register_library needed
 
518
 
 
519
let open_require i (_,(_,modl,export)) =
 
520
  Option.iter (fun exp -> open_libraries exp (List.map find_library modl))
 
521
    export
 
522
 
 
523
  (* [needed] is the ordered list of libraries not already loaded *)
 
524
let cache_require o =
 
525
  load_require 1 o;
 
526
  open_require 1 o
 
527
 
 
528
  (* keeps the require marker for closed section replay but removes
 
529
     OS dependent fields from .vo files for cross-platform compatibility *)
 
530
let export_require (_,l,e) = Some ([],l,e)
 
531
 
 
532
let discharge_require (_,o) = Some o
 
533
 
 
534
(* open_function is never called from here because an Anticipate object *) 
 
535
 
 
536
let (in_require, out_require) =
 
537
  declare_object {(default_object "REQUIRE") with
 
538
       cache_function = cache_require;
 
539
       load_function = load_require;
 
540
       open_function = (fun _ _ -> assert false);
 
541
       export_function = export_require;
 
542
       discharge_function = discharge_require;
 
543
       classify_function = (fun (_,o) -> Anticipate o) }
 
544
 
 
545
(* Require libraries, import them if [export <> None], mark them for export
 
546
   if [export = Some true] *)
 
547
 
 
548
let xml_require = ref (fun d -> ())
 
549
let set_xml_require f = xml_require := f
 
550
 
 
551
let require_library qidl export =
 
552
  let modrefl = List.map try_locate_qualified_library qidl in
 
553
  let needed = List.rev (List.fold_left rec_intern_library [] modrefl) in
 
554
  let modrefl = List.map fst modrefl in
 
555
    if Lib.is_modtype () || Lib.is_module () then 
 
556
      begin
 
557
        add_anonymous_leaf (in_require (needed,modrefl,None));
 
558
        Option.iter (fun exp ->
 
559
          List.iter (fun dir -> add_anonymous_leaf (in_import(dir,exp))) modrefl)
 
560
          export
 
561
      end
 
562
    else
 
563
      add_anonymous_leaf (in_require (needed,modrefl,export));
 
564
    if !Flags.xml_export then List.iter !xml_require modrefl;
 
565
  add_frozen_state ()
 
566
 
 
567
let require_library_from_file idopt file export =
 
568
  let modref,needed = rec_intern_library_from_file idopt file in
 
569
  let needed = List.rev needed in
 
570
  if Lib.is_modtype () || Lib.is_module () then begin
 
571
    add_anonymous_leaf (in_require (needed,[modref],None));
 
572
    Option.iter (fun exp -> add_anonymous_leaf (in_import (modref,exp)))
 
573
      export
 
574
  end
 
575
  else
 
576
    add_anonymous_leaf (in_require (needed,[modref],export));
 
577
  if !Flags.xml_export then !xml_require modref;
 
578
  add_frozen_state ()
 
579
 
 
580
(* the function called by Vernacentries.vernac_import *)
 
581
 
 
582
let import_module export (loc,qid) =
 
583
  try
 
584
    match Nametab.locate_module qid with
 
585
      | MPfile dir -> 
 
586
          if Lib.is_modtype () || Lib.is_module () || not export then
 
587
            add_anonymous_leaf (in_import (dir, export))
 
588
          else
 
589
            add_anonymous_leaf (in_import (dir, export))
 
590
      | mp ->
 
591
          Declaremods.import_module export mp
 
592
  with
 
593
      Not_found ->
 
594
        user_err_loc
 
595
          (loc,"import_library",
 
596
          str ((string_of_qualid qid)^" is not a module"))
 
597
  
 
598
(************************************************************************)
 
599
(*s Initializing the compilation of a library. *)
 
600
 
 
601
let check_coq_overwriting p =
 
602
  let l = repr_dirpath p in
 
603
  if not !Flags.boot && l <> [] && string_of_id (list_last l) = "Coq" then
 
604
    errorlabstrm "" (strbrk ("Name "^string_of_dirpath p^" starts with prefix \"Coq\" which is reserved for the Coq library."))
 
605
 
 
606
let start_library f = 
 
607
  let paths = get_load_paths () in
 
608
  let _,longf =
 
609
    System.find_file_in_path ~warn:(Flags.is_verbose()) paths (f^".v") in
 
610
  let ldir0 = find_logical_path (Filename.dirname longf) in
 
611
  check_coq_overwriting ldir0;
 
612
  let id = id_of_string (Filename.basename f) in
 
613
  let ldir = extend_dirpath ldir0 id in
 
614
  Declaremods.start_library ldir;
 
615
  ldir,longf
 
616
 
 
617
(************************************************************************)
 
618
(*s [save_library dir] ends library [dir] and save it to the disk. *)
 
619
 
 
620
let current_deps () =
 
621
  List.map (fun m -> (m.library_name, m.library_digest)) !libraries_loaded_list
 
622
 
 
623
let current_reexports () =
 
624
  List.map (fun m -> m.library_name) !libraries_exports_list
 
625
 
 
626
let error_recursively_dependent_library dir =
 
627
  errorlabstrm ""
 
628
    (strbrk "Unable to use logical name " ++ pr_dirpath dir ++ 
 
629
     strbrk " to save current library because" ++
 
630
     strbrk " it already depends on a library of this name.")
 
631
 
 
632
(* Security weakness: file might have been changed on disk between
 
633
   writing the content and computing the checksum... *) 
 
634
let save_library_to dir f =
 
635
  let cenv, seg = Declaremods.end_library dir in
 
636
  let md = { 
 
637
    md_name = dir;
 
638
    md_compiled = cenv;
 
639
    md_objects = seg;
 
640
    md_deps = current_deps ();
 
641
    md_imports = current_reexports () } in
 
642
  if List.mem_assoc dir md.md_deps then
 
643
    error_recursively_dependent_library dir;
 
644
  let (f',ch) = raw_extern_library f in
 
645
  try
 
646
    System.marshal_out ch md;
 
647
    flush ch;
 
648
    let di = Digest.file f' in
 
649
    System.marshal_out ch di;
 
650
    close_out ch
 
651
  with e -> warning ("Removed file "^f'); close_out ch; Sys.remove f'; raise e
 
652
 
 
653
(************************************************************************)
 
654
(*s Display the memory use of a library. *)
 
655
 
 
656
open Printf
 
657
 
 
658
let mem s =
 
659
  let m = try_find_library s in
 
660
  h 0 (str (sprintf "%dk (cenv = %dk / seg = %dk)"
 
661
                 (size_kb m) (size_kb m.library_compiled) 
 
662
                 (size_kb m.library_objects)))