Coccinelle release 1.0.0-rc12
[bpt/coccinelle.git] / parsing_cocci / plus.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 "./plus.ml"
34e49164
C
28(* The plus fragments are converted to a list of lists of lists.
29Innermost list: Elements have type anything. For any pair of successive
30elements, n and n+1, the ending line of n is the same as the starting line
31of n+1.
32Middle lists: For any pair of successive elements, n and n+1, the ending
33line of n is one less than the starting line of n+1.
34Outer list: For any pair of successive elements, n and n+1, the ending
35line of n is more than one less than the starting line of n+1. *)
36
37(* For nests and disjs, we are relying on the fact that <... ...> ( | )
38must appear on lines by themselves, meaning that the various + fragments
39can't be contiguous to each other or to unrelated things. *)
40
41module Ast = Ast_cocci
42module V = Visitor_ast
43
44(* --------------------------------------------------------------------- *)
45
46type res =
47 Open of Ast.anything * int * int * int * int
48 | Closed of (Ast.anything * int * int * int * int) list
49
50let mcode fn = function
51 (term, Ast.PLUS(info)) ->
52 let line = info.Ast.line in
53 let lline = info.Ast.logical_line in
54 [Open (fn term,line,line,lline,lline)]
55 | _ -> [Closed []]
56
57let mk_fullType x = Ast.FullTypeTag x
58let mk_baseType x = Ast.BaseTypeTag x
59let mk_structUnion x = Ast.StructUnionTag x
60let mk_sign x = Ast.SignTag x
61let mk_ident x = Ast.IdentTag x
62let mk_expression x = Ast.ExpressionTag x
63let mk_constant x = Ast.ConstantTag x
64let mk_unaryOp x = Ast.UnaryOpTag x
65let mk_assignOp x = Ast.AssignOpTag x
66let mk_fixOp x = Ast.FixOpTag x
67let mk_binaryOp x = Ast.BinaryOpTag x
68let mk_arithOp x = Ast.ArithOpTag x
69let mk_logicalOp x = Ast.LogicalOpTag x
70let mk_declaration x = Ast.DeclarationTag x
71let mk_storage x = Ast.StorageTag x
72let mk_rule_elem x = Ast.Rule_elemTag x
73let mk_const_vol x = Ast.ConstVolTag x
74let mk_token x = Ast.Token x
75
76let get_real_start = function
77 Open (_,line,_,_,_) -> line
78 | _ -> failwith "not possible"
79
80let get_real_finish = function
81 Open (_,_,line,_,_) -> line
82 | _ -> failwith "not possible"
83
84let get_start = function
85 Open (_,_,_,line,_) -> line
86 | _ -> failwith "not possible"
87
88let get_finish = function
89 Open (_,_,_,_,line) -> line
90 | _ -> failwith "not possible"
91
92let get_option fn = function
93 None -> []
94 | Some x -> [fn x]
95
96(* --------------------------------------------------------------------- *)
97(* --------------------------------------------------------------------- *)
98(* Step 1: coalesce + terms, record starting and ending line numbers *)
99
100let rec close l =
101 let rec loop = function
102 [] -> []
103 | Open(x,start,finish,lstart,lfinish)::rest ->
104 (x,start,finish,lstart,lfinish)::(loop rest)
105 | (Closed l)::rest -> l @ (loop rest) in
106 Closed (loop l)
107
108let test term subterms =
109 if List.for_all (function Open(_,_,_,_,_) -> true | _ -> false) subterms
110 then [Open(term,
111 get_real_start (List.hd subterms),
112 get_real_finish (List.hd (List.rev subterms)),
113 get_start (List.hd subterms),
114 get_finish (List.hd (List.rev subterms)))]
115 else [close subterms]
116
117(* --------------------------------------------------------------------- *)
118(* Dots *)
119
120let dots recursor k dotlist = [close (k dotlist)]
121
122(* --------------------------------------------------------------------- *)
123(* Identifier *)
124
125let ident recursor k i = test (Ast.IdentTag i) (k i)
126
127(* --------------------------------------------------------------------- *)
128(* Expression *)
129
130let expression recursor k = function
131 Ast.DisjExpr(exps) ->
132 [close (List.concat(List.map recursor.V.combiner_expression exps))]
133 | Ast.Edots(_,_) -> [Closed []] (* must be context *)
134 | Ast.Ecircles(_,_) -> [Closed []] (* must be context *)
135 | Ast.Estars(_,_) -> [Closed []] (* must be context *)
136 | Ast.OptExp(_) | Ast.UniqueExp(_) | Ast.MultiExp(_) -> failwith "impossible"
137 | e -> test (Ast.ExpressionTag e) (k e)
138
139(* --------------------------------------------------------------------- *)
140(* Types *)
141
142and fullType recursor k ft = test (Ast.FullTypeTag ft) (k ft)
143
144and typeC recursor k t = k t
145
146(* --------------------------------------------------------------------- *)
147(* Variable declaration *)
148(* Even if the Cocci program specifies a list of declarations, they are
149 split out into multiple declarations of a single variable each. *)
150
151let declaration recursor k d = test (Ast.DeclarationTag d) (k d)
152
153(* --------------------------------------------------------------------- *)
154(* Parameter *)
155
156let parameterTypeDef recursor k = function
157 Ast.Pdots(_) -> [Closed []]
158 | Ast.Pcircles(_) -> [Closed []]
159 | p -> test (Ast.ParameterTypeDefTag p) (k p)
160
161(* --------------------------------------------------------------------- *)
162(* Top-level code *)
163
164let rec rule_elem recursor k re = test (Ast.Rule_elemTag re) (k re)
165
166let rec statement recursor k = function
167 Ast.Disj(stmt_dots_list) ->
168 [close
169 (List.concat
170 (List.map recursor.V.combiner_statement_dots stmt_dots_list))]
171 | Ast.Dots(_,_,_) -> [Closed []]
172 | Ast.Circles(_,_,_) -> [Closed []]
173 | Ast.Stars(_,_,_) -> [Closed []]
174 | s -> test (Ast.StatementTag s) (k s)
175
176let rec meta recursor k m = test (Ast.MetaTag m) (k m)
177
178let top_level recursor k = function
179 Ast.FILEINFO(_,_) -> [Closed []]
180 | Ast.ERRORWORDS(exps) -> [Closed []]
181 | t -> test (Ast.Code t) (k t)
182
183let anything recursor k a = failwith "not called"
184
185let collect_tokens =
186 let recursor =
187 V.combiner (@) []
188 (mcode mk_token) (mcode mk_constant) (mcode mk_assignOp) (mcode mk_fixOp)
189 (mcode mk_unaryOp) (mcode mk_binaryOp) (mcode mk_const_vol)
190 (mcode mk_baseType) (mcode mk_sign) (mcode mk_structUnion)
191 (mcode mk_storage) dots dots dots
192 ident expression fullType typeC parameterTypeDef declaration
193 rule_elem statement meta top_level anything in
194 recursor.V.combiner_top_level
195
196let rule code = List.concat(List.map collect_tokens code)
197
198(* --------------------------------------------------------------------- *)
199(* --------------------------------------------------------------------- *)
200(* Step 2: find neighbors *)
201
202let rec find_neighbors = function
203 [] -> []
204 | (x1,real_start1,real_finish1,start1,finish1)::rest ->
205 (match find_neighbors rest with
206 ((((x2,real_start2,real_finish2,start2,finish2)::
207 rest_inner)::rest_middle)::rest_outer)
208 as rest ->
209 if finish1 = start2
faf9a90c 210 then
34e49164
C
211 ((((x1,real_start1,real_finish1,start1,finish1)::
212 (x2,real_start2,real_finish2,start2,finish2)::rest_inner)::
213 rest_middle)::
214 rest_outer)
215 else if finish1 + 1 = start2
216 then
217 (([(x1,real_start1,real_finish1,start1,finish1)]::
218 ((x2,real_start2,real_finish2,start2,finish2)::rest_inner)::
219 rest_middle)::
220 rest_outer)
221 else [[(x1,real_start1,real_finish1,start1,finish1)]]::rest
222 | _ -> [[[(x1,real_start1,real_finish1,start1,finish1)]]])
223 (* rest must be [] *)
faf9a90c 224
34e49164
C
225(* --------------------------------------------------------------------- *)
226(* --------------------------------------------------------------------- *)
227(* Entry point *)
228
229let plus ast =
230 match close (rule ast) with
231 Closed l -> find_neighbors l
232 | _ -> failwith "impossible"