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