1 (* Yoann Padioleau, Julia Lawall
3 * Copyright (C) 2006, 2007, 2008 Ecole des Mines de Nantes
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License (GPL)
7 * version 2 as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * file license.txt for more details.
14 * This file was part of Coccinelle.
22 module F
= Control_flow_c
24 module Flag
= Flag_matcher
26 (*****************************************************************************)
28 (*****************************************************************************)
29 let pr2, pr2_once
= Common.mk_pr2_wrappers
Flag_matcher.verbose_matcher
31 (*****************************************************************************)
33 (*****************************************************************************)
35 type sequence
= Ordered
| Unordered
38 match A.unwrap eas
with
40 | A.CIRCLES _
-> Unordered
41 | A.STARS _
-> failwith
"not handling stars"
43 let (redots
: 'a
A.dots
-> 'a list
-> 'a
A.dots
)=fun eas easundots
->
45 match A.unwrap eas
with
46 | A.DOTS _
-> A.DOTS easundots
47 | A.CIRCLES _
-> A.CIRCLES easundots
48 | A.STARS _
-> A.STARS easundots
52 let (need_unordered_initialisers
: B.initialiser
B.wrap2 list
-> bool) =
54 ibs
+> List.exists
(fun (ib
, icomma
) ->
55 match B.unwrap ib
with
65 (* For the #include <linux/...> in the .cocci, need to find where is
66 * the '+' attached to this element, to later find the first concrete
67 * #include <linux/xxx.h> or last one in the serie of #includes in the
70 type include_requirement
=
77 (* todo? put in semantic_c.ml *)
80 | LocalFunction
(* entails Function *)
84 let term mc
= A.unwrap_mcode mc
85 let mcodekind mc
= A.get_mcodekind mc
88 let mcode_contain_plus = function
89 | A.CONTEXT
(_
,A.NOTHING
) -> false
91 | A.MINUS
(_
,_
,_
,[]) -> false
92 | A.MINUS
(_
,_
,_
,x
::xs
) -> true
93 | A.PLUS _
-> raise Impossible
95 let mcode_simple_minus = function
96 | A.MINUS
(_
,_
,_
,[]) -> true
100 (* In transformation.ml sometime I build some mcodekind myself and
101 * julia has put None for the pos. But there is no possible raise
102 * NoMatch in those cases because it is for the minusall trick or for
103 * the distribute, so either have to build those pos, in fact a range,
104 * because for the distribute have to erase a fullType with one
105 * mcodekind, or add an argument to tag_with_mck such as "safe" that
106 * don't do the check_pos. Hence this DontCarePos constructor. *)
110 {A.line
= 0; A.column
=0; A.strbef
=[]; A.straft
=[];},
111 (A.MINUS
(A.DontCarePos
,[],-1,[])),
114 let generalize_mcode ia
=
115 let (s1
, i
, mck
, pos
) = ia
in
118 | A.PLUS _
-> raise Impossible
119 | A.CONTEXT
(A.NoPos
,x
) ->
120 A.CONTEXT
(A.DontCarePos
,x
)
121 | A.MINUS
(A.NoPos
,inst
,adj
,x
) ->
122 A.MINUS
(A.DontCarePos
,inst
,adj
,x
)
124 | A.CONTEXT
((A.FixPos _
|A.DontCarePos
), _
)
125 | A.MINUS
((A.FixPos _
|A.DontCarePos
), _
, _
, _
)
129 (s1
, i
, new_mck, pos
)
133 (*---------------------------------------------------------------------------*)
135 (* 0x0 is equivalent to 0, value format isomorphism *)
136 let equal_c_int s1 s2
=
138 int_of_string s1
=|= int_of_string s2
139 with Failure
("int_of_string") ->
144 (*---------------------------------------------------------------------------*)
145 (* Normally A should reuse some types of Ast_c, so those
146 * functions should not exist.
148 * update: but now Ast_c depends on A, so can't make too
149 * A depends on Ast_c, so have to stay with those equal_xxx
153 let equal_unaryOp a b
=
155 | A.GetRef
, B.GetRef
-> true
156 | A.DeRef
, B.DeRef
-> true
157 | A.UnPlus
, B.UnPlus
-> true
158 | A.UnMinus
, B.UnMinus
-> true
159 | A.Tilde
, B.Tilde
-> true
160 | A.Not
, B.Not
-> true
161 | _
, B.GetRefLabel
-> false (* todo cocci? *)
162 | _
, (B.Not
|B.Tilde
|B.UnMinus
|B.UnPlus
|B.DeRef
|B.GetRef
) -> false
166 let equal_arithOp a b
=
168 | A.Plus
, B.Plus
-> true
169 | A.Minus
, B.Minus
-> true
170 | A.Mul
, B.Mul
-> true
171 | A.Div
, B.Div
-> true
172 | A.Mod
, B.Mod
-> true
173 | A.DecLeft
, B.DecLeft
-> true
174 | A.DecRight
, B.DecRight
-> true
175 | A.And
, B.And
-> true
176 | A.Or
, B.Or
-> true
177 | A.Xor
, B.Xor
-> true
178 | _
, (B.Xor
|B.Or
|B.And
|B.DecRight
|B.DecLeft
|B.Mod
|B.Div
|B.Mul
|B.Minus
|B.Plus
)
181 let equal_logicalOp a b
=
183 | A.Inf
, B.Inf
-> true
184 | A.Sup
, B.Sup
-> true
185 | A.InfEq
, B.InfEq
-> true
186 | A.SupEq
, B.SupEq
-> true
187 | A.Eq
, B.Eq
-> true
188 | A.NotEq
, B.NotEq
-> true
189 | A.AndLog
, B.AndLog
-> true
190 | A.OrLog
, B.OrLog
-> true
191 | _
, (B.OrLog
|B.AndLog
|B.NotEq
|B.Eq
|B.SupEq
|B.InfEq
|B.Sup
|B.Inf
)
194 let equal_assignOp a b
=
196 | A.SimpleAssign
, B.SimpleAssign
-> true
197 | A.OpAssign a
, B.OpAssign b
-> equal_arithOp a b
198 | _
, (B.OpAssign _
|B.SimpleAssign
) -> false
200 let equal_fixOp a b
=
202 | A.Dec
, B.Dec
-> true
203 | A.Inc
, B.Inc
-> true
204 | _
, (B.Inc
|B.Dec
) -> false
206 let equal_binaryOp a b
=
208 | A.Arith a
, B.Arith b
-> equal_arithOp a b
209 | A.Logical a
, B.Logical b
-> equal_logicalOp a b
210 | _
, (B.Logical _
| B.Arith _
) -> false
212 let equal_structUnion a b
=
214 | A.Struct
, B.Struct
-> true
215 | A.Union
, B.Union
-> true
216 | _
, (B.Struct
|B.Union
) -> false
220 | A.Signed
, B.Signed
-> true
221 | A.Unsigned
, B.UnSigned
-> true
222 | _
, (B.UnSigned
|B.Signed
) -> false
224 let equal_storage a b
=
226 | A.Static
, B.Sto
B.Static
227 | A.Auto
, B.Sto
B.Auto
228 | A.Register
, B.Sto
B.Register
229 | A.Extern
, B.Sto
B.Extern
231 | _
, (B.NoSto
| B.StoTypedef
) -> false
232 | _
, (B.Sto
(B.Register
|B.Static
|B.Auto
|B.Extern
)) -> false
235 (*---------------------------------------------------------------------------*)
237 let equal_metavarval valu valu'
=
238 match valu
, valu'
with
239 | Ast_c.MetaIdVal a
, Ast_c.MetaIdVal b
-> a
=$
= b
240 | Ast_c.MetaFuncVal a
, Ast_c.MetaFuncVal b
-> a
=$
= b
241 | Ast_c.MetaLocalFuncVal a
, Ast_c.MetaLocalFuncVal b
->
242 (* do something more ? *)
245 (* al_expr before comparing !!! and accept when they match.
246 * Note that here we have Astc._expression, so it is a match
247 * modulo isomorphism (there is no metavariable involved here,
248 * just isomorphisms). => TODO call isomorphism_c_c instead of
249 * =*=. Maybe would be easier to transform ast_c in ast_cocci
250 * and call the iso engine of julia. *)
251 | Ast_c.MetaExprVal a
, Ast_c.MetaExprVal b
->
252 Lib_parsing_c.al_expr a
=*= Lib_parsing_c.al_expr b
253 | Ast_c.MetaExprListVal a
, Ast_c.MetaExprListVal b
->
254 Lib_parsing_c.al_arguments a
=*= Lib_parsing_c.al_arguments b
256 | Ast_c.MetaStmtVal a
, Ast_c.MetaStmtVal b
->
257 Lib_parsing_c.al_statement a
=*= Lib_parsing_c.al_statement b
258 | Ast_c.MetaInitVal a
, Ast_c.MetaInitVal b
->
259 Lib_parsing_c.al_init a
=*= Lib_parsing_c.al_init b
260 | Ast_c.MetaTypeVal a
, Ast_c.MetaTypeVal b
->
261 (* old: Lib_parsing_c.al_type a =*= Lib_parsing_c.al_type b *)
264 | Ast_c.MetaListlenVal a
, Ast_c.MetaListlenVal b
-> a
=|= b
266 | Ast_c.MetaParamVal a
, Ast_c.MetaParamVal b
->
267 Lib_parsing_c.al_param a
=*= Lib_parsing_c.al_param b
268 | Ast_c.MetaParamListVal a
, Ast_c.MetaParamListVal b
->
269 Lib_parsing_c.al_params a
=*= Lib_parsing_c.al_params b
271 | Ast_c.MetaPosVal
(posa1
,posa2
), Ast_c.MetaPosVal
(posb1
,posb2
) ->
272 Ast_cocci.equal_pos posa1 posb1
&& Ast_cocci.equal_pos posa2 posb2
274 | Ast_c.MetaPosValList l1
, Ast_c.MetaPosValList l2
->
276 (function (fla
,cea
,posa1
,posa2
) ->
278 (function (flb
,ceb
,posb1
,posb2
) ->
279 fla
=$
= flb
&& cea
=$
= ceb
&&
280 Ast_c.equal_posl posa1 posb1
&& Ast_c.equal_posl posa2 posb2
)
284 | (B.MetaPosValList _
|B.MetaListlenVal _
|B.MetaPosVal _
|B.MetaStmtVal _
285 |B.MetaTypeVal _
|B.MetaInitVal _
286 |B.MetaParamListVal _
|B.MetaParamVal _
|B.MetaExprListVal _
287 |B.MetaExprVal _
|B.MetaLocalFuncVal _
|B.MetaFuncVal _
|B.MetaIdVal _
291 (* probably only one argument needs to be stripped, because inherited
292 metavariables containing expressions are stripped in advance. But don't
293 know which one is which... *)
294 let equal_inh_metavarval valu valu'
=
295 match valu
, valu'
with
296 | Ast_c.MetaIdVal a
, Ast_c.MetaIdVal b
-> a
=$
= b
297 | Ast_c.MetaFuncVal a
, Ast_c.MetaFuncVal b
-> a
=$
= b
298 | Ast_c.MetaLocalFuncVal a
, Ast_c.MetaLocalFuncVal b
->
299 (* do something more ? *)
302 (* al_expr before comparing !!! and accept when they match.
303 * Note that here we have Astc._expression, so it is a match
304 * modulo isomorphism (there is no metavariable involved here,
305 * just isomorphisms). => TODO call isomorphism_c_c instead of
306 * =*=. Maybe would be easier to transform ast_c in ast_cocci
307 * and call the iso engine of julia. *)
308 | Ast_c.MetaExprVal a
, Ast_c.MetaExprVal b
->
309 Lib_parsing_c.al_inh_expr a
=*= Lib_parsing_c.al_inh_expr b
310 | Ast_c.MetaExprListVal a
, Ast_c.MetaExprListVal b
->
311 Lib_parsing_c.al_inh_arguments a
=*= Lib_parsing_c.al_inh_arguments b
313 | Ast_c.MetaStmtVal a
, Ast_c.MetaStmtVal b
->
314 Lib_parsing_c.al_inh_statement a
=*= Lib_parsing_c.al_inh_statement b
315 | Ast_c.MetaInitVal a
, Ast_c.MetaInitVal b
->
316 Lib_parsing_c.al_inh_init a
=*= Lib_parsing_c.al_inh_init b
317 | Ast_c.MetaTypeVal a
, Ast_c.MetaTypeVal b
->
318 (* old: Lib_parsing_c.al_inh_type a =*= Lib_parsing_c.al_inh_type b *)
321 | Ast_c.MetaListlenVal a
, Ast_c.MetaListlenVal b
-> a
=|= b
323 | Ast_c.MetaParamVal a
, Ast_c.MetaParamVal b
->
324 Lib_parsing_c.al_param a
=*= Lib_parsing_c.al_param b
325 | Ast_c.MetaParamListVal a
, Ast_c.MetaParamListVal b
->
326 Lib_parsing_c.al_params a
=*= Lib_parsing_c.al_params b
328 | Ast_c.MetaPosVal
(posa1
,posa2
), Ast_c.MetaPosVal
(posb1
,posb2
) ->
329 Ast_cocci.equal_pos posa1 posb1
&& Ast_cocci.equal_pos posa2 posb2
331 | Ast_c.MetaPosValList l1
, Ast_c.MetaPosValList l2
->
333 (function (fla
,cea
,posa1
,posa2
) ->
335 (function (flb
,ceb
,posb1
,posb2
) ->
336 fla
=$
= flb
&& cea
=$
= ceb
&&
337 Ast_c.equal_posl posa1 posb1
&& Ast_c.equal_posl posa2 posb2
)
341 | (B.MetaPosValList _
|B.MetaListlenVal _
|B.MetaPosVal _
|B.MetaStmtVal _
342 |B.MetaTypeVal _
|B.MetaInitVal _
343 |B.MetaParamListVal _
|B.MetaParamVal _
|B.MetaExprListVal _
344 |B.MetaExprVal _
|B.MetaLocalFuncVal _
|B.MetaFuncVal _
|B.MetaIdVal _
349 (*---------------------------------------------------------------------------*)
350 (* could put in ast_c.ml, next to the split/unsplit_comma *)
351 let split_signb_baseb_ii (baseb
, ii
) =
352 let iis = ii
+> List.map
(fun info
-> (B.str_of_info info
), info
) in
353 match baseb
, iis with
355 | B.Void
, ["void",i1
] -> None
, [i1
]
357 | B.FloatType
(B.CFloat
),["float",i1
] -> None
, [i1
]
358 | B.FloatType
(B.CDouble
),["double",i1
] -> None
, [i1
]
359 | B.FloatType
(B.CLongDouble
),["long",i1
;"double",i2
] -> None
,[i1
;i2
]
361 | B.IntType
(B.CChar
), ["char",i1
] -> None
, [i1
]
364 | B.IntType
(B.Si
(sign
, base
)), xs
->
368 | (B.Signed
,(("signed",i1
)::rest
)) -> (Some
(B.Signed
,i1
),rest
)
369 | (B.Signed
,rest
) -> (None
,rest
)
370 | (B.UnSigned
,(("unsigned",i1
)::rest
)) -> (Some
(B.UnSigned
,i1
),rest
)
371 | (B.UnSigned
,rest
) -> (* is this case possible? *) (None
,rest
) in
372 (* The original code only allowed explicit signed and unsigned for char,
373 while this code allows char by itself. Not sure that needs to be
374 checked for here. If it does, then add a special case. *)
376 match (base
,rest
) with
377 B.CInt
, ["int",i1
] -> [i1
]
380 | B.CInt
, ["",i1
] -> (* no type is specified at all *)
381 (match i1
.B.pinfo
with
383 | _
-> failwith
("unrecognized signed int: "^
384 (String.concat
" "(List.map fst
iis))))
386 | B.CChar2
, ["char",i2
] -> [i2
]
388 | B.CShort
, ["short",i1
] -> [i1
]
389 | B.CShort
, ["short",i1
;"int",i2
] -> [i1
;i2
]
391 | B.CLong
, ["long",i1
] -> [i1
]
392 | B.CLong
, ["long",i1
;"int",i2
] -> [i1
;i2
]
394 | B.CLongLong
, ["long",i1
;"long",i2
] -> [i1
;i2
]
395 | B.CLongLong
, ["long",i1
;"long",i2
;"int",i3
] -> [i1
;i2
;i3
]
398 failwith
("strange type1, maybe because of weird order: "^
399 (String.concat
" " (List.map fst
iis))) in
401 | _
-> failwith
("strange type2, maybe because of weird order: "^
402 (String.concat
" " (List.map fst
iis)))
404 (*---------------------------------------------------------------------------*)
406 let rec unsplit_icomma xs
=
410 (match A.unwrap y
with
412 (x
, y
)::unsplit_icomma xs
413 | _
-> failwith
"wrong ast_cocci in initializer"
416 failwith
("wrong ast_cocci in initializer, should have pair " ^
421 let resplit_initialiser ibs iicomma
=
422 match iicomma
, ibs
with
425 failwith
"should have a iicomma, do you generate fakeInfo in parser?"
427 failwith
"shouldn't have a iicomma"
428 | [iicomma
], x
::xs
->
429 let elems = List.map fst
(x
::xs
) in
430 let commas = List.map snd
(x
::xs
) +> List.flatten
in
431 let commas = commas @ [iicomma
] in
433 | _
-> raise Impossible
437 let rec split_icomma xs
=
440 | (x
,y
)::xs
-> x
::y
::split_icomma xs
442 let rec unsplit_initialiser ibs_unsplit
=
443 match ibs_unsplit
with
444 | [] -> [], [] (* empty iicomma *)
446 let (xs
, lastcomma
) = unsplit_initialiser_bis commax xs
in
447 (x
, [])::xs
, lastcomma
449 and unsplit_initialiser_bis comma_before
= function
450 | [] -> [], [comma_before
]
452 let (xs
, lastcomma
) = unsplit_initialiser_bis commax xs
in
453 (x
, [comma_before
])::xs
, lastcomma
458 (*---------------------------------------------------------------------------*)
459 (* coupling: same in type_annotater_c.ml *)
460 let structdef_to_struct_name ty
=
462 | qu
, (B.StructUnion
(su
, sopt
, fields
), iis) ->
464 | Some s
, [i1
;i2
;i3
;i4
] ->
465 qu
, (B.StructUnionName
(su
, s
), [i1
;i2
])
469 | x
-> raise Impossible
471 | _
-> raise Impossible
473 (*---------------------------------------------------------------------------*)
474 let initialisation_to_affectation decl
=
476 | B.MacroDecl _
-> F.Decl decl
477 | B.DeclList
(xs
, iis) ->
479 (* todo?: should not do that if the variable is an array cos
480 * will have x[] = , mais de toute facon ca sera pas un InitExp
483 | [] -> raise Impossible
485 let ({B.v_namei
= var
;
486 B.v_type
= returnType
;
487 B.v_type_bis
= tybis
;
488 B.v_storage
= storage
;
495 | Some
(name
, iniopt
) ->
497 | Some
(iini
, (B.InitExpr e
, ii_empty2
)) ->
501 Ast_c.NotLocalDecl
-> Ast_c.NotLocalVar
503 Ast_c.LocalVar
(Ast_c.info_of_type returnType
) in
506 (* old: Lib_parsing_c.al_type returnType
507 * but this type has not the typename completed so
508 * instead try to use tybis
511 | Some ty_with_typename_completed
->
512 ty_with_typename_completed
513 | None
-> raise Impossible
517 ref (Some
(typexp,local),
521 Ast_c.mk_e_bis
(B.Ident
(ident)) typ Ast_c.noii
525 (B.Assignment
(idexpr,B.SimpleAssign
, e
)) [iini
] in
533 pr2_once
"TODO: initialisation_to_affectation for multi vars";
534 (* todo? do a fold_left and generate 'x = a, y = b' etc, use
535 * the Sequence expression operator of C and make an
536 * ExprStatement from that.
545 (*****************************************************************************)
546 (* Functor parameter combinators *)
547 (*****************************************************************************)
549 * src: papers on parser combinators in haskell (cf a pearl by meijer in ICFP)
551 * version0: was not tagging the SP, so just tag the C
553 * (tin -> 'c tout) -> ('c -> (tin -> 'b tout)) -> (tin -> 'b tout)
554 * val return : 'b -> tin -> 'b tout
555 * val fail : tin -> 'b tout
557 * version1: now also tag the SP so return a ('a * 'b)
560 type mode
= PatternMode
| TransformMode
568 type ('a
, 'b
) matcher
= 'a
-> 'b
-> tin
-> ('a
* 'b
) tout
573 (tin
-> ('a
* 'b
) tout
) ->
574 ('a
-> 'b
-> (tin
-> ('c
* 'd
) tout
)) ->
575 (tin
-> ('c
* 'd
) tout
)
577 val return
: ('a
* 'b
) -> tin
-> ('a
*'b
) tout
578 val fail
: tin
-> ('a
* 'b
) tout
590 val (>&&>) : (tin
-> bool) -> (tin
-> 'x tout
) -> (tin
-> 'x tout
)
592 val tokenf
: ('a
A.mcode
, B.info
) matcher
593 val tokenf_mck
: (A.mcodekind, B.info
) matcher
596 (A.meta_name
A.mcode
, B.expression
) matcher
598 (A.meta_name
A.mcode
, (Ast_c.argument
, Ast_c.il
) either list
) matcher
600 (A.meta_name
A.mcode
, Ast_c.fullType
) matcher
602 (A.meta_name
A.mcode
,
603 (Ast_c.parameterType
, Ast_c.il
) either list
) matcher
605 (A.meta_name
A.mcode
, Ast_c.parameterType
) matcher
607 (A.meta_name
A.mcode
, Ast_c.initialiser
) matcher
609 (A.meta_name
A.mcode
, Control_flow_c.node
) matcher
611 val distrf_define_params
:
612 (A.meta_name
A.mcode
, (string Ast_c.wrap
, Ast_c.il
) either list
)
615 val distrf_struct_fields
:
616 (A.meta_name
A.mcode
, B.field list
) matcher
619 (A.meta_name
A.mcode
, (B.constant
, string) either
B.wrap
) matcher
622 (A.expression
, B.expression
) matcher
-> (A.expression
, F.node
) matcher
625 (A.expression
, B.expression
) matcher
->
626 (A.expression
, B.expression
) matcher
629 (A.fullType
, B.fullType
) matcher
-> (A.fullType
, F.node
) matcher
632 (A.initialiser
, B.initialiser
) matcher
-> (A.initialiser
, F.node
) matcher
635 A.keep_binding
-> A.inherited
->
636 A.meta_name
A.mcode
* Ast_c.metavar_binding_kind
*
637 (unit -> Common.filename
* string * Ast_c.posl
* Ast_c.posl
) ->
638 (unit -> tin
-> 'x tout
) -> (tin
-> 'x tout
)
640 val check_idconstraint
:
641 ('a
-> 'b
-> bool) -> 'a
-> 'b
->
642 (unit -> tin
-> 'x tout
) -> (tin
-> 'x tout
)
644 val check_constraints_ne
:
645 ('a
, 'b
) matcher
-> 'a list
-> 'b
->
646 (unit -> tin
-> 'x tout
) -> (tin
-> 'x tout
)
648 val all_bound
: A.meta_name list
-> (tin
-> bool)
650 val optional_storage_flag
: (bool -> tin
-> 'x tout
) -> (tin
-> 'x tout
)
651 val optional_qualifier_flag
: (bool -> tin
-> 'x tout
) -> (tin
-> 'x tout
)
652 val value_format_flag
: (bool -> tin
-> 'x tout
) -> (tin
-> 'x tout
)
657 (*****************************************************************************)
658 (* Functor code, "Cocci vs C" *)
659 (*****************************************************************************)
662 functor (X
: PARAM
) ->
665 type ('a
, 'b
) matcher
= 'a
-> 'b
-> X.tin
-> ('a
* 'b
) X.tout
668 let return = X.return
671 let (>||>) = X.(>||>)
672 let (>|+|>) = X.(>|+|>)
673 let (>&&>) = X.(>&&>)
675 let tokenf = X.tokenf
677 (* should be raise Impossible when called from transformation.ml *)
680 | PatternMode
-> fail
681 | TransformMode
-> raise Impossible
684 let (option: ('a
,'b
) matcher
-> ('a
option,'b
option) matcher
)= fun f t1 t2
->
686 | (Some t1
, Some t2
) ->
687 f t1 t2
>>= (fun t1 t2
->
688 return (Some t1
, Some t2
)
690 | (None
, None
) -> return (None
, None
)
693 (* Dots are sometimes used as metavariables, since like metavariables they
694 can match other things. But they no longer have the same type. Perhaps these
695 functions could be avoided by introducing an appropriate level of polymorphism,
696 but I don't know how to declare polymorphism across functors *)
697 let dots2metavar (_
,info
,mcodekind,pos
) = (("","..."),info
,mcodekind,pos
)
698 let metavar2dots (_
,info
,mcodekind,pos
) = ("...",info
,mcodekind,pos
)
700 let satisfies_iconstraint c id
: bool =
702 A.IdNoConstraint
-> true
703 | A.IdNegIdSet l
-> not
(List.mem id l
)
704 | A.IdRegExp
(_
,recompiled
) ->
705 if Str.string_match recompiled id
0 then
709 | A.IdNotRegExp
(_
,recompiled
) ->
710 if Str.string_match recompiled id
0 then
715 let satisfies_econstraint c exp
: bool =
716 match Ast_c.unwrap_expr exp
with
717 Ast_c.Ident
(name
) ->
720 Ast_c.RegularName rname
-> satisfies_iconstraint c
(Ast_c.unwrap_st rname
)
721 | Ast_c.CppConcatenatedName _
->
722 pr2_once
("WARNING: Unable to apply a constraint on a CppConcatenatedName identifier !"); true
723 | Ast_c.CppVariadicName _
->
724 pr2_once
("WARNING: Unable to apply a constraint on a CppVariadicName identifier !"); true
725 | Ast_c.CppIdentBuilder _
->
726 pr2_once
("WARNING: Unable to apply a constraint on a CppIdentBuilder identifier !"); true
728 | Ast_c.Constant cst
->
730 | Ast_c.String
(str
, _
) -> satisfies_iconstraint c str
731 | Ast_c.MultiString strlist
->
732 pr2_once
("WARNING: Unable to apply a constraint on an multistring constant !"); true
733 | Ast_c.Char
(char
, _
) -> satisfies_iconstraint c char
734 | Ast_c.Int
(int , _
) -> satisfies_iconstraint c
int
735 | Ast_c.Float
(float, _
) -> satisfies_iconstraint c
float
737 | _
-> pr2_once
("WARNING: Unable to apply a constraint on an expression !"); true
739 (*---------------------------------------------------------------------------*)
751 (*---------------------------------------------------------------------------*)
752 let rec (expression
: (A.expression
, Ast_c.expression
) matcher
) =
754 X.all_bound
(A.get_inherited ea
) >&&>
755 let wa x
= A.rewrap ea x
in
756 match A.unwrap ea
, eb
with
758 (* general case: a MetaExpr can match everything *)
759 | A.MetaExpr
(ida
,constraints
,keep
,opttypa
,form
,inherited
),
760 (((expr
, opttypb
), ii
) as expb
) ->
762 (* old: before have a MetaConst. Now we factorize and use 'form' to
763 * differentiate between different cases *)
764 let rec matches_id = function
765 B.Ident
(name
) -> true
766 | B.Cast
(ty
,e
) -> matches_id (B.unwrap_expr e
)
769 match (form
,expr
) with
772 let rec matches = function
773 B.Constant
(c
) -> true
774 | B.Ident
(nameidb
) ->
775 let s = Ast_c.str_of_name nameidb
in
776 if s =~
"^[A-Z_][A-Z_0-9]*$"
778 pr2_once
("warning: " ^
s ^
" treated as a constant");
782 | B.Cast
(ty
,e
) -> matches (B.unwrap_expr e
)
783 | B.Unary
(e
,B.UnMinus
) -> matches (B.unwrap_expr e
)
784 | B.SizeOfExpr
(exp
) -> true
785 | B.SizeOfType
(ty
) -> true
791 (Some
(_
,Ast_c.LocalVar _
),_
) -> true
793 | (A.ID
,e
) -> matches_id e
in
797 (let (opttypb
,_testb
) = !opttypb
in
798 match opttypa
, opttypb
with
799 | None
, _
-> return ((),())
801 pr2_once
("Missing type information. Certainly a pb in " ^
802 "annotate_typer.ml");
805 | Some tas
, Some tb
->
806 tas
+> List.fold_left
(fun acc ta
->
807 acc
>|+|> compatible_type ta tb
) fail
810 match constraints
with
811 Ast_cocci.NoConstraint
->
813 Lib_parsing_c.lin_col_by_pos
(Lib_parsing_c.ii_of_expr expb
) in
814 X.envf keep inherited
(ida
, Ast_c.MetaExprVal expb
, max_min)
816 X.distrf_e ida expb
>>=
819 A.MetaExpr
(ida
,constraints
,keep
,opttypa
,form
,inherited
)+>
825 | Ast_cocci.NotIdCstrt cstrt
->
826 X.check_idconstraint
satisfies_econstraint cstrt eb
829 Lib_parsing_c.lin_col_by_pos
(Lib_parsing_c.ii_of_expr expb
) in
830 X.envf keep inherited
(ida
, Ast_c.MetaExprVal expb
, max_min)
832 X.distrf_e ida expb
>>=
835 A.MetaExpr
(ida
,constraints
,keep
,opttypa
,form
,inherited
)+>
841 | Ast_cocci.NotExpCstrt cstrts
->
842 X.check_constraints_ne expression cstrts eb
845 Lib_parsing_c.lin_col_by_pos
(Lib_parsing_c.ii_of_expr expb
) in
846 X.envf keep inherited
(ida
, Ast_c.MetaExprVal expb
, max_min)
848 X.distrf_e ida expb
>>=
851 A.MetaExpr
(ida
,constraints
,keep
,opttypa
,form
,inherited
)+>
859 * | A.MetaExpr(ida,false,opttypa,_inherited), expb ->
860 * D.distribute_mck (mcodekind ida) D.distribute_mck_e expb binding
862 * but bug! because if have not tagged SP, then transform without doing
863 * any checks. Hopefully now have tagged SP technique.
868 * | A.Edots _, _ -> raise Impossible.
870 * In fact now can also have the Edots inside normal expression, not
871 * just in arg lists. in 'x[...];' less: in if(<... x ... y ...>)
873 | A.Edots
(mcode
, None
), expb
->
874 X.distrf_e
(dots2metavar mcode
) expb
>>= (fun mcode expb
->
876 A.Edots
(metavar2dots mcode
, None
) +> A.rewrap ea
,
881 | A.Edots
(_
, Some expr
), _
-> failwith
"not handling when on Edots"
884 | A.Ident ida
, ((B.Ident
(nameidb
), typ),noii
) ->
886 ident_cpp DontKnow ida nameidb
>>= (fun ida nameidb
->
888 ((A.Ident ida
)) +> wa,
889 ((B.Ident
(nameidb
), typ),Ast_c.noii
)
895 | A.MetaErr _
, _
-> failwith
"not handling MetaErr"
897 (* todo?: handle some isomorphisms in int/float ? can have different
898 * format : 1l can match a 1.
900 * todo: normally string can contain some metavar too, so should
901 * recurse on the string
903 | A.Constant
(ia1
), ((B.Constant
(ib
) , typ),ii
) ->
904 (* for everything except the String case where can have multi elems *)
906 let ib1 = tuple_of_list1 ii
in
907 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
909 ((A.Constant ia1
)) +> wa,
910 ((B.Constant
(ib
), typ),[ib1])
913 (match term ia1
, ib
with
914 | A.Int x
, B.Int
(y
,_
) ->
915 X.value_format_flag
(fun use_value_equivalence
->
916 if use_value_equivalence
926 | A.Char x
, B.Char
(y
,_
) when x
=$
= y
(* todo: use kind ? *)
928 | A.Float x
, B.Float
(y
,_
) when x
=$
= y
(* todo: use floatType ? *)
931 | A.String sa
, B.String
(sb
,_kind
) when sa
=$
= sb
->
934 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
936 ((A.Constant ia1
)) +> wa,
937 ((B.Constant
(ib
), typ),[ib1])
939 | _
-> fail (* multi string, not handled *)
942 | _
, B.MultiString _
-> (* todo cocci? *) fail
943 | _
, (B.String _
| B.Float _
| B.Char _
| B.Int _
) -> fail
947 | A.FunCall
(ea
, ia1
, eas
, ia2
), ((B.FunCall
(eb
, ebs
), typ),ii
) ->
948 (* todo: do special case to allow IdMetaFunc, cos doing the
949 * recursive call will be too late, match_ident will not have the
950 * info whether it was a function. todo: but how detect when do
951 * x.field = f; how know that f is a Func ? By having computed
952 * some information before the matching!
954 * Allow match with FunCall containing types. Now ast_cocci allow
955 * type in parameter, and morover ast_cocci allow f(...) and those
956 * ... could match type.
958 let (ib1, ib2
) = tuple_of_list2 ii
in
959 expression ea eb
>>= (fun ea eb
->
960 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
961 tokenf ia2 ib2
>>= (fun ia2 ib2
->
962 arguments
(seqstyle eas
) (A.undots eas
) ebs
>>= (fun easundots ebs
->
963 let eas = redots
eas easundots
in
965 ((A.FunCall
(ea
, ia1
, eas, ia2
)) +> wa,
966 ((B.FunCall
(eb
, ebs
),typ), [ib1;ib2
])
972 | A.Assignment
(ea1
, opa
, ea2
, simple
),
973 ((B.Assignment
(eb1
, opb
, eb2
), typ),ii
) ->
974 let (opbi
) = tuple_of_list1 ii
in
975 if equal_assignOp (term opa
) opb
977 expression ea1 eb1
>>= (fun ea1 eb1
->
978 expression ea2 eb2
>>= (fun ea2 eb2
->
979 tokenf opa opbi
>>= (fun opa opbi
->
981 ((A.Assignment
(ea1
, opa
, ea2
, simple
))) +> wa,
982 ((B.Assignment
(eb1
, opb
, eb2
), typ), [opbi
])
986 | A.CondExpr
(ea1
,ia1
,ea2opt
,ia2
,ea3
),((B.CondExpr
(eb1
,eb2opt
,eb3
),typ),ii
) ->
987 let (ib1, ib2
) = tuple_of_list2 ii
in
988 expression ea1 eb1
>>= (fun ea1 eb1
->
989 option expression ea2opt eb2opt
>>= (fun ea2opt eb2opt
->
990 expression ea3 eb3
>>= (fun ea3 eb3
->
991 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
992 tokenf ia2 ib2
>>= (fun ia2 ib2
->
994 ((A.CondExpr
(ea1
,ia1
,ea2opt
,ia2
,ea3
))) +> wa,
995 ((B.CondExpr
(eb1
, eb2opt
, eb3
),typ), [ib1;ib2
])
998 (* todo?: handle some isomorphisms here ? *)
999 | A.Postfix
(ea
, opa
), ((B.Postfix
(eb
, opb
), typ),ii
) ->
1000 let opbi = tuple_of_list1 ii
in
1001 if equal_fixOp (term opa
) opb
1003 expression ea eb
>>= (fun ea eb
->
1004 tokenf opa
opbi >>= (fun opa
opbi ->
1006 ((A.Postfix
(ea
, opa
))) +> wa,
1007 ((B.Postfix
(eb
, opb
), typ),[opbi])
1012 | A.Infix
(ea
, opa
), ((B.Infix
(eb
, opb
), typ),ii
) ->
1013 let opbi = tuple_of_list1 ii
in
1014 if equal_fixOp (term opa
) opb
1016 expression ea eb
>>= (fun ea eb
->
1017 tokenf opa
opbi >>= (fun opa
opbi ->
1019 ((A.Infix
(ea
, opa
))) +> wa,
1020 ((B.Infix
(eb
, opb
), typ),[opbi])
1024 | A.Unary
(ea
, opa
), ((B.Unary
(eb
, opb
), typ),ii
) ->
1025 let opbi = tuple_of_list1 ii
in
1026 if equal_unaryOp (term opa
) opb
1028 expression ea eb
>>= (fun ea eb
->
1029 tokenf opa
opbi >>= (fun opa
opbi ->
1031 ((A.Unary
(ea
, opa
))) +> wa,
1032 ((B.Unary
(eb
, opb
), typ),[opbi])
1036 | A.Binary
(ea1
, opa
, ea2
), ((B.Binary
(eb1
, opb
, eb2
), typ),ii
) ->
1037 let opbi = tuple_of_list1 ii
in
1038 if equal_binaryOp (term opa
) opb
1040 expression ea1 eb1
>>= (fun ea1 eb1
->
1041 expression ea2 eb2
>>= (fun ea2 eb2
->
1042 tokenf opa
opbi >>= (fun opa
opbi ->
1044 ((A.Binary
(ea1
, opa
, ea2
))) +> wa,
1045 ((B.Binary
(eb1
, opb
, eb2
), typ),[opbi]
1049 | A.Nested
(ea1
, opa
, ea2
), eb
->
1051 (if A.get_test_exp ea1
&& not
(Ast_c.is_test eb
) then fail
1052 else expression ea1 eb
) >|+|>
1054 ((B.Binary
(eb1
, opb
, eb2
), typ),ii
)
1055 when equal_binaryOp (term opa
) opb
->
1056 let opbi = tuple_of_list1 ii
in
1058 (expression ea1 eb1
>>= (fun ea1 eb1
->
1059 expression ea2 eb2
>>= (fun ea2 eb2
->
1060 tokenf opa
opbi >>= (fun opa
opbi ->
1062 ((A.Nested
(ea1
, opa
, ea2
))) +> wa,
1063 ((B.Binary
(eb1
, opb
, eb2
), typ),[opbi]
1066 (expression ea2 eb1
>>= (fun ea2 eb1
->
1067 expression ea1 eb2
>>= (fun ea1 eb2
->
1068 tokenf opa
opbi >>= (fun opa
opbi ->
1070 ((A.Nested
(ea1
, opa
, ea2
))) +> wa,
1071 ((B.Binary
(eb1
, opb
, eb2
), typ),[opbi]
1074 (loop eb1
>>= (fun ea1 eb1
->
1075 expression ea2 eb2
>>= (fun ea2 eb2
->
1076 tokenf opa
opbi >>= (fun opa
opbi ->
1078 ((A.Nested
(ea1
, opa
, ea2
))) +> wa,
1079 ((B.Binary
(eb1
, opb
, eb2
), typ),[opbi]
1082 (expression ea2 eb1
>>= (fun ea2 eb1
->
1083 loop eb2
>>= (fun ea1 eb2
->
1084 tokenf opa
opbi >>= (fun opa
opbi ->
1086 ((A.Nested
(ea1
, opa
, ea2
))) +> wa,
1087 ((B.Binary
(eb1
, opb
, eb2
), typ),[opbi]
1089 left_to_right >|+|> right_to_left >|+|> in_left >|+|> in_right
1093 (* todo?: handle some isomorphisms here ? (with pointers = Unary Deref) *)
1094 | A.ArrayAccess
(ea1
, ia1
, ea2
, ia2
),((B.ArrayAccess
(eb1
, eb2
), typ),ii
) ->
1095 let (ib1, ib2
) = tuple_of_list2 ii
in
1096 expression ea1 eb1
>>= (fun ea1 eb1
->
1097 expression ea2 eb2
>>= (fun ea2 eb2
->
1098 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
1099 tokenf ia2 ib2
>>= (fun ia2 ib2
->
1101 ((A.ArrayAccess
(ea1
, ia1
, ea2
, ia2
))) +> wa,
1102 ((B.ArrayAccess
(eb1
, eb2
),typ), [ib1;ib2
])
1105 (* todo?: handle some isomorphisms here ? *)
1106 | A.RecordAccess
(ea
, ia1
, ida
), ((B.RecordAccess
(eb
, idb
), typ),ii
) ->
1107 let (ib1) = tuple_of_list1 ii
in
1108 ident_cpp DontKnow ida idb
>>= (fun ida idb
->
1109 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
1110 expression ea eb
>>= (fun ea eb
->
1112 ((A.RecordAccess
(ea
, ia1
, ida
))) +> wa,
1113 ((B.RecordAccess
(eb
, idb
), typ), [ib1])
1118 | A.RecordPtAccess
(ea
,ia1
,ida
),((B.RecordPtAccess
(eb
, idb
), typ), ii
) ->
1119 let (ib1) = tuple_of_list1 ii
in
1120 ident_cpp DontKnow ida idb
>>= (fun ida idb
->
1121 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
1122 expression ea eb
>>= (fun ea eb
->
1124 ((A.RecordPtAccess
(ea
, ia1
, ida
))) +> wa,
1125 ((B.RecordPtAccess
(eb
, idb
), typ), [ib1])
1129 (* todo?: handle some isomorphisms here ?
1130 * todo?: do some iso-by-absence on cast ?
1131 * by trying | ea, B.Case (typb, eb) -> match_e_e ea eb ?
1134 | A.Cast
(ia1
, typa
, ia2
, ea
), ((B.Cast
(typb
, eb
), typ),ii
) ->
1135 let (ib1, ib2
) = tuple_of_list2 ii
in
1136 fullType typa typb
>>= (fun typa typb
->
1137 expression ea eb
>>= (fun ea eb
->
1138 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
1139 tokenf ia2 ib2
>>= (fun ia2 ib2
->
1141 ((A.Cast
(ia1
, typa
, ia2
, ea
))) +> wa,
1142 ((B.Cast
(typb
, eb
),typ),[ib1;ib2
])
1145 | A.SizeOfExpr
(ia1
, ea
), ((B.SizeOfExpr
(eb
), typ),ii
) ->
1146 let ib1 = tuple_of_list1 ii
in
1147 expression ea eb
>>= (fun ea eb
->
1148 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
1150 ((A.SizeOfExpr
(ia1
, ea
))) +> wa,
1151 ((B.SizeOfExpr
(eb
), typ),[ib1])
1154 | A.SizeOfType
(ia1
, ia2
, typa
, ia3
), ((B.SizeOfType typb
, typ),ii
) ->
1155 let (ib1,ib2
,ib3
) = tuple_of_list3 ii
in
1156 fullType typa typb
>>= (fun typa typb
->
1157 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
1158 tokenf ia2 ib2
>>= (fun ia2 ib2
->
1159 tokenf ia3 ib3
>>= (fun ia3 ib3
->
1161 ((A.SizeOfType
(ia1
, ia2
, typa
, ia3
))) +> wa,
1162 ((B.SizeOfType
(typb
),typ),[ib1;ib2
;ib3
])
1166 (* todo? iso ? allow all the combinations ? *)
1167 | A.Paren
(ia1
, ea
, ia2
), ((B.ParenExpr
(eb
), typ),ii
) ->
1168 let (ib1, ib2
) = tuple_of_list2 ii
in
1169 expression ea eb
>>= (fun ea eb
->
1170 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
1171 tokenf ia2 ib2
>>= (fun ia2 ib2
->
1173 ((A.Paren
(ia1
, ea
, ia2
))) +> wa,
1174 ((B.ParenExpr
(eb
), typ), [ib1;ib2
])
1177 | A.NestExpr
(exps
,None
,true), eb
->
1178 (match A.unwrap exps
with
1180 X.cocciExpExp expression exp eb
>>= (fun exp eb
->
1182 (A.NestExpr
(A.rewrap exps
(A.DOTS
[exp
]),None
,true)) +> wa,
1188 "for nestexpr, only handling the case with dots and only one exp")
1190 | A.NestExpr _
, _
->
1191 failwith
"only handling multi and no when code in a nest expr"
1193 (* only in arg lists or in define body *)
1194 | A.TypeExp _
, _
-> fail
1196 (* only in arg lists *)
1197 | A.MetaExprList _
, _
1204 | A.DisjExpr
eas, eb
->
1205 eas +> List.fold_left
(fun acc ea
-> acc
>|+|> (expression ea eb
)) fail
1207 | A.UniqueExp _
,_
| A.OptExp _
,_
->
1208 failwith
"not handling Opt/Unique/Multi on expr"
1210 (* Because of Exp cant put a raise Impossible; have to put a fail *)
1212 (* have not a counter part in coccinelle, for the moment *)
1213 | _
, ((B.Sequence _
,_
),_
)
1214 | _
, ((B.StatementExpr _
,_
),_
)
1215 | _
, ((B.Constructor _
,_
),_
)
1220 (((B.Cast
(_
, _
)|B.ParenExpr _
|B.SizeOfType _
|B.SizeOfExpr _
|
1221 B.RecordPtAccess
(_
, _
)|
1222 B.RecordAccess
(_
, _
)|B.ArrayAccess
(_
, _
)|
1223 B.Binary
(_
, _
, _
)|B.Unary
(_
, _
)|
1224 B.Infix
(_
, _
)|B.Postfix
(_
, _
)|
1225 B.Assignment
(_
, _
, _
)|B.CondExpr
(_
, _
, _
)|
1226 B.FunCall
(_
, _
)|B.Constant _
|B.Ident _
),
1234 (* ------------------------------------------------------------------------- *)
1235 and (ident_cpp
: info_ident
-> (A.ident, B.name
) matcher
) =
1236 fun infoidb ida idb
->
1238 | B.RegularName
(s, iis) ->
1239 let iis = tuple_of_list1
iis in
1240 ident infoidb ida
(s, iis) >>= (fun ida
(s,iis) ->
1243 (B.RegularName
(s, [iis]))
1245 | B.CppConcatenatedName _
| B.CppVariadicName _
|B.CppIdentBuilder _
1247 (* This should be moved to the Id case of ident. Metavariables
1248 should be allowed to be bound to such variables. But doing so
1249 would require implementing an appropriate distr function *)
1252 and (ident: info_ident
-> (A.ident, string * Ast_c.info
) matcher
) =
1253 fun infoidb ida
((idb
, iib
)) -> (* (idb, iib) as ib *)
1254 X.all_bound
(A.get_inherited ida
) >&&>
1255 match A.unwrap ida
with
1257 if (term sa
) =$
= idb
then
1258 tokenf sa iib
>>= (fun sa iib
->
1260 ((A.Id sa
)) +> A.rewrap ida
,
1265 | A.MetaId
(mida
,constraints
,keep
,inherited
) ->
1266 X.check_idconstraint
satisfies_iconstraint constraints idb
1268 let max_min _
= Lib_parsing_c.lin_col_by_pos
[iib
] in
1269 (* use drop_pos for ids so that the pos is not added a second time in
1270 the call to tokenf *)
1271 X.envf keep inherited
(A.drop_pos mida
, Ast_c.MetaIdVal
(idb
), max_min)
1273 tokenf mida iib
>>= (fun mida iib
->
1275 ((A.MetaId
(mida
, constraints
, keep
, inherited
)) +> A.rewrap ida
,
1280 | A.MetaFunc
(mida
,constraints
,keep
,inherited
) ->
1282 X.check_idconstraint
satisfies_iconstraint constraints idb
1284 let max_min _
= Lib_parsing_c.lin_col_by_pos
[iib
] in
1285 X.envf keep inherited
(A.drop_pos mida
,Ast_c.MetaFuncVal idb
,max_min)
1287 tokenf mida iib
>>= (fun mida iib
->
1289 ((A.MetaFunc
(mida
,constraints
,keep
,inherited
)))+>A.rewrap ida
,
1294 | LocalFunction
| Function
-> is_function()
1296 failwith
"MetaFunc, need more semantic info about id"
1297 (* the following implementation could possibly be useful, if one
1298 follows the convention that a macro is always in capital letters
1299 and that a macro is not a function.
1300 (if idb =~ "^[A-Z_][A-Z_0-9]*$" then fail else is_function())*)
1303 | A.MetaLocalFunc
(mida
,constraints
,keep
,inherited
) ->
1306 X.check_idconstraint
satisfies_iconstraint constraints idb
1308 let max_min _
= Lib_parsing_c.lin_col_by_pos
[iib
] in
1309 X.envf keep inherited
1310 (A.drop_pos mida
,Ast_c.MetaLocalFuncVal idb
, max_min)
1312 tokenf mida iib
>>= (fun mida iib
->
1314 ((A.MetaLocalFunc
(mida
,constraints
,keep
,inherited
)))
1320 | DontKnow
-> failwith
"MetaLocalFunc, need more semantic info about id"
1323 | A.OptIdent _
| A.UniqueIdent _
->
1324 failwith
"not handling Opt/Unique for ident"
1328 (* ------------------------------------------------------------------------- *)
1329 and (arguments
: sequence
->
1330 (A.expression list
, Ast_c.argument
Ast_c.wrap2 list
) matcher
) =
1331 fun seqstyle eas ebs
->
1333 | Unordered
-> failwith
"not handling ooo"
1335 arguments_bis
eas (Ast_c.split_comma ebs
) >>= (fun eas ebs_splitted
->
1336 return (eas, (Ast_c.unsplit_comma ebs_splitted
))
1338 (* because '...' can match nothing, need to take care when have
1339 * ', ...' or '...,' as in f(..., X, Y, ...). It must match
1340 * f(1,2) for instance.
1341 * So I have added special cases such as (if startxs = []) and code
1342 * in the Ecomma matching rule.
1344 * old: Must do some try, for instance when f(...,X,Y,...) have to
1345 * test the transfo for all the combinaitions and if multiple transfo
1346 * possible ? pb ? => the type is to return a expression option ? use
1347 * some combinators to help ?
1348 * update: with the tag-SP approach, no more a problem.
1351 and arguments_bis
= fun eas ebs
->
1353 | [], [] -> return ([], [])
1354 | [], eb
::ebs
-> fail
1356 X.all_bound
(A.get_inherited ea
) >&&>
1357 (match A.unwrap ea
, ebs
with
1358 | A.Edots
(mcode
, optexpr
), ys
->
1359 (* todo: if optexpr, then a WHEN and so may have to filter yys *)
1360 if optexpr
<> None
then failwith
"not handling when in argument";
1362 (* '...' can take more or less the beginnings of the arguments *)
1363 let startendxs = Common.zip
(Common.inits ys
) (Common.tails ys
) in
1364 startendxs +> List.fold_left
(fun acc
(startxs
, endxs
) ->
1367 (* allow '...', and maybe its associated ',' to match nothing.
1368 * for the associated ',' see below how we handle the EComma
1373 if mcode_contain_plus (mcodekind mcode
)
1375 (* failwith "I have no token that I could accroche myself on" *)
1376 else return (dots2metavar mcode
, [])
1378 (* subtil: we dont want the '...' to match until the
1379 * comma. cf -test pb_params_iso. We would get at
1380 * "already tagged" error.
1381 * this is because both f (... x, ...) and f (..., x, ...)
1382 * would match a f(x,3) with our "optional-comma" strategy.
1384 (match Common.last startxs
with
1387 X.distrf_args
(dots2metavar mcode
) startxs
1390 >>= (fun mcode startxs
->
1391 let mcode = metavar2dots mcode in
1392 arguments_bis
eas endxs
>>= (fun eas endxs
->
1394 (A.Edots
(mcode, optexpr
) +> A.rewrap ea
) ::eas,
1400 | A.EComma ia1
, Right ii
::ebs
->
1401 let ib1 = tuple_of_list1 ii
in
1402 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
1403 arguments_bis
eas ebs
>>= (fun eas ebs
->
1405 (A.EComma ia1
+> A.rewrap ea
)::eas,
1409 | A.EComma ia1
, ebs
->
1410 (* allow ',' to maching nothing. optional comma trick *)
1411 if mcode_contain_plus (mcodekind ia1
)
1413 else arguments_bis
eas ebs
1415 | A.MetaExprList
(ida
,leninfo
,keep
,inherited
),ys
->
1416 let startendxs = Common.zip
(Common.inits ys
) (Common.tails ys
) in
1417 startendxs +> List.fold_left
(fun acc
(startxs
, endxs
) ->
1422 if mcode_contain_plus (mcodekind ida
)
1424 (* failwith "no token that I could accroche myself on" *)
1427 (match Common.last startxs
with
1435 let startxs'
= Ast_c.unsplit_comma
startxs in
1436 let len = List.length
startxs'
in
1439 | Some
(lenname
,lenkeep
,leninherited
) ->
1440 let max_min _
= failwith
"no pos" in
1441 X.envf lenkeep leninherited
1442 (lenname
, Ast_c.MetaListlenVal
(len), max_min)
1443 | None
-> function f
-> f
()
1447 Lib_parsing_c.lin_col_by_pos
1448 (Lib_parsing_c.ii_of_args
startxs) in
1449 X.envf keep inherited
1450 (ida
, Ast_c.MetaExprListVal
startxs'
, max_min)
1453 then return (ida
, [])
1454 else X.distrf_args ida
(Ast_c.split_comma
startxs'
)
1456 >>= (fun ida
startxs ->
1457 arguments_bis
eas endxs
>>= (fun eas endxs
->
1459 (A.MetaExprList
(ida
,leninfo
,keep
,inherited
))
1460 +> A.rewrap ea
::eas,
1468 | _unwrapx
, (Left eb
)::ebs
->
1469 argument ea eb
>>= (fun ea eb
->
1470 arguments_bis
eas ebs
>>= (fun eas ebs
->
1471 return (ea
::eas, Left eb
::ebs
)
1473 | _unwrapx
, (Right y
)::ys
-> raise Impossible
1474 | _unwrapx
, [] -> fail
1478 and argument arga argb
=
1479 X.all_bound
(A.get_inherited arga
) >&&>
1480 match A.unwrap arga
, argb
with
1482 Right
(B.ArgType
{B.p_register
=b
,iib
; p_namei
=sopt
;p_type
=tyb
}) ->
1484 if b
|| sopt
<> None
1486 (* failwith "the argument have a storage and ast_cocci does not have"*)
1489 (* b = false and sopt = None *)
1490 fullType tya tyb
>>= (fun tya tyb
->
1492 (A.TypeExp tya
) +> A.rewrap arga
,
1493 (Right
(B.ArgType
{B.p_register
=(b
,iib
);
1498 | A.TypeExp tya
, _
-> fail
1499 | _
, Right
(B.ArgType _
) -> fail
1501 expression arga argb
>>= (fun arga argb
->
1502 return (arga
, Left argb
)
1504 | _
, Right
(B.ArgAction y
) -> fail
1507 (* ------------------------------------------------------------------------- *)
1508 (* todo? facto code with argument ? *)
1509 and (parameters
: sequence
->
1510 (A.parameterTypeDef list
, Ast_c.parameterType
Ast_c.wrap2 list
)
1512 fun seqstyle eas ebs
->
1514 | Unordered
-> failwith
"not handling ooo"
1516 parameters_bis
eas (Ast_c.split_comma ebs
) >>= (fun eas ebs_splitted
->
1517 return (eas, (Ast_c.unsplit_comma ebs_splitted
))
1521 and parameters_bis
eas ebs
=
1523 | [], [] -> return ([], [])
1524 | [], eb
::ebs
-> fail
1526 (* the management of positions is inlined into each case, because
1527 sometimes there is a Param and sometimes a ParamList *)
1528 X.all_bound
(A.get_inherited ea
) >&&>
1529 (match A.unwrap ea
, ebs
with
1530 | A.Pdots
(mcode), ys
->
1532 (* '...' can take more or less the beginnings of the arguments *)
1533 let startendxs = Common.zip
(Common.inits ys
) (Common.tails ys
) in
1534 startendxs +> List.fold_left
(fun acc
(startxs, endxs
) ->
1539 if mcode_contain_plus (mcodekind mcode)
1541 (* failwith "I have no token that I could accroche myself on"*)
1542 else return (dots2metavar mcode, [])
1544 (match Common.last
startxs with
1547 X.distrf_params
(dots2metavar mcode) startxs
1549 ) >>= (fun mcode startxs ->
1550 let mcode = metavar2dots mcode in
1551 parameters_bis
eas endxs
>>= (fun eas endxs
->
1553 (A.Pdots
(mcode) +> A.rewrap ea
) ::eas,
1559 | A.PComma ia1
, Right ii
::ebs
->
1560 let ib1 = tuple_of_list1 ii
in
1561 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
1562 parameters_bis
eas ebs
>>= (fun eas ebs
->
1564 (A.PComma ia1
+> A.rewrap ea
)::eas,
1569 | A.PComma ia1
, ebs
->
1570 (* try optional comma trick *)
1571 if mcode_contain_plus (mcodekind ia1
)
1573 else parameters_bis
eas ebs
1576 | A.MetaParamList
(ida
,leninfo
,keep
,inherited
),ys
->
1577 let startendxs = Common.zip
(Common.inits ys
) (Common.tails ys
) in
1578 startendxs +> List.fold_left
(fun acc
(startxs, endxs
) ->
1583 if mcode_contain_plus (mcodekind ida
)
1585 (* failwith "I have no token that I could accroche myself on" *)
1588 (match Common.last
startxs with
1596 let startxs'
= Ast_c.unsplit_comma
startxs in
1597 let len = List.length
startxs'
in
1600 Some
(lenname
,lenkeep
,leninherited
) ->
1601 let max_min _
= failwith
"no pos" in
1602 X.envf lenkeep leninherited
1603 (lenname
, Ast_c.MetaListlenVal
(len), max_min)
1604 | None
-> function f
-> f
()
1608 Lib_parsing_c.lin_col_by_pos
1609 (Lib_parsing_c.ii_of_params
startxs) in
1610 X.envf keep inherited
1611 (ida
, Ast_c.MetaParamListVal
startxs'
, max_min)
1614 then return (ida
, [])
1615 else X.distrf_params ida
(Ast_c.split_comma
startxs'
)
1616 ) >>= (fun ida
startxs ->
1617 parameters_bis
eas endxs
>>= (fun eas endxs
->
1619 (A.MetaParamList
(ida
,leninfo
,keep
,inherited
))
1620 +> A.rewrap ea
::eas,
1628 | A.VoidParam ta
, ys
->
1629 (match eas, ebs
with
1631 let {B.p_register
=(hasreg
,iihasreg
);
1633 p_type
=tb
; } = eb
in
1635 if idbopt
=*= None
&& not hasreg
1638 | (qub
, (B.BaseType
B.Void
,_
)) ->
1639 fullType ta tb
>>= (fun ta tb
->
1641 [(A.VoidParam ta
) +> A.rewrap ea
],
1642 [Left
{B.p_register
=(hasreg
, iihasreg
);
1651 | (A.OptParam _
| A.UniqueParam _
), _
->
1652 failwith
"handling Opt/Unique for Param"
1654 | A.Pcircles
(_
), ys
-> raise Impossible
(* in Ordered mode *)
1657 | A.MetaParam
(ida
,keep
,inherited
), (Left eb
)::ebs
->
1658 (* todo: use quaopt, hasreg ? *)
1660 Lib_parsing_c.lin_col_by_pos
(Lib_parsing_c.ii_of_param eb
) in
1661 X.envf keep inherited
(ida
,Ast_c.MetaParamVal eb
,max_min) (fun () ->
1662 X.distrf_param ida eb
1663 ) >>= (fun ida eb
->
1664 parameters_bis
eas ebs
>>= (fun eas ebs
->
1666 (A.MetaParam
(ida
,keep
,inherited
))+> A.rewrap ea
::eas,
1671 | A.Param
(typa
, idaopt
), (Left eb
)::ebs
->
1672 (*this should succeed if the C code has a name, and fail otherwise*)
1673 parameter
(idaopt
, typa
) eb
>>= (fun (idaopt
, typa
) eb
->
1674 parameters_bis
eas ebs
>>= (fun eas ebs
->
1676 (A.Param
(typa
, idaopt
))+> A.rewrap ea
:: eas,
1680 | _unwrapx
, (Right y
)::ys
-> raise Impossible
1681 | _unwrapx
, [] -> fail
1687 let split_register_param = fun (hasreg, idb, ii_b_s) ->
1688 match hasreg, idb, ii_b_s with
1689 | false, Some s, [i1] -> Left (s, [], i1)
1690 | true, Some s, [i1;i2] -> Left (s, [i1], i2)
1691 | _, None, ii -> Right ii
1692 | _ -> raise Impossible
1696 and parameter
= fun (idaopt
, typa
) paramb
->
1698 let {B.p_register
= (hasreg
,iihasreg
);
1699 p_namei
= nameidbopt
;
1700 p_type
= typb
;} = paramb
in
1702 fullType typa typb
>>= (fun typa typb
->
1703 match idaopt
, nameidbopt
with
1704 | Some ida
, Some nameidb
->
1705 (* todo: if minus on ida, should also minus the iihasreg ? *)
1706 ident_cpp DontKnow ida nameidb
>>= (fun ida nameidb
->
1709 {B.p_register
= (hasreg
, iihasreg
);
1710 p_namei
= Some
(nameidb
);
1717 {B.p_register
=(hasreg
,iihasreg
);
1723 (* why handle this case ? because of transform_proto ? we may not
1724 * have an ident in the proto.
1725 * If have some plus on ida ? do nothing about ida ?
1727 (* not anymore !!! now that julia is handling the proto.
1728 | _, Right iihasreg ->
1731 ((hasreg, None, typb), iihasreg)
1735 | Some _
, None
-> fail
1736 | None
, Some _
-> fail
1742 (* ------------------------------------------------------------------------- *)
1743 and (declaration
: (A.mcodekind * bool * A.declaration
,B.declaration
) matcher
) =
1744 fun (mckstart
, allminus
, decla
) declb
->
1745 X.all_bound
(A.get_inherited decla
) >&&>
1746 match A.unwrap decla
, declb
with
1748 (* Un MetaDecl est introduit dans l'asttoctl pour sauter au dessus
1749 * de toutes les declarations qui sont au debut d'un fonction et
1750 * commencer le reste du match au premier statement. Alors, ca matche
1751 * n'importe quelle declaration. On n'a pas besoin d'ajouter
1752 * quoi que ce soit dans l'environnement. C'est une sorte de DDots.
1754 * When the SP want to remove the whole function, the minus is not
1755 * on the MetaDecl but on the MetaRuleElem. So there should
1756 * be no transform of MetaDecl, just matching are allowed.
1759 | A.MetaDecl
(ida
,_keep
,_inherited
), _
-> (* keep ? inherited ? *)
1760 (* todo: should not happen in transform mode *)
1761 return ((mckstart
, allminus
, decla
), declb
)
1765 | _
, (B.DeclList
([var
], iiptvirgb
::iifakestart
::iisto
)) ->
1766 onedecl allminus decla
(var
,iiptvirgb
,iisto
) >>=
1767 (fun decla
(var
,iiptvirgb
,iisto
)->
1768 X.tokenf_mck mckstart iifakestart
>>= (fun mckstart iifakestart
->
1770 (mckstart
, allminus
, decla
),
1771 (B.DeclList
([var
], iiptvirgb
::iifakestart
::iisto
))
1774 | _
, (B.DeclList
(xs
, iiptvirgb
::iifakestart
::iisto
)) ->
1775 if X.mode
=*= PatternMode
1777 xs
+> List.fold_left
(fun acc var
->
1779 X.tokenf_mck mckstart iifakestart
>>= (fun mckstart iifakestart
->
1780 onedecl allminus decla
(var
, iiptvirgb
, iisto
) >>=
1781 (fun decla
(var
, iiptvirgb
, iisto
) ->
1783 (mckstart
, allminus
, decla
),
1784 (B.DeclList
([var
], iiptvirgb
::iifakestart
::iisto
))
1788 failwith
"More that one variable in decl. Have to split to transform."
1790 | A.MacroDecl
(sa
,lpa
,eas,rpa
,enda
), B.MacroDecl
((sb
,ebs
),ii
) ->
1791 let (iisb
, lpb
, rpb
, iiendb
, iifakestart
, iistob
) =
1793 | iisb
::lpb
::rpb
::iiendb
::iifakestart
::iisto
->
1794 (iisb
,lpb
,rpb
,iiendb
, iifakestart
,iisto
)
1795 | _
-> raise Impossible
1798 then minusize_list iistob
1799 else return ((), iistob
)
1800 ) >>= (fun () iistob
->
1802 X.tokenf_mck mckstart iifakestart
>>= (fun mckstart iifakestart
->
1803 ident DontKnow sa
(sb
, iisb
) >>= (fun sa
(sb
, iisb
) ->
1804 tokenf lpa lpb
>>= (fun lpa lpb
->
1805 tokenf rpa rpb
>>= (fun rpa rpb
->
1806 tokenf enda iiendb
>>= (fun enda iiendb
->
1807 arguments
(seqstyle eas) (A.undots
eas) ebs
>>= (fun easundots ebs
->
1808 let eas = redots
eas easundots
in
1811 (mckstart
, allminus
,
1812 (A.MacroDecl
(sa
,lpa
,eas,rpa
,enda
)) +> A.rewrap decla
),
1813 (B.MacroDecl
((sb
,ebs
),
1814 [iisb
;lpb
;rpb
;iiendb
;iifakestart
] ++ iistob
))
1817 | _
, (B.MacroDecl _
|B.DeclList _
) -> fail
1821 and onedecl
= fun allminus decla
(declb
, iiptvirgb
, iistob
) ->
1822 X.all_bound
(A.get_inherited decla
) >&&>
1823 match A.unwrap decla
, declb
with
1825 (* kind of typedef iso, we must unfold, it's for the case
1826 * T { }; that we want to match against typedef struct { } xx_t;
1828 | A.TyDecl
(tya0
, ptvirga
),
1829 ({B.v_namei
= Some
(nameidb
, None
);
1831 B.v_storage
= (B.StoTypedef
, inl
);
1834 B.v_type_bis
= typb0bis
;
1837 (match A.unwrap tya0
, typb0
with
1838 | A.Type
(cv1
,tya1
), ((qu
,il
),typb1
) ->
1840 (match A.unwrap tya1
, typb1
with
1841 | A.StructUnionDef
(tya2
, lba
, declsa
, rba
),
1842 (B.StructUnion
(sub
, sbopt
, declsb
), ii
) ->
1844 let (iisub
, iisbopt
, lbb
, rbb
) =
1847 let (iisub
, lbb
, rbb
) = tuple_of_list3 ii
in
1848 (iisub
, [], lbb
, rbb
)
1851 "warning: both a typedef (%s) and struct name introduction (%s)"
1852 (Ast_c.str_of_name nameidb
) s
1854 pr2 "warning: I will consider only the typedef";
1855 let (iisub
, iisb
, lbb
, rbb
) = tuple_of_list4 ii
in
1856 (iisub
, [iisb
], lbb
, rbb
)
1859 structdef_to_struct_name
1860 (Ast_c.nQ
, (B.StructUnion
(sub
, sbopt
, declsb
), ii
))
1863 Ast_c.nQ
,((B.TypeName
(nameidb
, Some
1864 (Lib_parsing_c.al_type
structnameb))), [])
1867 tokenf ptvirga iiptvirgb
>>= (fun ptvirga iiptvirgb
->
1868 tokenf lba lbb
>>= (fun lba lbb
->
1869 tokenf rba rbb
>>= (fun rba rbb
->
1870 struct_fields
(A.undots declsa
) declsb
>>=(fun undeclsa declsb
->
1871 let declsa = redots
declsa undeclsa
in
1873 (match A.unwrap tya2
with
1874 | A.Type
(cv3
, tya3
) ->
1875 (match A.unwrap tya3
with
1876 | A.MetaType
(ida
,keep
, inherited
) ->
1878 fullType tya2
fake_typeb >>= (fun tya2
fake_typeb ->
1880 A.StructUnionDef
(tya2
,lba
,declsa,rba
)+> A.rewrap
tya1 in
1881 let tya0 = A.Type
(cv1
, tya1) +> A.rewrap
tya0 in
1884 let typb1 = B.StructUnion
(sub
,sbopt
, declsb
),
1885 [iisub
] @ iisbopt
@ [lbb
;rbb
] in
1886 let typb0 = ((qu
, il
), typb1) in
1888 match fake_typeb with
1889 | _nQ
, ((B.TypeName
(nameidb
, _typ
)),[]) ->
1892 (A.TyDecl
(tya0, ptvirga
)) +> A.rewrap decla
,
1893 (({B.v_namei
= Some
(nameidb
, None
);
1895 B.v_storage
= (B.StoTypedef
, inl
);
1898 B.v_type_bis
= typb0bis
;
1900 iivirg
),iiptvirgb
,iistob
)
1902 | _
-> raise Impossible
1905 | A.StructUnionName
(sua
, sa
) ->
1907 fullType tya2
structnameb >>= (fun tya2
structnameb ->
1909 let tya1 = A.StructUnionDef
(tya2
,lba
,declsa,rba
)+> A.rewrap
tya1
1911 let tya0 = A.Type
(cv1
, tya1) +> A.rewrap
tya0 in
1913 match structnameb with
1914 | _nQ
, (B.StructUnionName
(sub
, s), [iisub
;iisbopt
]) ->
1916 let typb1 = B.StructUnion
(sub
,sbopt
, declsb
),
1917 [iisub
;iisbopt
;lbb
;rbb
] in
1918 let typb0 = ((qu
, il
), typb1) in
1921 (A.TyDecl
(tya0, ptvirga
)) +> A.rewrap decla
,
1922 (({B.v_namei
= Some
(nameidb
, None
);
1924 B.v_storage
= (B.StoTypedef
, inl
);
1927 B.v_type_bis
= typb0bis
;
1929 iivirg
),iiptvirgb
,iistob
)
1931 | _
-> raise Impossible
1933 | _
-> raise Impossible
1942 | A.UnInit
(stoa
, typa
, ida
, ptvirga
),
1943 ({B.v_namei
= Some
(nameidb
, _
);B.v_storage
= (B.StoTypedef
,_
);}, iivirg
)
1946 | A.Init
(stoa
, typa
, ida
, eqa
, inia
, ptvirga
),
1947 ({B.v_namei
=Some
(nameidb
, _
);B.v_storage
=(B.StoTypedef
,_
);}, iivirg
)
1952 (* could handle iso here but handled in standard.iso *)
1953 | A.UnInit
(stoa
, typa
, ida
, ptvirga
),
1954 ({B.v_namei
= Some
(nameidb
, None
);
1959 B.v_type_bis
= typbbis
;
1962 tokenf ptvirga iiptvirgb
>>= (fun ptvirga iiptvirgb
->
1963 fullType typa typb
>>= (fun typa typb
->
1964 ident_cpp DontKnow ida nameidb
>>= (fun ida nameidb
->
1965 storage_optional_allminus allminus stoa
(stob
, iistob
) >>=
1966 (fun stoa
(stob
, iistob
) ->
1968 (A.UnInit
(stoa
, typa
, ida
, ptvirga
)) +> A.rewrap decla
,
1969 (({B.v_namei
= Some
(nameidb
, None
);
1974 B.v_type_bis
= typbbis
;
1979 | A.Init
(stoa
, typa
, ida
, eqa
, inia
, ptvirga
),
1980 ({B.v_namei
= Some
(nameidb
, Some
(iieqb
, inib
));
1985 B.v_type_bis
= typbbis
;
1988 tokenf ptvirga iiptvirgb
>>= (fun ptvirga iiptvirgb
->
1989 tokenf eqa iieqb
>>= (fun eqa iieqb
->
1990 fullType typa typb
>>= (fun typa typb
->
1991 ident_cpp DontKnow ida nameidb
>>= (fun ida nameidb
->
1992 storage_optional_allminus allminus stoa
(stob
, iistob
) >>=
1993 (fun stoa
(stob
, iistob
) ->
1994 initialiser inia inib
>>= (fun inia inib
->
1996 (A.Init
(stoa
, typa
, ida
, eqa
, inia
, ptvirga
)) +> A.rewrap decla
,
1997 (({B.v_namei
= Some
(nameidb
, Some
(iieqb
, inib
));
2002 B.v_type_bis
= typbbis
;
2007 (* do iso-by-absence here ? allow typedecl and var ? *)
2008 | A.TyDecl
(typa
, ptvirga
),
2009 ({B.v_namei
= None
; B.v_type
= typb
;
2013 B.v_type_bis
= typbbis
;
2016 if stob
=*= (B.NoSto
, false)
2018 tokenf ptvirga iiptvirgb
>>= (fun ptvirga iiptvirgb
->
2019 fullType typa typb
>>= (fun typa typb
->
2021 (A.TyDecl
(typa
, ptvirga
)) +> A.rewrap decla
,
2022 (({B.v_namei
= None
;
2027 B.v_type_bis
= typbbis
;
2028 }, iivirg
), iiptvirgb
, iistob
)
2033 | A.Typedef
(stoa
, typa
, ida
, ptvirga
),
2034 ({B.v_namei
= Some
(nameidb
, None
);
2036 B.v_storage
= (B.StoTypedef
,inline
);
2039 B.v_type_bis
= typbbis
;
2042 tokenf ptvirga iiptvirgb
>>= (fun ptvirga iiptvirgb
->
2043 fullType typa typb
>>= (fun typa typb
->
2046 tokenf stoa iitypedef
>>= (fun stoa iitypedef
->
2047 return (stoa
, [iitypedef
])
2049 | _
-> failwith
"weird, have both typedef and inline or nothing";
2050 ) >>= (fun stoa iistob
->
2051 (match A.unwrap ida
with
2052 | A.MetaType
(_
,_
,_
) ->
2055 Ast_c.nQ
, ((B.TypeName
(nameidb
, Ast_c.noTypedefDef
())), [])
2057 fullTypebis ida
fake_typeb >>= (fun ida
fake_typeb ->
2058 match fake_typeb with
2059 | _nQ
, ((B.TypeName
(nameidb
, _typ
)), []) ->
2060 return (ida
, nameidb
)
2061 | _
-> raise Impossible
2066 | B.RegularName
(sb
, iidb
) ->
2067 let iidb1 = tuple_of_list1 iidb
in
2071 tokenf sa
iidb1 >>= (fun sa
iidb1 ->
2073 (A.TypeName sa
) +> A.rewrap ida
,
2074 B.RegularName
(sb
, [iidb1])
2078 | B.CppConcatenatedName _
| B.CppVariadicName _
|B.CppIdentBuilder _
2082 | _
-> raise Impossible
2084 ) >>= (fun ida nameidb
->
2086 (A.Typedef
(stoa
, typa
, ida
, ptvirga
)) +> A.rewrap decla
,
2087 (({B.v_namei
= Some
(nameidb
, None
);
2089 B.v_storage
= (B.StoTypedef
,inline
);
2092 B.v_type_bis
= typbbis
;
2100 | _
, ({B.v_namei
= None
;}, _
) ->
2101 (* old: failwith "no variable in this declaration, weird" *)
2106 | A.DisjDecl declas
, declb
->
2107 declas
+> List.fold_left
(fun acc decla
->
2109 (* (declaration (mckstart, allminus, decla) declb) *)
2110 (onedecl allminus decla
(declb
,iiptvirgb
, iistob
))
2115 (* only in struct type decls *)
2116 | A.Ddots
(dots
,whencode
), _
->
2119 | A.OptDecl _
, _
| A.UniqueDecl _
, _
->
2120 failwith
"not handling Opt/Unique Decl"
2122 | _
, ({B.v_namei
=Some _
}, _
) ->
2128 (* ------------------------------------------------------------------------- *)
2130 and (initialiser
: (A.initialiser
, Ast_c.initialiser
) matcher
) = fun ia ib
->
2131 X.all_bound
(A.get_inherited ia
) >&&>
2132 match (A.unwrap ia
,ib
) with
2134 | (A.MetaInit
(ida
,keep
,inherited
), ib
) ->
2136 Lib_parsing_c.lin_col_by_pos
(Lib_parsing_c.ii_of_ini ib
) in
2137 X.envf keep inherited
(ida
, Ast_c.MetaInitVal ib
, max_min)
2139 X.distrf_ini ida ib
>>= (fun ida ib
->
2141 A.MetaInit
(ida
,keep
,inherited
) +> A.rewrap ia
,
2146 | (A.InitExpr expa
, ib
) ->
2147 (match A.unwrap expa
, ib
with
2148 | A.Edots
(mcode, None
), ib
->
2149 X.distrf_ini
(dots2metavar mcode) ib
>>= (fun mcode ib
->
2152 (A.Edots
(metavar2dots mcode, None
) +> A.rewrap expa
)
2157 | A.Edots
(_
, Some expr
), _
-> failwith
"not handling when on Edots"
2159 | _
, (B.InitExpr expb
, ii
) ->
2161 expression expa expb
>>= (fun expa expb
->
2163 (A.InitExpr expa
) +> A.rewrap ia
,
2164 (B.InitExpr expb
, ii
)
2169 | (A.InitList
(ia1
, ias
, ia2
, []), (B.InitList ibs
, ii
)) ->
2171 | ib1::ib2
::iicommaopt
->
2172 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
2173 tokenf ia2 ib2
>>= (fun ia2 ib2
->
2174 initialisers ias
(ibs
, iicommaopt
) >>= (fun ias
(ibs
,iicommaopt
) ->
2176 (A.InitList
(ia1
, ias
, ia2
, [])) +> A.rewrap ia
,
2177 (B.InitList ibs
, ib1::ib2
::iicommaopt
)
2180 | _
-> raise Impossible
2183 | (A.InitList
(i1
, ias
, i2
, whencode
),(B.InitList ibs
, _ii
)) ->
2184 failwith
"TODO: not handling whencode in initialisers"
2187 | (A.InitGccExt
(designatorsa
, ia2
, inia
),
2188 (B.InitDesignators
(designatorsb
, inib
), ii2
))->
2190 let iieq = tuple_of_list1 ii2
in
2192 tokenf ia2
iieq >>= (fun ia2
iieq ->
2193 designators designatorsa designatorsb
>>=
2194 (fun designatorsa designatorsb
->
2195 initialiser inia inib
>>= (fun inia inib
->
2197 (A.InitGccExt
(designatorsa
, ia2
, inia
)) +> A.rewrap ia
,
2198 (B.InitDesignators
(designatorsb
, inib
), [iieq])
2204 | (A.InitGccName
(ida
, ia1
, inia
), (B.InitFieldOld
(idb
, inib
), ii
)) ->
2207 ident DontKnow ida
(idb
, iidb
) >>= (fun ida
(idb
, iidb
) ->
2208 initialiser inia inib
>>= (fun inia inib
->
2209 tokenf ia1 iicolon
>>= (fun ia1 iicolon
->
2211 (A.InitGccName
(ida
, ia1
, inia
)) +> A.rewrap ia
,
2212 (B.InitFieldOld
(idb
, inib
), [iidb
;iicolon
])
2219 | A.IComma
(comma
), _
->
2222 | A.UniqueIni _
,_
| A.OptIni _
,_
->
2223 failwith
"not handling Opt/Unique on initialisers"
2225 | _
, (B.InitIndexOld
(_
, _
), _
) -> fail
2226 | _
, (B.InitFieldOld
(_
, _
), _
) -> fail
2228 | _
, ((B.InitDesignators
(_
, _
)|B.InitList _
|B.InitExpr _
), _
)
2231 and designators dla dlb
=
2232 match (dla
,dlb
) with
2233 ([],[]) -> return ([], [])
2234 | ([],_
) | (_
,[]) -> fail
2235 | (da
::dla
,db
::dlb
) ->
2236 designator da db
>>= (fun da db
->
2237 designators dla dlb
>>= (fun dla dlb
->
2238 return (da
::dla
, db
::dlb
)))
2240 and designator da db
=
2242 (A.DesignatorField
(ia1
, ida
), (B.DesignatorField idb
,ii1
)) ->
2244 let (iidot
, iidb
) = tuple_of_list2 ii1
in
2245 tokenf ia1 iidot
>>= (fun ia1 iidot
->
2246 ident DontKnow ida
(idb
, iidb
) >>= (fun ida
(idb
, iidb
) ->
2248 A.DesignatorField
(ia1
, ida
),
2249 (B.DesignatorField idb
, [iidot
;iidb
])
2252 | (A.DesignatorIndex
(ia1
,ea
,ia2
), (B.DesignatorIndex eb
, ii1
)) ->
2254 let (ib1, ib2
) = tuple_of_list2 ii1
in
2255 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
2256 tokenf ia2 ib2
>>= (fun ia2 ib2
->
2257 expression ea eb
>>= (fun ea eb
->
2259 A.DesignatorIndex
(ia1
,ea
,ia2
),
2260 (B.DesignatorIndex eb
, [ib1;ib2
])
2263 | (A.DesignatorRange
(ia1
,e1a
,ia2
,e2a
,ia3
),
2264 (B.DesignatorRange
(e1b
, e2b
), ii1
)) ->
2266 let (ib1, ib2
, ib3
) = tuple_of_list3 ii1
in
2267 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
2268 tokenf ia2 ib2
>>= (fun ia2 ib2
->
2269 tokenf ia3 ib3
>>= (fun ia3 ib3
->
2270 expression e1a e1b
>>= (fun e1a e1b
->
2271 expression e2a e2b
>>= (fun e2a e2b
->
2273 A.DesignatorRange
(ia1
,e1a
,ia2
,e2a
,ia3
),
2274 (B.DesignatorRange
(e1b
, e2b
), [ib1;ib2
;ib3
])
2276 | (_
, ((B.DesignatorField _
|B.DesignatorIndex _
|B.DesignatorRange _
), _
)) ->
2280 and initialisers
= fun ias
(ibs
, iicomma
) ->
2281 let ias_unsplit = unsplit_icomma ias
in
2282 let ibs_split = resplit_initialiser ibs iicomma
in
2285 if need_unordered_initialisers ibs
2286 then initialisers_unordered2
2287 else initialisers_ordered2
2289 f ias_unsplit ibs_split >>=
2290 (fun ias_unsplit ibs_split ->
2292 split_icomma ias_unsplit,
2293 unsplit_initialiser ibs_split
2297 (* todo: one day julia will reput a IDots *)
2298 and initialisers_ordered2
= fun ias ibs
->
2300 | [], [] -> return ([], [])
2301 | (x
, xcomma
)::xs
, (y
, commay
)::ys
->
2302 (match A.unwrap xcomma
with
2303 | A.IComma commax
->
2304 tokenf commax commay
>>= (fun commax commay
->
2305 initialiser x y
>>= (fun x y
->
2306 initialisers_ordered2 xs ys
>>= (fun xs ys
->
2308 (x
, (A.IComma commax
) +> A.rewrap xcomma
)::xs
,
2312 | _
-> raise Impossible
(* unsplit_iicomma wrong *)
2318 and initialisers_unordered2
= fun ias ibs
->
2321 | [], ys
-> return ([], ys
)
2322 | (x
,xcomma
)::xs
, ys
->
2324 let permut = Common.uncons_permut_lazy ys
in
2325 permut +> List.fold_left
(fun acc
((e
, pos
), rest
) ->
2328 (match A.unwrap xcomma
, e
with
2329 | A.IComma commax
, (y
, commay
) ->
2330 tokenf commax commay
>>= (fun commax commay
->
2331 initialiser x y
>>= (fun x y
->
2333 (x
, (A.IComma commax
) +> A.rewrap xcomma
),
2337 | _
-> raise Impossible
(* unsplit_iicomma wrong *)
2340 let rest = Lazy.force
rest in
2341 initialisers_unordered2 xs
rest >>= (fun xs
rest ->
2344 Common.insert_elem_pos
(e
, pos
) rest
2349 (* ------------------------------------------------------------------------- *)
2350 and (struct_fields
: (A.declaration list
, B.field list
) matcher
) =
2353 | [], [] -> return ([], [])
2354 | [], eb
::ebs
-> fail
2356 X.all_bound
(A.get_inherited ea
) >&&>
2357 (match A.unwrap ea
, ebs
with
2358 | A.Ddots
(mcode, optwhen
), ys
->
2359 if optwhen
<> None
then failwith
"not handling when in argument";
2361 (* '...' can take more or less the beginnings of the arguments *)
2362 let startendxs = Common.zip
(Common.inits ys
) (Common.tails ys
) in
2363 startendxs +> List.fold_left
(fun acc
(startxs, endxs
) ->
2368 if mcode_contain_plus (mcodekind mcode)
2370 (* failwith "I have no token that I could accroche myself on" *)
2371 else return (dots2metavar mcode, [])
2374 X.distrf_struct_fields
(dots2metavar mcode) startxs
2375 ) >>= (fun mcode startxs ->
2376 let mcode = metavar2dots mcode in
2377 struct_fields
eas endxs
>>= (fun eas endxs
->
2379 (A.Ddots
(mcode, optwhen
) +> A.rewrap ea
) ::eas,
2384 | _unwrapx
, eb
::ebs
->
2385 struct_field ea eb
>>= (fun ea eb
->
2386 struct_fields
eas ebs
>>= (fun eas ebs
->
2387 return (ea
::eas, eb
::ebs
)
2390 | _unwrapx
, [] -> fail
2393 and (struct_field
: (A.declaration
, B.field
) matcher
) = fun fa fb
->
2396 | B.DeclarationField
(B.FieldDeclList
(onefield_multivars
,iiptvirg
)) ->
2398 let iiptvirgb = tuple_of_list1 iiptvirg
in
2400 (match onefield_multivars
with
2401 | [] -> raise Impossible
2402 | [onevar
,iivirg
] ->
2403 assert (null iivirg
);
2405 | B.BitField
(sopt
, typb
, _
, expr
) ->
2406 pr2_once
"warning: bitfield not handled by ast_cocci";
2408 | B.Simple
(None
, typb
) ->
2409 pr2_once
"warning: unamed struct field not handled by ast_cocci";
2411 | B.Simple
(Some nameidb
, typb
) ->
2413 (* build a declaration from a struct field *)
2414 let allminus = false in
2416 let stob = B.NoSto
, false in
2418 ({B.v_namei
= Some
(nameidb
, None
);
2421 B.v_local
= Ast_c.NotLocalDecl
;
2422 B.v_attr
= Ast_c.noattr
;
2423 B.v_type_bis
= ref None
;
2424 (* the struct field should also get expanded ? no it's not
2425 * important here, we will rematch very soon *)
2429 onedecl
allminus fa
(fake_var,iiptvirgb,iisto) >>=
2430 (fun fa
(var
,iiptvirgb,iisto) ->
2433 | ({B.v_namei
= Some
(nameidb
, None
);
2438 let onevar = B.Simple
(Some nameidb
, typb
) in
2442 ((B.DeclarationField
2443 (B.FieldDeclList
([onevar, iivirg
], [iiptvirgb])))
2446 | _
-> raise Impossible
2451 pr2_once
"PB: More that one variable in decl. Have to split";
2454 | B.EmptyField _iifield
->
2457 | B.MacroDeclField _
->
2460 | B.CppDirectiveStruct directive
-> fail
2461 | B.IfdefStruct directive
-> fail
2465 (* ------------------------------------------------------------------------- *)
2466 and (fullType
: (A.fullType
, Ast_c.fullType
) matcher
) =
2468 X.optional_qualifier_flag
(fun optional_qualifier
->
2469 X.all_bound
(A.get_inherited typa
) >&&>
2470 match A.unwrap typa
, typb
with
2471 | A.Type
(cv
,ty1
), ((qu
,il
),ty2
) ->
2473 if qu
.B.const
&& qu
.B.volatile
2476 ("warning: the type is both const & volatile but cocci " ^
2477 "does not handle that");
2479 (* Drop out the const/volatile part that has been matched.
2480 * This is because a SP can contain const T v; in which case
2481 * later in match_t_t when we encounter a T, we must not add in
2482 * the environment the whole type.
2487 (* "iso-by-absence" *)
2490 fullTypebis ty1
((qu
,il
), ty2
) >>= (fun ty1 fullty2
->
2492 (A.Type
(None
, ty1
)) +> A.rewrap typa
,
2496 (match optional_qualifier
, qu
.B.const
|| qu
.B.volatile
with
2497 | false, false -> do_stuff ()
2498 | false, true -> fail
2499 | true, false -> do_stuff ()
2502 then pr2_once
"USING optional_qualifier builtin isomorphism";
2508 (* todo: can be __const__ ? can be const & volatile so
2509 * should filter instead ?
2511 (match term x
, il
with
2512 | A.Const
, [i1
] when qu
.B.const
->
2514 tokenf x i1
>>= (fun x i1
->
2515 fullTypebis ty1
(Ast_c.nQ
,ty2
) >>= (fun ty1
(_
, ty2
) ->
2517 (A.Type
(Some x
, ty1
)) +> A.rewrap typa
,
2521 | A.Volatile
, [i1
] when qu
.B.volatile
->
2522 tokenf x i1
>>= (fun x i1
->
2523 fullTypebis ty1
(Ast_c.nQ
,ty2
) >>= (fun ty1
(_
, ty2
) ->
2525 (A.Type
(Some x
, ty1
)) +> A.rewrap typa
,
2533 | A.DisjType typas
, typb
->
2535 List.fold_left
(fun acc typa
-> acc
>|+|> (fullType typa typb
)) fail
2537 | A.OptType
(_
), _
| A.UniqueType
(_
), _
2538 -> failwith
"not handling Opt/Unique on type"
2543 * Why not (A.typeC, Ast_c.typeC) matcher ?
2544 * because when there is MetaType, we want that T record the whole type,
2545 * including the qualifier, and so this type (and the new_il function in
2546 * preceding function).
2549 and (fullTypebis
: (A.typeC
, Ast_c.fullType
) matcher
) =
2551 X.all_bound
(A.get_inherited ta
) >&&>
2552 match A.unwrap ta
, tb
with
2555 | A.MetaType
(ida
,keep
, inherited
), typb
->
2557 Lib_parsing_c.lin_col_by_pos
(Lib_parsing_c.ii_of_type typb
) in
2558 X.envf keep inherited
(ida
, B.MetaTypeVal typb
, max_min) (fun () ->
2559 X.distrf_type ida typb
>>= (fun ida typb
->
2561 A.MetaType
(ida
,keep
, inherited
) +> A.rewrap ta
,
2565 | unwrap
, (qub
, typb
) ->
2566 typeC ta typb
>>= (fun ta typb
->
2567 return (ta
, (qub
, typb
))
2570 and simulate_signed ta basea stringsa signaopt tb baseb ii rebuilda
=
2571 (* In ii there is a list, sometimes of length 1 or 2 or 3.
2572 * And even if in baseb we have a Signed Int, that does not mean
2573 * that ii is of length 2, cos Signed is the default, so if in signa
2574 * we have Signed explicitely ? we cant "accrocher" this mcode to
2575 * something :( So for the moment when there is signed in cocci,
2576 * we force that there is a signed in c too (done in pattern.ml).
2578 let signbopt, iibaseb
= split_signb_baseb_ii (baseb
, ii
) in
2581 (* handle some iso on type ? (cf complex C rule for possible implicit
2583 match basea
, baseb
with
2584 | A.VoidType
, B.Void
2585 | A.FloatType
, B.FloatType
(B.CFloat
)
2586 | A.DoubleType
, B.FloatType
(B.CDouble
) ->
2587 assert (signaopt
=*= None
);
2588 let stringa = tuple_of_list1 stringsa
in
2589 let (ibaseb
) = tuple_of_list1 ii
in
2590 tokenf stringa ibaseb
>>= (fun stringa ibaseb
->
2592 (rebuilda
([stringa], signaopt
)) +> A.rewrap ta
,
2593 (B.BaseType baseb
, [ibaseb
])
2596 | A.CharType
, B.IntType
B.CChar
when signaopt
=*= None
->
2597 let stringa = tuple_of_list1 stringsa
in
2598 let ibaseb = tuple_of_list1 ii
in
2599 tokenf stringa ibaseb >>= (fun stringa ibaseb ->
2601 (rebuilda
([stringa], signaopt
)) +> A.rewrap ta
,
2602 (B.BaseType
(B.IntType
B.CChar
), [ibaseb])
2605 | A.CharType
,B.IntType
(B.Si
(_sign
, B.CChar2
)) when signaopt
<> None
->
2606 let stringa = tuple_of_list1 stringsa
in
2607 let ibaseb = tuple_of_list1 iibaseb
in
2608 sign signaopt
signbopt >>= (fun signaopt iisignbopt
->
2609 tokenf stringa ibaseb >>= (fun stringa ibaseb ->
2611 (rebuilda
([stringa], signaopt
)) +> A.rewrap ta
,
2612 (B.BaseType
(baseb
), iisignbopt
++ [ibaseb])
2615 | A.ShortType
, B.IntType
(B.Si
(_
, B.CShort
))
2616 | A.IntType
, B.IntType
(B.Si
(_
, B.CInt
))
2617 | A.LongType
, B.IntType
(B.Si
(_
, B.CLong
)) ->
2618 let stringa = tuple_of_list1 stringsa
in
2621 (* iso-by-presence ? *)
2622 (* when unsigned int in SP, allow have just unsigned in C ? *)
2623 if mcode_contain_plus (mcodekind stringa)
2627 sign signaopt
signbopt >>= (fun signaopt iisignbopt
->
2629 (rebuilda
([stringa], signaopt
)) +> A.rewrap ta
,
2630 (B.BaseType
(baseb
), iisignbopt
++ [])
2636 "warning: long int or short int not handled by ast_cocci";
2640 sign signaopt
signbopt >>= (fun signaopt iisignbopt
->
2641 tokenf stringa ibaseb >>= (fun stringa ibaseb ->
2643 (rebuilda
([stringa], signaopt
)) +> A.rewrap ta
,
2644 (B.BaseType
(baseb
), iisignbopt
++ [ibaseb])
2646 | _
-> raise Impossible
2651 | A.LongLongType
, B.IntType
(B.Si
(_
, B.CLongLong
)) ->
2652 let (string1a
,string2a
) = tuple_of_list2 stringsa
in
2654 [ibase1b
;ibase2b
] ->
2655 sign signaopt
signbopt >>= (fun signaopt iisignbopt
->
2656 tokenf string1a ibase1b
>>= (fun base1a ibase1b
->
2657 tokenf string2a ibase2b
>>= (fun base2a ibase2b
->
2659 (rebuilda
([base1a
;base2a
], signaopt
)) +> A.rewrap ta
,
2660 (B.BaseType
(baseb
), iisignbopt
++ [ibase1b
;ibase2b
])
2662 | [] -> fail (* should something be done in this case? *)
2663 | _
-> raise Impossible
)
2666 | _
, B.FloatType
B.CLongDouble
2669 "warning: long double not handled by ast_cocci";
2672 | _
, (B.Void
|B.FloatType _
|B.IntType _
) -> fail
2674 and simulate_signed_meta ta basea signaopt tb baseb ii rebuilda
=
2675 (* In ii there is a list, sometimes of length 1 or 2 or 3.
2676 * And even if in baseb we have a Signed Int, that does not mean
2677 * that ii is of length 2, cos Signed is the default, so if in signa
2678 * we have Signed explicitely ? we cant "accrocher" this mcode to
2679 * something :( So for the moment when there is signed in cocci,
2680 * we force that there is a signed in c too (done in pattern.ml).
2682 let signbopt, iibaseb
= split_signb_baseb_ii (baseb
, ii
) in
2684 let match_to_type rebaseb
=
2685 sign signaopt
signbopt >>= (fun signaopt iisignbopt
->
2686 let fta = A.rewrap basea
(A.Type
(None
,basea
)) in
2687 let ftb = Ast_c.nQ
,(B.BaseType
(rebaseb
), iibaseb
) in
2688 fullType
fta ftb >>= (fun fta (_
,tb
) ->
2689 (match A.unwrap
fta,tb
with
2690 A.Type
(_
,basea
), (B.BaseType baseb
, ii
) ->
2692 (rebuilda
(basea
, signaopt
)) +> A.rewrap ta
,
2693 (B.BaseType
(baseb
), iisignbopt
++ ii
)
2695 | _
-> failwith
"not possible"))) in
2697 (* handle some iso on type ? (cf complex C rule for possible implicit
2700 | B.IntType
(B.Si
(_sign
, B.CChar2
)) ->
2701 match_to_type (B.IntType
B.CChar
)
2703 | B.IntType
(B.Si
(_
, ty
)) ->
2705 | [] -> fail (* metavariable has to match something *)
2707 | _
-> match_to_type (B.IntType
(B.Si
(B.Signed
, ty
)))
2711 | (B.Void
|B.FloatType _
|B.IntType _
) -> fail
2713 and (typeC
: (A.typeC
, Ast_c.typeC
) matcher
) =
2715 match A.unwrap ta
, tb
with
2716 | A.BaseType
(basea
,stringsa
), (B.BaseType baseb
, ii
) ->
2717 simulate_signed ta basea stringsa None tb baseb ii
2718 (function (stringsa
, signaopt
) -> A.BaseType
(basea
,stringsa
))
2719 | A.SignedT
(signaopt
, Some basea
), (B.BaseType baseb
, ii
) ->
2720 (match A.unwrap basea
with
2721 A.BaseType
(basea1
,strings1
) ->
2722 simulate_signed ta basea1 strings1
(Some signaopt
) tb baseb ii
2723 (function (strings1
, Some signaopt
) ->
2726 Some
(A.rewrap basea
(A.BaseType
(basea1
,strings1
))))
2727 | _
-> failwith
"not possible")
2728 | A.MetaType
(ida
,keep
,inherited
) ->
2729 simulate_signed_meta ta basea
(Some signaopt
) tb baseb ii
2730 (function (basea
, Some signaopt
) ->
2731 A.SignedT
(signaopt
,Some basea
)
2732 | _
-> failwith
"not possible")
2733 | _
-> failwith
"not possible")
2734 | A.SignedT
(signa
,None
), (B.BaseType baseb
, ii
) ->
2735 let signbopt, iibaseb
= split_signb_baseb_ii (baseb
, ii
) in
2736 (match iibaseb
, baseb
with
2737 | [], B.IntType
(B.Si
(_sign
, B.CInt
)) ->
2738 sign
(Some signa
) signbopt >>= (fun signaopt iisignbopt
->
2740 | None
-> raise Impossible
2743 (A.SignedT
(signa
,None
)) +> A.rewrap ta
,
2744 (B.BaseType baseb
, iisignbopt
)
2752 (* todo? iso with array *)
2753 | A.Pointer
(typa
, iamult
), (B.Pointer typb
, ii
) ->
2754 let (ibmult
) = tuple_of_list1 ii
in
2755 fullType typa typb
>>= (fun typa typb
->
2756 tokenf iamult ibmult
>>= (fun iamult ibmult
->
2758 (A.Pointer
(typa
, iamult
)) +> A.rewrap ta
,
2759 (B.Pointer typb
, [ibmult
])
2762 | A.FunctionType
(allminus,tyaopt
,lpa
,paramsa
,rpa
),
2763 (B.FunctionType
(tyb
, (paramsb
, (isvaargs
, iidotsb
))), ii
) ->
2765 let (lpb
, rpb
) = tuple_of_list2 ii
in
2769 ("Not handling well variable length arguments func. "^
2770 "You have been warned");
2771 tokenf lpa lpb
>>= (fun lpa lpb
->
2772 tokenf rpa rpb
>>= (fun rpa rpb
->
2773 fullType_optional_allminus
allminus tyaopt tyb
>>= (fun tyaopt tyb
->
2774 parameters
(seqstyle paramsa
) (A.undots paramsa
) paramsb
>>=
2775 (fun paramsaundots paramsb
->
2776 let paramsa = redots
paramsa paramsaundots
in
2778 (A.FunctionType
(allminus,tyaopt
,lpa
,paramsa,rpa
) +> A.rewrap ta
,
2779 (B.FunctionType
(tyb
, (paramsb
, (isvaargs
, iidotsb
))), [lpb
;rpb
])
2787 | A.FunctionPointer
(tya
,lp1a
,stara
,rp1a
,lp2a
,paramsa,rp2a
),
2788 (B.ParenType t1
, ii
) ->
2789 let (lp1b
, rp1b
) = tuple_of_list2 ii
in
2790 let (qu1b
, t1b
) = t1
in
2792 | B.Pointer t2
, ii
->
2793 let (starb
) = tuple_of_list1 ii
in
2794 let (qu2b
, t2b
) = t2
in
2796 | B.FunctionType
(tyb
, (paramsb
, (isvaargs
, iidotsb
))), ii
->
2797 let (lp2b
, rp2b
) = tuple_of_list2 ii
in
2802 ("Not handling well variable length arguments func. "^
2803 "You have been warned");
2805 fullType tya tyb
>>= (fun tya tyb
->
2806 tokenf lp1a lp1b
>>= (fun lp1a lp1b
->
2807 tokenf rp1a rp1b
>>= (fun rp1a rp1b
->
2808 tokenf lp2a lp2b
>>= (fun lp2a lp2b
->
2809 tokenf rp2a rp2b
>>= (fun rp2a rp2b
->
2810 tokenf stara starb
>>= (fun stara starb
->
2811 parameters
(seqstyle paramsa) (A.undots
paramsa) paramsb
>>=
2812 (fun paramsaundots paramsb
->
2813 let paramsa = redots
paramsa paramsaundots
in
2817 (B.FunctionType
(tyb
, (paramsb
, (isvaargs
, iidotsb
))),
2822 (B.Pointer
t2, [starb
]))
2826 (A.FunctionPointer
(tya
,lp1a
,stara
,rp1a
,lp2a
,paramsa,rp2a
))
2828 (B.ParenType
t1, [lp1b
;rp1b
])
2841 (* todo: handle the iso on optionnal size specifification ? *)
2842 | A.Array
(typa
, ia1
, eaopt
, ia2
), (B.Array
(ebopt
, typb
), ii
) ->
2843 let (ib1, ib2
) = tuple_of_list2 ii
in
2844 fullType typa typb
>>= (fun typa typb
->
2845 option expression eaopt ebopt
>>= (fun eaopt ebopt
->
2846 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
2847 tokenf ia2 ib2
>>= (fun ia2 ib2
->
2849 (A.Array
(typa
, ia1
, eaopt
, ia2
)) +> A.rewrap ta
,
2850 (B.Array
(ebopt
, typb
), [ib1;ib2
])
2854 (* todo: could also match a Struct that has provided a name *)
2855 (* This is for the case where the SmPL code contains "struct x", without
2856 a definition. In this case, the name field is always present.
2857 This case is also called from the case for A.StructUnionDef when
2858 a name is present in the C code. *)
2859 | A.StructUnionName
(sua
, Some sa
), (B.StructUnionName
(sub
, sb
), ii
) ->
2860 (* sa is now an ident, not an mcode, old: ... && (term sa) =$= sb *)
2861 let (ib1, ib2
) = tuple_of_list2 ii
in
2862 if equal_structUnion (term sua
) sub
2864 ident DontKnow sa
(sb
, ib2
) >>= (fun sa
(sb
, ib2
) ->
2865 tokenf sua
ib1 >>= (fun sua
ib1 ->
2867 (A.StructUnionName
(sua
, Some sa
)) +> A.rewrap ta
,
2868 (B.StructUnionName
(sub
, sb
), [ib1;ib2
])
2873 | A.StructUnionDef
(ty
, lba
, declsa, rba
),
2874 (B.StructUnion
(sub
, sbopt
, declsb
), ii
) ->
2876 let (ii_sub_sb
, lbb
, rbb
) =
2878 [iisub
; lbb
; rbb
] -> (Common.Left iisub
,lbb
,rbb
)
2879 | [iisub
; iisb
; lbb
; rbb
] -> (Common.Right
(iisub
,iisb
),lbb
,rbb
)
2880 | _
-> failwith
"list of length 3 or 4 expected" in
2883 match (sbopt
,ii_sub_sb
) with
2884 (None
,Common.Left iisub
) ->
2885 (* the following doesn't reconstruct the complete SP code, just
2886 the part that matched *)
2888 match A.unwrap
s with
2890 (match A.unwrap ty
with
2891 A.StructUnionName
(sua
, None
) ->
2892 tokenf sua iisub
>>= (fun sua iisub
->
2895 A.StructUnionName
(sua
, None
) +> A.rewrap
ty)
2897 return (ty,[iisub
]))
2899 | A.DisjType
(disjs
) ->
2901 List.fold_left
(fun acc disj
-> acc
>|+|> (loop disj
)) fail
2905 | (Some sb
,Common.Right
(iisub
,iisb
)) ->
2907 (* build a StructUnionName from a StructUnion *)
2908 let fake_su = B.nQ
, (B.StructUnionName
(sub
, sb
), [iisub
;iisb
]) in
2910 fullType
ty fake_su >>= (fun ty fake_su ->
2912 | _nQ
, (B.StructUnionName
(sub
, sb
), [iisub
;iisb
]) ->
2913 return (ty, [iisub
; iisb
])
2914 | _
-> raise Impossible
)
2918 >>= (fun ty ii_sub_sb
->
2920 tokenf lba lbb
>>= (fun lba lbb
->
2921 tokenf rba rbb
>>= (fun rba rbb
->
2922 struct_fields
(A.undots
declsa) declsb
>>=(fun undeclsa declsb
->
2923 let declsa = redots
declsa undeclsa
in
2926 (A.StructUnionDef
(ty, lba
, declsa, rba
)) +> A.rewrap ta
,
2927 (B.StructUnion
(sub
, sbopt
, declsb
),ii_sub_sb
@[lbb
;rbb
])
2931 (* todo? handle isomorphisms ? because Unsigned Int can be match on a
2932 * uint in the C code. But some CEs consists in renaming some types,
2933 * so we don't want apply isomorphisms every time.
2935 | A.TypeName sa
, (B.TypeName
(nameb
, typb
), noii
) ->
2939 | B.RegularName
(sb
, iidb
) ->
2940 let iidb1 = tuple_of_list1 iidb
in
2944 tokenf sa
iidb1 >>= (fun sa
iidb1 ->
2946 (A.TypeName sa
) +> A.rewrap ta
,
2947 (B.TypeName
(B.RegularName
(sb
, [iidb1]), typb
), noii
)
2951 | B.CppConcatenatedName _
| B.CppVariadicName _
|B.CppIdentBuilder _
2956 | _
, (B.TypeOfExpr e
, ii
) -> fail
2957 | _
, (B.TypeOfType e
, ii
) -> fail
2959 | _
, (B.ParenType e
, ii
) -> fail (* todo ?*)
2960 | A.EnumName
(en
,namea
), (B.EnumName nameb
, ii
) ->
2961 let (ib1,ib2
) = tuple_of_list2 ii
in
2962 ident DontKnow namea
(nameb
, ib2
) >>= (fun namea
(nameb
, ib2
) ->
2963 tokenf en
ib1 >>= (fun en
ib1 ->
2965 (A.EnumName
(en
, namea
)) +> A.rewrap ta
,
2966 (B.EnumName nameb
, [ib1;ib2
])
2969 | _
, (B.Enum _
, _
) -> fail (* todo cocci ?*)
2972 ((B.TypeName _
| B.StructUnionName
(_
, _
) | B.EnumName _
|
2973 B.StructUnion
(_
, _
, _
) |
2974 B.FunctionType _
| B.Array
(_
, _
) | B.Pointer _
|
2980 (* todo: iso on sign, if not mentioned then free. tochange?
2981 * but that require to know if signed int because explicit
2982 * signed int, or because implicit signed int.
2985 and sign signa signb
=
2986 match signa
, signb
with
2987 | None
, None
-> return (None
, [])
2988 | Some signa
, Some
(signb
, ib
) ->
2989 if equal_sign (term signa
) signb
2990 then tokenf signa ib
>>= (fun signa ib
->
2991 return (Some signa
, [ib
])
2997 and minusize_list iixs
=
2998 iixs
+> List.fold_left
(fun acc ii
->
2999 acc
>>= (fun xs ys
->
3000 tokenf minusizer ii
>>= (fun minus ii
->
3001 return (minus
::xs
, ii
::ys
)
3002 ))) (return ([],[]))
3003 >>= (fun _xsminys ys
->
3004 return ((), List.rev ys
)
3007 and storage_optional_allminus
allminus stoa
(stob, iistob
) =
3008 (* "iso-by-absence" for storage, and return type. *)
3009 X.optional_storage_flag
(fun optional_storage
->
3010 match stoa
, stob with
3011 | None
, (stobis
, inline
) ->
3015 minusize_list iistob
>>= (fun () iistob
->
3016 return (None
, (stob, iistob
))
3018 else return (None
, (stob, iistob
))
3021 (match optional_storage
, stobis
with
3022 | false, B.NoSto
-> do_minus ()
3024 | true, B.NoSto
-> do_minus ()
3027 then pr2_once
"USING optional_storage builtin isomorphism";
3031 | Some x
, ((stobis
, inline
)) ->
3032 if equal_storage (term x
) stobis
3036 tokenf x i1
>>= (fun x i1
->
3037 return (Some x
, ((stobis
, inline
), [i1
]))
3039 (* or if have inline ? have to do a split_storage_inline a la
3040 * split_signb_baseb_ii *)
3041 | _
-> raise Impossible
3049 and fullType_optional_allminus
allminus tya retb
=
3054 X.distrf_type
minusizer retb
>>= (fun _x retb
->
3058 else return (None
, retb
)
3060 fullType tya retb
>>= (fun tya retb
->
3061 return (Some tya
, retb
)
3066 (*---------------------------------------------------------------------------*)
3068 and compatible_base_type a signa b
=
3069 let ok = return ((),()) in
3072 | Type_cocci.VoidType
, B.Void
->
3073 assert (signa
=*= None
);
3075 | Type_cocci.CharType
, B.IntType
B.CChar
when signa
=*= None
->
3077 | Type_cocci.CharType
, B.IntType
(B.Si
(signb
, B.CChar2
)) ->
3078 compatible_sign signa signb
3079 | Type_cocci.ShortType
, B.IntType
(B.Si
(signb
, B.CShort
)) ->
3080 compatible_sign signa signb
3081 | Type_cocci.IntType
, B.IntType
(B.Si
(signb
, B.CInt
)) ->
3082 compatible_sign signa signb
3083 | Type_cocci.LongType
, B.IntType
(B.Si
(signb
, B.CLong
)) ->
3084 compatible_sign signa signb
3085 | _
, B.IntType
(B.Si
(signb
, B.CLongLong
)) ->
3086 pr2_once
"no longlong in cocci";
3088 | Type_cocci.FloatType
, B.FloatType
B.CFloat
->
3089 assert (signa
=*= None
);
3091 | Type_cocci.DoubleType
, B.FloatType
B.CDouble
->
3092 assert (signa
=*= None
);
3094 | _
, B.FloatType
B.CLongDouble
->
3095 pr2_once
"no longdouble in cocci";
3097 | Type_cocci.BoolType
, _
-> failwith
"no booltype in C"
3099 | _
, (B.Void
|B.FloatType _
|B.IntType _
) -> fail
3101 and compatible_base_type_meta a signa qua b ii
local =
3103 | Type_cocci.MetaType
(ida
,keep
,inherited
),
3104 B.IntType
(B.Si
(signb
, B.CChar2
)) ->
3105 compatible_sign signa signb
>>= fun _ _
->
3106 let newb = ((qua
, (B.BaseType
(B.IntType
B.CChar
),ii
)),local) in
3107 compatible_type a
newb
3108 | Type_cocci.MetaType
(ida
,keep
,inherited
), B.IntType
(B.Si
(signb
, ty)) ->
3109 compatible_sign signa signb
>>= fun _ _
->
3111 ((qua
, (B.BaseType
(B.IntType
(B.Si
(B.Signed
, ty))),ii
)),local) in
3112 compatible_type a
newb
3113 | _
, B.FloatType
B.CLongDouble
->
3114 pr2_once
"no longdouble in cocci";
3117 | _
, (B.Void
|B.FloatType _
|B.IntType _
) -> fail
3120 and compatible_type a
(b
,local) =
3121 let ok = return ((),()) in
3123 let rec loop = function
3124 | Type_cocci.BaseType a
, (qua
, (B.BaseType b
,ii
)) ->
3125 compatible_base_type a None b
3127 | Type_cocci.SignedT
(signa
,None
), (qua
, (B.BaseType b
,ii
)) ->
3128 compatible_base_type
Type_cocci.IntType
(Some signa
) b
3130 | Type_cocci.SignedT
(signa
,Some
ty), (qua
, (B.BaseType b
,ii
)) ->
3132 Type_cocci.BaseType
ty ->
3133 compatible_base_type
ty (Some signa
) b
3134 | Type_cocci.MetaType
(ida
,keep
,inherited
) ->
3135 compatible_base_type_meta
ty (Some signa
) qua b ii
local
3136 | _
-> failwith
"not possible")
3138 | Type_cocci.Pointer a
, (qub
, (B.Pointer b
, ii
)) ->
3140 | Type_cocci.FunctionPointer a
, _
->
3142 "TODO: function pointer type doesn't store enough information to determine compatability"
3143 | Type_cocci.Array a
, (qub
, (B.Array
(eopt
, b
),ii
)) ->
3144 (* no size info for cocci *)
3146 | Type_cocci.StructUnionName
(sua
, _
, sa
),
3147 (qub
, (B.StructUnionName
(sub
, sb
),ii
)) ->
3148 if equal_structUnion_type_cocci sua sub
&& sa
=$
= sb
3151 | Type_cocci.EnumName
(_
, sa
),
3152 (qub
, (B.EnumName
(sb
),ii
)) ->
3156 | Type_cocci.TypeName sa
, (qub
, (B.TypeName
(namesb
, _typb
),noii
)) ->
3157 let sb = Ast_c.str_of_name namesb
in
3162 | Type_cocci.ConstVol
(qua
, a
), (qub
, b
) ->
3163 if (fst qub
).B.const
&& (fst qub
).B.volatile
3166 pr2_once
("warning: the type is both const & volatile but cocci " ^
3167 "does not handle that");
3173 | Type_cocci.Const
-> (fst qub
).B.const
3174 | Type_cocci.Volatile
-> (fst qub
).B.volatile
3176 then loop (a
,(Ast_c.nQ
, b
))
3179 | Type_cocci.MetaType
(ida
,keep
,inherited
), typb
->
3181 Lib_parsing_c.lin_col_by_pos
(Lib_parsing_c.ii_of_type typb
) in
3182 X.envf keep inherited
(A.make_mcode ida
, B.MetaTypeVal typb
, max_min)
3186 (* subtil: must be after the MetaType case *)
3187 | a
, (qub
, (B.TypeName
(_namesb
, Some b
), noii
)) ->
3188 (* kind of typedef iso *)
3195 (* for metavariables of type expression *^* *)
3196 | Type_cocci.Unknown
, _
-> ok
3201 B.TypeOfType _
|B.TypeOfExpr _
|B.ParenType _
|
3202 B.EnumName _
|B.StructUnion
(_
, _
, _
)|B.Enum
(_
, _
)
3209 B.StructUnionName
(_
, _
)|
3211 B.Array
(_
, _
)|B.Pointer _
|B.TypeName _
|
3220 and compatible_sign signa signb
=
3221 let ok = return ((),()) in
3222 match signa
, signb
with
3224 | Some
Type_cocci.Signed
, B.Signed
3225 | Some
Type_cocci.Unsigned
, B.UnSigned
3230 and equal_structUnion_type_cocci a b
=
3232 | Type_cocci.Struct
, B.Struct
-> true
3233 | Type_cocci.Union
, B.Union
-> true
3234 | _
, (B.Struct
| B.Union
) -> false
3238 (*---------------------------------------------------------------------------*)
3239 and inc_file
(a
, before_after
) (b
, h_rel_pos
) =
3241 let rec aux_inc (ass
, bss
) passed
=
3245 let passed = List.rev
passed in
3247 (match before_after
, !h_rel_pos
with
3248 | IncludeNothing
, _
-> true
3249 | IncludeMcodeBefore
, Some x
->
3250 List.mem
passed (x
.Ast_c.first_of
)
3252 | IncludeMcodeAfter
, Some x
->
3253 List.mem
passed (x
.Ast_c.last_of
)
3255 (* no info, maybe cos of a #include <xx.h> that was already in a .h *)
3259 | (A.IncPath x
)::xs
, y
::ys
-> x
=$
= y
&& aux_inc (xs
, ys
) (x
::passed)
3260 | _
-> failwith
"IncDots not in last place or other pb"
3265 | A.Local ass
, B.Local bss
->
3266 aux_inc (ass
, bss
) []
3267 | A.NonLocal ass
, B.NonLocal bss
->
3268 aux_inc (ass
, bss
) []
3273 (*---------------------------------------------------------------------------*)
3275 and (define_params
: sequence
->
3276 (A.define_param list
, (string B.wrap
) B.wrap2 list
) matcher
) =
3277 fun seqstyle eas ebs
->
3279 | Unordered
-> failwith
"not handling ooo"
3281 define_paramsbis
eas (Ast_c.split_comma ebs
) >>= (fun eas ebs_splitted
->
3282 return (eas, (Ast_c.unsplit_comma ebs_splitted
))
3285 (* todo? facto code with argument and parameters ? *)
3286 and define_paramsbis
= fun eas ebs
->
3288 | [], [] -> return ([], [])
3289 | [], eb
::ebs
-> fail
3291 X.all_bound
(A.get_inherited ea
) >&&>
3292 (match A.unwrap ea
, ebs
with
3293 | A.DPdots
(mcode), ys
->
3295 (* '...' can take more or less the beginnings of the arguments *)
3296 let startendxs = Common.zip
(Common.inits ys
) (Common.tails ys
) in
3297 startendxs +> List.fold_left
(fun acc
(startxs, endxs
) ->
3302 if mcode_contain_plus (mcodekind mcode)
3304 (* failwith "I have no token that I could accroche myself on" *)
3305 else return (dots2metavar mcode, [])
3307 (match Common.last
startxs with
3310 X.distrf_define_params
(dots2metavar mcode) startxs
3312 ) >>= (fun mcode startxs ->
3313 let mcode = metavar2dots mcode in
3314 define_paramsbis
eas endxs
>>= (fun eas endxs
->
3316 (A.DPdots
(mcode) +> A.rewrap ea
) ::eas,
3322 | A.DPComma ia1
, Right ii
::ebs
->
3323 let ib1 = tuple_of_list1 ii
in
3324 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
3325 define_paramsbis
eas ebs
>>= (fun eas ebs
->
3327 (A.DPComma ia1
+> A.rewrap ea
)::eas,
3332 | A.DPComma ia1
, ebs
->
3333 if mcode_contain_plus (mcodekind ia1
)
3336 (define_paramsbis
eas ebs
) (* try optional comma trick *)
3338 | (A.OptDParam _
| A.UniqueDParam _
), _
->
3339 failwith
"handling Opt/Unique for define parameters"
3341 | A.DPcircles
(_
), ys
-> raise Impossible
(* in Ordered mode *)
3343 | A.DParam ida
, (Left
(idb
, ii
))::ebs
->
3344 let ib1 = tuple_of_list1 ii
in
3345 ident DontKnow ida
(idb
, ib1) >>= (fun ida
(idb
, ib1) ->
3346 define_paramsbis
eas ebs
>>= (fun eas ebs
->
3348 (A.DParam ida
)+> A.rewrap ea
:: eas,
3349 (Left
(idb
, [ib1]))::ebs
3352 | _unwrapx
, (Right y
)::ys
-> raise Impossible
3353 | _unwrapx
, [] -> fail
3358 (*****************************************************************************)
3360 (*****************************************************************************)
3362 (* no global solution for positions here, because for a statement metavariable
3363 we want a MetaStmtVal, and for the others, it's not clear what we want *)
3365 let rec (rule_elem_node
: (A.rule_elem
, Control_flow_c.node
) matcher
) =
3368 x
>>= (fun a b
-> return (A.rewrap re a
, F.rewrap node b
))
3370 X.all_bound
(A.get_inherited re
) >&&>
3373 match A.unwrap re
, F.unwrap node
with
3375 (* note: the order of the clauses is important. *)
3377 | _
, F.Enter
| _
, F.Exit
| _
, F.ErrorExit
-> fail2()
3379 (* the metaRuleElem contains just '-' information. We dont need to add
3380 * stuff in the environment. If we need stuff in environment, because
3381 * there is a + S somewhere, then this will be done via MetaStmt, not
3383 * Can match TrueNode/FalseNode/... so must be placed before those cases.
3386 | A.MetaRuleElem
(mcode,keep
,inherited
), unwrap_node
->
3387 let default = A.MetaRuleElem
(mcode,keep
,inherited
), unwrap_node
in
3388 (match unwrap_node
with
3390 | F.TrueNode
| F.FalseNode
| F.AfterNode
3391 | F.LoopFallThroughNode
| F.FallThroughNode
3393 if X.mode
=*= PatternMode
3396 if mcode_contain_plus (mcodekind mcode)
3397 then failwith
"try add stuff on fake node"
3398 (* minusize or contextize a fake node is ok *)
3401 | F.EndStatement None
->
3402 if X.mode
=*= PatternMode
then return default
3404 (* DEAD CODE NOW ? only useful in -no_cocci_vs_c_3 ?
3405 if mcode_contain_plus (mcodekind mcode)
3407 let fake_info = Ast_c.fakeInfo() in
3408 distrf distrf_node (mcodekind mcode)
3409 (F.EndStatement (Some fake_info))
3410 else return unwrap_node
3414 | F.EndStatement
(Some i1
) ->
3415 tokenf mcode i1
>>= (fun mcode i1
->
3417 A.MetaRuleElem
(mcode,keep
, inherited
),
3418 F.EndStatement
(Some i1
)
3422 if X.mode
=*= PatternMode
then return default
3423 else failwith
"a MetaRuleElem can't transform a headfunc"
3425 if X.mode
=*= PatternMode
then return default
3427 X.distrf_node
(generalize_mcode mcode) node
>>= (fun mcode node
->
3429 A.MetaRuleElem
(mcode,keep
, inherited
),
3435 (* rene cant have found that a state containing a fake/exit/... should be
3437 * TODO: and F.Fake ?
3439 | _
, F.EndStatement _
| _
, F.CaseNode _
3440 | _
, F.TrueNode
| _
, F.FalseNode
| _
, F.AfterNode
3441 | _
, F.FallThroughNode
| _
, F.LoopFallThroughNode
3445 (* really ? diff between pattern.ml and transformation.ml *)
3446 | _
, F.Fake
-> fail2()
3449 (* cas general: a Meta can match everything. It matches only
3450 * "header"-statement. We transform only MetaRuleElem, not MetaStmt.
3451 * So can't have been called in transform.
3453 | A.MetaStmt
(ida
,keep
,metainfoMaybeTodo
,inherited
), F.Decl
(_
) -> fail
3455 | A.MetaStmt
(ida
,keep
,metainfoMaybeTodo
,inherited
), unwrap_node
->
3456 (* todo: should not happen in transform mode *)
3458 (match Control_flow_c.extract_fullstatement node
with
3461 Lib_parsing_c.lin_col_by_pos
(Lib_parsing_c.ii_of_stmt stb
) in
3462 X.envf keep inherited
(ida
, Ast_c.MetaStmtVal stb
, max_min)
3464 (* no need tag ida, we can't be called in transform-mode *)
3466 A.MetaStmt
(ida
, keep
, metainfoMaybeTodo
, inherited
),
3474 | A.MetaStmtList _
, _
->
3475 failwith
"not handling MetaStmtList"
3477 | A.TopExp ea
, F.DefineExpr eb
->
3478 expression ea eb
>>= (fun ea eb
->
3484 | A.TopExp ea
, F.DefineType eb
->
3485 (match A.unwrap ea
with
3487 fullType ft eb
>>= (fun ft eb
->
3489 A.TopExp
(A.rewrap ea
(A.TypeExp
(ft
))),
3496 (* It is important to put this case before the one that fails because
3497 * of the lack of the counter part of a C construct in SmPL (for instance
3498 * there is not yet a CaseRange in SmPL). Even if SmPL don't handle
3499 * yet certain constructs, those constructs may contain expression
3500 * that we still want and can transform.
3503 | A.Exp exp
, nodeb
->
3505 (* kind of iso, initialisation vs affectation *)
3507 match A.unwrap exp
, nodeb
with
3508 | A.Assignment
(ea
, op
, eb
, true), F.Decl decl
->
3509 initialisation_to_affectation decl
+> F.rewrap node
3514 (* Now keep fullstatement inside the control flow node,
3515 * so that can then get in a MetaStmtVar the fullstatement to later
3516 * pp back when the S is in a +. But that means that
3517 * Exp will match an Ifnode even if there is no such exp
3518 * inside the condition of the Ifnode (because the exp may
3519 * be deeper, in the then branch). So have to not visit
3520 * all inside a node anymore.
3522 * update: j'ai choisi d'accrocher au noeud du CFG Ã la
3523 * fois le fullstatement et le partialstatement et appeler le
3524 * visiteur que sur le partialstatement.
3527 match Ast_cocci.get_pos re
with
3528 | None
-> expression
3532 Lib_parsing_c.max_min_by_pos
(Lib_parsing_c.ii_of_expr eb
) in
3533 let keep = Type_cocci.Unitary
in
3534 let inherited = false in
3535 let max_min _
= failwith
"no pos" in
3536 X.envf
keep inherited (pos
, B.MetaPosVal
(min
,max
), max_min)
3542 X.cocciExp
expfn exp
node >>= (fun exp
node ->
3550 X.cocciTy fullType
ty node >>= (fun ty node ->
3557 | A.TopInit init
, nodeb
->
3558 X.cocciInit initialiser init
node >>= (fun init
node ->
3566 | A.FunHeader
(mckstart
, allminus, fninfoa
, ida
, oparen
, paramsa, cparen
),
3567 F.FunHeader
({B.f_name
= nameidb
;
3568 f_type
= (retb
, (paramsb
, (isvaargs
, iidotsb
)));
3572 f_old_c_style
= oldstyle
;
3577 then pr2 "OLD STYLE DECL NOT WELL SUPPORTED";
3580 (* fninfoa records the order in which the SP specified the various
3581 information, but this isn't taken into account in the matching.
3582 Could this be a problem for transformation? *)
3585 List.filter
(function A.FStorage
(s) -> true | _
-> false) fninfoa
3586 with [A.FStorage
(s)] -> Some
s | _
-> None
in
3588 match List.filter
(function A.FType
(s) -> true | _
-> false) fninfoa
3589 with [A.FType
(t
)] -> Some t
| _
-> None
in
3591 (match List.filter
(function A.FInline
(i
) -> true | _
-> false) fninfoa
3592 with [A.FInline
(i
)] -> failwith
"not checking inline" | _
-> ());
3594 (match List.filter
(function A.FAttr
(a
) -> true | _
-> false) fninfoa
3595 with [A.FAttr
(a
)] -> failwith
"not checking attributes" | _
-> ());
3598 | ioparenb
::icparenb
::iifakestart
::iistob
->
3600 (* maybe important to put ident as the first tokens to transform.
3601 * It's related to transform_proto. So don't change order
3604 ident_cpp LocalFunction ida nameidb
>>= (fun ida nameidb
->
3605 X.tokenf_mck mckstart iifakestart
>>= (fun mckstart iifakestart
->
3606 tokenf oparen ioparenb
>>= (fun oparen ioparenb
->
3607 tokenf cparen icparenb
>>= (fun cparen icparenb
->
3608 parameters
(seqstyle paramsa)
3609 (A.undots
paramsa) paramsb
>>=
3610 (fun paramsaundots paramsb
->
3611 let paramsa = redots
paramsa paramsaundots
in
3612 storage_optional_allminus
allminus
3613 stoa (stob, iistob
) >>= (fun stoa (stob, iistob
) ->
3618 ("Not handling well variable length arguments func. "^
3619 "You have been warned");
3621 then minusize_list iidotsb
3622 else return ((),iidotsb
)
3623 ) >>= (fun () iidotsb
->
3625 fullType_optional_allminus
allminus tya retb
>>= (fun tya retb
->
3628 (match stoa with Some st
-> [A.FStorage st
] | None
-> []) ++
3629 (match tya with Some t
-> [A.FType t
] | None
-> [])
3634 A.FunHeader
(mckstart
,allminus,fninfoa,ida
,oparen
,
3636 F.FunHeader
({B.f_name
= nameidb
;
3637 f_type
= (retb
, (paramsb
, (isvaargs
, iidotsb
)));
3641 f_old_c_style
= oldstyle
; (* TODO *)
3643 ioparenb
::icparenb
::iifakestart
::iistob
)
3646 | _
-> raise Impossible
3654 | A.Decl
(mckstart
,allminus,decla
), F.Decl declb
->
3655 declaration
(mckstart
,allminus,decla
) declb
>>=
3656 (fun (mckstart
,allminus,decla
) declb
->
3658 A.Decl
(mckstart
,allminus,decla
),
3663 | A.SeqStart
mcode, F.SeqStart
(st
, level
, i1
) ->
3664 tokenf mcode i1
>>= (fun mcode i1
->
3667 F.SeqStart
(st
, level
, i1
)
3670 | A.SeqEnd
mcode, F.SeqEnd
(level
, i1
) ->
3671 tokenf mcode i1
>>= (fun mcode i1
->
3674 F.SeqEnd
(level
, i1
)
3677 | A.ExprStatement
(ea
, ia1
), F.ExprStatement
(st
, (Some eb
, ii
)) ->
3678 let ib1 = tuple_of_list1 ii
in
3679 expression ea eb
>>= (fun ea eb
->
3680 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
3682 A.ExprStatement
(ea
, ia1
),
3683 F.ExprStatement
(st
, (Some eb
, [ib1]))
3688 | A.IfHeader
(ia1
,ia2
, ea
, ia3
), F.IfHeader
(st
, (eb
,ii
)) ->
3689 let (ib1, ib2
, ib3
) = tuple_of_list3 ii
in
3690 expression ea eb
>>= (fun ea eb
->
3691 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
3692 tokenf ia2 ib2
>>= (fun ia2 ib2
->
3693 tokenf ia3 ib3
>>= (fun ia3 ib3
->
3695 A.IfHeader
(ia1
, ia2
, ea
, ia3
),
3696 F.IfHeader
(st
, (eb
,[ib1;ib2
;ib3
]))
3699 | A.Else ia
, F.Else ib
->
3700 tokenf ia ib
>>= (fun ia ib
->
3701 return (A.Else ia
, F.Else ib
)
3704 | A.WhileHeader
(ia1
, ia2
, ea
, ia3
), F.WhileHeader
(st
, (eb
, ii
)) ->
3705 let (ib1, ib2
, ib3
) = tuple_of_list3 ii
in
3706 expression ea eb
>>= (fun ea eb
->
3707 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
3708 tokenf ia2 ib2
>>= (fun ia2 ib2
->
3709 tokenf ia3 ib3
>>= (fun ia3 ib3
->
3711 A.WhileHeader
(ia1
, ia2
, ea
, ia3
),
3712 F.WhileHeader
(st
, (eb
, [ib1;ib2
;ib3
]))
3715 | A.DoHeader ia
, F.DoHeader
(st
, ib
) ->
3716 tokenf ia ib
>>= (fun ia ib
->
3721 | A.WhileTail
(ia1
,ia2
,ea
,ia3
,ia4
), F.DoWhileTail
(eb
, ii
) ->
3722 let (ib1, ib2
, ib3
, ib4
) = tuple_of_list4 ii
in
3723 expression ea eb
>>= (fun ea eb
->
3724 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
3725 tokenf ia2 ib2
>>= (fun ia2 ib2
->
3726 tokenf ia3 ib3
>>= (fun ia3 ib3
->
3727 tokenf ia4 ib4
>>= (fun ia4 ib4
->
3729 A.WhileTail
(ia1
,ia2
,ea
,ia3
,ia4
),
3730 F.DoWhileTail
(eb
, [ib1;ib2
;ib3
;ib4
])
3732 | A.IteratorHeader
(ia1
, ia2
, eas, ia3
), F.MacroIterHeader
(st
, ((s,ebs
),ii
))
3734 let (ib1, ib2
, ib3
) = tuple_of_list3 ii
in
3736 ident DontKnow ia1
(s, ib1) >>= (fun ia1
(s, ib1) ->
3737 tokenf ia2 ib2
>>= (fun ia2 ib2
->
3738 tokenf ia3 ib3
>>= (fun ia3 ib3
->
3739 arguments
(seqstyle eas) (A.undots
eas) ebs
>>= (fun easundots ebs
->
3740 let eas = redots
eas easundots
in
3742 A.IteratorHeader
(ia1
, ia2
, eas, ia3
),
3743 F.MacroIterHeader
(st
, ((s,ebs
), [ib1;ib2
;ib3
]))
3748 | A.ForHeader
(ia1
, ia2
, ea1opt
, ia3
, ea2opt
, ia4
, ea3opt
, ia5
),
3749 F.ForHeader
(st
, (((eb1opt
,ib3s
), (eb2opt
,ib4s
), (eb3opt
,ib4vide
)), ii
))
3751 assert (null ib4vide
);
3752 let (ib1, ib2
, ib5
) = tuple_of_list3 ii
in
3753 let ib3 = tuple_of_list1 ib3s
in
3754 let ib4 = tuple_of_list1 ib4s
in
3756 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
3757 tokenf ia2 ib2
>>= (fun ia2 ib2
->
3758 tokenf ia3
ib3 >>= (fun ia3
ib3 ->
3759 tokenf ia4
ib4 >>= (fun ia4
ib4 ->
3760 tokenf ia5 ib5
>>= (fun ia5 ib5
->
3761 option expression ea1opt eb1opt
>>= (fun ea1opt eb1opt
->
3762 option expression ea2opt eb2opt
>>= (fun ea2opt eb2opt
->
3763 option expression ea3opt eb3opt
>>= (fun ea3opt eb3opt
->
3765 A.ForHeader
(ia1
, ia2
, ea1opt
, ia3
, ea2opt
, ia4
, ea3opt
, ia5
),
3766 F.ForHeader
(st
, (((eb1opt
,[ib3]), (eb2opt
,[ib4]), (eb3opt
,[])),
3772 | A.SwitchHeader
(ia1
,ia2
,ea
,ia3
), F.SwitchHeader
(st
, (eb
,ii
)) ->
3773 let (ib1, ib2
, ib3) = tuple_of_list3 ii
in
3774 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
3775 tokenf ia2 ib2
>>= (fun ia2 ib2
->
3776 tokenf ia3
ib3 >>= (fun ia3
ib3 ->
3777 expression ea eb
>>= (fun ea eb
->
3779 A.SwitchHeader
(ia1
,ia2
,ea
,ia3
),
3780 F.SwitchHeader
(st
, (eb
,[ib1;ib2
;ib3]))
3783 | A.Break
(ia1
, ia2
), F.Break
(st
, ((),ii
)) ->
3784 let (ib1, ib2
) = tuple_of_list2 ii
in
3785 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
3786 tokenf ia2 ib2
>>= (fun ia2 ib2
->
3789 F.Break
(st
, ((),[ib1;ib2
]))
3792 | A.Continue
(ia1
, ia2
), F.Continue
(st
, ((),ii
)) ->
3793 let (ib1, ib2
) = tuple_of_list2 ii
in
3794 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
3795 tokenf ia2 ib2
>>= (fun ia2 ib2
->
3797 A.Continue
(ia1
, ia2
),
3798 F.Continue
(st
, ((),[ib1;ib2
]))
3801 | A.Return
(ia1
, ia2
), F.Return
(st
, ((),ii
)) ->
3802 let (ib1, ib2
) = tuple_of_list2 ii
in
3803 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
3804 tokenf ia2 ib2
>>= (fun ia2 ib2
->
3806 A.Return
(ia1
, ia2
),
3807 F.Return
(st
, ((),[ib1;ib2
]))
3810 | A.ReturnExpr
(ia1
, ea
, ia2
), F.ReturnExpr
(st
, (eb
, ii
)) ->
3811 let (ib1, ib2
) = tuple_of_list2 ii
in
3812 tokenf ia1
ib1 >>= (fun ia1
ib1 ->
3813 tokenf ia2 ib2
>>= (fun ia2 ib2
->
3814 expression ea eb
>>= (fun ea eb
->
3816 A.ReturnExpr
(ia1
, ea
, ia2
),
3817 F.ReturnExpr
(st
, (eb
, [ib1;ib2
]))
3822 | A.Include
(incla
,filea
),
3823 F.Include
{B.i_include
= (fileb
, ii
);
3824 B.i_rel_pos
= h_rel_pos
;
3825 B.i_is_in_ifdef
= inifdef
;
3828 assert (copt
=*= None
);
3830 let include_requirment =
3831 match mcodekind incla
, mcodekind filea
with
3832 | A.CONTEXT
(_
, A.BEFORE _
), _
->
3834 | _
, A.CONTEXT
(_
, A.AFTER _
) ->
3840 let (inclb
, iifileb
) = tuple_of_list2 ii
in
3841 if inc_file
(term filea
, include_requirment) (fileb
, h_rel_pos
)
3843 tokenf incla inclb
>>= (fun incla inclb
->
3844 tokenf filea iifileb
>>= (fun filea iifileb
->
3846 A.Include
(incla
, filea
),
3847 F.Include
{B.i_include
= (fileb
, [inclb
;iifileb
]);
3848 B.i_rel_pos
= h_rel_pos
;
3849 B.i_is_in_ifdef
= inifdef
;
3857 | A.DefineHeader
(definea
,ida
,params
), F.DefineHeader
((idb
, ii
), defkind
) ->
3858 let (defineb
, iidb
, ieol
) = tuple_of_list3 ii
in
3859 ident DontKnow ida
(idb
, iidb
) >>= (fun ida
(idb
, iidb
) ->
3860 tokenf definea defineb
>>= (fun definea defineb
->
3861 (match A.unwrap params
, defkind
with
3862 | A.NoParams
, B.DefineVar
->
3864 A.NoParams
+> A.rewrap params
,
3867 | A.DParams
(lpa
,eas,rpa
), (B.DefineFunc
(ebs
, ii
)) ->
3868 let (lpb
, rpb
) = tuple_of_list2 ii
in
3869 tokenf lpa lpb
>>= (fun lpa lpb
->
3870 tokenf rpa rpb
>>= (fun rpa rpb
->
3872 define_params
(seqstyle eas) (A.undots
eas) ebs
>>=
3873 (fun easundots ebs
->
3874 let eas = redots
eas easundots
in
3876 A.DParams
(lpa
,eas,rpa
) +> A.rewrap params
,
3877 B.DefineFunc
(ebs
,[lpb
;rpb
])
3881 ) >>= (fun params defkind
->
3883 A.DefineHeader
(definea
, ida
, params
),
3884 F.DefineHeader
((idb
,[defineb
;iidb
;ieol
]),defkind
)
3889 | A.Default
(def
,colon
), F.Default
(st
, ((),ii
)) ->
3890 let (ib1, ib2
) = tuple_of_list2 ii
in
3891 tokenf def
ib1 >>= (fun def
ib1 ->
3892 tokenf colon ib2
>>= (fun colon ib2
->
3894 A.Default
(def
,colon
),
3895 F.Default
(st
, ((),[ib1;ib2
]))
3900 | A.Case
(case
,ea
,colon
), F.Case
(st
, (eb
,ii
)) ->
3901 let (ib1, ib2
) = tuple_of_list2 ii
in
3902 tokenf case
ib1 >>= (fun case
ib1 ->
3903 expression ea eb
>>= (fun ea eb
->
3904 tokenf colon ib2
>>= (fun colon ib2
->
3906 A.Case
(case
,ea
,colon
),
3907 F.Case
(st
, (eb
,[ib1;ib2
]))
3910 (* only occurs in the predicates generated by asttomember *)
3911 | A.DisjRuleElem
eas, _
->
3913 List.fold_left
(fun acc ea
-> acc
>|+|> (rule_elem_node ea
node)) fail)
3914 >>= (fun ea eb
-> return (A.unwrap ea
,F.unwrap eb
))
3916 | _
, F.ExprStatement
(_
, (None
, ii
)) -> fail (* happen ? *)
3918 | A.Label
(id
,dd
), F.Label
(st
, nameb
, ((),ii
)) ->
3919 let (ib2
) = tuple_of_list1 ii
in
3920 ident_cpp DontKnow id nameb
>>= (fun ida nameb
->
3921 tokenf dd ib2
>>= (fun dd ib2
->
3924 F.Label
(st
,nameb
, ((),[ib2
]))
3927 | A.Goto
(goto
,id
,sem
), F.Goto
(st
,nameb
, ((),ii
)) ->
3928 let (ib1,ib3) = tuple_of_list2 ii
in
3929 tokenf goto
ib1 >>= (fun goto
ib1 ->
3930 ident_cpp DontKnow id nameb
>>= (fun id nameb
->
3931 tokenf sem
ib3 >>= (fun sem
ib3 ->
3933 A.Goto
(goto
,id
,sem
),
3934 F.Goto
(st
,nameb
, ((),[ib1;ib3]))
3937 (* have not a counter part in coccinelle, for the moment *)
3938 (* todo?: print a warning at least ? *)
3944 | _
, (F.IfdefEndif _
|F.IfdefElse _
|F.IfdefHeader _
)
3948 (F.MacroStmt
(_
, _
)| F.DefineDoWhileZeroHeader _
| F.EndNode
|F.TopNode
)
3951 (F.Label
(_
, _
, _
)|F.Break
(_
, _
)|F.Continue
(_
, _
)|F.Default
(_
, _
)|
3952 F.Case
(_
, _
)|F.Include _
|F.Goto _
|F.ExprStatement _
|
3953 F.DefineType _
|F.DefineExpr _
|F.DefineTodo
|
3954 F.DefineHeader
(_
, _
)|F.ReturnExpr
(_
, _
)|F.Return
(_
, _
)|F.MacroIterHeader
(_
, _
)|
3955 F.SwitchHeader
(_
, _
)|F.ForHeader
(_
, _
)|F.DoWhileTail _
|F.DoHeader
(_
, _
)|
3956 F.WhileHeader
(_
, _
)|F.Else _
|F.IfHeader
(_
, _
)|
3957 F.SeqEnd
(_
, _
)|F.SeqStart
(_
, _
, _
)|
3958 F.Decl _
|F.FunHeader _
)