2 * Copyright 2010, INRIA, University of Copenhagen
3 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
4 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
5 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
6 * This file is part of Coccinelle.
8 * Coccinelle is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, according to version 2 of the License.
12 * Coccinelle is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
26 * Copyright 2010, INRIA, University of Copenhagen
27 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
28 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
29 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
30 * This file is part of Coccinelle.
32 * Coccinelle is free software: you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License as published by
34 * the Free Software Foundation, according to version 2 of the License.
36 * Coccinelle is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU General Public License for more details.
41 * You should have received a copy of the GNU General Public License
42 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
44 * The authors reserve the right to distribute this or future versions of
45 * Coccinelle under other licenses.
49 (* For minus fragment, checks that all of the identifier metavariables that
50 are used are not declared as fresh, and check that all declared variables
51 are used. For plus fragment, just check that the variables declared as
52 fresh are used. What is the issue about error variables? (don't remember) *)
54 module Ast0
= Ast0_cocci
55 module Ast
= Ast_cocci
56 module V0
= Visitor_ast0
57 module VT0
= Visitor_ast0_types
59 (* all fresh identifiers *)
60 let fresh_table = (Hashtbl.create
(50) : (Ast.meta_name
, unit) Hashtbl.t
)
62 let warning s
= Printf.fprintf stderr
"warning: %s\n" s
64 let promote name
= (name
,(),Ast0.default_info
(),(),None
,-1)
66 (* --------------------------------------------------------------------- *)
68 let find_loop table name
=
69 let rec loop = function
71 | x
::xs
-> (try Hashtbl.find x name
with Not_found
-> loop xs
) in
74 let check_table table minus
(name
,_
,info
,_
,_
,_
) =
75 let rl = info
.Ast0.pos_info
.Ast0.line_start
in
78 (try (find_loop table name
) := true
82 Hashtbl.find
fresh_table name
;
83 let (_
,name
) = name
in
86 "%d: unexpected use of a fresh identifier %s" rl name
)
87 with Not_found
-> ()))
88 else (try (find_loop table name
) := true with Not_found
-> ())
90 let get_opt fn
= Common.do_option fn
92 (* --------------------------------------------------------------------- *)
96 match Ast0.unwrap d
with
97 Ast0.DOTS
(x
) -> List.iter fn x
98 | Ast0.CIRCLES
(x
) -> List.iter fn x
99 | Ast0.STARS
(x
) -> List.iter fn x
101 (* --------------------------------------------------------------------- *)
104 type context
= ID
| FIELD
| FN
| GLOBAL
106 (* heuristic for distinguishing ifdef variables from undeclared metavariables*)
108 String.length name
> 2 && String.uppercase name
= name
110 let ident context old_metas table minus i
=
111 match Ast0.unwrap i
with
112 Ast0.Id
((name
,_
,info
,_
,_
,_
) : string Ast0.mcode
) ->
113 let rl = info
.Ast0.pos_info
.Ast0.line_start
in
115 match Ast0.get_mcodekind i
with Ast0.PLUS _
-> true | _
-> false in
117 if List.exists
(function x
-> x
= name
) old_metas
118 && (minus
|| is_plus i
)
123 "line %d: %s, previously declared as a metavariable, is used as an identifier" rl name
);
129 if not
(is_ifdef name
) && minus
&& not
err(* warn only once per id *)
132 (Printf.sprintf
"line %d: should %s be a metavariable?" rl name
)
134 | Ast0.MetaId
(name
,_
,_
) -> check_table table minus name
135 | Ast0.MetaFunc
(name
,_
,_
) -> check_table table minus name
136 | Ast0.MetaLocalFunc
(name
,_
,_
) -> check_table table minus name
137 | Ast0.OptIdent
(_
) | Ast0.UniqueIdent
(_
) ->
138 failwith
"unexpected code"
140 (* --------------------------------------------------------------------- *)
143 let rec expression context old_metas table minus e
=
144 match Ast0.unwrap e
with
146 ident context old_metas table minus id
147 | Ast0.FunCall
(fn
,lp
,args
,rp
) ->
148 expression FN old_metas table minus fn
;
149 dots (expression ID old_metas table minus
) args
150 | Ast0.Assignment
(left
,op
,right
,_
) ->
151 expression context old_metas table minus left
;
152 expression ID old_metas table minus right
153 | Ast0.CondExpr
(exp1
,why
,exp2
,colon
,exp3
) ->
154 expression ID old_metas table minus exp1
;
155 get_opt (expression ID old_metas table minus
) exp2
;
156 expression ID old_metas table minus exp3
157 | Ast0.Postfix
(exp
,op
) ->
158 expression ID old_metas table minus exp
159 | Ast0.Infix
(exp
,op
) ->
160 expression ID old_metas table minus exp
161 | Ast0.Unary
(exp
,op
) ->
162 expression ID old_metas table minus exp
163 | Ast0.Binary
(left
,op
,right
) ->
164 expression ID old_metas table minus left
;
165 expression ID old_metas table minus right
166 | Ast0.Paren
(lp
,exp
,rp
) ->
167 expression ID old_metas table minus exp
168 | Ast0.ArrayAccess
(exp1
,lb
,exp2
,rb
) ->
169 expression ID old_metas table minus exp1
;
170 expression ID old_metas table minus exp2
171 | Ast0.RecordAccess
(exp
,pt
,field
) ->
172 expression ID old_metas table minus exp
;
173 ident FIELD old_metas table minus field
174 | Ast0.RecordPtAccess
(exp
,ar
,field
) ->
175 expression ID old_metas table minus exp
;
176 ident FIELD old_metas table minus field
177 | Ast0.Cast
(lp
,ty
,rp
,exp
) ->
178 typeC old_metas table minus ty
; expression ID old_metas table minus exp
179 | Ast0.SizeOfExpr
(szf
,exp
) -> expression ID old_metas table minus exp
180 | Ast0.SizeOfType
(szf
,lp
,ty
,rp
) -> typeC old_metas table minus ty
181 | Ast0.TypeExp
(ty
) -> typeC old_metas table minus ty
182 | Ast0.MetaExpr
(name
,_
,Some tys
,_
,_
) ->
185 match get_type_name x
with
186 Some
(ty
) -> check_table table minus
(promote ty
)
189 check_table table minus name
190 | Ast0.MetaExpr
(name
,_
,_
,_
,_
) | Ast0.MetaErr
(name
,_
,_
) ->
191 check_table table minus name
192 | Ast0.MetaExprList
(name
,Ast0.MetaListLen lenname
,_
) ->
193 check_table table minus name
;
194 check_table table minus lenname
195 | Ast0.MetaExprList
(name
,_
,_
) ->
196 check_table table minus name
197 | Ast0.DisjExpr
(_
,exps
,_
,_
) ->
198 List.iter
(expression context old_metas table minus
) exps
199 | Ast0.NestExpr
(_
,exp_dots
,_
,w
,_
) ->
200 dots (expression ID old_metas table minus
) exp_dots
;
201 get_opt (expression ID old_metas table minus
) w
202 | Ast0.Edots
(_
,Some x
) | Ast0.Ecircles
(_
,Some x
) | Ast0.Estars
(_
,Some x
) ->
203 expression ID old_metas table minus x
204 | _
-> () (* no metavariable subterms *)
206 and get_type_name
= function
207 Type_cocci.ConstVol
(_
,ty
) | Type_cocci.SignedT
(_
,Some ty
)
208 | Type_cocci.Pointer
(ty
)
209 | Type_cocci.FunctionPointer
(ty
) | Type_cocci.Array
(ty
) -> get_type_name ty
210 | Type_cocci.EnumName
(Type_cocci.MV
(nm
,_
,_
)) -> Some nm
211 | Type_cocci.StructUnionName
(_
,Type_cocci.MV
(nm
,_
,_
)) -> Some nm
212 | Type_cocci.MetaType
(nm
,_
,_
) -> Some nm
215 (* --------------------------------------------------------------------- *)
218 and typeC old_metas table minus t
=
219 match Ast0.unwrap t
with
220 Ast0.ConstVol
(cv
,ty
) -> typeC old_metas table minus ty
221 | Ast0.Signed
(sgn
,ty
) ->
222 get_opt (typeC old_metas table minus
) ty
223 | Ast0.Pointer
(ty
,star
) -> typeC old_metas table minus ty
224 | Ast0.FunctionPointer
(ty
,lp1
,star
,rp1
,lp2
,params
,rp2
) ->
225 typeC old_metas table minus ty
;
226 parameter_list old_metas table minus params
227 | Ast0.FunctionType
(ty
,lp1
,params
,rp1
) ->
228 get_opt (typeC old_metas table minus
) ty
;
229 parameter_list old_metas table minus params
230 | Ast0.Array
(ty
,lb
,size
,rb
) ->
231 typeC old_metas table minus ty
;
232 get_opt (expression ID old_metas table minus
) size
233 | Ast0.MetaType
(name
,_
) ->
234 check_table table minus name
235 | Ast0.DisjType
(_
,types
,_
,_
) ->
236 List.iter
(typeC old_metas table minus
) types
237 | Ast0.EnumName
(en
,Some id
) -> ident GLOBAL old_metas table minus id
238 | Ast0.EnumDef
(ty
,lb
,ids
,rb
) ->
239 typeC old_metas table minus ty
;
240 dots (expression GLOBAL old_metas table minus
) ids
241 | Ast0.StructUnionName
(su
,Some id
) -> ident GLOBAL old_metas table minus id
242 | Ast0.StructUnionDef
(ty
,lb
,decls
,rb
) ->
243 typeC old_metas table minus ty
;
244 dots (declaration GLOBAL old_metas table minus
) decls
245 | Ast0.OptType
(ty
) | Ast0.UniqueType
(ty
) ->
246 failwith
"unexpected code"
247 | _
-> () (* no metavariable subterms *)
249 (* --------------------------------------------------------------------- *)
250 (* Variable declaration *)
251 (* Even if the Cocci program specifies a list of declarations, they are
252 split out into multiple declarations of a single variable each. *)
254 and declaration context old_metas table minus d
=
255 match Ast0.unwrap d
with
256 Ast0.MetaDecl
(name
,_
) | Ast0.MetaField
(name
,_
) ->
257 check_table table minus name
258 | Ast0.Init
(stg
,ty
,id
,eq
,ini
,sem
) ->
259 (match Ast0.unwrap ini
with
261 typeC old_metas table minus ty
;
262 ident context old_metas table minus id
;
263 expression ID old_metas table minus exp
268 failwith "complex initializer specification not allowed in - code"
270 (typeC old_metas table minus ty
;
271 ident context old_metas table minus id
;
272 initialiser old_metas table minus ini
))
273 | Ast0.UnInit
(stg
,ty
,id
,sem
) ->
274 typeC old_metas table minus ty
; ident context old_metas table minus id
275 | Ast0.MacroDecl
(name
,lp
,args
,rp
,sem
) ->
276 ident GLOBAL old_metas table minus name
;
277 dots (expression ID old_metas table minus
) args
278 | Ast0.TyDecl
(ty
,sem
) -> typeC old_metas table minus ty
279 | Ast0.Typedef
(stg
,ty
,id
,sem
) ->
280 typeC old_metas table minus ty
;
281 typeC old_metas table minus id
282 | Ast0.DisjDecl
(_
,decls
,_
,_
) ->
283 List.iter
(declaration ID old_metas table minus
) decls
284 | Ast0.Ddots
(_
,Some x
) -> declaration ID old_metas table minus x
285 | Ast0.Ddots
(_
,None
) -> ()
286 | Ast0.OptDecl
(_
) | Ast0.UniqueDecl
(_
) ->
287 failwith
"unexpected code"
289 (* --------------------------------------------------------------------- *)
292 and initialiser old_metas table minus ini
=
293 match Ast0.unwrap ini
with
294 Ast0.MetaInit
(name
,_
) ->
295 check_table table minus name
296 | Ast0.InitExpr
(exp
) -> expression ID old_metas table minus exp
297 | Ast0.InitList
(lb
,initlist
,rb
,ordered
) ->
298 dots (initialiser old_metas table minus
) initlist
299 | Ast0.InitGccExt
(designators
,eq
,ini
) ->
300 List.iter
(designator old_metas table minus
) designators
;
301 initialiser old_metas table minus ini
302 | Ast0.InitGccName
(name
,eq
,ini
) ->
303 ident FIELD old_metas table minus name
;
304 initialiser old_metas table minus ini
305 | Ast0.Idots
(_
,Some x
) -> initialiser old_metas table minus x
306 | Ast0.OptIni
(_
) | Ast0.UniqueIni
(_
) ->
307 failwith
"unexpected code"
308 | _
-> () (* no metavariable subterms *)
310 and designator old_metas table minus
= function
311 Ast0.DesignatorField
(dot
,id
) ->
312 ident FIELD old_metas table minus id
313 | Ast0.DesignatorIndex
(lb
,exp
,rb
) ->
314 expression ID old_metas table minus exp
315 | Ast0.DesignatorRange
(lb
,min
,dots,max
,rb
) ->
316 expression ID old_metas table minus min
;
317 expression ID old_metas table minus max
319 and initialiser_list old_metas table minus
=
320 dots (initialiser old_metas table minus
)
322 (* --------------------------------------------------------------------- *)
325 and parameterTypeDef old_metas table minus param
=
326 match Ast0.unwrap param
with
328 get_opt (ident ID old_metas table minus
) id
;
329 typeC old_metas table minus ty
330 | Ast0.MetaParam
(name
,_
) ->
331 check_table table minus name
332 | Ast0.MetaParamList
(name
,Ast0.MetaListLen lenname
,_
) ->
333 check_table table minus name
;
334 check_table table minus lenname
335 | Ast0.MetaParamList
(name
,_
,_
) ->
336 check_table table minus name
337 | _
-> () (* no metavariable subterms *)
339 and parameter_list old_metas table minus
=
340 dots (parameterTypeDef old_metas table minus
)
342 (* --------------------------------------------------------------------- *)
345 and statement old_metas table minus s
=
346 match Ast0.unwrap s
with
347 Ast0.Decl
(_
,decl
) -> declaration ID old_metas table minus decl
348 | Ast0.Seq
(lbrace
,body
,rbrace
) -> dots (statement old_metas table minus
) body
349 | Ast0.ExprStatement
(exp
,sem
) -> expression ID old_metas table minus exp
350 | Ast0.IfThen
(iff
,lp
,exp
,rp
,branch
,_
) ->
351 expression ID old_metas table minus exp
;
352 statement old_metas table minus branch
353 | Ast0.IfThenElse
(iff
,lp
,exp
,rp
,branch1
,els
,branch2
,_
) ->
354 expression ID old_metas table minus exp
;
355 statement old_metas table minus branch1
;
356 statement old_metas table minus branch2
357 | Ast0.While
(wh
,lp
,exp
,rp
,body
,_
) ->
358 expression ID old_metas table minus exp
;
359 statement old_metas table minus body
360 | Ast0.Do
(d
,body
,wh
,lp
,exp
,rp
,sem
) ->
361 statement old_metas table minus body
;
362 expression ID old_metas table minus exp
363 | Ast0.For
(fr
,lp
,exp1
,sem1
,exp2
,sem2
,exp3
,rp
,body
,_
) ->
364 get_opt (expression ID old_metas table minus
) exp1
;
365 get_opt (expression ID old_metas table minus
) exp2
;
366 get_opt (expression ID old_metas table minus
) exp3
;
367 statement old_metas table minus body
368 | Ast0.Iterator
(nm
,lp
,args
,rp
,body
,_
) ->
369 ident GLOBAL old_metas table minus nm
;
370 dots (expression ID old_metas table minus
) args
;
371 statement old_metas table minus body
372 | Ast0.Switch
(switch
,lp
,exp
,rp
,lb
,decls
,cases
,rb
) ->
373 expression ID old_metas table minus exp
;
374 dots (statement old_metas table minus
) decls
;
375 dots (case_line old_metas table minus
) cases
376 | Ast0.ReturnExpr
(ret
,exp
,sem
) -> expression ID old_metas table minus exp
377 | Ast0.MetaStmt
(name
,_
) -> check_table table minus name
378 | Ast0.MetaStmtList
(name
,_
) -> check_table table minus name
379 | Ast0.Exp
(exp
) -> expression ID old_metas table minus exp
380 | Ast0.TopExp
(exp
) -> expression ID old_metas table minus exp
381 | Ast0.Ty
(ty
) -> typeC old_metas table minus ty
382 | Ast0.TopInit
(init
) -> initialiser old_metas table minus init
383 | Ast0.Disj
(_
,rule_elem_dots_list
,_
,_
) ->
384 List.iter
(dots (statement old_metas table minus
)) rule_elem_dots_list
385 | Ast0.Nest
(_
,rule_elem_dots
,_
,w
,_
) ->
386 dots (statement old_metas table minus
) rule_elem_dots
;
387 List.iter
(whencode
(dots (statement old_metas table minus
))
388 (statement old_metas table minus
)
389 (expression ID old_metas table minus
))
391 | Ast0.Dots
(_
,x
) | Ast0.Circles
(_
,x
) | Ast0.Stars
(_
,x
) ->
393 (whencode
(dots (statement old_metas table minus
))
394 (statement old_metas table minus
)
395 (expression ID old_metas table minus
)) x
396 | Ast0.FunDecl
(_
,fi
,name
,lp
,params
,rp
,lbrace
,body
,rbrace
) ->
397 ident FN old_metas table minus name
;
398 List.iter
(fninfo old_metas table minus
) fi
;
399 parameter_list old_metas table minus params
;
400 dots (statement old_metas table minus
) body
401 | Ast0.Include
(inc
,s
) -> () (* no metavariables possible *)
402 | Ast0.Define
(def
,id
,params
,body
) ->
403 ident GLOBAL old_metas table minus id
;
404 define_parameters old_metas table minus params
;
405 dots (statement old_metas table minus
) body
406 | Ast0.Label
(i
,_
) -> ident ID old_metas table minus i
407 | Ast0.Goto
(_
,i
,_
) -> ident ID old_metas table minus i
408 | _
-> () (* no metavariable subterms *)
410 and define_param old_metas table minus p
=
411 match Ast0.unwrap p
with
412 Ast0.DParam
(id
) -> ident GLOBAL old_metas table minus id
413 | Ast0.DPComma
(_
) | Ast0.DPdots
(_
) | Ast0.DPcircles
(_
) ->
414 () (* no metavariable subterms *)
415 | Ast0.OptDParam
(dp
) -> define_param old_metas table minus dp
416 | Ast0.UniqueDParam
(dp
) -> define_param old_metas table minus dp
418 and define_parameters old_metas table minus x
=
419 match Ast0.unwrap x
with
421 | Ast0.DParams
(lp
,dp
,rp
) -> dots (define_param old_metas table minus
) dp
423 and fninfo old_metas table minus
= function
424 Ast0.FStorage
(stg
) -> ()
425 | Ast0.FType
(ty
) -> typeC old_metas table minus ty
426 | Ast0.FInline
(inline
) -> ()
427 | Ast0.FAttr
(attr
) -> ()
429 and whencode notfn alwaysfn
expression = function
430 Ast0.WhenNot a
-> notfn a
431 | Ast0.WhenAlways a
-> alwaysfn a
432 | Ast0.WhenModifier
(_
) -> ()
433 | Ast0.WhenNotTrue a
-> expression a
434 | Ast0.WhenNotFalse a
-> expression a
436 and case_line old_metas table minus c
=
437 match Ast0.unwrap c
with
438 Ast0.Default
(def
,colon
,code
) ->
439 dots (statement old_metas table minus
) code
440 | Ast0.Case
(case
,exp
,colon
,code
) ->
441 expression GLOBAL old_metas table minus exp
;
442 dots (statement old_metas table minus
) code
443 | Ast0.DisjCase
(_
,case_lines
,_
,_
) ->
444 List.iter
(case_line old_metas table minus
) case_lines
445 | Ast0.OptCase
(case
) -> failwith
"unexpected code"
447 (* --------------------------------------------------------------------- *)
450 let top_level old_metas table minus t
=
451 match Ast0.unwrap t
with
452 Ast0.DECL
(stmt
) -> statement old_metas table minus stmt
453 | Ast0.CODE
(stmt_dots
) -> dots (statement old_metas table minus
) stmt_dots
454 | Ast0.ERRORWORDS
(exps
) ->
455 List.iter
(expression FN old_metas table minus
) exps
456 | _
-> () (* no metavariables possible *)
458 let rule old_metas table minus rules
=
459 List.iter
(top_level old_metas table minus
) rules
461 (* --------------------------------------------------------------------- *)
463 let positions table rules
=
465 match Ast0.get_pos x
with
466 Ast0.MetaPos
(name
,constraints
,_
) ->
467 let pos = Ast0.unwrap_mcode name
in
468 (find_loop table
pos) := true
470 let option_default = () in
472 let donothing r k e
= k e
in
474 V0.flat_combiner
bind option_default
475 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
476 donothing donothing donothing donothing donothing donothing
477 donothing donothing donothing donothing donothing donothing donothing
478 donothing donothing in
480 List.iter
fn.VT0.combiner_rec_top_level rules
482 let dup_positions rules
=
484 match Ast0.get_pos x
with
485 Ast0.MetaPos
(name
,constraints
,_
) ->
486 let pos = Ast0.unwrap_mcode name
in [pos]
488 let option_default = [] in
489 let bind x y
= x
@y
in
491 (* Case for everything that has a disj.
492 Note, no positions on ( | ) of a disjunction, so no need to recurse on
495 let expression r k e
=
496 match Ast0.unwrap e
with
497 Ast0.DisjExpr
(_
,explist
,_
,_
) ->
498 List.fold_left
Common.union_set
option_default
499 (List.map r
.VT0.combiner_rec_expression explist
)
502 let typeC r k e
= (* not sure relevent because "only after iso" *)
503 match Ast0.unwrap e
with
504 Ast0.DisjType
(_
,types
,_
,_
) ->
505 List.fold_left
Common.union_set
option_default
506 (List.map r
.VT0.combiner_rec_typeC types
)
509 let declaration r k e
=
510 match Ast0.unwrap e
with
511 Ast0.DisjDecl
(_
,decls
,_
,_
) ->
512 List.fold_left
Common.union_set
option_default
513 (List.map r
.VT0.combiner_rec_declaration decls
)
516 let statement r k e
=
517 match Ast0.unwrap e
with
518 Ast0.Disj
(_
,stmts
,_
,_
) ->
519 List.fold_left
Common.union_set
option_default
520 (List.map r
.VT0.combiner_rec_statement_dots stmts
)
523 let donothing r k e
= k e
in
525 V0.flat_combiner
bind option_default
526 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
527 donothing donothing donothing donothing donothing donothing
528 donothing expression typeC donothing donothing declaration statement
529 donothing donothing in
533 (List.fold_left
Common.union_set
option_default
534 (List.map
fn.VT0.combiner_rec_top_level rules
)) in
535 let rec loop = function
537 | ((rule,name
) as x
)::y
::_
when x
= y
->
539 (Printf.sprintf
"duplicate use of %s.%s" rule name
)
540 | _
::xs
-> loop xs
in
543 (* --------------------------------------------------------------------- *)
547 (Hashtbl.create
(List.length l
) :
548 (Ast.meta_name
, bool ref) Hashtbl.t
) in
550 (function x
-> Hashtbl.add
table (Ast.get_meta_name x
) (ref false)) l
;
553 let add_to_fresh_table l
=
556 let name = Ast.get_meta_name x
in Hashtbl.replace
fresh_table name ())
559 let check_all_marked rname
err table after_err
=
565 let (_
,name) = name in
567 (Printf.sprintf
"%s: %s %s not used %s" rname
err name after_err
))
570 let check_meta rname old_metas inherited_metavars metavars minus plus
=
572 List.map
(function (_
,x
) -> x
) (List.map
Ast.get_meta_name
old_metas) in
574 List.partition
(function Ast.MetaFreshIdDecl
(_
,_
) -> true | _
-> false)
577 List.partition
(function Ast.MetaErrDecl
(_
,_
) -> true | _
-> false)
580 List.partition
(function Ast.MetaErrDecl
(_
,_
) -> true | _
-> false)
581 inherited_metavars
in
582 let fresh_table = make_table fresh
in
583 let err_table = make_table (err@ierr
) in
584 let other_table = make_table other
in
585 let iother_table = make_table iother
in
586 add_to_fresh_table fresh
;
587 rule old_metas [iother_table;other_table;err_table] true minus
;
588 positions [iother_table;other_table] minus
;
590 check_all_marked rname
"metavariable" other_table "in the - or context code";
591 rule old_metas [iother_table;fresh_table;err_table] false plus
;
592 check_all_marked rname
"inherited metavariable" iother_table
593 "in the -, +, or context code";
594 check_all_marked rname
"metavariable" fresh_table "in the + code";
595 check_all_marked rname
"error metavariable" err_table ""