1 (* Copyright (C) 2005, HELM Team.
3 * This file is part of HELM, an Hypertextual, Electronic
4 * Library of Mathematics, developed at the Computer Science
5 * Department, University of Bologna, Italy.
7 * HELM is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * HELM is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with HELM; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 * For details, see the HELM World-Wide-Web page,
23 * http://helm.cs.unibo.it/
28 module GA = GrafiteAst
31 let obj_file_of_baseuri writable baseuri =
33 LibraryMisc.obj_file_of_baseuri
34 ~must_exist:true ~baseuri ~writable
36 | Http_getter_types.Unresolvable_URI _
37 | Http_getter_types.Key_not_found _ ->
38 LibraryMisc.obj_file_of_baseuri
39 ~must_exist:false ~baseuri ~writable:true
43 (* all are maps from "file" to "something" *)
44 let include_deps = Hashtbl.create (Array.length Sys.argv) in
45 let include_deps_dot = Hashtbl.create (Array.length Sys.argv) in
46 let baseuri_of = Hashtbl.create (Array.length Sys.argv) in
47 let baseuri_of_inv = Hashtbl.create (Array.length Sys.argv) in
48 let uri_deps = Hashtbl.create (Array.length Sys.argv) in
49 let buri alias = U.buri_of_uri (U.uri_of_string alias) in
50 let resolve alias current_buri =
51 let buri = buri alias in
52 if buri <> current_buri then Some buri else None in
53 MatitaInit.fill_registry ();
54 let dot_file = ref "" in
55 MatitaInit.add_cmdline_spec
56 ["-dot", Arg.Set_string dot_file,
57 "<file> Save dependency graph in dot format to the given file"];
58 MatitaInit.parse_cmdline ();
59 MatitaInit.load_configuration_file ();
61 Helm_registry.get_list Helm_registry.string "matita.includes" in
62 let args = Helm_registry.get_list Helm_registry.string "matita.args" in
65 prerr_endline "At least one .ma file must be specified";
68 let ma_files = args in
69 let bof = Hashtbl.create 10 in
70 let baseuri_of_script s =
71 try Hashtbl.find bof s
73 let b,_ = DependenciesParser.baseuri_of_script ~include_paths s in
74 Hashtbl.add bof s b; b
78 let ic = open_in ma_file in
79 let istream = Ulexing.from_utf8_channel ic in
80 let dependencies = DependenciesParser.parse_dependencies istream in
84 | DependenciesParser.UriDep uri ->
85 let uri = UriManager.string_of_uri uri in
86 if not (Http_getter_storage.is_legacy uri) then
87 Hashtbl.add uri_deps ma_file uri
88 | DependenciesParser.BaseuriDep uri ->
89 let uri = Http_getter_misc.strip_trailing_slash uri in
90 Hashtbl.add baseuri_of ma_file uri;
91 Hashtbl.add baseuri_of_inv uri ma_file
92 | DependenciesParser.IncludeDep path ->
94 let baseuri = baseuri_of_script path in
95 if not (Http_getter_storage.is_legacy baseuri) then
96 (let moo_file = obj_file_of_baseuri false baseuri in
97 Hashtbl.add include_deps ma_file moo_file;
98 Hashtbl.add include_deps_dot ma_file baseuri)
101 ("Unable to find " ^ path ^ " that is included in " ^ ma_file))
107 let dep = resolve alias (Hashtbl.find baseuri_of file) in
111 Hashtbl.add include_deps file (obj_file_of_baseuri false u)
113 prerr_endline ("File "^ file^" has no baseuri. Use set baseuri");
117 (* explode and implode from the OCaml Expert FAQ. *)
120 if i < 0 then l else exp (i - 1) (s.[i] :: l) in
121 exp (String.length s - 1) []
124 let res = String.create (List.length l) in
125 let rec imp i = function
127 | c :: l -> res.[i] <- c; imp (i + 1) l in
130 let rec aux = function
131 | x::tl1,y::tl2 when x = y -> x::(aux (tl1,tl2))
134 implode (aux (explode x,explode y))
136 let max_path = List.hd ma_files in
137 let max_path = List.fold_left gcp max_path ma_files in
138 let short x = Pcre.replace ~pat:("^"^max_path) x in
139 if !dot_file <> "" then (* generate dependency graph if required *)
141 let oc = open_out !dot_file in
142 let fmt = Format.formatter_of_out_channel oc in
143 GraphvizPp.Dot.header (* ~graph_attrs:["rankdir","LR"] *) fmt;
146 let deps = Hashtbl.find_all include_deps_dot ma_file in
150 try Some (Hashtbl.find baseuri_of_inv u)
151 with Not_found -> None)
154 let deps = List.fast_sort Pervasives.compare deps in
155 let deps = HExtlib.list_uniq deps in
156 GraphvizPp.Dot.node (short ma_file) fmt;
157 List.iter (fun dep -> GraphvizPp.Dot.edge (short ma_file) (short dep) fmt) deps)
159 GraphvizPp.Dot.trailer fmt;
162 List.iter (* (always) generate regular .depend output *)
165 let deps = Hashtbl.find_all include_deps ma_file in
166 let deps = List.fast_sort Pervasives.compare deps in
167 let deps = HExtlib.list_uniq deps in
168 let deps = ma_file :: deps in
169 let baseuri = Hashtbl.find baseuri_of ma_file in
170 let moo = obj_file_of_baseuri true baseuri in
171 Printf.printf "%s: %s\n%s: %s\n%s: %s\n%s: %s\n"
172 moo (String.concat " " deps)
173 (Filename.basename(Pcre.replace ~pat:"ma$" ~templ:"mo" ma_file)) moo
174 (Pcre.replace ~pat:"ma$" ~templ:"mo" ma_file) moo
175 (Pcre.replace ~pat:"ma$" ~templ:"mo" (short ma_file)) moo
177 prerr_endline ("File "^ma_file^" has no baseuri. Use set baseuri");