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