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