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