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