2 * Copyright 2010, INRIA, University of Copenhagen
3 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
4 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
5 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
6 * This file is part of Coccinelle.
8 * Coccinelle is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, according to version 2 of the License.
12 * Coccinelle 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 Coccinelle. If not, see <http://www.gnu.org/licenses/>.
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
26 * Copyright 2010, INRIA, University of Copenhagen
27 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
28 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
29 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
30 * This file is part of Coccinelle.
32 * Coccinelle is free software: you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License as published by
34 * the Free Software Foundation, according to version 2 of the License.
36 * Coccinelle is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU General Public License for more details.
41 * You should have received a copy of the GNU General Public License
42 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
44 * The authors reserve the right to distribute this or future versions of
45 * Coccinelle under other licenses.
50 String.concat
"" (Str.split
(Str.regexp
"[ ]+") s
)
52 let parse_line fp l n
=
56 if Str.string_match
(Str.regexp
"#") l
0
57 then None
(* comment line *)
59 let top_split = Str.split
(Str.regexp
":") l
in
61 cocci
::first
::others
->
62 let rec loop tag
= function
65 String.concat
"\\ " (Str.split
(Str.regexp
"[ ]+") x) in
68 let splitted = Str.split
(Str.regexp
"[ ]+") first
in
69 (match List.rev
splitted with
71 let rest = loop new_tag
rest in
72 (tag
,String.concat
"\\ " (List.rev info
))::rest
73 | _
-> failwith
"bad element")
74 | _
-> failwith
"no data" in
75 Some
(cocci
,loop (drop_spaces first
) others
)
76 | _
-> failwith
(Printf.sprintf
"bad line: %s" l
)
78 let collect_lines fp i
=
83 (match parse_line fp
(input_line i
) !ln with
87 else lines := l
::!lines
90 try loop() with End_of_file
-> !lines
92 (* --------------------------------------------------------------------- *)
96 let lines = ref ([] : string list
) in
98 let l = input_line
i in
99 (if not
(Str.string_match
(Str.regexp
"#") l 0)
100 then lines := l :: !lines);
102 (try loop() with End_of_file
-> ());
106 (* --------------------------------------------------------------------- *)
107 (* same info, different categories *)
109 let discard_ambiguous lines =
110 let rec loop = function
112 | (cocci
,tags
)::rest ->
115 (function (cocci2
,tags2
) -> tags
= tags2
&& not
(cocci
= cocci2
))
118 [] -> (cocci
,tags
)::loop rest
120 Printf.printf
"ignoring ambiguity:\n";
122 (function (cocci
,tags
) ->
123 Printf.printf
"%s: %s\n" cocci
126 (function (tag
,tagval
) ->
127 Printf.sprintf
"%s: %s" tag tagval
)
129 ((cocci
,tags
)::same
);
133 (* --------------------------------------------------------------------- *)
134 (* only actually collects the rightmost element into ors *)
136 let split_or (cocci
,line
) =
137 let rev = List.rev line
in
138 (cocci
,List.rev(List.tl
rev), List.hd
rev)
140 let collect_ors fp
lines =
141 let rec loop = function
142 [] -> failwith
"no lines"
144 let (c
,k
,v
) = split_or line
in
147 let (c
,k
,v
) = split_or line
in
148 let ((c1
,k1
,v1
),rest) = loop xs
in
149 if c
= c1
&& k
= k1
&& not
(k
= [])
152 then ((c1
,k1
,v1
),rest)
153 else ((c1
,k1
,v
::v1
),rest)
154 else ((c
,k
,[v
]),((c1
,k1
,v1
)::rest)) in
155 let ((c
,k
,v
),rest) = loop lines in
156 let res = (c
,k
,v
)::rest in
161 [] -> failwith
"not possible"
162 | [x] -> (c
,k
@v
) :: prev
165 Printf.sprintf "%s:(%s)" tag
168 (List.map (function (_,vl) -> vl) v))) in
170 Printf.sprintf "%s: %s %s" c
171 (String.concat " " (List.map (function (k,v) -> k^":"^v) k))
173 if true (*List.mem attempt fp*)
176 Printf.sprintf
"\\\\\\\\\\(%s\\\\\\\\\\)"
177 (String.concat
"\\\\\\\\\\|"
179 (List.map
(function (_
,vl
) -> vl
) v
))) in
180 (c
,k
@[(tag
,vs)]) :: prev
181 else (List.map
(function vi
-> (c
,k
@[vi
])) v
) @ prev
)
184 (* --------------------------------------------------------------------- *)
187 let _ = Sys.command s
in
190 let created = ref ([] : (string * (string list
ref * out_channel
)) list
)
192 let mktag n
= Printf.sprintf
"x%d" n
194 let created_files = ref ([] : (string * int ref) list
)
196 let process_line env
(cocci
,tags
) =
197 let files = List.filter
(function (c
,f
) -> c
= cocci
) env
in
199 (function (_,cocci_file
) ->
200 let resdir = Filename.chop_extension cocci_file
in
201 (if not
(Sys.file_exists cocci_file
)
202 then failwith
"no cocci file");
204 try List.assoc
resdir !created
207 if Sys.file_exists
resdir
211 "test %s -nt %s && /bin/rm -r -f %s && mkdir %s"
212 cocci_file
resdir resdir resdir)
213 else command (Printf.sprintf
"mkdir %s" resdir);
214 let files = Printf.sprintf
"%s/files" resdir in
215 let o = open_out
files in
216 Printf.fprintf
o "all: real_all\n\n";
217 let cell = ((ref []),o) in
218 created := (resdir,cell) :: !created;
221 let temp_file = Filename.temp_file cocci
".cocci" in
222 command (Printf.sprintf
"cp %s %s" cocci_file
temp_file);
225 [] -> failwith
"no tags"
226 | (_,first_tag_val)::_ ->
228 try List.assoc
first_tag_val !created_files
231 created_files := (first_tag_val,c)::!created_files;
236 else Printf.sprintf
"%s%d" first_tag_val !cell in
238 (function (tag
,tagval
) ->
240 (Printf.sprintf
"sed s/%s/%s/ %s > %s_out; cp %s_out %s"
241 tag tagval
temp_file temp_file temp_file temp_file))
244 (Printf.sprintf
"mv %s %s/%s.cocci" temp_file resdir first_tag_val);
245 Printf.fprintf
o "%s.out:\n\tmono_spatch_linux %s.cocci ${ARGS}\n\n"
246 first_tag_val first_tag_val;
247 n
:= (first_tag_val^
".out") :: !n
)
250 (* --------------------------------------------------------------------- *)
252 let rec mkenv = function
254 | [_] -> failwith
"required arguments: file (category x cocci file)*"
255 | category
::cocci
::rest ->
256 if Filename.check_suffix cocci
".cocci"
257 then (category
,cocci
)::mkenv rest
258 else failwith
"required arguments: file (category x cocci file)*"
260 let rec upto = function
262 | n
-> (mktag (n
-1)) :: (upto (n
-1))
266 List.partition
(function "-no_ors" -> true | _ -> false)
267 (Array.to_list
Sys.argv
) in
269 match List.tl args
with
271 let rec loop prev
= function
278 let _ = Str.search_forward
(Str.regexp
".cocci") x 0 in
281 else ([],prev
::x::xs
)
283 let (fp
,env
) = loop x xs
in
286 else (prev
::fp
,env
) in
287 let (fp
,env
) = loop "" env
in
289 | _ -> failwith
"one argument expected" in
290 let fp = List.fold_left
(@) [] (List.map
process_fp fp) in
291 let i = open_in file
in
292 let lines = collect_lines fp i in
293 let lines = if no_ors
= [] then collect_ors fp lines else lines in
295 let lines = discard_ambiguous lines in
296 List.iter
(process_line env
) lines;
298 (function (resdir,(n
,o)) ->
299 Printf.fprintf
o "real_all: %s\n"
300 (String.concat
" " (List.rev !n
));
301 Printf.fprintf
o "\tcat %s > completed\n"
302 (String.concat
" " (List.rev !n
));