Release coccinelle-0.2.3rc1
[bpt/coccinelle.git] / tools / alloc_free.ml
CommitLineData
5636bb2c
C
1(*
2 * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
3 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
4 * This file is part of Coccinelle.
5 *
6 * Coccinelle is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, according to version 2 of the License.
9 *
10 * Coccinelle is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
20 *)
21
22
9f8e26f4 23(*
ae4735db 24 * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
9f8e26f4
C
25 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
26 * This file is part of Coccinelle.
27 *
28 * Coccinelle is free software: you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation, according to version 2 of the License.
31 *
32 * Coccinelle is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 *
37 * You should have received a copy of the GNU General Public License
38 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
39 *
40 * The authors reserve the right to distribute this or future versions of
41 * Coccinelle under other licenses.
42 *)
43
44
34e49164
C
45(* The following finds out for each file, how it does deallocation for each
46allocator *)
47
48let collect i =
49 let info = ref [] in
50 let rec loop _ =
51 let l = input_line i in
52 (if String.length l > 2 && String.get l 0 = '+'
53 then info := (String.sub l 1 (String.length l - 1))::!info);
54 loop() in
55 try loop()
56 with End_of_file -> List.rev !info
57
58let split l =
59 let rec loop acc = function
60 [] -> acc
61 | x::xs ->
62 if String.get x 0 = '+' (* the start of a new file *)
63 then
64 (match Str.split (Str.regexp " ") x with
65 _::x::_ -> loop ((x,[])::acc) xs
66 | _ -> failwith ("no file: "^x))
67 else
68 let acc =
69 match acc with
70 (file,instances)::rest -> (file,x::instances)::rest
71 | _ -> failwith "not possible" in
72 loop acc xs in
73 let res = List.rev (loop [] l) in
74 List.map (function (x,l) -> (x,List.rev l)) res
75
76let detect_alloc_free str l =
77 let try_add a f l =
78 let (same,diff) = List.partition (function (a1,f1) -> a = a1) l in
79 match same with
80 [(a1,f1)] -> if List.mem f f1 then l else (a1,f::f1) :: diff
81 | _ -> (a,[f])::l in
82 let rec loop acc = function
83 [] -> acc
84 | x::xs ->
85 match Str.split (Str.regexp (str^"\", ")) x with
86 _::matches ->
87 let acc =
88 List.fold_left
89 (function acc ->
90 function rest ->
91 (match Str.split (Str.regexp "[, )]+") rest with
92 alloc::free::_ -> try_add alloc free acc
93 | _ -> acc))
94 acc matches in
95 loop acc xs
96 | _ -> loop acc xs in
97 List.sort compare
98 (List.map (function (a,f) -> (a,List.sort compare f)) (loop [] l))
99
100let rec iterate str = function
101 [] -> []
102 | (x,l)::xs ->
103 List.fold_left
104 (function rest ->
105 function info ->
106 let (same,diff) =
107 List.partition (function (x1,l1) -> l1 = info) rest in
108 match same with
109 [(files,info)] -> (x::files,info)::diff
110 | _ -> ([x],info)::diff)
111 (iterate str xs) (detect_alloc_free str l)
112
113(* ------------------------------------------------------------------------ *)
114(* The following prints that information *)
115
116let print_output l =
117 List.iter
118 (function (files,(a,fs)) ->
119 List.iter (function x -> Printf.printf "%s\n" x) files;
120 Printf.printf " alloc: %s, free: %s\n" a (String.concat ", " fs);
121 Printf.printf "\n")
122 l
123
124(* ------------------------------------------------------------------------ *)
125(* The following makes a semantic patch for that information *)
126
127let sedify o generic_file dir l =
128 List.iter
129 (function (files,(a,fs)) ->
130 match fs with
131 [f] ->
132 let _ =
133 Sys.command
134 (Printf.sprintf
135 "sed s/ALLOC/%s/ %s | sed s/FREE/%s/ > %s/%s-%s.cocci\n"
136 a generic_file f dir a f) in ()
137 | _ -> ())
138 l;
139 List.iter
140 (function (files,(a,fs)) ->
141 match fs with
142 [f] -> Printf.fprintf o "mono_spatch_linux %s-%s.cocci &\n" a f
143 | _ -> ())
144 l
145
146let collect_allocs l =
147 let union =
148 List.fold_left
149 (function rest -> function x ->
150 if List.mem x rest then rest else x::rest) in
151 List.fold_left
152 (function rest ->
153 function (files,(a,fs)) ->
154 let (same,diff) =
155 List.partition (function (a1,fs1) -> a = a1) rest in
156 match same with
157 [(a1,fs1)] -> (a,union fs fs1)::diff
158 | [] -> (a,fs)::rest
159 | _ -> failwith "not possible")
160 [] l
161
162let sedify_ors o generic_file dir l =
163 let l = collect_allocs l in
164 List.iter
165 (function (a,fs) ->
166 match fs with
167 [_] | [] -> ()
168 | (f::_) ->
169 let sfs =
170 Printf.sprintf "\"\\\\\\(%s\\\\\\)\""
171 (String.concat "\\\\\\|" fs) in
172 let _ =
173 Sys.command
174 (Printf.sprintf
175 "sed s/ALLOC/%s/ %s | sed s/FREE/%s/ > %s/%s-%s_et_al.cocci\n"
176 a generic_file sfs dir a f) in ())
177 l;
178 List.iter
179 (function (a,fs) ->
180 match fs with
181 [_] | [] -> ()
182 | (f::_) ->
183 Printf.fprintf o "mono_spatch_linux %s-%s_et_al.cocci &\n" a f)
184 l
185
186(* ------------------------------------------------------------------------ *)
187
188let sed = ref false
189let gen = ref "generic2.cocci"
190let dir = ref "p2"
191let file = ref ""
192let str = ref "detected allocator"
193
194let options = [ "-sed", Arg.Set sed, "sed output";
195 "-sp", Arg.String (function x -> gen := x),
196 "detection string";
197 "-str", Arg.String (function x -> str := x),
198 "cocci file for use with sed";
199 "-dir", Arg.String (function x -> dir := x),
200 "dir for sed output"; ]
201let usage = ""
202
203let _ =
204 Arg.parse (Arg.align options) (fun x -> file := x) usage;
205 let i = open_in !file in
206 let l = collect i in
207 close_in i;
208 let l = split l in
209 let l = iterate !str l in
210 (if !sed
211 then
212 begin
213 let o = open_out (Printf.sprintf "%s/files" !dir) in
8ba84ae2 214 Printf.fprintf o "#!/bin/sh\n\n";
34e49164
C
215 sedify o !gen !dir l;
216 sedify_ors o !gen !dir l;
217 Printf.fprintf o "\nwait\n/bin/rm tmp*out\n";
218 close_out o
219 end);
220 if not !sed then print_output l