Release coccinelle-0.2.3rc1
[bpt/coccinelle.git] / parsing_cocci / top_level.ml
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
23 (*
24 * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
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
45 (* Reorganize the top level of a rule to be a list of either top-level
46 declarations or code dots. A function declaration is always considered top
47 level. A statement is always considered code dots. A variable declaration
48 is ambiguous. We use the heuristic that if there are code dots somewhere
49 else, then the variable declaration is at top level, otherwise it applies
50 both at top level and to all code. *)
51
52 (* This is assumed to be done before compute_lines, and thus the info on a
53 complex term is assumed to be Ast0.default_info *)
54
55 module Ast0 = Ast0_cocci
56
57 let top_dots l =
58 let circle x =
59 match Ast0.unwrap x with Ast0.Circles(_) -> true | _ -> false in
60 let star x =
61 match Ast0.unwrap x with Ast0.Stars(_) -> true | _ -> false in
62 if List.exists circle l
63 then Ast0.wrap (Ast0.CIRCLES(l))
64 else if List.exists star l
65 then Ast0.wrap (Ast0.STARS(l))
66 else Ast0.wrap (Ast0.DOTS(l))
67
68 let scan_code l =
69 let statements = ref false in
70 let rec loop = function
71 [] -> ([],[])
72 | (x::xs) as all ->
73 (match Ast0.unwrap x with
74 (Ast0.OTHER(code)) ->
75 (match Ast0.unwrap code with
76 Ast0.Decl(_) ->
77 let (front,rest) = loop xs in
78 (code::front,rest)
79 | _ ->
80 statements := true;
81 let (front,rest) = loop xs in
82 (code::front,rest))
83 | _ -> ([],all)) in
84 match loop l with
85 ([],_) as res -> res
86 | (code,rest) ->
87 if !statements = true
88 then ([Ast0.wrap(Ast0.CODE(top_dots code))],rest)
89 else
90 (List.map
91 (function d ->
92 match Ast0.unwrap d with
93 Ast0.Decl(bef,x) -> Ast0.wrap (Ast0.DECL(d))
94 | _ -> failwith "impossible")
95 code,
96 rest)
97
98 let rec scan_top_decl = function
99 [] -> ([],[])
100 | ((topdecl::rest) as all) ->
101 (match Ast0.unwrap topdecl with
102 Ast0.OTHER(_) -> ([],all)
103 | _ -> let (front,rest) = scan_top_decl rest in (topdecl::front,rest))
104
105 (* for debugging *)
106 let l2c l =
107 match Ast0.unwrap l with
108 Ast0.DECL(_) -> "decl"
109 | Ast0.CODE(_) -> "code"
110 | Ast0.FILEINFO(_,_) -> "fileinfo"
111 | Ast0.ERRORWORDS(_) -> "errorwords"
112 | Ast0.OTHER(_) -> "other"
113
114 let rec top_level l =
115 match scan_code l with
116 (code,[]) -> code
117 | (code,rest) ->
118 (match scan_top_decl rest with
119 (top_decls,[]) -> code@top_decls
120 | (top_decls,rest) -> code @ top_decls @ (top_level rest))