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