Release coccinelle-0.2.0rc1
[bpt/coccinelle.git] / parsing_cocci / top_level.ml
1 (* Reorganize the top level of a rule to be a list of either top-level
2 declarations or code dots. A function declaration is always considered top
3 level. A statement is always considered code dots. A variable declaration
4 is ambiguous. We use the heuristic that if there are code dots somewhere
5 else, then the variable declaration is at top level, otherwise it applies
6 both at top level and to all code. *)
7
8 (* This is assumed to be done before compute_lines, and thus the info on a
9 complex term is assumed to be Ast0.default_info *)
10
11 module Ast0 = Ast0_cocci
12
13 let top_dots l =
14 let circle x =
15 match Ast0.unwrap x with Ast0.Circles(_) -> true | _ -> false in
16 let star x =
17 match Ast0.unwrap x with Ast0.Stars(_) -> true | _ -> false in
18 if List.exists circle l
19 then Ast0.wrap (Ast0.CIRCLES(l))
20 else if List.exists star l
21 then Ast0.wrap (Ast0.STARS(l))
22 else Ast0.wrap (Ast0.DOTS(l))
23
24 let scan_code l =
25 let statements = ref false in
26 let rec loop = function
27 [] -> ([],[])
28 | (x::xs) as all ->
29 (match Ast0.unwrap x with
30 (Ast0.OTHER(code)) ->
31 (match Ast0.unwrap code with
32 Ast0.Decl(_) ->
33 let (front,rest) = loop xs in
34 (code::front,rest)
35 | _ ->
36 statements := true;
37 let (front,rest) = loop xs in
38 (code::front,rest))
39 | _ -> ([],all)) in
40 match loop l with
41 ([],_) as res -> res
42 | (code,rest) ->
43 if !statements = true
44 then ([Ast0.wrap(Ast0.CODE(top_dots code))],rest)
45 else
46 (List.map
47 (function d ->
48 match Ast0.unwrap d with
49 Ast0.Decl(bef,x) -> Ast0.wrap (Ast0.DECL(d))
50 | _ -> failwith "impossible")
51 code,
52 rest)
53
54 let rec scan_top_decl = function
55 [] -> ([],[])
56 | ((topdecl::rest) as all) ->
57 (match Ast0.unwrap topdecl with
58 Ast0.OTHER(_) -> ([],all)
59 | _ -> let (front,rest) = scan_top_decl rest in (topdecl::front,rest))
60
61 (* for debugging *)
62 let l2c l =
63 match Ast0.unwrap l with
64 Ast0.DECL(_) -> "decl"
65 | Ast0.CODE(_) -> "code"
66 | Ast0.FILEINFO(_,_) -> "fileinfo"
67 | Ast0.ERRORWORDS(_) -> "errorwords"
68 | Ast0.OTHER(_) -> "other"
69
70 let rec top_level l =
71 match scan_code l with
72 (code,[]) -> code
73 | (code,rest) ->
74 (match scan_top_decl rest with
75 (top_decls,[]) -> code@top_decls
76 | (top_decls,rest) -> code @ top_decls @ (top_level rest))