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