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