]> matita.cs.unibo.it Git - helm.git/blob - helm/software/matita/matitadep.ml
moved to pkg-ocaml-maint
[helm.git] / helm / software / matita / matitadep.ml
1 (* Copyright (C) 2005, HELM Team.
2  * 
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.
6  * 
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.
11  * 
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.
16  *
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,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://helm.cs.unibo.it/
24  *)
25
26 (* $Id$ *)
27
28 module GA = GrafiteAst 
29 module U = UriManager
30                 
31 let obj_file_of_baseuri writable baseuri = 
32   try 
33     LibraryMisc.obj_file_of_baseuri 
34      ~must_exist:true ~baseuri ~writable 
35   with 
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 
40 ;;
41
42 let main () =
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   let dot_file = ref "" in
54   MatitaInit.add_cmdline_spec 
55     ["-dot", Arg.Set_string dot_file,
56       "<file> Save dependency graph in dot format to the given file"];
57   MatitaInit.parse_cmdline_and_configuration_file ();
58   MatitaInit.initialize_environment ();
59   let include_paths =
60    Helm_registry.get_list Helm_registry.string "matita.includes" in
61   let args = Helm_registry.get_list Helm_registry.string "matita.args" in
62   if args = [] then
63     begin
64       prerr_endline "At least one .ma file must be specified";
65       exit 1
66     end;
67   let ma_files = args in
68   let bof = Hashtbl.create 10 in
69   let baseuri_of_script s = 
70      try Hashtbl.find bof s 
71      with Not_found -> 
72        let b,_ = DependenciesParser.baseuri_of_script ~include_paths s in
73        Hashtbl.add bof s b; b
74   in
75   List.iter
76    (fun ma_file -> 
77     let ic = open_in ma_file in
78       let istream = Ulexing.from_utf8_channel ic in
79       let dependencies = DependenciesParser.parse_dependencies istream in
80     close_in ic;
81     List.iter 
82      (function
83        | DependenciesParser.UriDep uri -> 
84           let uri = UriManager.string_of_uri uri in
85           if not (Http_getter_storage.is_legacy uri) then
86             Hashtbl.add uri_deps ma_file uri
87        | DependenciesParser.BaseuriDep uri -> 
88           let uri = Http_getter_misc.strip_trailing_slash uri in
89           Hashtbl.add baseuri_of ma_file uri;
90           Hashtbl.add baseuri_of_inv uri ma_file
91        | DependenciesParser.IncludeDep path -> 
92           try 
93             let baseuri = baseuri_of_script path in
94             if not (Http_getter_storage.is_legacy baseuri) then
95               (let moo_file = obj_file_of_baseuri false baseuri in
96               Hashtbl.add include_deps ma_file moo_file;
97               Hashtbl.add include_deps_dot ma_file baseuri)
98           with Sys_error _ -> 
99             HLog.warn 
100               ("Unable to find " ^ path ^ " that is included in " ^ ma_file))
101      dependencies)
102    ma_files;
103   Hashtbl.iter 
104     (fun file alias -> 
105       try 
106         let dep = resolve alias (Hashtbl.find baseuri_of file) in
107         match dep with 
108         | None -> ()
109         | Some u -> 
110            Hashtbl.add include_deps file (obj_file_of_baseuri false u)
111       with Not_found -> 
112         prerr_endline ("File "^ file^" has no baseuri. Use set baseuri");
113         exit 1)
114   uri_deps;
115       let gcp x y = 
116       (* explode and implode from the OCaml Expert FAQ. *)
117         let explode s =
118           let rec exp i l =
119             if i < 0 then l else exp (i - 1) (s.[i] :: l) in
120           exp (String.length s - 1) []
121         in      
122         let implode l =
123           let res = String.create (List.length l) in
124           let rec imp i = function
125           | [] -> res
126           | c :: l -> res.[i] <- c; imp (i + 1) l in
127           imp 0 l
128         in
129         let rec aux = function
130           | x::tl1,y::tl2 when x = y -> x::(aux (tl1,tl2))
131           | _ -> [] 
132         in
133         implode (aux (explode x,explode y))
134       in
135       let max_path = List.hd ma_files in 
136       let max_path = List.fold_left gcp max_path ma_files in
137       let short x = Pcre.replace ~pat:("^"^max_path) x in
138   if !dot_file <> "" then (* generate dependency graph if required *)
139     begin
140       let oc = open_out !dot_file in
141       let fmt = Format.formatter_of_out_channel oc in 
142       GraphvizPp.Dot.header (* ~graph_attrs:["rankdir","LR"] *) fmt;
143       List.iter
144        (fun ma_file -> 
145         let deps = Hashtbl.find_all include_deps_dot ma_file in
146         let deps = 
147           HExtlib.filter_map 
148             (fun u -> 
149               try Some (Hashtbl.find baseuri_of_inv u) 
150               with Not_found -> None) 
151             deps 
152         in
153         let deps = List.fast_sort Pervasives.compare deps in
154         let deps = HExtlib.list_uniq deps in
155         GraphvizPp.Dot.node (short ma_file) fmt;
156         List.iter (fun dep -> GraphvizPp.Dot.edge (short ma_file) (short dep) fmt) deps)
157        ma_files;
158       GraphvizPp.Dot.trailer fmt;
159       close_out oc
160     end;
161   List.iter (* (always) generate regular .depend output *)
162    (fun ma_file -> 
163      try
164       let deps = Hashtbl.find_all include_deps ma_file in
165       let deps = List.fast_sort Pervasives.compare deps in
166       let deps = HExtlib.list_uniq deps in
167       let deps = ma_file :: deps in
168       let baseuri = Hashtbl.find baseuri_of ma_file in
169       let moo = obj_file_of_baseuri true baseuri in
170       Printf.printf "%s: %s\n%s: %s\n%s: %s\n%s: %s\n" 
171         moo (String.concat " " deps)
172         (Filename.basename(Pcre.replace ~pat:"ma$" ~templ:"mo" ma_file)) moo
173         (Pcre.replace ~pat:"ma$" ~templ:"mo" ma_file) moo
174         (Pcre.replace ~pat:"ma$" ~templ:"mo" (short ma_file)) moo
175      with Not_found -> 
176        prerr_endline ("File "^ma_file^" has no baseuri. Use set baseuri");
177        exit 1)
178     ma_files
179