Release coccinelle-0.2.0
[bpt/coccinelle.git] / parsing_cocci / top_level.ml
CommitLineData
9f8e26f4
C
1(*
2 * Copyright 2005-2009, 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
34e49164
C
23(* Reorganize the top level of a rule to be a list of either top-level
24declarations or code dots. A function declaration is always considered top
25level. A statement is always considered code dots. A variable declaration
26is ambiguous. We use the heuristic that if there are code dots somewhere
27else, then the variable declaration is at top level, otherwise it applies
28both at top level and to all code. *)
29
30(* This is assumed to be done before compute_lines, and thus the info on a
31complex term is assumed to be Ast0.default_info *)
32
33module Ast0 = Ast0_cocci
34
35let top_dots l =
36 let circle x =
37 match Ast0.unwrap x with Ast0.Circles(_) -> true | _ -> false in
38 let star x =
39 match Ast0.unwrap x with Ast0.Stars(_) -> true | _ -> false in
40 if List.exists circle l
41 then Ast0.wrap (Ast0.CIRCLES(l))
42 else if List.exists star l
43 then Ast0.wrap (Ast0.STARS(l))
44 else Ast0.wrap (Ast0.DOTS(l))
45
46let scan_code l =
47 let statements = ref false in
48 let rec loop = function
49 [] -> ([],[])
50 | (x::xs) as all ->
51 (match Ast0.unwrap x with
52 (Ast0.OTHER(code)) ->
53 (match Ast0.unwrap code with
54 Ast0.Decl(_) ->
55 let (front,rest) = loop xs in
56 (code::front,rest)
57 | _ ->
58 statements := true;
59 let (front,rest) = loop xs in
60 (code::front,rest))
61 | _ -> ([],all)) in
62 match loop l with
63 ([],_) as res -> res
64 | (code,rest) ->
65 if !statements = true
66 then ([Ast0.wrap(Ast0.CODE(top_dots code))],rest)
67 else
68 (List.map
69 (function d ->
70 match Ast0.unwrap d with
71 Ast0.Decl(bef,x) -> Ast0.wrap (Ast0.DECL(d))
72 | _ -> failwith "impossible")
73 code,
74 rest)
75
76let rec scan_top_decl = function
77 [] -> ([],[])
78 | ((topdecl::rest) as all) ->
79 (match Ast0.unwrap topdecl with
80 Ast0.OTHER(_) -> ([],all)
81 | _ -> let (front,rest) = scan_top_decl rest in (topdecl::front,rest))
82
83(* for debugging *)
84let l2c l =
85 match Ast0.unwrap l with
86 Ast0.DECL(_) -> "decl"
87 | Ast0.CODE(_) -> "code"
88 | Ast0.FILEINFO(_,_) -> "fileinfo"
89 | Ast0.ERRORWORDS(_) -> "errorwords"
90 | Ast0.OTHER(_) -> "other"
91
92let rec top_level l =
93 match scan_code l with
94 (code,[]) -> code
95 | (code,rest) ->
96 (match scan_top_decl rest with
97 (top_decls,[]) -> code@top_decls
98 | (top_decls,rest) -> code @ top_decls @ (top_level rest))