permit multiline comments and strings in macros
[bpt/coccinelle.git] / extra / maintainers.ml
1 open Common
2
3
4 type subsystem_info = subsystem list
5 and subsystem = Subsystem of (dir * maintainers) *
6 (dir * maintainers) list (* subdirs *)
7 and dir = string
8 and maintainers = string list
9
10
11 let mk_inverted_index_subsystem xs =
12 let h = Hashtbl.create 101 in
13 xs +> List.iter (function (Subsystem ((leader, emails), dirs)) ->
14 Hashtbl.add h leader leader;
15 dirs +> List.iter (fun (subdir, emails) ->
16 Hashtbl.add h subdir leader
17 ));
18 h
19
20 let subsystem_to_assoc xs =
21 xs +> List.map (function (Subsystem ((s, emails), ys)) -> s, (emails, ys))
22 let subsystem_to_hash xs =
23 xs +> subsystem_to_assoc +> Common.hash_of_list
24
25 let all_dirs_from_subsystem_info xs =
26 xs +> List.map (function (Subsystem ((s, emails), dirs)) ->
27 s::(List.map fst dirs)
28 ) +> Common.union_all
29
30
31
32 let unparse_subsystem_info xs filename =
33 Common.with_open_outfile filename (fun (pr_no_nl,chan) ->
34 let pr s = pr_no_nl (s ^ "\n") in
35
36 xs +> List.iter (function Subsystem ((s, emails), ys) ->
37 pr (sprintf "%-40s : %s" s (Common.join " ," emails));
38 ys +> List.iter (fun (s, emails) ->
39 pr (sprintf " %-40s : %s" s (Common.join " ," emails));
40 );
41 pr "";
42 )
43 )
44
45 let parse_subsystem_info filename =
46 let xs = cat filename in
47 let xs = xs +> List.map (Str.global_replace (Str.regexp "#.*") "" ) in
48 let xs = xs +> List.filter (fun s -> not (s =~ "^[ \t]*$")) in
49
50 (* split by header of section *)
51 let xs = xs +> Common.split_list_regexp "^[^ ]" in
52
53 xs +> List.map (fun (s, xs) ->
54 assert (s =~ "^\\([^ ]+\\) *: *\\(.*\\)");
55 let (dir, email) = matched2 s in
56 let emails = Common.split "[ ,]+" email in
57 let group = xs +> List.map (fun s ->
58 assert (s =~ "^[ ]+\\([^ ]+\\) *: *\\(.*\\)");
59 let (dir, email) = matched2 s in
60 let emails = Common.split "[ ,]+" email in
61 (dir, emails)
62 ) in
63 Subsystem ((dir, emails), group)
64 )
65
66
67 let generate_naive_subsystem_info dirs =
68 let dirs' = dirs +> List.map (fun s -> Common.split "/" s, s ) in
69
70 let rec aux_dirs xs =
71 match xs with
72 | [] -> []
73 | (dir_elems,s)::xs ->
74 let cond, base =
75 if List.length dir_elems >= 2 then
76 let base = Common.take 2 dir_elems in
77 (fun dir_elems' ->
78 List.length dir_elems' >= 2 && Common.take 2 dir_elems' =*= base),
79 base
80 else
81 (fun dir_elems' -> dir_elems' =*= dir_elems),
82 dir_elems
83 in
84
85 let (yes, no) = xs +> Common.partition_either (fun (dir_elems', x) ->
86 if cond dir_elems'
87 then Left (x, [])
88 else Right (dir_elems', x)
89 ) in
90 (Subsystem ((s, [""]), yes))::aux_dirs no
91 in
92 aux_dirs dirs'
93 (* old: dirs +> List.map (fun s -> Subsystem (s, "", [])) *)
94
95
96 (* a = current info file, in general manually extended; b = generated one *)
97 let check_up_to_date a b =
98 let set1 = all_dirs_from_subsystem_info a in
99 let set2 = all_dirs_from_subsystem_info b in
100 (set1 $-$ set2) +> List.iter (fun s ->
101 pr2 ("old directory disappeared: " ^ s)
102 );
103 (set2 $-$ set1) +> List.iter (fun s ->
104 pr2 ("new directory appeared: " ^ s)
105 )
106