Release coccinelle-0.2.0
[bpt/coccinelle.git] / parsing_cocci / check_meta.ml
CommitLineData
9f8e26f4
C
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
34e49164
C
23(* For minus fragment, checks that all of the identifier metavariables that
24are used are not declared as fresh, and check that all declared variables
25are used. For plus fragment, just check that the variables declared as
26fresh are used. What is the issue about error variables? (don't remember) *)
27
28module Ast0 = Ast0_cocci
29module Ast = Ast_cocci
30module V0 = Visitor_ast0
b1b2de81 31module VT0 = Visitor_ast0_types
34e49164
C
32
33(* all fresh identifiers *)
34let fresh_table = (Hashtbl.create(50) : ((string * string), unit) Hashtbl.t)
35
36let warning s = Printf.fprintf stderr "warning: %s\n" s
37
708f4980 38let promote name = (name,(),Ast0.default_info(),(),None,-1)
34e49164
C
39
40(* --------------------------------------------------------------------- *)
41
42let find_loop table name =
43 let rec loop = function
44 [] -> raise Not_found
45 | x::xs -> (try Hashtbl.find x name with Not_found -> loop xs) in
46 loop table
47
708f4980 48let check_table table minus (name,_,info,_,_,_) =
0708f913 49 let rl = info.Ast0.pos_info.Ast0.line_start in
34e49164
C
50 if minus
51 then
52 (try (find_loop table name) := true
53 with
54 Not_found ->
55 (try
56 Hashtbl.find fresh_table name;
57 let (_,name) = name in
58 failwith
59 (Printf.sprintf
60 "%d: unexpected use of a fresh identifier %s" rl name)
61 with Not_found -> ()))
62 else (try (find_loop table name) := true with Not_found -> ())
63
64let get_opt fn = Common.do_option fn
65
66(* --------------------------------------------------------------------- *)
67(* Dots *)
68
69let dots fn d =
70 match Ast0.unwrap d with
71 Ast0.DOTS(x) -> List.iter fn x
72 | Ast0.CIRCLES(x) -> List.iter fn x
73 | Ast0.STARS(x) -> List.iter fn x
74
75(* --------------------------------------------------------------------- *)
76(* Identifier *)
77
78type context = ID | FIELD | FN | GLOBAL
79
80(* heuristic for distinguishing ifdef variables from undeclared metavariables*)
81let is_ifdef name =
82 String.length name > 2 && String.uppercase name = name
83
84let ident context old_metas table minus i =
85 match Ast0.unwrap i with
951c7801
C
86 Ast0.Id((name,_,info,_,_,_) : string Ast0.mcode) ->
87 let rl = info.Ast0.pos_info.Ast0.line_start in
88 let is_plus i =
89 match Ast0.get_mcodekind i with Ast0.PLUS _ -> true | _ -> false in
90 let err =
91 if List.exists (function x -> x = name) old_metas
92 && (minus || is_plus i)
34e49164 93 then
951c7801
C
94 begin
95 warning
96 (Printf.sprintf
97 "line %d: %s, previously declared as a metavariable, is used as an identifier" rl name);
98 true
99 end
100 else false in
101 (match context with
102 ID ->
103 if not (is_ifdef name) && minus && not err(* warn only once per id *)
104 then
105 warning
106 (Printf.sprintf "line %d: should %s be a metavariable?" rl name)
107 | _ -> ())
108 | Ast0.MetaId(name,_,_) -> check_table table minus name
109 | Ast0.MetaFunc(name,_,_) -> check_table table minus name
110 | Ast0.MetaLocalFunc(name,_,_) -> check_table table minus name
111 | Ast0.OptIdent(_) | Ast0.UniqueIdent(_) ->
112 failwith "unexpected code"
34e49164
C
113
114(* --------------------------------------------------------------------- *)
115(* Expression *)
116
117let rec expression context old_metas table minus e =
118 match Ast0.unwrap e with
119 Ast0.Ident(id) ->
120 ident context old_metas table minus id
121 | Ast0.FunCall(fn,lp,args,rp) ->
122 expression FN old_metas table minus fn;
123 dots (expression ID old_metas table minus) args
124 | Ast0.Assignment(left,op,right,_) ->
125 expression context old_metas table minus left;
126 expression ID old_metas table minus right
127 | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
128 expression ID old_metas table minus exp1;
129 get_opt (expression ID old_metas table minus) exp2;
130 expression ID old_metas table minus exp3
131 | Ast0.Postfix(exp,op) ->
132 expression ID old_metas table minus exp
133 | Ast0.Infix(exp,op) ->
134 expression ID old_metas table minus exp
135 | Ast0.Unary(exp,op) ->
136 expression ID old_metas table minus exp
137 | Ast0.Binary(left,op,right) ->
138 expression ID old_metas table minus left;
139 expression ID old_metas table minus right
140 | Ast0.Paren(lp,exp,rp) ->
141 expression ID old_metas table minus exp
142 | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
143 expression ID old_metas table minus exp1;
144 expression ID old_metas table minus exp2
145 | Ast0.RecordAccess(exp,pt,field) ->
146 expression ID old_metas table minus exp;
147 ident FIELD old_metas table minus field
148 | Ast0.RecordPtAccess(exp,ar,field) ->
149 expression ID old_metas table minus exp;
150 ident FIELD old_metas table minus field
151 | Ast0.Cast(lp,ty,rp,exp) ->
152 typeC old_metas table minus ty; expression ID old_metas table minus exp
153 | Ast0.SizeOfExpr(szf,exp) -> expression ID old_metas table minus exp
154 | Ast0.SizeOfType(szf,lp,ty,rp) -> typeC old_metas table minus ty
155 | Ast0.TypeExp(ty) -> typeC old_metas table minus ty
156 | Ast0.MetaExpr(name,_,Some tys,_,_) ->
157 List.iter
158 (function x ->
159 match get_type_name x with
160 Some(ty) -> check_table table minus (promote ty)
161 | None -> ())
162 tys;
163 check_table table minus name
164 | Ast0.MetaExpr(name,_,_,_,_) | Ast0.MetaErr(name,_,_) ->
165 check_table table minus name
166 | Ast0.MetaExprList(name,None,_) ->
167 check_table table minus name
168 | Ast0.MetaExprList(name,Some lenname,_) ->
169 check_table table minus name;
170 check_table table minus lenname
171 | Ast0.DisjExpr(_,exps,_,_) ->
0708f913 172 List.iter (expression context old_metas table minus) exps
34e49164
C
173 | Ast0.NestExpr(_,exp_dots,_,w,_) ->
174 dots (expression ID old_metas table minus) exp_dots;
175 get_opt (expression ID old_metas table minus) w
176 | Ast0.Edots(_,Some x) | Ast0.Ecircles(_,Some x) | Ast0.Estars(_,Some x) ->
177 expression ID old_metas table minus x
178 | _ -> () (* no metavariable subterms *)
179
180and get_type_name = function
faf9a90c
C
181 Type_cocci.ConstVol(_,ty) | Type_cocci.SignedT(_,Some ty)
182 | Type_cocci.Pointer(ty)
34e49164
C
183 | Type_cocci.FunctionPointer(ty) | Type_cocci.Array(ty) -> get_type_name ty
184 | Type_cocci.MetaType(nm,_,_) -> Some nm
185 | _ -> None
186
187(* --------------------------------------------------------------------- *)
188(* Types *)
189
190and typeC old_metas table minus t =
191 match Ast0.unwrap t with
192 Ast0.ConstVol(cv,ty) -> typeC old_metas table minus ty
faf9a90c
C
193 | Ast0.Signed(sgn,ty) ->
194 get_opt (typeC old_metas table minus) ty
34e49164
C
195 | Ast0.Pointer(ty,star) -> typeC old_metas table minus ty
196 | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
197 typeC old_metas table minus ty;
198 parameter_list old_metas table minus params
199 | Ast0.FunctionType(ty,lp1,params,rp1) ->
200 get_opt (typeC old_metas table minus) ty;
201 parameter_list old_metas table minus params
202 | Ast0.Array(ty,lb,size,rb) ->
203 typeC old_metas table minus ty;
204 get_opt (expression ID old_metas table minus) size
205 | Ast0.MetaType(name,_) ->
206 check_table table minus name
207 | Ast0.DisjType(_,types,_,_) ->
208 List.iter (typeC old_metas table minus) types
faf9a90c 209 | Ast0.EnumName(en,id) -> ident GLOBAL old_metas table minus id
34e49164
C
210 | Ast0.StructUnionName(su,Some id) -> ident GLOBAL old_metas table minus id
211 | Ast0.StructUnionDef(ty,lb,decls,rb) ->
212 typeC old_metas table minus ty;
213 dots (declaration GLOBAL old_metas table minus) decls
214 | Ast0.OptType(ty) | Ast0.UniqueType(ty) ->
215 failwith "unexpected code"
216 | _ -> () (* no metavariable subterms *)
217
218(* --------------------------------------------------------------------- *)
219(* Variable declaration *)
220(* Even if the Cocci program specifies a list of declarations, they are
221 split out into multiple declarations of a single variable each. *)
222
223and declaration context old_metas table minus d =
224 match Ast0.unwrap d with
225 Ast0.Init(stg,ty,id,eq,ini,sem) ->
226 (match Ast0.unwrap ini with
227 Ast0.InitExpr exp ->
228 typeC old_metas table minus ty;
229 ident context old_metas table minus id;
230 expression ID old_metas table minus exp
231 | _ ->
232 (*
233 if minus
234 then
235 failwith "complex initializer specification not allowed in - code"
236 else*)
237 (typeC old_metas table minus ty;
238 ident context old_metas table minus id;
239 initialiser old_metas table minus ini))
240 | Ast0.UnInit(stg,ty,id,sem) ->
241 typeC old_metas table minus ty; ident context old_metas table minus id
242 | Ast0.MacroDecl(name,lp,args,rp,sem) ->
faf9a90c 243 ident GLOBAL old_metas table minus name;
34e49164
C
244 dots (expression ID old_metas table minus) args
245 | Ast0.TyDecl(ty,sem) -> typeC old_metas table minus ty
246 | Ast0.Typedef(stg,ty,id,sem) ->
247 typeC old_metas table minus ty;
248 typeC old_metas table minus id
249 | Ast0.DisjDecl(_,decls,_,_) ->
250 List.iter (declaration ID old_metas table minus) decls
251 | Ast0.Ddots(_,Some x) -> declaration ID old_metas table minus x
252 | Ast0.Ddots(_,None) -> ()
253 | Ast0.OptDecl(_) | Ast0.UniqueDecl(_) ->
254 failwith "unexpected code"
255
256(* --------------------------------------------------------------------- *)
257(* Initialiser *)
258
259and initialiser old_metas table minus ini =
260 match Ast0.unwrap ini with
113803cf
C
261 Ast0.MetaInit(name,_) ->
262 check_table table minus name
263 | Ast0.InitExpr(exp) -> expression ID old_metas table minus exp
34e49164
C
264 | Ast0.InitList(lb,initlist,rb) ->
265 dots (initialiser old_metas table minus) initlist
113803cf
C
266 | Ast0.InitGccExt(designators,eq,ini) ->
267 List.iter (designator old_metas table minus) designators;
34e49164
C
268 initialiser old_metas table minus ini
269 | Ast0.InitGccName(name,eq,ini) ->
270 ident FIELD old_metas table minus name;
271 initialiser old_metas table minus ini
34e49164
C
272 | Ast0.Idots(_,Some x) -> initialiser old_metas table minus x
273 | Ast0.OptIni(_) | Ast0.UniqueIni(_) ->
274 failwith "unexpected code"
275 | _ -> () (* no metavariable subterms *)
276
113803cf
C
277and designator old_metas table minus = function
278 Ast0.DesignatorField(dot,id) ->
279 ident FIELD old_metas table minus id
280 | Ast0.DesignatorIndex(lb,exp,rb) ->
281 expression ID old_metas table minus exp
282 | Ast0.DesignatorRange(lb,min,dots,max,rb) ->
283 expression ID old_metas table minus min;
284 expression ID old_metas table minus max
285
34e49164
C
286and initialiser_list old_metas table minus =
287 dots (initialiser old_metas table minus)
288
289(* --------------------------------------------------------------------- *)
290(* Parameter *)
291
292and parameterTypeDef old_metas table minus param =
293 match Ast0.unwrap param with
294 Ast0.Param(ty,id) ->
295 get_opt (ident ID old_metas table minus) id;
296 typeC old_metas table minus ty
297 | Ast0.MetaParam(name,_) ->
298 check_table table minus name
299 | Ast0.MetaParamList(name,None,_) ->
300 check_table table minus name
301 | Ast0.MetaParamList(name,Some lenname,_) ->
302 check_table table minus name;
303 check_table table minus lenname
304 | _ -> () (* no metavariable subterms *)
305
306and parameter_list old_metas table minus =
307 dots (parameterTypeDef old_metas table minus)
308
309(* --------------------------------------------------------------------- *)
310(* Top-level code *)
311
312and statement old_metas table minus s =
313 match Ast0.unwrap s with
314 Ast0.Decl(_,decl) -> declaration ID old_metas table minus decl
315 | Ast0.Seq(lbrace,body,rbrace) -> dots (statement old_metas table minus) body
316 | Ast0.ExprStatement(exp,sem) -> expression ID old_metas table minus exp
317 | Ast0.IfThen(iff,lp,exp,rp,branch,_) ->
318 expression ID old_metas table minus exp;
319 statement old_metas table minus branch
320 | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,_) ->
321 expression ID old_metas table minus exp;
322 statement old_metas table minus branch1;
323 statement old_metas table minus branch2
324 | Ast0.While(wh,lp,exp,rp,body,_) ->
325 expression ID old_metas table minus exp;
326 statement old_metas table minus body
327 | Ast0.Do(d,body,wh,lp,exp,rp,sem) ->
328 statement old_metas table minus body;
329 expression ID old_metas table minus exp
330 | Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,_) ->
331 get_opt (expression ID old_metas table minus) exp1;
332 get_opt (expression ID old_metas table minus) exp2;
333 get_opt (expression ID old_metas table minus) exp3;
334 statement old_metas table minus body
335 | Ast0.Iterator(nm,lp,args,rp,body,_) ->
faf9a90c 336 ident GLOBAL old_metas table minus nm;
34e49164
C
337 dots (expression ID old_metas table minus) args;
338 statement old_metas table minus body
fc1ad971 339 | Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb) ->
34e49164 340 expression ID old_metas table minus exp;
fc1ad971 341 dots (statement old_metas table minus) decls;
34e49164
C
342 dots (case_line old_metas table minus) cases
343 | Ast0.ReturnExpr(ret,exp,sem) -> expression ID old_metas table minus exp
344 | Ast0.MetaStmt(name,_) -> check_table table minus name
345 | Ast0.MetaStmtList(name,_) -> check_table table minus name
346 | Ast0.Exp(exp) -> expression ID old_metas table minus exp
347 | Ast0.TopExp(exp) -> expression ID old_metas table minus exp
348 | Ast0.Ty(ty) -> typeC old_metas table minus ty
1be43e12 349 | Ast0.TopInit(init) -> initialiser old_metas table minus init
34e49164
C
350 | Ast0.Disj(_,rule_elem_dots_list,_,_) ->
351 List.iter (dots (statement old_metas table minus)) rule_elem_dots_list
352 | Ast0.Nest(_,rule_elem_dots,_,w,_) ->
353 dots (statement old_metas table minus) rule_elem_dots;
354 List.iter (whencode (dots (statement old_metas table minus))
1be43e12
C
355 (statement old_metas table minus)
356 (expression ID old_metas table minus))
34e49164
C
357 w
358 | Ast0.Dots(_,x) | Ast0.Circles(_,x) | Ast0.Stars(_,x) ->
359 List.iter
360 (whencode (dots (statement old_metas table minus))
1be43e12
C
361 (statement old_metas table minus)
362 (expression ID old_metas table minus)) x
34e49164
C
363 | Ast0.FunDecl(_,fi,name,lp,params,rp,lbrace,body,rbrace) ->
364 ident FN old_metas table minus name;
365 List.iter (fninfo old_metas table minus) fi;
366 parameter_list old_metas table minus params;
367 dots (statement old_metas table minus) body
368 | Ast0.Include(inc,s) -> () (* no metavariables possible *)
7f004419 369 | Ast0.Define(def,id,params,body) ->
34e49164 370 ident GLOBAL old_metas table minus id;
7f004419 371 define_parameters old_metas table minus params;
34e49164 372 dots (statement old_metas table minus) body
978fd7e5 373 | Ast0.Label(i,_) -> ident ID old_metas table minus i
34e49164
C
374 | Ast0.Goto(_,i,_) -> ident ID old_metas table minus i
375 | _ -> () (* no metavariable subterms *)
376
7f004419
C
377and define_param old_metas table minus p =
378 match Ast0.unwrap p with
379 Ast0.DParam(id) -> ident GLOBAL old_metas table minus id
380 | Ast0.DPComma(_) | Ast0.DPdots(_) | Ast0.DPcircles(_) ->
381 () (* no metavariable subterms *)
382 | Ast0.OptDParam(dp) -> define_param old_metas table minus dp
383 | Ast0.UniqueDParam(dp) -> define_param old_metas table minus dp
384
385and define_parameters old_metas table minus x =
386 match Ast0.unwrap x with
387 Ast0.NoParams -> ()
388 | Ast0.DParams(lp,dp,rp) -> dots (define_param old_metas table minus) dp
389
34e49164
C
390and fninfo old_metas table minus = function
391 Ast0.FStorage(stg) -> ()
392 | Ast0.FType(ty) -> typeC old_metas table minus ty
393 | Ast0.FInline(inline) -> ()
394 | Ast0.FAttr(attr) -> ()
395
1be43e12 396and whencode notfn alwaysfn expression = function
34e49164
C
397 Ast0.WhenNot a -> notfn a
398 | Ast0.WhenAlways a -> alwaysfn a
399 | Ast0.WhenModifier(_) -> ()
1be43e12
C
400 | Ast0.WhenNotTrue a -> expression a
401 | Ast0.WhenNotFalse a -> expression a
34e49164
C
402
403and case_line old_metas table minus c =
404 match Ast0.unwrap c with
405 Ast0.Default(def,colon,code) ->
406 dots (statement old_metas table minus) code
407 | Ast0.Case(case,exp,colon,code) ->
408 dots (statement old_metas table minus) code
fc1ad971
C
409 | Ast0.DisjCase(_,case_lines,_,_) ->
410 List.iter (case_line old_metas table minus) case_lines
34e49164
C
411 | Ast0.OptCase(case) -> failwith "unexpected code"
412
413(* --------------------------------------------------------------------- *)
414(* Rules *)
415
416let top_level old_metas table minus t =
417 match Ast0.unwrap t with
418 Ast0.DECL(stmt) -> statement old_metas table minus stmt
419 | Ast0.CODE(stmt_dots) -> dots (statement old_metas table minus) stmt_dots
420 | Ast0.ERRORWORDS(exps) ->
421 List.iter (expression FN old_metas table minus) exps
422 | _ -> () (* no metavariables possible *)
423
424let rule old_metas table minus rules =
425 List.iter (top_level old_metas table minus) rules
426
427(* --------------------------------------------------------------------- *)
428
429let positions table rules =
430 let mcode x =
431 match Ast0.get_pos x with
432 Ast0.MetaPos(name,constraints,_) ->
433 let pos = Ast0.unwrap_mcode name in
434 (find_loop table pos) := true
435 | _ -> () in
436 let option_default = () in
437 let bind x y = () in
438 let donothing r k e = k e in
439 let fn =
b1b2de81 440 V0.flat_combiner bind option_default
34e49164 441 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
34e49164
C
442 donothing donothing donothing donothing donothing donothing
443 donothing donothing donothing donothing donothing donothing donothing
444 donothing donothing in
445
b1b2de81 446 List.iter fn.VT0.combiner_rec_top_level rules
34e49164
C
447
448let dup_positions rules =
449 let mcode x =
450 match Ast0.get_pos x with
451 Ast0.MetaPos(name,constraints,_) ->
452 let pos = Ast0.unwrap_mcode name in [pos]
453 | _ -> [] in
454 let option_default = [] in
455 let bind x y = x@y in
456
457 (* Case for everything that has a disj.
458 Note, no positions on ( | ) of a disjunction, so no need to recurse on
459 these. *)
460
461 let expression r k e =
462 match Ast0.unwrap e with
463 Ast0.DisjExpr(_,explist,_,_) ->
464 List.fold_left Common.union_set option_default
b1b2de81 465 (List.map r.VT0.combiner_rec_expression explist)
34e49164
C
466 | _ -> k e in
467
468 let typeC r k e = (* not sure relevent because "only after iso" *)
469 match Ast0.unwrap e with
470 Ast0.DisjType(_,types,_,_) ->
471 List.fold_left Common.union_set option_default
b1b2de81 472 (List.map r.VT0.combiner_rec_typeC types)
34e49164
C
473 | _ -> k e in
474
475 let declaration r k e =
476 match Ast0.unwrap e with
477 Ast0.DisjDecl(_,decls,_,_) ->
478 List.fold_left Common.union_set option_default
b1b2de81 479 (List.map r.VT0.combiner_rec_declaration decls)
34e49164
C
480 | _ -> k e in
481
482 let statement r k e =
483 match Ast0.unwrap e with
484 Ast0.Disj(_,stmts,_,_) ->
485 List.fold_left Common.union_set option_default
b1b2de81 486 (List.map r.VT0.combiner_rec_statement_dots stmts)
34e49164
C
487 | _ -> k e in
488
489 let donothing r k e = k e in
490 let fn =
b1b2de81 491 V0.flat_combiner bind option_default
34e49164 492 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
34e49164
C
493 donothing donothing donothing donothing donothing donothing
494 donothing expression typeC donothing donothing declaration statement
495 donothing donothing in
496
497 let res =
498 List.sort compare
499 (List.fold_left Common.union_set option_default
b1b2de81 500 (List.map fn.VT0.combiner_rec_top_level rules)) in
34e49164
C
501 let rec loop = function
502 [] | [_] -> ()
503 | ((rule,name) as x)::y::_ when x = y ->
504 failwith (Printf.sprintf "duplicate use of %s.%s" rule name)
505 | _::xs -> loop xs in
506 loop res
507
508(* --------------------------------------------------------------------- *)
509
510let make_table l =
511 let table =
512 (Hashtbl.create(List.length l) :
513 ((string * string), bool ref) Hashtbl.t) in
514 List.iter
515 (function x -> Hashtbl.add table (Ast.get_meta_name x) (ref false)) l;
516 table
517
518let add_to_fresh_table l =
519 List.iter
520 (function x ->
521 let name = Ast.get_meta_name x in Hashtbl.replace fresh_table name ())
522 l
523
524let check_all_marked rname err table after_err =
525 Hashtbl.iter
526 (function name ->
527 function (cell) ->
528 if not (!cell)
529 then
530 let (_,name) = name in
531 warning
532 (Printf.sprintf "%s: %s %s not used %s" rname err name after_err))
533 table
534
535let check_meta rname old_metas inherited_metavars metavars minus plus =
536 let old_metas =
537 List.map (function (_,x) -> x) (List.map Ast.get_meta_name old_metas) in
538 let (fresh,other) =
539 List.partition (function Ast.MetaFreshIdDecl(_,_) -> true | _ -> false)
540 metavars in
541 let (err,other) =
542 List.partition (function Ast.MetaErrDecl(_,_) -> true | _ -> false)
543 other in
544 let (ierr,iother) =
545 List.partition (function Ast.MetaErrDecl(_,_) -> true | _ -> false)
546 inherited_metavars in
547 let fresh_table = make_table fresh in
548 let err_table = make_table (err@ierr) in
549 let other_table = make_table other in
550 let iother_table = make_table iother in
551 add_to_fresh_table fresh;
552 rule old_metas [iother_table;other_table;err_table] true minus;
553 positions [iother_table;other_table] minus;
554 dup_positions minus;
555 check_all_marked rname "metavariable" other_table "in the - or context code";
556 rule old_metas [iother_table;fresh_table;err_table] false plus;
faf9a90c 557 check_all_marked rname "inherited metavariable" iother_table
34e49164
C
558 "in the -, +, or context code";
559 check_all_marked rname "metavariable" fresh_table "in the + code";
560 check_all_marked rname "error metavariable" err_table ""