Coccinelle release 1.0.0-rc3
[bpt/coccinelle.git] / parsing_cocci / top_level.ml
CommitLineData
f537ebc4
C
1(*
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.
7 *
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.
11 *
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.
16 *
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/>.
19 *
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
22 *)
23
24
34e49164
C
25(* Reorganize the top level of a rule to be a list of either top-level
26declarations or code dots. A function declaration is always considered top
27level. A statement is always considered code dots. A variable declaration
28is ambiguous. We use the heuristic that if there are code dots somewhere
29else, then the variable declaration is at top level, otherwise it applies
30both at top level and to all code. *)
31
32(* This is assumed to be done before compute_lines, and thus the info on a
33complex term is assumed to be Ast0.default_info *)
34
35module Ast0 = Ast0_cocci
36
37let top_dots l =
38 let circle x =
39 match Ast0.unwrap x with Ast0.Circles(_) -> true | _ -> false in
40 let star x =
41 match Ast0.unwrap x with Ast0.Stars(_) -> true | _ -> false in
42 if List.exists circle l
43 then Ast0.wrap (Ast0.CIRCLES(l))
44 else if List.exists star l
45 then Ast0.wrap (Ast0.STARS(l))
46 else Ast0.wrap (Ast0.DOTS(l))
47
65038c61
C
48let rec is_decl s =
49 match Ast0.unwrap s with
50 Ast0.Decl(_,e) -> true
51 | _ -> false
52
53let isonly f l = match Ast0.undots l with [s] -> f s | _ -> false
54let isall f l = List.for_all (isonly f) l
55
56let rec is_toplevel s =
57 match Ast0.unwrap s with
58 Ast0.Decl(_,e) -> true
59 | Ast0.FunDecl(_,_,_,_,_,_,_,_,_) -> true
60 | Ast0.Disj(_,stmts,_,_) -> isall is_toplevel stmts
61 | Ast0.ExprStatement(Some fc,_) -> false
62 | Ast0.Include(_,_) -> true
63 | Ast0.Undef(_,_) -> true
64 | Ast0.Define(_,_,_,_) -> true
65 | _ -> false
66
67let scan_code must_be_code l =
34e49164
C
68 let rec loop = function
69 [] -> ([],[])
70 | (x::xs) as all ->
65038c61
C
71 (match Ast0.unwrap x with
72 (Ast0.OTHER(code)) ->
73 let (front,rest) = loop xs in
74 (code::front,rest)
75 | _ -> ([],all)) in
34e49164
C
76 match loop l with
77 ([],_) as res -> res
78 | (code,rest) ->
65038c61
C
79 (match code with
80 | [x] when is_decl x && must_be_code ->
81 ([Ast0.wrap(Ast0.NONDECL x)],rest)
82 | _ when List.for_all is_toplevel code ->
83 ([Ast0.wrap(Ast0.TOPCODE(top_dots code))],rest)
84 | _ ->
85 ([Ast0.wrap(Ast0.CODE(top_dots code))],rest))
34e49164
C
86
87let rec scan_top_decl = function
88 [] -> ([],[])
89 | ((topdecl::rest) as all) ->
90 (match Ast0.unwrap topdecl with
91 Ast0.OTHER(_) -> ([],all)
65038c61
C
92 | _ ->
93 let (front,rest) = scan_top_decl rest
94 in (topdecl::front,rest))
34e49164
C
95
96(* for debugging *)
97let l2c l =
98 match Ast0.unwrap l with
65038c61 99 Ast0.NONDECL(_) -> "decl"
34e49164 100 | Ast0.CODE(_) -> "code"
65038c61 101 | Ast0.TOPCODE(_) -> "code"
34e49164
C
102 | Ast0.FILEINFO(_,_) -> "fileinfo"
103 | Ast0.ERRORWORDS(_) -> "errorwords"
104 | Ast0.OTHER(_) -> "other"
105
65038c61
C
106let rec top_level must_be_code l =
107 match scan_code must_be_code l with
34e49164
C
108 (code,[]) -> code
109 | (code,rest) ->
110 (match scan_top_decl rest with
111 (top_decls,[]) -> code@top_decls
65038c61
C
112 | (top_decls,rest) -> code @ top_decls @ (top_level must_be_code rest))
113
114let clean l =
115 List.map
116 (function tl ->
117 match Ast0.unwrap tl with
118 Ast0.TOPCODE x -> Ast0.rewrap tl (Ast0.CODE x)
119 | _ -> tl)
120 l