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