Release coccinelle-0.1.1
[bpt/coccinelle.git] / parsing_cocci / ast0toast.ml
CommitLineData
34e49164
C
1(*
2* Copyright 2005-2008, Ecole des Mines de Nantes, University of Copenhagen
3* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
4* This file is part of Coccinelle.
5*
6* Coccinelle is free software: you can redistribute it and/or modify
7* it under the terms of the GNU General Public License as published by
8* the Free Software Foundation, according to version 2 of the License.
9*
10* Coccinelle is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
17*
18* The authors reserve the right to distribute this or future versions of
19* Coccinelle under other licenses.
20*)
21
22
23(* Arities matter for the minus slice, but not for the plus slice. *)
24
25(* + only allowed on code in a nest (in_nest = true). ? only allowed on
26rule_elems, and on subterms if the context is ? also. *)
27
28module Ast0 = Ast0_cocci
29module Ast = Ast_cocci
30module V0 = Visitor_ast0
31module V = Visitor_ast
32
33let unitary = Type_cocci.Unitary
34
35let ctr = ref 0
36let get_ctr _ =
37 let c = !ctr in
38 ctr := !ctr + 1;
39 c
40
41(* --------------------------------------------------------------------- *)
42(* Move plus tokens from the MINUS and CONTEXT structured nodes to the
43corresponding leftmost and rightmost mcodes *)
44
45let inline_mcodes =
46 let bind x y = () in
47 let option_default = () in
48 let mcode _ = () in
49 let do_nothing r k e =
50 k e;
51 let einfo = Ast0.get_info e in
52 match (Ast0.get_mcodekind e) with
53 Ast0.MINUS(replacements) ->
54 (match !replacements with
55 ([],_) -> ()
56 | replacements ->
57 let minus_try = function
58 (true,mc) ->
59 if List.for_all
60 (function
61 Ast0.MINUS(mreplacements) -> true | _ -> false)
62 mc
63 then
64 (List.iter
65 (function
66 Ast0.MINUS(mreplacements) ->
67 mreplacements := replacements
68 | _ -> ())
69 mc;
70 true)
71 else false
72 | _ -> false in
73 if not (minus_try(einfo.Ast0.attachable_start,
74 einfo.Ast0.mcode_start)
75 or
76 minus_try(einfo.Ast0.attachable_end,
77 einfo.Ast0.mcode_end))
78 then
79 failwith "minus tree should not have bad code on both sides")
80 | Ast0.CONTEXT(befaft)
81 | Ast0.MIXED(befaft) ->
82 let concat starter startinfo ender endinfo =
83 let lst =
84 match (starter,ender) with
85 ([],_) -> ender
86 | (_,[]) -> starter
87 | _ ->
88 if startinfo.Ast0.tline_end = endinfo.Ast0.tline_start
89 then (* put them in the same inner list *)
90 let last = List.hd (List.rev starter) in
91 let butlast = List.rev(List.tl(List.rev starter)) in
92 butlast @ (last@(List.hd ender)) :: (List.tl ender)
93 else starter @ ender in
94 (lst,
95 {endinfo with Ast0.tline_start = startinfo.Ast0.tline_start}) in
96 let attach_bef bef beforeinfo = function
97 (true,mcl) ->
98 List.iter
99 (function
100 Ast0.MINUS(mreplacements) ->
101 let (mrepl,tokeninfo) = !mreplacements in
102 mreplacements := concat bef beforeinfo mrepl tokeninfo
103 | Ast0.CONTEXT(mbefaft) ->
104 (match !mbefaft with
105 (Ast.BEFORE(mbef),mbeforeinfo,a) ->
106 let (newbef,newinfo) =
107 concat bef beforeinfo mbef mbeforeinfo in
108 mbefaft := (Ast.BEFORE(newbef),newinfo,a)
109 | (Ast.AFTER(maft),_,a) ->
110 mbefaft :=
111 (Ast.BEFOREAFTER(bef,maft),beforeinfo,a)
112 | (Ast.BEFOREAFTER(mbef,maft),mbeforeinfo,a) ->
113 let (newbef,newinfo) =
114 concat bef beforeinfo mbef mbeforeinfo in
115 mbefaft :=
116 (Ast.BEFOREAFTER(newbef,maft),newinfo,a)
117 | (Ast.NOTHING,_,a) ->
118 mbefaft := (Ast.BEFORE(bef),beforeinfo,a))
119 | _ -> failwith "unexpected annotation")
120 mcl
121 | _ ->
122 failwith
123 "context tree should not have bad code on both sides" in
124 let attach_aft aft afterinfo = function
125 (true,mcl) ->
126 List.iter
127 (function
128 Ast0.MINUS(mreplacements) ->
129 let (mrepl,tokeninfo) = !mreplacements in
130 mreplacements := concat mrepl tokeninfo aft afterinfo
131 | Ast0.CONTEXT(mbefaft) ->
132 (match !mbefaft with
133 (Ast.BEFORE(mbef),b,_) ->
134 mbefaft :=
135 (Ast.BEFOREAFTER(mbef,aft),b,afterinfo)
136 | (Ast.AFTER(maft),b,mafterinfo) ->
137 let (newaft,newinfo) =
138 concat maft mafterinfo aft afterinfo in
139 mbefaft := (Ast.AFTER(newaft),b,newinfo)
140 | (Ast.BEFOREAFTER(mbef,maft),b,mafterinfo) ->
141 let (newaft,newinfo) =
142 concat maft mafterinfo aft afterinfo in
143 mbefaft :=
144 (Ast.BEFOREAFTER(mbef,newaft),b,newinfo)
145 | (Ast.NOTHING,b,_) ->
146 mbefaft := (Ast.AFTER(aft),b,afterinfo))
147 | _ -> failwith "unexpected annotation")
148 mcl
149 | _ ->
150 failwith
151 "context tree should not have bad code on both sides" in
152 (match !befaft with
153 (Ast.BEFORE(bef),beforeinfo,_) ->
154 attach_bef bef beforeinfo
155 (einfo.Ast0.attachable_start,einfo.Ast0.mcode_start)
156 | (Ast.AFTER(aft),_,afterinfo) ->
157 attach_aft aft afterinfo
158 (einfo.Ast0.attachable_end,einfo.Ast0.mcode_end)
159 | (Ast.BEFOREAFTER(bef,aft),beforeinfo,afterinfo) ->
160 attach_bef bef beforeinfo
161 (einfo.Ast0.attachable_start,einfo.Ast0.mcode_start);
162 attach_aft aft afterinfo
163 (einfo.Ast0.attachable_end,einfo.Ast0.mcode_end)
164 | (Ast.NOTHING,_,_) -> ())
165 | Ast0.PLUS -> () in
166 V0.combiner bind option_default
167 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
168 mcode mcode mcode
169 do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
170 do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
171 do_nothing do_nothing do_nothing
172
173(* --------------------------------------------------------------------- *)
174(* For function declarations. Can't use the mcode at the root, because that
175might be mixed when the function contains ()s, where agglomeration of -s is
176not possible. *)
177
178let check_allminus =
179 let donothing r k e = k e in
180 let bind x y = x && y in
181 let option_default = true in
182 let mcode (_,_,_,mc,_) =
183 match mc with
184 Ast0.MINUS(r) -> let (plusses,_) = !r in plusses = []
185 | _ -> false in
186
187 (* special case for disj *)
188 let expression r k e =
189 match Ast0.unwrap e with
190 Ast0.DisjExpr(starter,expr_list,mids,ender) ->
191 List.for_all r.V0.combiner_expression expr_list
192 | _ -> k e in
193
194 let declaration r k e =
195 match Ast0.unwrap e with
196 Ast0.DisjDecl(starter,decls,mids,ender) ->
197 List.for_all r.V0.combiner_declaration decls
198 | _ -> k e in
199
200 let typeC r k e =
201 match Ast0.unwrap e with
202 Ast0.DisjType(starter,decls,mids,ender) ->
203 List.for_all r.V0.combiner_typeC decls
204 | _ -> k e in
205
206 let statement r k e =
207 match Ast0.unwrap e with
208 Ast0.Disj(starter,statement_dots_list,mids,ender) ->
209 List.for_all r.V0.combiner_statement_dots statement_dots_list
210 | _ -> k e in
211
212 V0.combiner bind option_default
213 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
214 mcode mcode mcode
215 donothing donothing donothing donothing donothing donothing
216 donothing expression typeC donothing donothing declaration
217 statement donothing donothing
218
219(* --------------------------------------------------------------------- *)
220(* --------------------------------------------------------------------- *)
221
222let get_option fn = function
223 None -> None
224 | Some x -> Some (fn x)
225
226(* --------------------------------------------------------------------- *)
227(* --------------------------------------------------------------------- *)
228(* Mcode *)
229
230let convert_info info =
231 { Ast.line = info.Ast0.line_start; Ast.column = info.Ast0.column;
232 Ast.strbef = info.Ast0.strings_before;
233 Ast.straft = info.Ast0.strings_after; }
234
235let convert_mcodekind = function
236 Ast0.MINUS(replacements) ->
237 let (replacements,_) = !replacements in
238 Ast.MINUS(Ast.NoPos,replacements)
239 | Ast0.PLUS -> Ast.PLUS
240 | Ast0.CONTEXT(befaft) ->
241 let (befaft,_,_) = !befaft in Ast.CONTEXT(Ast.NoPos,befaft)
242 | Ast0.MIXED(_) -> failwith "not possible for mcode"
243
244let pos_mcode(term,_,info,mcodekind,pos) =
245 (* avoids a recursion problem *)
246 (term,convert_info info,convert_mcodekind mcodekind,Ast.NoMetaPos)
247
248let mcode(term,_,info,mcodekind,pos) =
249 let pos =
250 match !pos with
251 Ast0.MetaPos(pos,constraints,per) ->
252 Ast.MetaPos(pos_mcode pos,constraints,per,unitary,false)
253 | _ -> Ast.NoMetaPos in
254 (term,convert_info info,convert_mcodekind mcodekind,pos)
255
256(* --------------------------------------------------------------------- *)
257(* Dots *)
258let wrap ast line isos =
259 {(Ast.make_term ast) with Ast.node_line = line;
260 Ast.iso_info = isos}
261
262let rewrap ast0 isos ast =
263 wrap ast ((Ast0.get_info ast0).Ast0.line_start) isos
264
265let no_isos = []
266
267(* no isos on tokens *)
268let tokenwrap (_,info,_,_) s ast = wrap ast info.Ast.line no_isos
269let iso_tokenwrap (_,info,_,_) s ast iso = wrap ast info.Ast.line iso
270
271let dots fn d =
272 rewrap d no_isos
273 (match Ast0.unwrap d with
274 Ast0.DOTS(x) -> Ast.DOTS(List.map fn x)
275 | Ast0.CIRCLES(x) -> Ast.CIRCLES(List.map fn x)
276 | Ast0.STARS(x) -> Ast.STARS(List.map fn x))
277
278(* --------------------------------------------------------------------- *)
279(* Identifier *)
280
281let rec do_isos l = List.map (function (nm,x) -> (nm,anything x)) l
282
283and ident i =
284 rewrap i (do_isos (Ast0.get_iso i))
285 (match Ast0.unwrap i with
286 Ast0.Id(name) -> Ast.Id(mcode name)
287 | Ast0.MetaId(name,constraints,_) ->
288 let constraints = List.map ident constraints in
289 Ast.MetaId(mcode name,constraints,unitary,false)
290 | Ast0.MetaFunc(name,constraints,_) ->
291 let constraints = List.map ident constraints in
292 Ast.MetaFunc(mcode name,constraints,unitary,false)
293 | Ast0.MetaLocalFunc(name,constraints,_) ->
294 let constraints = List.map ident constraints in
295 Ast.MetaLocalFunc(mcode name,constraints,unitary,false)
296 | Ast0.OptIdent(id) -> Ast.OptIdent(ident id)
297 | Ast0.UniqueIdent(id) -> Ast.UniqueIdent(ident id))
298
299(* --------------------------------------------------------------------- *)
300(* Expression *)
301
302and expression e =
303 let e1 =
304 rewrap e (do_isos (Ast0.get_iso e))
305 (match Ast0.unwrap e with
306 Ast0.Ident(id) -> Ast.Ident(ident id)
307 | Ast0.Constant(const) ->
308 Ast.Constant(mcode const)
309 | Ast0.FunCall(fn,lp,args,rp) ->
310 let fn = expression fn in
311 let lp = mcode lp in
312 let args = dots expression args in
313 let rp = mcode rp in
314 Ast.FunCall(fn,lp,args,rp)
315 | Ast0.Assignment(left,op,right,simple) ->
316 Ast.Assignment(expression left,mcode op,expression right,simple)
317 | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
318 let exp1 = expression exp1 in
319 let why = mcode why in
320 let exp2 = get_option expression exp2 in
321 let colon = mcode colon in
322 let exp3 = expression exp3 in
323 Ast.CondExpr(exp1,why,exp2,colon,exp3)
324 | Ast0.Postfix(exp,op) ->
325 Ast.Postfix(expression exp,mcode op)
326 | Ast0.Infix(exp,op) ->
327 Ast.Infix(expression exp,mcode op)
328 | Ast0.Unary(exp,op) ->
329 Ast.Unary(expression exp,mcode op)
330 | Ast0.Binary(left,op,right) ->
331 Ast.Binary(expression left,mcode op,expression right)
332 | Ast0.Nested(left,op,right) ->
333 Ast.Nested(expression left,mcode op,expression right)
334 | Ast0.Paren(lp,exp,rp) ->
335 Ast.Paren(mcode lp,expression exp,mcode rp)
336 | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
337 Ast.ArrayAccess(expression exp1,mcode lb,expression exp2,mcode rb)
338 | Ast0.RecordAccess(exp,pt,field) ->
339 Ast.RecordAccess(expression exp,mcode pt,ident field)
340 | Ast0.RecordPtAccess(exp,ar,field) ->
341 Ast.RecordPtAccess(expression exp,mcode ar,ident field)
342 | Ast0.Cast(lp,ty,rp,exp) ->
343 Ast.Cast(mcode lp,typeC ty,mcode rp,expression exp)
344 | Ast0.SizeOfExpr(szf,exp) ->
345 Ast.SizeOfExpr(mcode szf,expression exp)
346 | Ast0.SizeOfType(szf,lp,ty,rp) ->
347 Ast.SizeOfType(mcode szf, mcode lp,typeC ty,mcode rp)
348 | Ast0.TypeExp(ty) -> Ast.TypeExp(typeC ty)
349 | Ast0.MetaErr(name,constraints,_) ->
350 let constraints = List.map expression constraints in
351 Ast.MetaErr(mcode name,constraints,unitary,false)
352 | Ast0.MetaExpr(name,constraints,ty,form,_) ->
353 let constraints = List.map expression constraints in
354 Ast.MetaExpr(mcode name,constraints,unitary,ty,form,false)
355 | Ast0.MetaExprList(name,Some lenname,_) ->
356 Ast.MetaExprList(mcode name,Some (mcode lenname,unitary,false),
357 unitary,false)
358 | Ast0.MetaExprList(name,None,_) ->
359 Ast.MetaExprList(mcode name,None,unitary,false)
360 | Ast0.EComma(cm) -> Ast.EComma(mcode cm)
361 | Ast0.DisjExpr(_,exps,_,_) -> Ast.DisjExpr(List.map expression exps)
362 | Ast0.NestExpr(_,exp_dots,_,whencode,multi) ->
363 let whencode = get_option expression whencode in
364 Ast.NestExpr(dots expression exp_dots,whencode,multi)
365 | Ast0.Edots(dots,whencode) ->
366 let dots = mcode dots in
367 let whencode = get_option expression whencode in
368 Ast.Edots(dots,whencode)
369 | Ast0.Ecircles(dots,whencode) ->
370 let dots = mcode dots in
371 let whencode = get_option expression whencode in
372 Ast.Ecircles(dots,whencode)
373 | Ast0.Estars(dots,whencode) ->
374 let dots = mcode dots in
375 let whencode = get_option expression whencode in
376 Ast.Estars(dots,whencode)
377 | Ast0.OptExp(exp) -> Ast.OptExp(expression exp)
378 | Ast0.UniqueExp(exp) -> Ast.UniqueExp(expression exp)) in
379 if Ast0.get_test_exp e then Ast.set_test_exp e1 else e1
380
381and expression_dots ed = dots expression ed
382
383(* --------------------------------------------------------------------- *)
384(* Types *)
385
386and typeC t =
387 rewrap t (do_isos (Ast0.get_iso t))
388 (match Ast0.unwrap t with
389 Ast0.ConstVol(cv,ty) ->
390 let rec collect_disjs t =
391 match Ast0.unwrap t with
392 Ast0.DisjType(_,types,_,_) ->
393 if Ast0.get_iso t = []
394 then List.concat (List.map collect_disjs types)
395 else failwith "unexpected iso on a disjtype"
396 | _ -> [t] in
397 let res =
398 List.map
399 (function ty ->
400 Ast.Type
401 (Some (mcode cv),
402 rewrap ty (do_isos (Ast0.get_iso ty)) (base_typeC ty)))
403 (collect_disjs ty) in
404 (* one could worry that isos are lost because we flatten the
405 disjunctions. but there should not be isos on the disjunctions
406 themselves. *)
407 (match res with
408 [ty] -> ty
409 | types -> Ast.DisjType(List.map (rewrap t no_isos) types))
410 | Ast0.BaseType(_,_) | Ast0.ImplicitInt(_) | Ast0.Pointer(_,_)
411 | Ast0.FunctionPointer(_,_,_,_,_,_,_) | Ast0.FunctionType(_,_,_,_)
412 | Ast0.Array(_,_,_,_) | Ast0.StructUnionName(_,_)
413 | Ast0.StructUnionDef(_,_,_,_) | Ast0.TypeName(_) | Ast0.MetaType(_,_) ->
414 Ast.Type(None,rewrap t no_isos (base_typeC t))
415 | Ast0.DisjType(_,types,_,_) -> Ast.DisjType(List.map typeC types)
416 | Ast0.OptType(ty) -> Ast.OptType(typeC ty)
417 | Ast0.UniqueType(ty) -> Ast.UniqueType(typeC ty))
418
419and base_typeC t =
420 match Ast0.unwrap t with
421 Ast0.BaseType(ty,sign) ->
422 Ast.BaseType(mcode ty,get_option mcode sign)
423 | Ast0.ImplicitInt(sgn) -> Ast.ImplicitInt(mcode sgn)
424 | Ast0.Pointer(ty,star) -> Ast.Pointer(typeC ty,mcode star)
425 | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
426 Ast.FunctionPointer
427 (typeC ty,mcode lp1,mcode star,mcode rp1,
428 mcode lp2,parameter_list params,mcode rp2)
429 | Ast0.FunctionType(ret,lp,params,rp) ->
430 let allminus = check_allminus.V0.combiner_typeC t in
431 Ast.FunctionType
432 (allminus,get_option typeC ret,mcode lp,
433 parameter_list params,mcode rp)
434 | Ast0.Array(ty,lb,size,rb) ->
435 Ast.Array(typeC ty,mcode lb,get_option expression size,mcode rb)
436 | Ast0.StructUnionName(kind,name) ->
437 Ast.StructUnionName(mcode kind,get_option ident name)
438 | Ast0.StructUnionDef(ty,lb,decls,rb) ->
439 Ast.StructUnionDef(typeC ty,mcode lb,
440 dots declaration decls,
441 mcode rb)
442 | Ast0.TypeName(name) -> Ast.TypeName(mcode name)
443 | Ast0.MetaType(name,_) ->
444 Ast.MetaType(mcode name,unitary,false)
445 | _ -> failwith "ast0toast: unexpected type"
446
447(* --------------------------------------------------------------------- *)
448(* Variable declaration *)
449(* Even if the Cocci program specifies a list of declarations, they are
450 split out into multiple declarations of a single variable each. *)
451
452and declaration d =
453 rewrap d (do_isos (Ast0.get_iso d))
454 (match Ast0.unwrap d with
455 Ast0.Init(stg,ty,id,eq,ini,sem) ->
456 let stg = get_option mcode stg in
457 let ty = typeC ty in
458 let id = ident id in
459 let eq = mcode eq in
460 let ini = initialiser ini in
461 let sem = mcode sem in
462 Ast.Init(stg,ty,id,eq,ini,sem)
463 | Ast0.UnInit(stg,ty,id,sem) ->
464 (match Ast0.unwrap ty with
465 Ast0.FunctionType(tyx,lp1,params,rp1) ->
466 let allminus = check_allminus.V0.combiner_declaration d in
467 Ast.UnInit(get_option mcode stg,
468 rewrap ty (do_isos (Ast0.get_iso ty))
469 (Ast.Type
470 (None,
471 rewrap ty no_isos
472 (Ast.FunctionType
473 (allminus,get_option typeC tyx,mcode lp1,
474 parameter_list params,mcode rp1)))),
475 ident id,mcode sem)
476 | _ -> Ast.UnInit(get_option mcode stg,typeC ty,ident id,mcode sem))
477 | Ast0.MacroDecl(name,lp,args,rp,sem) ->
478 let name = ident name in
479 let lp = mcode lp in
480 let args = dots expression args in
481 let rp = mcode rp in
482 let sem = mcode sem in
483 Ast.MacroDecl(name,lp,args,rp,sem)
484 | Ast0.TyDecl(ty,sem) -> Ast.TyDecl(typeC ty,mcode sem)
485 | Ast0.Typedef(stg,ty,id,sem) ->
486 let id = typeC id in
487 (match Ast.unwrap id with
488 Ast.Type(None,id) -> (* only MetaType or Id *)
489 Ast.Typedef(mcode stg,typeC ty,id,mcode sem)
490 | _ -> failwith "bad typedef")
491 | Ast0.DisjDecl(_,decls,_,_) -> Ast.DisjDecl(List.map declaration decls)
492 | Ast0.Ddots(dots,whencode) ->
493 let dots = mcode dots in
494 let whencode = get_option declaration whencode in
495 Ast.Ddots(dots,whencode)
496 | Ast0.OptDecl(decl) -> Ast.OptDecl(declaration decl)
497 | Ast0.UniqueDecl(decl) -> Ast.UniqueDecl(declaration decl))
498
499and declaration_dots l = dots declaration l
500
501(* --------------------------------------------------------------------- *)
502(* Initialiser *)
503
504and strip_idots initlist =
505 match Ast0.unwrap initlist with
506 Ast0.DOTS(x) ->
507 let (whencode,init) =
508 List.fold_left
509 (function (prevwhen,previnit) ->
510 function cur ->
511 match Ast0.unwrap cur with
512 Ast0.Idots(dots,Some whencode) ->
513 (whencode :: prevwhen, previnit)
514 | Ast0.Idots(dots,None) -> (prevwhen,previnit)
515 | _ -> (prevwhen, cur :: previnit))
516 ([],[]) x in
517 (List.rev whencode, List.rev init)
518 | Ast0.CIRCLES(x) | Ast0.STARS(x) -> failwith "not possible for an initlist"
519
520and initialiser i =
521 rewrap i no_isos
522 (match Ast0.unwrap i with
523 Ast0.InitExpr(exp) -> Ast.InitExpr(expression exp)
524 | Ast0.InitList(lb,initlist,rb) ->
525 let (whencode,initlist) = strip_idots initlist in
526 Ast.InitList(mcode lb,List.map initialiser initlist,mcode rb,
527 List.map initialiser whencode)
528 | Ast0.InitGccDotName(dot,name,eq,ini) ->
529 Ast.InitGccDotName(mcode dot,ident name,mcode eq,initialiser ini)
530 | Ast0.InitGccName(name,eq,ini) ->
531 Ast.InitGccName(ident name,mcode eq,initialiser ini)
532 | Ast0.InitGccIndex(lb,exp,rb,eq,ini) ->
533 Ast.InitGccIndex(mcode lb,expression exp,mcode rb,mcode eq,
534 initialiser ini)
535 | Ast0.InitGccRange(lb,exp1,dots,exp2,rb,eq,ini) ->
536 Ast.InitGccRange(mcode lb,expression exp1,mcode dots,
537 expression exp2,mcode rb,mcode eq,initialiser ini)
538 | Ast0.IComma(comma) -> Ast.IComma(mcode comma)
539 | Ast0.Idots(_,_) -> failwith "Idots should have been removed"
540 | Ast0.OptIni(ini) -> Ast.OptIni(initialiser ini)
541 | Ast0.UniqueIni(ini) -> Ast.UniqueIni(initialiser ini))
542
543(* --------------------------------------------------------------------- *)
544(* Parameter *)
545
546and parameterTypeDef p =
547 rewrap p no_isos
548 (match Ast0.unwrap p with
549 Ast0.VoidParam(ty) -> Ast.VoidParam(typeC ty)
550 | Ast0.Param(ty,id) -> Ast.Param(typeC ty,get_option ident id)
551 | Ast0.MetaParam(name,_) ->
552 Ast.MetaParam(mcode name,unitary,false)
553 | Ast0.MetaParamList(name,Some lenname,_) ->
554 Ast.MetaParamList(mcode name,Some(mcode lenname,unitary,false),
555 unitary,false)
556 | Ast0.MetaParamList(name,None,_) ->
557 Ast.MetaParamList(mcode name,None,unitary,false)
558 | Ast0.PComma(cm) -> Ast.PComma(mcode cm)
559 | Ast0.Pdots(dots) -> Ast.Pdots(mcode dots)
560 | Ast0.Pcircles(dots) -> Ast.Pcircles(mcode dots)
561 | Ast0.OptParam(param) -> Ast.OptParam(parameterTypeDef param)
562 | Ast0.UniqueParam(param) -> Ast.UniqueParam(parameterTypeDef param))
563
564and parameter_list l = dots parameterTypeDef l
565
566(* --------------------------------------------------------------------- *)
567(* Top-level code *)
568
569and statement s =
570 let rec statement seqible s =
571 let rewrap_stmt ast0 ast =
572 let befaft =
573 match Ast0.get_dots_bef_aft s with
574 Ast0.NoDots -> Ast.NoDots
575 | Ast0.DroppingBetweenDots s ->
576 Ast.DroppingBetweenDots (statement seqible s,get_ctr())
577 | Ast0.AddingBetweenDots s ->
578 Ast.AddingBetweenDots (statement seqible s,get_ctr()) in
579 Ast.set_dots_bef_aft befaft (rewrap ast0 no_isos ast) in
580 let rewrap_rule_elem ast0 ast =
581 rewrap ast0 (do_isos (Ast0.get_iso ast0)) ast in
582 rewrap_stmt s
583 (match Ast0.unwrap s with
584 Ast0.Decl((_,bef),decl) ->
585 Ast.Atomic(rewrap_rule_elem s
586 (Ast.Decl(convert_mcodekind bef,
587 check_allminus.V0.combiner_statement s,
588 declaration decl)))
589 | Ast0.Seq(lbrace,body,rbrace) ->
590 let lbrace = mcode lbrace in
591 let (decls,body) = separate_decls seqible body in
592 let rbrace = mcode rbrace in
593 Ast.Seq(iso_tokenwrap lbrace s (Ast.SeqStart(lbrace))
594 (do_isos (Ast0.get_iso s)),
595 decls,body,
596 tokenwrap rbrace s (Ast.SeqEnd(rbrace)))
597 | Ast0.ExprStatement(exp,sem) ->
598 Ast.Atomic(rewrap_rule_elem s
599 (Ast.ExprStatement(expression exp,mcode sem)))
600 | Ast0.IfThen(iff,lp,exp,rp,branch,(_,aft)) ->
601 Ast.IfThen
602 (rewrap_rule_elem s
603 (Ast.IfHeader(mcode iff,mcode lp,expression exp,mcode rp)),
604 statement Ast.NotSequencible branch,
605 ([],[],[],convert_mcodekind aft))
606 | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(_,aft)) ->
607 let els = mcode els in
608 Ast.IfThenElse
609 (rewrap_rule_elem s
610 (Ast.IfHeader(mcode iff,mcode lp,expression exp,mcode rp)),
611 statement Ast.NotSequencible branch1,
612 tokenwrap els s (Ast.Else(els)),
613 statement Ast.NotSequencible branch2,
614 ([],[],[],convert_mcodekind aft))
615 | Ast0.While(wh,lp,exp,rp,body,(_,aft)) ->
616 Ast.While(rewrap_rule_elem s
617 (Ast.WhileHeader
618 (mcode wh,mcode lp,expression exp,mcode rp)),
619 statement Ast.NotSequencible body,
620 ([],[],[],convert_mcodekind aft))
621 | Ast0.Do(d,body,wh,lp,exp,rp,sem) ->
622 let wh = mcode wh in
623 Ast.Do(rewrap_rule_elem s (Ast.DoHeader(mcode d)),
624 statement Ast.NotSequencible body,
625 tokenwrap wh s
626 (Ast.WhileTail(wh,mcode lp,expression exp,mcode rp,
627 mcode sem)))
628 | Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,(_,aft)) ->
629 let fr = mcode fr in
630 let lp = mcode lp in
631 let exp1 = get_option expression exp1 in
632 let sem1 = mcode sem1 in
633 let exp2 = get_option expression exp2 in
634 let sem2= mcode sem2 in
635 let exp3 = get_option expression exp3 in
636 let rp = mcode rp in
637 let body = statement Ast.NotSequencible body in
638 Ast.For(rewrap_rule_elem s
639 (Ast.ForHeader(fr,lp,exp1,sem1,exp2,sem2,exp3,rp)),
640 body,([],[],[],convert_mcodekind aft))
641 | Ast0.Iterator(nm,lp,args,rp,body,(_,aft)) ->
642 Ast.Iterator(rewrap_rule_elem s
643 (Ast.IteratorHeader
644 (ident nm,mcode lp,
645 dots expression args,
646 mcode rp)),
647 statement Ast.NotSequencible body,
648 ([],[],[],convert_mcodekind aft))
649 | Ast0.Switch(switch,lp,exp,rp,lb,cases,rb) ->
650 let switch = mcode switch in
651 let lp = mcode lp in
652 let exp = expression exp in
653 let rp = mcode rp in
654 let lb = mcode lb in
655 let cases = List.map case_line (Ast0.undots cases) in
656 let rb = mcode rb in
657 Ast.Switch(rewrap_rule_elem s (Ast.SwitchHeader(switch,lp,exp,rp)),
658 tokenwrap lb s (Ast.SeqStart(lb)),
659 cases,
660 tokenwrap rb s (Ast.SeqEnd(rb)))
661 | Ast0.Break(br,sem) ->
662 Ast.Atomic(rewrap_rule_elem s (Ast.Break(mcode br,mcode sem)))
663 | Ast0.Continue(cont,sem) ->
664 Ast.Atomic(rewrap_rule_elem s (Ast.Continue(mcode cont,mcode sem)))
665 | Ast0.Label(l,dd) ->
666 Ast.Atomic(rewrap_rule_elem s (Ast.Label(ident l,mcode dd)))
667 | Ast0.Goto(goto,l,sem) ->
668 Ast.Atomic
669 (rewrap_rule_elem s (Ast.Goto(mcode goto,ident l,mcode sem)))
670 | Ast0.Return(ret,sem) ->
671 Ast.Atomic(rewrap_rule_elem s (Ast.Return(mcode ret,mcode sem)))
672 | Ast0.ReturnExpr(ret,exp,sem) ->
673 Ast.Atomic
674 (rewrap_rule_elem s
675 (Ast.ReturnExpr(mcode ret,expression exp,mcode sem)))
676 | Ast0.MetaStmt(name,_) ->
677 Ast.Atomic(rewrap_rule_elem s
678 (Ast.MetaStmt(mcode name,unitary,seqible,false)))
679 | Ast0.MetaStmtList(name,_) ->
680 Ast.Atomic(rewrap_rule_elem s
681 (Ast.MetaStmtList(mcode name,unitary,false)))
682 | Ast0.TopExp(exp) ->
683 Ast.Atomic(rewrap_rule_elem s (Ast.TopExp(expression exp)))
684 | Ast0.Exp(exp) ->
685 Ast.Atomic(rewrap_rule_elem s (Ast.Exp(expression exp)))
1be43e12
C
686 | Ast0.TopInit(init) ->
687 Ast.Atomic(rewrap_rule_elem s (Ast.TopInit(initialiser init)))
34e49164
C
688 | Ast0.Ty(ty) ->
689 Ast.Atomic(rewrap_rule_elem s (Ast.Ty(typeC ty)))
690 | Ast0.Disj(_,rule_elem_dots_list,_,_) ->
691 Ast.Disj(List.map (function x -> statement_dots seqible x)
692 rule_elem_dots_list)
693 | Ast0.Nest(_,rule_elem_dots,_,whn,multi) ->
694 Ast.Nest
695 (statement_dots Ast.Sequencible rule_elem_dots,
696 List.map
697 (whencode (statement_dots Ast.Sequencible)
698 (statement Ast.NotSequencible))
699 whn,
700 multi,[],[])
701 | Ast0.Dots(d,whn) ->
702 let d = mcode d in
703 let whn =
704 List.map
705 (whencode (statement_dots Ast.Sequencible)
706 (statement Ast.NotSequencible))
707 whn in
708 Ast.Dots(d,whn,[],[])
709 | Ast0.Circles(d,whn) ->
710 let d = mcode d in
711 let whn =
712 List.map
713 (whencode (statement_dots Ast.Sequencible)
714 (statement Ast.NotSequencible))
715 whn in
716 Ast.Circles(d,whn,[],[])
717 | Ast0.Stars(d,whn) ->
718 let d = mcode d in
719 let whn =
720 List.map
721 (whencode (statement_dots Ast.Sequencible)
722 (statement Ast.NotSequencible))
723 whn in
724 Ast.Stars(d,whn,[],[])
725 | Ast0.FunDecl((_,bef),fi,name,lp,params,rp,lbrace,body,rbrace) ->
726 let fi = List.map fninfo fi in
727 let name = ident name in
728 let lp = mcode lp in
729 let params = parameter_list params in
730 let rp = mcode rp in
731 let lbrace = mcode lbrace in
732 let (decls,body) = separate_decls seqible body in
733 let rbrace = mcode rbrace in
734 let allminus = check_allminus.V0.combiner_statement s in
735 Ast.FunDecl(rewrap_rule_elem s
736 (Ast.FunHeader(convert_mcodekind bef,
737 allminus,fi,name,lp,params,rp)),
738 tokenwrap lbrace s (Ast.SeqStart(lbrace)),
739 decls,body,
740 tokenwrap rbrace s (Ast.SeqEnd(rbrace)))
741 | Ast0.Include(inc,str) ->
742 Ast.Atomic(rewrap_rule_elem s (Ast.Include(mcode inc,mcode str)))
743 | Ast0.Define(def,id,params,body) ->
744 Ast.Define
745 (rewrap_rule_elem s
746 (Ast.DefineHeader
747 (mcode def,ident id, define_parameters params)),
748 statement_dots Ast.NotSequencible (*not sure*) body)
749 | Ast0.OptStm(stm) -> Ast.OptStm(statement seqible stm)
750 | Ast0.UniqueStm(stm) -> Ast.UniqueStm(statement seqible stm))
751
752 and define_parameters p =
753 rewrap p no_isos
754 (match Ast0.unwrap p with
755 Ast0.NoParams -> Ast.NoParams
756 | Ast0.DParams(lp,params,rp) ->
757 Ast.DParams(mcode lp,
758 dots define_param params,
759 mcode rp))
760
761 and define_param p =
762 rewrap p no_isos
763 (match Ast0.unwrap p with
764 Ast0.DParam(id) -> Ast.DParam(ident id)
765 | Ast0.DPComma(comma) -> Ast.DPComma(mcode comma)
766 | Ast0.DPdots(d) -> Ast.DPdots(mcode d)
767 | Ast0.DPcircles(c) -> Ast.DPcircles(mcode c)
768 | Ast0.OptDParam(dp) -> Ast.OptDParam(define_param dp)
769 | Ast0.UniqueDParam(dp) -> Ast.UniqueDParam(define_param dp))
770
771 and whencode notfn alwaysfn = function
772 Ast0.WhenNot a -> Ast.WhenNot (notfn a)
773 | Ast0.WhenAlways a -> Ast.WhenAlways (alwaysfn a)
774 | Ast0.WhenModifier(x) -> Ast.WhenModifier(x)
1be43e12
C
775 | x ->
776 let rewrap_rule_elem ast0 ast =
777 rewrap ast0 (do_isos (Ast0.get_iso ast0)) ast in
778 match x with
779 Ast0.WhenNotTrue(e) ->
780 Ast.WhenNotTrue(rewrap_rule_elem e (Ast.Exp(expression e)))
781 | Ast0.WhenNotFalse(e) ->
782 Ast.WhenNotFalse(rewrap_rule_elem e (Ast.Exp(expression e)))
783 | _ -> failwith "not possible"
34e49164
C
784
785 and process_list seqible isos = function
786 [] -> []
787 | x::rest ->
788 let first = statement seqible x in
789 let first =
790 if !Flag.track_iso_usage
791 then Ast.set_isos first (isos@(Ast.get_isos first))
792 else first in
793 (match Ast0.unwrap x with
794 Ast0.Dots(_,_) | Ast0.Nest(_) ->
795 first::(process_list (Ast.SequencibleAfterDots []) no_isos rest)
796 | _ ->
797 first::(process_list Ast.Sequencible no_isos rest))
798
799 and statement_dots seqible d =
800 let isos = do_isos (Ast0.get_iso d) in
801 rewrap d no_isos
802 (match Ast0.unwrap d with
803 Ast0.DOTS(x) -> Ast.DOTS(process_list seqible isos x)
804 | Ast0.CIRCLES(x) -> Ast.CIRCLES(process_list seqible isos x)
805 | Ast0.STARS(x) -> Ast.STARS(process_list seqible isos x))
806
807 and separate_decls seqible d =
808 let rec collect_decls = function
809 [] -> ([],[])
810 | (x::xs) as l ->
811 (match Ast0.unwrap x with
812 Ast0.Decl(_) ->
813 let (decls,other) = collect_decls xs in
814 (x :: decls,other)
815 | Ast0.Dots(_,_) | Ast0.Nest(_,_,_,_,_) ->
816 let (decls,other) = collect_decls xs in
817 (match decls with
818 [] -> ([],x::other)
819 | _ -> (x :: decls,other))
820 | Ast0.Disj(starter,stmt_dots_list,mids,ender) ->
821 let disjs = List.map collect_dot_decls stmt_dots_list in
822 let all_decls = List.for_all (function (_,s) -> s=[]) disjs in
823 if all_decls
824 then
825 let (decls,other) = collect_decls xs in
826 (x :: decls,other)
827 else ([],l)
828 | _ -> ([],l))
829
830 and collect_dot_decls d =
831 match Ast0.unwrap d with
832 Ast0.DOTS(x) -> collect_decls x
833 | Ast0.CIRCLES(x) -> collect_decls x
834 | Ast0.STARS(x) -> collect_decls x in
835
836 let process l d fn =
837 let (decls,other) = collect_decls l in
838 (rewrap d no_isos (fn (List.map (statement seqible) decls)),
839 rewrap d no_isos
840 (fn (process_list seqible (do_isos (Ast0.get_iso d)) other))) in
841 match Ast0.unwrap d with
842 Ast0.DOTS(x) -> process x d (function x -> Ast.DOTS x)
843 | Ast0.CIRCLES(x) -> process x d (function x -> Ast.CIRCLES x)
844 | Ast0.STARS(x) -> process x d (function x -> Ast.STARS x) in
845
846 statement Ast.Sequencible s
847
848and fninfo = function
849 Ast0.FStorage(stg) -> Ast.FStorage(mcode stg)
850 | Ast0.FType(ty) -> Ast.FType(typeC ty)
851 | Ast0.FInline(inline) -> Ast.FInline(mcode inline)
852 | Ast0.FAttr(attr) -> Ast.FAttr(mcode attr)
853
854and option_to_list = function
855 Some x -> [x]
856 | None -> []
857
858and case_line c =
859 rewrap c no_isos
860 (match Ast0.unwrap c with
861 Ast0.Default(def,colon,code) ->
862 let def = mcode def in
863 let colon = mcode colon in
864 let code = dots statement code in
865 Ast.CaseLine(rewrap c no_isos (Ast.Default(def,colon)),code)
866 | Ast0.Case(case,exp,colon,code) ->
867 let case = mcode case in
868 let exp = expression exp in
869 let colon = mcode colon in
870 let code = dots statement code in
871 Ast.CaseLine(rewrap c no_isos (Ast.Case(case,exp,colon)),code)
872 | Ast0.OptCase(case) -> Ast.OptCase(case_line case))
873
874and statement_dots l = dots statement l
875
876(* --------------------------------------------------------------------- *)
877
878(* what is possible is only what is at the top level in an iso *)
879and anything = function
880 Ast0.DotsExprTag(d) -> Ast.ExprDotsTag(expression_dots d)
881 | Ast0.DotsParamTag(d) -> Ast.ParamDotsTag(parameter_list d)
882 | Ast0.DotsInitTag(d) -> failwith "not possible"
883 | Ast0.DotsStmtTag(d) -> Ast.StmtDotsTag(statement_dots d)
884 | Ast0.DotsDeclTag(d) -> Ast.DeclDotsTag(declaration_dots d)
885 | Ast0.DotsCaseTag(d) -> failwith "not possible"
886 | Ast0.IdentTag(d) -> Ast.IdentTag(ident d)
887 | Ast0.ExprTag(d) -> Ast.ExpressionTag(expression d)
888 | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
889 failwith "only in isos, not converted to ast"
890 | Ast0.TypeCTag(d) -> Ast.FullTypeTag(typeC d)
891 | Ast0.ParamTag(d) -> Ast.ParamTag(parameterTypeDef d)
892 | Ast0.InitTag(d) -> Ast.InitTag(initialiser d)
893 | Ast0.DeclTag(d) -> Ast.DeclarationTag(declaration d)
894 | Ast0.StmtTag(d) -> Ast.StatementTag(statement d)
895 | Ast0.CaseLineTag(d) -> Ast.CaseLineTag(case_line d)
896 | Ast0.TopTag(d) -> Ast.Code(top_level d)
897 | Ast0.IsoWhenTag(_) -> failwith "not possible"
1be43e12
C
898 | Ast0.IsoWhenTTag(_) -> failwith "not possible"
899 | Ast0.IsoWhenFTag(_) -> failwith "not possible"
34e49164
C
900 | Ast0.MetaPosTag _ -> failwith "not possible"
901
902(* --------------------------------------------------------------------- *)
903(* Function declaration *)
904(* top level isos are probably lost to tracking *)
905
906and top_level t =
907 rewrap t no_isos
908 (match Ast0.unwrap t with
909 Ast0.FILEINFO(old_file,new_file) ->
910 Ast.FILEINFO(mcode old_file,mcode new_file)
911 | Ast0.DECL(stmt) -> Ast.DECL(statement stmt)
912 | Ast0.CODE(rule_elem_dots) ->
913 Ast.CODE(statement_dots rule_elem_dots)
914 | Ast0.ERRORWORDS(exps) -> Ast.ERRORWORDS(List.map expression exps)
915 | Ast0.OTHER(_) -> failwith "eliminated by top_level")
916
917(* --------------------------------------------------------------------- *)
918(* Entry point for minus code *)
919
920(* Inline_mcodes is very important - sends + code attached to the - code
921down to the mcodes. The functions above can only be used when there is no
922attached + code, eg in + code itself. *)
923let ast0toast_toplevel x =
924 inline_mcodes.V0.combiner_top_level x;
925 top_level x
926
927let ast0toast name deps dropped exists x is_exp =
928 List.iter inline_mcodes.V0.combiner_top_level x;
929 Ast.CocciRule (name,(deps,dropped,exists),List.map top_level x,is_exp)