Coccinelle release 1.0.0-rc14
[bpt/coccinelle.git] / parsing_cocci / top_level.ml
CommitLineData
f537ebc4 1(*
17ba0788
C
2 * Copyright 2012, INRIA
3 * Julia Lawall, Gilles Muller
4 * Copyright 2010-2011, INRIA, University of Copenhagen
f537ebc4
C
5 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
6 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
7 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
8 * This file is part of Coccinelle.
9 *
10 * Coccinelle is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, according to version 2 of the License.
13 *
14 * Coccinelle is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
21 *
22 * The authors reserve the right to distribute this or future versions of
23 * Coccinelle under other licenses.
24 *)
25
26
feec80c3 27# 0 "./top_level.ml"
34e49164
C
28(* Reorganize the top level of a rule to be a list of either top-level
29declarations or code dots. A function declaration is always considered top
30level. A statement is always considered code dots. A variable declaration
31is ambiguous. We use the heuristic that if there are code dots somewhere
32else, then the variable declaration is at top level, otherwise it applies
33both at top level and to all code. *)
34
35(* This is assumed to be done before compute_lines, and thus the info on a
36complex term is assumed to be Ast0.default_info *)
37
38module Ast0 = Ast0_cocci
39
40let top_dots l =
41 let circle x =
42 match Ast0.unwrap x with Ast0.Circles(_) -> true | _ -> false in
43 let star x =
44 match Ast0.unwrap x with Ast0.Stars(_) -> true | _ -> false in
45 if List.exists circle l
46 then Ast0.wrap (Ast0.CIRCLES(l))
47 else if List.exists star l
48 then Ast0.wrap (Ast0.STARS(l))
49 else Ast0.wrap (Ast0.DOTS(l))
50
65038c61
C
51let rec is_decl s =
52 match Ast0.unwrap s with
53 Ast0.Decl(_,e) -> true
54 | _ -> false
55
56let isonly f l = match Ast0.undots l with [s] -> f s | _ -> false
57let isall f l = List.for_all (isonly f) l
58
59let rec is_toplevel s =
60 match Ast0.unwrap s with
61 Ast0.Decl(_,e) -> true
62 | Ast0.FunDecl(_,_,_,_,_,_,_,_,_) -> true
63 | Ast0.Disj(_,stmts,_,_) -> isall is_toplevel stmts
64 | Ast0.ExprStatement(Some fc,_) -> false
65 | Ast0.Include(_,_) -> true
66 | Ast0.Undef(_,_) -> true
67 | Ast0.Define(_,_,_,_) -> true
68 | _ -> false
69
70let scan_code must_be_code l =
34e49164
C
71 let rec loop = function
72 [] -> ([],[])
73 | (x::xs) as all ->
65038c61
C
74 (match Ast0.unwrap x with
75 (Ast0.OTHER(code)) ->
76 let (front,rest) = loop xs in
77 (code::front,rest)
78 | _ -> ([],all)) in
34e49164
C
79 match loop l with
80 ([],_) as res -> res
81 | (code,rest) ->
65038c61
C
82 (match code with
83 | [x] when is_decl x && must_be_code ->
84 ([Ast0.wrap(Ast0.NONDECL x)],rest)
85 | _ when List.for_all is_toplevel code ->
86 ([Ast0.wrap(Ast0.TOPCODE(top_dots code))],rest)
87 | _ ->
88 ([Ast0.wrap(Ast0.CODE(top_dots code))],rest))
34e49164
C
89
90let rec scan_top_decl = function
91 [] -> ([],[])
92 | ((topdecl::rest) as all) ->
93 (match Ast0.unwrap topdecl with
94 Ast0.OTHER(_) -> ([],all)
65038c61
C
95 | _ ->
96 let (front,rest) = scan_top_decl rest
97 in (topdecl::front,rest))
34e49164
C
98
99(* for debugging *)
100let l2c l =
101 match Ast0.unwrap l with
65038c61 102 Ast0.NONDECL(_) -> "decl"
34e49164 103 | Ast0.CODE(_) -> "code"
65038c61 104 | Ast0.TOPCODE(_) -> "code"
34e49164
C
105 | Ast0.FILEINFO(_,_) -> "fileinfo"
106 | Ast0.ERRORWORDS(_) -> "errorwords"
107 | Ast0.OTHER(_) -> "other"
108
65038c61
C
109let rec top_level must_be_code l =
110 match scan_code must_be_code l with
34e49164
C
111 (code,[]) -> code
112 | (code,rest) ->
113 (match scan_top_decl rest with
114 (top_decls,[]) -> code@top_decls
65038c61
C
115 | (top_decls,rest) -> code @ top_decls @ (top_level must_be_code rest))
116
117let clean l =
118 List.map
119 (function tl ->
120 match Ast0.unwrap tl with
121 Ast0.TOPCODE x -> Ast0.rewrap tl (Ast0.CODE x)
122 | _ -> tl)
123 l