Release coccinelle-0.2.0
[bpt/coccinelle.git] / parsing_cocci / parse_aux.ml
1 (*
2 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
3 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
4 * This file is part of Coccinelle.
5 *
6 * Coccinelle is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, according to version 2 of the License.
9 *
10 * Coccinelle is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
20 *)
21
22
23 (* exports everything, used only by parser_cocci_menhir.mly *)
24 module Ast0 = Ast0_cocci
25 module Ast = Ast_cocci
26
27 (* types for metavariable tokens *)
28 type info = Ast.meta_name * Ast0.pure * Data.clt
29 type idinfo = Ast.meta_name * Data.iconstraints * Ast0.pure * Data.clt
30 type expinfo = Ast.meta_name * Data.econstraints * Ast0.pure * Data.clt
31 type tyinfo = Ast.meta_name * Ast0.typeC list * Ast0.pure * Data.clt
32 type list_info = Ast.meta_name * Ast.meta_name option * Ast0.pure * Data.clt
33 type typed_expinfo =
34 Ast.meta_name * Data.econstraints * Ast0.pure *
35 Type_cocci.typeC list option * Data.clt
36 type pos_info = Ast.meta_name * Data.pconstraints * Ast.meta_collect * Data.clt
37
38
39 let get_option fn = function
40 None -> None
41 | Some x -> Some (fn x)
42
43 let make_info line logical_line offset col strbef straft =
44 let new_pos_info =
45 {Ast0.line_start = line; Ast0.line_end = line;
46 Ast0.logical_start = logical_line; Ast0.logical_end = logical_line;
47 Ast0.column = col; Ast0.offset = offset; } in
48 { Ast0.pos_info = new_pos_info;
49 Ast0.attachable_start = true; Ast0.attachable_end = true;
50 Ast0.mcode_start = []; Ast0.mcode_end = [];
51 Ast0.strings_before = strbef; Ast0.strings_after = straft; }
52
53 let clt2info (_,line,logical_line,offset,col,strbef,straft,pos) =
54 make_info line logical_line offset col strbef straft
55
56 let drop_bef (arity,line,lline,offset,col,strbef,straft,pos) =
57 (arity,line,lline,offset,col,[],straft,pos)
58
59 let drop_aft (arity,line,lline,offset,col,strbef,straft,pos) =
60 (arity,line,lline,offset,col,strbef,[],pos)
61
62 let drop_pos (arity,line,lline,offset,col,strbef,straft,pos) =
63 (arity,line,lline,offset,col,strbef,straft,Ast0.NoMetaPos)
64
65 let clt2mcode str = function
66 (Data.MINUS,line,lline,offset,col,strbef,straft,pos) ->
67 (str,Ast0.NONE,make_info line lline offset col strbef straft,
68 Ast0.MINUS(ref([],Ast0.default_token_info)),ref pos,-1)
69 | (Data.OPTMINUS,line,lline,offset,col,strbef,straft,pos) ->
70 (str,Ast0.OPT,make_info line lline offset col strbef straft,
71 Ast0.MINUS(ref([],Ast0.default_token_info)),ref pos,-1)
72 | (Data.UNIQUEMINUS,line,lline,offset,col,strbef,straft,pos) ->
73 (str,Ast0.UNIQUE,make_info line lline offset col strbef straft,
74 Ast0.MINUS(ref([],Ast0.default_token_info)),ref pos,-1)
75 | (Data.PLUS,line,lline,offset,col,strbef,straft,pos) ->
76 (str,Ast0.NONE,make_info line lline offset col strbef straft,
77 Ast0.PLUS(Ast.ONE),ref pos,-1)
78 | (Data.PLUSPLUS,line,lline,offset,col,strbef,straft,pos) ->
79 (str,Ast0.NONE,make_info line lline offset col strbef straft,
80 Ast0.PLUS(Ast.MANY),ref pos,-1)
81 | (Data.CONTEXT,line,lline,offset,col,strbef,straft,pos) ->
82 (str,Ast0.NONE,make_info line lline offset col strbef straft,
83 Ast0.CONTEXT(ref(Ast.NOTHING,
84 Ast0.default_token_info,Ast0.default_token_info)),
85 ref pos,-1)
86 | (Data.OPT,line,lline,offset,col,strbef,straft,pos) ->
87 (str,Ast0.OPT,make_info line lline offset col strbef straft,
88 Ast0.CONTEXT(ref(Ast.NOTHING,
89 Ast0.default_token_info,Ast0.default_token_info)),
90 ref pos,-1)
91 | (Data.UNIQUE,line,lline,offset,col,strbef,straft,pos) ->
92 (str,Ast0.UNIQUE,make_info line lline offset col strbef straft,
93 Ast0.CONTEXT(ref(Ast.NOTHING,
94 Ast0.default_token_info,Ast0.default_token_info)),
95 ref pos,-1)
96
97 let id2name (name, clt) = name
98 let id2clt (name, clt) = clt
99 let id2mcode (name, clt) = clt2mcode name clt
100
101 let mkdots str (dot,whencode) =
102 match str with
103 "..." -> Ast0.wrap(Ast0.Dots(clt2mcode str dot, whencode))
104 | "ooo" -> Ast0.wrap(Ast0.Circles(clt2mcode str dot, whencode))
105 | "***" -> Ast0.wrap(Ast0.Stars(clt2mcode str dot, whencode))
106 | _ -> failwith "cannot happen"
107
108 let mkedots str (dot,whencode) =
109 match str with
110 "..." -> Ast0.wrap(Ast0.Edots(clt2mcode str dot, whencode))
111 | "ooo" -> Ast0.wrap(Ast0.Ecircles(clt2mcode str dot, whencode))
112 | "***" -> Ast0.wrap(Ast0.Estars(clt2mcode str dot, whencode))
113 | _ -> failwith "cannot happen"
114
115 let mkdpdots str dot =
116 match str with
117 "..." -> Ast0.wrap(Ast0.DPdots(clt2mcode str dot))
118 | "ooo" -> Ast0.wrap(Ast0.DPcircles(clt2mcode str dot))
119 | _ -> failwith "cannot happen"
120
121 let mkidots str (dot,whencode) =
122 match str with
123 "..." -> Ast0.wrap(Ast0.Idots(clt2mcode str dot, whencode))
124 | _ -> failwith "cannot happen"
125
126 let mkddots str (dot,whencode) =
127 match (str,whencode) with
128 ("...",None) -> Ast0.wrap(Ast0.Ddots(clt2mcode str dot, None))
129 | ("...",Some [w]) -> Ast0.wrap(Ast0.Ddots(clt2mcode str dot, Some w))
130 | _ -> failwith "cannot happen"
131
132 let mkpdots str dot =
133 match str with
134 "..." -> Ast0.wrap(Ast0.Pdots(clt2mcode str dot))
135 | "ooo" -> Ast0.wrap(Ast0.Pcircles(clt2mcode str dot))
136 | _ -> failwith "cannot happen"
137
138 let arith_op ast_op left op right =
139 Ast0.wrap
140 (Ast0.Binary(left, clt2mcode (Ast.Arith ast_op) op, right))
141
142 let logic_op ast_op left op right =
143 Ast0.wrap
144 (Ast0.Binary(left, clt2mcode (Ast.Logical ast_op) op, right))
145
146 let make_cv cv ty =
147 match cv with None -> ty | Some x -> Ast0.wrap (Ast0.ConstVol(x,ty))
148
149 let top_dots l =
150 let circle x =
151 match Ast0.unwrap x with Ast0.Circles(_) -> true | _ -> false in
152 let star x =
153 match Ast0.unwrap x with Ast0.Stars(_) -> true | _ -> false in
154 if List.exists circle l
155 then Ast0.wrap(Ast0.CIRCLES(l))
156 else
157 if List.exists star l
158 then Ast0.wrap(Ast0.STARS(l))
159 else Ast0.wrap(Ast0.DOTS(l))
160
161 (* here the offset is that of the first in the sequence of *s, not that of
162 each * individually *)
163 let pointerify ty m =
164 List.fold_left
165 (function inner ->
166 function cur ->
167 Ast0.wrap(Ast0.Pointer(inner,clt2mcode "*" cur)))
168 ty m
169
170 let ty_pointerify ty m =
171 List.fold_left
172 (function inner -> function cur -> Type_cocci.Pointer(inner))
173 ty m
174
175 (* Left is <=>, Right is =>. Collect <=>s. *)
176 (* The parser should have done this, with precedences. But whatever... *)
177 let iso_adjust fn first rest =
178 let rec loop = function
179 [] -> [[]]
180 | (Common.Left x)::rest ->
181 (match loop rest with
182 front::after -> (fn x::front)::after
183 | _ -> failwith "not possible")
184 | (Common.Right x)::rest ->
185 (match loop rest with
186 front::after -> []::(fn x::front)::after
187 | _ -> failwith "not possible") in
188 match loop rest with
189 front::after -> (fn first::front)::after
190 | _ -> failwith "not possible"
191
192 let check_meta tok =
193 let lookup rule name =
194 try
195 let info = Hashtbl.find Data.all_metadecls rule in
196 List.find (function mv -> Ast.get_meta_name mv = (rule,name)) info
197 with
198 Not_found ->
199 raise
200 (Semantic_cocci.Semantic
201 ("bad rule "^rule^" or bad variable "^name)) in
202 match tok with
203 Ast.MetaIdDecl(Ast.NONE,(rule,name)) ->
204 (match lookup rule name with
205 Ast.MetaIdDecl(_,_) | Ast.MetaFreshIdDecl(_,_) -> ()
206 | _ ->
207 raise
208 (Semantic_cocci.Semantic
209 ("incompatible inheritance declaration "^name)))
210 | Ast.MetaFreshIdDecl((rule,name),seed) ->
211 raise
212 (Semantic_cocci.Semantic
213 "can't inherit the freshness of an identifier")
214 | Ast.MetaListlenDecl((rule,name)) ->
215 (match lookup rule name with
216 Ast.MetaListlenDecl(_) -> ()
217 | _ ->
218 raise
219 (Semantic_cocci.Semantic
220 ("incompatible inheritance declaration "^name)))
221 | Ast.MetaTypeDecl(Ast.NONE,(rule,name)) ->
222 (match lookup rule name with
223 Ast.MetaTypeDecl(_,_) -> ()
224 | _ ->
225 raise
226 (Semantic_cocci.Semantic
227 ("incompatible inheritance declaration "^name)))
228 | Ast.MetaInitDecl(Ast.NONE,(rule,name)) ->
229 (match lookup rule name with
230 Ast.MetaInitDecl(_,_) -> ()
231 | _ ->
232 raise
233 (Semantic_cocci.Semantic
234 ("incompatible inheritance declaration "^name)))
235 | Ast.MetaParamDecl(Ast.NONE,(rule,name)) ->
236 (match lookup rule name with
237 Ast.MetaParamDecl(_,_) -> ()
238 | _ ->
239 raise
240 (Semantic_cocci.Semantic
241 ("incompatible inheritance declaration "^name)))
242 | Ast.MetaParamListDecl(Ast.NONE,(rule,name),len_name) ->
243 (match lookup rule name with
244 Ast.MetaParamListDecl(_,_,_) -> ()
245 | _ ->
246 raise
247 (Semantic_cocci.Semantic
248 ("incompatible inheritance declaration "^name)))
249 | Ast.MetaErrDecl(Ast.NONE,(rule,name)) ->
250 (match lookup rule name with
251 Ast.MetaErrDecl(_,_) -> ()
252 | _ ->
253 raise
254 (Semantic_cocci.Semantic
255 ("incompatible inheritance declaration "^name)))
256 | Ast.MetaExpDecl(Ast.NONE,(rule,name),ty) ->
257 (match lookup rule name with
258 Ast.MetaExpDecl(_,_,ty1) when ty = ty1 -> ()
259 | _ ->
260 raise
261 (Semantic_cocci.Semantic
262 ("incompatible inheritance declaration "^name)))
263 | Ast.MetaIdExpDecl(Ast.NONE,(rule,name),ty) ->
264 (match lookup rule name with
265 Ast.MetaIdExpDecl(_,_,ty1) when ty = ty1 -> ()
266 | _ ->
267 raise
268 (Semantic_cocci.Semantic
269 ("incompatible inheritance declaration "^name)))
270 | Ast.MetaLocalIdExpDecl(Ast.NONE,(rule,name),ty) ->
271 (match lookup rule name with
272 Ast.MetaLocalIdExpDecl(_,_,ty1) when ty = ty1 -> ()
273 | _ ->
274 raise
275 (Semantic_cocci.Semantic
276 ("incompatible inheritance declaration "^name)))
277 | Ast.MetaExpListDecl(Ast.NONE,(rule,name),len_name) ->
278 (match lookup rule name with
279 Ast.MetaExpListDecl(_,_,_) -> ()
280 | Ast.MetaParamListDecl(_,_,_) when not (!Flag.make_hrule = None) -> ()
281 | _ ->
282 raise
283 (Semantic_cocci.Semantic
284 ("incompatible inheritance declaration "^name)))
285 | Ast.MetaStmDecl(Ast.NONE,(rule,name)) ->
286 (match lookup rule name with
287 Ast.MetaStmDecl(_,_) -> ()
288 | _ ->
289 raise
290 (Semantic_cocci.Semantic
291 ("incompatible inheritance declaration "^name)))
292 | Ast.MetaStmListDecl(Ast.NONE,(rule,name)) ->
293 (match lookup rule name with
294 Ast.MetaStmListDecl(_,_) -> ()
295 | _ ->
296 raise
297 (Semantic_cocci.Semantic
298 ("incompatible inheritance declaration "^name)))
299 | Ast.MetaFuncDecl(Ast.NONE,(rule,name)) ->
300 (match lookup rule name with
301 Ast.MetaFuncDecl(_,_) -> ()
302 | _ ->
303 raise
304 (Semantic_cocci.Semantic
305 ("incompatible inheritance declaration "^name)))
306 | Ast.MetaLocalFuncDecl(Ast.NONE,(rule,name)) ->
307 (match lookup rule name with
308 Ast.MetaLocalFuncDecl(_,_) -> ()
309 | _ ->
310 raise
311 (Semantic_cocci.Semantic
312 ("incompatible inheritance declaration "^name)))
313 | Ast.MetaConstDecl(Ast.NONE,(rule,name),ty) ->
314 (match lookup rule name with
315 Ast.MetaConstDecl(_,_,ty1) when ty = ty1 -> ()
316 | _ ->
317 raise
318 (Semantic_cocci.Semantic
319 ("incompatible inheritance declaration "^name)))
320 | Ast.MetaPosDecl(Ast.NONE,(rule,name)) ->
321 (match lookup rule name with
322 Ast.MetaPosDecl(_,_) ->
323 if not (List.mem rule !Data.inheritable_positions)
324 then
325 raise
326 (Semantic_cocci.Semantic
327 ("position cannot be inherited over modifications: "^name))
328 | _ ->
329 raise
330 (Semantic_cocci.Semantic
331 ("incompatible inheritance declaration "^name)))
332 | _ ->
333 raise
334 (Semantic_cocci.Semantic ("arity not allowed on imported declaration"))
335
336 let create_metadec ar ispure kindfn ids current_rule =
337 List.concat
338 (List.map
339 (function (rule,nm) ->
340 let (rule,checker) =
341 match rule with
342 None -> ((current_rule,nm),function x -> [Common.Left x])
343 | Some rule ->
344 ((rule,nm),
345 function x -> check_meta x; [Common.Right x]) in
346 kindfn ar rule ispure checker)
347 ids)
348
349 let create_fresh_metadec kindfn ids current_rule =
350 List.concat
351 (List.map
352 (function ((rule,nm),seed) ->
353 let (rule,checker) =
354 match rule with
355 None -> ((current_rule,nm),function x -> [Common.Left x])
356 | Some rule ->
357 ((rule,nm),
358 function x -> check_meta x; [Common.Right x]) in
359 kindfn rule checker seed)
360 ids)
361
362 let create_metadec_with_constraints ar ispure kindfn ids current_rule =
363 List.concat
364 (List.map
365 (function ((rule,nm),constraints) ->
366 let (rule,checker) =
367 match rule with
368 None -> ((current_rule,nm),function x -> [Common.Left x])
369 | Some rule ->
370 ((rule,nm),
371 function x -> check_meta x; [Common.Right x]) in
372 kindfn ar rule ispure checker constraints)
373 ids)
374
375 let create_metadec_ty ar ispure kindfn ids current_rule =
376 List.concat
377 (List.map
378 (function ((rule,nm),constraints) ->
379 let (rule,checker) =
380 match rule with
381 None -> ((current_rule,nm),function x -> [Common.Left x])
382 | Some rule ->
383 ((rule,nm),
384 function x -> check_meta x; [Common.Right x]) in
385 kindfn ar rule ispure checker constraints)
386 ids)
387
388 let create_len_metadec ar ispure kindfn lenid ids current_rule =
389 let lendec =
390 create_metadec Ast.NONE Ast0.Impure
391 (fun _ name _ check_meta -> check_meta(Ast.MetaListlenDecl(name)))
392 [lenid] current_rule in
393 let lenname =
394 match lendec with
395 [Common.Left (Ast.MetaListlenDecl(x))] -> x
396 | [Common.Right (Ast.MetaListlenDecl(x))] -> x
397 | _ -> failwith "unexpected length declaration" in
398 lendec@(create_metadec ar ispure (kindfn lenname) ids current_rule)
399
400 (* ---------------------------------------------------------------------- *)
401
402 let str2inc s =
403 let elements = Str.split (Str.regexp "/") s in
404 List.map (function "..." -> Ast.IncDots | s -> Ast.IncPath s) elements
405
406 (* ---------------------------------------------------------------------- *)
407 (* statements *)
408
409 let meta_stm name =
410 let (nm,pure,clt) = name in
411 Ast0.wrap(Ast0.MetaStmt(clt2mcode nm clt,pure))
412
413 let exp_stm exp pv =
414 Ast0.wrap(Ast0.ExprStatement (exp, clt2mcode ";" pv))
415
416 let ifthen iff lp tst rp thn =
417 Ast0.wrap(Ast0.IfThen(clt2mcode "if" iff,
418 clt2mcode "(" lp,tst,clt2mcode ")" rp,thn,
419 (Ast0.default_info(),Ast0.context_befaft())))
420
421 let ifthenelse iff lp tst rp thn e els =
422 Ast0.wrap(Ast0.IfThenElse(clt2mcode "if" iff,
423 clt2mcode "(" lp,tst,clt2mcode ")" rp,thn,
424 clt2mcode "else" e,els,
425 (Ast0.default_info(),Ast0.context_befaft())))
426
427 let forloop fr lp e1 sc1 e2 sc2 e3 rp s =
428 Ast0.wrap(Ast0.For(clt2mcode "for" fr,clt2mcode "(" lp,e1,
429 clt2mcode ";" sc1,e2,
430 clt2mcode ";" sc2,e3,clt2mcode ")" rp,s,
431 (Ast0.default_info(),Ast0.context_befaft())))
432
433 let whileloop w lp e rp s =
434 Ast0.wrap(Ast0.While(clt2mcode "while" w,clt2mcode "(" lp,
435 e,clt2mcode ")" rp,s,
436 (Ast0.default_info(),Ast0.context_befaft())))
437
438 let doloop d s w lp e rp pv =
439 Ast0.wrap(Ast0.Do(clt2mcode "do" d,s,clt2mcode "while" w,
440 clt2mcode "(" lp,e,clt2mcode ")" rp,
441 clt2mcode ";" pv))
442
443 let iterator i lp e rp s =
444 Ast0.wrap(Ast0.Iterator(i,clt2mcode "(" lp,e,clt2mcode ")" rp,s,
445 (Ast0.default_info(),Ast0.context_befaft())))
446
447 let switch s lp e rp lb d c rb =
448 let d =
449 List.map
450 (function d ->
451 Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),d)))
452 d in
453 Ast0.wrap(Ast0.Switch(clt2mcode "switch" s,clt2mcode "(" lp,e,
454 clt2mcode ")" rp,clt2mcode "{" lb,
455 Ast0.wrap(Ast0.DOTS(d)),
456 Ast0.wrap(Ast0.DOTS(c)),clt2mcode "}" rb))
457
458 let ret_exp r e pv =
459 Ast0.wrap(Ast0.ReturnExpr(clt2mcode "return" r,e,clt2mcode ";" pv))
460
461 let ret r pv =
462 Ast0.wrap(Ast0.Return(clt2mcode "return" r,clt2mcode ";" pv))
463
464 let break b pv =
465 Ast0.wrap(Ast0.Break(clt2mcode "break" b,clt2mcode ";" pv))
466
467 let cont c pv =
468 Ast0.wrap(Ast0.Continue(clt2mcode "continue" c,clt2mcode ";" pv))
469
470 let label i dd =
471 Ast0.wrap(Ast0.Label(i,clt2mcode ":" dd))
472
473 let goto g i pv =
474 Ast0.wrap(Ast0.Goto(clt2mcode "goto" g,i,clt2mcode ";" pv))
475
476 let seq lb s rb =
477 Ast0.wrap(Ast0.Seq(clt2mcode "{" lb,s,clt2mcode "}" rb))
478
479 (* ---------------------------------------------------------------------- *)
480
481 let make_iso_rule_name_result n =
482 (try let _ = Hashtbl.find Data.all_metadecls n in
483 raise (Semantic_cocci.Semantic ("repeated rule name"))
484 with Not_found -> ());
485 Ast.CocciRulename (Some n,Ast.NoDep,[],[],Ast.Undetermined,false (*discarded*))
486
487 let make_cocci_rule_name_result nm d i a e ee =
488 match nm with
489 Some nm ->
490 let n = id2name nm in
491 (try let _ = Hashtbl.find Data.all_metadecls n in
492 raise (Semantic_cocci.Semantic ("repeated rule name"))
493 with Not_found -> ());
494 Ast.CocciRulename (Some n,d,i,a,e,ee)
495 | None -> Ast.CocciRulename (None,d,i,a,e,ee)
496
497 let make_generated_rule_name_result nm d i a e ee =
498 match nm with
499 Some nm ->
500 let n = id2name nm in
501 (try let _ = Hashtbl.find Data.all_metadecls n in
502 raise (Semantic_cocci.Semantic ("repeated rule name"))
503 with Not_found -> ());
504 Ast.GeneratedRulename (Some n,d,i,a,e,ee)
505 | None -> Ast.GeneratedRulename (None,d,i,a,e,ee)
506
507 let make_script_rule_name_result lang deps =
508 let l = id2name lang in
509 Ast.ScriptRulename (l,deps)
510
511 let make_initial_script_rule_name_result lang =
512 let l = id2name lang in
513 Ast.InitialScriptRulename(l)
514
515 let make_final_script_rule_name_result lang =
516 let l = id2name lang in
517 Ast.FinalScriptRulename(l)
518
519 (* Allows type alone only when it is void and only when there is only one
520 parameter. This avoids ambiguity problems in the parser. *)
521 let verify_parameter_declarations = function
522 [] -> ()
523 | [x] ->
524 (match Ast0.unwrap x with
525 Ast0.Param(t, None) ->
526 (match Ast0.unwrap t with
527 Ast0.BaseType(Ast.VoidType,_) -> ()
528 | _ ->
529 failwith
530 (Printf.sprintf
531 "%d: only void can be a parameter without an identifier"
532 (Ast0.get_line t)))
533 | _ -> ())
534 | l ->
535 List.iter
536 (function x ->
537 match Ast0.unwrap x with
538 Ast0.Param(t, None) ->
539 failwith
540 (Printf.sprintf
541 "%d: only void alone can be a parameter without an identifier"
542 (Ast0.get_line t))
543 | _ -> ())
544 l