Coccinelle release 1.0.0-rc3
[bpt/coccinelle.git] / engine / cocci_vs_c.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
25open Common
26
27module A = Ast_cocci
28module B = Ast_c
29
30module F = Control_flow_c
31
485bce71
C
32module Flag = Flag_matcher
33
34e49164
C
34(*****************************************************************************)
35(* Wrappers *)
36(*****************************************************************************)
708f4980 37let pr2, pr2_once = Common.mk_pr2_wrappers Flag_matcher.verbose_matcher
34e49164 38
c491d8ee
C
39let (+++) a b = match a with Some x -> Some x | None -> b
40
190f1acf
C
41let error ii str =
42 match ii with
43 [] -> failwith str
6756e19d
C
44 | ii::_ ->
45 failwith
46 (Printf.sprintf "%s: %d: %s"
47 (Ast_c.file_of_info ii) (Ast_c.line_of_info ii) str)
190f1acf 48
34e49164
C
49(*****************************************************************************)
50(* Helpers *)
51(*****************************************************************************)
52
53type sequence = Ordered | Unordered
54
951c7801
C
55let seqstyle eas =
56 match A.unwrap eas with
57 | A.DOTS _ -> Ordered
58 | A.CIRCLES _ -> Unordered
34e49164
C
59 | A.STARS _ -> failwith "not handling stars"
60
61let (redots : 'a A.dots -> 'a list -> 'a A.dots)=fun eas easundots ->
ae4735db
C
62 A.rewrap eas (
63 match A.unwrap eas with
34e49164
C
64 | A.DOTS _ -> A.DOTS easundots
65 | A.CIRCLES _ -> A.CIRCLES easundots
66 | A.STARS _ -> A.STARS easundots
67 )
68
69
ae4735db
C
70let (need_unordered_initialisers : B.initialiser B.wrap2 list -> bool) =
71 fun ibs ->
72 ibs +> List.exists (fun (ib, icomma) ->
34e49164 73 match B.unwrap ib with
ae4735db
C
74 | B.InitDesignators _
75 | B.InitFieldOld _
34e49164 76 | B.InitIndexOld _
90aeb998 77 -> true
ae4735db
C
78 | B.InitExpr _
79 | B.InitList _
90aeb998 80 -> false)
34e49164
C
81
82(* For the #include <linux/...> in the .cocci, need to find where is
83 * the '+' attached to this element, to later find the first concrete
c491d8ee 84 * #include <linux/xxx.h> or last one in the series of #includes in the
34e49164
C
85 * .c.
86 *)
ae4735db 87type include_requirement =
34e49164 88 | IncludeMcodeBefore
ae4735db 89 | IncludeMcodeAfter
34e49164
C
90 | IncludeNothing
91
92
ae4735db 93
34e49164 94(* todo? put in semantic_c.ml *)
ae4735db
C
95type info_ident =
96 | Function
34e49164
C
97 | LocalFunction (* entails Function *)
98 | DontKnow
99
100
101let term mc = A.unwrap_mcode mc
102let mcodekind mc = A.get_mcodekind mc
103
104
105let mcode_contain_plus = function
106 | A.CONTEXT (_,A.NOTHING) -> false
107 | A.CONTEXT _ -> true
8babbc8f
C
108 | A.MINUS (_,_,_,A.NOREPLACEMENT) -> false
109 | A.MINUS (_,_,_,A.REPLACEMENT _) -> true (* repl is nonempty *)
951c7801 110 | A.PLUS _ -> raise Impossible
34e49164
C
111
112let mcode_simple_minus = function
8babbc8f 113 | A.MINUS (_,_,_,A.NOREPLACEMENT) -> true
34e49164
C
114 | _ -> false
115
116
117(* In transformation.ml sometime I build some mcodekind myself and
118 * julia has put None for the pos. But there is no possible raise
119 * NoMatch in those cases because it is for the minusall trick or for
120 * the distribute, so either have to build those pos, in fact a range,
121 * because for the distribute have to erase a fullType with one
122 * mcodekind, or add an argument to tag_with_mck such as "safe" that
123 * don't do the check_pos. Hence this DontCarePos constructor. *)
124
ae4735db
C
125let minusizer =
126 ("fake","fake"),
708f4980 127 {A.line = 0; A.column =0; A.strbef=[]; A.straft=[];},
8babbc8f 128 (A.MINUS(A.DontCarePos,[],A.ALLMINUS,A.NOREPLACEMENT)),
8f657093 129 []
34e49164 130
ae4735db 131let generalize_mcode ia =
34e49164
C
132 let (s1, i, mck, pos) = ia in
133 let new_mck =
134 match mck with
951c7801 135 | A.PLUS _ -> raise Impossible
ae4735db 136 | A.CONTEXT (A.NoPos,x) ->
34e49164 137 A.CONTEXT (A.DontCarePos,x)
ae4735db 138 | A.MINUS (A.NoPos,inst,adj,x) ->
708f4980 139 A.MINUS (A.DontCarePos,inst,adj,x)
485bce71 140
ae4735db 141 | A.CONTEXT ((A.FixPos _|A.DontCarePos), _)
708f4980 142 | A.MINUS ((A.FixPos _|A.DontCarePos), _, _, _)
485bce71
C
143 ->
144 raise Impossible
145 in
34e49164
C
146 (s1, i, new_mck, pos)
147
148
149
150(*---------------------------------------------------------------------------*)
151
152(* 0x0 is equivalent to 0, value format isomorphism *)
ae4735db
C
153let equal_c_int s1 s2 =
154 try
b1b2de81 155 int_of_string s1 =|= int_of_string s2
ae4735db 156 with Failure("int_of_string") ->
34e49164
C
157 s1 =$= s2
158
159
160
161(*---------------------------------------------------------------------------*)
162(* Normally A should reuse some types of Ast_c, so those
163 * functions should not exist.
ae4735db 164 *
34e49164
C
165 * update: but now Ast_c depends on A, so can't make too
166 * A depends on Ast_c, so have to stay with those equal_xxx
ae4735db 167 * functions.
34e49164
C
168 *)
169
ae4735db 170let equal_unaryOp a b =
34e49164
C
171 match a, b with
172 | A.GetRef , B.GetRef -> true
8babbc8f 173 | A.GetRefLabel, B.GetRefLabel -> true
34e49164
C
174 | A.DeRef , B.DeRef -> true
175 | A.UnPlus , B.UnPlus -> true
176 | A.UnMinus , B.UnMinus -> true
177 | A.Tilde , B.Tilde -> true
178 | A.Not , B.Not -> true
8babbc8f
C
179 | _, (B.Not|B.Tilde|B.UnMinus|B.UnPlus|B.DeRef|B.GetRef|B.GetRefLabel) ->
180 false
485bce71 181
34e49164 182
ae4735db
C
183
184let equal_arithOp a b =
34e49164
C
185 match a, b with
186 | A.Plus , B.Plus -> true
187 | A.Minus , B.Minus -> true
188 | A.Mul , B.Mul -> true
189 | A.Div , B.Div -> true
190 | A.Mod , B.Mod -> true
191 | A.DecLeft , B.DecLeft -> true
192 | A.DecRight , B.DecRight -> true
193 | A.And , B.And -> true
194 | A.Or , B.Or -> true
195 | A.Xor , B.Xor -> true
485bce71
C
196 | _, (B.Xor|B.Or|B.And|B.DecRight|B.DecLeft|B.Mod|B.Div|B.Mul|B.Minus|B.Plus)
197 -> false
34e49164 198
ae4735db 199let equal_logicalOp a b =
34e49164
C
200 match a, b with
201 | A.Inf , B.Inf -> true
202 | A.Sup , B.Sup -> true
203 | A.InfEq , B.InfEq -> true
204 | A.SupEq , B.SupEq -> true
205 | A.Eq , B.Eq -> true
206 | A.NotEq , B.NotEq -> true
207 | A.AndLog , B.AndLog -> true
208 | A.OrLog , B.OrLog -> true
485bce71
C
209 | _, (B.OrLog|B.AndLog|B.NotEq|B.Eq|B.SupEq|B.InfEq|B.Sup|B.Inf)
210 -> false
34e49164 211
ae4735db 212let equal_assignOp a b =
34e49164
C
213 match a, b with
214 | A.SimpleAssign, B.SimpleAssign -> true
215 | A.OpAssign a, B.OpAssign b -> equal_arithOp a b
485bce71 216 | _, (B.OpAssign _|B.SimpleAssign) -> false
34e49164 217
ae4735db 218let equal_fixOp a b =
34e49164
C
219 match a, b with
220 | A.Dec, B.Dec -> true
221 | A.Inc, B.Inc -> true
485bce71 222 | _, (B.Inc|B.Dec) -> false
34e49164 223
ae4735db 224let equal_binaryOp a b =
34e49164
C
225 match a, b with
226 | A.Arith a, B.Arith b -> equal_arithOp a b
227 | A.Logical a, B.Logical b -> equal_logicalOp a b
485bce71 228 | _, (B.Logical _ | B.Arith _) -> false
34e49164 229
ae4735db 230let equal_structUnion a b =
34e49164
C
231 match a, b with
232 | A.Struct, B.Struct -> true
233 | A.Union, B.Union -> true
485bce71 234 | _, (B.Struct|B.Union) -> false
34e49164 235
ae4735db 236let equal_sign a b =
34e49164
C
237 match a, b with
238 | A.Signed, B.Signed -> true
239 | A.Unsigned, B.UnSigned -> true
485bce71 240 | _, (B.UnSigned|B.Signed) -> false
34e49164 241
ae4735db 242let equal_storage a b =
34e49164
C
243 match a, b with
244 | A.Static , B.Sto B.Static
245 | A.Auto , B.Sto B.Auto
246 | A.Register , B.Sto B.Register
ae4735db 247 | A.Extern , B.Sto B.Extern
34e49164 248 -> true
485bce71
C
249 | _, (B.NoSto | B.StoTypedef) -> false
250 | _, (B.Sto (B.Register|B.Static|B.Auto|B.Extern)) -> false
251
34e49164
C
252
253(*---------------------------------------------------------------------------*)
254
255let equal_metavarval valu valu' =
256 match valu, valu' with
5636bb2c 257 | Ast_c.MetaIdVal (a,_), Ast_c.MetaIdVal (b,_) -> a =$= b
34e49164 258 | Ast_c.MetaFuncVal a, Ast_c.MetaFuncVal b -> a =$= b
ae4735db 259 | Ast_c.MetaLocalFuncVal a, Ast_c.MetaLocalFuncVal b ->
34e49164
C
260 (* do something more ? *)
261 a =$= b
262
263 (* al_expr before comparing !!! and accept when they match.
264 * Note that here we have Astc._expression, so it is a match
265 * modulo isomorphism (there is no metavariable involved here,
266 * just isomorphisms). => TODO call isomorphism_c_c instead of
267 * =*=. Maybe would be easier to transform ast_c in ast_cocci
268 * and call the iso engine of julia. *)
5636bb2c 269 | Ast_c.MetaExprVal (a,_), Ast_c.MetaExprVal (b,_) ->
34e49164 270 Lib_parsing_c.al_expr a =*= Lib_parsing_c.al_expr b
ae4735db 271 | Ast_c.MetaExprListVal a, Ast_c.MetaExprListVal b ->
34e49164
C
272 Lib_parsing_c.al_arguments a =*= Lib_parsing_c.al_arguments b
273
413ffc02
C
274 | Ast_c.MetaDeclVal a, Ast_c.MetaDeclVal b ->
275 Lib_parsing_c.al_declaration a =*= Lib_parsing_c.al_declaration b
276 | Ast_c.MetaFieldVal a, Ast_c.MetaFieldVal b ->
277 Lib_parsing_c.al_field a =*= Lib_parsing_c.al_field b
190f1acf
C
278 | Ast_c.MetaFieldListVal a, Ast_c.MetaFieldListVal b ->
279 Lib_parsing_c.al_fields a =*= Lib_parsing_c.al_fields b
ae4735db 280 | Ast_c.MetaStmtVal a, Ast_c.MetaStmtVal b ->
34e49164 281 Lib_parsing_c.al_statement a =*= Lib_parsing_c.al_statement b
ae4735db 282 | Ast_c.MetaInitVal a, Ast_c.MetaInitVal b ->
113803cf 283 Lib_parsing_c.al_init a =*= Lib_parsing_c.al_init b
8f657093
C
284 | Ast_c.MetaInitListVal a, Ast_c.MetaInitListVal b ->
285 Lib_parsing_c.al_inits a =*= Lib_parsing_c.al_inits b
ae4735db 286 | Ast_c.MetaTypeVal a, Ast_c.MetaTypeVal b ->
34e49164
C
287 (* old: Lib_parsing_c.al_type a =*= Lib_parsing_c.al_type b *)
288 C_vs_c.eq_type a b
ae4735db 289
34e49164
C
290 | Ast_c.MetaListlenVal a, Ast_c.MetaListlenVal b -> a =|= b
291
ae4735db 292 | Ast_c.MetaParamVal a, Ast_c.MetaParamVal b ->
34e49164 293 Lib_parsing_c.al_param a =*= Lib_parsing_c.al_param b
ae4735db 294 | Ast_c.MetaParamListVal a, Ast_c.MetaParamListVal b ->
34e49164
C
295 Lib_parsing_c.al_params a =*= Lib_parsing_c.al_params b
296
ae4735db 297 | Ast_c.MetaPosVal (posa1,posa2), Ast_c.MetaPosVal (posb1,posb2) ->
34e49164 298 Ast_cocci.equal_pos posa1 posb1 && Ast_cocci.equal_pos posa2 posb2
951c7801 299
34e49164
C
300 | Ast_c.MetaPosValList l1, Ast_c.MetaPosValList l2 ->
301 List.exists
485bce71 302 (function (fla,cea,posa1,posa2) ->
34e49164 303 List.exists
485bce71 304 (function (flb,ceb,posb1,posb2) ->
b1b2de81 305 fla =$= flb && cea =$= ceb &&
34e49164
C
306 Ast_c.equal_posl posa1 posb1 && Ast_c.equal_posl posa2 posb2)
307 l2)
308 l1
34e49164 309
485bce71 310 | (B.MetaPosValList _|B.MetaListlenVal _|B.MetaPosVal _|B.MetaStmtVal _
190f1acf 311 |B.MetaDeclVal _ |B.MetaFieldVal _ |B.MetaFieldListVal _
8f657093 312 |B.MetaTypeVal _ |B.MetaInitVal _ |B.MetaInitListVal _
485bce71
C
313 |B.MetaParamListVal _|B.MetaParamVal _|B.MetaExprListVal _
314 |B.MetaExprVal _|B.MetaLocalFuncVal _|B.MetaFuncVal _|B.MetaIdVal _
315 ), _
316 -> raise Impossible
34e49164 317
002099fc
C
318(* probably only one argument needs to be stripped, because inherited
319metavariables containing expressions are stripped in advance. But don't
320know which one is which... *)
321let equal_inh_metavarval valu valu'=
978fd7e5 322 match valu, valu' with
5636bb2c 323 | Ast_c.MetaIdVal (a,_), Ast_c.MetaIdVal (b,_) -> a =$= b
978fd7e5 324 | Ast_c.MetaFuncVal a, Ast_c.MetaFuncVal b -> a =$= b
ae4735db 325 | Ast_c.MetaLocalFuncVal a, Ast_c.MetaLocalFuncVal b ->
978fd7e5
C
326 (* do something more ? *)
327 a =$= b
328
329 (* al_expr before comparing !!! and accept when they match.
330 * Note that here we have Astc._expression, so it is a match
331 * modulo isomorphism (there is no metavariable involved here,
332 * just isomorphisms). => TODO call isomorphism_c_c instead of
333 * =*=. Maybe would be easier to transform ast_c in ast_cocci
334 * and call the iso engine of julia. *)
5636bb2c 335 | Ast_c.MetaExprVal (a,_), Ast_c.MetaExprVal (b,_) ->
978fd7e5 336 Lib_parsing_c.al_inh_expr a =*= Lib_parsing_c.al_inh_expr b
ae4735db 337 | Ast_c.MetaExprListVal a, Ast_c.MetaExprListVal b ->
978fd7e5
C
338 Lib_parsing_c.al_inh_arguments a =*= Lib_parsing_c.al_inh_arguments b
339
413ffc02
C
340 | Ast_c.MetaDeclVal a, Ast_c.MetaDeclVal b ->
341 Lib_parsing_c.al_inh_declaration a =*= Lib_parsing_c.al_inh_declaration b
342 | Ast_c.MetaFieldVal a, Ast_c.MetaFieldVal b ->
343 Lib_parsing_c.al_inh_field a =*= Lib_parsing_c.al_inh_field b
190f1acf
C
344 | Ast_c.MetaFieldListVal a, Ast_c.MetaFieldListVal b ->
345 Lib_parsing_c.al_inh_field_list a =*= Lib_parsing_c.al_inh_field_list b
ae4735db 346 | Ast_c.MetaStmtVal a, Ast_c.MetaStmtVal b ->
978fd7e5 347 Lib_parsing_c.al_inh_statement a =*= Lib_parsing_c.al_inh_statement b
ae4735db 348 | Ast_c.MetaInitVal a, Ast_c.MetaInitVal b ->
978fd7e5 349 Lib_parsing_c.al_inh_init a =*= Lib_parsing_c.al_inh_init b
8f657093
C
350 | Ast_c.MetaInitListVal a, Ast_c.MetaInitListVal b ->
351 Lib_parsing_c.al_inh_inits a =*= Lib_parsing_c.al_inh_inits b
ae4735db 352 | Ast_c.MetaTypeVal a, Ast_c.MetaTypeVal b ->
978fd7e5
C
353 (* old: Lib_parsing_c.al_inh_type a =*= Lib_parsing_c.al_inh_type b *)
354 C_vs_c.eq_type a b
ae4735db 355
978fd7e5
C
356 | Ast_c.MetaListlenVal a, Ast_c.MetaListlenVal b -> a =|= b
357
ae4735db 358 | Ast_c.MetaParamVal a, Ast_c.MetaParamVal b ->
978fd7e5 359 Lib_parsing_c.al_param a =*= Lib_parsing_c.al_param b
ae4735db 360 | Ast_c.MetaParamListVal a, Ast_c.MetaParamListVal b ->
978fd7e5
C
361 Lib_parsing_c.al_params a =*= Lib_parsing_c.al_params b
362
ae4735db 363 | Ast_c.MetaPosVal (posa1,posa2), Ast_c.MetaPosVal (posb1,posb2) ->
978fd7e5 364 Ast_cocci.equal_pos posa1 posb1 && Ast_cocci.equal_pos posa2 posb2
ae4735db 365
978fd7e5
C
366 | Ast_c.MetaPosValList l1, Ast_c.MetaPosValList l2 ->
367 List.exists
368 (function (fla,cea,posa1,posa2) ->
369 List.exists
370 (function (flb,ceb,posb1,posb2) ->
371 fla =$= flb && cea =$= ceb &&
372 Ast_c.equal_posl posa1 posb1 && Ast_c.equal_posl posa2 posb2)
373 l2)
374 l1
375
376 | (B.MetaPosValList _|B.MetaListlenVal _|B.MetaPosVal _|B.MetaStmtVal _
190f1acf 377 |B.MetaDeclVal _ |B.MetaFieldVal _ |B.MetaFieldListVal _
8f657093 378 |B.MetaTypeVal _ |B.MetaInitVal _ |B.MetaInitListVal _
978fd7e5
C
379 |B.MetaParamListVal _|B.MetaParamVal _|B.MetaExprListVal _
380 |B.MetaExprVal _|B.MetaLocalFuncVal _|B.MetaFuncVal _|B.MetaIdVal _
381 ), _
382 -> raise Impossible
383
34e49164
C
384
385(*---------------------------------------------------------------------------*)
386(* could put in ast_c.ml, next to the split/unsplit_comma *)
ae4735db 387let split_signb_baseb_ii (baseb, ii) =
34e49164
C
388 let iis = ii +> List.map (fun info -> (B.str_of_info info), info) in
389 match baseb, iis with
ae4735db 390
34e49164 391 | B.Void, ["void",i1] -> None, [i1]
ae4735db 392
34e49164
C
393 | B.FloatType (B.CFloat),["float",i1] -> None, [i1]
394 | B.FloatType (B.CDouble),["double",i1] -> None, [i1]
395 | B.FloatType (B.CLongDouble),["long",i1;"double",i2] -> None,[i1;i2]
ae4735db 396
34e49164
C
397 | B.IntType (B.CChar), ["char",i1] -> None, [i1]
398
399
b1b2de81
C
400 | B.IntType (B.Si (sign, base)), xs ->
401 let (signed,rest) =
402 match (sign,xs) with
403 (_,[]) -> None,[]
404 | (B.Signed,(("signed",i1)::rest)) -> (Some (B.Signed,i1),rest)
405 | (B.Signed,rest) -> (None,rest)
406 | (B.UnSigned,(("unsigned",i1)::rest)) -> (Some (B.UnSigned,i1),rest)
407 | (B.UnSigned,rest) -> (* is this case possible? *) (None,rest) in
408 (* The original code only allowed explicit signed and unsigned for char,
409 while this code allows char by itself. Not sure that needs to be
410 checked for here. If it does, then add a special case. *)
411 let base_res =
412 match (base,rest) with
413 B.CInt, ["int",i1] -> [i1]
414 | B.CInt, [] -> []
415
416 | B.CInt, ["",i1] -> (* no type is specified at all *)
417 (match i1.B.pinfo with
418 B.FakeTok(_,_) -> []
190f1acf
C
419 | _ -> error [i1] ("unrecognized signed int: "^
420 (String.concat " "(List.map fst iis))))
b1b2de81
C
421
422 | B.CChar2, ["char",i2] -> [i2]
423
424 | B.CShort, ["short",i1] -> [i1]
425 | B.CShort, ["short",i1;"int",i2] -> [i1;i2]
426
427 | B.CLong, ["long",i1] -> [i1]
428 | B.CLong, ["long",i1;"int",i2] -> [i1;i2]
429
430 | B.CLongLong, ["long",i1;"long",i2] -> [i1;i2]
431 | B.CLongLong, ["long",i1;"long",i2;"int",i3] -> [i1;i2;i3]
432
433 | _ ->
190f1acf
C
434 error (List.map snd iis)
435 ("strange type1, maybe because of weird order: "^
436 (String.concat " " (List.map fst iis))) in
b1b2de81 437 (signed,base_res)
1eddfd50
C
438
439 | B.SizeType, ["size_t",i1] -> None, [i1]
440 | B.SSizeType, ["ssize_t",i1] -> None, [i1]
441 | B.PtrDiffType, ["ptrdiff_t",i1] -> None, [i1]
442
190f1acf
C
443 | _ ->
444 error (List.map snd iis)
445 ("strange type2, maybe because of weird order: "^
446 (String.concat " " (List.map fst iis)))
34e49164
C
447
448(*---------------------------------------------------------------------------*)
449
ae4735db 450let rec unsplit_icomma xs =
34e49164
C
451 match xs with
452 | [] -> []
ae4735db 453 | x::y::xs ->
34e49164 454 (match A.unwrap y with
ae4735db 455 | A.IComma mcode ->
34e49164
C
456 (x, y)::unsplit_icomma xs
457 | _ -> failwith "wrong ast_cocci in initializer"
458 )
ae4735db 459 | _ ->
34e49164
C
460 failwith ("wrong ast_cocci in initializer, should have pair " ^
461 "number of Icomma")
462
463
464
ae4735db 465let resplit_initialiser ibs iicomma =
34e49164
C
466 match iicomma, ibs with
467 | [], [] -> []
ae4735db 468 | [], _ ->
34e49164 469 failwith "should have a iicomma, do you generate fakeInfo in parser?"
190f1acf
C
470 | iicommas, [] ->
471 error iicommas "shouldn't have a iicomma"
ae4735db 472 | [iicomma], x::xs ->
34e49164
C
473 let elems = List.map fst (x::xs) in
474 let commas = List.map snd (x::xs) +> List.flatten in
475 let commas = commas @ [iicomma] in
ae4735db 476 zip elems commas
34e49164
C
477 | _ -> raise Impossible
478
479
480
ae4735db 481let rec split_icomma xs =
34e49164
C
482 match xs with
483 | [] -> []
484 | (x,y)::xs -> x::y::split_icomma xs
485
ae4735db 486let rec unsplit_initialiser ibs_unsplit =
34e49164
C
487 match ibs_unsplit with
488 | [] -> [], [] (* empty iicomma *)
ae4735db 489 | (x, commax)::xs ->
34e49164
C
490 let (xs, lastcomma) = unsplit_initialiser_bis commax xs in
491 (x, [])::xs, lastcomma
492
493and unsplit_initialiser_bis comma_before = function
494 | [] -> [], [comma_before]
ae4735db 495 | (x, commax)::xs ->
34e49164
C
496 let (xs, lastcomma) = unsplit_initialiser_bis commax xs in
497 (x, [comma_before])::xs, lastcomma
498
499
500
501
502(*---------------------------------------------------------------------------*)
503(* coupling: same in type_annotater_c.ml *)
ae4735db
C
504let structdef_to_struct_name ty =
505 match ty with
506 | qu, (B.StructUnion (su, sopt, fields), iis) ->
34e49164 507 (match sopt,iis with
ae4735db 508 | Some s , [i1;i2;i3;i4] ->
34e49164 509 qu, (B.StructUnionName (su, s), [i1;i2])
ae4735db 510 | None, _ ->
34e49164 511 ty
ae4735db 512
34e49164
C
513 | x -> raise Impossible
514 )
515 | _ -> raise Impossible
516
517(*---------------------------------------------------------------------------*)
5626f154
C
518let one_initialisation_to_affectation x =
519 let ({B.v_namei = var;
520 B.v_type = returnType;
521 B.v_type_bis = tybis;
522 B.v_storage = storage;
523 B.v_local = local},
524 iisep) = x in
525 match var with
526 | Some (name, iniopt) ->
527 (match iniopt with
4dfbc1c2 528 | B.ValInit (iini, (B.InitExpr e, ii_empty2)) ->
5626f154
C
529 let local =
530 match local with
531 Ast_c.NotLocalDecl -> Ast_c.NotLocalVar
532 | Ast_c.LocalDecl ->
533 Ast_c.LocalVar (Ast_c.info_of_type returnType) in
534 let typexp =
535 (* old: Lib_parsing_c.al_type returnType
536 * but this type has not the typename completed so
537 * instead try to use tybis
538 *)
539 match !tybis with
540 | Some ty_with_typename_completed -> ty_with_typename_completed
541 | None -> raise Impossible
542 in
543
544 let typ = ref (Some (typexp,local), Ast_c.NotTest) in
545 let ident = name in
546 let idexpr = Ast_c.mk_e_bis (B.Ident ident) typ Ast_c.noii in
547 let assign =
548 Ast_c.mk_e (B.Assignment (idexpr,B.SimpleAssign, e)) [iini] in
549 Some assign
550 | _ -> None)
551 | _ -> None
552
ae4735db 553let initialisation_to_affectation decl =
34e49164
C
554 match decl with
555 | B.MacroDecl _ -> F.Decl decl
ae4735db
C
556 | B.DeclList (xs, iis) ->
557
34e49164
C
558 (* todo?: should not do that if the variable is an array cos
559 * will have x[] = , mais de toute facon ca sera pas un InitExp
560 *)
5626f154
C
561 let possible_assignment =
562 List.fold_left
563 (function prev ->
564 function x ->
565 match prev,one_initialisation_to_affectation x with
566 _,None -> prev
567 | None,Some x -> Some x
568 | Some prev,Some x ->
569 (* [] is clearly an invalid ii value for a sequence.
570 hope that no one looks at it, since nothing will
571 match the sequence. Fortunately, SmPL doesn't
572 support , expressions. *)
573 Some (Ast_c.mk_e (Ast_c.Sequence (prev, x)) []))
574 None xs in
575 match possible_assignment with
576 Some x -> F.DefineExpr x
577 | None -> F.Decl decl
34e49164
C
578
579(*****************************************************************************)
580(* Functor parameter combinators *)
581(*****************************************************************************)
582(* monad like stuff
583 * src: papers on parser combinators in haskell (cf a pearl by meijer in ICFP)
ae4735db 584 *
34e49164 585 * version0: was not tagging the SP, so just tag the C
ae4735db 586 * val (>>=):
34e49164
C
587 * (tin -> 'c tout) -> ('c -> (tin -> 'b tout)) -> (tin -> 'b tout)
588 * val return : 'b -> tin -> 'b tout
589 * val fail : tin -> 'b tout
ae4735db 590 *
34e49164
C
591 * version1: now also tag the SP so return a ('a * 'b)
592 *)
593
594type mode = PatternMode | TransformMode
595
ae4735db
C
596module type PARAM =
597 sig
34e49164
C
598 type tin
599 type 'x tout
600
601
602 type ('a, 'b) matcher = 'a -> 'b -> tin -> ('a * 'b) tout
603
604 val mode : mode
605
ae4735db
C
606 val (>>=):
607 (tin -> ('a * 'b) tout) ->
608 ('a -> 'b -> (tin -> ('c * 'd) tout)) ->
34e49164
C
609 (tin -> ('c * 'd) tout)
610
611 val return : ('a * 'b) -> tin -> ('a *'b) tout
612 val fail : tin -> ('a * 'b) tout
613
ae4735db
C
614 val (>||>) :
615 (tin -> 'x tout) ->
34e49164 616 (tin -> 'x tout) ->
34e49164
C
617 (tin -> 'x tout)
618
ae4735db
C
619 val (>|+|>) :
620 (tin -> 'x tout) ->
34e49164 621 (tin -> 'x tout) ->
34e49164
C
622 (tin -> 'x tout)
623
624 val (>&&>) : (tin -> bool) -> (tin -> 'x tout) -> (tin -> 'x tout)
625
626 val tokenf : ('a A.mcode, B.info) matcher
627 val tokenf_mck : (A.mcodekind, B.info) matcher
628
ae4735db 629 val distrf_e :
34e49164 630 (A.meta_name A.mcode, B.expression) matcher
ae4735db 631 val distrf_args :
34e49164 632 (A.meta_name A.mcode, (Ast_c.argument, Ast_c.il) either list) matcher
ae4735db 633 val distrf_type :
34e49164 634 (A.meta_name A.mcode, Ast_c.fullType) matcher
ae4735db 635 val distrf_params :
34e49164
C
636 (A.meta_name A.mcode,
637 (Ast_c.parameterType, Ast_c.il) either list) matcher
ae4735db 638 val distrf_param :
34e49164 639 (A.meta_name A.mcode, Ast_c.parameterType) matcher
ae4735db 640 val distrf_ini :
34e49164 641 (A.meta_name A.mcode, Ast_c.initialiser) matcher
c491d8ee
C
642 val distrf_inis :
643 (A.meta_name A.mcode, (Ast_c.initialiser, Ast_c.il) either list) matcher
413ffc02
C
644 val distrf_decl :
645 (A.meta_name A.mcode, Ast_c.declaration) matcher
646 val distrf_field :
647 (A.meta_name A.mcode, Ast_c.field) matcher
ae4735db 648 val distrf_node :
34e49164
C
649 (A.meta_name A.mcode, Control_flow_c.node) matcher
650
ae4735db 651 val distrf_define_params :
c491d8ee
C
652 (A.meta_name A.mcode, (string Ast_c.wrap, Ast_c.il) either list) matcher
653
654 val distrf_enum_fields :
655 (A.meta_name A.mcode, (B.oneEnumType, B.il) either list) matcher
34e49164 656
ae4735db 657 val distrf_struct_fields :
485bce71 658 (A.meta_name A.mcode, B.field list) matcher
34e49164 659
ae4735db 660 val distrf_cst :
34e49164
C
661 (A.meta_name A.mcode, (B.constant, string) either B.wrap) matcher
662
ae4735db 663 val cocciExp :
34e49164
C
664 (A.expression, B.expression) matcher -> (A.expression, F.node) matcher
665
ae4735db 666 val cocciExpExp :
34e49164
C
667 (A.expression, B.expression) matcher ->
668 (A.expression, B.expression) matcher
669
ae4735db 670 val cocciTy :
34e49164
C
671 (A.fullType, B.fullType) matcher -> (A.fullType, F.node) matcher
672
ae4735db 673 val cocciInit :
1be43e12
C
674 (A.initialiser, B.initialiser) matcher -> (A.initialiser, F.node) matcher
675
34e49164 676 val envf :
ae4735db 677 A.keep_binding -> A.inherited ->
34e49164 678 A.meta_name A.mcode * Ast_c.metavar_binding_kind *
485bce71 679 (unit -> Common.filename * string * Ast_c.posl * Ast_c.posl) ->
34e49164
C
680 (unit -> tin -> 'x tout) -> (tin -> 'x tout)
681
951c7801
C
682 val check_idconstraint :
683 ('a -> 'b -> bool) -> 'a -> 'b ->
684 (unit -> tin -> 'x tout) -> (tin -> 'x tout)
685
686 val check_constraints_ne :
34e49164
C
687 ('a, 'b) matcher -> 'a list -> 'b ->
688 (unit -> tin -> 'x tout) -> (tin -> 'x tout)
689
690 val all_bound : A.meta_name list -> (tin -> bool)
691
692 val optional_storage_flag : (bool -> tin -> 'x tout) -> (tin -> 'x tout)
693 val optional_qualifier_flag : (bool -> tin -> 'x tout) -> (tin -> 'x tout)
694 val value_format_flag: (bool -> tin -> 'x tout) -> (tin -> 'x tout)
695
34e49164
C
696 end
697
698(*****************************************************************************)
699(* Functor code, "Cocci vs C" *)
700(*****************************************************************************)
701
702module COCCI_VS_C =
951c7801 703 functor (X : PARAM) ->
34e49164
C
704struct
705
706type ('a, 'b) matcher = 'a -> 'b -> X.tin -> ('a * 'b) X.tout
707
708let (>>=) = X.(>>=)
709let return = X.return
710let fail = X.fail
711
712let (>||>) = X.(>||>)
713let (>|+|>) = X.(>|+|>)
714let (>&&>) = X.(>&&>)
715
716let tokenf = X.tokenf
717
718(* should be raise Impossible when called from transformation.ml *)
ae4735db 719let fail2 () =
34e49164
C
720 match X.mode with
721 | PatternMode -> fail
722 | TransformMode -> raise Impossible
723
724
725let (option: ('a,'b) matcher -> ('a option,'b option) matcher)= fun f t1 t2 ->
726 match (t1,t2) with
ae4735db
C
727 | (Some t1, Some t2) ->
728 f t1 t2 >>= (fun t1 t2 ->
34e49164
C
729 return (Some t1, Some t2)
730 )
731 | (None, None) -> return (None, None)
732 | _ -> fail
733
734(* Dots are sometimes used as metavariables, since like metavariables they
735can match other things. But they no longer have the same type. Perhaps these
736functions could be avoided by introducing an appropriate level of polymorphism,
737but I don't know how to declare polymorphism across functors *)
ae4735db
C
738let dots2metavar (_,info,mcodekind,pos) =
739 (("","..."),info,mcodekind,pos)
34e49164 740let metavar2dots (_,info,mcodekind,pos) = ("...",info,mcodekind,pos)
65038c61 741let metavar2ndots (_,info,mcodekind,pos) = ("<+...",info,mcodekind,pos)
34e49164 742
5636bb2c 743let satisfies_regexpconstraint c id : bool =
951c7801 744 match c with
5636bb2c
C
745 A.IdRegExp (_,recompiled) -> Str.string_match recompiled id 0
746 | A.IdNotRegExp (_,recompiled) -> not (Str.string_match recompiled id 0)
747
748let satisfies_iconstraint c id : bool =
749 not (List.mem id c)
951c7801
C
750
751let satisfies_econstraint c exp : bool =
5636bb2c
C
752 let warning s = pr2_once ("WARNING: "^s); false in
753 match Ast_c.unwrap_expr exp with
754 Ast_c.Ident (name) ->
755 (match name with
756 Ast_c.RegularName rname ->
757 satisfies_regexpconstraint c (Ast_c.unwrap_st rname)
758 | Ast_c.CppConcatenatedName _ ->
759 warning
760 "Unable to apply a constraint on a CppConcatenatedName identifier!"
761 | Ast_c.CppVariadicName _ ->
762 warning
763 "Unable to apply a constraint on a CppVariadicName identifier!"
764 | Ast_c.CppIdentBuilder _ ->
765 warning
766 "Unable to apply a constraint on a CppIdentBuilder identifier!")
767 | Ast_c.Constant cst ->
768 (match cst with
769 | Ast_c.String (str, _) -> satisfies_regexpconstraint c str
770 | Ast_c.MultiString strlist ->
771 warning "Unable to apply a constraint on an multistring constant!"
772 | Ast_c.Char (char , _) -> satisfies_regexpconstraint c char
773 | Ast_c.Int (int , _) -> satisfies_regexpconstraint c int
774 | Ast_c.Float (float, _) -> satisfies_regexpconstraint c float)
775 | _ -> warning "Unable to apply a constraint on an expression!"
951c7801 776
c491d8ee
C
777
778(* ------------------------------------------------------------------------- *)
779(* This has to be up here to allow adequate polymorphism *)
780
781let list_matcher match_dots rebuild_dots match_comma rebuild_comma
782 match_metalist rebuild_metalist mktermval special_cases
783 element distrf get_iis = fun eas ebs ->
784 let rec loop = function
785 [], [] -> return ([], [])
786 | [], eb::ebs -> fail
787 | ea::eas, ebs ->
788 X.all_bound (A.get_inherited ea) >&&>
789 let try_matches =
790 (match match_dots ea, ebs with
791 Some (mcode, optexpr), ys ->
792 (* todo: if optexpr, then a WHEN and so may have to filter yys *)
793 if optexpr <> None then failwith "not handling when in a list";
794
795 (* '...' can take more or less the beginnings of the arguments *)
796 let startendxs =
797 Common.zip (Common.inits ys) (Common.tails ys) in
798 Some
799 (startendxs +> List.fold_left (fun acc (startxs, endxs) ->
800 acc >||> (
801
802 (* allow '...', and maybe its associated ',' to match nothing.
803 * for the associated ',' see below how we handle the EComma
804 * to match nothing.
805 *)
806 (if null startxs
807 then
808 if mcode_contain_plus (mcodekind mcode)
809 then fail
810 (*failwith
811 "I have no token that I could accroche myself on"*)
812 else return (dots2metavar mcode, [])
813 else
814 (* subtil: we dont want the '...' to match until the
815 * comma. cf -test pb_params_iso. We would get at
816 * "already tagged" error.
817 * this is because both f (... x, ...) and f (..., x, ...)
818 * would match a f(x,3) with our "optional-comma" strategy.
819 *)
820 (match Common.last startxs with
821 | Right _ -> fail
822 | Left _ -> distrf (dots2metavar mcode) startxs))
823
824 >>= (fun mcode startxs ->
825 let mcode = metavar2dots mcode in
826 loop (eas, endxs) >>= (fun eas endxs ->
827 return (
828 (rebuild_dots (mcode, optexpr) +> A.rewrap ea) ::eas,
829 startxs ++ endxs
830 )))
831 )
832 ) fail)
833
834 | None,_ -> None)
835 +++
836 (match match_comma ea, ebs with
837 | Some ia1, Right ii::ebs ->
838 Some
839 (let ib1 = tuple_of_list1 ii in
840 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
841 loop (eas, ebs) >>= (fun eas ebs ->
842 return (
843 (rebuild_comma ia1 +> A.rewrap ea)::eas,
844 (Right [ib1])::ebs
845 )
846 )))
847 | Some ia1, ebs ->
848 (* allow ',' to maching nothing. optional comma trick *)
849 Some
850 (if mcode_contain_plus (mcodekind ia1)
851 then fail
852 else loop (eas, ebs))
853 | None,_ -> None)
854 +++
855 (match match_metalist ea, ebs with
856 Some (ida,leninfo,keep,inherited), ys ->
857 let startendxs =
858 Common.zip (Common.inits ys) (Common.tails ys) in
859 Some
860 (startendxs +> List.fold_left (fun acc (startxs, endxs) ->
861 acc >||> (
862 let ok =
863 if null startxs
864 then
865 if mcode_contain_plus (mcodekind ida)
866 then false
867 (* failwith "no token that I could accroche myself on" *)
868 else true
869 else
870 (match Common.last startxs with
871 | Right _ -> false
872 | Left _ -> true)
873 in
874 if not ok
875 then fail
876 else
877 let startxs' = Ast_c.unsplit_comma startxs in
878 let len = List.length startxs' in
879
880 (match leninfo with
881 | A.MetaListLen (lenname,lenkeep,leninherited) ->
882 let max_min _ = failwith "no pos" in
883 X.envf lenkeep leninherited
884 (lenname, Ast_c.MetaListlenVal (len), max_min)
885 | A.CstListLen n ->
886 if len = n
887 then (function f -> f())
888 else (function f -> fail)
8babbc8f 889 | A.AnyListLen -> function f -> f())
c491d8ee
C
890 (fun () ->
891 let max_min _ =
892 Lib_parsing_c.lin_col_by_pos (get_iis startxs) in
893 X.envf keep inherited
894 (ida, mktermval startxs', max_min)
895 (fun () ->
896 if null startxs
897 then return (ida, [])
898 else distrf ida (Ast_c.split_comma startxs'))
899 >>= (fun ida startxs ->
900 loop (eas, endxs) >>= (fun eas endxs ->
901 return (
902 (rebuild_metalist(ida,leninfo,keep,inherited))
903 +> A.rewrap ea::eas,
904 startxs ++ endxs
905 ))
906 )
907 )
908 )) fail)
909 | None,_ -> None)
910 +++
911 special_cases ea eas ebs in
912 match try_matches with
913 Some res -> res
914 | None ->
915 (match ebs with
916 | (Left eb)::ebs ->
917 element ea eb >>= (fun ea eb ->
918 loop (eas, ebs) >>= (fun eas ebs ->
919 return (ea::eas, Left eb::ebs)))
920 | (Right y)::ys -> raise Impossible
921 | [] -> fail) in
922 loop (eas,ebs)
923
34e49164 924(*---------------------------------------------------------------------------*)
ae4735db 925(* toc:
34e49164
C
926 * - expression
927 * - ident
928 * - arguments
929 * - parameters
930 * - declaration
931 * - initialisers
ae4735db 932 * - type
34e49164
C
933 * - node
934 *)
935
936(*---------------------------------------------------------------------------*)
937let rec (expression: (A.expression, Ast_c.expression) matcher) =
ae4735db 938 fun ea eb ->
c3e37e97
C
939 if A.get_test_exp ea && not (Ast_c.is_test eb) then fail
940 else
34e49164
C
941 X.all_bound (A.get_inherited ea) >&&>
942 let wa x = A.rewrap ea x in
943 match A.unwrap ea, eb with
ae4735db 944
34e49164
C
945 (* general case: a MetaExpr can match everything *)
946 | A.MetaExpr (ida,constraints,keep,opttypa,form,inherited),
947 (((expr, opttypb), ii) as expb) ->
948
ae4735db 949 (* old: before have a MetaConst. Now we factorize and use 'form' to
34e49164
C
950 * differentiate between different cases *)
951 let rec matches_id = function
b1b2de81 952 B.Ident(name) -> true
34e49164
C
953 | B.Cast(ty,e) -> matches_id (B.unwrap_expr e)
954 | _ -> false in
955 let form_ok =
956 match (form,expr) with
957 (A.ANY,_) -> true
958 | (A.CONST,e) ->
959 let rec matches = function
960 B.Constant(c) -> true
ae4735db
C
961 | B.Ident (nameidb) ->
962 let s = Ast_c.str_of_name nameidb in
963 if s =~ "^[A-Z_][A-Z_0-9]*$"
b1b2de81 964 then begin
002099fc 965 pr2_once ("warning: " ^ s ^ " treated as a constant");
b1b2de81
C
966 true
967 end
968 else false
34e49164
C
969 | B.Cast(ty,e) -> matches (B.unwrap_expr e)
970 | B.Unary(e,B.UnMinus) -> matches (B.unwrap_expr e)
971 | B.SizeOfExpr(exp) -> true
972 | B.SizeOfType(ty) -> true
973 | _ -> false in
974 matches e
975 | (A.LocalID,e) ->
976 (matches_id e) &&
977 (match !opttypb with
978 (Some (_,Ast_c.LocalVar _),_) -> true
979 | _ -> false)
980 | (A.ID,e) -> matches_id e in
981
982 if form_ok
983 then
984 (let (opttypb,_testb) = !opttypb in
985 match opttypa, opttypb with
986 | None, _ -> return ((),())
ae4735db 987 | Some _, None ->
34e49164
C
988 pr2_once ("Missing type information. Certainly a pb in " ^
989 "annotate_typer.ml");
990 fail
951c7801 991
fc1ad971 992 | Some tas, Some tb ->
951c7801 993 tas +> List.fold_left (fun acc ta ->
34e49164
C
994 acc >|+|> compatible_type ta tb) fail
995 ) >>=
996 (fun () () ->
5636bb2c
C
997 let meta_expr_val l x = Ast_c.MetaExprVal(x,l) in
998 match constraints with
999 Ast_cocci.NoConstraint -> return (meta_expr_val [],())
1000 | Ast_cocci.NotIdCstrt cstrt ->
1001 X.check_idconstraint satisfies_econstraint cstrt eb
1002 (fun () -> return (meta_expr_val [],()))
1003 | Ast_cocci.NotExpCstrt cstrts ->
1004 X.check_constraints_ne expression cstrts eb
1005 (fun () -> return (meta_expr_val [],()))
1006 | Ast_cocci.SubExpCstrt cstrts ->
1007 return (meta_expr_val cstrts,()))
1008 >>=
1009 (fun wrapper () ->
1010 let max_min _ =
1011 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_expr expb) in
1012 X.envf keep inherited (ida, wrapper expb, max_min)
1013 (fun () ->
1014 X.distrf_e ida expb >>=
1015 (fun ida expb ->
1016 return (
1017 A.MetaExpr (ida,constraints,keep,opttypa,form,inherited)+>
1018 A.rewrap ea,
1019 expb
1020 ))
1021 ))
34e49164 1022 else fail
951c7801 1023
ae4735db 1024 (* old:
34e49164
C
1025 * | A.MetaExpr(ida,false,opttypa,_inherited), expb ->
1026 * D.distribute_mck (mcodekind ida) D.distribute_mck_e expb binding
ae4735db 1027 *
34e49164
C
1028 * but bug! because if have not tagged SP, then transform without doing
1029 * any checks. Hopefully now have tagged SP technique.
1030 *)
ae4735db
C
1031
1032
1033 (* old:
1034 * | A.Edots _, _ -> raise Impossible.
1035 *
1036 * In fact now can also have the Edots inside normal expression, not
1037 * just in arg lists. in 'x[...];' less: in if(<... x ... y ...>)
34e49164 1038 *)
ae4735db
C
1039 | A.Edots (mcode, None), expb ->
1040 X.distrf_e (dots2metavar mcode) expb >>= (fun mcode expb ->
34e49164 1041 return (
ae4735db 1042 A.Edots (metavar2dots mcode, None) +> A.rewrap ea ,
34e49164
C
1043 expb
1044 ))
ae4735db
C
1045
1046
34e49164 1047 | A.Edots (_, Some expr), _ -> failwith "not handling when on Edots"
ae4735db
C
1048
1049
b1b2de81
C
1050 | A.Ident ida, ((B.Ident (nameidb), typ),noii) ->
1051 assert (null noii);
ae4735db 1052 ident_cpp DontKnow ida nameidb >>= (fun ida nameidb ->
34e49164 1053 return (
ae4735db 1054 ((A.Ident ida)) +> wa,
b1b2de81 1055 ((B.Ident (nameidb), typ),Ast_c.noii)
34e49164 1056 ))
ae4735db
C
1057
1058
1059
34e49164 1060
485bce71 1061 | A.MetaErr _, _ -> failwith "not handling MetaErr"
34e49164
C
1062
1063 (* todo?: handle some isomorphisms in int/float ? can have different
1064 * format : 1l can match a 1.
ae4735db 1065 *
34e49164 1066 * todo: normally string can contain some metavar too, so should
ae4735db 1067 * recurse on the string
34e49164 1068 *)
ae4735db 1069 | A.Constant (ia1), ((B.Constant (ib) , typ),ii) ->
34e49164 1070 (* for everything except the String case where can have multi elems *)
ae4735db
C
1071 let do1 () =
1072 let ib1 = tuple_of_list1 ii in
1073 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
1074 return (
1075 ((A.Constant ia1)) +> wa,
34e49164
C
1076 ((B.Constant (ib), typ),[ib1])
1077 ))
1078 in
ae4735db
C
1079 (match term ia1, ib with
1080 | A.Int x, B.Int (y,_) ->
1081 X.value_format_flag (fun use_value_equivalence ->
1082 if use_value_equivalence
1083 then
34e49164
C
1084 if equal_c_int x y
1085 then do1()
1086 else fail
ae4735db 1087 else
34e49164
C
1088 if x =$= y
1089 then do1()
1090 else fail
1091 )
1092 | A.Char x, B.Char (y,_) when x =$= y (* todo: use kind ? *)
1093 -> do1()
1094 | A.Float x, B.Float (y,_) when x =$= y (* todo: use floatType ? *)
1095 -> do1()
1096
1097 | A.String sa, B.String (sb,_kind) when sa =$= sb ->
1098 (match ii with
ae4735db
C
1099 | [ib1] ->
1100 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
1101 return (
1102 ((A.Constant ia1)) +> wa,
34e49164
C
1103 ((B.Constant (ib), typ),[ib1])
1104 ))
1105 | _ -> fail (* multi string, not handled *)
1106 )
485bce71 1107
0708f913 1108 | _, B.MultiString _ -> (* todo cocci? *) fail
485bce71 1109 | _, (B.String _ | B.Float _ | B.Char _ | B.Int _) -> fail
34e49164
C
1110 )
1111
1112
ae4735db 1113 | A.FunCall (ea, ia1, eas, ia2), ((B.FunCall (eb, ebs), typ),ii) ->
34e49164
C
1114 (* todo: do special case to allow IdMetaFunc, cos doing the
1115 * recursive call will be too late, match_ident will not have the
1116 * info whether it was a function. todo: but how detect when do
1117 * x.field = f; how know that f is a Func ? By having computed
1118 * some information before the matching!
ae4735db 1119 *
34e49164
C
1120 * Allow match with FunCall containing types. Now ast_cocci allow
1121 * type in parameter, and morover ast_cocci allow f(...) and those
ae4735db 1122 * ... could match type.
34e49164
C
1123 *)
1124 let (ib1, ib2) = tuple_of_list2 ii in
113803cf
C
1125 expression ea eb >>= (fun ea eb ->
1126 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
1127 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
1128 arguments (seqstyle eas) (A.undots eas) ebs >>= (fun easundots ebs ->
34e49164
C
1129 let eas = redots eas easundots in
1130 return (
1131 ((A.FunCall (ea, ia1, eas, ia2)) +> wa,
1132 ((B.FunCall (eb, ebs),typ), [ib1;ib2])
1133 ))))))
1134
1135
1136
1137
1138 | A.Assignment (ea1, opa, ea2, simple),
ae4735db 1139 ((B.Assignment (eb1, opb, eb2), typ),ii) ->
34e49164 1140 let (opbi) = tuple_of_list1 ii in
ae4735db 1141 if equal_assignOp (term opa) opb
34e49164 1142 then
ae4735db
C
1143 expression ea1 eb1 >>= (fun ea1 eb1 ->
1144 expression ea2 eb2 >>= (fun ea2 eb2 ->
1145 tokenf opa opbi >>= (fun opa opbi ->
34e49164 1146 return (
c491d8ee 1147 (A.Assignment (ea1, opa, ea2, simple)) +> wa,
34e49164
C
1148 ((B.Assignment (eb1, opb, eb2), typ), [opbi])
1149 ))))
1150 else fail
1151
1152 | A.CondExpr(ea1,ia1,ea2opt,ia2,ea3),((B.CondExpr(eb1,eb2opt,eb3),typ),ii) ->
1153 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
1154 expression ea1 eb1 >>= (fun ea1 eb1 ->
1155 option expression ea2opt eb2opt >>= (fun ea2opt eb2opt ->
1156 expression ea3 eb3 >>= (fun ea3 eb3 ->
1157 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
1158 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
34e49164
C
1159 return (
1160 ((A.CondExpr(ea1,ia1,ea2opt,ia2,ea3))) +> wa,
1161 ((B.CondExpr (eb1, eb2opt, eb3),typ), [ib1;ib2])
1162 ))))))
1163
1164 (* todo?: handle some isomorphisms here ? *)
ae4735db 1165 | A.Postfix (ea, opa), ((B.Postfix (eb, opb), typ),ii) ->
34e49164
C
1166 let opbi = tuple_of_list1 ii in
1167 if equal_fixOp (term opa) opb
1168 then
ae4735db
C
1169 expression ea eb >>= (fun ea eb ->
1170 tokenf opa opbi >>= (fun opa opbi ->
34e49164
C
1171 return (
1172 ((A.Postfix (ea, opa))) +> wa,
1173 ((B.Postfix (eb, opb), typ),[opbi])
1174 )))
1175 else fail
ae4735db
C
1176
1177
1178 | A.Infix (ea, opa), ((B.Infix (eb, opb), typ),ii) ->
34e49164
C
1179 let opbi = tuple_of_list1 ii in
1180 if equal_fixOp (term opa) opb
1181 then
ae4735db
C
1182 expression ea eb >>= (fun ea eb ->
1183 tokenf opa opbi >>= (fun opa opbi ->
34e49164
C
1184 return (
1185 ((A.Infix (ea, opa))) +> wa,
1186 ((B.Infix (eb, opb), typ),[opbi])
1187 )))
1188 else fail
1189
ae4735db 1190 | A.Unary (ea, opa), ((B.Unary (eb, opb), typ),ii) ->
34e49164
C
1191 let opbi = tuple_of_list1 ii in
1192 if equal_unaryOp (term opa) opb
1193 then
ae4735db
C
1194 expression ea eb >>= (fun ea eb ->
1195 tokenf opa opbi >>= (fun opa opbi ->
34e49164
C
1196 return (
1197 ((A.Unary (ea, opa))) +> wa,
1198 ((B.Unary (eb, opb), typ),[opbi])
1199 )))
1200 else fail
1201
ae4735db 1202 | A.Binary (ea1, opa, ea2), ((B.Binary (eb1, opb, eb2), typ),ii) ->
34e49164
C
1203 let opbi = tuple_of_list1 ii in
1204 if equal_binaryOp (term opa) opb
ae4735db
C
1205 then
1206 expression ea1 eb1 >>= (fun ea1 eb1 ->
1207 expression ea2 eb2 >>= (fun ea2 eb2 ->
1208 tokenf opa opbi >>= (fun opa opbi ->
34e49164
C
1209 return (
1210 ((A.Binary (ea1, opa, ea2))) +> wa,
1211 ((B.Binary (eb1, opb, eb2), typ),[opbi]
1212 )))))
1213 else fail
1214
ae4735db 1215 | A.Nested (ea1, opa, ea2), eb ->
34e49164 1216 let rec loop eb =
c3e37e97 1217 expression ea1 eb >|+|>
34e49164
C
1218 (match eb with
1219 ((B.Binary (eb1, opb, eb2), typ),ii)
1220 when equal_binaryOp (term opa) opb ->
1221 let opbi = tuple_of_list1 ii in
1222 let left_to_right =
ae4735db
C
1223 (expression ea1 eb1 >>= (fun ea1 eb1 ->
1224 expression ea2 eb2 >>= (fun ea2 eb2 ->
1225 tokenf opa opbi >>= (fun opa opbi ->
34e49164
C
1226 return (
1227 ((A.Nested (ea1, opa, ea2))) +> wa,
1228 ((B.Binary (eb1, opb, eb2), typ),[opbi]
1229 )))))) in
1230 let right_to_left =
ae4735db
C
1231 (expression ea2 eb1 >>= (fun ea2 eb1 ->
1232 expression ea1 eb2 >>= (fun ea1 eb2 ->
1233 tokenf opa opbi >>= (fun opa opbi ->
34e49164
C
1234 return (
1235 ((A.Nested (ea1, opa, ea2))) +> wa,
1236 ((B.Binary (eb1, opb, eb2), typ),[opbi]
1237 )))))) in
1238 let in_left =
ae4735db
C
1239 (loop eb1 >>= (fun ea1 eb1 ->
1240 expression ea2 eb2 >>= (fun ea2 eb2 ->
1241 tokenf opa opbi >>= (fun opa opbi ->
34e49164
C
1242 return (
1243 ((A.Nested (ea1, opa, ea2))) +> wa,
1244 ((B.Binary (eb1, opb, eb2), typ),[opbi]
1245 )))))) in
1246 let in_right =
ae4735db
C
1247 (expression ea2 eb1 >>= (fun ea2 eb1 ->
1248 loop eb2 >>= (fun ea1 eb2 ->
1249 tokenf opa opbi >>= (fun opa opbi ->
34e49164
C
1250 return (
1251 ((A.Nested (ea1, opa, ea2))) +> wa,
1252 ((B.Binary (eb1, opb, eb2), typ),[opbi]
1253 )))))) in
1254 left_to_right >|+|> right_to_left >|+|> in_left >|+|> in_right
1255 | _ -> fail) in
1256 loop eb
1257
1258 (* todo?: handle some isomorphisms here ? (with pointers = Unary Deref) *)
ae4735db 1259 | A.ArrayAccess (ea1, ia1, ea2, ia2),((B.ArrayAccess (eb1, eb2), typ),ii) ->
34e49164 1260 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
1261 expression ea1 eb1 >>= (fun ea1 eb1 ->
1262 expression ea2 eb2 >>= (fun ea2 eb2 ->
1263 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
1264 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
34e49164
C
1265 return (
1266 ((A.ArrayAccess (ea1, ia1, ea2, ia2))) +> wa,
1267 ((B.ArrayAccess (eb1, eb2),typ), [ib1;ib2])
1268 )))))
1269
1270 (* todo?: handle some isomorphisms here ? *)
1271 | A.RecordAccess (ea, ia1, ida), ((B.RecordAccess (eb, idb), typ),ii) ->
b1b2de81 1272 let (ib1) = tuple_of_list1 ii in
ae4735db
C
1273 ident_cpp DontKnow ida idb >>= (fun ida idb ->
1274 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
1275 expression ea eb >>= (fun ea eb ->
34e49164
C
1276 return (
1277 ((A.RecordAccess (ea, ia1, ida))) +> wa,
b1b2de81 1278 ((B.RecordAccess (eb, idb), typ), [ib1])
34e49164
C
1279 ))))
1280
1281
1282
1283 | A.RecordPtAccess (ea,ia1,ida),((B.RecordPtAccess (eb, idb), typ), ii) ->
b1b2de81 1284 let (ib1) = tuple_of_list1 ii in
ae4735db
C
1285 ident_cpp DontKnow ida idb >>= (fun ida idb ->
1286 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
1287 expression ea eb >>= (fun ea eb ->
34e49164
C
1288 return (
1289 ((A.RecordPtAccess (ea, ia1, ida))) +> wa,
b1b2de81 1290 ((B.RecordPtAccess (eb, idb), typ), [ib1])
34e49164
C
1291 ))))
1292
1293
ae4735db
C
1294 (* todo?: handle some isomorphisms here ?
1295 * todo?: do some iso-by-absence on cast ?
34e49164
C
1296 * by trying | ea, B.Case (typb, eb) -> match_e_e ea eb ?
1297 *)
1298
ae4735db 1299 | A.Cast (ia1, typa, ia2, ea), ((B.Cast (typb, eb), typ),ii) ->
34e49164 1300 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
1301 fullType typa typb >>= (fun typa typb ->
1302 expression ea eb >>= (fun ea eb ->
1303 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
1304 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
34e49164
C
1305 return (
1306 ((A.Cast (ia1, typa, ia2, ea))) +> wa,
1307 ((B.Cast (typb, eb),typ),[ib1;ib2])
1308 )))))
1309
ae4735db 1310 | A.SizeOfExpr (ia1, ea), ((B.SizeOfExpr (eb), typ),ii) ->
34e49164 1311 let ib1 = tuple_of_list1 ii in
ae4735db
C
1312 expression ea eb >>= (fun ea eb ->
1313 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
34e49164
C
1314 return (
1315 ((A.SizeOfExpr (ia1, ea))) +> wa,
1316 ((B.SizeOfExpr (eb), typ),[ib1])
1317 )))
1318
ae4735db 1319 | A.SizeOfType (ia1, ia2, typa, ia3), ((B.SizeOfType typb, typ),ii) ->
34e49164 1320 let (ib1,ib2,ib3) = tuple_of_list3 ii in
ae4735db
C
1321 fullType typa typb >>= (fun typa typb ->
1322 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
1323 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
1324 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
34e49164
C
1325 return (
1326 ((A.SizeOfType (ia1, ia2, typa, ia3))) +> wa,
1327 ((B.SizeOfType (typb),typ),[ib1;ib2;ib3])
1328 )))))
1329
1330
1331 (* todo? iso ? allow all the combinations ? *)
ae4735db 1332 | A.Paren (ia1, ea, ia2), ((B.ParenExpr (eb), typ),ii) ->
34e49164 1333 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
1334 expression ea eb >>= (fun ea eb ->
1335 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
1336 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
34e49164
C
1337 return (
1338 ((A.Paren (ia1, ea, ia2))) +> wa,
1339 ((B.ParenExpr (eb), typ), [ib1;ib2])
1340 ))))
1341
5636bb2c 1342 | A.NestExpr(starter,exps,ender,None,true), eb ->
34e49164
C
1343 (match A.unwrap exps with
1344 A.DOTS [exp] ->
ae4735db 1345 X.cocciExpExp expression exp eb >>= (fun exp eb ->
8babbc8f 1346 X.distrf_e (dots2metavar starter) eb >>= (fun mcode eb ->
34e49164 1347 return (
5636bb2c 1348 (A.NestExpr
65038c61 1349 (metavar2ndots mcode,
8babbc8f 1350 A.rewrap exps (A.DOTS [exp]),ender,None,true)) +> wa,
34e49164
C
1351 eb
1352 )
8babbc8f 1353 ))
34e49164
C
1354 | _ ->
1355 failwith
1356 "for nestexpr, only handling the case with dots and only one exp")
1357
485bce71 1358 | A.NestExpr _, _ ->
34e49164
C
1359 failwith "only handling multi and no when code in a nest expr"
1360
ae4735db 1361 (* only in arg lists or in define body *)
485bce71 1362 | A.TypeExp _, _ -> fail
34e49164
C
1363
1364 (* only in arg lists *)
ae4735db
C
1365 | A.MetaExprList _, _
1366 | A.EComma _, _
1367 | A.Ecircles _, _
1368 | A.Estars _, _
34e49164
C
1369 ->
1370 raise Impossible
1371
ae4735db 1372 | A.DisjExpr eas, eb ->
34e49164
C
1373 eas +> List.fold_left (fun acc ea -> acc >|+|> (expression ea eb)) fail
1374
ae4735db 1375 | A.UniqueExp _,_ | A.OptExp _,_ ->
34e49164
C
1376 failwith "not handling Opt/Unique/Multi on expr"
1377
1378 (* Because of Exp cant put a raise Impossible; have to put a fail *)
1379
ae4735db
C
1380 (* have not a counter part in coccinelle, for the moment *)
1381 | _, ((B.Sequence _,_),_)
1382 | _, ((B.StatementExpr _,_),_)
1383 | _, ((B.Constructor _,_),_)
f59c9fb7 1384 | _, ((B.New _,_),_)
4dfbc1c2 1385 | _, ((B.Delete _,_),_)
34e49164
C
1386 -> fail
1387
485bce71 1388
ae4735db 1389 | _,
485bce71
C
1390 (((B.Cast (_, _)|B.ParenExpr _|B.SizeOfType _|B.SizeOfExpr _|
1391 B.RecordPtAccess (_, _)|
1392 B.RecordAccess (_, _)|B.ArrayAccess (_, _)|
1393 B.Binary (_, _, _)|B.Unary (_, _)|
1394 B.Infix (_, _)|B.Postfix (_, _)|
1395 B.Assignment (_, _, _)|B.CondExpr (_, _, _)|
1396 B.FunCall (_, _)|B.Constant _|B.Ident _),
1397 _),_)
1398 -> fail
1399
1400
1401
34e49164
C
1402
1403
34e49164 1404(* ------------------------------------------------------------------------- *)
ae4735db 1405and (ident_cpp: info_ident -> (A.ident, B.name) matcher) =
708f4980 1406 fun infoidb ida idb ->
b1b2de81 1407 match idb with
ae4735db 1408 | B.RegularName (s, iis) ->
b1b2de81 1409 let iis = tuple_of_list1 iis in
ae4735db 1410 ident infoidb ida (s, iis) >>= (fun ida (s,iis) ->
b1b2de81 1411 return (
ae4735db 1412 ida,
b1b2de81
C
1413 (B.RegularName (s, [iis]))
1414 ))
1415 | B.CppConcatenatedName _ | B.CppVariadicName _ |B.CppIdentBuilder _
708f4980
C
1416 ->
1417 (* This should be moved to the Id case of ident. Metavariables
1418 should be allowed to be bound to such variables. But doing so
1419 would require implementing an appropriate distr function *)
1420 fail
b1b2de81 1421
ae4735db 1422and (ident: info_ident -> (A.ident, string * Ast_c.info) matcher) =
d3f655c6 1423 fun infoidb ida ((idb, iib) as ib) -> (* (idb, iib) as ib *)
5636bb2c
C
1424 let check_constraints constraints idb =
1425 let meta_id_val l x = Ast_c.MetaIdVal(x,l) in
1426 match constraints with
1427 A.IdNoConstraint -> return (meta_id_val [],())
1428 | A.IdNegIdSet (str,meta) ->
1429 X.check_idconstraint satisfies_iconstraint str idb
1430 (fun () -> return (meta_id_val meta,()))
1431 | A.IdRegExpConstraint re ->
1432 X.check_idconstraint satisfies_regexpconstraint re idb
1433 (fun () -> return (meta_id_val [],())) in
34e49164
C
1434 X.all_bound (A.get_inherited ida) >&&>
1435 match A.unwrap ida with
ae4735db 1436 | A.Id sa ->
34e49164 1437 if (term sa) =$= idb then
ae4735db 1438 tokenf sa iib >>= (fun sa iib ->
34e49164
C
1439 return (
1440 ((A.Id sa)) +> A.rewrap ida,
1441 (idb, iib)
1442 ))
1443 else fail
1444
ae4735db 1445 | A.MetaId(mida,constraints,keep,inherited) ->
5636bb2c
C
1446 check_constraints constraints idb >>=
1447 (fun wrapper () ->
34e49164
C
1448 let max_min _ = Lib_parsing_c.lin_col_by_pos [iib] in
1449 (* use drop_pos for ids so that the pos is not added a second time in
1450 the call to tokenf *)
5636bb2c 1451 X.envf keep inherited (A.drop_pos mida, wrapper idb, max_min)
ae4735db
C
1452 (fun () ->
1453 tokenf mida iib >>= (fun mida iib ->
34e49164
C
1454 return (
1455 ((A.MetaId (mida, constraints, keep, inherited)) +> A.rewrap ida,
1456 (idb, iib)
1457 )))
1458 ))
1459
ae4735db 1460 | A.MetaFunc(mida,constraints,keep,inherited) ->
34e49164 1461 let is_function _ =
5636bb2c
C
1462 check_constraints constraints idb >>=
1463 (fun wrapper () ->
34e49164
C
1464 let max_min _ = Lib_parsing_c.lin_col_by_pos [iib] in
1465 X.envf keep inherited (A.drop_pos mida,Ast_c.MetaFuncVal idb,max_min)
1466 (fun () ->
ae4735db 1467 tokenf mida iib >>= (fun mida iib ->
34e49164
C
1468 return (
1469 ((A.MetaFunc(mida,constraints,keep,inherited)))+>A.rewrap ida,
1470 (idb, iib)
1471 ))
1472 )) in
ae4735db 1473 (match infoidb with
34e49164
C
1474 | LocalFunction | Function -> is_function()
1475 | DontKnow ->
1476 failwith "MetaFunc, need more semantic info about id"
1477 (* the following implementation could possibly be useful, if one
1478 follows the convention that a macro is always in capital letters
1479 and that a macro is not a function.
1480 (if idb =~ "^[A-Z_][A-Z_0-9]*$" then fail else is_function())*)
1481 )
1482
ae4735db
C
1483 | A.MetaLocalFunc(mida,constraints,keep,inherited) ->
1484 (match infoidb with
1485 | LocalFunction ->
5636bb2c
C
1486 check_constraints constraints idb >>=
1487 (fun wrapper () ->
34e49164
C
1488 let max_min _ = Lib_parsing_c.lin_col_by_pos [iib] in
1489 X.envf keep inherited
1490 (A.drop_pos mida,Ast_c.MetaLocalFuncVal idb, max_min)
1491 (fun () ->
ae4735db 1492 tokenf mida iib >>= (fun mida iib ->
34e49164
C
1493 return (
1494 ((A.MetaLocalFunc(mida,constraints,keep,inherited)))
1495 +> A.rewrap ida,
1496 (idb, iib)
1497 ))
1498 ))
1499 | Function -> fail
1500 | DontKnow -> failwith "MetaLocalFunc, need more semantic info about id"
1501 )
1502
d3f655c6
C
1503 (* not clear why disj things are needed, after disjdistr? *)
1504 | A.DisjId ias ->
1505 ias +> List.fold_left (fun acc ia -> acc >|+|> (ident infoidb ia ib)) fail
1506
ae4735db 1507 | A.OptIdent _ | A.UniqueIdent _ ->
34e49164 1508 failwith "not handling Opt/Unique for ident"
c491d8ee 1509
34e49164 1510(* ------------------------------------------------------------------------- *)
ae4735db 1511and (arguments: sequence ->
c491d8ee
C
1512 (A.expression list, Ast_c.argument Ast_c.wrap2 list) matcher) =
1513 fun seqstyle eas ebs ->
1514 match seqstyle with
1515 | Unordered -> failwith "not handling ooo"
1516 | Ordered ->
1517 arguments_bis eas (Ast_c.split_comma ebs) >>= (fun eas ebs_splitted ->
1518 return (eas, (Ast_c.unsplit_comma ebs_splitted))
1519 )
ae4735db 1520(* because '...' can match nothing, need to take care when have
c491d8ee
C
1521 * ', ...' or '...,' as in f(..., X, Y, ...). It must match
1522 * f(1,2) for instance.
1523 * So I have added special cases such as (if startxs = []) and code
1524 * in the Ecomma matching rule.
1525 *
1526 * old: Must do some try, for instance when f(...,X,Y,...) have to
1527 * test the transfo for all the combinaitions and if multiple transfo
1528 * possible ? pb ? => the type is to return a expression option ? use
1529 * some combinators to help ?
1530 * update: with the tag-SP approach, no more a problem.
1531*)
1532
ae4735db 1533and arguments_bis = fun eas ebs ->
c491d8ee
C
1534 let match_dots ea =
1535 match A.unwrap ea with
1536 A.Edots(mcode, optexpr) -> Some (mcode, optexpr)
1537 | _ -> None in
1538 let build_dots (mcode, optexpr) = A.Edots(mcode, optexpr) in
1539 let match_comma ea =
1540 match A.unwrap ea with
1541 A.EComma ia1 -> Some ia1
1542 | _ -> None in
1543 let build_comma ia1 = A.EComma ia1 in
1544 let match_metalist ea =
1545 match A.unwrap ea with
1546 A.MetaExprList(ida,leninfo,keep,inherited) ->
1547 Some(ida,leninfo,keep,inherited)
1548 | _ -> None in
1549 let build_metalist (ida,leninfo,keep,inherited) =
1550 A.MetaExprList(ida,leninfo,keep,inherited) in
1551 let mktermval v = Ast_c.MetaExprListVal v in
1552 let special_cases ea eas ebs = None in
1553 list_matcher match_dots build_dots match_comma build_comma
1554 match_metalist build_metalist mktermval
1555 special_cases argument X.distrf_args
1556 Lib_parsing_c.ii_of_args eas ebs
ae4735db 1557
113803cf 1558and argument arga argb =
34e49164 1559 X.all_bound (A.get_inherited arga) >&&>
c491d8ee 1560 match A.unwrap arga, argb with
ae4735db 1561 | A.TypeExp tya,
b1b2de81 1562 Right (B.ArgType {B.p_register=b,iib; p_namei=sopt;p_type=tyb}) ->
34e49164 1563 if b || sopt <> None
ae4735db 1564 then
34e49164
C
1565 (* failwith "the argument have a storage and ast_cocci does not have"*)
1566 fail
ae4735db 1567 else
b1b2de81 1568 (* b = false and sopt = None *)
ae4735db 1569 fullType tya tyb >>= (fun tya tyb ->
34e49164
C
1570 return (
1571 (A.TypeExp tya) +> A.rewrap arga,
b1b2de81
C
1572 (Right (B.ArgType {B.p_register=(b,iib);
1573 p_namei=sopt;
1574 p_type=tyb;}))
34e49164
C
1575 ))
1576
1577 | A.TypeExp tya, _ -> fail
b1b2de81 1578 | _, Right (B.ArgType _) -> fail
113803cf
C
1579 | _, Left argb ->
1580 expression arga argb >>= (fun arga argb ->
34e49164
C
1581 return (arga, Left argb)
1582 )
1583 | _, Right (B.ArgAction y) -> fail
1584
1585
1586(* ------------------------------------------------------------------------- *)
1587(* todo? facto code with argument ? *)
ae4735db 1588and (parameters: sequence ->
34e49164 1589 (A.parameterTypeDef list, Ast_c.parameterType Ast_c.wrap2 list)
ae4735db 1590 matcher) =
34e49164
C
1591 fun seqstyle eas ebs ->
1592 match seqstyle with
1593 | Unordered -> failwith "not handling ooo"
ae4735db
C
1594 | Ordered ->
1595 parameters_bis eas (Ast_c.split_comma ebs) >>= (fun eas ebs_splitted ->
34e49164
C
1596 return (eas, (Ast_c.unsplit_comma ebs_splitted))
1597 )
1598
1599
ae4735db 1600and parameters_bis eas ebs =
c491d8ee
C
1601 let match_dots ea =
1602 match A.unwrap ea with
1603 A.Pdots(mcode) -> Some (mcode, None)
1604 | _ -> None in
1605 let build_dots (mcode, _optexpr) = A.Pdots(mcode) in
1606 let match_comma ea =
1607 match A.unwrap ea with
1608 A.PComma ia1 -> Some ia1
1609 | _ -> None in
1610 let build_comma ia1 = A.PComma ia1 in
1611 let match_metalist ea =
1612 match A.unwrap ea with
1613 A.MetaParamList(ida,leninfo,keep,inherited) ->
1614 Some(ida,leninfo,keep,inherited)
1615 | _ -> None in
1616 let build_metalist (ida,leninfo,keep,inherited) =
1617 A.MetaParamList(ida,leninfo,keep,inherited) in
1618 let mktermval v = Ast_c.MetaParamListVal v in
1619 let special_cases ea eas ebs =
1620 (* a case where one smpl parameter matches a list of C parameters *)
1621 match A.unwrap ea,ebs with
1622 A.VoidParam ta, ys ->
1623 Some
34e49164 1624 (match eas, ebs with
ae4735db 1625 | [], [Left eb] ->
b1b2de81 1626 let {B.p_register=(hasreg,iihasreg);
c491d8ee
C
1627 p_namei = idbopt;
1628 p_type=tb; } = eb in
1629
b1b2de81 1630 if idbopt =*= None && not hasreg
ae4735db
C
1631 then
1632 match tb with
1633 | (qub, (B.BaseType B.Void,_)) ->
1634 fullType ta tb >>= (fun ta tb ->
34e49164 1635 return (
c491d8ee
C
1636 [(A.VoidParam ta) +> A.rewrap ea],
1637 [Left {B.p_register=(hasreg, iihasreg);
1638 p_namei = idbopt;
1639 p_type = tb;}]
1640 ))
34e49164
C
1641 | _ -> fail
1642 else fail
c491d8ee
C
1643 | _ -> fail)
1644 | _ -> None in
1645 list_matcher match_dots build_dots match_comma build_comma
1646 match_metalist build_metalist mktermval
1647 special_cases parameter X.distrf_params
1648 Lib_parsing_c.ii_of_params eas ebs
1649
b1b2de81 1650(*
c491d8ee
C
1651 let split_register_param = fun (hasreg, idb, ii_b_s) ->
1652 match hasreg, idb, ii_b_s with
1653 | false, Some s, [i1] -> Left (s, [], i1)
1654 | true, Some s, [i1;i2] -> Left (s, [i1], i2)
1655 | _, None, ii -> Right ii
1656 | _ -> raise Impossible
b1b2de81 1657*)
c491d8ee
C
1658
1659
1660and parameter = fun parama paramb ->
1661 match A.unwrap parama, paramb with
1662 A.MetaParam (ida,keep,inherited), eb ->
1663 (* todo: use quaopt, hasreg ? *)
1664 let max_min _ =
1665 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_param eb) in
1666 X.envf keep inherited (ida,Ast_c.MetaParamVal eb,max_min) (fun () ->
1667 X.distrf_param ida eb
1668 ) >>= (fun ida eb ->
1669 return (A.MetaParam(ida,keep,inherited)+> A.rewrap parama,eb))
1670 | A.Param (typa, idaopt), eb ->
1671 let {B.p_register = (hasreg,iihasreg);
1672 p_namei = nameidbopt;
1673 p_type = typb;} = paramb in
1674
1675 fullType typa typb >>= (fun typa typb ->
1676 match idaopt, nameidbopt with
1677 | Some ida, Some nameidb ->
34e49164 1678 (* todo: if minus on ida, should also minus the iihasreg ? *)
c491d8ee
C
1679 ident_cpp DontKnow ida nameidb >>= (fun ida nameidb ->
1680 return (
1681 A.Param (typa, Some ida)+> A.rewrap parama,
1682 {B.p_register = (hasreg, iihasreg);
1683 p_namei = Some (nameidb);
1684 p_type = typb}
1685 ))
1686
1687 | None, None ->
1688 return (
1689 A.Param (typa, None)+> A.rewrap parama,
1690 {B.p_register=(hasreg,iihasreg);
1691 p_namei = None;
1692 p_type = typb;}
1693 )
34e49164
C
1694 (* why handle this case ? because of transform_proto ? we may not
1695 * have an ident in the proto.
ae4735db 1696 * If have some plus on ida ? do nothing about ida ?
34e49164
C
1697 *)
1698 (* not anymore !!! now that julia is handling the proto.
ae4735db 1699 | _, Right iihasreg ->
34e49164
C
1700 return (
1701 (idaopt, typa),
1702 ((hasreg, None, typb), iihasreg)
1703 )
1704 *)
1705
c491d8ee
C
1706 | Some _, None -> fail
1707 | None, Some _ -> fail)
1708 | (A.OptParam _ | A.UniqueParam _), _ ->
1709 failwith "not handling Opt/Unique for Param"
1710 | A.Pcircles (_), ys -> raise Impossible (* in Ordered mode *)
1711 | _ -> fail
34e49164
C
1712
1713(* ------------------------------------------------------------------------- *)
1714and (declaration: (A.mcodekind * bool * A.declaration,B.declaration) matcher) =
ae4735db 1715 fun (mckstart, allminus, decla) declb ->
34e49164
C
1716 X.all_bound (A.get_inherited decla) >&&>
1717 match A.unwrap decla, declb with
1718
1719 (* Un MetaDecl est introduit dans l'asttoctl pour sauter au dessus
1720 * de toutes les declarations qui sont au debut d'un fonction et
1721 * commencer le reste du match au premier statement. Alors, ca matche
1722 * n'importe quelle declaration. On n'a pas besoin d'ajouter
1723 * quoi que ce soit dans l'environnement. C'est une sorte de DDots.
ae4735db 1724 *
34e49164
C
1725 * When the SP want to remove the whole function, the minus is not
1726 * on the MetaDecl but on the MetaRuleElem. So there should
1727 * be no transform of MetaDecl, just matching are allowed.
1728 *)
1729
413ffc02
C
1730 | A.MetaDecl (ida,keep,inherited), _ ->
1731 let max_min _ =
1732 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_decl declb) in
1733 X.envf keep inherited (ida, Ast_c.MetaDeclVal declb, max_min) (fun () ->
1734 X.distrf_decl ida declb
1735 ) >>= (fun ida declb ->
1736 return ((mckstart, allminus,
1737 (A.MetaDecl (ida, keep, inherited))+> A.rewrap decla),
1738 declb))
ae4735db 1739 | _, (B.DeclList ([var], iiptvirgb::iifakestart::iisto)) ->
34e49164
C
1740 onedecl allminus decla (var,iiptvirgb,iisto) >>=
1741 (fun decla (var,iiptvirgb,iisto)->
ae4735db 1742 X.tokenf_mck mckstart iifakestart >>= (fun mckstart iifakestart ->
34e49164
C
1743 return (
1744 (mckstart, allminus, decla),
1745 (B.DeclList ([var], iiptvirgb::iifakestart::iisto))
1746 )))
ae4735db 1747
190f1acf 1748 | _, (B.DeclList (xs, ((iiptvirgb::iifakestart::iisto) as ii))) ->
690d68d1
C
1749 let indexify l =
1750 let rec loop n = function
1751 [] -> []
1752 | x::xs -> (n,x)::(loop (n+1) xs) in
1753 loop 0 l in
1754 let rec repln n vl cur = function
1755 [] -> []
1756 | x::xs ->
1757 if n = cur then vl :: xs else x :: (repln n vl (cur+1) xs) in
1758 if X.mode =*= PatternMode || A.get_safe_decl decla
34e49164 1759 then
690d68d1
C
1760 (indexify xs) +> List.fold_left (fun acc (n,var) ->
1761 (* consider all possible matches *)
1762 acc >||> (function tin -> (
34e49164 1763 X.tokenf_mck mckstart iifakestart >>= (fun mckstart iifakestart ->
ae4735db
C
1764 onedecl allminus decla (var, iiptvirgb, iisto) >>=
1765 (fun decla (var, iiptvirgb, iisto) ->
34e49164
C
1766 return (
1767 (mckstart, allminus, decla),
690d68d1
C
1768 (* adjust the variable that was chosen *)
1769 (B.DeclList (repln n var 0 xs,
1770 iiptvirgb::iifakestart::iisto))
1771 )))) tin))
34e49164 1772 fail
ae4735db 1773 else
190f1acf
C
1774 error ii
1775 "More than one variable in the declaration, and so it cannot be transformed. Check that there is no transformation on the type or the ;"
34e49164
C
1776
1777 | A.MacroDecl (sa,lpa,eas,rpa,enda), B.MacroDecl ((sb,ebs),ii) ->
ae4735db 1778 let (iisb, lpb, rpb, iiendb, iifakestart, iistob) =
34e49164 1779 (match ii with
ae4735db 1780 | iisb::lpb::rpb::iiendb::iifakestart::iisto ->
34e49164
C
1781 (iisb,lpb,rpb,iiendb, iifakestart,iisto)
1782 | _ -> raise Impossible
1783 ) in
ae4735db 1784 (if allminus
34e49164
C
1785 then minusize_list iistob
1786 else return ((), iistob)
1787 ) >>= (fun () iistob ->
1788
ae4735db 1789 X.tokenf_mck mckstart iifakestart >>= (fun mckstart iifakestart ->
34e49164 1790 ident DontKnow sa (sb, iisb) >>= (fun sa (sb, iisb) ->
ae4735db
C
1791 tokenf lpa lpb >>= (fun lpa lpb ->
1792 tokenf rpa rpb >>= (fun rpa rpb ->
1793 tokenf enda iiendb >>= (fun enda iiendb ->
1794 arguments (seqstyle eas) (A.undots eas) ebs >>= (fun easundots ebs ->
34e49164
C
1795 let eas = redots eas easundots in
1796
1797 return (
ae4735db
C
1798 (mckstart, allminus,
1799 (A.MacroDecl (sa,lpa,eas,rpa,enda)) +> A.rewrap decla),
34e49164
C
1800 (B.MacroDecl ((sb,ebs),
1801 [iisb;lpb;rpb;iiendb;iifakestart] ++ iistob))
1802 ))))))))
485bce71 1803
413ffc02 1804 | _, (B.MacroDecl _ |B.DeclList _) -> fail
34e49164
C
1805
1806
ae4735db 1807and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
34e49164
C
1808 X.all_bound (A.get_inherited decla) >&&>
1809 match A.unwrap decla, declb with
1810
ae4735db 1811 (* kind of typedef iso, we must unfold, it's for the case
34e49164
C
1812 * T { }; that we want to match against typedef struct { } xx_t;
1813 *)
413ffc02 1814
ae4735db 1815 | A.TyDecl (tya0, ptvirga),
4dfbc1c2 1816 ({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
1817 B.v_type = typb0;
1818 B.v_storage = (B.StoTypedef, inl);
ae4735db 1819 B.v_local = local;
485bce71 1820 B.v_attr = attrs;
978fd7e5 1821 B.v_type_bis = typb0bis;
485bce71 1822 }, iivirg) ->
34e49164
C
1823
1824 (match A.unwrap tya0, typb0 with
1825 | A.Type(cv1,tya1), ((qu,il),typb1) ->
1826
1827 (match A.unwrap tya1, typb1 with
ae4735db
C
1828 | A.StructUnionDef(tya2, lba, declsa, rba),
1829 (B.StructUnion (sub, sbopt, declsb), ii) ->
34e49164 1830
ae4735db 1831 let (iisub, iisbopt, lbb, rbb) =
34e49164 1832 match sbopt with
ae4735db 1833 | None ->
34e49164
C
1834 let (iisub, lbb, rbb) = tuple_of_list3 ii in
1835 (iisub, [], lbb, rbb)
ae4735db
C
1836 | Some s ->
1837 pr2 (sprintf
34e49164 1838 "warning: both a typedef (%s) and struct name introduction (%s)"
b1b2de81 1839 (Ast_c.str_of_name nameidb) s
34e49164
C
1840 );
1841 pr2 "warning: I will consider only the typedef";
1842 let (iisub, iisb, lbb, rbb) = tuple_of_list4 ii in
1843 (iisub, [iisb], lbb, rbb)
1844 in
ae4735db 1845 let structnameb =
34e49164
C
1846 structdef_to_struct_name
1847 (Ast_c.nQ, (B.StructUnion (sub, sbopt, declsb), ii))
1848 in
ae4735db
C
1849 let fake_typeb =
1850 Ast_c.nQ,((B.TypeName (nameidb, Some
1851 (Lib_parsing_c.al_type structnameb))), [])
34e49164
C
1852 in
1853
ae4735db
C
1854 tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
1855 tokenf lba lbb >>= (fun lba lbb ->
1856 tokenf rba rbb >>= (fun rba rbb ->
34e49164
C
1857 struct_fields (A.undots declsa) declsb >>=(fun undeclsa declsb ->
1858 let declsa = redots declsa undeclsa in
1859
1860 (match A.unwrap tya2 with
ae4735db 1861 | A.Type(cv3, tya3) ->
34e49164 1862 (match A.unwrap tya3 with
ae4735db 1863 | A.MetaType(ida,keep, inherited) ->
34e49164 1864
ae4735db 1865 fullType tya2 fake_typeb >>= (fun tya2 fake_typeb ->
34e49164
C
1866 let tya1 =
1867 A.StructUnionDef(tya2,lba,declsa,rba)+> A.rewrap tya1 in
1868 let tya0 = A.Type(cv1, tya1) +> A.rewrap tya0 in
ae4735db
C
1869
1870
34e49164
C
1871 let typb1 = B.StructUnion (sub,sbopt, declsb),
1872 [iisub] @ iisbopt @ [lbb;rbb] in
1873 let typb0 = ((qu, il), typb1) in
ae4735db
C
1874
1875 match fake_typeb with
1876 | _nQ, ((B.TypeName (nameidb, _typ)),[]) ->
34e49164
C
1877
1878 return (
1879 (A.TyDecl (tya0, ptvirga)) +> A.rewrap decla,
4dfbc1c2 1880 (({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
1881 B.v_type = typb0;
1882 B.v_storage = (B.StoTypedef, inl);
1883 B.v_local = local;
1884 B.v_attr = attrs;
978fd7e5 1885 B.v_type_bis = typb0bis;
485bce71 1886 },
34e49164
C
1887 iivirg),iiptvirgb,iistob)
1888 )
ae4735db 1889 | _ -> raise Impossible
34e49164
C
1890 )
1891
c491d8ee 1892 (* do we need EnumName here too? *)
ae4735db 1893 | A.StructUnionName(sua, sa) ->
ae4735db 1894 fullType tya2 structnameb >>= (fun tya2 structnameb ->
34e49164
C
1895
1896 let tya1 = A.StructUnionDef(tya2,lba,declsa,rba)+> A.rewrap tya1
1897 in
1898 let tya0 = A.Type(cv1, tya1) +> A.rewrap tya0 in
1899
ae4735db 1900 match structnameb with
34e49164
C
1901 | _nQ, (B.StructUnionName (sub, s), [iisub;iisbopt]) ->
1902
1903 let typb1 = B.StructUnion (sub,sbopt, declsb),
1904 [iisub;iisbopt;lbb;rbb] in
1905 let typb0 = ((qu, il), typb1) in
ae4735db 1906
34e49164
C
1907 return (
1908 (A.TyDecl (tya0, ptvirga)) +> A.rewrap decla,
4dfbc1c2 1909 (({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
1910 B.v_type = typb0;
1911 B.v_storage = (B.StoTypedef, inl);
1912 B.v_local = local;
1913 B.v_attr = attrs;
978fd7e5 1914 B.v_type_bis = typb0bis;
485bce71 1915 },
34e49164
C
1916 iivirg),iiptvirgb,iistob)
1917 )
ae4735db 1918 | _ -> raise Impossible
34e49164
C
1919 )
1920 | _ -> raise Impossible
1921 )
1922 | _ -> fail
1923 )))))
1924 | _ -> fail
1925 )
1926 | _ -> fail
1927 )
ae4735db
C
1928
1929 | A.UnInit (stoa, typa, ida, ptvirga),
1930 ({B.v_namei= Some (nameidb, _);B.v_storage= (B.StoTypedef,_);}, iivirg)
b1b2de81 1931 -> fail
34e49164 1932
ae4735db 1933 | A.Init (stoa, typa, ida, eqa, inia, ptvirga),
b1b2de81
C
1934 ({B.v_namei=Some(nameidb, _);B.v_storage=(B.StoTypedef,_);}, iivirg)
1935 -> fail
34e49164
C
1936
1937
1938
1939 (* could handle iso here but handled in standard.iso *)
ae4735db 1940 | A.UnInit (stoa, typa, ida, ptvirga),
4dfbc1c2 1941 ({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
1942 B.v_type = typb;
1943 B.v_storage = stob;
1944 B.v_local = local;
1945 B.v_attr = attrs;
978fd7e5 1946 B.v_type_bis = typbbis;
ae4735db 1947 }, iivirg) ->
ae4735db
C
1948 tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
1949 fullType typa typb >>= (fun typa typb ->
1950 ident_cpp DontKnow ida nameidb >>= (fun ida nameidb ->
1951 storage_optional_allminus allminus stoa (stob, iistob) >>=
1952 (fun stoa (stob, iistob) ->
34e49164
C
1953 return (
1954 (A.UnInit (stoa, typa, ida, ptvirga)) +> A.rewrap decla,
4dfbc1c2 1955 (({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
1956 B.v_type = typb;
1957 B.v_storage = stob;
1958 B.v_local = local;
1959 B.v_attr = attrs;
978fd7e5 1960 B.v_type_bis = typbbis;
485bce71 1961 },iivirg),
34e49164
C
1962 iiptvirgb,iistob)
1963 )))))
1964
ae4735db 1965 | A.Init (stoa, typa, ida, eqa, inia, ptvirga),
4dfbc1c2 1966 ({B.v_namei = Some(nameidb, B.ValInit (iieqb, inib));
485bce71
C
1967 B.v_type = typb;
1968 B.v_storage = stob;
1969 B.v_local = local;
1970 B.v_attr = attrs;
978fd7e5 1971 B.v_type_bis = typbbis;
485bce71 1972 },iivirg)
34e49164 1973 ->
ae4735db
C
1974 tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
1975 tokenf eqa iieqb >>= (fun eqa iieqb ->
1976 fullType typa typb >>= (fun typa typb ->
1977 ident_cpp DontKnow ida nameidb >>= (fun ida nameidb ->
1978 storage_optional_allminus allminus stoa (stob, iistob) >>=
1979 (fun stoa (stob, iistob) ->
1980 initialiser inia inib >>= (fun inia inib ->
34e49164
C
1981 return (
1982 (A.Init (stoa, typa, ida, eqa, inia, ptvirga)) +> A.rewrap decla,
4dfbc1c2 1983 (({B.v_namei = Some(nameidb, B.ValInit (iieqb, inib));
485bce71
C
1984 B.v_type = typb;
1985 B.v_storage = stob;
1986 B.v_local = local;
1987 B.v_attr = attrs;
978fd7e5 1988 B.v_type_bis = typbbis;
485bce71 1989 },iivirg),
34e49164
C
1990 iiptvirgb,iistob)
1991 )))))))
ae4735db 1992
4dfbc1c2
C
1993 | A.Init (stoa, typa, ida, eqa, inia, ptvirga),
1994 ({B.v_namei = Some(nameidb, B.ConstrInit _);
1995 B.v_type = typb;
1996 B.v_storage = stob;
1997 B.v_local = local;
1998 B.v_attr = attrs;
1999 B.v_type_bis = typbbis;
2000 },iivirg)
2001 -> fail (* C++ constructor declaration not supported in SmPL *)
2002
34e49164 2003 (* do iso-by-absence here ? allow typedecl and var ? *)
ae4735db
C
2004 | A.TyDecl (typa, ptvirga),
2005 ({B.v_namei = None; B.v_type = typb;
2006 B.v_storage = stob;
485bce71
C
2007 B.v_local = local;
2008 B.v_attr = attrs;
978fd7e5 2009 B.v_type_bis = typbbis;
485bce71
C
2010 }, iivirg) ->
2011
b1b2de81 2012 if stob =*= (B.NoSto, false)
34e49164 2013 then
ae4735db
C
2014 tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
2015 fullType typa typb >>= (fun typa typb ->
34e49164
C
2016 return (
2017 (A.TyDecl (typa, ptvirga)) +> A.rewrap decla,
485bce71
C
2018 (({B.v_namei = None;
2019 B.v_type = typb;
2020 B.v_storage = stob;
2021 B.v_local = local;
2022 B.v_attr = attrs;
978fd7e5 2023 B.v_type_bis = typbbis;
485bce71 2024 }, iivirg), iiptvirgb, iistob)
34e49164
C
2025 )))
2026 else fail
2027
2028
ae4735db 2029 | A.Typedef (stoa, typa, ida, ptvirga),
4dfbc1c2 2030 ({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
2031 B.v_type = typb;
2032 B.v_storage = (B.StoTypedef,inline);
2033 B.v_local = local;
2034 B.v_attr = attrs;
978fd7e5 2035 B.v_type_bis = typbbis;
485bce71 2036 },iivirg) ->
34e49164 2037
ae4735db
C
2038 tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
2039 fullType typa typb >>= (fun typa typb ->
34e49164 2040 (match iistob with
ae4735db
C
2041 | [iitypedef] ->
2042 tokenf stoa iitypedef >>= (fun stoa iitypedef ->
34e49164
C
2043 return (stoa, [iitypedef])
2044 )
190f1acf 2045 | _ -> error iistob "weird, have both typedef and inline or nothing";
ae4735db 2046 ) >>= (fun stoa iistob ->
34e49164 2047 (match A.unwrap ida with
ae4735db 2048 | A.MetaType(_,_,_) ->
34e49164 2049
ae4735db
C
2050 let fake_typeb =
2051 Ast_c.nQ, ((B.TypeName (nameidb, Ast_c.noTypedefDef())), [])
34e49164 2052 in
ae4735db 2053 fullTypebis ida fake_typeb >>= (fun ida fake_typeb ->
34e49164 2054 match fake_typeb with
b1b2de81
C
2055 | _nQ, ((B.TypeName (nameidb, _typ)), []) ->
2056 return (ida, nameidb)
34e49164
C
2057 | _ -> raise Impossible
2058 )
2059
ae4735db 2060 | A.TypeName sa ->
b1b2de81 2061 (match nameidb with
ae4735db 2062 | B.RegularName (sb, iidb) ->
b1b2de81 2063 let iidb1 = tuple_of_list1 iidb in
ae4735db 2064
b1b2de81 2065 if (term sa) =$= sb
ae4735db
C
2066 then
2067 tokenf sa iidb1 >>= (fun sa iidb1 ->
b1b2de81
C
2068 return (
2069 (A.TypeName sa) +> A.rewrap ida,
2070 B.RegularName (sb, [iidb1])
2071 ))
2072 else fail
2073
2074 | B.CppConcatenatedName _ | B.CppVariadicName _ |B.CppIdentBuilder _
2075 -> raise Todo
2076 )
2077
34e49164
C
2078 | _ -> raise Impossible
2079
b1b2de81 2080 ) >>= (fun ida nameidb ->
34e49164
C
2081 return (
2082 (A.Typedef (stoa, typa, ida, ptvirga)) +> A.rewrap decla,
4dfbc1c2 2083 (({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
2084 B.v_type = typb;
2085 B.v_storage = (B.StoTypedef,inline);
2086 B.v_local = local;
2087 B.v_attr = attrs;
978fd7e5 2088 B.v_type_bis = typbbis;
485bce71 2089 },
34e49164
C
2090 iivirg),
2091 iiptvirgb, iistob)
2092 )
2093 ))))
ae4735db
C
2094
2095
2096 | _, ({B.v_namei = None;}, _) ->
0708f913 2097 (* old: failwith "no variable in this declaration, weird" *)
34e49164
C
2098 fail
2099
2100
2101
ae4735db
C
2102 | A.DisjDecl declas, declb ->
2103 declas +> List.fold_left (fun acc decla ->
2104 acc >|+|>
34e49164
C
2105 (* (declaration (mckstart, allminus, decla) declb) *)
2106 (onedecl allminus decla (declb,iiptvirgb, iistob))
2107 ) fail
2108
2109
ae4735db 2110
34e49164
C
2111 (* only in struct type decls *)
2112 | A.Ddots(dots,whencode), _ ->
2113 raise Impossible
ae4735db
C
2114
2115 | A.OptDecl _, _ | A.UniqueDecl _, _ ->
34e49164
C
2116 failwith "not handling Opt/Unique Decl"
2117
ae4735db 2118 | _, ({B.v_namei=Some _}, _) ->
b1b2de81 2119 fail
34e49164 2120
34e49164
C
2121
2122
2123
2124(* ------------------------------------------------------------------------- *)
2125
ae4735db 2126and (initialiser: (A.initialiser, Ast_c.initialiser) matcher) = fun ia ib ->
34e49164
C
2127 X.all_bound (A.get_inherited ia) >&&>
2128 match (A.unwrap ia,ib) with
2129
ae4735db 2130 | (A.MetaInit(ida,keep,inherited), ib) ->
113803cf
C
2131 let max_min _ =
2132 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_ini ib) in
2133 X.envf keep inherited (ida, Ast_c.MetaInitVal ib, max_min)
ae4735db
C
2134 (fun () ->
2135 X.distrf_ini ida ib >>= (fun ida ib ->
113803cf
C
2136 return (
2137 A.MetaInit (ida,keep,inherited) +> A.rewrap ia,
2138 ib
2139 ))
2140 )
2141
ae4735db 2142 | (A.InitExpr expa, ib) ->
34e49164 2143 (match A.unwrap expa, ib with
ae4735db
C
2144 | A.Edots (mcode, None), ib ->
2145 X.distrf_ini (dots2metavar mcode) ib >>= (fun mcode ib ->
34e49164 2146 return (
ae4735db
C
2147 A.InitExpr
2148 (A.Edots (metavar2dots mcode, None) +> A.rewrap expa)
34e49164
C
2149 +> A.rewrap ia,
2150 ib
2151 ))
2152
2153 | A.Edots (_, Some expr), _ -> failwith "not handling when on Edots"
2154
ae4735db 2155 | _, (B.InitExpr expb, ii) ->
34e49164 2156 assert (null ii);
ae4735db 2157 expression expa expb >>= (fun expa expb ->
34e49164
C
2158 return (
2159 (A.InitExpr expa) +> A.rewrap ia,
2160 (B.InitExpr expb, ii)
2161 ))
2162 | _ -> fail
2163 )
2164
c491d8ee
C
2165 | (A.ArInitList (ia1, ias, ia2), (B.InitList ibs, ii)) ->
2166 (match ii with
2167 | ib1::ib2::iicommaopt ->
2168 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
2169 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
2170 ar_initialisers (A.undots ias) (ibs, iicommaopt) >>=
2171 (fun iasundots (ibs,iicommaopt) ->
2172 return (
2173 (A.ArInitList (ia1, redots ias iasundots, ia2)) +> A.rewrap ia,
2174 (B.InitList ibs, ib1::ib2::iicommaopt)
2175 ))))
2176
2177 | _ -> raise Impossible
2178 )
2179
2180 | (A.StrInitList (allminus, ia1, ias, ia2, []), (B.InitList ibs, ii)) ->
ae4735db
C
2181 (match ii with
2182 | ib1::ib2::iicommaopt ->
34e49164
C
2183 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
2184 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
c491d8ee 2185 str_initialisers allminus ias (ibs, iicommaopt) >>=
90aeb998 2186 (fun ias (ibs,iicommaopt) ->
34e49164 2187 return (
c491d8ee 2188 (A.StrInitList (allminus, ia1, ias, ia2, [])) +> A.rewrap ia,
34e49164
C
2189 (B.InitList ibs, ib1::ib2::iicommaopt)
2190 ))))
ae4735db 2191
34e49164
C
2192 | _ -> raise Impossible
2193 )
2194
c491d8ee
C
2195 | (A.StrInitList (allminus, i1, ias, i2, whencode),
2196 (B.InitList ibs, _ii)) ->
34e49164
C
2197 failwith "TODO: not handling whencode in initialisers"
2198
2199
ae4735db 2200 | (A.InitGccExt (designatorsa, ia2, inia),
113803cf 2201 (B.InitDesignators (designatorsb, inib), ii2))->
34e49164 2202
34e49164
C
2203 let iieq = tuple_of_list1 ii2 in
2204
ae4735db 2205 tokenf ia2 iieq >>= (fun ia2 iieq ->
113803cf
C
2206 designators designatorsa designatorsb >>=
2207 (fun designatorsa designatorsb ->
ae4735db 2208 initialiser inia inib >>= (fun inia inib ->
34e49164 2209 return (
113803cf
C
2210 (A.InitGccExt (designatorsa, ia2, inia)) +> A.rewrap ia,
2211 (B.InitDesignators (designatorsb, inib), [iieq])
2212 ))))
34e49164
C
2213
2214
2215
2216
ae4735db
C
2217 | (A.InitGccName (ida, ia1, inia), (B.InitFieldOld (idb, inib), ii)) ->
2218 (match ii with
2219 | [iidb;iicolon] ->
2220 ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
2221 initialiser inia inib >>= (fun inia inib ->
2222 tokenf ia1 iicolon >>= (fun ia1 iicolon ->
34e49164
C
2223 return (
2224 (A.InitGccName (ida, ia1, inia)) +> A.rewrap ia,
2225 (B.InitFieldOld (idb, inib), [iidb;iicolon])
2226 ))))
2227 | _ -> fail
2228 )
2229
2230
2231
2232 | A.IComma(comma), _ ->
2233 raise Impossible
2234
ae4735db 2235 | A.UniqueIni _,_ | A.OptIni _,_ ->
34e49164 2236 failwith "not handling Opt/Unique on initialisers"
485bce71 2237
ae4735db
C
2238 | _, (B.InitIndexOld (_, _), _) -> fail
2239 | _, (B.InitFieldOld (_, _), _) -> fail
485bce71
C
2240
2241 | _, ((B.InitDesignators (_, _)|B.InitList _|B.InitExpr _), _)
2242 -> fail
2243
113803cf
C
2244and designators dla dlb =
2245 match (dla,dlb) with
2246 ([],[]) -> return ([], [])
2247 | ([],_) | (_,[]) -> fail
2248 | (da::dla,db::dlb) ->
2249 designator da db >>= (fun da db ->
2250 designators dla dlb >>= (fun dla dlb ->
2251 return (da::dla, db::dlb)))
2252
2253and designator da db =
2254 match (da,db) with
2255 (A.DesignatorField (ia1, ida), (B.DesignatorField idb,ii1)) ->
34e49164 2256
113803cf 2257 let (iidot, iidb) = tuple_of_list2 ii1 in
ae4735db 2258 tokenf ia1 iidot >>= (fun ia1 iidot ->
113803cf
C
2259 ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
2260 return (
2261 A.DesignatorField (ia1, ida),
2262 (B.DesignatorField idb, [iidot;iidb])
2263 )))
2264
2265 | (A.DesignatorIndex (ia1,ea,ia2), (B.DesignatorIndex eb, ii1)) ->
ae4735db 2266
113803cf 2267 let (ib1, ib2) = tuple_of_list2 ii1 in
ae4735db
C
2268 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
2269 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
2270 expression ea eb >>= (fun ea eb ->
113803cf
C
2271 return (
2272 A.DesignatorIndex (ia1,ea,ia2),
2273 (B.DesignatorIndex eb, [ib1;ib2])
2274 ))))
34e49164 2275
113803cf
C
2276 | (A.DesignatorRange (ia1,e1a,ia2,e2a,ia3),
2277 (B.DesignatorRange (e1b, e2b), ii1)) ->
34e49164 2278
113803cf 2279 let (ib1, ib2, ib3) = tuple_of_list3 ii1 in
ae4735db
C
2280 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
2281 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
2282 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
2283 expression e1a e1b >>= (fun e1a e1b ->
2284 expression e2a e2b >>= (fun e2a e2b ->
113803cf
C
2285 return (
2286 A.DesignatorRange (ia1,e1a,ia2,e2a,ia3),
2287 (B.DesignatorRange (e1b, e2b), [ib1;ib2;ib3])
2288 ))))))
2289 | (_, ((B.DesignatorField _|B.DesignatorIndex _|B.DesignatorRange _), _)) ->
2290 fail
34e49164 2291
c491d8ee 2292and str_initialisers = fun allminus ias (ibs, iicomma) ->
34e49164
C
2293 let ias_unsplit = unsplit_icomma ias in
2294 let ibs_split = resplit_initialiser ibs iicomma in
2295
c491d8ee
C
2296 if need_unordered_initialisers ibs
2297 then initialisers_unordered2 allminus ias_unsplit ibs_split >>=
2298 (fun ias_unsplit ibs_split ->
2299 return (
2300 split_icomma ias_unsplit,
2301 unsplit_initialiser ibs_split))
2302 else fail
2303
2304and ar_initialisers = fun ias (ibs, iicomma) ->
2305 (* this doesn't check need_unordered_initialisers because ... can be
2306 implemented as ordered, even if it matches unordered initializers *)
2307 let ibs = resplit_initialiser ibs iicomma in
2308 let ibs =
2309 List.concat
2310 (List.map (function (elem,comma) -> [Left elem; Right [comma]]) ibs) in
2311 initialisers_ordered2 ias ibs >>=
2312 (fun ias ibs_split ->
2313 let ibs,iicomma =
2314 match List.rev ibs_split with
2315 (Right comma)::rest -> (Ast_c.unsplit_comma (List.rev rest),comma)
2316 | (Left _)::_ -> (Ast_c.unsplit_comma ibs_split,[]) (* possible *)
2317 | [] -> ([],[]) in
2318 return (ias, (ibs,iicomma)))
34e49164 2319
ae4735db 2320and initialisers_ordered2 = fun ias ibs ->
c491d8ee
C
2321 let match_dots ea =
2322 match A.unwrap ea with
2323 A.Idots(mcode, optexpr) -> Some (mcode, optexpr)
2324 | _ -> None in
2325 let build_dots (mcode, optexpr) = A.Idots(mcode, optexpr) in
2326 let match_comma ea =
2327 match A.unwrap ea with
2328 A.IComma ia1 -> Some ia1
2329 | _ -> None in
2330 let build_comma ia1 = A.IComma ia1 in
8f657093
C
2331 let match_metalist ea =
2332 match A.unwrap ea with
2333 A.MetaInitList(ida,leninfo,keep,inherited) ->
2334 Some(ida,leninfo,keep,inherited)
2335 | _ -> None in
2336 let build_metalist (ida,leninfo,keep,inherited) =
2337 A.MetaInitList(ida,leninfo,keep,inherited) in
2338 let mktermval v = Ast_c.MetaInitListVal v in
c491d8ee
C
2339 let special_cases ea eas ebs = None in
2340 let no_ii x = failwith "not possible" in
2341 list_matcher match_dots build_dots match_comma build_comma
2342 match_metalist build_metalist mktermval
2343 special_cases initialiser X.distrf_inis no_ii ias ibs
34e49164 2344
90aeb998 2345and initialisers_unordered2 = fun allminus ias ibs ->
34e49164 2346 match ias, ibs with
90aeb998
C
2347 | [], ys ->
2348 if allminus
2349 then
2350 let rec loop = function
2351 [] -> return ([],[])
2352 | (ib,comma)::ibs ->
2353 X.distrf_ini minusizer ib >>= (fun _ ib ->
2354 tokenf minusizer comma >>= (fun _ comma ->
2355 loop ibs >>= (fun l ibs ->
2356 return(l,(ib,comma)::ibs)))) in
2357 loop ibs
2358 else return ([], ys)
c491d8ee 2359 | x::xs, ys ->
34e49164 2360 let permut = Common.uncons_permut_lazy ys in
ae4735db
C
2361 permut +> List.fold_left (fun acc ((e, pos), rest) ->
2362 acc >||>
c491d8ee 2363 (initialiser_comma x e
ae4735db 2364 >>= (fun x e ->
34e49164 2365 let rest = Lazy.force rest in
90aeb998 2366 initialisers_unordered2 allminus xs rest >>= (fun xs rest ->
34e49164
C
2367 return (
2368 x::xs,
2369 Common.insert_elem_pos (e, pos) rest
2370 ))))
2371 ) fail
ae4735db 2372
c491d8ee
C
2373and initialiser_comma (x,xcomma) (y, commay) =
2374 match A.unwrap xcomma with
2375 A.IComma commax ->
2376 tokenf commax commay >>= (fun commax commay ->
2377 initialiser x y >>= (fun x y ->
2378 return (
2379 (x, (A.IComma commax) +> A.rewrap xcomma),
2380 (y, commay))))
2381 | _ -> raise Impossible (* unsplit_iicomma wrong *)
34e49164
C
2382
2383(* ------------------------------------------------------------------------- *)
485bce71 2384and (struct_fields: (A.declaration list, B.field list) matcher) =
ae4735db 2385 fun eas ebs ->
c491d8ee
C
2386 let match_dots ea =
2387 match A.unwrap ea with
2388 A.Ddots(mcode, optexpr) -> Some (mcode, optexpr)
2389 | _ -> None in
2390 let build_dots (mcode, optexpr) = A.Ddots(mcode, optexpr) in
2391 let match_comma ea = None in
2392 let build_comma ia1 = failwith "not possible" in
190f1acf
C
2393 let match_metalist ea =
2394 match A.unwrap ea with
2395 A.MetaFieldList(ida,leninfo,keep,inherited) ->
2396 Some(ida,leninfo,keep,inherited)
2397 | _ -> None in
2398 let build_metalist (ida,leninfo,keep,inherited) =
2399 A.MetaFieldList(ida,leninfo,keep,inherited) in
2400 let mktermval v =
2401 (* drop empty ii information, because nothing between elements *)
2402 let v = List.map Ast_c.unwrap v in
2403 Ast_c.MetaFieldListVal v in
c491d8ee
C
2404 let special_cases ea eas ebs = None in
2405 let no_ii x = failwith "not possible" in
2406 let make_ebs ebs = List.map (function x -> Left x) ebs in
2407 let unmake_ebs ebs =
2408 List.map (function Left x -> x | Right x -> failwith "no right") ebs in
2409 let distrf mcode startxs =
2410 let startxs = unmake_ebs startxs in
2411 X.distrf_struct_fields mcode startxs >>=
2412 (fun mcode startxs -> return (mcode,make_ebs startxs)) in
2413 list_matcher match_dots build_dots match_comma build_comma
2414 match_metalist build_metalist mktermval
2415 special_cases struct_field distrf no_ii eas (make_ebs ebs) >>=
2416 (fun eas ebs -> return (eas,unmake_ebs ebs))
34e49164 2417
ae4735db 2418and (struct_field: (A.declaration, B.field) matcher) = fun fa fb ->
34e49164 2419
413ffc02
C
2420 match A.unwrap fa,fb with
2421 | A.MetaField (ida,keep,inherited), _ ->
2422 let max_min _ =
2423 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_field fb) in
2424 X.envf keep inherited (ida, Ast_c.MetaFieldVal fb, max_min) (fun () ->
2425 X.distrf_field ida fb
2426 ) >>= (fun ida fb ->
2427 return ((A.MetaField (ida, keep, inherited))+> A.rewrap fa,
2428 fb))
2429 | _,B.DeclarationField (B.FieldDeclList (onefield_multivars,iiptvirg)) ->
485bce71
C
2430
2431 let iiptvirgb = tuple_of_list1 iiptvirg in
34e49164
C
2432
2433 (match onefield_multivars with
2434 | [] -> raise Impossible
ae4735db 2435 | [onevar,iivirg] ->
34e49164
C
2436 assert (null iivirg);
2437 (match onevar with
ae4735db 2438 | B.BitField (sopt, typb, _, expr) ->
34e49164
C
2439 pr2_once "warning: bitfield not handled by ast_cocci";
2440 fail
ae4735db 2441 | B.Simple (None, typb) ->
34e49164
C
2442 pr2_once "warning: unamed struct field not handled by ast_cocci";
2443 fail
ae4735db 2444 | B.Simple (Some nameidb, typb) ->
34e49164
C
2445
2446 (* build a declaration from a struct field *)
2447 let allminus = false in
2448 let iisto = [] in
2449 let stob = B.NoSto, false in
ae4735db 2450 let fake_var =
4dfbc1c2 2451 ({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
2452 B.v_type = typb;
2453 B.v_storage = stob;
2454 B.v_local = Ast_c.NotLocalDecl;
2455 B.v_attr = Ast_c.noattr;
ae4735db 2456 B.v_type_bis = ref None;
978fd7e5
C
2457 (* the struct field should also get expanded ? no it's not
2458 * important here, we will rematch very soon *)
485bce71 2459 },
ae4735db 2460 iivirg)
34e49164 2461 in
ae4735db
C
2462 onedecl allminus fa (fake_var,iiptvirgb,iisto) >>=
2463 (fun fa (var,iiptvirgb,iisto) ->
34e49164
C
2464
2465 match fake_var with
4dfbc1c2 2466 | ({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
2467 B.v_type = typb;
2468 B.v_storage = stob;
ae4735db 2469 }, iivirg) ->
b1b2de81
C
2470
2471 let onevar = B.Simple (Some nameidb, typb) in
ae4735db 2472
34e49164
C
2473 return (
2474 (fa),
ae4735db 2475 ((B.DeclarationField
708f4980
C
2476 (B.FieldDeclList ([onevar, iivirg], [iiptvirgb])))
2477 )
34e49164
C
2478 )
2479 | _ -> raise Impossible
2480 )
2481 )
2482
ae4735db 2483 | x::y::xs ->
34e49164
C
2484 pr2_once "PB: More that one variable in decl. Have to split";
2485 fail
2486 )
413ffc02 2487 | _,B.EmptyField _iifield ->
485bce71
C
2488 fail
2489
413ffc02
C
2490 | A.MacroDecl (sa,lpa,eas,rpa,enda),B.MacroDeclField ((sb,ebs),ii) ->
2491 raise Todo
2492 | _,B.MacroDeclField ((sb,ebs),ii) -> fail
708f4980 2493
413ffc02
C
2494 | _,B.CppDirectiveStruct directive -> fail
2495 | _,B.IfdefStruct directive -> fail
34e49164
C
2496
2497
c491d8ee
C
2498and enum_fields = fun eas ebs ->
2499 let match_dots ea =
2500 match A.unwrap ea with
2501 A.Edots(mcode, optexpr) -> Some (mcode, optexpr)
2502 | _ -> None in
2503 let build_dots (mcode, optexpr) = A.Edots(mcode, optexpr) in
2504 let match_comma ea =
2505 match A.unwrap ea with
2506 A.EComma ia1 -> Some ia1
2507 | _ -> None in
2508 let build_comma ia1 = A.EComma ia1 in
2509 let match_metalist ea = None in
2510 let build_metalist (ida,leninfo,keep,inherited) = failwith "not possible" in
2511 let mktermval v = failwith "not possible" in
2512 let special_cases ea eas ebs = None in
2513 list_matcher match_dots build_dots match_comma build_comma
2514 match_metalist build_metalist mktermval
2515 special_cases enum_field X.distrf_enum_fields
2516 Lib_parsing_c.ii_of_enum_fields eas ebs
2517
2518and enum_field ida idb =
2519 X.all_bound (A.get_inherited ida) >&&>
2520 match A.unwrap ida, idb with
2521 A.Ident(id),(nameidb,None) ->
2522 ident_cpp DontKnow id nameidb >>= (fun id nameidb ->
2523 return ((A.Ident id) +> A.rewrap ida, (nameidb,None)))
2524 | A.Assignment(ea1,opa,ea2,init),(nameidb,Some(opbi,eb2)) ->
2525 (match A.unwrap ea1 with
2526 A.Ident(id) ->
2527 ident_cpp DontKnow id nameidb >>= (fun id nameidb ->
2528 expression ea2 eb2 >>= (fun ea2 eb2 ->
2529 tokenf opa opbi >>= (fun opa opbi -> (* only one kind of assignop *)
2530 return (
2531 (A.Assignment((A.Ident(id))+>A.rewrap ea1,opa,ea2,init)) +>
2532 A.rewrap ida,
2533 (nameidb,Some(opbi,eb2))))))
2534 | _ -> failwith "not possible")
2535 | _ -> failwith "not possible"
34e49164
C
2536
2537(* ------------------------------------------------------------------------- *)
ae4735db
C
2538and (fullType: (A.fullType, Ast_c.fullType) matcher) =
2539 fun typa typb ->
2540 X.optional_qualifier_flag (fun optional_qualifier ->
34e49164
C
2541 X.all_bound (A.get_inherited typa) >&&>
2542 match A.unwrap typa, typb with
2543 | A.Type(cv,ty1), ((qu,il),ty2) ->
2544
ae4735db 2545 if qu.B.const && qu.B.volatile
34e49164
C
2546 then
2547 pr2_once
ae4735db 2548 ("warning: the type is both const & volatile but cocci " ^
34e49164
C
2549 "does not handle that");
2550
2551 (* Drop out the const/volatile part that has been matched.
2552 * This is because a SP can contain const T v; in which case
2553 * later in match_t_t when we encounter a T, we must not add in
2554 * the environment the whole type.
2555 *)
ae4735db 2556
34e49164
C
2557
2558 (match cv with
2559 (* "iso-by-absence" *)
ae4735db
C
2560 | None ->
2561 let do_stuff () =
2562 fullTypebis ty1 ((qu,il), ty2) >>= (fun ty1 fullty2 ->
34e49164
C
2563 return (
2564 (A.Type(None, ty1)) +> A.rewrap typa,
2565 fullty2
2566 ))
2567 in
2568 (match optional_qualifier, qu.B.const || qu.B.volatile with
2569 | false, false -> do_stuff ()
2570 | false, true -> fail
2571 | true, false -> do_stuff ()
ae4735db
C
2572 | true, true ->
2573 if !Flag.show_misc
34e49164
C
2574 then pr2_once "USING optional_qualifier builtin isomorphism";
2575 do_stuff()
2576 )
ae4735db
C
2577
2578
2579 | Some x ->
2580 (* todo: can be __const__ ? can be const & volatile so
2581 * should filter instead ?
34e49164 2582 *)
ae4735db
C
2583 (match term x, il with
2584 | A.Const, [i1] when qu.B.const ->
2585
2586 tokenf x i1 >>= (fun x i1 ->
2587 fullTypebis ty1 (Ast_c.nQ,ty2) >>= (fun ty1 (_, ty2) ->
34e49164
C
2588 return (
2589 (A.Type(Some x, ty1)) +> A.rewrap typa,
2590 ((qu, [i1]), ty2)
2591 )))
ae4735db
C
2592
2593 | A.Volatile, [i1] when qu.B.volatile ->
2594 tokenf x i1 >>= (fun x i1 ->
2595 fullTypebis ty1 (Ast_c.nQ,ty2) >>= (fun ty1 (_, ty2) ->
34e49164
C
2596 return (
2597 (A.Type(Some x, ty1)) +> A.rewrap typa,
2598 ((qu, [i1]), ty2)
2599 )))
ae4735db 2600
34e49164
C
2601 | _ -> fail
2602 )
2603 )
2604
ae4735db 2605 | A.DisjType typas, typb ->
34e49164
C
2606 typas +>
2607 List.fold_left (fun acc typa -> acc >|+|> (fullType typa typb)) fail
2608
2609 | A.OptType(_), _ | A.UniqueType(_), _
2610 -> failwith "not handling Opt/Unique on type"
2611 )
ae4735db 2612
34e49164
C
2613
2614(*
2615 * Why not (A.typeC, Ast_c.typeC) matcher ?
ae4735db 2616 * because when there is MetaType, we want that T record the whole type,
34e49164
C
2617 * including the qualifier, and so this type (and the new_il function in
2618 * preceding function).
2619*)
2620
ae4735db
C
2621and (fullTypebis: (A.typeC, Ast_c.fullType) matcher) =
2622 fun ta tb ->
2623 X.all_bound (A.get_inherited ta) >&&>
34e49164
C
2624 match A.unwrap ta, tb with
2625
2626 (* cas general *)
ae4735db 2627 | A.MetaType(ida,keep, inherited), typb ->
34e49164
C
2628 let max_min _ =
2629 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_type typb) in
ae4735db
C
2630 X.envf keep inherited (ida, B.MetaTypeVal typb, max_min) (fun () ->
2631 X.distrf_type ida typb >>= (fun ida typb ->
34e49164
C
2632 return (
2633 A.MetaType(ida,keep, inherited) +> A.rewrap ta,
2634 typb
2635 ))
2636 )
ae4735db
C
2637 | unwrap, (qub, typb) ->
2638 typeC ta typb >>= (fun ta typb ->
34e49164
C
2639 return (ta, (qub, typb))
2640 )
2641
faf9a90c 2642and simulate_signed ta basea stringsa signaopt tb baseb ii rebuilda =
34e49164
C
2643 (* In ii there is a list, sometimes of length 1 or 2 or 3.
2644 * And even if in baseb we have a Signed Int, that does not mean
2645 * that ii is of length 2, cos Signed is the default, so if in signa
ae4735db 2646 * we have Signed explicitely ? we cant "accrocher" this mcode to
34e49164
C
2647 * something :( So for the moment when there is signed in cocci,
2648 * we force that there is a signed in c too (done in pattern.ml).
2649 *)
2650 let signbopt, iibaseb = split_signb_baseb_ii (baseb, ii) in
2651
ae4735db 2652
34e49164
C
2653 (* handle some iso on type ? (cf complex C rule for possible implicit
2654 casting) *)
faf9a90c 2655 match basea, baseb with
1eddfd50
C
2656 | A.VoidType, B.Void
2657 | A.FloatType, B.FloatType (B.CFloat)
2658 | A.DoubleType, B.FloatType (B.CDouble)
2659 | A.SizeType, B.SizeType
2660 | A.SSizeType, B.SSizeType
2661 | A.PtrDiffType,B.PtrDiffType ->
ae4735db 2662 assert (signaopt =*= None);
faf9a90c 2663 let stringa = tuple_of_list1 stringsa in
ae4735db
C
2664 let (ibaseb) = tuple_of_list1 ii in
2665 tokenf stringa ibaseb >>= (fun stringa ibaseb ->
34e49164 2666 return (
faf9a90c 2667 (rebuilda ([stringa], signaopt)) +> A.rewrap ta,
34e49164
C
2668 (B.BaseType baseb, [ibaseb])
2669 ))
ae4735db
C
2670
2671 | A.CharType, B.IntType B.CChar when signaopt =*= None ->
faf9a90c 2672 let stringa = tuple_of_list1 stringsa in
34e49164 2673 let ibaseb = tuple_of_list1 ii in
ae4735db 2674 tokenf stringa ibaseb >>= (fun stringa ibaseb ->
34e49164 2675 return (
faf9a90c 2676 (rebuilda ([stringa], signaopt)) +> A.rewrap ta,
34e49164
C
2677 (B.BaseType (B.IntType B.CChar), [ibaseb])
2678 ))
ae4735db
C
2679
2680 | A.CharType,B.IntType (B.Si (_sign, B.CChar2)) when signaopt <> None ->
faf9a90c 2681 let stringa = tuple_of_list1 stringsa in
34e49164 2682 let ibaseb = tuple_of_list1 iibaseb in
ae4735db
C
2683 sign signaopt signbopt >>= (fun signaopt iisignbopt ->
2684 tokenf stringa ibaseb >>= (fun stringa ibaseb ->
34e49164 2685 return (
faf9a90c 2686 (rebuilda ([stringa], signaopt)) +> A.rewrap ta,
34e49164
C
2687 (B.BaseType (baseb), iisignbopt ++ [ibaseb])
2688 )))
ae4735db
C
2689
2690 | A.ShortType, B.IntType (B.Si (_, B.CShort))
2691 | A.IntType, B.IntType (B.Si (_, B.CInt))
34e49164 2692 | A.LongType, B.IntType (B.Si (_, B.CLong)) ->
faf9a90c 2693 let stringa = tuple_of_list1 stringsa in
ae4735db
C
2694 (match iibaseb with
2695 | [] ->
34e49164
C
2696 (* iso-by-presence ? *)
2697 (* when unsigned int in SP, allow have just unsigned in C ? *)
faf9a90c 2698 if mcode_contain_plus (mcodekind stringa)
34e49164 2699 then fail
ae4735db
C
2700 else
2701
2702 sign signaopt signbopt >>= (fun signaopt iisignbopt ->
34e49164 2703 return (
faf9a90c 2704 (rebuilda ([stringa], signaopt)) +> A.rewrap ta,
34e49164
C
2705 (B.BaseType (baseb), iisignbopt ++ [])
2706 ))
34e49164 2707
ae4735db
C
2708
2709 | [x;y] ->
2710 pr2_once
34e49164
C
2711 "warning: long int or short int not handled by ast_cocci";
2712 fail
2713
ae4735db
C
2714 | [ibaseb] ->
2715 sign signaopt signbopt >>= (fun signaopt iisignbopt ->
2716 tokenf stringa ibaseb >>= (fun stringa ibaseb ->
34e49164 2717 return (
faf9a90c 2718 (rebuilda ([stringa], signaopt)) +> A.rewrap ta,
34e49164
C
2719 (B.BaseType (baseb), iisignbopt ++ [ibaseb])
2720 )))
2721 | _ -> raise Impossible
2722
2723 )
2724
ae4735db 2725
faf9a90c
C
2726 | A.LongLongType, B.IntType (B.Si (_, B.CLongLong)) ->
2727 let (string1a,string2a) = tuple_of_list2 stringsa in
ae4735db
C
2728 (match iibaseb with
2729 [ibase1b;ibase2b] ->
2730 sign signaopt signbopt >>= (fun signaopt iisignbopt ->
2731 tokenf string1a ibase1b >>= (fun base1a ibase1b ->
2732 tokenf string2a ibase2b >>= (fun base2a ibase2b ->
faf9a90c
C
2733 return (
2734 (rebuilda ([base1a;base2a], signaopt)) +> A.rewrap ta,
2735 (B.BaseType (baseb), iisignbopt ++ [ibase1b;ibase2b])
2736 ))))
2737 | [] -> fail (* should something be done in this case? *)
2738 | _ -> raise Impossible)
2739
2740
ae4735db
C
2741 | _, B.FloatType B.CLongDouble
2742 ->
2743 pr2_once
faf9a90c 2744 "warning: long double not handled by ast_cocci";
34e49164 2745 fail
485bce71 2746
1eddfd50
C
2747 | _, (B.Void|B.FloatType _|B.IntType _
2748 |B.SizeType|B.SSizeType|B.PtrDiffType) -> fail
485bce71 2749
faf9a90c
C
2750and simulate_signed_meta ta basea signaopt tb baseb ii rebuilda =
2751 (* In ii there is a list, sometimes of length 1 or 2 or 3.
2752 * And even if in baseb we have a Signed Int, that does not mean
2753 * that ii is of length 2, cos Signed is the default, so if in signa
ae4735db 2754 * we have Signed explicitely ? we cant "accrocher" this mcode to
faf9a90c
C
2755 * something :( So for the moment when there is signed in cocci,
2756 * we force that there is a signed in c too (done in pattern.ml).
2757 *)
2758 let signbopt, iibaseb = split_signb_baseb_ii (baseb, ii) in
2759
ae4735db
C
2760 let match_to_type rebaseb =
2761 sign signaopt signbopt >>= (fun signaopt iisignbopt ->
faf9a90c 2762 let fta = A.rewrap basea (A.Type(None,basea)) in
b1b2de81 2763 let ftb = Ast_c.nQ,(B.BaseType (rebaseb), iibaseb) in
faf9a90c
C
2764 fullType fta ftb >>= (fun fta (_,tb) ->
2765 (match A.unwrap fta,tb with
2766 A.Type(_,basea), (B.BaseType baseb, ii) ->
faf9a90c
C
2767 return (
2768 (rebuilda (basea, signaopt)) +> A.rewrap ta,
b1b2de81 2769 (B.BaseType (baseb), iisignbopt ++ ii)
faf9a90c
C
2770 )
2771 | _ -> failwith "not possible"))) in
ae4735db 2772
faf9a90c
C
2773 (* handle some iso on type ? (cf complex C rule for possible implicit
2774 casting) *)
2775 match baseb with
2776 | B.IntType (B.Si (_sign, B.CChar2)) ->
2777 match_to_type (B.IntType B.CChar)
ae4735db 2778
faf9a90c 2779 | B.IntType (B.Si (_, ty)) ->
ae4735db 2780 (match iibaseb with
faf9a90c
C
2781 | [] -> fail (* metavariable has to match something *)
2782
b1b2de81 2783 | _ -> match_to_type (B.IntType (B.Si (B.Signed, ty)))
34e49164 2784
faf9a90c
C
2785 )
2786
1eddfd50
C
2787 | (B.Void|B.FloatType _|B.IntType _
2788 |B.SizeType|B.SSizeType|B.PtrDiffType) -> fail
faf9a90c 2789
ae4735db
C
2790and (typeC: (A.typeC, Ast_c.typeC) matcher) =
2791 fun ta tb ->
faf9a90c 2792 match A.unwrap ta, tb with
ae4735db 2793 | A.BaseType (basea,stringsa), (B.BaseType baseb, ii) ->
faf9a90c
C
2794 simulate_signed ta basea stringsa None tb baseb ii
2795 (function (stringsa, signaopt) -> A.BaseType (basea,stringsa))
ae4735db 2796 | A.SignedT (signaopt, Some basea), (B.BaseType baseb, ii) ->
faf9a90c
C
2797 (match A.unwrap basea with
2798 A.BaseType (basea1,strings1) ->
2799 simulate_signed ta basea1 strings1 (Some signaopt) tb baseb ii
2800 (function (strings1, Some signaopt) ->
2801 A.SignedT
2802 (signaopt,
2803 Some (A.rewrap basea (A.BaseType (basea1,strings1))))
2804 | _ -> failwith "not possible")
2805 | A.MetaType(ida,keep,inherited) ->
2806 simulate_signed_meta ta basea (Some signaopt) tb baseb ii
2807 (function (basea, Some signaopt) ->
2808 A.SignedT(signaopt,Some basea)
2809 | _ -> failwith "not possible")
2810 | _ -> failwith "not possible")
ae4735db 2811 | A.SignedT (signa,None), (B.BaseType baseb, ii) ->
34e49164
C
2812 let signbopt, iibaseb = split_signb_baseb_ii (baseb, ii) in
2813 (match iibaseb, baseb with
ae4735db
C
2814 | [], B.IntType (B.Si (_sign, B.CInt)) ->
2815 sign (Some signa) signbopt >>= (fun signaopt iisignbopt ->
34e49164
C
2816 match signaopt with
2817 | None -> raise Impossible
ae4735db 2818 | Some signa ->
34e49164 2819 return (
faf9a90c 2820 (A.SignedT (signa,None)) +> A.rewrap ta,
34e49164
C
2821 (B.BaseType baseb, iisignbopt)
2822 )
2823 )
2824 | _ -> fail
2825 )
2826
2827
2828
2829 (* todo? iso with array *)
ae4735db
C
2830 | A.Pointer (typa, iamult), (B.Pointer typb, ii) ->
2831 let (ibmult) = tuple_of_list1 ii in
2832 fullType typa typb >>= (fun typa typb ->
2833 tokenf iamult ibmult >>= (fun iamult ibmult ->
34e49164
C
2834 return (
2835 (A.Pointer (typa, iamult)) +> A.rewrap ta,
2836 (B.Pointer typb, [ibmult])
2837 )))
2838
ae4735db
C
2839 | A.FunctionType(allminus,tyaopt,lpa,paramsa,rpa),
2840 (B.FunctionType(tyb, (paramsb, (isvaargs, iidotsb))), ii) ->
34e49164
C
2841
2842 let (lpb, rpb) = tuple_of_list2 ii in
ae4735db 2843 if isvaargs
34e49164
C
2844 then
2845 pr2_once
2846 ("Not handling well variable length arguments func. "^
2847 "You have been warned");
ae4735db
C
2848 tokenf lpa lpb >>= (fun lpa lpb ->
2849 tokenf rpa rpb >>= (fun rpa rpb ->
2850 fullType_optional_allminus allminus tyaopt tyb >>= (fun tyaopt tyb ->
34e49164 2851 parameters (seqstyle paramsa) (A.undots paramsa) paramsb >>=
ae4735db 2852 (fun paramsaundots paramsb ->
34e49164
C
2853 let paramsa = redots paramsa paramsaundots in
2854 return (
2855 (A.FunctionType(allminus,tyaopt,lpa,paramsa,rpa) +> A.rewrap ta,
2856 (B.FunctionType(tyb, (paramsb, (isvaargs, iidotsb))), [lpb;rpb])
2857 )
2858 )))))
34e49164 2859
34e49164 2860
ae4735db
C
2861
2862
2863
2864 | A.FunctionPointer(tya,lp1a,stara,rp1a,lp2a,paramsa,rp2a),
34e49164
C
2865 (B.ParenType t1, ii) ->
2866 let (lp1b, rp1b) = tuple_of_list2 ii in
2867 let (qu1b, t1b) = t1 in
2868 (match t1b with
ae4735db 2869 | B.Pointer t2, ii ->
34e49164
C
2870 let (starb) = tuple_of_list1 ii in
2871 let (qu2b, t2b) = t2 in
2872 (match t2b with
ae4735db 2873 | B.FunctionType (tyb, (paramsb, (isvaargs, iidotsb))), ii ->
34e49164
C
2874 let (lp2b, rp2b) = tuple_of_list2 ii in
2875
2876 if isvaargs
2877 then
2878 pr2_once
2879 ("Not handling well variable length arguments func. "^
2880 "You have been warned");
2881
ae4735db
C
2882 fullType tya tyb >>= (fun tya tyb ->
2883 tokenf lp1a lp1b >>= (fun lp1a lp1b ->
2884 tokenf rp1a rp1b >>= (fun rp1a rp1b ->
2885 tokenf lp2a lp2b >>= (fun lp2a lp2b ->
2886 tokenf rp2a rp2b >>= (fun rp2a rp2b ->
2887 tokenf stara starb >>= (fun stara starb ->
34e49164 2888 parameters (seqstyle paramsa) (A.undots paramsa) paramsb >>=
ae4735db 2889 (fun paramsaundots paramsb ->
34e49164
C
2890 let paramsa = redots paramsa paramsaundots in
2891
ae4735db
C
2892 let t2 =
2893 (qu2b,
34e49164 2894 (B.FunctionType (tyb, (paramsb, (isvaargs, iidotsb))),
ae4735db 2895 [lp2b;rp2b]))
34e49164 2896 in
ae4735db 2897 let t1 =
34e49164
C
2898 (qu1b,
2899 (B.Pointer t2, [starb]))
2900 in
ae4735db 2901
34e49164
C
2902 return (
2903 (A.FunctionPointer(tya,lp1a,stara,rp1a,lp2a,paramsa,rp2a))
2904 +> A.rewrap ta,
2905 (B.ParenType t1, [lp1b;rp1b])
2906 )
2907 )))))))
2908
2909
2910
2911 | _ -> fail
2912 )
2913 | _ -> fail
2914 )
ae4735db
C
2915
2916
34e49164
C
2917
2918 (* todo: handle the iso on optionnal size specifification ? *)
ae4735db 2919 | A.Array (typa, ia1, eaopt, ia2), (B.Array (ebopt, typb), ii) ->
34e49164 2920 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
2921 fullType typa typb >>= (fun typa typb ->
2922 option expression eaopt ebopt >>= (fun eaopt ebopt ->
2923 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
2924 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
34e49164
C
2925 return (
2926 (A.Array (typa, ia1, eaopt, ia2)) +> A.rewrap ta,
2927 (B.Array (ebopt, typb), [ib1;ib2])
2928 )))))
2929
2930
2931 (* todo: could also match a Struct that has provided a name *)
2932 (* This is for the case where the SmPL code contains "struct x", without
2933 a definition. In this case, the name field is always present.
2934 This case is also called from the case for A.StructUnionDef when
2935 a name is present in the C code. *)
ae4735db 2936 | A.StructUnionName(sua, Some sa), (B.StructUnionName (sub, sb), ii) ->
34e49164
C
2937 (* sa is now an ident, not an mcode, old: ... && (term sa) =$= sb *)
2938 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db 2939 if equal_structUnion (term sua) sub
34e49164 2940 then
ae4735db
C
2941 ident DontKnow sa (sb, ib2) >>= (fun sa (sb, ib2) ->
2942 tokenf sua ib1 >>= (fun sua ib1 ->
34e49164
C
2943 return (
2944 (A.StructUnionName (sua, Some sa)) +> A.rewrap ta,
2945 (B.StructUnionName (sub, sb), [ib1;ib2])
2946 )))
2947 else fail
34e49164 2948
ae4735db
C
2949
2950 | A.StructUnionDef(ty, lba, declsa, rba),
2951 (B.StructUnion (sub, sbopt, declsb), ii) ->
34e49164
C
2952
2953 let (ii_sub_sb, lbb, rbb) =
2954 match ii with
2955 [iisub; lbb; rbb] -> (Common.Left iisub,lbb,rbb)
2956 | [iisub; iisb; lbb; rbb] -> (Common.Right (iisub,iisb),lbb,rbb)
190f1acf 2957 | _ -> error ii "list of length 3 or 4 expected" in
34e49164
C
2958
2959 let process_type =
2960 match (sbopt,ii_sub_sb) with
2961 (None,Common.Left iisub) ->
2962 (* the following doesn't reconstruct the complete SP code, just
2963 the part that matched *)
2964 let rec loop s =
2965 match A.unwrap s with
2966 A.Type(None,ty) ->
2967 (match A.unwrap ty with
2968 A.StructUnionName(sua, None) ->
90aeb998
C
2969 (match (term sua, sub) with
2970 (A.Struct,B.Struct)
2971 | (A.Union,B.Union) -> return ((),())
2972 | _ -> fail) >>=
2973 (fun _ _ ->
2974 tokenf sua iisub >>= (fun sua iisub ->
2975 let ty =
2976 A.Type(None,
2977 A.StructUnionName(sua, None) +> A.rewrap ty)
2978 +> A.rewrap s in
2979 return (ty,[iisub])))
34e49164
C
2980 | _ -> fail)
2981 | A.DisjType(disjs) ->
2982 disjs +>
2983 List.fold_left (fun acc disj -> acc >|+|> (loop disj)) fail
2984 | _ -> fail in
2985 loop ty
ae4735db 2986
34e49164
C
2987 | (Some sb,Common.Right (iisub,iisb)) ->
2988
2989 (* build a StructUnionName from a StructUnion *)
2990 let fake_su = B.nQ, (B.StructUnionName (sub, sb), [iisub;iisb]) in
ae4735db
C
2991
2992 fullType ty fake_su >>= (fun ty fake_su ->
34e49164 2993 match fake_su with
ae4735db 2994 | _nQ, (B.StructUnionName (sub, sb), [iisub;iisb]) ->
34e49164
C
2995 return (ty, [iisub; iisb])
2996 | _ -> raise Impossible)
2997 | _ -> fail in
2998
2999 process_type
9f8e26f4 3000 >>= (fun ty ii_sub_sb ->
34e49164 3001
ae4735db
C
3002 tokenf lba lbb >>= (fun lba lbb ->
3003 tokenf rba rbb >>= (fun rba rbb ->
34e49164
C
3004 struct_fields (A.undots declsa) declsb >>=(fun undeclsa declsb ->
3005 let declsa = redots declsa undeclsa in
3006
3007 return (
3008 (A.StructUnionDef(ty, lba, declsa, rba)) +> A.rewrap ta,
3009 (B.StructUnion (sub, sbopt, declsb),ii_sub_sb@[lbb;rbb])
3010 )))))
3011
3012
ae4735db 3013 (* todo? handle isomorphisms ? because Unsigned Int can be match on a
34e49164 3014 * uint in the C code. But some CEs consists in renaming some types,
ae4735db
C
3015 * so we don't want apply isomorphisms every time.
3016 *)
b1b2de81
C
3017 | A.TypeName sa, (B.TypeName (nameb, typb), noii) ->
3018 assert (null noii);
3019
3020 (match nameb with
ae4735db 3021 | B.RegularName (sb, iidb) ->
b1b2de81 3022 let iidb1 = tuple_of_list1 iidb in
ae4735db 3023
b1b2de81 3024 if (term sa) =$= sb
ae4735db
C
3025 then
3026 tokenf sa iidb1 >>= (fun sa iidb1 ->
b1b2de81
C
3027 return (
3028 (A.TypeName sa) +> A.rewrap ta,
3029 (B.TypeName (B.RegularName (sb, [iidb1]), typb), noii)
3030 ))
3031 else fail
3032
3033 | B.CppConcatenatedName _ | B.CppVariadicName _ |B.CppIdentBuilder _
3034 -> raise Todo
3035 )
3036
34e49164 3037
f59c9fb7 3038 | _, (B.NoType, ii) -> fail
34e49164
C
3039 | _, (B.TypeOfExpr e, ii) -> fail
3040 | _, (B.TypeOfType e, ii) -> fail
485bce71
C
3041
3042 | _, (B.ParenType e, ii) -> fail (* todo ?*)
c491d8ee 3043 | A.EnumName(en,Some namea), (B.EnumName nameb, ii) ->
faf9a90c 3044 let (ib1,ib2) = tuple_of_list2 ii in
ae4735db
C
3045 ident DontKnow namea (nameb, ib2) >>= (fun namea (nameb, ib2) ->
3046 tokenf en ib1 >>= (fun en ib1 ->
faf9a90c 3047 return (
c491d8ee 3048 (A.EnumName (en, Some namea)) +> A.rewrap ta,
faf9a90c
C
3049 (B.EnumName nameb, [ib1;ib2])
3050 )))
3051
c491d8ee
C
3052 | A.EnumDef(ty, lba, idsa, rba),
3053 (B.Enum (sbopt, idsb), ii) ->
3054
3055 let (ii_sub_sb, lbb, rbb, comma_opt) =
3056 match ii with
3057 [iisub; lbb; rbb; comma_opt] ->
3058 (Common.Left iisub,lbb,rbb,comma_opt)
3059 | [iisub; iisb; lbb; rbb; comma_opt] ->
3060 (Common.Right (iisub,iisb),lbb,rbb,comma_opt)
190f1acf 3061 | _ -> error ii "list of length 4 or 5 expected" in
c491d8ee
C
3062
3063 let process_type =
3064 match (sbopt,ii_sub_sb) with
3065 (None,Common.Left iisub) ->
3066 (* the following doesn't reconstruct the complete SP code, just
3067 the part that matched *)
3068 let rec loop s =
3069 match A.unwrap s with
3070 A.Type(None,ty) ->
3071 (match A.unwrap ty with
3072 A.EnumName(sua, None) ->
3073 tokenf sua iisub >>= (fun sua iisub ->
3074 let ty =
3075 A.Type(None,A.EnumName(sua, None) +> A.rewrap ty)
3076 +> A.rewrap s in
3077 return (ty,[iisub]))
3078 | _ -> fail)
3079 | A.DisjType(disjs) ->
3080 disjs +>
3081 List.fold_left (fun acc disj -> acc >|+|> (loop disj)) fail
3082 | _ -> fail in
3083 loop ty
3084
3085 | (Some sb,Common.Right (iisub,iisb)) ->
3086
3087 (* build an EnumName from an Enum *)
3088 let fake_su = B.nQ, (B.EnumName sb, [iisub;iisb]) in
3089
3090 fullType ty fake_su >>= (fun ty fake_su ->
3091 match fake_su with
3092 | _nQ, (B.EnumName sb, [iisub;iisb]) ->
3093 return (ty, [iisub; iisb])
3094 | _ -> raise Impossible)
3095 | _ -> fail in
3096
3097 process_type
3098 >>= (fun ty ii_sub_sb ->
3099
3100 tokenf lba lbb >>= (fun lba lbb ->
3101 tokenf rba rbb >>= (fun rba rbb ->
3102 let idsb = resplit_initialiser idsb [comma_opt] in
3103 let idsb =
3104 List.concat
3105 (List.map
3106 (function (elem,comma) -> [Left elem; Right [comma]])
3107 idsb) in
3108 enum_fields (A.undots idsa) idsb >>= (fun unidsa idsb ->
3109 let idsa = redots idsa unidsa in
3110 let idsb,iicomma =
3111 match List.rev idsb with
3112 (Right comma)::rest ->
3113 (Ast_c.unsplit_comma (List.rev rest),comma)
3114 | (Left _)::_ -> (Ast_c.unsplit_comma idsb,[]) (* possible *)
3115 | [] -> ([],[]) in
3116 return (
3117 (A.EnumDef(ty, lba, idsa, rba)) +> A.rewrap ta,
3118 (B.Enum (sbopt, idsb),ii_sub_sb@[lbb;rbb]@iicomma)
3119 ))
3120 )))
3121
485bce71
C
3122 | _, (B.Enum _, _) -> fail (* todo cocci ?*)
3123
3124 | _,
b1b2de81 3125 ((B.TypeName _ | B.StructUnionName (_, _) | B.EnumName _ |
faf9a90c
C
3126 B.StructUnion (_, _, _) |
3127 B.FunctionType _ | B.Array (_, _) | B.Pointer _ |
485bce71
C
3128 B.BaseType _),
3129 _)
3130 -> fail
3131
34e49164 3132
ae4735db 3133(* todo: iso on sign, if not mentioned then free. tochange?
34e49164
C
3134 * but that require to know if signed int because explicit
3135 * signed int, or because implicit signed int.
3136 *)
3137
ae4735db 3138and sign signa signb =
34e49164
C
3139 match signa, signb with
3140 | None, None -> return (None, [])
ae4735db 3141 | Some signa, Some (signb, ib) ->
34e49164 3142 if equal_sign (term signa) signb
ae4735db 3143 then tokenf signa ib >>= (fun signa ib ->
34e49164
C
3144 return (Some signa, [ib])
3145 )
3146 else fail
3147 | _, _ -> fail
3148
3149
ae4735db
C
3150and minusize_list iixs =
3151 iixs +> List.fold_left (fun acc ii ->
3152 acc >>= (fun xs ys ->
3153 tokenf minusizer ii >>= (fun minus ii ->
34e49164
C
3154 return (minus::xs, ii::ys)
3155 ))) (return ([],[]))
ae4735db 3156 >>= (fun _xsminys ys ->
34e49164
C
3157 return ((), List.rev ys)
3158 )
3159
ae4735db 3160and storage_optional_allminus allminus stoa (stob, iistob) =
34e49164 3161 (* "iso-by-absence" for storage, and return type. *)
ae4735db 3162 X.optional_storage_flag (fun optional_storage ->
34e49164 3163 match stoa, stob with
ae4735db
C
3164 | None, (stobis, inline) ->
3165 let do_minus () =
3166 if allminus
3167 then
3168 minusize_list iistob >>= (fun () iistob ->
34e49164
C
3169 return (None, (stob, iistob))
3170 )
3171 else return (None, (stob, iistob))
3172 in
3173
3174 (match optional_storage, stobis with
3175 | false, B.NoSto -> do_minus ()
3176 | false, _ -> fail
3177 | true, B.NoSto -> do_minus ()
ae4735db
C
3178 | true, _ ->
3179 if !Flag.show_misc
34e49164
C
3180 then pr2_once "USING optional_storage builtin isomorphism";
3181 do_minus()
3182 )
3183
ae4735db 3184 | Some x, ((stobis, inline)) ->
34e49164 3185 if equal_storage (term x) stobis
ae4735db 3186 then
aa721442
C
3187 let rec loop acc = function
3188 [] -> fail
3189 | i1::iistob ->
90aeb998
C
3190 let str = B.str_of_info i1 in
3191 (match str with
3192 "static" | "extern" | "auto" | "register" ->
3193 (* not very elegant, but tokenf doesn't know what token to
3194 match with *)
3195 tokenf x i1 >>= (fun x i1 ->
3196 let rebuilt = (List.rev acc) @ i1 :: iistob in
3197 return (Some x, ((stobis, inline), rebuilt)))
3198 | _ -> loop (i1::acc) iistob) in
aa721442 3199 loop [] iistob
34e49164
C
3200 else fail
3201 )
34e49164 3202
90aeb998
C
3203and inline_optional_allminus allminus inla (stob, iistob) =
3204 (* "iso-by-absence" for storage, and return type. *)
3205 X.optional_storage_flag (fun optional_storage ->
3206 match inla, stob with
3207 | None, (stobis, inline) ->
3208 let do_minus () =
3209 if allminus
3210 then
3211 minusize_list iistob >>= (fun () iistob ->
3212 return (None, (stob, iistob))
3213 )
3214 else return (None, (stob, iistob))
3215 in
3216
3217 if inline
3218 then
3219 if optional_storage
3220 then
3221 begin
3222 if !Flag.show_misc
3223 then pr2_once "USING optional_storage builtin isomorphism";
3224 do_minus()
3225 end
3226 else fail (* inline not in SP and present in C code *)
3227 else do_minus()
3228
3229 | Some x, ((stobis, inline)) ->
3230 if inline
3231 then
3232 let rec loop acc = function
3233 [] -> fail
3234 | i1::iistob ->
3235 let str = B.str_of_info i1 in
3236 (match str with
3237 "inline" ->
3238 (* not very elegant, but tokenf doesn't know what token to
3239 match with *)
3240 tokenf x i1 >>= (fun x i1 ->
3241 let rebuilt = (List.rev acc) @ i1 :: iistob in
3242 return (Some x, ((stobis, inline), rebuilt)))
3243 | _ -> loop (i1::acc) iistob) in
3244 loop [] iistob
3245 else fail (* SP has inline, but the C code does not *)
3246 )
3247
ae4735db
C
3248and fullType_optional_allminus allminus tya retb =
3249 match tya with
3250 | None ->
34e49164 3251 if allminus
ae4735db
C
3252 then
3253 X.distrf_type minusizer retb >>= (fun _x retb ->
34e49164
C
3254 return (None, retb)
3255 )
3256
3257 else return (None, retb)
ae4735db
C
3258 | Some tya ->
3259 fullType tya retb >>= (fun tya retb ->
34e49164
C
3260 return (Some tya, retb)
3261 )
3262
3263
3264
3265(*---------------------------------------------------------------------------*)
faf9a90c
C
3266
3267and compatible_base_type a signa b =
34e49164
C
3268 let ok = return ((),()) in
3269
faf9a90c 3270 match a, b with
1eddfd50
C
3271 | Type_cocci.VoidType, B.Void
3272 | Type_cocci.SizeType, B.SizeType
3273 | Type_cocci.SSizeType, B.SSizeType
3274 | Type_cocci.PtrDiffType, B.PtrDiffType ->
b1b2de81 3275 assert (signa =*= None);
faf9a90c 3276 ok
ae4735db 3277 | Type_cocci.CharType, B.IntType B.CChar when signa =*= None ->
faf9a90c 3278 ok
ae4735db
C
3279 | Type_cocci.CharType, B.IntType (B.Si (signb, B.CChar2)) ->
3280 compatible_sign signa signb
3281 | Type_cocci.ShortType, B.IntType (B.Si (signb, B.CShort)) ->
faf9a90c 3282 compatible_sign signa signb
ae4735db 3283 | Type_cocci.IntType, B.IntType (B.Si (signb, B.CInt)) ->
faf9a90c 3284 compatible_sign signa signb
ae4735db 3285 | Type_cocci.LongType, B.IntType (B.Si (signb, B.CLong)) ->
faf9a90c 3286 compatible_sign signa signb
ae4735db 3287 | _, B.IntType (B.Si (signb, B.CLongLong)) ->
faf9a90c
C
3288 pr2_once "no longlong in cocci";
3289 fail
3290 | Type_cocci.FloatType, B.FloatType B.CFloat ->
ae4735db 3291 assert (signa =*= None);
faf9a90c
C
3292 ok
3293 | Type_cocci.DoubleType, B.FloatType B.CDouble ->
ae4735db 3294 assert (signa =*= None);
faf9a90c 3295 ok
ae4735db 3296 | _, B.FloatType B.CLongDouble ->
faf9a90c
C
3297 pr2_once "no longdouble in cocci";
3298 fail
3299 | Type_cocci.BoolType, _ -> failwith "no booltype in C"
ae4735db 3300
1eddfd50
C
3301 | _, (B.Void|B.FloatType _|B.IntType _
3302 |B.SizeType|B.SSizeType|B.PtrDiffType) -> fail
faf9a90c
C
3303
3304and compatible_base_type_meta a signa qua b ii local =
3305 match a, b with
3306 | Type_cocci.MetaType(ida,keep,inherited),
ae4735db 3307 B.IntType (B.Si (signb, B.CChar2)) ->
faf9a90c
C
3308 compatible_sign signa signb >>= fun _ _ ->
3309 let newb = ((qua, (B.BaseType (B.IntType B.CChar),ii)),local) in
3310 compatible_type a newb
ae4735db 3311 | Type_cocci.MetaType(ida,keep,inherited), B.IntType (B.Si (signb, ty)) ->
faf9a90c
C
3312 compatible_sign signa signb >>= fun _ _ ->
3313 let newb =
3314 ((qua, (B.BaseType (B.IntType (B.Si (B.Signed, ty))),ii)),local) in
3315 compatible_type a newb
ae4735db 3316 | _, B.FloatType B.CLongDouble ->
faf9a90c
C
3317 pr2_once "no longdouble in cocci";
3318 fail
ae4735db 3319
1eddfd50
C
3320 | _, (B.Void|B.FloatType _|B.IntType _
3321 |B.SizeType|B.SSizeType|B.PtrDiffType) -> fail
485bce71
C
3322
3323
ae4735db 3324and compatible_type a (b,local) =
faf9a90c
C
3325 let ok = return ((),()) in
3326
3327 let rec loop = function
f59c9fb7
C
3328 | _, (qua, (B.NoType, _)) ->
3329 failwith "compatible_type: matching with NoType"
ae4735db 3330 | Type_cocci.BaseType a, (qua, (B.BaseType b,ii)) ->
faf9a90c 3331 compatible_base_type a None b
485bce71 3332
ae4735db 3333 | Type_cocci.SignedT (signa,None), (qua, (B.BaseType b,ii)) ->
faf9a90c 3334 compatible_base_type Type_cocci.IntType (Some signa) b
485bce71 3335
ae4735db 3336 | Type_cocci.SignedT (signa,Some ty), (qua, (B.BaseType b,ii)) ->
faf9a90c
C
3337 (match ty with
3338 Type_cocci.BaseType ty ->
3339 compatible_base_type ty (Some signa) b
3340 | Type_cocci.MetaType(ida,keep,inherited) ->
3341 compatible_base_type_meta ty (Some signa) qua b ii local
3342 | _ -> failwith "not possible")
485bce71 3343
ae4735db 3344 | Type_cocci.Pointer a, (qub, (B.Pointer b, ii)) ->
34e49164
C
3345 loop (a,b)
3346 | Type_cocci.FunctionPointer a, _ ->
3347 failwith
3348 "TODO: function pointer type doesn't store enough information to determine compatability"
3349 | Type_cocci.Array a, (qub, (B.Array (eopt, b),ii)) ->
3350 (* no size info for cocci *)
3351 loop (a,b)
e6509c05 3352 | Type_cocci.StructUnionName (sua, name),
ae4735db 3353 (qub, (B.StructUnionName (sub, sb),ii)) ->
e6509c05
C
3354 if equal_structUnion_type_cocci sua sub
3355 then structure_type_name name sb ii
faf9a90c 3356 else fail
e6509c05
C
3357 | Type_cocci.EnumName (name),
3358 (qub, (B.EnumName (sb),ii)) -> structure_type_name name sb ii
ae4735db 3359 | Type_cocci.TypeName sa, (qub, (B.TypeName (namesb, _typb),noii)) ->
b1b2de81 3360 let sb = Ast_c.str_of_name namesb in
ae4735db 3361 if sa =$= sb
34e49164
C
3362 then ok
3363 else fail
3364
ae4735db
C
3365 | Type_cocci.ConstVol (qua, a), (qub, b) ->
3366 if (fst qub).B.const && (fst qub).B.volatile
34e49164
C
3367 then
3368 begin
3369 pr2_once ("warning: the type is both const & volatile but cocci " ^
3370 "does not handle that");
3371 fail
3372 end
ae4735db
C
3373 else
3374 if
3375 (match qua with
34e49164
C
3376 | Type_cocci.Const -> (fst qub).B.const
3377 | Type_cocci.Volatile -> (fst qub).B.volatile
3378 )
3379 then loop (a,(Ast_c.nQ, b))
3380 else fail
3381
ae4735db 3382 | Type_cocci.MetaType (ida,keep,inherited), typb ->
34e49164
C
3383 let max_min _ =
3384 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_type typb) in
3385 X.envf keep inherited (A.make_mcode ida, B.MetaTypeVal typb, max_min)
3386 (fun () -> ok
3387 )
3388
3389 (* subtil: must be after the MetaType case *)
ae4735db 3390 | a, (qub, (B.TypeName (_namesb, Some b), noii)) ->
34e49164
C
3391 (* kind of typedef iso *)
3392 loop (a,b)
3393
34e49164
C
3394 (* for metavariables of type expression *^* *)
3395 | Type_cocci.Unknown , _ -> ok
3396
485bce71
C
3397 | (_,
3398 (_,
3399 ((
3400 B.TypeOfType _|B.TypeOfExpr _|B.ParenType _|
3401 B.EnumName _|B.StructUnion (_, _, _)|B.Enum (_, _)
3402 ),
3403 _))) -> fail
3404
3405 | (_,
3406 (_,
3407 ((
3408 B.StructUnionName (_, _)|
3409 B.FunctionType _|
3410 B.Array (_, _)|B.Pointer _|B.TypeName _|
3411 B.BaseType _
3412 ),
3413 _))) -> fail
3414
e6509c05
C
3415and structure_type_name nm sb ii =
3416 match nm with
3417 Type_cocci.NoName -> ok
3418 | Type_cocci.Name sa ->
3419 if sa =$= sb
3420 then ok
3421 else fail
3422 | Type_cocci.MV(ida,keep,inherited) ->
3423 (* degenerate version of MetaId, no transformation possible *)
3424 let (ib1, ib2) = tuple_of_list2 ii in
3425 let max_min _ = Lib_parsing_c.lin_col_by_pos [ib2] in
3426 let mida = A.make_mcode ida in
3427 X.envf keep inherited (mida, B.MetaIdVal (sb,[]), max_min)
3428 (fun () -> ok)
485bce71
C
3429
3430 in
34e49164
C
3431 loop (a,b)
3432
ae4735db 3433and compatible_sign signa signb =
34e49164
C
3434 let ok = return ((),()) in
3435 match signa, signb with
ae4735db 3436 | None, B.Signed
34e49164
C
3437 | Some Type_cocci.Signed, B.Signed
3438 | Some Type_cocci.Unsigned, B.UnSigned
3439 -> ok
3440 | _ -> fail
3441
3442
ae4735db 3443and equal_structUnion_type_cocci a b =
34e49164
C
3444 match a, b with
3445 | Type_cocci.Struct, B.Struct -> true
3446 | Type_cocci.Union, B.Union -> true
485bce71 3447 | _, (B.Struct | B.Union) -> false
34e49164
C
3448
3449
3450
3451(*---------------------------------------------------------------------------*)
ae4735db 3452and inc_file (a, before_after) (b, h_rel_pos) =
34e49164 3453
ae4735db 3454 let rec aux_inc (ass, bss) passed =
34e49164
C
3455 match ass, bss with
3456 | [], [] -> true
ae4735db 3457 | [A.IncDots], _ ->
34e49164
C
3458 let passed = List.rev passed in
3459
3460 (match before_after, !h_rel_pos with
3461 | IncludeNothing, _ -> true
ae4735db 3462 | IncludeMcodeBefore, Some x ->
34e49164
C
3463 List.mem passed (x.Ast_c.first_of)
3464
ae4735db 3465 | IncludeMcodeAfter, Some x ->
34e49164
C
3466 List.mem passed (x.Ast_c.last_of)
3467
3468 (* no info, maybe cos of a #include <xx.h> that was already in a .h *)
ae4735db 3469 | _, None -> false
34e49164
C
3470 )
3471
b1b2de81 3472 | (A.IncPath x)::xs, y::ys -> x =$= y && aux_inc (xs, ys) (x::passed)
34e49164 3473 | _ -> failwith "IncDots not in last place or other pb"
ae4735db 3474
34e49164
C
3475 in
3476
3477 match a, b with
ae4735db 3478 | A.Local ass, B.Local bss ->
34e49164 3479 aux_inc (ass, bss) []
ae4735db 3480 | A.NonLocal ass, B.NonLocal bss ->
34e49164
C
3481 aux_inc (ass, bss) []
3482 | _ -> false
ae4735db 3483
34e49164
C
3484
3485
3486(*---------------------------------------------------------------------------*)
3487
ae4735db
C
3488and (define_params: sequence ->
3489 (A.define_param list, (string B.wrap) B.wrap2 list) matcher) =
3490 fun seqstyle eas ebs ->
34e49164
C
3491 match seqstyle with
3492 | Unordered -> failwith "not handling ooo"
ae4735db 3493 | Ordered ->
34e49164
C
3494 define_paramsbis eas (Ast_c.split_comma ebs) >>= (fun eas ebs_splitted ->
3495 return (eas, (Ast_c.unsplit_comma ebs_splitted))
3496 )
3497
3498(* todo? facto code with argument and parameters ? *)
ae4735db 3499and define_paramsbis = fun eas ebs ->
c491d8ee
C
3500 let match_dots ea =
3501 match A.unwrap ea with
3502 A.DPdots(mcode) -> Some (mcode, None)
3503 | _ -> None in
3504 let build_dots (mcode, _optexpr) = A.DPdots(mcode) in
3505 let match_comma ea =
3506 match A.unwrap ea with
3507 A.DPComma ia1 -> Some ia1
3508 | _ -> None in
3509 let build_comma ia1 = A.DPComma ia1 in
3510 let match_metalist ea = None in
3511 let build_metalist (ida,leninfo,keep,inherited) = failwith "not possible" in
3512 let mktermval v = failwith "not possible" in
3513 let special_cases ea eas ebs = None in
3514 let no_ii x = failwith "not possible" in
3515 list_matcher match_dots build_dots match_comma build_comma
3516 match_metalist build_metalist mktermval
3517 special_cases define_parameter X.distrf_define_params no_ii eas ebs
3518
3519and define_parameter = fun parama paramb ->
3520 match A.unwrap parama, paramb with
3521 A.DParam ida, (idb, ii) ->
3522 let ib1 = tuple_of_list1 ii in
3523 ident DontKnow ida (idb, ib1) >>= (fun ida (idb, ib1) ->
3524 return ((A.DParam ida)+> A.rewrap parama,(idb, [ib1])))
3525 | (A.OptDParam _ | A.UniqueDParam _), _ ->
3526 failwith "handling Opt/Unique for define parameters"
3527 | A.DPcircles (_), ys -> raise Impossible (* in Ordered mode *)
3528 | _ -> fail
34e49164
C
3529
3530(*****************************************************************************)
3531(* Entry points *)
3532(*****************************************************************************)
3533
3534(* no global solution for positions here, because for a statement metavariable
3535we want a MetaStmtVal, and for the others, it's not clear what we want *)
3536
ae4735db
C
3537let rec (rule_elem_node: (A.rule_elem, Control_flow_c.node) matcher) =
3538 fun re node ->
3539 let rewrap x =
34e49164
C
3540 x >>= (fun a b -> return (A.rewrap re a, F.rewrap node b))
3541 in
3542 X.all_bound (A.get_inherited re) >&&>
3543
3544 rewrap (
3545 match A.unwrap re, F.unwrap node with
3546
3547 (* note: the order of the clauses is important. *)
3548
3549 | _, F.Enter | _, F.Exit | _, F.ErrorExit -> fail2()
3550
3551 (* the metaRuleElem contains just '-' information. We dont need to add
3552 * stuff in the environment. If we need stuff in environment, because
3553 * there is a + S somewhere, then this will be done via MetaStmt, not
ae4735db 3554 * via MetaRuleElem.
34e49164
C
3555 * Can match TrueNode/FalseNode/... so must be placed before those cases.
3556 *)
3557
ae4735db 3558 | A.MetaRuleElem(mcode,keep,inherited), unwrap_node ->
34e49164
C
3559 let default = A.MetaRuleElem(mcode,keep,inherited), unwrap_node in
3560 (match unwrap_node with
3561 | F.CaseNode _
951c7801 3562 | F.TrueNode | F.FalseNode | F.AfterNode
ae4735db
C
3563 | F.LoopFallThroughNode | F.FallThroughNode
3564 | F.InLoopNode ->
3565 if X.mode =*= PatternMode
3566 then return default
34e49164
C
3567 else
3568 if mcode_contain_plus (mcodekind mcode)
3569 then failwith "try add stuff on fake node"
3570 (* minusize or contextize a fake node is ok *)
3571 else return default
3572
ae4735db
C
3573 | F.EndStatement None ->
3574 if X.mode =*= PatternMode then return default
3575 else
34e49164
C
3576 (* DEAD CODE NOW ? only useful in -no_cocci_vs_c_3 ?
3577 if mcode_contain_plus (mcodekind mcode)
3578 then
3579 let fake_info = Ast_c.fakeInfo() in
ae4735db
C
3580 distrf distrf_node (mcodekind mcode)
3581 (F.EndStatement (Some fake_info))
34e49164
C
3582 else return unwrap_node
3583 *)
3584 raise Todo
ae4735db
C
3585
3586 | F.EndStatement (Some i1) ->
3587 tokenf mcode i1 >>= (fun mcode i1 ->
34e49164
C
3588 return (
3589 A.MetaRuleElem (mcode,keep, inherited),
3590 F.EndStatement (Some i1)
3591 ))
3592
ae4735db 3593 | F.FunHeader _ ->
b1b2de81 3594 if X.mode =*= PatternMode then return default
34e49164 3595 else failwith "a MetaRuleElem can't transform a headfunc"
ae4735db
C
3596 | _n ->
3597 if X.mode =*= PatternMode then return default
3598 else
3599 X.distrf_node (generalize_mcode mcode) node >>= (fun mcode node ->
34e49164
C
3600 return (
3601 A.MetaRuleElem(mcode,keep, inherited),
3602 F.unwrap node
3603 ))
3604 )
3605
3606
ae4735db
C
3607 (* rene cant have found that a state containing a fake/exit/... should be
3608 * transformed
34e49164
C
3609 * TODO: and F.Fake ?
3610 *)
3611 | _, F.EndStatement _ | _, F.CaseNode _
951c7801
C
3612 | _, F.TrueNode | _, F.FalseNode | _, F.AfterNode
3613 | _, F.FallThroughNode | _, F.LoopFallThroughNode
690d68d1 3614 | _, F.InLoopNode -> fail2()
34e49164
C
3615
3616 (* really ? diff between pattern.ml and transformation.ml *)
3617 | _, F.Fake -> fail2()
3618
3619
3620 (* cas general: a Meta can match everything. It matches only
3621 * "header"-statement. We transform only MetaRuleElem, not MetaStmt.
ae4735db 3622 * So can't have been called in transform.
34e49164
C
3623 *)
3624 | A.MetaStmt (ida,keep,metainfoMaybeTodo,inherited), F.Decl(_) -> fail
3625
ae4735db 3626 | A.MetaStmt (ida,keep,metainfoMaybeTodo,inherited), unwrap_node ->
34e49164
C
3627 (* todo: should not happen in transform mode *)
3628
3629 (match Control_flow_c.extract_fullstatement node with
ae4735db 3630 | Some stb ->
34e49164
C
3631 let max_min _ =
3632 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_stmt stb) in
3633 X.envf keep inherited (ida, Ast_c.MetaStmtVal stb, max_min)
ae4735db 3634 (fun () ->
34e49164
C
3635 (* no need tag ida, we can't be called in transform-mode *)
3636 return (
3637 A.MetaStmt (ida, keep, metainfoMaybeTodo, inherited),
3638 unwrap_node
3639 )
3640 )
3641 | None -> fail
3642 )
3643
3644 (* not me?: *)
ae4735db 3645 | A.MetaStmtList _, _ ->
34e49164
C
3646 failwith "not handling MetaStmtList"
3647
3648 | A.TopExp ea, F.DefineExpr eb ->
ae4735db 3649 expression ea eb >>= (fun ea eb ->
34e49164
C
3650 return (
3651 A.TopExp ea,
3652 F.DefineExpr eb
3653 ))
ae4735db 3654
34e49164
C
3655 | A.TopExp ea, F.DefineType eb ->
3656 (match A.unwrap ea with
3657 A.TypeExp(ft) ->
ae4735db 3658 fullType ft eb >>= (fun ft eb ->
34e49164
C
3659 return (
3660 A.TopExp (A.rewrap ea (A.TypeExp(ft))),
3661 F.DefineType eb
3662 ))
3663 | _ -> fail)
ae4735db 3664
34e49164
C
3665
3666
3667 (* It is important to put this case before the one that fails because
3668 * of the lack of the counter part of a C construct in SmPL (for instance
3669 * there is not yet a CaseRange in SmPL). Even if SmPL don't handle
3670 * yet certain constructs, those constructs may contain expression
3671 * that we still want and can transform.
3672 *)
3673
ae4735db 3674 | A.Exp exp, nodeb ->
34e49164
C
3675
3676 (* kind of iso, initialisation vs affectation *)
ae4735db 3677 let node =
34e49164 3678 match A.unwrap exp, nodeb with
ae4735db 3679 | A.Assignment (ea, op, eb, true), F.Decl decl ->
34e49164
C
3680 initialisation_to_affectation decl +> F.rewrap node
3681 | _ -> node
3682 in
3683
3684
ae4735db 3685 (* Now keep fullstatement inside the control flow node,
34e49164 3686 * so that can then get in a MetaStmtVar the fullstatement to later
ae4735db 3687 * pp back when the S is in a +. But that means that
34e49164
C
3688 * Exp will match an Ifnode even if there is no such exp
3689 * inside the condition of the Ifnode (because the exp may
3690 * be deeper, in the then branch). So have to not visit
3691 * all inside a node anymore.
ae4735db 3692 *
34e49164 3693 * update: j'ai choisi d'accrocher au noeud du CFG à la
ae4735db 3694 * fois le fullstatement et le partialstatement et appeler le
34e49164
C
3695 * visiteur que sur le partialstatement.
3696 *)
ae4735db 3697 let expfn =
34e49164
C
3698 match Ast_cocci.get_pos re with
3699 | None -> expression
ae4735db
C
3700 | Some pos ->
3701 (fun ea eb ->
3702 let (max,min) =
34e49164
C
3703 Lib_parsing_c.max_min_by_pos (Lib_parsing_c.ii_of_expr eb) in
3704 let keep = Type_cocci.Unitary in
3705 let inherited = false in
3706 let max_min _ = failwith "no pos" in
3707 X.envf keep inherited (pos, B.MetaPosVal (min,max), max_min)
ae4735db 3708 (fun () ->
34e49164
C
3709 expression ea eb
3710 )
3711 )
3712 in
ae4735db 3713 X.cocciExp expfn exp node >>= (fun exp node ->
34e49164
C
3714 return (
3715 A.Exp exp,
3716 F.unwrap node
3717 )
3718 )
3719
ae4735db
C
3720 | A.Ty ty, nodeb ->
3721 X.cocciTy fullType ty node >>= (fun ty node ->
34e49164
C
3722 return (
3723 A.Ty ty,
3724 F.unwrap node
3725 )
3726 )
1be43e12 3727
ae4735db
C
3728 | A.TopInit init, nodeb ->
3729 X.cocciInit initialiser init node >>= (fun init node ->
1be43e12
C
3730 return (
3731 A.TopInit init,
3732 F.unwrap node
3733 )
3734 )
34e49164
C
3735
3736
3737 | A.FunHeader (mckstart, allminus, fninfoa, ida, oparen, paramsa, cparen),
b1b2de81 3738 F.FunHeader ({B.f_name = nameidb;
485bce71
C
3739 f_type = (retb, (paramsb, (isvaargs, iidotsb)));
3740 f_storage = stob;
3741 f_attr = attrs;
3742 f_body = body;
91eba41f 3743 f_old_c_style = oldstyle;
ae4735db 3744 }, ii) ->
485bce71 3745 assert (null body);
34e49164 3746
91eba41f
C
3747 if oldstyle <> None
3748 then pr2 "OLD STYLE DECL NOT WELL SUPPORTED";
3749
3750
34e49164
C
3751 (* fninfoa records the order in which the SP specified the various
3752 information, but this isn't taken into account in the matching.
3753 Could this be a problem for transformation? *)
3754 let stoa =
3755 match
3756 List.filter (function A.FStorage(s) -> true | _ -> false) fninfoa
3757 with [A.FStorage(s)] -> Some s | _ -> None in
ae4735db 3758 let tya =
34e49164
C
3759 match List.filter (function A.FType(s) -> true | _ -> false) fninfoa
3760 with [A.FType(t)] -> Some t | _ -> None in
3761
90aeb998
C
3762 let inla =
3763 match List.filter (function A.FInline(i) -> true | _ -> false) fninfoa
3764 with [A.FInline(i)] -> Some i | _ -> None in
34e49164
C
3765
3766 (match List.filter (function A.FAttr(a) -> true | _ -> false) fninfoa
3767 with [A.FAttr(a)] -> failwith "not checking attributes" | _ -> ());
3768
3769 (match ii with
ae4735db 3770 | ioparenb::icparenb::iifakestart::iistob ->
34e49164
C
3771
3772 (* maybe important to put ident as the first tokens to transform.
3773 * It's related to transform_proto. So don't change order
3774 * between the >>=.
3775 *)
ae4735db
C
3776 ident_cpp LocalFunction ida nameidb >>= (fun ida nameidb ->
3777 X.tokenf_mck mckstart iifakestart >>= (fun mckstart iifakestart ->
34e49164
C
3778 tokenf oparen ioparenb >>= (fun oparen ioparenb ->
3779 tokenf cparen icparenb >>= (fun cparen icparenb ->
ae4735db 3780 parameters (seqstyle paramsa)
34e49164 3781 (A.undots paramsa) paramsb >>=
ae4735db 3782 (fun paramsaundots paramsb ->
34e49164 3783 let paramsa = redots paramsa paramsaundots in
90aeb998
C
3784 inline_optional_allminus allminus
3785 inla (stob, iistob) >>= (fun inla (stob, iistob) ->
ae4735db
C
3786 storage_optional_allminus allminus
3787 stoa (stob, iistob) >>= (fun stoa (stob, iistob) ->
34e49164 3788 (
ae4735db
C
3789 if isvaargs
3790 then
34e49164
C
3791 pr2_once
3792 ("Not handling well variable length arguments func. "^
3793 "You have been warned");
3794 if allminus
3795 then minusize_list iidotsb
3796 else return ((),iidotsb)
ae4735db
C
3797 ) >>= (fun () iidotsb ->
3798
3799 fullType_optional_allminus allminus tya retb >>= (fun tya retb ->
34e49164 3800
ae4735db 3801 let fninfoa =
34e49164 3802 (match stoa with Some st -> [A.FStorage st] | None -> []) ++
90aeb998 3803 (match inla with Some i -> [A.FInline i] | None -> []) ++
34e49164
C
3804 (match tya with Some t -> [A.FType t] | None -> [])
3805
3806 in
3807
3808 return (
3809 A.FunHeader(mckstart,allminus,fninfoa,ida,oparen,
3810 paramsa,cparen),
b1b2de81 3811 F.FunHeader ({B.f_name = nameidb;
485bce71
C
3812 f_type = (retb, (paramsb, (isvaargs, iidotsb)));
3813 f_storage = stob;
3814 f_attr = attrs;
3815 f_body = body;
91eba41f 3816 f_old_c_style = oldstyle; (* TODO *)
485bce71 3817 },
b1b2de81 3818 ioparenb::icparenb::iifakestart::iistob)
34e49164 3819 )
90aeb998 3820 )))))))))
34e49164
C
3821 | _ -> raise Impossible
3822 )
3823
3824
3825
3826
3827
3828
ae4735db
C
3829 | A.Decl (mckstart,allminus,decla), F.Decl declb ->
3830 declaration (mckstart,allminus,decla) declb >>=
3831 (fun (mckstart,allminus,decla) declb ->
34e49164
C
3832 return (
3833 A.Decl (mckstart,allminus,decla),
3834 F.Decl declb
3835 ))
3836
3837
ae4735db
C
3838 | A.SeqStart mcode, F.SeqStart (st, level, i1) ->
3839 tokenf mcode i1 >>= (fun mcode i1 ->
34e49164 3840 return (
ae4735db 3841 A.SeqStart mcode,
34e49164
C
3842 F.SeqStart (st, level, i1)
3843 ))
3844
ae4735db
C
3845 | A.SeqEnd mcode, F.SeqEnd (level, i1) ->
3846 tokenf mcode i1 >>= (fun mcode i1 ->
34e49164
C
3847 return (
3848 A.SeqEnd mcode,
3849 F.SeqEnd (level, i1)
3850 ))
3851
8babbc8f 3852 | A.ExprStatement (Some ea, ia1), F.ExprStatement (st, (Some eb, ii)) ->
ae4735db
C
3853 let ib1 = tuple_of_list1 ii in
3854 expression ea eb >>= (fun ea eb ->
3855 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
34e49164 3856 return (
8babbc8f 3857 A.ExprStatement (Some ea, ia1),
34e49164
C
3858 F.ExprStatement (st, (Some eb, [ib1]))
3859 )
3860 ))
3861
8babbc8f
C
3862 | A.ExprStatement (None, ia1), F.ExprStatement (st, (None, ii)) ->
3863 let ib1 = tuple_of_list1 ii in
3864 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3865 return (
3866 A.ExprStatement (None, ia1),
3867 F.ExprStatement (st, (None, [ib1]))
3868 )
3869 )
3870
34e49164 3871
ae4735db 3872 | A.IfHeader (ia1,ia2, ea, ia3), F.IfHeader (st, (eb,ii)) ->
34e49164 3873 let (ib1, ib2, ib3) = tuple_of_list3 ii in
ae4735db
C
3874 expression ea eb >>= (fun ea eb ->
3875 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3876 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3877 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
34e49164
C
3878 return (
3879 A.IfHeader (ia1, ia2, ea, ia3),
3880 F.IfHeader (st, (eb,[ib1;ib2;ib3]))
3881 )))))
3882
ae4735db
C
3883 | A.Else ia, F.Else ib ->
3884 tokenf ia ib >>= (fun ia ib ->
34e49164
C
3885 return (A.Else ia, F.Else ib)
3886 )
3887
ae4735db 3888 | A.WhileHeader (ia1, ia2, ea, ia3), F.WhileHeader (st, (eb, ii)) ->
34e49164 3889 let (ib1, ib2, ib3) = tuple_of_list3 ii in
ae4735db
C
3890 expression ea eb >>= (fun ea eb ->
3891 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3892 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3893 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
34e49164 3894 return (
ae4735db 3895 A.WhileHeader (ia1, ia2, ea, ia3),
34e49164
C
3896 F.WhileHeader (st, (eb, [ib1;ib2;ib3]))
3897 )))))
3898
ae4735db
C
3899 | A.DoHeader ia, F.DoHeader (st, ib) ->
3900 tokenf ia ib >>= (fun ia ib ->
34e49164 3901 return (
ae4735db 3902 A.DoHeader ia,
34e49164
C
3903 F.DoHeader (st, ib)
3904 ))
ae4735db 3905 | A.WhileTail (ia1,ia2,ea,ia3,ia4), F.DoWhileTail (eb, ii) ->
34e49164 3906 let (ib1, ib2, ib3, ib4) = tuple_of_list4 ii in
ae4735db
C
3907 expression ea eb >>= (fun ea eb ->
3908 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3909 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3910 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
3911 tokenf ia4 ib4 >>= (fun ia4 ib4 ->
34e49164 3912 return (
ae4735db 3913 A.WhileTail (ia1,ia2,ea,ia3,ia4),
34e49164
C
3914 F.DoWhileTail (eb, [ib1;ib2;ib3;ib4])
3915 ))))))
3916 | A.IteratorHeader (ia1, ia2, eas, ia3), F.MacroIterHeader (st, ((s,ebs),ii))
ae4735db 3917 ->
34e49164
C
3918 let (ib1, ib2, ib3) = tuple_of_list3 ii in
3919
ae4735db
C
3920 ident DontKnow ia1 (s, ib1) >>= (fun ia1 (s, ib1) ->
3921 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3922 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
3923 arguments (seqstyle eas) (A.undots eas) ebs >>= (fun easundots ebs ->
34e49164
C
3924 let eas = redots eas easundots in
3925 return (
ae4735db 3926 A.IteratorHeader (ia1, ia2, eas, ia3),
34e49164
C
3927 F.MacroIterHeader (st, ((s,ebs), [ib1;ib2;ib3]))
3928 )))))
3929
34e49164 3930
ae4735db
C
3931
3932 | A.ForHeader (ia1, ia2, ea1opt, ia3, ea2opt, ia4, ea3opt, ia5),
34e49164 3933 F.ForHeader (st, (((eb1opt,ib3s), (eb2opt,ib4s), (eb3opt,ib4vide)), ii))
ae4735db 3934 ->
34e49164
C
3935 assert (null ib4vide);
3936 let (ib1, ib2, ib5) = tuple_of_list3 ii in
3937 let ib3 = tuple_of_list1 ib3s in
3938 let ib4 = tuple_of_list1 ib4s in
ae4735db 3939
34e49164
C
3940 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3941 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3942 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
3943 tokenf ia4 ib4 >>= (fun ia4 ib4 ->
3944 tokenf ia5 ib5 >>= (fun ia5 ib5 ->
3945 option expression ea1opt eb1opt >>= (fun ea1opt eb1opt ->
3946 option expression ea2opt eb2opt >>= (fun ea2opt eb2opt ->
3947 option expression ea3opt eb3opt >>= (fun ea3opt eb3opt ->
3948 return (
3949 A.ForHeader (ia1, ia2, ea1opt, ia3, ea2opt, ia4, ea3opt, ia5),
3950 F.ForHeader (st, (((eb1opt,[ib3]), (eb2opt,[ib4]), (eb3opt,[])),
3951 [ib1;ib2;ib5]))
3952
3953 )))))))))
3954
3955
3956 | A.SwitchHeader(ia1,ia2,ea,ia3), F.SwitchHeader (st, (eb,ii)) ->
3957 let (ib1, ib2, ib3) = tuple_of_list3 ii in
ae4735db
C
3958 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3959 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3960 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
3961 expression ea eb >>= (fun ea eb ->
34e49164 3962 return (
ae4735db 3963 A.SwitchHeader(ia1,ia2,ea,ia3),
34e49164
C
3964 F.SwitchHeader (st, (eb,[ib1;ib2;ib3]))
3965 )))))
ae4735db
C
3966
3967 | A.Break (ia1, ia2), F.Break (st, ((),ii)) ->
34e49164 3968 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
3969 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3970 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
34e49164 3971 return (
ae4735db 3972 A.Break (ia1, ia2),
34e49164
C
3973 F.Break (st, ((),[ib1;ib2]))
3974 )))
3975
ae4735db 3976 | A.Continue (ia1, ia2), F.Continue (st, ((),ii)) ->
34e49164 3977 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
3978 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3979 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
34e49164 3980 return (
ae4735db 3981 A.Continue (ia1, ia2),
34e49164
C
3982 F.Continue (st, ((),[ib1;ib2]))
3983 )))
3984
ae4735db 3985 | A.Return (ia1, ia2), F.Return (st, ((),ii)) ->
34e49164 3986 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
3987 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3988 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
34e49164 3989 return (
ae4735db 3990 A.Return (ia1, ia2),
34e49164
C
3991 F.Return (st, ((),[ib1;ib2]))
3992 )))
3993
ae4735db 3994 | A.ReturnExpr (ia1, ea, ia2), F.ReturnExpr (st, (eb, ii)) ->
34e49164 3995 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
3996 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3997 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3998 expression ea eb >>= (fun ea eb ->
34e49164 3999 return (
ae4735db 4000 A.ReturnExpr (ia1, ea, ia2),
34e49164
C
4001 F.ReturnExpr (st, (eb, [ib1;ib2]))
4002 ))))
4003
4004
4005
ae4735db 4006 | A.Include(incla,filea),
485bce71
C
4007 F.Include {B.i_include = (fileb, ii);
4008 B.i_rel_pos = h_rel_pos;
4009 B.i_is_in_ifdef = inifdef;
4010 B.i_content = copt;
4011 } ->
b1b2de81 4012 assert (copt =*= None);
ae4735db
C
4013
4014 let include_requirment =
34e49164 4015 match mcodekind incla, mcodekind filea with
ae4735db 4016 | A.CONTEXT (_, A.BEFORE _), _ ->
34e49164 4017 IncludeMcodeBefore
ae4735db 4018 | _, A.CONTEXT (_, A.AFTER _) ->
34e49164 4019 IncludeMcodeAfter
ae4735db 4020 | _ ->
34e49164
C
4021 IncludeNothing
4022 in
4023
ae4735db 4024 let (inclb, iifileb) = tuple_of_list2 ii in
34e49164 4025 if inc_file (term filea, include_requirment) (fileb, h_rel_pos)
ae4735db
C
4026 then
4027 tokenf incla inclb >>= (fun incla inclb ->
4028 tokenf filea iifileb >>= (fun filea iifileb ->
34e49164
C
4029 return (
4030 A.Include(incla, filea),
485bce71
C
4031 F.Include {B.i_include = (fileb, [inclb;iifileb]);
4032 B.i_rel_pos = h_rel_pos;
4033 B.i_is_in_ifdef = inifdef;
4034 B.i_content = copt;
4035 }
34e49164
C
4036 )))
4037 else fail
4038
3a314143
C
4039 | A.Undef(undefa,ida), F.DefineHeader ((idb, ii), B.Undef) ->
4040 let (defineb, iidb, ieol) = tuple_of_list3 ii in
4041 ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
4042 tokenf undefa defineb >>= (fun undefa defineb ->
4043 return (
4044 A.Undef(undefa,ida),
4045 F.DefineHeader ((idb,[defineb;iidb;ieol]),B.Undef)
4046 ))
4047 )
34e49164
C
4048
4049
4050 | A.DefineHeader(definea,ida,params), F.DefineHeader ((idb, ii), defkind) ->
4051 let (defineb, iidb, ieol) = tuple_of_list3 ii in
ae4735db
C
4052 ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
4053 tokenf definea defineb >>= (fun definea defineb ->
34e49164 4054 (match A.unwrap params, defkind with
ae4735db 4055 | A.NoParams, B.DefineVar ->
34e49164 4056 return (
ae4735db 4057 A.NoParams +> A.rewrap params,
34e49164
C
4058 B.DefineVar
4059 )
ae4735db 4060 | A.DParams(lpa,eas,rpa), (B.DefineFunc (ebs, ii)) ->
34e49164 4061 let (lpb, rpb) = tuple_of_list2 ii in
ae4735db
C
4062 tokenf lpa lpb >>= (fun lpa lpb ->
4063 tokenf rpa rpb >>= (fun rpa rpb ->
34e49164 4064
ae4735db
C
4065 define_params (seqstyle eas) (A.undots eas) ebs >>=
4066 (fun easundots ebs ->
34e49164
C
4067 let eas = redots eas easundots in
4068 return (
4069 A.DParams (lpa,eas,rpa) +> A.rewrap params,
4070 B.DefineFunc (ebs,[lpb;rpb])
4071 )
4072 )))
4073 | _ -> fail
ae4735db 4074 ) >>= (fun params defkind ->
34e49164
C
4075 return (
4076 A.DefineHeader (definea, ida, params),
4077 F.DefineHeader ((idb,[defineb;iidb;ieol]),defkind)
4078 ))
4079 ))
4080
4081
ae4735db 4082 | A.Default(def,colon), F.Default (st, ((),ii)) ->
34e49164 4083 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
4084 tokenf def ib1 >>= (fun def ib1 ->
4085 tokenf colon ib2 >>= (fun colon ib2 ->
34e49164 4086 return (
ae4735db 4087 A.Default(def,colon),
34e49164
C
4088 F.Default (st, ((),[ib1;ib2]))
4089 )))
4090
ae4735db
C
4091
4092
4093 | A.Case(case,ea,colon), F.Case (st, (eb,ii)) ->
34e49164 4094 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
4095 tokenf case ib1 >>= (fun case ib1 ->
4096 expression ea eb >>= (fun ea eb ->
4097 tokenf colon ib2 >>= (fun colon ib2 ->
34e49164 4098 return (
ae4735db 4099 A.Case(case,ea,colon),
34e49164
C
4100 F.Case (st, (eb,[ib1;ib2]))
4101 ))))
4102
4103 (* only occurs in the predicates generated by asttomember *)
ae4735db 4104 | A.DisjRuleElem eas, _ ->
34e49164
C
4105 (eas +>
4106 List.fold_left (fun acc ea -> acc >|+|> (rule_elem_node ea node)) fail)
4107 >>= (fun ea eb -> return (A.unwrap ea,F.unwrap eb))
4108
4109 | _, F.ExprStatement (_, (None, ii)) -> fail (* happen ? *)
4110
b1b2de81
C
4111 | A.Label(id,dd), F.Label (st, nameb, ((),ii)) ->
4112 let (ib2) = tuple_of_list1 ii in
978fd7e5
C
4113 ident_cpp DontKnow id nameb >>= (fun ida nameb ->
4114 tokenf dd ib2 >>= (fun dd ib2 ->
4115 return (
4116 A.Label (ida,dd),
4117 F.Label (st,nameb, ((),[ib2]))
4118 )))
34e49164 4119
b1b2de81
C
4120 | A.Goto(goto,id,sem), F.Goto (st,nameb, ((),ii)) ->
4121 let (ib1,ib3) = tuple_of_list2 ii in
34e49164 4122 tokenf goto ib1 >>= (fun goto ib1 ->
b1b2de81 4123 ident_cpp DontKnow id nameb >>= (fun id nameb ->
34e49164
C
4124 tokenf sem ib3 >>= (fun sem ib3 ->
4125 return(
4126 A.Goto(goto,id,sem),
b1b2de81 4127 F.Goto (st,nameb, ((),[ib1;ib3]))
34e49164
C
4128 ))))
4129
4130 (* have not a counter part in coccinelle, for the moment *)
4131 (* todo?: print a warning at least ? *)
ae4735db 4132 | _, F.CaseRange _
34e49164 4133 | _, F.Asm _
34e49164
C
4134 | _, F.MacroTop _
4135 -> fail2()
4136
485bce71
C
4137 | _, (F.IfdefEndif _|F.IfdefElse _|F.IfdefHeader _)
4138 -> fail2 ()
4139
ae4735db 4140 | _,
485bce71
C
4141 (F.MacroStmt (_, _)| F.DefineDoWhileZeroHeader _| F.EndNode|F.TopNode)
4142 -> fail
ae4735db 4143 | _,
b1b2de81 4144 (F.Label (_, _, _)|F.Break (_, _)|F.Continue (_, _)|F.Default (_, _)|
485bce71
C
4145 F.Case (_, _)|F.Include _|F.Goto _|F.ExprStatement _|
4146 F.DefineType _|F.DefineExpr _|F.DefineTodo|
3a314143
C
4147 F.DefineHeader (_, _)|F.ReturnExpr (_, _)|F.Return (_, _)|
4148 F.MacroIterHeader (_, _)|
485bce71
C
4149 F.SwitchHeader (_, _)|F.ForHeader (_, _)|F.DoWhileTail _|F.DoHeader (_, _)|
4150 F.WhileHeader (_, _)|F.Else _|F.IfHeader (_, _)|
4151 F.SeqEnd (_, _)|F.SeqStart (_, _, _)|
4152 F.Decl _|F.FunHeader _)
4153 -> fail
4154
34e49164 4155
34e49164
C
4156 )
4157end
4158