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