Coccinelle release 0.2.5-rc7.
[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
4dfbc1c2 506 | B.ValInit (iini, (B.InitExpr e, ii_empty2)) ->
5626f154
C
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 _,_),_)
4dfbc1c2 1364 | _, ((B.Delete _,_),_)
34e49164
C
1365 -> fail
1366
485bce71 1367
ae4735db 1368 | _,
485bce71
C
1369 (((B.Cast (_, _)|B.ParenExpr _|B.SizeOfType _|B.SizeOfExpr _|
1370 B.RecordPtAccess (_, _)|
1371 B.RecordAccess (_, _)|B.ArrayAccess (_, _)|
1372 B.Binary (_, _, _)|B.Unary (_, _)|
1373 B.Infix (_, _)|B.Postfix (_, _)|
1374 B.Assignment (_, _, _)|B.CondExpr (_, _, _)|
1375 B.FunCall (_, _)|B.Constant _|B.Ident _),
1376 _),_)
1377 -> fail
1378
1379
1380
34e49164
C
1381
1382
34e49164 1383(* ------------------------------------------------------------------------- *)
ae4735db 1384and (ident_cpp: info_ident -> (A.ident, B.name) matcher) =
708f4980 1385 fun infoidb ida idb ->
b1b2de81 1386 match idb with
ae4735db 1387 | B.RegularName (s, iis) ->
b1b2de81 1388 let iis = tuple_of_list1 iis in
ae4735db 1389 ident infoidb ida (s, iis) >>= (fun ida (s,iis) ->
b1b2de81 1390 return (
ae4735db 1391 ida,
b1b2de81
C
1392 (B.RegularName (s, [iis]))
1393 ))
1394 | B.CppConcatenatedName _ | B.CppVariadicName _ |B.CppIdentBuilder _
708f4980
C
1395 ->
1396 (* This should be moved to the Id case of ident. Metavariables
1397 should be allowed to be bound to such variables. But doing so
1398 would require implementing an appropriate distr function *)
1399 fail
b1b2de81 1400
ae4735db 1401and (ident: info_ident -> (A.ident, string * Ast_c.info) matcher) =
d3f655c6 1402 fun infoidb ida ((idb, iib) as ib) -> (* (idb, iib) as ib *)
5636bb2c
C
1403 let check_constraints constraints idb =
1404 let meta_id_val l x = Ast_c.MetaIdVal(x,l) in
1405 match constraints with
1406 A.IdNoConstraint -> return (meta_id_val [],())
1407 | A.IdNegIdSet (str,meta) ->
1408 X.check_idconstraint satisfies_iconstraint str idb
1409 (fun () -> return (meta_id_val meta,()))
1410 | A.IdRegExpConstraint re ->
1411 X.check_idconstraint satisfies_regexpconstraint re idb
1412 (fun () -> return (meta_id_val [],())) in
34e49164
C
1413 X.all_bound (A.get_inherited ida) >&&>
1414 match A.unwrap ida with
ae4735db 1415 | A.Id sa ->
34e49164 1416 if (term sa) =$= idb then
ae4735db 1417 tokenf sa iib >>= (fun sa iib ->
34e49164
C
1418 return (
1419 ((A.Id sa)) +> A.rewrap ida,
1420 (idb, iib)
1421 ))
1422 else fail
1423
ae4735db 1424 | A.MetaId(mida,constraints,keep,inherited) ->
5636bb2c
C
1425 check_constraints constraints idb >>=
1426 (fun wrapper () ->
34e49164
C
1427 let max_min _ = Lib_parsing_c.lin_col_by_pos [iib] in
1428 (* use drop_pos for ids so that the pos is not added a second time in
1429 the call to tokenf *)
5636bb2c 1430 X.envf keep inherited (A.drop_pos mida, wrapper idb, max_min)
ae4735db
C
1431 (fun () ->
1432 tokenf mida iib >>= (fun mida iib ->
34e49164
C
1433 return (
1434 ((A.MetaId (mida, constraints, keep, inherited)) +> A.rewrap ida,
1435 (idb, iib)
1436 )))
1437 ))
1438
ae4735db 1439 | A.MetaFunc(mida,constraints,keep,inherited) ->
34e49164 1440 let is_function _ =
5636bb2c
C
1441 check_constraints constraints idb >>=
1442 (fun wrapper () ->
34e49164
C
1443 let max_min _ = Lib_parsing_c.lin_col_by_pos [iib] in
1444 X.envf keep inherited (A.drop_pos mida,Ast_c.MetaFuncVal idb,max_min)
1445 (fun () ->
ae4735db 1446 tokenf mida iib >>= (fun mida iib ->
34e49164
C
1447 return (
1448 ((A.MetaFunc(mida,constraints,keep,inherited)))+>A.rewrap ida,
1449 (idb, iib)
1450 ))
1451 )) in
ae4735db 1452 (match infoidb with
34e49164
C
1453 | LocalFunction | Function -> is_function()
1454 | DontKnow ->
1455 failwith "MetaFunc, need more semantic info about id"
1456 (* the following implementation could possibly be useful, if one
1457 follows the convention that a macro is always in capital letters
1458 and that a macro is not a function.
1459 (if idb =~ "^[A-Z_][A-Z_0-9]*$" then fail else is_function())*)
1460 )
1461
ae4735db
C
1462 | A.MetaLocalFunc(mida,constraints,keep,inherited) ->
1463 (match infoidb with
1464 | LocalFunction ->
5636bb2c
C
1465 check_constraints constraints idb >>=
1466 (fun wrapper () ->
34e49164
C
1467 let max_min _ = Lib_parsing_c.lin_col_by_pos [iib] in
1468 X.envf keep inherited
1469 (A.drop_pos mida,Ast_c.MetaLocalFuncVal idb, max_min)
1470 (fun () ->
ae4735db 1471 tokenf mida iib >>= (fun mida iib ->
34e49164
C
1472 return (
1473 ((A.MetaLocalFunc(mida,constraints,keep,inherited)))
1474 +> A.rewrap ida,
1475 (idb, iib)
1476 ))
1477 ))
1478 | Function -> fail
1479 | DontKnow -> failwith "MetaLocalFunc, need more semantic info about id"
1480 )
1481
d3f655c6
C
1482 (* not clear why disj things are needed, after disjdistr? *)
1483 | A.DisjId ias ->
1484 ias +> List.fold_left (fun acc ia -> acc >|+|> (ident infoidb ia ib)) fail
1485
ae4735db 1486 | A.OptIdent _ | A.UniqueIdent _ ->
34e49164 1487 failwith "not handling Opt/Unique for ident"
c491d8ee 1488
34e49164 1489(* ------------------------------------------------------------------------- *)
ae4735db 1490and (arguments: sequence ->
c491d8ee
C
1491 (A.expression list, Ast_c.argument Ast_c.wrap2 list) matcher) =
1492 fun seqstyle eas ebs ->
1493 match seqstyle with
1494 | Unordered -> failwith "not handling ooo"
1495 | Ordered ->
1496 arguments_bis eas (Ast_c.split_comma ebs) >>= (fun eas ebs_splitted ->
1497 return (eas, (Ast_c.unsplit_comma ebs_splitted))
1498 )
ae4735db 1499(* because '...' can match nothing, need to take care when have
c491d8ee
C
1500 * ', ...' or '...,' as in f(..., X, Y, ...). It must match
1501 * f(1,2) for instance.
1502 * So I have added special cases such as (if startxs = []) and code
1503 * in the Ecomma matching rule.
1504 *
1505 * old: Must do some try, for instance when f(...,X,Y,...) have to
1506 * test the transfo for all the combinaitions and if multiple transfo
1507 * possible ? pb ? => the type is to return a expression option ? use
1508 * some combinators to help ?
1509 * update: with the tag-SP approach, no more a problem.
1510*)
1511
ae4735db 1512and arguments_bis = fun eas ebs ->
c491d8ee
C
1513 let match_dots ea =
1514 match A.unwrap ea with
1515 A.Edots(mcode, optexpr) -> Some (mcode, optexpr)
1516 | _ -> None in
1517 let build_dots (mcode, optexpr) = A.Edots(mcode, optexpr) in
1518 let match_comma ea =
1519 match A.unwrap ea with
1520 A.EComma ia1 -> Some ia1
1521 | _ -> None in
1522 let build_comma ia1 = A.EComma ia1 in
1523 let match_metalist ea =
1524 match A.unwrap ea with
1525 A.MetaExprList(ida,leninfo,keep,inherited) ->
1526 Some(ida,leninfo,keep,inherited)
1527 | _ -> None in
1528 let build_metalist (ida,leninfo,keep,inherited) =
1529 A.MetaExprList(ida,leninfo,keep,inherited) in
1530 let mktermval v = Ast_c.MetaExprListVal v in
1531 let special_cases ea eas ebs = None in
1532 list_matcher match_dots build_dots match_comma build_comma
1533 match_metalist build_metalist mktermval
1534 special_cases argument X.distrf_args
1535 Lib_parsing_c.ii_of_args eas ebs
ae4735db 1536
113803cf 1537and argument arga argb =
34e49164 1538 X.all_bound (A.get_inherited arga) >&&>
c491d8ee 1539 match A.unwrap arga, argb with
ae4735db 1540 | A.TypeExp tya,
b1b2de81 1541 Right (B.ArgType {B.p_register=b,iib; p_namei=sopt;p_type=tyb}) ->
34e49164 1542 if b || sopt <> None
ae4735db 1543 then
34e49164
C
1544 (* failwith "the argument have a storage and ast_cocci does not have"*)
1545 fail
ae4735db 1546 else
b1b2de81 1547 (* b = false and sopt = None *)
ae4735db 1548 fullType tya tyb >>= (fun tya tyb ->
34e49164
C
1549 return (
1550 (A.TypeExp tya) +> A.rewrap arga,
b1b2de81
C
1551 (Right (B.ArgType {B.p_register=(b,iib);
1552 p_namei=sopt;
1553 p_type=tyb;}))
34e49164
C
1554 ))
1555
1556 | A.TypeExp tya, _ -> fail
b1b2de81 1557 | _, Right (B.ArgType _) -> fail
113803cf
C
1558 | _, Left argb ->
1559 expression arga argb >>= (fun arga argb ->
34e49164
C
1560 return (arga, Left argb)
1561 )
1562 | _, Right (B.ArgAction y) -> fail
1563
1564
1565(* ------------------------------------------------------------------------- *)
1566(* todo? facto code with argument ? *)
ae4735db 1567and (parameters: sequence ->
34e49164 1568 (A.parameterTypeDef list, Ast_c.parameterType Ast_c.wrap2 list)
ae4735db 1569 matcher) =
34e49164
C
1570 fun seqstyle eas ebs ->
1571 match seqstyle with
1572 | Unordered -> failwith "not handling ooo"
ae4735db
C
1573 | Ordered ->
1574 parameters_bis eas (Ast_c.split_comma ebs) >>= (fun eas ebs_splitted ->
34e49164
C
1575 return (eas, (Ast_c.unsplit_comma ebs_splitted))
1576 )
1577
1578
ae4735db 1579and parameters_bis eas ebs =
c491d8ee
C
1580 let match_dots ea =
1581 match A.unwrap ea with
1582 A.Pdots(mcode) -> Some (mcode, None)
1583 | _ -> None in
1584 let build_dots (mcode, _optexpr) = A.Pdots(mcode) in
1585 let match_comma ea =
1586 match A.unwrap ea with
1587 A.PComma ia1 -> Some ia1
1588 | _ -> None in
1589 let build_comma ia1 = A.PComma ia1 in
1590 let match_metalist ea =
1591 match A.unwrap ea with
1592 A.MetaParamList(ida,leninfo,keep,inherited) ->
1593 Some(ida,leninfo,keep,inherited)
1594 | _ -> None in
1595 let build_metalist (ida,leninfo,keep,inherited) =
1596 A.MetaParamList(ida,leninfo,keep,inherited) in
1597 let mktermval v = Ast_c.MetaParamListVal v in
1598 let special_cases ea eas ebs =
1599 (* a case where one smpl parameter matches a list of C parameters *)
1600 match A.unwrap ea,ebs with
1601 A.VoidParam ta, ys ->
1602 Some
34e49164 1603 (match eas, ebs with
ae4735db 1604 | [], [Left eb] ->
b1b2de81 1605 let {B.p_register=(hasreg,iihasreg);
c491d8ee
C
1606 p_namei = idbopt;
1607 p_type=tb; } = eb in
1608
b1b2de81 1609 if idbopt =*= None && not hasreg
ae4735db
C
1610 then
1611 match tb with
1612 | (qub, (B.BaseType B.Void,_)) ->
1613 fullType ta tb >>= (fun ta tb ->
34e49164 1614 return (
c491d8ee
C
1615 [(A.VoidParam ta) +> A.rewrap ea],
1616 [Left {B.p_register=(hasreg, iihasreg);
1617 p_namei = idbopt;
1618 p_type = tb;}]
1619 ))
34e49164
C
1620 | _ -> fail
1621 else fail
c491d8ee
C
1622 | _ -> fail)
1623 | _ -> None in
1624 list_matcher match_dots build_dots match_comma build_comma
1625 match_metalist build_metalist mktermval
1626 special_cases parameter X.distrf_params
1627 Lib_parsing_c.ii_of_params eas ebs
1628
b1b2de81 1629(*
c491d8ee
C
1630 let split_register_param = fun (hasreg, idb, ii_b_s) ->
1631 match hasreg, idb, ii_b_s with
1632 | false, Some s, [i1] -> Left (s, [], i1)
1633 | true, Some s, [i1;i2] -> Left (s, [i1], i2)
1634 | _, None, ii -> Right ii
1635 | _ -> raise Impossible
b1b2de81 1636*)
c491d8ee
C
1637
1638
1639and parameter = fun parama paramb ->
1640 match A.unwrap parama, paramb with
1641 A.MetaParam (ida,keep,inherited), eb ->
1642 (* todo: use quaopt, hasreg ? *)
1643 let max_min _ =
1644 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_param eb) in
1645 X.envf keep inherited (ida,Ast_c.MetaParamVal eb,max_min) (fun () ->
1646 X.distrf_param ida eb
1647 ) >>= (fun ida eb ->
1648 return (A.MetaParam(ida,keep,inherited)+> A.rewrap parama,eb))
1649 | A.Param (typa, idaopt), eb ->
1650 let {B.p_register = (hasreg,iihasreg);
1651 p_namei = nameidbopt;
1652 p_type = typb;} = paramb in
1653
1654 fullType typa typb >>= (fun typa typb ->
1655 match idaopt, nameidbopt with
1656 | Some ida, Some nameidb ->
34e49164 1657 (* todo: if minus on ida, should also minus the iihasreg ? *)
c491d8ee
C
1658 ident_cpp DontKnow ida nameidb >>= (fun ida nameidb ->
1659 return (
1660 A.Param (typa, Some ida)+> A.rewrap parama,
1661 {B.p_register = (hasreg, iihasreg);
1662 p_namei = Some (nameidb);
1663 p_type = typb}
1664 ))
1665
1666 | None, None ->
1667 return (
1668 A.Param (typa, None)+> A.rewrap parama,
1669 {B.p_register=(hasreg,iihasreg);
1670 p_namei = None;
1671 p_type = typb;}
1672 )
34e49164
C
1673 (* why handle this case ? because of transform_proto ? we may not
1674 * have an ident in the proto.
ae4735db 1675 * If have some plus on ida ? do nothing about ida ?
34e49164
C
1676 *)
1677 (* not anymore !!! now that julia is handling the proto.
ae4735db 1678 | _, Right iihasreg ->
34e49164
C
1679 return (
1680 (idaopt, typa),
1681 ((hasreg, None, typb), iihasreg)
1682 )
1683 *)
1684
c491d8ee
C
1685 | Some _, None -> fail
1686 | None, Some _ -> fail)
1687 | (A.OptParam _ | A.UniqueParam _), _ ->
1688 failwith "not handling Opt/Unique for Param"
1689 | A.Pcircles (_), ys -> raise Impossible (* in Ordered mode *)
1690 | _ -> fail
34e49164
C
1691
1692(* ------------------------------------------------------------------------- *)
1693and (declaration: (A.mcodekind * bool * A.declaration,B.declaration) matcher) =
ae4735db 1694 fun (mckstart, allminus, decla) declb ->
34e49164
C
1695 X.all_bound (A.get_inherited decla) >&&>
1696 match A.unwrap decla, declb with
1697
1698 (* Un MetaDecl est introduit dans l'asttoctl pour sauter au dessus
1699 * de toutes les declarations qui sont au debut d'un fonction et
1700 * commencer le reste du match au premier statement. Alors, ca matche
1701 * n'importe quelle declaration. On n'a pas besoin d'ajouter
1702 * quoi que ce soit dans l'environnement. C'est une sorte de DDots.
ae4735db 1703 *
34e49164
C
1704 * When the SP want to remove the whole function, the minus is not
1705 * on the MetaDecl but on the MetaRuleElem. So there should
1706 * be no transform of MetaDecl, just matching are allowed.
1707 *)
1708
413ffc02
C
1709 | A.MetaDecl (ida,keep,inherited), _ ->
1710 let max_min _ =
1711 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_decl declb) in
1712 X.envf keep inherited (ida, Ast_c.MetaDeclVal declb, max_min) (fun () ->
1713 X.distrf_decl ida declb
1714 ) >>= (fun ida declb ->
1715 return ((mckstart, allminus,
1716 (A.MetaDecl (ida, keep, inherited))+> A.rewrap decla),
1717 declb))
ae4735db 1718 | _, (B.DeclList ([var], iiptvirgb::iifakestart::iisto)) ->
34e49164
C
1719 onedecl allminus decla (var,iiptvirgb,iisto) >>=
1720 (fun decla (var,iiptvirgb,iisto)->
ae4735db 1721 X.tokenf_mck mckstart iifakestart >>= (fun mckstart iifakestart ->
34e49164
C
1722 return (
1723 (mckstart, allminus, decla),
1724 (B.DeclList ([var], iiptvirgb::iifakestart::iisto))
1725 )))
ae4735db
C
1726
1727 | _, (B.DeclList (xs, iiptvirgb::iifakestart::iisto)) ->
690d68d1
C
1728 let indexify l =
1729 let rec loop n = function
1730 [] -> []
1731 | x::xs -> (n,x)::(loop (n+1) xs) in
1732 loop 0 l in
1733 let rec repln n vl cur = function
1734 [] -> []
1735 | x::xs ->
1736 if n = cur then vl :: xs else x :: (repln n vl (cur+1) xs) in
1737 if X.mode =*= PatternMode || A.get_safe_decl decla
34e49164 1738 then
690d68d1
C
1739 (indexify xs) +> List.fold_left (fun acc (n,var) ->
1740 (* consider all possible matches *)
1741 acc >||> (function tin -> (
34e49164 1742 X.tokenf_mck mckstart iifakestart >>= (fun mckstart iifakestart ->
ae4735db
C
1743 onedecl allminus decla (var, iiptvirgb, iisto) >>=
1744 (fun decla (var, iiptvirgb, iisto) ->
34e49164
C
1745 return (
1746 (mckstart, allminus, decla),
690d68d1
C
1747 (* adjust the variable that was chosen *)
1748 (B.DeclList (repln n var 0 xs,
1749 iiptvirgb::iifakestart::iisto))
1750 )))) tin))
34e49164 1751 fail
ae4735db 1752 else
3a314143 1753 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
1754
1755 | A.MacroDecl (sa,lpa,eas,rpa,enda), B.MacroDecl ((sb,ebs),ii) ->
ae4735db 1756 let (iisb, lpb, rpb, iiendb, iifakestart, iistob) =
34e49164 1757 (match ii with
ae4735db 1758 | iisb::lpb::rpb::iiendb::iifakestart::iisto ->
34e49164
C
1759 (iisb,lpb,rpb,iiendb, iifakestart,iisto)
1760 | _ -> raise Impossible
1761 ) in
ae4735db 1762 (if allminus
34e49164
C
1763 then minusize_list iistob
1764 else return ((), iistob)
1765 ) >>= (fun () iistob ->
1766
ae4735db 1767 X.tokenf_mck mckstart iifakestart >>= (fun mckstart iifakestart ->
34e49164 1768 ident DontKnow sa (sb, iisb) >>= (fun sa (sb, iisb) ->
ae4735db
C
1769 tokenf lpa lpb >>= (fun lpa lpb ->
1770 tokenf rpa rpb >>= (fun rpa rpb ->
1771 tokenf enda iiendb >>= (fun enda iiendb ->
1772 arguments (seqstyle eas) (A.undots eas) ebs >>= (fun easundots ebs ->
34e49164
C
1773 let eas = redots eas easundots in
1774
1775 return (
ae4735db
C
1776 (mckstart, allminus,
1777 (A.MacroDecl (sa,lpa,eas,rpa,enda)) +> A.rewrap decla),
34e49164
C
1778 (B.MacroDecl ((sb,ebs),
1779 [iisb;lpb;rpb;iiendb;iifakestart] ++ iistob))
1780 ))))))))
485bce71 1781
413ffc02 1782 | _, (B.MacroDecl _ |B.DeclList _) -> fail
34e49164
C
1783
1784
ae4735db 1785and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
34e49164
C
1786 X.all_bound (A.get_inherited decla) >&&>
1787 match A.unwrap decla, declb with
1788
ae4735db 1789 (* kind of typedef iso, we must unfold, it's for the case
34e49164
C
1790 * T { }; that we want to match against typedef struct { } xx_t;
1791 *)
413ffc02 1792
ae4735db 1793 | A.TyDecl (tya0, ptvirga),
4dfbc1c2 1794 ({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
1795 B.v_type = typb0;
1796 B.v_storage = (B.StoTypedef, inl);
ae4735db 1797 B.v_local = local;
485bce71 1798 B.v_attr = attrs;
978fd7e5 1799 B.v_type_bis = typb0bis;
485bce71 1800 }, iivirg) ->
34e49164
C
1801
1802 (match A.unwrap tya0, typb0 with
1803 | A.Type(cv1,tya1), ((qu,il),typb1) ->
1804
1805 (match A.unwrap tya1, typb1 with
ae4735db
C
1806 | A.StructUnionDef(tya2, lba, declsa, rba),
1807 (B.StructUnion (sub, sbopt, declsb), ii) ->
34e49164 1808
ae4735db 1809 let (iisub, iisbopt, lbb, rbb) =
34e49164 1810 match sbopt with
ae4735db 1811 | None ->
34e49164
C
1812 let (iisub, lbb, rbb) = tuple_of_list3 ii in
1813 (iisub, [], lbb, rbb)
ae4735db
C
1814 | Some s ->
1815 pr2 (sprintf
34e49164 1816 "warning: both a typedef (%s) and struct name introduction (%s)"
b1b2de81 1817 (Ast_c.str_of_name nameidb) s
34e49164
C
1818 );
1819 pr2 "warning: I will consider only the typedef";
1820 let (iisub, iisb, lbb, rbb) = tuple_of_list4 ii in
1821 (iisub, [iisb], lbb, rbb)
1822 in
ae4735db 1823 let structnameb =
34e49164
C
1824 structdef_to_struct_name
1825 (Ast_c.nQ, (B.StructUnion (sub, sbopt, declsb), ii))
1826 in
ae4735db
C
1827 let fake_typeb =
1828 Ast_c.nQ,((B.TypeName (nameidb, Some
1829 (Lib_parsing_c.al_type structnameb))), [])
34e49164
C
1830 in
1831
ae4735db
C
1832 tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
1833 tokenf lba lbb >>= (fun lba lbb ->
1834 tokenf rba rbb >>= (fun rba rbb ->
34e49164
C
1835 struct_fields (A.undots declsa) declsb >>=(fun undeclsa declsb ->
1836 let declsa = redots declsa undeclsa in
1837
1838 (match A.unwrap tya2 with
ae4735db 1839 | A.Type(cv3, tya3) ->
34e49164 1840 (match A.unwrap tya3 with
ae4735db 1841 | A.MetaType(ida,keep, inherited) ->
34e49164 1842
ae4735db 1843 fullType tya2 fake_typeb >>= (fun tya2 fake_typeb ->
34e49164
C
1844 let tya1 =
1845 A.StructUnionDef(tya2,lba,declsa,rba)+> A.rewrap tya1 in
1846 let tya0 = A.Type(cv1, tya1) +> A.rewrap tya0 in
ae4735db
C
1847
1848
34e49164
C
1849 let typb1 = B.StructUnion (sub,sbopt, declsb),
1850 [iisub] @ iisbopt @ [lbb;rbb] in
1851 let typb0 = ((qu, il), typb1) in
ae4735db
C
1852
1853 match fake_typeb with
1854 | _nQ, ((B.TypeName (nameidb, _typ)),[]) ->
34e49164
C
1855
1856 return (
1857 (A.TyDecl (tya0, ptvirga)) +> A.rewrap decla,
4dfbc1c2 1858 (({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
1859 B.v_type = typb0;
1860 B.v_storage = (B.StoTypedef, inl);
1861 B.v_local = local;
1862 B.v_attr = attrs;
978fd7e5 1863 B.v_type_bis = typb0bis;
485bce71 1864 },
34e49164
C
1865 iivirg),iiptvirgb,iistob)
1866 )
ae4735db 1867 | _ -> raise Impossible
34e49164
C
1868 )
1869
c491d8ee 1870 (* do we need EnumName here too? *)
ae4735db 1871 | A.StructUnionName(sua, sa) ->
ae4735db 1872 fullType tya2 structnameb >>= (fun tya2 structnameb ->
34e49164
C
1873
1874 let tya1 = A.StructUnionDef(tya2,lba,declsa,rba)+> A.rewrap tya1
1875 in
1876 let tya0 = A.Type(cv1, tya1) +> A.rewrap tya0 in
1877
ae4735db 1878 match structnameb with
34e49164
C
1879 | _nQ, (B.StructUnionName (sub, s), [iisub;iisbopt]) ->
1880
1881 let typb1 = B.StructUnion (sub,sbopt, declsb),
1882 [iisub;iisbopt;lbb;rbb] in
1883 let typb0 = ((qu, il), typb1) in
ae4735db 1884
34e49164
C
1885 return (
1886 (A.TyDecl (tya0, ptvirga)) +> A.rewrap decla,
4dfbc1c2 1887 (({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
1888 B.v_type = typb0;
1889 B.v_storage = (B.StoTypedef, inl);
1890 B.v_local = local;
1891 B.v_attr = attrs;
978fd7e5 1892 B.v_type_bis = typb0bis;
485bce71 1893 },
34e49164
C
1894 iivirg),iiptvirgb,iistob)
1895 )
ae4735db 1896 | _ -> raise Impossible
34e49164
C
1897 )
1898 | _ -> raise Impossible
1899 )
1900 | _ -> fail
1901 )))))
1902 | _ -> fail
1903 )
1904 | _ -> fail
1905 )
ae4735db
C
1906
1907 | A.UnInit (stoa, typa, ida, ptvirga),
1908 ({B.v_namei= Some (nameidb, _);B.v_storage= (B.StoTypedef,_);}, iivirg)
b1b2de81 1909 -> fail
34e49164 1910
ae4735db 1911 | A.Init (stoa, typa, ida, eqa, inia, ptvirga),
b1b2de81
C
1912 ({B.v_namei=Some(nameidb, _);B.v_storage=(B.StoTypedef,_);}, iivirg)
1913 -> fail
34e49164
C
1914
1915
1916
1917 (* could handle iso here but handled in standard.iso *)
ae4735db 1918 | A.UnInit (stoa, typa, ida, ptvirga),
4dfbc1c2 1919 ({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
1920 B.v_type = typb;
1921 B.v_storage = stob;
1922 B.v_local = local;
1923 B.v_attr = attrs;
978fd7e5 1924 B.v_type_bis = typbbis;
ae4735db 1925 }, iivirg) ->
ae4735db
C
1926 tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
1927 fullType typa typb >>= (fun typa typb ->
1928 ident_cpp DontKnow ida nameidb >>= (fun ida nameidb ->
1929 storage_optional_allminus allminus stoa (stob, iistob) >>=
1930 (fun stoa (stob, iistob) ->
34e49164
C
1931 return (
1932 (A.UnInit (stoa, typa, ida, ptvirga)) +> A.rewrap decla,
4dfbc1c2 1933 (({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
1934 B.v_type = typb;
1935 B.v_storage = stob;
1936 B.v_local = local;
1937 B.v_attr = attrs;
978fd7e5 1938 B.v_type_bis = typbbis;
485bce71 1939 },iivirg),
34e49164
C
1940 iiptvirgb,iistob)
1941 )))))
1942
ae4735db 1943 | A.Init (stoa, typa, ida, eqa, inia, ptvirga),
4dfbc1c2 1944 ({B.v_namei = Some(nameidb, B.ValInit (iieqb, inib));
485bce71
C
1945 B.v_type = typb;
1946 B.v_storage = stob;
1947 B.v_local = local;
1948 B.v_attr = attrs;
978fd7e5 1949 B.v_type_bis = typbbis;
485bce71 1950 },iivirg)
34e49164 1951 ->
ae4735db
C
1952 tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
1953 tokenf eqa iieqb >>= (fun eqa iieqb ->
1954 fullType typa typb >>= (fun typa typb ->
1955 ident_cpp DontKnow ida nameidb >>= (fun ida nameidb ->
1956 storage_optional_allminus allminus stoa (stob, iistob) >>=
1957 (fun stoa (stob, iistob) ->
1958 initialiser inia inib >>= (fun inia inib ->
34e49164
C
1959 return (
1960 (A.Init (stoa, typa, ida, eqa, inia, ptvirga)) +> A.rewrap decla,
4dfbc1c2 1961 (({B.v_namei = Some(nameidb, B.ValInit (iieqb, inib));
485bce71
C
1962 B.v_type = typb;
1963 B.v_storage = stob;
1964 B.v_local = local;
1965 B.v_attr = attrs;
978fd7e5 1966 B.v_type_bis = typbbis;
485bce71 1967 },iivirg),
34e49164
C
1968 iiptvirgb,iistob)
1969 )))))))
ae4735db 1970
4dfbc1c2
C
1971 | A.Init (stoa, typa, ida, eqa, inia, ptvirga),
1972 ({B.v_namei = Some(nameidb, B.ConstrInit _);
1973 B.v_type = typb;
1974 B.v_storage = stob;
1975 B.v_local = local;
1976 B.v_attr = attrs;
1977 B.v_type_bis = typbbis;
1978 },iivirg)
1979 -> fail (* C++ constructor declaration not supported in SmPL *)
1980
34e49164 1981 (* do iso-by-absence here ? allow typedecl and var ? *)
ae4735db
C
1982 | A.TyDecl (typa, ptvirga),
1983 ({B.v_namei = None; B.v_type = typb;
1984 B.v_storage = stob;
485bce71
C
1985 B.v_local = local;
1986 B.v_attr = attrs;
978fd7e5 1987 B.v_type_bis = typbbis;
485bce71
C
1988 }, iivirg) ->
1989
b1b2de81 1990 if stob =*= (B.NoSto, false)
34e49164 1991 then
ae4735db
C
1992 tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
1993 fullType typa typb >>= (fun typa typb ->
34e49164
C
1994 return (
1995 (A.TyDecl (typa, ptvirga)) +> A.rewrap decla,
485bce71
C
1996 (({B.v_namei = None;
1997 B.v_type = typb;
1998 B.v_storage = stob;
1999 B.v_local = local;
2000 B.v_attr = attrs;
978fd7e5 2001 B.v_type_bis = typbbis;
485bce71 2002 }, iivirg), iiptvirgb, iistob)
34e49164
C
2003 )))
2004 else fail
2005
2006
ae4735db 2007 | A.Typedef (stoa, typa, ida, ptvirga),
4dfbc1c2 2008 ({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
2009 B.v_type = typb;
2010 B.v_storage = (B.StoTypedef,inline);
2011 B.v_local = local;
2012 B.v_attr = attrs;
978fd7e5 2013 B.v_type_bis = typbbis;
485bce71 2014 },iivirg) ->
34e49164 2015
ae4735db
C
2016 tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
2017 fullType typa typb >>= (fun typa typb ->
34e49164 2018 (match iistob with
ae4735db
C
2019 | [iitypedef] ->
2020 tokenf stoa iitypedef >>= (fun stoa iitypedef ->
34e49164
C
2021 return (stoa, [iitypedef])
2022 )
0708f913 2023 | _ -> failwith "weird, have both typedef and inline or nothing";
ae4735db 2024 ) >>= (fun stoa iistob ->
34e49164 2025 (match A.unwrap ida with
ae4735db 2026 | A.MetaType(_,_,_) ->
34e49164 2027
ae4735db
C
2028 let fake_typeb =
2029 Ast_c.nQ, ((B.TypeName (nameidb, Ast_c.noTypedefDef())), [])
34e49164 2030 in
ae4735db 2031 fullTypebis ida fake_typeb >>= (fun ida fake_typeb ->
34e49164 2032 match fake_typeb with
b1b2de81
C
2033 | _nQ, ((B.TypeName (nameidb, _typ)), []) ->
2034 return (ida, nameidb)
34e49164
C
2035 | _ -> raise Impossible
2036 )
2037
ae4735db 2038 | A.TypeName sa ->
b1b2de81 2039 (match nameidb with
ae4735db 2040 | B.RegularName (sb, iidb) ->
b1b2de81 2041 let iidb1 = tuple_of_list1 iidb in
ae4735db 2042
b1b2de81 2043 if (term sa) =$= sb
ae4735db
C
2044 then
2045 tokenf sa iidb1 >>= (fun sa iidb1 ->
b1b2de81
C
2046 return (
2047 (A.TypeName sa) +> A.rewrap ida,
2048 B.RegularName (sb, [iidb1])
2049 ))
2050 else fail
2051
2052 | B.CppConcatenatedName _ | B.CppVariadicName _ |B.CppIdentBuilder _
2053 -> raise Todo
2054 )
2055
34e49164
C
2056 | _ -> raise Impossible
2057
b1b2de81 2058 ) >>= (fun ida nameidb ->
34e49164
C
2059 return (
2060 (A.Typedef (stoa, typa, ida, ptvirga)) +> A.rewrap decla,
4dfbc1c2 2061 (({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
2062 B.v_type = typb;
2063 B.v_storage = (B.StoTypedef,inline);
2064 B.v_local = local;
2065 B.v_attr = attrs;
978fd7e5 2066 B.v_type_bis = typbbis;
485bce71 2067 },
34e49164
C
2068 iivirg),
2069 iiptvirgb, iistob)
2070 )
2071 ))))
ae4735db
C
2072
2073
2074 | _, ({B.v_namei = None;}, _) ->
0708f913 2075 (* old: failwith "no variable in this declaration, weird" *)
34e49164
C
2076 fail
2077
2078
2079
ae4735db
C
2080 | A.DisjDecl declas, declb ->
2081 declas +> List.fold_left (fun acc decla ->
2082 acc >|+|>
34e49164
C
2083 (* (declaration (mckstart, allminus, decla) declb) *)
2084 (onedecl allminus decla (declb,iiptvirgb, iistob))
2085 ) fail
2086
2087
ae4735db 2088
34e49164
C
2089 (* only in struct type decls *)
2090 | A.Ddots(dots,whencode), _ ->
2091 raise Impossible
ae4735db
C
2092
2093 | A.OptDecl _, _ | A.UniqueDecl _, _ ->
34e49164
C
2094 failwith "not handling Opt/Unique Decl"
2095
ae4735db 2096 | _, ({B.v_namei=Some _}, _) ->
b1b2de81 2097 fail
34e49164 2098
34e49164
C
2099
2100
2101
2102(* ------------------------------------------------------------------------- *)
2103
ae4735db 2104and (initialiser: (A.initialiser, Ast_c.initialiser) matcher) = fun ia ib ->
34e49164
C
2105 X.all_bound (A.get_inherited ia) >&&>
2106 match (A.unwrap ia,ib) with
2107
ae4735db 2108 | (A.MetaInit(ida,keep,inherited), ib) ->
113803cf
C
2109 let max_min _ =
2110 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_ini ib) in
2111 X.envf keep inherited (ida, Ast_c.MetaInitVal ib, max_min)
ae4735db
C
2112 (fun () ->
2113 X.distrf_ini ida ib >>= (fun ida ib ->
113803cf
C
2114 return (
2115 A.MetaInit (ida,keep,inherited) +> A.rewrap ia,
2116 ib
2117 ))
2118 )
2119
ae4735db 2120 | (A.InitExpr expa, ib) ->
34e49164 2121 (match A.unwrap expa, ib with
ae4735db
C
2122 | A.Edots (mcode, None), ib ->
2123 X.distrf_ini (dots2metavar mcode) ib >>= (fun mcode ib ->
34e49164 2124 return (
ae4735db
C
2125 A.InitExpr
2126 (A.Edots (metavar2dots mcode, None) +> A.rewrap expa)
34e49164
C
2127 +> A.rewrap ia,
2128 ib
2129 ))
2130
2131 | A.Edots (_, Some expr), _ -> failwith "not handling when on Edots"
2132
ae4735db 2133 | _, (B.InitExpr expb, ii) ->
34e49164 2134 assert (null ii);
ae4735db 2135 expression expa expb >>= (fun expa expb ->
34e49164
C
2136 return (
2137 (A.InitExpr expa) +> A.rewrap ia,
2138 (B.InitExpr expb, ii)
2139 ))
2140 | _ -> fail
2141 )
2142
c491d8ee
C
2143 | (A.ArInitList (ia1, ias, ia2), (B.InitList ibs, ii)) ->
2144 (match ii with
2145 | ib1::ib2::iicommaopt ->
2146 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
2147 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
2148 ar_initialisers (A.undots ias) (ibs, iicommaopt) >>=
2149 (fun iasundots (ibs,iicommaopt) ->
2150 return (
2151 (A.ArInitList (ia1, redots ias iasundots, ia2)) +> A.rewrap ia,
2152 (B.InitList ibs, ib1::ib2::iicommaopt)
2153 ))))
2154
2155 | _ -> raise Impossible
2156 )
2157
2158 | (A.StrInitList (allminus, ia1, ias, ia2, []), (B.InitList ibs, ii)) ->
ae4735db
C
2159 (match ii with
2160 | ib1::ib2::iicommaopt ->
34e49164
C
2161 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
2162 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
c491d8ee 2163 str_initialisers allminus ias (ibs, iicommaopt) >>=
90aeb998 2164 (fun ias (ibs,iicommaopt) ->
34e49164 2165 return (
c491d8ee 2166 (A.StrInitList (allminus, ia1, ias, ia2, [])) +> A.rewrap ia,
34e49164
C
2167 (B.InitList ibs, ib1::ib2::iicommaopt)
2168 ))))
ae4735db 2169
34e49164
C
2170 | _ -> raise Impossible
2171 )
2172
c491d8ee
C
2173 | (A.StrInitList (allminus, i1, ias, i2, whencode),
2174 (B.InitList ibs, _ii)) ->
34e49164
C
2175 failwith "TODO: not handling whencode in initialisers"
2176
2177
ae4735db 2178 | (A.InitGccExt (designatorsa, ia2, inia),
113803cf 2179 (B.InitDesignators (designatorsb, inib), ii2))->
34e49164 2180
34e49164
C
2181 let iieq = tuple_of_list1 ii2 in
2182
ae4735db 2183 tokenf ia2 iieq >>= (fun ia2 iieq ->
113803cf
C
2184 designators designatorsa designatorsb >>=
2185 (fun designatorsa designatorsb ->
ae4735db 2186 initialiser inia inib >>= (fun inia inib ->
34e49164 2187 return (
113803cf
C
2188 (A.InitGccExt (designatorsa, ia2, inia)) +> A.rewrap ia,
2189 (B.InitDesignators (designatorsb, inib), [iieq])
2190 ))))
34e49164
C
2191
2192
2193
2194
ae4735db
C
2195 | (A.InitGccName (ida, ia1, inia), (B.InitFieldOld (idb, inib), ii)) ->
2196 (match ii with
2197 | [iidb;iicolon] ->
2198 ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
2199 initialiser inia inib >>= (fun inia inib ->
2200 tokenf ia1 iicolon >>= (fun ia1 iicolon ->
34e49164
C
2201 return (
2202 (A.InitGccName (ida, ia1, inia)) +> A.rewrap ia,
2203 (B.InitFieldOld (idb, inib), [iidb;iicolon])
2204 ))))
2205 | _ -> fail
2206 )
2207
2208
2209
2210 | A.IComma(comma), _ ->
2211 raise Impossible
2212
ae4735db 2213 | A.UniqueIni _,_ | A.OptIni _,_ ->
34e49164 2214 failwith "not handling Opt/Unique on initialisers"
485bce71 2215
ae4735db
C
2216 | _, (B.InitIndexOld (_, _), _) -> fail
2217 | _, (B.InitFieldOld (_, _), _) -> fail
485bce71
C
2218
2219 | _, ((B.InitDesignators (_, _)|B.InitList _|B.InitExpr _), _)
2220 -> fail
2221
113803cf
C
2222and designators dla dlb =
2223 match (dla,dlb) with
2224 ([],[]) -> return ([], [])
2225 | ([],_) | (_,[]) -> fail
2226 | (da::dla,db::dlb) ->
2227 designator da db >>= (fun da db ->
2228 designators dla dlb >>= (fun dla dlb ->
2229 return (da::dla, db::dlb)))
2230
2231and designator da db =
2232 match (da,db) with
2233 (A.DesignatorField (ia1, ida), (B.DesignatorField idb,ii1)) ->
34e49164 2234
113803cf 2235 let (iidot, iidb) = tuple_of_list2 ii1 in
ae4735db 2236 tokenf ia1 iidot >>= (fun ia1 iidot ->
113803cf
C
2237 ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
2238 return (
2239 A.DesignatorField (ia1, ida),
2240 (B.DesignatorField idb, [iidot;iidb])
2241 )))
2242
2243 | (A.DesignatorIndex (ia1,ea,ia2), (B.DesignatorIndex eb, ii1)) ->
ae4735db 2244
113803cf 2245 let (ib1, ib2) = tuple_of_list2 ii1 in
ae4735db
C
2246 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
2247 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
2248 expression ea eb >>= (fun ea eb ->
113803cf
C
2249 return (
2250 A.DesignatorIndex (ia1,ea,ia2),
2251 (B.DesignatorIndex eb, [ib1;ib2])
2252 ))))
34e49164 2253
113803cf
C
2254 | (A.DesignatorRange (ia1,e1a,ia2,e2a,ia3),
2255 (B.DesignatorRange (e1b, e2b), ii1)) ->
34e49164 2256
113803cf 2257 let (ib1, ib2, ib3) = tuple_of_list3 ii1 in
ae4735db
C
2258 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
2259 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
2260 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
2261 expression e1a e1b >>= (fun e1a e1b ->
2262 expression e2a e2b >>= (fun e2a e2b ->
113803cf
C
2263 return (
2264 A.DesignatorRange (ia1,e1a,ia2,e2a,ia3),
2265 (B.DesignatorRange (e1b, e2b), [ib1;ib2;ib3])
2266 ))))))
2267 | (_, ((B.DesignatorField _|B.DesignatorIndex _|B.DesignatorRange _), _)) ->
2268 fail
34e49164 2269
c491d8ee 2270and str_initialisers = fun allminus ias (ibs, iicomma) ->
34e49164
C
2271 let ias_unsplit = unsplit_icomma ias in
2272 let ibs_split = resplit_initialiser ibs iicomma in
2273
c491d8ee
C
2274 if need_unordered_initialisers ibs
2275 then initialisers_unordered2 allminus ias_unsplit ibs_split >>=
2276 (fun ias_unsplit ibs_split ->
2277 return (
2278 split_icomma ias_unsplit,
2279 unsplit_initialiser ibs_split))
2280 else fail
2281
2282and ar_initialisers = fun ias (ibs, iicomma) ->
2283 (* this doesn't check need_unordered_initialisers because ... can be
2284 implemented as ordered, even if it matches unordered initializers *)
2285 let ibs = resplit_initialiser ibs iicomma in
2286 let ibs =
2287 List.concat
2288 (List.map (function (elem,comma) -> [Left elem; Right [comma]]) ibs) in
2289 initialisers_ordered2 ias ibs >>=
2290 (fun ias ibs_split ->
2291 let ibs,iicomma =
2292 match List.rev ibs_split with
2293 (Right comma)::rest -> (Ast_c.unsplit_comma (List.rev rest),comma)
2294 | (Left _)::_ -> (Ast_c.unsplit_comma ibs_split,[]) (* possible *)
2295 | [] -> ([],[]) in
2296 return (ias, (ibs,iicomma)))
34e49164 2297
ae4735db 2298and initialisers_ordered2 = fun ias ibs ->
c491d8ee
C
2299 let match_dots ea =
2300 match A.unwrap ea with
2301 A.Idots(mcode, optexpr) -> Some (mcode, optexpr)
2302 | _ -> None in
2303 let build_dots (mcode, optexpr) = A.Idots(mcode, optexpr) in
2304 let match_comma ea =
2305 match A.unwrap ea with
2306 A.IComma ia1 -> Some ia1
2307 | _ -> None in
2308 let build_comma ia1 = A.IComma ia1 in
2309 let match_metalist ea = None in
2310 let build_metalist (ida,leninfo,keep,inherited) = failwith "not possible" in
2311 let mktermval v = failwith "not possible" in
2312 let special_cases ea eas ebs = None in
2313 let no_ii x = failwith "not possible" in
2314 list_matcher match_dots build_dots match_comma build_comma
2315 match_metalist build_metalist mktermval
2316 special_cases initialiser X.distrf_inis no_ii ias ibs
34e49164 2317
34e49164 2318
90aeb998 2319and initialisers_unordered2 = fun allminus ias ibs ->
34e49164 2320 match ias, ibs with
90aeb998
C
2321 | [], ys ->
2322 if allminus
2323 then
2324 let rec loop = function
2325 [] -> return ([],[])
2326 | (ib,comma)::ibs ->
2327 X.distrf_ini minusizer ib >>= (fun _ ib ->
2328 tokenf minusizer comma >>= (fun _ comma ->
2329 loop ibs >>= (fun l ibs ->
2330 return(l,(ib,comma)::ibs)))) in
2331 loop ibs
2332 else return ([], ys)
c491d8ee 2333 | x::xs, ys ->
34e49164 2334 let permut = Common.uncons_permut_lazy ys in
ae4735db
C
2335 permut +> List.fold_left (fun acc ((e, pos), rest) ->
2336 acc >||>
c491d8ee 2337 (initialiser_comma x e
ae4735db 2338 >>= (fun x e ->
34e49164 2339 let rest = Lazy.force rest in
90aeb998 2340 initialisers_unordered2 allminus xs rest >>= (fun xs rest ->
34e49164
C
2341 return (
2342 x::xs,
2343 Common.insert_elem_pos (e, pos) rest
2344 ))))
2345 ) fail
ae4735db 2346
c491d8ee
C
2347and initialiser_comma (x,xcomma) (y, commay) =
2348 match A.unwrap xcomma with
2349 A.IComma commax ->
2350 tokenf commax commay >>= (fun commax commay ->
2351 initialiser x y >>= (fun x y ->
2352 return (
2353 (x, (A.IComma commax) +> A.rewrap xcomma),
2354 (y, commay))))
2355 | _ -> raise Impossible (* unsplit_iicomma wrong *)
34e49164
C
2356
2357(* ------------------------------------------------------------------------- *)
485bce71 2358and (struct_fields: (A.declaration list, B.field list) matcher) =
ae4735db 2359 fun eas ebs ->
c491d8ee
C
2360 let match_dots ea =
2361 match A.unwrap ea with
2362 A.Ddots(mcode, optexpr) -> Some (mcode, optexpr)
2363 | _ -> None in
2364 let build_dots (mcode, optexpr) = A.Ddots(mcode, optexpr) in
2365 let match_comma ea = None in
2366 let build_comma ia1 = failwith "not possible" in
2367 let match_metalist ea = None in
2368 let build_metalist (ida,leninfo,keep,inherited) = failwith "not possible" in
2369 let mktermval v = failwith "not possible" in
2370 let special_cases ea eas ebs = None in
2371 let no_ii x = failwith "not possible" in
2372 let make_ebs ebs = List.map (function x -> Left x) ebs in
2373 let unmake_ebs ebs =
2374 List.map (function Left x -> x | Right x -> failwith "no right") ebs in
2375 let distrf mcode startxs =
2376 let startxs = unmake_ebs startxs in
2377 X.distrf_struct_fields mcode startxs >>=
2378 (fun mcode startxs -> return (mcode,make_ebs startxs)) in
2379 list_matcher match_dots build_dots match_comma build_comma
2380 match_metalist build_metalist mktermval
2381 special_cases struct_field distrf no_ii eas (make_ebs ebs) >>=
2382 (fun eas ebs -> return (eas,unmake_ebs ebs))
34e49164 2383
ae4735db 2384and (struct_field: (A.declaration, B.field) matcher) = fun fa fb ->
34e49164 2385
413ffc02
C
2386 match A.unwrap fa,fb with
2387 | A.MetaField (ida,keep,inherited), _ ->
2388 let max_min _ =
2389 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_field fb) in
2390 X.envf keep inherited (ida, Ast_c.MetaFieldVal fb, max_min) (fun () ->
2391 X.distrf_field ida fb
2392 ) >>= (fun ida fb ->
2393 return ((A.MetaField (ida, keep, inherited))+> A.rewrap fa,
2394 fb))
2395 | _,B.DeclarationField (B.FieldDeclList (onefield_multivars,iiptvirg)) ->
485bce71
C
2396
2397 let iiptvirgb = tuple_of_list1 iiptvirg in
34e49164
C
2398
2399 (match onefield_multivars with
2400 | [] -> raise Impossible
ae4735db 2401 | [onevar,iivirg] ->
34e49164
C
2402 assert (null iivirg);
2403 (match onevar with
ae4735db 2404 | B.BitField (sopt, typb, _, expr) ->
34e49164
C
2405 pr2_once "warning: bitfield not handled by ast_cocci";
2406 fail
ae4735db 2407 | B.Simple (None, typb) ->
34e49164
C
2408 pr2_once "warning: unamed struct field not handled by ast_cocci";
2409 fail
ae4735db 2410 | B.Simple (Some nameidb, typb) ->
34e49164
C
2411
2412 (* build a declaration from a struct field *)
2413 let allminus = false in
2414 let iisto = [] in
2415 let stob = B.NoSto, false in
ae4735db 2416 let fake_var =
4dfbc1c2 2417 ({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
2418 B.v_type = typb;
2419 B.v_storage = stob;
2420 B.v_local = Ast_c.NotLocalDecl;
2421 B.v_attr = Ast_c.noattr;
ae4735db 2422 B.v_type_bis = ref None;
978fd7e5
C
2423 (* the struct field should also get expanded ? no it's not
2424 * important here, we will rematch very soon *)
485bce71 2425 },
ae4735db 2426 iivirg)
34e49164 2427 in
ae4735db
C
2428 onedecl allminus fa (fake_var,iiptvirgb,iisto) >>=
2429 (fun fa (var,iiptvirgb,iisto) ->
34e49164
C
2430
2431 match fake_var with
4dfbc1c2 2432 | ({B.v_namei = Some (nameidb, B.NoInit);
485bce71
C
2433 B.v_type = typb;
2434 B.v_storage = stob;
ae4735db 2435 }, iivirg) ->
b1b2de81
C
2436
2437 let onevar = B.Simple (Some nameidb, typb) in
ae4735db 2438
34e49164
C
2439 return (
2440 (fa),
ae4735db 2441 ((B.DeclarationField
708f4980
C
2442 (B.FieldDeclList ([onevar, iivirg], [iiptvirgb])))
2443 )
34e49164
C
2444 )
2445 | _ -> raise Impossible
2446 )
2447 )
2448
ae4735db 2449 | x::y::xs ->
34e49164
C
2450 pr2_once "PB: More that one variable in decl. Have to split";
2451 fail
2452 )
413ffc02 2453 | _,B.EmptyField _iifield ->
485bce71
C
2454 fail
2455
413ffc02
C
2456 | A.MacroDecl (sa,lpa,eas,rpa,enda),B.MacroDeclField ((sb,ebs),ii) ->
2457 raise Todo
2458 | _,B.MacroDeclField ((sb,ebs),ii) -> fail
708f4980 2459
413ffc02
C
2460 | _,B.CppDirectiveStruct directive -> fail
2461 | _,B.IfdefStruct directive -> fail
34e49164
C
2462
2463
c491d8ee
C
2464and enum_fields = fun eas ebs ->
2465 let match_dots ea =
2466 match A.unwrap ea with
2467 A.Edots(mcode, optexpr) -> Some (mcode, optexpr)
2468 | _ -> None in
2469 let build_dots (mcode, optexpr) = A.Edots(mcode, optexpr) in
2470 let match_comma ea =
2471 match A.unwrap ea with
2472 A.EComma ia1 -> Some ia1
2473 | _ -> None in
2474 let build_comma ia1 = A.EComma ia1 in
2475 let match_metalist ea = None in
2476 let build_metalist (ida,leninfo,keep,inherited) = failwith "not possible" in
2477 let mktermval v = failwith "not possible" in
2478 let special_cases ea eas ebs = None in
2479 list_matcher match_dots build_dots match_comma build_comma
2480 match_metalist build_metalist mktermval
2481 special_cases enum_field X.distrf_enum_fields
2482 Lib_parsing_c.ii_of_enum_fields eas ebs
2483
2484and enum_field ida idb =
2485 X.all_bound (A.get_inherited ida) >&&>
2486 match A.unwrap ida, idb with
2487 A.Ident(id),(nameidb,None) ->
2488 ident_cpp DontKnow id nameidb >>= (fun id nameidb ->
2489 return ((A.Ident id) +> A.rewrap ida, (nameidb,None)))
2490 | A.Assignment(ea1,opa,ea2,init),(nameidb,Some(opbi,eb2)) ->
2491 (match A.unwrap ea1 with
2492 A.Ident(id) ->
2493 ident_cpp DontKnow id nameidb >>= (fun id nameidb ->
2494 expression ea2 eb2 >>= (fun ea2 eb2 ->
2495 tokenf opa opbi >>= (fun opa opbi -> (* only one kind of assignop *)
2496 return (
2497 (A.Assignment((A.Ident(id))+>A.rewrap ea1,opa,ea2,init)) +>
2498 A.rewrap ida,
2499 (nameidb,Some(opbi,eb2))))))
2500 | _ -> failwith "not possible")
2501 | _ -> failwith "not possible"
34e49164
C
2502
2503(* ------------------------------------------------------------------------- *)
ae4735db
C
2504and (fullType: (A.fullType, Ast_c.fullType) matcher) =
2505 fun typa typb ->
2506 X.optional_qualifier_flag (fun optional_qualifier ->
34e49164
C
2507 X.all_bound (A.get_inherited typa) >&&>
2508 match A.unwrap typa, typb with
2509 | A.Type(cv,ty1), ((qu,il),ty2) ->
2510
ae4735db 2511 if qu.B.const && qu.B.volatile
34e49164
C
2512 then
2513 pr2_once
ae4735db 2514 ("warning: the type is both const & volatile but cocci " ^
34e49164
C
2515 "does not handle that");
2516
2517 (* Drop out the const/volatile part that has been matched.
2518 * This is because a SP can contain const T v; in which case
2519 * later in match_t_t when we encounter a T, we must not add in
2520 * the environment the whole type.
2521 *)
ae4735db 2522
34e49164
C
2523
2524 (match cv with
2525 (* "iso-by-absence" *)
ae4735db
C
2526 | None ->
2527 let do_stuff () =
2528 fullTypebis ty1 ((qu,il), ty2) >>= (fun ty1 fullty2 ->
34e49164
C
2529 return (
2530 (A.Type(None, ty1)) +> A.rewrap typa,
2531 fullty2
2532 ))
2533 in
2534 (match optional_qualifier, qu.B.const || qu.B.volatile with
2535 | false, false -> do_stuff ()
2536 | false, true -> fail
2537 | true, false -> do_stuff ()
ae4735db
C
2538 | true, true ->
2539 if !Flag.show_misc
34e49164
C
2540 then pr2_once "USING optional_qualifier builtin isomorphism";
2541 do_stuff()
2542 )
ae4735db
C
2543
2544
2545 | Some x ->
2546 (* todo: can be __const__ ? can be const & volatile so
2547 * should filter instead ?
34e49164 2548 *)
ae4735db
C
2549 (match term x, il with
2550 | A.Const, [i1] when qu.B.const ->
2551
2552 tokenf x i1 >>= (fun x i1 ->
2553 fullTypebis ty1 (Ast_c.nQ,ty2) >>= (fun ty1 (_, ty2) ->
34e49164
C
2554 return (
2555 (A.Type(Some x, ty1)) +> A.rewrap typa,
2556 ((qu, [i1]), ty2)
2557 )))
ae4735db
C
2558
2559 | A.Volatile, [i1] when qu.B.volatile ->
2560 tokenf x i1 >>= (fun x i1 ->
2561 fullTypebis ty1 (Ast_c.nQ,ty2) >>= (fun ty1 (_, ty2) ->
34e49164
C
2562 return (
2563 (A.Type(Some x, ty1)) +> A.rewrap typa,
2564 ((qu, [i1]), ty2)
2565 )))
ae4735db 2566
34e49164
C
2567 | _ -> fail
2568 )
2569 )
2570
ae4735db 2571 | A.DisjType typas, typb ->
34e49164
C
2572 typas +>
2573 List.fold_left (fun acc typa -> acc >|+|> (fullType typa typb)) fail
2574
2575 | A.OptType(_), _ | A.UniqueType(_), _
2576 -> failwith "not handling Opt/Unique on type"
2577 )
ae4735db 2578
34e49164
C
2579
2580(*
2581 * Why not (A.typeC, Ast_c.typeC) matcher ?
ae4735db 2582 * because when there is MetaType, we want that T record the whole type,
34e49164
C
2583 * including the qualifier, and so this type (and the new_il function in
2584 * preceding function).
2585*)
2586
ae4735db
C
2587and (fullTypebis: (A.typeC, Ast_c.fullType) matcher) =
2588 fun ta tb ->
2589 X.all_bound (A.get_inherited ta) >&&>
34e49164
C
2590 match A.unwrap ta, tb with
2591
2592 (* cas general *)
ae4735db 2593 | A.MetaType(ida,keep, inherited), typb ->
34e49164
C
2594 let max_min _ =
2595 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_type typb) in
ae4735db
C
2596 X.envf keep inherited (ida, B.MetaTypeVal typb, max_min) (fun () ->
2597 X.distrf_type ida typb >>= (fun ida typb ->
34e49164
C
2598 return (
2599 A.MetaType(ida,keep, inherited) +> A.rewrap ta,
2600 typb
2601 ))
2602 )
ae4735db
C
2603 | unwrap, (qub, typb) ->
2604 typeC ta typb >>= (fun ta typb ->
34e49164
C
2605 return (ta, (qub, typb))
2606 )
2607
faf9a90c 2608and simulate_signed ta basea stringsa signaopt tb baseb ii rebuilda =
34e49164
C
2609 (* In ii there is a list, sometimes of length 1 or 2 or 3.
2610 * And even if in baseb we have a Signed Int, that does not mean
2611 * that ii is of length 2, cos Signed is the default, so if in signa
ae4735db 2612 * we have Signed explicitely ? we cant "accrocher" this mcode to
34e49164
C
2613 * something :( So for the moment when there is signed in cocci,
2614 * we force that there is a signed in c too (done in pattern.ml).
2615 *)
2616 let signbopt, iibaseb = split_signb_baseb_ii (baseb, ii) in
2617
ae4735db 2618
34e49164
C
2619 (* handle some iso on type ? (cf complex C rule for possible implicit
2620 casting) *)
faf9a90c 2621 match basea, baseb with
1eddfd50
C
2622 | A.VoidType, B.Void
2623 | A.FloatType, B.FloatType (B.CFloat)
2624 | A.DoubleType, B.FloatType (B.CDouble)
2625 | A.SizeType, B.SizeType
2626 | A.SSizeType, B.SSizeType
2627 | A.PtrDiffType,B.PtrDiffType ->
ae4735db 2628 assert (signaopt =*= None);
faf9a90c 2629 let stringa = tuple_of_list1 stringsa in
ae4735db
C
2630 let (ibaseb) = tuple_of_list1 ii in
2631 tokenf stringa ibaseb >>= (fun stringa ibaseb ->
34e49164 2632 return (
faf9a90c 2633 (rebuilda ([stringa], signaopt)) +> A.rewrap ta,
34e49164
C
2634 (B.BaseType baseb, [ibaseb])
2635 ))
ae4735db
C
2636
2637 | A.CharType, B.IntType B.CChar when signaopt =*= None ->
faf9a90c 2638 let stringa = tuple_of_list1 stringsa in
34e49164 2639 let ibaseb = tuple_of_list1 ii in
ae4735db 2640 tokenf stringa ibaseb >>= (fun stringa ibaseb ->
34e49164 2641 return (
faf9a90c 2642 (rebuilda ([stringa], signaopt)) +> A.rewrap ta,
34e49164
C
2643 (B.BaseType (B.IntType B.CChar), [ibaseb])
2644 ))
ae4735db
C
2645
2646 | A.CharType,B.IntType (B.Si (_sign, B.CChar2)) when signaopt <> None ->
faf9a90c 2647 let stringa = tuple_of_list1 stringsa in
34e49164 2648 let ibaseb = tuple_of_list1 iibaseb in
ae4735db
C
2649 sign signaopt signbopt >>= (fun signaopt iisignbopt ->
2650 tokenf stringa ibaseb >>= (fun stringa ibaseb ->
34e49164 2651 return (
faf9a90c 2652 (rebuilda ([stringa], signaopt)) +> A.rewrap ta,
34e49164
C
2653 (B.BaseType (baseb), iisignbopt ++ [ibaseb])
2654 )))
ae4735db
C
2655
2656 | A.ShortType, B.IntType (B.Si (_, B.CShort))
2657 | A.IntType, B.IntType (B.Si (_, B.CInt))
34e49164 2658 | A.LongType, B.IntType (B.Si (_, B.CLong)) ->
faf9a90c 2659 let stringa = tuple_of_list1 stringsa in
ae4735db
C
2660 (match iibaseb with
2661 | [] ->
34e49164
C
2662 (* iso-by-presence ? *)
2663 (* when unsigned int in SP, allow have just unsigned in C ? *)
faf9a90c 2664 if mcode_contain_plus (mcodekind stringa)
34e49164 2665 then fail
ae4735db
C
2666 else
2667
2668 sign signaopt signbopt >>= (fun signaopt iisignbopt ->
34e49164 2669 return (
faf9a90c 2670 (rebuilda ([stringa], signaopt)) +> A.rewrap ta,
34e49164
C
2671 (B.BaseType (baseb), iisignbopt ++ [])
2672 ))
34e49164 2673
ae4735db
C
2674
2675 | [x;y] ->
2676 pr2_once
34e49164
C
2677 "warning: long int or short int not handled by ast_cocci";
2678 fail
2679
ae4735db
C
2680 | [ibaseb] ->
2681 sign signaopt signbopt >>= (fun signaopt iisignbopt ->
2682 tokenf stringa ibaseb >>= (fun stringa ibaseb ->
34e49164 2683 return (
faf9a90c 2684 (rebuilda ([stringa], signaopt)) +> A.rewrap ta,
34e49164
C
2685 (B.BaseType (baseb), iisignbopt ++ [ibaseb])
2686 )))
2687 | _ -> raise Impossible
2688
2689 )
2690
ae4735db 2691
faf9a90c
C
2692 | A.LongLongType, B.IntType (B.Si (_, B.CLongLong)) ->
2693 let (string1a,string2a) = tuple_of_list2 stringsa in
ae4735db
C
2694 (match iibaseb with
2695 [ibase1b;ibase2b] ->
2696 sign signaopt signbopt >>= (fun signaopt iisignbopt ->
2697 tokenf string1a ibase1b >>= (fun base1a ibase1b ->
2698 tokenf string2a ibase2b >>= (fun base2a ibase2b ->
faf9a90c
C
2699 return (
2700 (rebuilda ([base1a;base2a], signaopt)) +> A.rewrap ta,
2701 (B.BaseType (baseb), iisignbopt ++ [ibase1b;ibase2b])
2702 ))))
2703 | [] -> fail (* should something be done in this case? *)
2704 | _ -> raise Impossible)
2705
2706
ae4735db
C
2707 | _, B.FloatType B.CLongDouble
2708 ->
2709 pr2_once
faf9a90c 2710 "warning: long double not handled by ast_cocci";
34e49164 2711 fail
485bce71 2712
1eddfd50
C
2713 | _, (B.Void|B.FloatType _|B.IntType _
2714 |B.SizeType|B.SSizeType|B.PtrDiffType) -> fail
485bce71 2715
faf9a90c
C
2716and simulate_signed_meta ta basea signaopt tb baseb ii rebuilda =
2717 (* In ii there is a list, sometimes of length 1 or 2 or 3.
2718 * And even if in baseb we have a Signed Int, that does not mean
2719 * that ii is of length 2, cos Signed is the default, so if in signa
ae4735db 2720 * we have Signed explicitely ? we cant "accrocher" this mcode to
faf9a90c
C
2721 * something :( So for the moment when there is signed in cocci,
2722 * we force that there is a signed in c too (done in pattern.ml).
2723 *)
2724 let signbopt, iibaseb = split_signb_baseb_ii (baseb, ii) in
2725
ae4735db
C
2726 let match_to_type rebaseb =
2727 sign signaopt signbopt >>= (fun signaopt iisignbopt ->
faf9a90c 2728 let fta = A.rewrap basea (A.Type(None,basea)) in
b1b2de81 2729 let ftb = Ast_c.nQ,(B.BaseType (rebaseb), iibaseb) in
faf9a90c
C
2730 fullType fta ftb >>= (fun fta (_,tb) ->
2731 (match A.unwrap fta,tb with
2732 A.Type(_,basea), (B.BaseType baseb, ii) ->
faf9a90c
C
2733 return (
2734 (rebuilda (basea, signaopt)) +> A.rewrap ta,
b1b2de81 2735 (B.BaseType (baseb), iisignbopt ++ ii)
faf9a90c
C
2736 )
2737 | _ -> failwith "not possible"))) in
ae4735db 2738
faf9a90c
C
2739 (* handle some iso on type ? (cf complex C rule for possible implicit
2740 casting) *)
2741 match baseb with
2742 | B.IntType (B.Si (_sign, B.CChar2)) ->
2743 match_to_type (B.IntType B.CChar)
ae4735db 2744
faf9a90c 2745 | B.IntType (B.Si (_, ty)) ->
ae4735db 2746 (match iibaseb with
faf9a90c
C
2747 | [] -> fail (* metavariable has to match something *)
2748
b1b2de81 2749 | _ -> match_to_type (B.IntType (B.Si (B.Signed, ty)))
34e49164 2750
faf9a90c
C
2751 )
2752
1eddfd50
C
2753 | (B.Void|B.FloatType _|B.IntType _
2754 |B.SizeType|B.SSizeType|B.PtrDiffType) -> fail
faf9a90c 2755
ae4735db
C
2756and (typeC: (A.typeC, Ast_c.typeC) matcher) =
2757 fun ta tb ->
faf9a90c 2758 match A.unwrap ta, tb with
ae4735db 2759 | A.BaseType (basea,stringsa), (B.BaseType baseb, ii) ->
faf9a90c
C
2760 simulate_signed ta basea stringsa None tb baseb ii
2761 (function (stringsa, signaopt) -> A.BaseType (basea,stringsa))
ae4735db 2762 | A.SignedT (signaopt, Some basea), (B.BaseType baseb, ii) ->
faf9a90c
C
2763 (match A.unwrap basea with
2764 A.BaseType (basea1,strings1) ->
2765 simulate_signed ta basea1 strings1 (Some signaopt) tb baseb ii
2766 (function (strings1, Some signaopt) ->
2767 A.SignedT
2768 (signaopt,
2769 Some (A.rewrap basea (A.BaseType (basea1,strings1))))
2770 | _ -> failwith "not possible")
2771 | A.MetaType(ida,keep,inherited) ->
2772 simulate_signed_meta ta basea (Some signaopt) tb baseb ii
2773 (function (basea, Some signaopt) ->
2774 A.SignedT(signaopt,Some basea)
2775 | _ -> failwith "not possible")
2776 | _ -> failwith "not possible")
ae4735db 2777 | A.SignedT (signa,None), (B.BaseType baseb, ii) ->
34e49164
C
2778 let signbopt, iibaseb = split_signb_baseb_ii (baseb, ii) in
2779 (match iibaseb, baseb with
ae4735db
C
2780 | [], B.IntType (B.Si (_sign, B.CInt)) ->
2781 sign (Some signa) signbopt >>= (fun signaopt iisignbopt ->
34e49164
C
2782 match signaopt with
2783 | None -> raise Impossible
ae4735db 2784 | Some signa ->
34e49164 2785 return (
faf9a90c 2786 (A.SignedT (signa,None)) +> A.rewrap ta,
34e49164
C
2787 (B.BaseType baseb, iisignbopt)
2788 )
2789 )
2790 | _ -> fail
2791 )
2792
2793
2794
2795 (* todo? iso with array *)
ae4735db
C
2796 | A.Pointer (typa, iamult), (B.Pointer typb, ii) ->
2797 let (ibmult) = tuple_of_list1 ii in
2798 fullType typa typb >>= (fun typa typb ->
2799 tokenf iamult ibmult >>= (fun iamult ibmult ->
34e49164
C
2800 return (
2801 (A.Pointer (typa, iamult)) +> A.rewrap ta,
2802 (B.Pointer typb, [ibmult])
2803 )))
2804
ae4735db
C
2805 | A.FunctionType(allminus,tyaopt,lpa,paramsa,rpa),
2806 (B.FunctionType(tyb, (paramsb, (isvaargs, iidotsb))), ii) ->
34e49164
C
2807
2808 let (lpb, rpb) = tuple_of_list2 ii in
ae4735db 2809 if isvaargs
34e49164
C
2810 then
2811 pr2_once
2812 ("Not handling well variable length arguments func. "^
2813 "You have been warned");
ae4735db
C
2814 tokenf lpa lpb >>= (fun lpa lpb ->
2815 tokenf rpa rpb >>= (fun rpa rpb ->
2816 fullType_optional_allminus allminus tyaopt tyb >>= (fun tyaopt tyb ->
34e49164 2817 parameters (seqstyle paramsa) (A.undots paramsa) paramsb >>=
ae4735db 2818 (fun paramsaundots paramsb ->
34e49164
C
2819 let paramsa = redots paramsa paramsaundots in
2820 return (
2821 (A.FunctionType(allminus,tyaopt,lpa,paramsa,rpa) +> A.rewrap ta,
2822 (B.FunctionType(tyb, (paramsb, (isvaargs, iidotsb))), [lpb;rpb])
2823 )
2824 )))))
34e49164 2825
34e49164 2826
ae4735db
C
2827
2828
2829
2830 | A.FunctionPointer(tya,lp1a,stara,rp1a,lp2a,paramsa,rp2a),
34e49164
C
2831 (B.ParenType t1, ii) ->
2832 let (lp1b, rp1b) = tuple_of_list2 ii in
2833 let (qu1b, t1b) = t1 in
2834 (match t1b with
ae4735db 2835 | B.Pointer t2, ii ->
34e49164
C
2836 let (starb) = tuple_of_list1 ii in
2837 let (qu2b, t2b) = t2 in
2838 (match t2b with
ae4735db 2839 | B.FunctionType (tyb, (paramsb, (isvaargs, iidotsb))), ii ->
34e49164
C
2840 let (lp2b, rp2b) = tuple_of_list2 ii in
2841
2842 if isvaargs
2843 then
2844 pr2_once
2845 ("Not handling well variable length arguments func. "^
2846 "You have been warned");
2847
ae4735db
C
2848 fullType tya tyb >>= (fun tya tyb ->
2849 tokenf lp1a lp1b >>= (fun lp1a lp1b ->
2850 tokenf rp1a rp1b >>= (fun rp1a rp1b ->
2851 tokenf lp2a lp2b >>= (fun lp2a lp2b ->
2852 tokenf rp2a rp2b >>= (fun rp2a rp2b ->
2853 tokenf stara starb >>= (fun stara starb ->
34e49164 2854 parameters (seqstyle paramsa) (A.undots paramsa) paramsb >>=
ae4735db 2855 (fun paramsaundots paramsb ->
34e49164
C
2856 let paramsa = redots paramsa paramsaundots in
2857
ae4735db
C
2858 let t2 =
2859 (qu2b,
34e49164 2860 (B.FunctionType (tyb, (paramsb, (isvaargs, iidotsb))),
ae4735db 2861 [lp2b;rp2b]))
34e49164 2862 in
ae4735db 2863 let t1 =
34e49164
C
2864 (qu1b,
2865 (B.Pointer t2, [starb]))
2866 in
ae4735db 2867
34e49164
C
2868 return (
2869 (A.FunctionPointer(tya,lp1a,stara,rp1a,lp2a,paramsa,rp2a))
2870 +> A.rewrap ta,
2871 (B.ParenType t1, [lp1b;rp1b])
2872 )
2873 )))))))
2874
2875
2876
2877 | _ -> fail
2878 )
2879 | _ -> fail
2880 )
ae4735db
C
2881
2882
34e49164
C
2883
2884 (* todo: handle the iso on optionnal size specifification ? *)
ae4735db 2885 | A.Array (typa, ia1, eaopt, ia2), (B.Array (ebopt, typb), ii) ->
34e49164 2886 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
2887 fullType typa typb >>= (fun typa typb ->
2888 option expression eaopt ebopt >>= (fun eaopt ebopt ->
2889 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
2890 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
34e49164
C
2891 return (
2892 (A.Array (typa, ia1, eaopt, ia2)) +> A.rewrap ta,
2893 (B.Array (ebopt, typb), [ib1;ib2])
2894 )))))
2895
2896
2897 (* todo: could also match a Struct that has provided a name *)
2898 (* This is for the case where the SmPL code contains "struct x", without
2899 a definition. In this case, the name field is always present.
2900 This case is also called from the case for A.StructUnionDef when
2901 a name is present in the C code. *)
ae4735db 2902 | A.StructUnionName(sua, Some sa), (B.StructUnionName (sub, sb), ii) ->
34e49164
C
2903 (* sa is now an ident, not an mcode, old: ... && (term sa) =$= sb *)
2904 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db 2905 if equal_structUnion (term sua) sub
34e49164 2906 then
ae4735db
C
2907 ident DontKnow sa (sb, ib2) >>= (fun sa (sb, ib2) ->
2908 tokenf sua ib1 >>= (fun sua ib1 ->
34e49164
C
2909 return (
2910 (A.StructUnionName (sua, Some sa)) +> A.rewrap ta,
2911 (B.StructUnionName (sub, sb), [ib1;ib2])
2912 )))
2913 else fail
34e49164 2914
ae4735db
C
2915
2916 | A.StructUnionDef(ty, lba, declsa, rba),
2917 (B.StructUnion (sub, sbopt, declsb), ii) ->
34e49164
C
2918
2919 let (ii_sub_sb, lbb, rbb) =
2920 match ii with
2921 [iisub; lbb; rbb] -> (Common.Left iisub,lbb,rbb)
2922 | [iisub; iisb; lbb; rbb] -> (Common.Right (iisub,iisb),lbb,rbb)
2923 | _ -> failwith "list of length 3 or 4 expected" in
2924
2925 let process_type =
2926 match (sbopt,ii_sub_sb) with
2927 (None,Common.Left iisub) ->
2928 (* the following doesn't reconstruct the complete SP code, just
2929 the part that matched *)
2930 let rec loop s =
2931 match A.unwrap s with
2932 A.Type(None,ty) ->
2933 (match A.unwrap ty with
2934 A.StructUnionName(sua, None) ->
90aeb998
C
2935 (match (term sua, sub) with
2936 (A.Struct,B.Struct)
2937 | (A.Union,B.Union) -> return ((),())
2938 | _ -> fail) >>=
2939 (fun _ _ ->
2940 tokenf sua iisub >>= (fun sua iisub ->
2941 let ty =
2942 A.Type(None,
2943 A.StructUnionName(sua, None) +> A.rewrap ty)
2944 +> A.rewrap s in
2945 return (ty,[iisub])))
34e49164
C
2946 | _ -> fail)
2947 | A.DisjType(disjs) ->
2948 disjs +>
2949 List.fold_left (fun acc disj -> acc >|+|> (loop disj)) fail
2950 | _ -> fail in
2951 loop ty
ae4735db 2952
34e49164
C
2953 | (Some sb,Common.Right (iisub,iisb)) ->
2954
2955 (* build a StructUnionName from a StructUnion *)
2956 let fake_su = B.nQ, (B.StructUnionName (sub, sb), [iisub;iisb]) in
ae4735db
C
2957
2958 fullType ty fake_su >>= (fun ty fake_su ->
34e49164 2959 match fake_su with
ae4735db 2960 | _nQ, (B.StructUnionName (sub, sb), [iisub;iisb]) ->
34e49164
C
2961 return (ty, [iisub; iisb])
2962 | _ -> raise Impossible)
2963 | _ -> fail in
2964
2965 process_type
9f8e26f4 2966 >>= (fun ty ii_sub_sb ->
34e49164 2967
ae4735db
C
2968 tokenf lba lbb >>= (fun lba lbb ->
2969 tokenf rba rbb >>= (fun rba rbb ->
34e49164
C
2970 struct_fields (A.undots declsa) declsb >>=(fun undeclsa declsb ->
2971 let declsa = redots declsa undeclsa in
2972
2973 return (
2974 (A.StructUnionDef(ty, lba, declsa, rba)) +> A.rewrap ta,
2975 (B.StructUnion (sub, sbopt, declsb),ii_sub_sb@[lbb;rbb])
2976 )))))
2977
2978
ae4735db 2979 (* todo? handle isomorphisms ? because Unsigned Int can be match on a
34e49164 2980 * uint in the C code. But some CEs consists in renaming some types,
ae4735db
C
2981 * so we don't want apply isomorphisms every time.
2982 *)
b1b2de81
C
2983 | A.TypeName sa, (B.TypeName (nameb, typb), noii) ->
2984 assert (null noii);
2985
2986 (match nameb with
ae4735db 2987 | B.RegularName (sb, iidb) ->
b1b2de81 2988 let iidb1 = tuple_of_list1 iidb in
ae4735db 2989
b1b2de81 2990 if (term sa) =$= sb
ae4735db
C
2991 then
2992 tokenf sa iidb1 >>= (fun sa iidb1 ->
b1b2de81
C
2993 return (
2994 (A.TypeName sa) +> A.rewrap ta,
2995 (B.TypeName (B.RegularName (sb, [iidb1]), typb), noii)
2996 ))
2997 else fail
2998
2999 | B.CppConcatenatedName _ | B.CppVariadicName _ |B.CppIdentBuilder _
3000 -> raise Todo
3001 )
3002
34e49164 3003
f59c9fb7 3004 | _, (B.NoType, ii) -> fail
34e49164
C
3005 | _, (B.TypeOfExpr e, ii) -> fail
3006 | _, (B.TypeOfType e, ii) -> fail
485bce71
C
3007
3008 | _, (B.ParenType e, ii) -> fail (* todo ?*)
c491d8ee 3009 | A.EnumName(en,Some namea), (B.EnumName nameb, ii) ->
faf9a90c 3010 let (ib1,ib2) = tuple_of_list2 ii in
ae4735db
C
3011 ident DontKnow namea (nameb, ib2) >>= (fun namea (nameb, ib2) ->
3012 tokenf en ib1 >>= (fun en ib1 ->
faf9a90c 3013 return (
c491d8ee 3014 (A.EnumName (en, Some namea)) +> A.rewrap ta,
faf9a90c
C
3015 (B.EnumName nameb, [ib1;ib2])
3016 )))
3017
c491d8ee
C
3018 | A.EnumDef(ty, lba, idsa, rba),
3019 (B.Enum (sbopt, idsb), ii) ->
3020
3021 let (ii_sub_sb, lbb, rbb, comma_opt) =
3022 match ii with
3023 [iisub; lbb; rbb; comma_opt] ->
3024 (Common.Left iisub,lbb,rbb,comma_opt)
3025 | [iisub; iisb; lbb; rbb; comma_opt] ->
3026 (Common.Right (iisub,iisb),lbb,rbb,comma_opt)
3027 | _ -> failwith "list of length 4 or 5 expected" in
3028
3029 let process_type =
3030 match (sbopt,ii_sub_sb) with
3031 (None,Common.Left iisub) ->
3032 (* the following doesn't reconstruct the complete SP code, just
3033 the part that matched *)
3034 let rec loop s =
3035 match A.unwrap s with
3036 A.Type(None,ty) ->
3037 (match A.unwrap ty with
3038 A.EnumName(sua, None) ->
3039 tokenf sua iisub >>= (fun sua iisub ->
3040 let ty =
3041 A.Type(None,A.EnumName(sua, None) +> A.rewrap ty)
3042 +> A.rewrap s in
3043 return (ty,[iisub]))
3044 | _ -> fail)
3045 | A.DisjType(disjs) ->
3046 disjs +>
3047 List.fold_left (fun acc disj -> acc >|+|> (loop disj)) fail
3048 | _ -> fail in
3049 loop ty
3050
3051 | (Some sb,Common.Right (iisub,iisb)) ->
3052
3053 (* build an EnumName from an Enum *)
3054 let fake_su = B.nQ, (B.EnumName sb, [iisub;iisb]) in
3055
3056 fullType ty fake_su >>= (fun ty fake_su ->
3057 match fake_su with
3058 | _nQ, (B.EnumName sb, [iisub;iisb]) ->
3059 return (ty, [iisub; iisb])
3060 | _ -> raise Impossible)
3061 | _ -> fail in
3062
3063 process_type
3064 >>= (fun ty ii_sub_sb ->
3065
3066 tokenf lba lbb >>= (fun lba lbb ->
3067 tokenf rba rbb >>= (fun rba rbb ->
3068 let idsb = resplit_initialiser idsb [comma_opt] in
3069 let idsb =
3070 List.concat
3071 (List.map
3072 (function (elem,comma) -> [Left elem; Right [comma]])
3073 idsb) in
3074 enum_fields (A.undots idsa) idsb >>= (fun unidsa idsb ->
3075 let idsa = redots idsa unidsa in
3076 let idsb,iicomma =
3077 match List.rev idsb with
3078 (Right comma)::rest ->
3079 (Ast_c.unsplit_comma (List.rev rest),comma)
3080 | (Left _)::_ -> (Ast_c.unsplit_comma idsb,[]) (* possible *)
3081 | [] -> ([],[]) in
3082 return (
3083 (A.EnumDef(ty, lba, idsa, rba)) +> A.rewrap ta,
3084 (B.Enum (sbopt, idsb),ii_sub_sb@[lbb;rbb]@iicomma)
3085 ))
3086 )))
3087
485bce71
C
3088 | _, (B.Enum _, _) -> fail (* todo cocci ?*)
3089
3090 | _,
b1b2de81 3091 ((B.TypeName _ | B.StructUnionName (_, _) | B.EnumName _ |
faf9a90c
C
3092 B.StructUnion (_, _, _) |
3093 B.FunctionType _ | B.Array (_, _) | B.Pointer _ |
485bce71
C
3094 B.BaseType _),
3095 _)
3096 -> fail
3097
34e49164 3098
ae4735db 3099(* todo: iso on sign, if not mentioned then free. tochange?
34e49164
C
3100 * but that require to know if signed int because explicit
3101 * signed int, or because implicit signed int.
3102 *)
3103
ae4735db 3104and sign signa signb =
34e49164
C
3105 match signa, signb with
3106 | None, None -> return (None, [])
ae4735db 3107 | Some signa, Some (signb, ib) ->
34e49164 3108 if equal_sign (term signa) signb
ae4735db 3109 then tokenf signa ib >>= (fun signa ib ->
34e49164
C
3110 return (Some signa, [ib])
3111 )
3112 else fail
3113 | _, _ -> fail
3114
3115
ae4735db
C
3116and minusize_list iixs =
3117 iixs +> List.fold_left (fun acc ii ->
3118 acc >>= (fun xs ys ->
3119 tokenf minusizer ii >>= (fun minus ii ->
34e49164
C
3120 return (minus::xs, ii::ys)
3121 ))) (return ([],[]))
ae4735db 3122 >>= (fun _xsminys ys ->
34e49164
C
3123 return ((), List.rev ys)
3124 )
3125
ae4735db 3126and storage_optional_allminus allminus stoa (stob, iistob) =
34e49164 3127 (* "iso-by-absence" for storage, and return type. *)
ae4735db 3128 X.optional_storage_flag (fun optional_storage ->
34e49164 3129 match stoa, stob with
ae4735db
C
3130 | None, (stobis, inline) ->
3131 let do_minus () =
3132 if allminus
3133 then
3134 minusize_list iistob >>= (fun () iistob ->
34e49164
C
3135 return (None, (stob, iistob))
3136 )
3137 else return (None, (stob, iistob))
3138 in
3139
3140 (match optional_storage, stobis with
3141 | false, B.NoSto -> do_minus ()
3142 | false, _ -> fail
3143 | true, B.NoSto -> do_minus ()
ae4735db
C
3144 | true, _ ->
3145 if !Flag.show_misc
34e49164
C
3146 then pr2_once "USING optional_storage builtin isomorphism";
3147 do_minus()
3148 )
3149
ae4735db 3150 | Some x, ((stobis, inline)) ->
34e49164 3151 if equal_storage (term x) stobis
ae4735db 3152 then
aa721442
C
3153 let rec loop acc = function
3154 [] -> fail
3155 | i1::iistob ->
90aeb998
C
3156 let str = B.str_of_info i1 in
3157 (match str with
3158 "static" | "extern" | "auto" | "register" ->
3159 (* not very elegant, but tokenf doesn't know what token to
3160 match with *)
3161 tokenf x i1 >>= (fun x i1 ->
3162 let rebuilt = (List.rev acc) @ i1 :: iistob in
3163 return (Some x, ((stobis, inline), rebuilt)))
3164 | _ -> loop (i1::acc) iistob) in
aa721442 3165 loop [] iistob
34e49164
C
3166 else fail
3167 )
34e49164 3168
90aeb998
C
3169and inline_optional_allminus allminus inla (stob, iistob) =
3170 (* "iso-by-absence" for storage, and return type. *)
3171 X.optional_storage_flag (fun optional_storage ->
3172 match inla, stob with
3173 | None, (stobis, inline) ->
3174 let do_minus () =
3175 if allminus
3176 then
3177 minusize_list iistob >>= (fun () iistob ->
3178 return (None, (stob, iistob))
3179 )
3180 else return (None, (stob, iistob))
3181 in
3182
3183 if inline
3184 then
3185 if optional_storage
3186 then
3187 begin
3188 if !Flag.show_misc
3189 then pr2_once "USING optional_storage builtin isomorphism";
3190 do_minus()
3191 end
3192 else fail (* inline not in SP and present in C code *)
3193 else do_minus()
3194
3195 | Some x, ((stobis, inline)) ->
3196 if inline
3197 then
3198 let rec loop acc = function
3199 [] -> fail
3200 | i1::iistob ->
3201 let str = B.str_of_info i1 in
3202 (match str with
3203 "inline" ->
3204 (* not very elegant, but tokenf doesn't know what token to
3205 match with *)
3206 tokenf x i1 >>= (fun x i1 ->
3207 let rebuilt = (List.rev acc) @ i1 :: iistob in
3208 return (Some x, ((stobis, inline), rebuilt)))
3209 | _ -> loop (i1::acc) iistob) in
3210 loop [] iistob
3211 else fail (* SP has inline, but the C code does not *)
3212 )
3213
ae4735db
C
3214and fullType_optional_allminus allminus tya retb =
3215 match tya with
3216 | None ->
34e49164 3217 if allminus
ae4735db
C
3218 then
3219 X.distrf_type minusizer retb >>= (fun _x retb ->
34e49164
C
3220 return (None, retb)
3221 )
3222
3223 else return (None, retb)
ae4735db
C
3224 | Some tya ->
3225 fullType tya retb >>= (fun tya retb ->
34e49164
C
3226 return (Some tya, retb)
3227 )
3228
3229
3230
3231(*---------------------------------------------------------------------------*)
faf9a90c
C
3232
3233and compatible_base_type a signa b =
34e49164
C
3234 let ok = return ((),()) in
3235
faf9a90c 3236 match a, b with
1eddfd50
C
3237 | Type_cocci.VoidType, B.Void
3238 | Type_cocci.SizeType, B.SizeType
3239 | Type_cocci.SSizeType, B.SSizeType
3240 | Type_cocci.PtrDiffType, B.PtrDiffType ->
b1b2de81 3241 assert (signa =*= None);
faf9a90c 3242 ok
ae4735db 3243 | Type_cocci.CharType, B.IntType B.CChar when signa =*= None ->
faf9a90c 3244 ok
ae4735db
C
3245 | Type_cocci.CharType, B.IntType (B.Si (signb, B.CChar2)) ->
3246 compatible_sign signa signb
3247 | Type_cocci.ShortType, B.IntType (B.Si (signb, B.CShort)) ->
faf9a90c 3248 compatible_sign signa signb
ae4735db 3249 | Type_cocci.IntType, B.IntType (B.Si (signb, B.CInt)) ->
faf9a90c 3250 compatible_sign signa signb
ae4735db 3251 | Type_cocci.LongType, B.IntType (B.Si (signb, B.CLong)) ->
faf9a90c 3252 compatible_sign signa signb
ae4735db 3253 | _, B.IntType (B.Si (signb, B.CLongLong)) ->
faf9a90c
C
3254 pr2_once "no longlong in cocci";
3255 fail
3256 | Type_cocci.FloatType, B.FloatType B.CFloat ->
ae4735db 3257 assert (signa =*= None);
faf9a90c
C
3258 ok
3259 | Type_cocci.DoubleType, B.FloatType B.CDouble ->
ae4735db 3260 assert (signa =*= None);
faf9a90c 3261 ok
ae4735db 3262 | _, B.FloatType B.CLongDouble ->
faf9a90c
C
3263 pr2_once "no longdouble in cocci";
3264 fail
3265 | Type_cocci.BoolType, _ -> failwith "no booltype in C"
ae4735db 3266
1eddfd50
C
3267 | _, (B.Void|B.FloatType _|B.IntType _
3268 |B.SizeType|B.SSizeType|B.PtrDiffType) -> fail
faf9a90c
C
3269
3270and compatible_base_type_meta a signa qua b ii local =
3271 match a, b with
3272 | Type_cocci.MetaType(ida,keep,inherited),
ae4735db 3273 B.IntType (B.Si (signb, B.CChar2)) ->
faf9a90c
C
3274 compatible_sign signa signb >>= fun _ _ ->
3275 let newb = ((qua, (B.BaseType (B.IntType B.CChar),ii)),local) in
3276 compatible_type a newb
ae4735db 3277 | Type_cocci.MetaType(ida,keep,inherited), B.IntType (B.Si (signb, ty)) ->
faf9a90c
C
3278 compatible_sign signa signb >>= fun _ _ ->
3279 let newb =
3280 ((qua, (B.BaseType (B.IntType (B.Si (B.Signed, ty))),ii)),local) in
3281 compatible_type a newb
ae4735db 3282 | _, B.FloatType B.CLongDouble ->
faf9a90c
C
3283 pr2_once "no longdouble in cocci";
3284 fail
ae4735db 3285
1eddfd50
C
3286 | _, (B.Void|B.FloatType _|B.IntType _
3287 |B.SizeType|B.SSizeType|B.PtrDiffType) -> fail
485bce71
C
3288
3289
ae4735db 3290and compatible_type a (b,local) =
faf9a90c
C
3291 let ok = return ((),()) in
3292
3293 let rec loop = function
f59c9fb7
C
3294 | _, (qua, (B.NoType, _)) ->
3295 failwith "compatible_type: matching with NoType"
ae4735db 3296 | Type_cocci.BaseType a, (qua, (B.BaseType b,ii)) ->
faf9a90c 3297 compatible_base_type a None b
485bce71 3298
ae4735db 3299 | Type_cocci.SignedT (signa,None), (qua, (B.BaseType b,ii)) ->
faf9a90c 3300 compatible_base_type Type_cocci.IntType (Some signa) b
485bce71 3301
ae4735db 3302 | Type_cocci.SignedT (signa,Some ty), (qua, (B.BaseType b,ii)) ->
faf9a90c
C
3303 (match ty with
3304 Type_cocci.BaseType ty ->
3305 compatible_base_type ty (Some signa) b
3306 | Type_cocci.MetaType(ida,keep,inherited) ->
3307 compatible_base_type_meta ty (Some signa) qua b ii local
3308 | _ -> failwith "not possible")
485bce71 3309
ae4735db 3310 | Type_cocci.Pointer a, (qub, (B.Pointer b, ii)) ->
34e49164
C
3311 loop (a,b)
3312 | Type_cocci.FunctionPointer a, _ ->
3313 failwith
3314 "TODO: function pointer type doesn't store enough information to determine compatability"
3315 | Type_cocci.Array a, (qub, (B.Array (eopt, b),ii)) ->
3316 (* no size info for cocci *)
3317 loop (a,b)
e6509c05 3318 | Type_cocci.StructUnionName (sua, name),
ae4735db 3319 (qub, (B.StructUnionName (sub, sb),ii)) ->
e6509c05
C
3320 if equal_structUnion_type_cocci sua sub
3321 then structure_type_name name sb ii
faf9a90c 3322 else fail
e6509c05
C
3323 | Type_cocci.EnumName (name),
3324 (qub, (B.EnumName (sb),ii)) -> structure_type_name name sb ii
ae4735db 3325 | Type_cocci.TypeName sa, (qub, (B.TypeName (namesb, _typb),noii)) ->
b1b2de81 3326 let sb = Ast_c.str_of_name namesb in
ae4735db 3327 if sa =$= sb
34e49164
C
3328 then ok
3329 else fail
3330
ae4735db
C
3331 | Type_cocci.ConstVol (qua, a), (qub, b) ->
3332 if (fst qub).B.const && (fst qub).B.volatile
34e49164
C
3333 then
3334 begin
3335 pr2_once ("warning: the type is both const & volatile but cocci " ^
3336 "does not handle that");
3337 fail
3338 end
ae4735db
C
3339 else
3340 if
3341 (match qua with
34e49164
C
3342 | Type_cocci.Const -> (fst qub).B.const
3343 | Type_cocci.Volatile -> (fst qub).B.volatile
3344 )
3345 then loop (a,(Ast_c.nQ, b))
3346 else fail
3347
ae4735db 3348 | Type_cocci.MetaType (ida,keep,inherited), typb ->
34e49164
C
3349 let max_min _ =
3350 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_type typb) in
3351 X.envf keep inherited (A.make_mcode ida, B.MetaTypeVal typb, max_min)
3352 (fun () -> ok
3353 )
3354
3355 (* subtil: must be after the MetaType case *)
ae4735db 3356 | a, (qub, (B.TypeName (_namesb, Some b), noii)) ->
34e49164
C
3357 (* kind of typedef iso *)
3358 loop (a,b)
3359
34e49164
C
3360 (* for metavariables of type expression *^* *)
3361 | Type_cocci.Unknown , _ -> ok
3362
485bce71
C
3363 | (_,
3364 (_,
3365 ((
3366 B.TypeOfType _|B.TypeOfExpr _|B.ParenType _|
3367 B.EnumName _|B.StructUnion (_, _, _)|B.Enum (_, _)
3368 ),
3369 _))) -> fail
3370
3371 | (_,
3372 (_,
3373 ((
3374 B.StructUnionName (_, _)|
3375 B.FunctionType _|
3376 B.Array (_, _)|B.Pointer _|B.TypeName _|
3377 B.BaseType _
3378 ),
3379 _))) -> fail
3380
e6509c05
C
3381and structure_type_name nm sb ii =
3382 match nm with
3383 Type_cocci.NoName -> ok
3384 | Type_cocci.Name sa ->
3385 if sa =$= sb
3386 then ok
3387 else fail
3388 | Type_cocci.MV(ida,keep,inherited) ->
3389 (* degenerate version of MetaId, no transformation possible *)
3390 let (ib1, ib2) = tuple_of_list2 ii in
3391 let max_min _ = Lib_parsing_c.lin_col_by_pos [ib2] in
3392 let mida = A.make_mcode ida in
3393 X.envf keep inherited (mida, B.MetaIdVal (sb,[]), max_min)
3394 (fun () -> ok)
485bce71
C
3395
3396 in
34e49164
C
3397 loop (a,b)
3398
ae4735db 3399and compatible_sign signa signb =
34e49164
C
3400 let ok = return ((),()) in
3401 match signa, signb with
ae4735db 3402 | None, B.Signed
34e49164
C
3403 | Some Type_cocci.Signed, B.Signed
3404 | Some Type_cocci.Unsigned, B.UnSigned
3405 -> ok
3406 | _ -> fail
3407
3408
ae4735db 3409and equal_structUnion_type_cocci a b =
34e49164
C
3410 match a, b with
3411 | Type_cocci.Struct, B.Struct -> true
3412 | Type_cocci.Union, B.Union -> true
485bce71 3413 | _, (B.Struct | B.Union) -> false
34e49164
C
3414
3415
3416
3417(*---------------------------------------------------------------------------*)
ae4735db 3418and inc_file (a, before_after) (b, h_rel_pos) =
34e49164 3419
ae4735db 3420 let rec aux_inc (ass, bss) passed =
34e49164
C
3421 match ass, bss with
3422 | [], [] -> true
ae4735db 3423 | [A.IncDots], _ ->
34e49164
C
3424 let passed = List.rev passed in
3425
3426 (match before_after, !h_rel_pos with
3427 | IncludeNothing, _ -> true
ae4735db 3428 | IncludeMcodeBefore, Some x ->
34e49164
C
3429 List.mem passed (x.Ast_c.first_of)
3430
ae4735db 3431 | IncludeMcodeAfter, Some x ->
34e49164
C
3432 List.mem passed (x.Ast_c.last_of)
3433
3434 (* no info, maybe cos of a #include <xx.h> that was already in a .h *)
ae4735db 3435 | _, None -> false
34e49164
C
3436 )
3437
b1b2de81 3438 | (A.IncPath x)::xs, y::ys -> x =$= y && aux_inc (xs, ys) (x::passed)
34e49164 3439 | _ -> failwith "IncDots not in last place or other pb"
ae4735db 3440
34e49164
C
3441 in
3442
3443 match a, b with
ae4735db 3444 | A.Local ass, B.Local bss ->
34e49164 3445 aux_inc (ass, bss) []
ae4735db 3446 | A.NonLocal ass, B.NonLocal bss ->
34e49164
C
3447 aux_inc (ass, bss) []
3448 | _ -> false
ae4735db 3449
34e49164
C
3450
3451
3452(*---------------------------------------------------------------------------*)
3453
ae4735db
C
3454and (define_params: sequence ->
3455 (A.define_param list, (string B.wrap) B.wrap2 list) matcher) =
3456 fun seqstyle eas ebs ->
34e49164
C
3457 match seqstyle with
3458 | Unordered -> failwith "not handling ooo"
ae4735db 3459 | Ordered ->
34e49164
C
3460 define_paramsbis eas (Ast_c.split_comma ebs) >>= (fun eas ebs_splitted ->
3461 return (eas, (Ast_c.unsplit_comma ebs_splitted))
3462 )
3463
3464(* todo? facto code with argument and parameters ? *)
ae4735db 3465and define_paramsbis = fun eas ebs ->
c491d8ee
C
3466 let match_dots ea =
3467 match A.unwrap ea with
3468 A.DPdots(mcode) -> Some (mcode, None)
3469 | _ -> None in
3470 let build_dots (mcode, _optexpr) = A.DPdots(mcode) in
3471 let match_comma ea =
3472 match A.unwrap ea with
3473 A.DPComma ia1 -> Some ia1
3474 | _ -> None in
3475 let build_comma ia1 = A.DPComma ia1 in
3476 let match_metalist ea = None in
3477 let build_metalist (ida,leninfo,keep,inherited) = failwith "not possible" in
3478 let mktermval v = failwith "not possible" in
3479 let special_cases ea eas ebs = None in
3480 let no_ii x = failwith "not possible" in
3481 list_matcher match_dots build_dots match_comma build_comma
3482 match_metalist build_metalist mktermval
3483 special_cases define_parameter X.distrf_define_params no_ii eas ebs
3484
3485and define_parameter = fun parama paramb ->
3486 match A.unwrap parama, paramb with
3487 A.DParam ida, (idb, ii) ->
3488 let ib1 = tuple_of_list1 ii in
3489 ident DontKnow ida (idb, ib1) >>= (fun ida (idb, ib1) ->
3490 return ((A.DParam ida)+> A.rewrap parama,(idb, [ib1])))
3491 | (A.OptDParam _ | A.UniqueDParam _), _ ->
3492 failwith "handling Opt/Unique for define parameters"
3493 | A.DPcircles (_), ys -> raise Impossible (* in Ordered mode *)
3494 | _ -> fail
34e49164
C
3495
3496(*****************************************************************************)
3497(* Entry points *)
3498(*****************************************************************************)
3499
3500(* no global solution for positions here, because for a statement metavariable
3501we want a MetaStmtVal, and for the others, it's not clear what we want *)
3502
ae4735db
C
3503let rec (rule_elem_node: (A.rule_elem, Control_flow_c.node) matcher) =
3504 fun re node ->
3505 let rewrap x =
34e49164
C
3506 x >>= (fun a b -> return (A.rewrap re a, F.rewrap node b))
3507 in
3508 X.all_bound (A.get_inherited re) >&&>
3509
3510 rewrap (
3511 match A.unwrap re, F.unwrap node with
3512
3513 (* note: the order of the clauses is important. *)
3514
3515 | _, F.Enter | _, F.Exit | _, F.ErrorExit -> fail2()
3516
3517 (* the metaRuleElem contains just '-' information. We dont need to add
3518 * stuff in the environment. If we need stuff in environment, because
3519 * there is a + S somewhere, then this will be done via MetaStmt, not
ae4735db 3520 * via MetaRuleElem.
34e49164
C
3521 * Can match TrueNode/FalseNode/... so must be placed before those cases.
3522 *)
3523
ae4735db 3524 | A.MetaRuleElem(mcode,keep,inherited), unwrap_node ->
34e49164
C
3525 let default = A.MetaRuleElem(mcode,keep,inherited), unwrap_node in
3526 (match unwrap_node with
3527 | F.CaseNode _
951c7801 3528 | F.TrueNode | F.FalseNode | F.AfterNode
ae4735db
C
3529 | F.LoopFallThroughNode | F.FallThroughNode
3530 | F.InLoopNode ->
3531 if X.mode =*= PatternMode
3532 then return default
34e49164
C
3533 else
3534 if mcode_contain_plus (mcodekind mcode)
3535 then failwith "try add stuff on fake node"
3536 (* minusize or contextize a fake node is ok *)
3537 else return default
3538
ae4735db
C
3539 | F.EndStatement None ->
3540 if X.mode =*= PatternMode then return default
3541 else
34e49164
C
3542 (* DEAD CODE NOW ? only useful in -no_cocci_vs_c_3 ?
3543 if mcode_contain_plus (mcodekind mcode)
3544 then
3545 let fake_info = Ast_c.fakeInfo() in
ae4735db
C
3546 distrf distrf_node (mcodekind mcode)
3547 (F.EndStatement (Some fake_info))
34e49164
C
3548 else return unwrap_node
3549 *)
3550 raise Todo
ae4735db
C
3551
3552 | F.EndStatement (Some i1) ->
3553 tokenf mcode i1 >>= (fun mcode i1 ->
34e49164
C
3554 return (
3555 A.MetaRuleElem (mcode,keep, inherited),
3556 F.EndStatement (Some i1)
3557 ))
3558
ae4735db 3559 | F.FunHeader _ ->
b1b2de81 3560 if X.mode =*= PatternMode then return default
34e49164 3561 else failwith "a MetaRuleElem can't transform a headfunc"
ae4735db
C
3562 | _n ->
3563 if X.mode =*= PatternMode then return default
3564 else
3565 X.distrf_node (generalize_mcode mcode) node >>= (fun mcode node ->
34e49164
C
3566 return (
3567 A.MetaRuleElem(mcode,keep, inherited),
3568 F.unwrap node
3569 ))
3570 )
3571
3572
ae4735db
C
3573 (* rene cant have found that a state containing a fake/exit/... should be
3574 * transformed
34e49164
C
3575 * TODO: and F.Fake ?
3576 *)
3577 | _, F.EndStatement _ | _, F.CaseNode _
951c7801
C
3578 | _, F.TrueNode | _, F.FalseNode | _, F.AfterNode
3579 | _, F.FallThroughNode | _, F.LoopFallThroughNode
690d68d1 3580 | _, F.InLoopNode -> fail2()
34e49164
C
3581
3582 (* really ? diff between pattern.ml and transformation.ml *)
3583 | _, F.Fake -> fail2()
3584
3585
3586 (* cas general: a Meta can match everything. It matches only
3587 * "header"-statement. We transform only MetaRuleElem, not MetaStmt.
ae4735db 3588 * So can't have been called in transform.
34e49164
C
3589 *)
3590 | A.MetaStmt (ida,keep,metainfoMaybeTodo,inherited), F.Decl(_) -> fail
3591
ae4735db 3592 | A.MetaStmt (ida,keep,metainfoMaybeTodo,inherited), unwrap_node ->
34e49164
C
3593 (* todo: should not happen in transform mode *)
3594
3595 (match Control_flow_c.extract_fullstatement node with
ae4735db 3596 | Some stb ->
34e49164
C
3597 let max_min _ =
3598 Lib_parsing_c.lin_col_by_pos (Lib_parsing_c.ii_of_stmt stb) in
3599 X.envf keep inherited (ida, Ast_c.MetaStmtVal stb, max_min)
ae4735db 3600 (fun () ->
34e49164
C
3601 (* no need tag ida, we can't be called in transform-mode *)
3602 return (
3603 A.MetaStmt (ida, keep, metainfoMaybeTodo, inherited),
3604 unwrap_node
3605 )
3606 )
3607 | None -> fail
3608 )
3609
3610 (* not me?: *)
ae4735db 3611 | A.MetaStmtList _, _ ->
34e49164
C
3612 failwith "not handling MetaStmtList"
3613
3614 | A.TopExp ea, F.DefineExpr eb ->
ae4735db 3615 expression ea eb >>= (fun ea eb ->
34e49164
C
3616 return (
3617 A.TopExp ea,
3618 F.DefineExpr eb
3619 ))
ae4735db 3620
34e49164
C
3621 | A.TopExp ea, F.DefineType eb ->
3622 (match A.unwrap ea with
3623 A.TypeExp(ft) ->
ae4735db 3624 fullType ft eb >>= (fun ft eb ->
34e49164
C
3625 return (
3626 A.TopExp (A.rewrap ea (A.TypeExp(ft))),
3627 F.DefineType eb
3628 ))
3629 | _ -> fail)
ae4735db 3630
34e49164
C
3631
3632
3633 (* It is important to put this case before the one that fails because
3634 * of the lack of the counter part of a C construct in SmPL (for instance
3635 * there is not yet a CaseRange in SmPL). Even if SmPL don't handle
3636 * yet certain constructs, those constructs may contain expression
3637 * that we still want and can transform.
3638 *)
3639
ae4735db 3640 | A.Exp exp, nodeb ->
34e49164
C
3641
3642 (* kind of iso, initialisation vs affectation *)
ae4735db 3643 let node =
34e49164 3644 match A.unwrap exp, nodeb with
ae4735db 3645 | A.Assignment (ea, op, eb, true), F.Decl decl ->
34e49164
C
3646 initialisation_to_affectation decl +> F.rewrap node
3647 | _ -> node
3648 in
3649
3650
ae4735db 3651 (* Now keep fullstatement inside the control flow node,
34e49164 3652 * so that can then get in a MetaStmtVar the fullstatement to later
ae4735db 3653 * pp back when the S is in a +. But that means that
34e49164
C
3654 * Exp will match an Ifnode even if there is no such exp
3655 * inside the condition of the Ifnode (because the exp may
3656 * be deeper, in the then branch). So have to not visit
3657 * all inside a node anymore.
ae4735db 3658 *
34e49164 3659 * update: j'ai choisi d'accrocher au noeud du CFG à la
ae4735db 3660 * fois le fullstatement et le partialstatement et appeler le
34e49164
C
3661 * visiteur que sur le partialstatement.
3662 *)
ae4735db 3663 let expfn =
34e49164
C
3664 match Ast_cocci.get_pos re with
3665 | None -> expression
ae4735db
C
3666 | Some pos ->
3667 (fun ea eb ->
3668 let (max,min) =
34e49164
C
3669 Lib_parsing_c.max_min_by_pos (Lib_parsing_c.ii_of_expr eb) in
3670 let keep = Type_cocci.Unitary in
3671 let inherited = false in
3672 let max_min _ = failwith "no pos" in
3673 X.envf keep inherited (pos, B.MetaPosVal (min,max), max_min)
ae4735db 3674 (fun () ->
34e49164
C
3675 expression ea eb
3676 )
3677 )
3678 in
ae4735db 3679 X.cocciExp expfn exp node >>= (fun exp node ->
34e49164
C
3680 return (
3681 A.Exp exp,
3682 F.unwrap node
3683 )
3684 )
3685
ae4735db
C
3686 | A.Ty ty, nodeb ->
3687 X.cocciTy fullType ty node >>= (fun ty node ->
34e49164
C
3688 return (
3689 A.Ty ty,
3690 F.unwrap node
3691 )
3692 )
1be43e12 3693
ae4735db
C
3694 | A.TopInit init, nodeb ->
3695 X.cocciInit initialiser init node >>= (fun init node ->
1be43e12
C
3696 return (
3697 A.TopInit init,
3698 F.unwrap node
3699 )
3700 )
34e49164
C
3701
3702
3703 | A.FunHeader (mckstart, allminus, fninfoa, ida, oparen, paramsa, cparen),
b1b2de81 3704 F.FunHeader ({B.f_name = nameidb;
485bce71
C
3705 f_type = (retb, (paramsb, (isvaargs, iidotsb)));
3706 f_storage = stob;
3707 f_attr = attrs;
3708 f_body = body;
91eba41f 3709 f_old_c_style = oldstyle;
ae4735db 3710 }, ii) ->
485bce71 3711 assert (null body);
34e49164 3712
91eba41f
C
3713 if oldstyle <> None
3714 then pr2 "OLD STYLE DECL NOT WELL SUPPORTED";
3715
3716
34e49164
C
3717 (* fninfoa records the order in which the SP specified the various
3718 information, but this isn't taken into account in the matching.
3719 Could this be a problem for transformation? *)
3720 let stoa =
3721 match
3722 List.filter (function A.FStorage(s) -> true | _ -> false) fninfoa
3723 with [A.FStorage(s)] -> Some s | _ -> None in
ae4735db 3724 let tya =
34e49164
C
3725 match List.filter (function A.FType(s) -> true | _ -> false) fninfoa
3726 with [A.FType(t)] -> Some t | _ -> None in
3727
90aeb998
C
3728 let inla =
3729 match List.filter (function A.FInline(i) -> true | _ -> false) fninfoa
3730 with [A.FInline(i)] -> Some i | _ -> None in
34e49164
C
3731
3732 (match List.filter (function A.FAttr(a) -> true | _ -> false) fninfoa
3733 with [A.FAttr(a)] -> failwith "not checking attributes" | _ -> ());
3734
3735 (match ii with
ae4735db 3736 | ioparenb::icparenb::iifakestart::iistob ->
34e49164
C
3737
3738 (* maybe important to put ident as the first tokens to transform.
3739 * It's related to transform_proto. So don't change order
3740 * between the >>=.
3741 *)
ae4735db
C
3742 ident_cpp LocalFunction ida nameidb >>= (fun ida nameidb ->
3743 X.tokenf_mck mckstart iifakestart >>= (fun mckstart iifakestart ->
34e49164
C
3744 tokenf oparen ioparenb >>= (fun oparen ioparenb ->
3745 tokenf cparen icparenb >>= (fun cparen icparenb ->
ae4735db 3746 parameters (seqstyle paramsa)
34e49164 3747 (A.undots paramsa) paramsb >>=
ae4735db 3748 (fun paramsaundots paramsb ->
34e49164 3749 let paramsa = redots paramsa paramsaundots in
90aeb998
C
3750 inline_optional_allminus allminus
3751 inla (stob, iistob) >>= (fun inla (stob, iistob) ->
ae4735db
C
3752 storage_optional_allminus allminus
3753 stoa (stob, iistob) >>= (fun stoa (stob, iistob) ->
34e49164 3754 (
ae4735db
C
3755 if isvaargs
3756 then
34e49164
C
3757 pr2_once
3758 ("Not handling well variable length arguments func. "^
3759 "You have been warned");
3760 if allminus
3761 then minusize_list iidotsb
3762 else return ((),iidotsb)
ae4735db
C
3763 ) >>= (fun () iidotsb ->
3764
3765 fullType_optional_allminus allminus tya retb >>= (fun tya retb ->
34e49164 3766
ae4735db 3767 let fninfoa =
34e49164 3768 (match stoa with Some st -> [A.FStorage st] | None -> []) ++
90aeb998 3769 (match inla with Some i -> [A.FInline i] | None -> []) ++
34e49164
C
3770 (match tya with Some t -> [A.FType t] | None -> [])
3771
3772 in
3773
3774 return (
3775 A.FunHeader(mckstart,allminus,fninfoa,ida,oparen,
3776 paramsa,cparen),
b1b2de81 3777 F.FunHeader ({B.f_name = nameidb;
485bce71
C
3778 f_type = (retb, (paramsb, (isvaargs, iidotsb)));
3779 f_storage = stob;
3780 f_attr = attrs;
3781 f_body = body;
91eba41f 3782 f_old_c_style = oldstyle; (* TODO *)
485bce71 3783 },
b1b2de81 3784 ioparenb::icparenb::iifakestart::iistob)
34e49164 3785 )
90aeb998 3786 )))))))))
34e49164
C
3787 | _ -> raise Impossible
3788 )
3789
3790
3791
3792
3793
3794
ae4735db
C
3795 | A.Decl (mckstart,allminus,decla), F.Decl declb ->
3796 declaration (mckstart,allminus,decla) declb >>=
3797 (fun (mckstart,allminus,decla) declb ->
34e49164
C
3798 return (
3799 A.Decl (mckstart,allminus,decla),
3800 F.Decl declb
3801 ))
3802
3803
ae4735db
C
3804 | A.SeqStart mcode, F.SeqStart (st, level, i1) ->
3805 tokenf mcode i1 >>= (fun mcode i1 ->
34e49164 3806 return (
ae4735db 3807 A.SeqStart mcode,
34e49164
C
3808 F.SeqStart (st, level, i1)
3809 ))
3810
ae4735db
C
3811 | A.SeqEnd mcode, F.SeqEnd (level, i1) ->
3812 tokenf mcode i1 >>= (fun mcode i1 ->
34e49164
C
3813 return (
3814 A.SeqEnd mcode,
3815 F.SeqEnd (level, i1)
3816 ))
3817
ae4735db
C
3818 | A.ExprStatement (ea, ia1), F.ExprStatement (st, (Some eb, ii)) ->
3819 let ib1 = tuple_of_list1 ii in
3820 expression ea eb >>= (fun ea eb ->
3821 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
34e49164
C
3822 return (
3823 A.ExprStatement (ea, ia1),
3824 F.ExprStatement (st, (Some eb, [ib1]))
3825 )
3826 ))
3827
3828
ae4735db 3829 | A.IfHeader (ia1,ia2, ea, ia3), F.IfHeader (st, (eb,ii)) ->
34e49164 3830 let (ib1, ib2, ib3) = tuple_of_list3 ii in
ae4735db
C
3831 expression ea eb >>= (fun ea eb ->
3832 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3833 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3834 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
34e49164
C
3835 return (
3836 A.IfHeader (ia1, ia2, ea, ia3),
3837 F.IfHeader (st, (eb,[ib1;ib2;ib3]))
3838 )))))
3839
ae4735db
C
3840 | A.Else ia, F.Else ib ->
3841 tokenf ia ib >>= (fun ia ib ->
34e49164
C
3842 return (A.Else ia, F.Else ib)
3843 )
3844
ae4735db 3845 | A.WhileHeader (ia1, ia2, ea, ia3), F.WhileHeader (st, (eb, ii)) ->
34e49164 3846 let (ib1, ib2, ib3) = tuple_of_list3 ii in
ae4735db
C
3847 expression ea eb >>= (fun ea eb ->
3848 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3849 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3850 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
34e49164 3851 return (
ae4735db 3852 A.WhileHeader (ia1, ia2, ea, ia3),
34e49164
C
3853 F.WhileHeader (st, (eb, [ib1;ib2;ib3]))
3854 )))))
3855
ae4735db
C
3856 | A.DoHeader ia, F.DoHeader (st, ib) ->
3857 tokenf ia ib >>= (fun ia ib ->
34e49164 3858 return (
ae4735db 3859 A.DoHeader ia,
34e49164
C
3860 F.DoHeader (st, ib)
3861 ))
ae4735db 3862 | A.WhileTail (ia1,ia2,ea,ia3,ia4), F.DoWhileTail (eb, ii) ->
34e49164 3863 let (ib1, ib2, ib3, ib4) = tuple_of_list4 ii in
ae4735db
C
3864 expression ea eb >>= (fun ea eb ->
3865 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3866 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3867 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
3868 tokenf ia4 ib4 >>= (fun ia4 ib4 ->
34e49164 3869 return (
ae4735db 3870 A.WhileTail (ia1,ia2,ea,ia3,ia4),
34e49164
C
3871 F.DoWhileTail (eb, [ib1;ib2;ib3;ib4])
3872 ))))))
3873 | A.IteratorHeader (ia1, ia2, eas, ia3), F.MacroIterHeader (st, ((s,ebs),ii))
ae4735db 3874 ->
34e49164
C
3875 let (ib1, ib2, ib3) = tuple_of_list3 ii in
3876
ae4735db
C
3877 ident DontKnow ia1 (s, ib1) >>= (fun ia1 (s, ib1) ->
3878 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3879 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
3880 arguments (seqstyle eas) (A.undots eas) ebs >>= (fun easundots ebs ->
34e49164
C
3881 let eas = redots eas easundots in
3882 return (
ae4735db 3883 A.IteratorHeader (ia1, ia2, eas, ia3),
34e49164
C
3884 F.MacroIterHeader (st, ((s,ebs), [ib1;ib2;ib3]))
3885 )))))
3886
34e49164 3887
ae4735db
C
3888
3889 | A.ForHeader (ia1, ia2, ea1opt, ia3, ea2opt, ia4, ea3opt, ia5),
34e49164 3890 F.ForHeader (st, (((eb1opt,ib3s), (eb2opt,ib4s), (eb3opt,ib4vide)), ii))
ae4735db 3891 ->
34e49164
C
3892 assert (null ib4vide);
3893 let (ib1, ib2, ib5) = tuple_of_list3 ii in
3894 let ib3 = tuple_of_list1 ib3s in
3895 let ib4 = tuple_of_list1 ib4s in
ae4735db 3896
34e49164
C
3897 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3898 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3899 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
3900 tokenf ia4 ib4 >>= (fun ia4 ib4 ->
3901 tokenf ia5 ib5 >>= (fun ia5 ib5 ->
3902 option expression ea1opt eb1opt >>= (fun ea1opt eb1opt ->
3903 option expression ea2opt eb2opt >>= (fun ea2opt eb2opt ->
3904 option expression ea3opt eb3opt >>= (fun ea3opt eb3opt ->
3905 return (
3906 A.ForHeader (ia1, ia2, ea1opt, ia3, ea2opt, ia4, ea3opt, ia5),
3907 F.ForHeader (st, (((eb1opt,[ib3]), (eb2opt,[ib4]), (eb3opt,[])),
3908 [ib1;ib2;ib5]))
3909
3910 )))))))))
3911
3912
3913 | A.SwitchHeader(ia1,ia2,ea,ia3), F.SwitchHeader (st, (eb,ii)) ->
3914 let (ib1, ib2, ib3) = tuple_of_list3 ii in
ae4735db
C
3915 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3916 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3917 tokenf ia3 ib3 >>= (fun ia3 ib3 ->
3918 expression ea eb >>= (fun ea eb ->
34e49164 3919 return (
ae4735db 3920 A.SwitchHeader(ia1,ia2,ea,ia3),
34e49164
C
3921 F.SwitchHeader (st, (eb,[ib1;ib2;ib3]))
3922 )))))
ae4735db
C
3923
3924 | A.Break (ia1, ia2), F.Break (st, ((),ii)) ->
34e49164 3925 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
3926 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3927 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
34e49164 3928 return (
ae4735db 3929 A.Break (ia1, ia2),
34e49164
C
3930 F.Break (st, ((),[ib1;ib2]))
3931 )))
3932
ae4735db 3933 | A.Continue (ia1, ia2), F.Continue (st, ((),ii)) ->
34e49164 3934 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
3935 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3936 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
34e49164 3937 return (
ae4735db 3938 A.Continue (ia1, ia2),
34e49164
C
3939 F.Continue (st, ((),[ib1;ib2]))
3940 )))
3941
ae4735db 3942 | A.Return (ia1, ia2), F.Return (st, ((),ii)) ->
34e49164 3943 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
3944 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3945 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
34e49164 3946 return (
ae4735db 3947 A.Return (ia1, ia2),
34e49164
C
3948 F.Return (st, ((),[ib1;ib2]))
3949 )))
3950
ae4735db 3951 | A.ReturnExpr (ia1, ea, ia2), F.ReturnExpr (st, (eb, ii)) ->
34e49164 3952 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
3953 tokenf ia1 ib1 >>= (fun ia1 ib1 ->
3954 tokenf ia2 ib2 >>= (fun ia2 ib2 ->
3955 expression ea eb >>= (fun ea eb ->
34e49164 3956 return (
ae4735db 3957 A.ReturnExpr (ia1, ea, ia2),
34e49164
C
3958 F.ReturnExpr (st, (eb, [ib1;ib2]))
3959 ))))
3960
3961
3962
ae4735db 3963 | A.Include(incla,filea),
485bce71
C
3964 F.Include {B.i_include = (fileb, ii);
3965 B.i_rel_pos = h_rel_pos;
3966 B.i_is_in_ifdef = inifdef;
3967 B.i_content = copt;
3968 } ->
b1b2de81 3969 assert (copt =*= None);
ae4735db
C
3970
3971 let include_requirment =
34e49164 3972 match mcodekind incla, mcodekind filea with
ae4735db 3973 | A.CONTEXT (_, A.BEFORE _), _ ->
34e49164 3974 IncludeMcodeBefore
ae4735db 3975 | _, A.CONTEXT (_, A.AFTER _) ->
34e49164 3976 IncludeMcodeAfter
ae4735db 3977 | _ ->
34e49164
C
3978 IncludeNothing
3979 in
3980
ae4735db 3981 let (inclb, iifileb) = tuple_of_list2 ii in
34e49164 3982 if inc_file (term filea, include_requirment) (fileb, h_rel_pos)
ae4735db
C
3983 then
3984 tokenf incla inclb >>= (fun incla inclb ->
3985 tokenf filea iifileb >>= (fun filea iifileb ->
34e49164
C
3986 return (
3987 A.Include(incla, filea),
485bce71
C
3988 F.Include {B.i_include = (fileb, [inclb;iifileb]);
3989 B.i_rel_pos = h_rel_pos;
3990 B.i_is_in_ifdef = inifdef;
3991 B.i_content = copt;
3992 }
34e49164
C
3993 )))
3994 else fail
3995
3a314143
C
3996 | A.Undef(undefa,ida), F.DefineHeader ((idb, ii), B.Undef) ->
3997 let (defineb, iidb, ieol) = tuple_of_list3 ii in
3998 ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
3999 tokenf undefa defineb >>= (fun undefa defineb ->
4000 return (
4001 A.Undef(undefa,ida),
4002 F.DefineHeader ((idb,[defineb;iidb;ieol]),B.Undef)
4003 ))
4004 )
34e49164
C
4005
4006
4007 | A.DefineHeader(definea,ida,params), F.DefineHeader ((idb, ii), defkind) ->
4008 let (defineb, iidb, ieol) = tuple_of_list3 ii in
ae4735db
C
4009 ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
4010 tokenf definea defineb >>= (fun definea defineb ->
34e49164 4011 (match A.unwrap params, defkind with
ae4735db 4012 | A.NoParams, B.DefineVar ->
34e49164 4013 return (
ae4735db 4014 A.NoParams +> A.rewrap params,
34e49164
C
4015 B.DefineVar
4016 )
ae4735db 4017 | A.DParams(lpa,eas,rpa), (B.DefineFunc (ebs, ii)) ->
34e49164 4018 let (lpb, rpb) = tuple_of_list2 ii in
ae4735db
C
4019 tokenf lpa lpb >>= (fun lpa lpb ->
4020 tokenf rpa rpb >>= (fun rpa rpb ->
34e49164 4021
ae4735db
C
4022 define_params (seqstyle eas) (A.undots eas) ebs >>=
4023 (fun easundots ebs ->
34e49164
C
4024 let eas = redots eas easundots in
4025 return (
4026 A.DParams (lpa,eas,rpa) +> A.rewrap params,
4027 B.DefineFunc (ebs,[lpb;rpb])
4028 )
4029 )))
4030 | _ -> fail
ae4735db 4031 ) >>= (fun params defkind ->
34e49164
C
4032 return (
4033 A.DefineHeader (definea, ida, params),
4034 F.DefineHeader ((idb,[defineb;iidb;ieol]),defkind)
4035 ))
4036 ))
4037
4038
ae4735db 4039 | A.Default(def,colon), F.Default (st, ((),ii)) ->
34e49164 4040 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
4041 tokenf def ib1 >>= (fun def ib1 ->
4042 tokenf colon ib2 >>= (fun colon ib2 ->
34e49164 4043 return (
ae4735db 4044 A.Default(def,colon),
34e49164
C
4045 F.Default (st, ((),[ib1;ib2]))
4046 )))
4047
ae4735db
C
4048
4049
4050 | A.Case(case,ea,colon), F.Case (st, (eb,ii)) ->
34e49164 4051 let (ib1, ib2) = tuple_of_list2 ii in
ae4735db
C
4052 tokenf case ib1 >>= (fun case ib1 ->
4053 expression ea eb >>= (fun ea eb ->
4054 tokenf colon ib2 >>= (fun colon ib2 ->
34e49164 4055 return (
ae4735db 4056 A.Case(case,ea,colon),
34e49164
C
4057 F.Case (st, (eb,[ib1;ib2]))
4058 ))))
4059
4060 (* only occurs in the predicates generated by asttomember *)
ae4735db 4061 | A.DisjRuleElem eas, _ ->
34e49164
C
4062 (eas +>
4063 List.fold_left (fun acc ea -> acc >|+|> (rule_elem_node ea node)) fail)
4064 >>= (fun ea eb -> return (A.unwrap ea,F.unwrap eb))
4065
4066 | _, F.ExprStatement (_, (None, ii)) -> fail (* happen ? *)
4067
b1b2de81
C
4068 | A.Label(id,dd), F.Label (st, nameb, ((),ii)) ->
4069 let (ib2) = tuple_of_list1 ii in
978fd7e5
C
4070 ident_cpp DontKnow id nameb >>= (fun ida nameb ->
4071 tokenf dd ib2 >>= (fun dd ib2 ->
4072 return (
4073 A.Label (ida,dd),
4074 F.Label (st,nameb, ((),[ib2]))
4075 )))
34e49164 4076
b1b2de81
C
4077 | A.Goto(goto,id,sem), F.Goto (st,nameb, ((),ii)) ->
4078 let (ib1,ib3) = tuple_of_list2 ii in
34e49164 4079 tokenf goto ib1 >>= (fun goto ib1 ->
b1b2de81 4080 ident_cpp DontKnow id nameb >>= (fun id nameb ->
34e49164
C
4081 tokenf sem ib3 >>= (fun sem ib3 ->
4082 return(
4083 A.Goto(goto,id,sem),
b1b2de81 4084 F.Goto (st,nameb, ((),[ib1;ib3]))
34e49164
C
4085 ))))
4086
4087 (* have not a counter part in coccinelle, for the moment *)
4088 (* todo?: print a warning at least ? *)
ae4735db 4089 | _, F.CaseRange _
34e49164 4090 | _, F.Asm _
34e49164
C
4091 | _, F.MacroTop _
4092 -> fail2()
4093
485bce71
C
4094 | _, (F.IfdefEndif _|F.IfdefElse _|F.IfdefHeader _)
4095 -> fail2 ()
4096
ae4735db 4097 | _,
485bce71
C
4098 (F.MacroStmt (_, _)| F.DefineDoWhileZeroHeader _| F.EndNode|F.TopNode)
4099 -> fail
ae4735db 4100 | _,
b1b2de81 4101 (F.Label (_, _, _)|F.Break (_, _)|F.Continue (_, _)|F.Default (_, _)|
485bce71
C
4102 F.Case (_, _)|F.Include _|F.Goto _|F.ExprStatement _|
4103 F.DefineType _|F.DefineExpr _|F.DefineTodo|
3a314143
C
4104 F.DefineHeader (_, _)|F.ReturnExpr (_, _)|F.Return (_, _)|
4105 F.MacroIterHeader (_, _)|
485bce71
C
4106 F.SwitchHeader (_, _)|F.ForHeader (_, _)|F.DoWhileTail _|F.DoHeader (_, _)|
4107 F.WhileHeader (_, _)|F.Else _|F.IfHeader (_, _)|
4108 F.SeqEnd (_, _)|F.SeqStart (_, _, _)|
4109 F.Decl _|F.FunHeader _)
4110 -> fail
4111
34e49164 4112
34e49164
C
4113 )
4114end
4115