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