Coccinelle release 1.0.0-rc3
[bpt/coccinelle.git] / parsing_cocci / parse_cocci.ml
index e78b7a0..f721e53 100644 (file)
@@ -1,5 +1,7 @@
 (*
- * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
+ * Copyright 2010, INRIA, University of Copenhagen
+ * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
+ * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
  * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
  * This file is part of Coccinelle.
  *
@@ -29,6 +31,9 @@ module V0 = Visitor_ast0
 module VT0 = Visitor_ast0_types
 module Ast = Ast_cocci
 module Ast0 = Ast0_cocci
+
+exception Bad_virt of string
+
 let pr = Printf.sprintf
 (*let pr2 s = prerr_string s; prerr_string "\n"; flush stderr*)
 let pr2 s = Printf.printf "%s\n" s
@@ -51,13 +56,16 @@ let line_type2c tok =
 
 let token2c (tok,_) =
  match tok with
-    PC.TIdentifier -> "identifier"
+    PC.TMetavariable -> "metavariable"
+  | PC.TIdentifier -> "identifier"
   | PC.TType -> "type"
   | PC.TParameter -> "parameter"
   | PC.TConstant -> "constant"
   | PC.TExpression -> "expression"
   | PC.TIdExpression -> "idexpression"
   | PC.TInitialiser -> "initialiser"
+  | PC.TDeclaration -> "declaration"
+  | PC.TField -> "field"
   | PC.TStatement -> "statement"
   | PC.TPosition -> "position"
   | PC.TPosAny -> "any"
@@ -97,6 +105,9 @@ let token2c (tok,_) =
   | PC.Tfloat(clt) -> "float"^(line_type2c clt)
   | PC.Tlong(clt) -> "long"^(line_type2c clt)
   | PC.Tvoid(clt) -> "void"^(line_type2c clt)
+  | PC.Tsize_t(clt) -> "size_t"^(line_type2c clt)
+  | PC.Tssize_t(clt) -> "ssize_t"^(line_type2c clt)
+  | PC.Tptrdiff_t(clt) -> "ptrdiff_t"^(line_type2c clt)
   | PC.Tstruct(clt) -> "struct"^(line_type2c clt)
   | PC.Tunion(clt) -> "union"^(line_type2c clt)
   | PC.Tenum(clt) -> "enum"^(line_type2c clt)
@@ -114,8 +125,10 @@ let token2c (tok,_) =
 
   | PC.TPragma(Ast.Noindent s,_) -> s
   | PC.TPragma(Ast.Indent s,_)   -> s
+  | PC.TPragma(Ast.Space s,_)   -> s
   | PC.TIncludeL(s,clt) -> (pr "#include \"%s\"" s)^(line_type2c clt)
   | PC.TIncludeNL(s,clt) -> (pr "#include <%s>" s)^(line_type2c clt)
+  | PC.TUndef(clt,_) -> "#undef"^(line_type2c clt)
   | PC.TDefine(clt,_) -> "#define"^(line_type2c clt)
   | PC.TDefineParam(clt,_,_,_) -> "#define_param"^(line_type2c clt)
   | PC.TMinusFile(s,clt) -> (pr "--- %s" s)^(line_type2c clt)
@@ -157,6 +170,7 @@ let token2c (tok,_) =
   | PC.TAnd (clt) -> "&"^(line_type2c clt)
   | PC.TEqEq(clt) -> "=="^(line_type2c clt)
   | PC.TNotEq(clt) -> "!="^(line_type2c clt)
+  | PC.TSub(clt) -> "<="^(line_type2c clt)
   | PC.TTildeEq(clt) -> "~="^(line_type2c clt)
   | PC.TTildeExclEq(clt) -> "~!="^(line_type2c clt)
   | PC.TLogOp(op,clt) ->
@@ -167,12 +181,8 @@ let token2c (tok,_) =
       |        Ast.SupEq -> ">="
       |        _ -> failwith "not possible")
       ^(line_type2c clt)
-  | PC.TShOp(op,clt) ->
-      (match op with
-       Ast.DecLeft -> "<<"
-      |        Ast.DecRight -> ">>"
-      |        _ -> failwith "not possible")
-      ^(line_type2c clt)
+  | PC.TShLOp(op,clt) -> "<<"^(line_type2c clt)
+  | PC.TShROp(op,clt) -> ">>"^(line_type2c clt)
   | PC.TPlus(clt) -> "+"^(line_type2c clt)
   | PC.TMinus(clt) -> "-"^(line_type2c clt)
   | PC.TMul(clt) -> "*"^(line_type2c clt)
@@ -184,6 +194,7 @@ let token2c (tok,_) =
       ^(line_type2c clt)
   | PC.TTilde (clt) -> "~"^(line_type2c clt)
 
+  | PC.TMeta(_,_,clt) -> "meta"^(line_type2c clt)
   | PC.TMetaParam(_,_,clt) -> "parammeta"^(line_type2c clt)
   | PC.TMetaParamList(_,_,_,clt) -> "paramlistmeta"^(line_type2c clt)
   | PC.TMetaConst(_,_,_,_,clt) -> "constmeta"^(line_type2c clt)
@@ -192,11 +203,15 @@ let token2c (tok,_) =
   | PC.TMetaIdExp(_,_,_,_,clt) -> "idexpmeta"^(line_type2c clt)
   | PC.TMetaLocalIdExp(_,_,_,_,clt) -> "localidexpmeta"^(line_type2c clt)
   | PC.TMetaExpList(_,_,_,clt) -> "explistmeta"^(line_type2c clt)
-  | PC.TMetaId(_,_,_,clt)    -> "idmeta"^(line_type2c clt)
+  | PC.TMetaId(nm,_,_,_,clt)    -> "idmeta-"^(Dumper.dump nm)^(line_type2c clt)
   | PC.TMetaType(_,_,clt)    -> "typemeta"^(line_type2c clt)
   | PC.TMetaInit(_,_,clt)    -> "initmeta"^(line_type2c clt)
-  | PC.TMetaStm(_,_,clt)   -> "stmmeta"^(line_type2c clt)
-  | PC.TMetaStmList(_,_,clt)   -> "stmlistmeta"^(line_type2c clt)
+  | PC.TMetaInitList(_,_,_,clt)    -> "initlistmeta"^(line_type2c clt)
+  | PC.TMetaDecl(_,_,clt)    -> "declmeta"^(line_type2c clt)
+  | PC.TMetaField(_,_,clt)   -> "fieldmeta"^(line_type2c clt)
+  | PC.TMetaFieldList(_,_,_,clt)   -> "fieldlistmeta"^(line_type2c clt)
+  | PC.TMetaStm(_,_,clt)     -> "stmmeta"^(line_type2c clt)
+  | PC.TMetaStmList(_,_,clt) -> "stmlistmeta"^(line_type2c clt)
   | PC.TMetaFunc(_,_,_,clt)  -> "funcmeta"^(line_type2c clt)
   | PC.TMetaLocalFunc(_,_,_,clt) -> "funcmeta"^(line_type2c clt)
   | PC.TMetaPos(_,_,_,clt)   -> "posmeta"
@@ -271,6 +286,7 @@ let token2c (tok,_) =
   | PC.TIsoStatement -> "Statement"
   | PC.TIsoDeclaration -> "Declaration"
   | PC.TIsoType -> "Type"
+  | PC.TUnderscore -> "_"
   | PC.TScriptData s -> s
 
 let print_tokens s tokens =
@@ -284,14 +300,17 @@ type plus = PLUS | NOTPLUS | SKIP
 let plus_attachable only_plus (tok,_) =
   match tok with
     PC.Tchar(clt) | PC.Tshort(clt) | PC.Tint(clt) | PC.Tdouble(clt)
-  | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt) | PC.Tstruct(clt)
+  | PC.Tfloat(clt) | PC.Tlong(clt)
+  | PC.Tsize_t(clt) | PC.Tssize_t(clt) | PC.Tptrdiff_t(clt)
+  | PC.Tstruct(clt)
   | PC.Tunion(clt) | PC.Tenum(clt) | PC.Tunsigned(clt) | PC.Tsigned(clt)
   | PC.Tstatic(clt)
   | PC.Tinline(clt) | PC.Ttypedef(clt) | PC.Tattr(_,clt)
   | PC.Tauto(clt) | PC.Tregister(clt)
   | PC.Textern(clt) | PC.Tconst(clt) | PC.Tvolatile(clt)
 
-  | PC.TIncludeL(_,clt) | PC.TIncludeNL(_,clt) | PC.TDefine(clt,_)
+  | PC.TIncludeL(_,clt) | PC.TIncludeNL(_,clt) | PC.TUndef(clt,_)
+  | PC.TDefine(clt,_)
   | PC.TDefineParam(clt,_,_,_) | PC.TMinusFile(_,clt) | PC.TPlusFile(_,clt)
 
   | PC.TInc(clt) | PC.TDec(clt)
@@ -306,23 +325,31 @@ let plus_attachable only_plus (tok,_) =
   | PC.TString(_,clt) | PC.TChar(_,clt) | PC.TFloat(_,clt) | PC.TInt(_,clt)
 
   | PC.TOrLog(clt) | PC.TAndLog(clt) | PC.TOr(clt) | PC.TXor(clt)
-  | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TTildeEq(clt) | PC.TLogOp(_,clt)
-  | PC.TShOp(_,clt) | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
+  | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TTildeEq(clt)
+  | PC.TLogOp(_,clt)
+  | PC.TShLOp(_,clt) | PC.TShROp(_,clt)
+  | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
   | PC.TDmOp(_,clt) | PC.TTilde (clt)
 
-  | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
+  | PC.TMeta(_,_,clt) | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
   | PC.TMetaConst(_,_,_,_,clt) | PC.TMetaErr(_,_,_,clt)
   | PC.TMetaExp(_,_,_,_,clt) | PC.TMetaIdExp(_,_,_,_,clt)
   | PC.TMetaLocalIdExp(_,_,_,_,clt)
   | PC.TMetaExpList(_,_,_,clt)
-  | PC.TMetaId(_,_,_,clt)
-  | PC.TMetaType(_,_,clt) | PC.TMetaInit(_,_,clt) | PC.TMetaStm(_,_,clt)
-  | PC.TMetaStmList(_,_,clt)  | PC.TMetaFunc(_,_,_,clt)
-  | PC.TMetaLocalFunc(_,_,_,clt)
+  | PC.TMetaId(_,_,_,_,clt)
+  | PC.TMetaType(_,_,clt) | PC.TMetaInit(_,_,clt) | PC.TMetaInitList(_,_,_,clt)
+  | PC.TMetaStm(_,_,clt)
+  | PC.TMetaStmList(_,_,clt)
+  | PC.TMetaDecl(_,_,clt) | PC.TMetaField(_,_,clt)
+  | PC.TMetaFieldList(_,_,_,clt)
+  | PC.TMetaFunc(_,_,_,clt) | PC.TMetaLocalFunc(_,_,_,clt)
 
   | PC.TWhen(clt) |  PC.TWhenTrue(clt) |  PC.TWhenFalse(clt)
   | PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
   (* | PC.TCircles(clt) | PC.TStars(clt) *)
+  | PC.TOEllipsis(clt) | PC.TCEllipsis(clt)
+  | PC.TPOEllipsis(clt) | PC.TPCEllipsis(clt) (* | PC.TOCircles(clt)
+  | PC.TCCircles(clt) | PC.TOStars(clt) | PC.TCStars(clt) *)
 
   | PC.TWhy(clt) | PC.TDotDot(clt) | PC.TBang(clt) | PC.TOPar(clt)
   | PC.TCPar(clt)
@@ -339,24 +366,25 @@ let plus_attachable only_plus (tok,_) =
       else if only_plus then NOTPLUS
       else if line_type clt = D.CONTEXT then PLUS else NOTPLUS
 
-  | PC.TOPar0(clt) | PC.TMid0(clt) | PC.TCPar0(clt)
-  | PC.TOEllipsis(clt) | PC.TCEllipsis(clt)
-  | PC.TPOEllipsis(clt) | PC.TPCEllipsis(clt) (* | PC.TOCircles(clt)
-  | PC.TCCircles(clt) | PC.TOStars(clt) | PC.TCStars(clt) *) -> NOTPLUS
+  | PC.TOPar0(clt) | PC.TMid0(clt) | PC.TCPar0(clt) -> NOTPLUS
   | PC.TMetaPos(nm,_,_,_) -> NOTPLUS
+  | PC.TSub(clt) -> NOTPLUS
 
   | _ -> SKIP
 
 let get_clt (tok,_) =
   match tok with
     PC.Tchar(clt) | PC.Tshort(clt) | PC.Tint(clt) | PC.Tdouble(clt)
-  | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt) | PC.Tstruct(clt)
+  | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt)
+  | PC.Tsize_t(clt) | PC.Tssize_t(clt) | PC.Tptrdiff_t(clt)
+  | PC.Tstruct(clt)
   | PC.Tunion(clt) | PC.Tenum(clt) | PC.Tunsigned(clt) | PC.Tsigned(clt)
   | PC.Tstatic(clt)
   | PC.Tinline(clt) | PC.Tattr(_,clt) | PC.Tauto(clt) | PC.Tregister(clt)
   | PC.Textern(clt) | PC.Tconst(clt) | PC.Tvolatile(clt)
 
-  | PC.TIncludeL(_,clt) | PC.TIncludeNL(_,clt) | PC.TDefine(clt,_)
+  | PC.TIncludeL(_,clt) | PC.TIncludeNL(_,clt) | PC.TUndef(clt,_)
+  | PC.TDefine(clt,_)
   | PC.TDefineParam(clt,_,_,_) | PC.TMinusFile(_,clt) | PC.TPlusFile(_,clt)
 
   | PC.TInc(clt) | PC.TDec(clt)
@@ -371,19 +399,25 @@ let get_clt (tok,_) =
   | PC.TString(_,clt) | PC.TChar(_,clt) | PC.TFloat(_,clt) | PC.TInt(_,clt)
 
   | PC.TOrLog(clt) | PC.TAndLog(clt) | PC.TOr(clt) | PC.TXor(clt)
-  | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TTildeEq(clt) | PC.TLogOp(_,clt)
-  | PC.TShOp(_,clt) | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
+  | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TTildeEq(clt)
+  | PC.TSub(clt) | PC.TLogOp(_,clt)
+  | PC.TShLOp(_,clt) | PC.TShROp(_,clt)
+  | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
   | PC.TDmOp(_,clt) | PC.TTilde (clt)
 
-  | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
+  | PC.TMeta(_,_,clt) | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
   | PC.TMetaConst(_,_,_,_,clt) | PC.TMetaErr(_,_,_,clt)
   | PC.TMetaExp(_,_,_,_,clt) | PC.TMetaIdExp(_,_,_,_,clt)
   | PC.TMetaLocalIdExp(_,_,_,_,clt)
   | PC.TMetaExpList(_,_,_,clt)
-  | PC.TMetaId(_,_,_,clt)
-  | PC.TMetaType(_,_,clt) | PC.TMetaInit(_,_,clt) | PC.TMetaStm(_,_,clt)
-  | PC.TMetaStmList(_,_,clt)  | PC.TMetaFunc(_,_,_,clt)
-  | PC.TMetaLocalFunc(_,_,_,clt) | PC.TMetaPos(_,_,_,clt)
+  | PC.TMetaId(_,_,_,_,clt)
+  | PC.TMetaType(_,_,clt) | PC.TMetaInit(_,_,clt) | PC.TMetaInitList(_,_,_,clt)
+  | PC.TMetaStm(_,_,clt)
+  | PC.TMetaStmList(_,_,clt)
+  | PC.TMetaDecl(_,_,clt) | PC.TMetaField(_,_,clt)
+  | PC.TMetaFieldList(_,_,_,clt)
+  | PC.TMetaFunc(_,_,_,clt) | PC.TMetaLocalFunc(_,_,_,clt)
+  | PC.TMetaPos(_,_,_,clt)
 
   | PC.TWhen(clt) | PC.TWhenTrue(clt) | PC.TWhenFalse(clt) |
     PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
@@ -416,6 +450,9 @@ let update_clt (tok,x) clt =
   | PC.Tfloat(_) -> (PC.Tfloat(clt),x)
   | PC.Tlong(_) -> (PC.Tlong(clt),x)
   | PC.Tvoid(_) -> (PC.Tvoid(clt),x)
+  | PC.Tsize_t(_) -> (PC.Tsize_t(clt),x)
+  | PC.Tssize_t(_) -> (PC.Tssize_t(clt),x)
+  | PC.Tptrdiff_t(_) -> (PC.Tptrdiff_t(clt),x)
   | PC.Tstruct(_) -> (PC.Tstruct(clt),x)
   | PC.Tunion(_) -> (PC.Tunion(clt),x)
   | PC.Tenum(_) -> (PC.Tenum(clt),x)
@@ -433,6 +470,7 @@ let update_clt (tok,x) clt =
 
   | PC.TIncludeL(s,_) -> (PC.TIncludeL(s,clt),x)
   | PC.TIncludeNL(s,_) -> (PC.TIncludeNL(s,clt),x)
+  | PC.TUndef(_,a) -> (PC.TUndef(clt,a),x)
   | PC.TDefine(_,a) -> (PC.TDefine(clt,a),x)
   | PC.TDefineParam(_,a,b,c) -> (PC.TDefineParam(clt,a,b,c),x)
   | PC.TMinusFile(s,_) -> (PC.TMinusFile(s,clt),x)
@@ -473,14 +511,17 @@ let update_clt (tok,x) clt =
   | PC.TEqEq(_) -> (PC.TEqEq(clt),x)
   | PC.TNotEq(_) -> (PC.TNotEq(clt),x)
   | PC.TTildeEq(_) -> (PC.TTildeEq(clt),x)
+  | PC.TSub(_) -> (PC.TSub(clt),x)
   | PC.TLogOp(op,_) -> (PC.TLogOp(op,clt),x)
-  | PC.TShOp(op,_) -> (PC.TShOp(op,clt),x)
+  | PC.TShLOp(op,_) -> (PC.TShLOp(op,clt),x)
+  | PC.TShROp(op,_) -> (PC.TShROp(op,clt),x)
   | PC.TPlus(_) -> (PC.TPlus(clt),x)
   | PC.TMinus(_) -> (PC.TMinus(clt),x)
   | PC.TMul(_) -> (PC.TMul(clt),x)
   | PC.TDmOp(op,_) -> (PC.TDmOp(op,clt),x)
   | PC.TTilde (_) -> (PC.TTilde (clt),x)
 
+  | PC.TMeta(a,b,_)      -> (PC.TMeta(a,b,clt),x)
   | PC.TMetaParam(a,b,_) -> (PC.TMetaParam(a,b,clt),x)
   | PC.TMetaParamList(a,b,c,_) -> (PC.TMetaParamList(a,b,c,clt),x)
   | PC.TMetaConst(a,b,c,d,_) -> (PC.TMetaConst(a,b,c,d,clt),x)
@@ -489,11 +530,15 @@ let update_clt (tok,x) clt =
   | PC.TMetaIdExp(a,b,c,d,_) -> (PC.TMetaIdExp(a,b,c,d,clt),x)
   | PC.TMetaLocalIdExp(a,b,c,d,_) -> (PC.TMetaLocalIdExp(a,b,c,d,clt),x)
   | PC.TMetaExpList(a,b,c,_) -> (PC.TMetaExpList(a,b,c,clt),x)
-  | PC.TMetaId(a,b,c,_)    -> (PC.TMetaId(a,b,c,clt),x)
+  | PC.TMetaId(a,b,c,d,_)    -> (PC.TMetaId(a,b,c,d,clt),x)
   | PC.TMetaType(a,b,_)    -> (PC.TMetaType(a,b,clt),x)
   | PC.TMetaInit(a,b,_)    -> (PC.TMetaInit(a,b,clt),x)
-  | PC.TMetaStm(a,b,_)   -> (PC.TMetaStm(a,b,clt),x)
-  | PC.TMetaStmList(a,b,_)   -> (PC.TMetaStmList(a,b,clt),x)
+  | PC.TMetaInitList(a,b,c,_) -> (PC.TMetaInitList(a,b,c,clt),x)
+  | PC.TMetaDecl(a,b,_)    -> (PC.TMetaDecl(a,b,clt),x)
+  | PC.TMetaField(a,b,_)   -> (PC.TMetaField(a,b,clt),x)
+  | PC.TMetaFieldList(a,b,c,_)   -> (PC.TMetaFieldList(a,b,c,clt),x)
+  | PC.TMetaStm(a,b,_)     -> (PC.TMetaStm(a,b,clt),x)
+  | PC.TMetaStmList(a,b,_) -> (PC.TMetaStmList(a,b,clt),x)
   | PC.TMetaFunc(a,b,c,_)  -> (PC.TMetaFunc(a,b,c,clt),x)
   | PC.TMetaLocalFunc(a,b,c,_) -> (PC.TMetaLocalFunc(a,b,c,clt),x)
 
@@ -600,7 +645,9 @@ let split t clt =
 
 let split_token ((tok,_) as t) =
   match tok with
-    PC.TIdentifier | PC.TConstant | PC.TExpression | PC.TIdExpression
+    PC.TMetavariable | PC.TIdentifier
+  | PC.TConstant | PC.TExpression | PC.TIdExpression
+  | PC.TDeclaration | PC.TField
   | PC.TStatement | PC.TPosition | PC.TPosAny | PC.TInitialiser
   | PC.TFunction | PC.TTypedef | PC.TDeclarer | PC.TIterator | PC.TName
   | PC.TType | PC.TParameter | PC.TLocal | PC.Tlist | PC.TFresh
@@ -611,7 +658,9 @@ let split_token ((tok,_) as t) =
   | PC.TError | PC.TWords | PC.TGenerated | PC.TNothing -> ([t],[t])
 
   | PC.Tchar(clt) | PC.Tshort(clt) | PC.Tint(clt) | PC.Tdouble(clt)
-  | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt) | PC.Tstruct(clt)
+  | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt)
+  | PC.Tsize_t(clt) | PC.Tssize_t(clt) | PC.Tptrdiff_t(clt)
+  | PC.Tstruct(clt)
   | PC.Tunion(clt) | PC.Tenum(clt) | PC.Tunsigned(clt) | PC.Tsigned(clt)
   | PC.Tstatic(clt) | PC.Tauto(clt) | PC.Tregister(clt) | PC.Textern(clt)
   | PC.Tinline(clt) | PC.Ttypedef(clt) | PC.Tattr(_,clt)
@@ -621,7 +670,8 @@ let split_token ((tok,_) as t) =
   | PC.TPlusFile(s,clt) | PC.TMinusFile(s,clt)
   | PC.TIncludeL(s,clt) | PC.TIncludeNL(s,clt) ->
       split t clt
-  | PC.TDefine(clt,_) | PC.TDefineParam(clt,_,_,_) -> split t clt
+  | PC.TUndef(clt,_) | PC.TDefine(clt,_) | PC.TDefineParam(clt,_,_,_) ->
+      split t clt
 
   | PC.TIf(clt) | PC.TElse(clt)  | PC.TWhile(clt) | PC.TFor(clt) | PC.TDo(clt)
   | PC.TSwitch(clt) | PC.TCase(clt) | PC.TDefault(clt)
@@ -629,11 +679,14 @@ let split_token ((tok,_) as t) =
   | PC.TReturn(clt) | PC.TBreak(clt) | PC.TContinue(clt) | PC.TGoto(clt)
   | PC.TIdent(_,clt)
   | PC.TTypeId(_,clt) | PC.TDeclarerId(_,clt) | PC.TIteratorId(_,clt)
-  | PC.TMetaConst(_,_,_,_,clt) | PC.TMetaExp(_,_,_,_,clt)
+  | PC.TMeta(_,_,clt) | PC.TMetaConst(_,_,_,_,clt) | PC.TMetaExp(_,_,_,_,clt)
   | PC.TMetaIdExp(_,_,_,_,clt) | PC.TMetaLocalIdExp(_,_,_,_,clt)
   | PC.TMetaExpList(_,_,_,clt)
   | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
-  | PC.TMetaId(_,_,_,clt) | PC.TMetaType(_,_,clt) | PC.TMetaInit(_,_,clt)
+  | PC.TMetaId(_,_,_,_,clt) | PC.TMetaType(_,_,clt)
+  | PC.TMetaInit(_,_,clt) | PC.TMetaInitList(_,_,_,clt)
+  | PC.TMetaDecl(_,_,clt) | PC.TMetaField(_,_,clt)
+  | PC.TMetaFieldList(_,_,_,clt)
   | PC.TMetaStm(_,_,clt) | PC.TMetaStmList(_,_,clt) | PC.TMetaErr(_,_,_,clt)
   | PC.TMetaFunc(_,_,_,clt) | PC.TMetaLocalFunc(_,_,_,clt)
   | PC.TMetaDeclarer(_,_,_,clt) | PC.TMetaIterator(_,_,_,clt) -> split t clt
@@ -644,14 +697,15 @@ let split_token ((tok,_) as t) =
   | PC.TFunDecl(clt)
   | PC.TWhen(clt) | PC.TWhenTrue(clt) | PC.TWhenFalse(clt)
   | PC.TAny(clt) | PC.TStrict(clt) | PC.TLineEnd(clt)
-  | PC.TEllipsis(clt) (* | PC.TCircles(clt) | PC.TStars(clt) *) -> split t clt
+  | PC.TEllipsis(clt) (* | PC.TCircles(clt) | PC.TStars(clt) *)
+  | PC.TOEllipsis(clt) | PC.TCEllipsis(clt)
+  | PC.TPOEllipsis(clt) | PC.TPCEllipsis(clt) -> split t clt
 
-  | PC.TOEllipsis(_) | PC.TCEllipsis(_) (* clt must be context *)
-  | PC.TPOEllipsis(_) | PC.TPCEllipsis(_) (* clt must be context *)
 (*
   | PC.TOCircles(_) | PC.TCCircles(_)   (* clt must be context *)
   | PC.TOStars(_) | PC.TCStars(_)       (* clt must be context *)
 *)
+
   | PC.TBang0 | PC.TPlus0 | PC.TWhy0 ->
       ([t],[t])
 
@@ -665,8 +719,10 @@ let split_token ((tok,_) as t) =
       split t clt
 
   | PC.TOrLog(clt) | PC.TAndLog(clt) | PC.TOr(clt) | PC.TXor(clt)
-  | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TTildeEq(clt) | PC.TTildeExclEq(clt) | PC.TLogOp(_,clt)
-  | PC.TShOp(_,clt) | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
+  | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TTildeEq(clt)
+  | PC.TTildeExclEq(clt) | PC.TSub(clt) | PC.TLogOp(_,clt)
+  | PC.TShLOp(_,clt) | PC.TShROp(_,clt)
+  | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
   | PC.TDmOp(_,clt) | PC.TTilde (clt) -> split t clt
 
   | PC.TOBrace(clt) | PC.TCBrace(clt) | PC.TOInit(clt) -> split t clt
@@ -677,7 +733,7 @@ let split_token ((tok,_) as t) =
   | PC.TEq(clt) | PC.TAssign(_,clt) | PC.TDot(clt) | PC.TComma(clt)
   | PC.TPtVirg(clt) -> split t clt
 
-  | PC.EOF | PC.TInvalid -> ([t],[t])
+  | PC.EOF | PC.TInvalid | PC.TUnderscore -> ([t],[t])
 
   | PC.TIso | PC.TRightIso
   | PC.TIsoExpression | PC.TIsoStatement | PC.TIsoDeclaration | PC.TIsoType
@@ -702,35 +758,77 @@ distinguish a function declaration from a function call even if the latter
 has no return type.  Undoubtedly, this is not very nice, but it doesn't
 seem very convenient to refactor the grammar to get around the problem. *)
 
-let rec find_function_names = function
-    [] -> []
-  | ((PC.TIdent(_,clt),info) as t1) :: ((PC.TOPar(_),_) as t2) :: rest
-  | ((PC.TMetaId(_,_,_,clt),info) as t1) :: ((PC.TOPar(_),_) as t2) :: rest
-  | ((PC.TMetaFunc(_,_,_,clt),info) as t1) :: ((PC.TOPar(_),_) as t2) :: rest
-  | ((PC.TMetaLocalFunc(_,_,_,clt),info) as t1)::((PC.TOPar(_),_) as t2)::rest
-    ->
-      let rec skip level = function
-         [] -> ([],false,[])
-       | ((PC.TCPar(_),_) as t)::rest ->
-           let level = level - 1 in
-           if level = 0
-           then ([t],true,rest)
-           else let (pre,found,post) = skip level rest in (t::pre,found,post)
-       | ((PC.TOPar(_),_) as t)::rest ->
-           let level = level + 1 in
-           let (pre,found,post) = skip level rest in (t::pre,found,post)
-       | ((PC.TArobArob,_) as t)::rest
-       | ((PC.TArob,_) as t)::rest
-       | ((PC.EOF,_) as t)::rest -> ([t],false,rest)
-       | t::rest ->
-           let (pre,found,post) = skip level rest in (t::pre,found,post) in
-      let (pre,found,post) = skip 1 rest in
-      (match (found,post) with
-       (true,((PC.TOBrace(_),_) as t3)::rest) ->
-         (PC.TFunDecl(clt),info) :: t1 :: t2 :: pre @
-         t3 :: (find_function_names rest)
-      |        _ -> t1 :: t2 :: pre @ find_function_names post)
-  | t :: rest -> t :: find_function_names rest
+exception Irrelevant
+
+let rec find_function_names l =
+  let is_ident = function
+      (PC.TIdent(_,clt),info)
+    | (PC.TMeta(_,_,clt),info)
+    | (PC.TMetaId(_,_,_,_,clt),info)
+    | (PC.TMetaFunc(_,_,_,clt),info)
+    | (PC.TMetaLocalFunc(_,_,_,clt),info) -> true
+    | _ -> false in
+  let is_mid = function
+      (PC.TMid0(_),info) -> true
+    | _ -> false in
+  let is_par = function
+      (PC.TOPar0(_),info) -> true
+    | _ -> false in
+  let rec split acc = function
+      [] | [_] -> raise Irrelevant
+    | ((PC.TCPar(_),_) as t1) :: ((PC.TOBrace(_),_) as t2) :: rest ->
+       (List.rev (t1::acc),(t2::rest))
+    | x::xs -> split (x::acc) xs in
+  let rec balanced_name level = function
+      [] -> raise Irrelevant
+    | (PC.TCPar0(_),_)::rest ->
+       let level = level - 1 in
+       if level = 0
+       then rest
+       else balanced_name level rest
+    | (PC.TOPar0(_),_)::rest ->
+       let level = level + 1 in
+       balanced_name level rest
+    | (PC.TArobArob,_)::_ | (PC.TArob,_)::_ | (PC.EOF,_)::_ ->
+       raise Irrelevant
+    | t::rest when is_ident t && level = 0 -> rest
+    | t::rest when is_ident t or is_mid t -> balanced_name level rest
+    | _ -> raise Irrelevant in
+  let rec balanced_args level = function
+      [] -> raise Irrelevant
+    | (PC.TCPar(_),_)::rest ->
+       let level = level - 1 in
+       if level = 0
+       then rest
+       else balanced_args level rest
+    | (PC.TOPar(_),_)::rest ->
+       let level = level + 1 in
+       balanced_args level rest
+    | (PC.TArobArob,_)::_ | (PC.TArob,_)::_ | (PC.EOF,_)::_ ->
+       raise Irrelevant
+    | t::rest -> balanced_args level rest in
+  let rec loop = function
+      [] -> []
+    | t :: rest ->
+       if is_par t or is_mid t or is_ident t
+       then
+         let (t,rest) =
+           try
+             let (bef,aft) = split [] (t::rest) in
+             let rest = balanced_name 0 bef in
+             (match rest with
+               (PC.TOPar(_),_)::_ ->
+                 (match balanced_args 0 rest with
+                   [] ->
+                     let (_,info) as h = List.hd bef in
+                     let clt = get_clt h in
+                     (((PC.TFunDecl(clt),info) :: bef), aft)
+                 | _ -> raise Irrelevant)
+             | _ -> raise Irrelevant)
+           with Irrelevant -> ([t],rest) in
+         t @ (loop rest)
+       else t :: (loop rest) in
+  loop l
 
 (* ----------------------------------------------------------------------- *)
 (* an attribute is an identifier that preceeds another identifier and
@@ -738,7 +836,7 @@ let rec find_function_names = function
 
 let rec detect_attr l =
   let is_id = function
-      (PC.TIdent(_,_),_) | (PC.TMetaId(_,_,_,_),_) | (PC.TMetaFunc(_,_,_,_),_)
+      (PC.TIdent(_,_),_) | (PC.TMetaId(_,_,_,_,_),_) | (PC.TMetaFunc(_,_,_,_),_)
     | (PC.TMetaLocalFunc(_,_,_,_),_) -> true
     | _ -> false in
   let rec loop = function
@@ -774,7 +872,7 @@ let detect_types in_meta_decls l =
   let is_choices_delim = function
       (PC.TOBrace(_),_) | (PC.TComma(_),_) -> true | _ -> false in
   let is_id = function
-      (PC.TIdent(_,_),_) | (PC.TMetaId(_,_,_,_),_) | (PC.TMetaFunc(_,_,_,_),_)
+      (PC.TIdent(_,_),_) | (PC.TMetaId(_,_,_,_,_),_) | (PC.TMetaFunc(_,_,_,_),_)
     | (PC.TMetaLocalFunc(_,_,_,_),_) -> true
     | (PC.TMetaParam(_,_,_),_)
     | (PC.TMetaParamList(_,_,_,_),_)
@@ -786,6 +884,10 @@ let detect_types in_meta_decls l =
     | (PC.TMetaExpList(_,_,_,_),_)
     | (PC.TMetaType(_,_,_),_)
     | (PC.TMetaInit(_,_,_),_)
+    | (PC.TMetaInitList(_,_,_,_),_)
+    | (PC.TMetaDecl(_,_,_),_)
+    | (PC.TMetaField(_,_,_),_)
+    | (PC.TMetaFieldList(_,_,_,_),_)
     | (PC.TMetaStm(_,_,_),_)
     | (PC.TMetaStmList(_,_,_),_)
     | (PC.TMetaPos(_,_,_,_),_) -> in_meta_decls
@@ -847,7 +949,9 @@ let detect_types in_meta_decls l =
 let token2line (tok,_) =
   match tok with
     PC.Tchar(clt) | PC.Tshort(clt) | PC.Tint(clt) | PC.Tdouble(clt)
-  | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt) | PC.Tstruct(clt)
+  | PC.Tfloat(clt) | PC.Tlong(clt) | PC.Tvoid(clt)
+  | PC.Tsize_t(clt) | PC.Tssize_t(clt) | PC.Tptrdiff_t(clt)
+  | PC.Tstruct(clt)
   | PC.Tunion(clt) | PC.Tenum(clt) | PC.Tunsigned(clt) | PC.Tsigned(clt)
   | PC.Tstatic(clt) | PC.Tauto(clt) | PC.Tregister(clt) | PC.Textern(clt)
   | PC.Tinline(clt) | PC.Ttypedef(clt) | PC.Tattr(_,clt) | PC.Tconst(clt)
@@ -866,14 +970,18 @@ let token2line (tok,_) =
 
   | PC.TOrLog(clt) | PC.TAndLog(clt) | PC.TOr(clt) | PC.TXor(clt)
   | PC.TAnd (clt) | PC.TEqEq(clt) | PC.TNotEq(clt) | PC.TLogOp(_,clt)
-  | PC.TShOp(_,clt) | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
+  | PC.TShLOp(_,clt) | PC.TShROp(_,clt)
+  | PC.TPlus(clt) | PC.TMinus(clt) | PC.TMul(clt)
   | PC.TDmOp(_,clt) | PC.TTilde (clt)
 
-  | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
+  | PC.TMeta(_,_,clt) | PC.TMetaParam(_,_,clt) | PC.TMetaParamList(_,_,_,clt)
   | PC.TMetaConst(_,_,_,_,clt) | PC.TMetaExp(_,_,_,_,clt)
   | PC.TMetaIdExp(_,_,_,_,clt) | PC.TMetaLocalIdExp(_,_,_,_,clt)
   | PC.TMetaExpList(_,_,_,clt)
-  | PC.TMetaId(_,_,_,clt) | PC.TMetaType(_,_,clt) | PC.TMetaInit(_,_,clt)
+  | PC.TMetaId(_,_,_,_,clt) | PC.TMetaType(_,_,clt)
+  | PC.TMetaInit(_,_,clt) | PC.TMetaInitList(_,_,_,clt)
+  | PC.TMetaDecl(_,_,clt) | PC.TMetaField(_,_,clt)
+  | PC.TMetaFieldList(_,_,_,clt)
   | PC.TMetaStm(_,_,clt) | PC.TMetaStmList(_,_,clt) | PC.TMetaFunc(_,_,_,clt)
   | PC.TMetaLocalFunc(_,_,_,clt) | PC.TMetaPos(_,_,_,clt)
 
@@ -895,7 +1003,7 @@ let token2line (tok,_) =
 
   | PC.TPtrOp(clt)
 
-  | PC.TDefine(clt,_) | PC.TDefineParam(clt,_,_,_)
+  | PC.TUndef(clt,_) | PC.TDefine(clt,_) | PC.TDefineParam(clt,_,_,_)
   | PC.TIncludeL(_,clt) | PC.TIncludeNL(_,clt)
 
   | PC.TEq(clt) | PC.TAssign(_,clt) | PC.TDot(clt) | PC.TComma(clt)
@@ -908,6 +1016,7 @@ let rec insert_line_end = function
     [] -> []
   | (((PC.TWhen(clt),q) as x)::xs) ->
       x::(find_line_end true (token2line x) clt q xs)
+  | (((PC.TUndef(clt,_),q) as x)::xs)
   | (((PC.TDefine(clt,_),q) as x)::xs)
   | (((PC.TDefineParam(clt,_,_,_),q) as x)::xs) ->
       x::(find_line_end false (token2line x) clt q xs)
@@ -946,6 +1055,36 @@ let rec translate_when_true_false = function
 
 (* ----------------------------------------------------------------------- *)
 
+(* In a nest, if the nest is -, all of the nested code must also be -.
+All are converted to context, because the next takes care of the -. *)
+let check_nests tokens =
+  let is_minus t =
+    let (line_type,a,b,c,d,e,f,g) = get_clt t in
+    List.mem line_type [D.MINUS;D.OPTMINUS;D.UNIQUEMINUS] in
+  let drop_minus t =
+    let clt = try Some(get_clt t) with Failure _ -> None in
+       match clt with
+         Some (line_type,a,b,c,d,e,f,g) ->
+           (match line_type with
+             D.MINUS -> update_clt t (D.CONTEXT,a,b,c,d,e,f,g)
+           | D.OPTMINUS -> update_clt t (D.OPT,a,b,c,d,e,f,g)
+           | D.UNIQUEMINUS -> update_clt t (D.UNIQUE,a,b,c,d,e,f,g)
+           | _ -> failwith "minus token expected")
+       | None -> t in
+  let rec outside = function
+      [] -> []
+    | ((PC.TPOEllipsis(clt),q) as t)::r when is_minus t -> t :: inside 0 r
+    | t::r -> t :: outside r
+  and inside stack = function
+      [] -> failwith "missing nest end"
+    | ((PC.TPCEllipsis(clt),q) as t)::r ->
+       (drop_minus t)
+       :: (if stack = 0 then outside r else inside (stack - 1) r)
+    | ((PC.TPOEllipsis(clt),q) as t)::r ->
+       (drop_minus t) :: (inside (stack + 1) r)
+    | t :: r -> (drop_minus t) :: (inside stack r) in
+  outside tokens
+
 let check_parentheses tokens =
   let clt2line (_,line,_,_,_,_,_,_) = line in
   let rec loop seen_open = function
@@ -1043,12 +1182,17 @@ let add_bef = function Some x -> [x] | None -> []
 
 (*skips should be things like line end
 skips is things before pragmas that can't be attached to, pass is things
-after.  pass is used immediately.  skips accumulates. *)
+after.  pass is used immediately.  skips accumulates.
+When stuff is added before some + code, the logical line of the + code
+becomes that of the pragma.  context_neg relies on things that are adjacent
+having sequential logical lines.  Not sure that this is good enough,
+as it might result in later gaps in the logical lines... *)
 let rec process_pragmas bef skips = function
     [] -> add_bef bef @ List.rev skips
   | ((PC.TPragma(s,i),_)::_) as l ->
       let (pragmas,rest) = collect_all_pragmas [] l in
       let (pass,rest0) = collect_pass rest in
+      let (_,_,prag_lline,_,_,_,_,_) = i in
       let (next,rest) =
        match rest0 with [] -> (None,[]) | next::rest -> (Some next,rest) in
       (match (bef,plus_attach true bef,next,plus_attach true next) with
@@ -1057,10 +1201,10 @@ let rec process_pragmas bef skips = function
          (update_clt bef (a,b,c,d,e,strbef,pragmas,pos))::List.rev skips@
          pass@process_pragmas None [] rest0
       |        (_,_,Some next,PLUS) ->
-         let (a,b,c,d,e,strbef,straft,pos) = get_clt next in
+         let (a,b,lline,d,e,strbef,straft,pos) = get_clt next in
          (add_bef bef) @ List.rev skips @ pass @
          (process_pragmas
-            (Some (update_clt next (a,b,c,d,e,pragmas,straft,pos)))
+            (Some (update_clt next (a,b,prag_lline,d,e,pragmas,straft,pos)))
             [] rest)
       |        _ ->
          (match (bef,plus_attach false bef,next,plus_attach false next) with
@@ -1069,10 +1213,11 @@ let rec process_pragmas bef skips = function
              (update_clt bef (a,b,c,d,e,strbef,pragmas,pos))::List.rev skips@
              pass@process_pragmas None [] rest0
          | (_,_,Some next,PLUS) ->
-             let (a,b,c,d,e,strbef,straft,pos) = get_clt next in
+             let (a,b,lline,d,e,strbef,straft,pos) = get_clt next in
              (add_bef bef) @ List.rev skips @ pass @
              (process_pragmas
-                (Some (update_clt next (a,b,c,d,e,pragmas,straft,pos)))
+                (Some
+                   (update_clt next (a,b,prag_lline,d,e,pragmas,straft,pos)))
                 [] rest)
          | _ -> failwith "nothing to attach pragma to"))
   | x::xs ->
@@ -1149,6 +1294,8 @@ let rec drop_double_dots l =
       [] -> []
     | x::rest when any_before prev && any_after x ->
        (PC.TNothing,i)::x::(loop x rest)
+    | ((PC.TComma(_),_) as c)::x::rest when any_before prev && any_after x ->
+       c::(PC.TNothing,i)::x::(loop x rest)
     | x::rest -> x :: (loop x rest) in
   match l with
     [] -> []
@@ -1236,7 +1383,10 @@ let prepare_tokens tokens =
     (translate_when_true_false (* after insert_line_end *)
        (insert_line_end
          (detect_types false
-            (find_function_names (detect_attr (check_parentheses tokens))))))
+            (find_function_names
+               (detect_attr
+                  (check_nests
+                     (check_parentheses tokens)))))))
 
 let prepare_mv_tokens tokens =
   detect_types false (detect_attr tokens)
@@ -1246,13 +1396,13 @@ let rec consume_minus_positions = function
   | ((PC.TOPar0(_),_) as x)::xs | ((PC.TCPar0(_),_) as x)::xs
   | ((PC.TMid0(_),_) as x)::xs -> x::consume_minus_positions xs
   | x::(PC.TPArob,_)::(PC.TMetaPos(name,constraints,per,clt),_)::xs ->
-      let (arity,ln,lln,offset,col,strbef,straft,_) = get_clt x in
+      let (arity,ln,lln,offset,col,strbef,straft,pos) = get_clt x in
       let name = Parse_aux.clt2mcode name clt in
       let x =
        update_clt x
          (arity,ln,lln,offset,col,strbef,straft,
-          Ast0.MetaPos(name,constraints,per)) in
-      x::(consume_minus_positions xs)
+          (Ast0.MetaPos(name,constraints,per)::pos)) in
+      (consume_minus_positions (x::xs))
   | x::xs -> x::consume_minus_positions xs
 
 let any_modif rule =
@@ -1275,9 +1425,7 @@ let eval_virt virt =
   List.iter
     (function x ->
       if not (List.mem x virt)
-      then
-        failwith
-          (Printf.sprintf "unknown virtual rule %s\n" x))
+      then raise (Bad_virt x))
     !Flag.defined_virtual_rules
 
 let drop_last extra l = List.rev(extra@(List.tl(List.rev l)))
@@ -1336,9 +1484,12 @@ let get_rule_name parse_fn starts_with_name get_tokens file prefix =
           Ast.CocciRulename (check_name nm,a,b,c,d,e)
       | Ast.GeneratedRulename (nm,a,b,c,d,e) ->
           Ast.GeneratedRulename (check_name nm,a,b,c,d,e)
-      | Ast.ScriptRulename(s,deps) -> Ast.ScriptRulename(s,deps)
-      | Ast.InitialScriptRulename(s,deps) -> Ast.InitialScriptRulename(s,deps)
-      | Ast.FinalScriptRulename(s,deps) -> Ast.FinalScriptRulename(s,deps)
+      | Ast.ScriptRulename(nm,s,deps) ->
+         Ast.ScriptRulename(check_name nm,s,deps)
+      | Ast.InitialScriptRulename(_,s,deps) ->
+         Ast.InitialScriptRulename(check_name None,s,deps)
+      | Ast.FinalScriptRulename(_,s,deps) ->
+         Ast.FinalScriptRulename(check_name None,s,deps)
     else
       Ast.CocciRulename(Some(mknm()),Ast.NoDep,[],[],Ast.Undetermined,false) in
   Data.in_rule_name := false;
@@ -1384,7 +1535,7 @@ let parse_iso file =
            let tokens = prepare_tokens (start@tokens) in
             (*
               print_tokens "iso tokens" tokens;
-           *)
+           å*)
            let entry = parse_one "iso main" PC.iso_main file tokens in
            let entry = List.map (List.map Test_exps.process_anything) entry in
            if more
@@ -1462,6 +1613,7 @@ let eval_depend dep virt =
 let parse file =
   Lexer_cocci.init();
   let rec parse_loop file =
+  Lexer_cocci.include_init ();
   let table = Common.full_charpos_to_pos file in
   Common.with_open_infile file (fun channel ->
   let lexbuf = Lexing.from_channel channel in
@@ -1489,16 +1641,17 @@ let parse file =
          List.iter (function x -> Hashtbl.add Lexer_cocci.rule_names x ())
            virt;
 
-         let (extra_iso_files, extra_rules, extra_virt) =
+         let (extra_iso_files, extra_rules, extra_virt, extra_metas) =
            let rec loop = function
-               [] -> ([],[],[])
-             | (a,b,c)::rest ->
-                 let (x,y,z) = loop rest in
-                 (a::x,b::y,c::z) in
+               [] -> ([],[],[],[])
+             | (a,b,c,d)::rest ->
+                 let (x,y,z,zz) = loop rest in
+                 (a::x,b::y,c::z,d@zz) in
            loop (List.map parse_loop include_files) in
 
           let parse_cocci_rule ruletype old_metas
              (rule_name, dependencies, iso, dropiso, exists, is_expression) =
+           let dropiso = !Flag_parsing_cocci.disabled_isos @ dropiso in
             Ast0.rule_name := rule_name;
             Data.inheritable_positions :=
                rule_name :: !Data.inheritable_positions;
@@ -1556,17 +1709,33 @@ let parse file =
              then (* not actually used for anything, except context_neg *)
                List.map
                  (Iso_pattern.rebuild_mcode None).VT0.rebuilder_rec_top_level
-                 minus_res
+                 (Top_level.top_level false minus_res)
              else
                if is_expression
                then parse_one "plus" PC.plus_exp_main file plus_tokens
                else parse_one "plus" PC.plus_main file plus_tokens in
+           let plus_res = Top_level.top_level false plus_res in
+           (* minus code has to be CODE if the + code is CODE, otherwise
+              doesn't matter if + code is CODE or DECL or TOPCODE *)
+           let minus_res =
+             let any_code =
+               List.exists
+                 (function x ->
+                   match Ast0.unwrap x with Ast0.CODE _ -> true | _ -> false)
+                 plus_res in
+             if any_code
+             then Top_level.top_level true minus_res
+             else Top_level.top_level false minus_res in
+           let minus_res = Top_level.clean minus_res in
+           let plus_res = Top_level.clean plus_res in
            (*
+              Unparse_ast0.unparse plus_res;
               Printf.printf "after plus parse\n";
            *)
 
            (if not !Flag.sgrep_mode2 &&
-             (any_modif minus_res or any_modif plus_res)
+             (any_modif minus_res or any_modif plus_res) &&
+             not(dependencies = Ast.FailDep)
            then Data.inheritable_positions := []);
 
            Check_meta.check_meta rule_name old_metas inherited_metavars
@@ -1586,7 +1755,7 @@ let parse file =
                  toks;
                failwith "Malformed script rule" in
 
-          let parse_script_rule language old_metas deps =
+          let parse_script_rule name language old_metas deps =
             let get_tokens = tokens_script_all table file false lexbuf in
 
               (* meta-variables *)
@@ -1594,7 +1763,26 @@ let parse file =
              Data.call_in_meta
                (function _ ->
                  get_script_metavars PC.script_meta_main table file lexbuf) in
+           let (metavars,script_metavars) =
+             List.fold_left
+               (function (metavars,script_metavars) ->
+                 function
+                     (script_var,Some(parent,var)) ->
+                       ((script_var,parent,var) :: metavars, script_metavars)
+                   | ((Some script_var,None),None) ->
+                       (metavars, (name,script_var) :: script_metavars)
+                   | _ -> failwith "not possible")
+               ([],[]) metavars in
+           let metavars = List.rev metavars in
+           let script_metavars = List.rev script_metavars in
+
+           Hashtbl.add Data.all_metadecls name
+             (List.map (function x -> Ast.MetaIdDecl(Ast.NONE,x))
+                script_metavars);
+           Hashtbl.add Lexer_cocci.rule_names name ();
+           (*TODOHashtbl.add Lexer_cocci.all_metavariables name script_metavars;*)
 
+(*
             let exists_in old_metas (py,(r,m)) =
              r = "virtual" or
               let test (rr,mr) x =
@@ -1611,34 +1799,37 @@ let parse file =
                       "Script references unknown meta-variable: %s"
                       (meta2c(snd x))))
              metavars;
-
+*)
               (* script code *)
             let (more, tokens) = get_tokens [PC.TArobArob; PC.TArob] in
             let data = collect_script_tokens tokens in
-            (more,Ast0.ScriptRule(language, deps, metavars, data),[],tokens) in
+            (more,
+            Ast0.ScriptRule(name, language, deps, metavars,
+                            script_metavars, data),
+            [],tokens) in
 
-          let parse_if_script_rule k language _ deps =
+          let parse_if_script_rule k name language _ deps =
             let get_tokens = tokens_script_all table file false lexbuf in
 
               (* script code *)
             let (more, tokens) = get_tokens [PC.TArobArob; PC.TArob] in
             let data = collect_script_tokens tokens in
-            (more,k (language, deps, data),[],tokens) in
+            (more,k (name, language, deps, data),[],tokens) in
 
          let parse_iscript_rule =
            parse_if_script_rule
-             (function (language,deps,data) ->
-               Ast0.InitialScriptRule(language,deps,data)) in
+             (function (name,language,deps,data) ->
+               Ast0.InitialScriptRule(name,language,deps,data)) in
 
          let parse_fscript_rule =
            parse_if_script_rule
-             (function (language,deps,data) ->
-               Ast0.FinalScriptRule(language,deps,data)) in
+             (function (name,language,deps,data) ->
+               Ast0.FinalScriptRule(name,language,deps,data)) in
 
-         let do_parse_script_rule fn l old_metas deps =
+         let do_parse_script_rule fn name l old_metas deps =
            match eval_depend deps virt with
-             Some deps -> fn l old_metas deps
-           | None ->  fn l old_metas Ast.FailDep in
+             Some deps -> fn name l old_metas deps
+           | None ->  fn name l old_metas Ast.FailDep in
 
           let parse_rule old_metas starts_with_name =
             let rulename =
@@ -1661,24 +1852,25 @@ let parse file =
                  Some (dep) ->
                    Data.in_generating := true;
                    let res =
-                     parse_cocci_rule Ast.Normal old_metas (s,dep,b,c,d,e) in
+                     parse_cocci_rule Ast.Generated old_metas
+                       (s,dep,b,c,d,e) in
                    Data.in_generating := false;
                    res
                | None ->
                    D.ignore_patch_or_match := true;
                    Data.in_generating := true;
                     let res =
-                     parse_cocci_rule Ast.Normal old_metas
+                     parse_cocci_rule Ast.Generated old_metas
                        (s, Ast.FailDep, b, c, d, e) in
                    D.ignore_patch_or_match := false;
                    Data.in_generating := false;
                    res)
-            | Ast.ScriptRulename(l,deps) ->
-               do_parse_script_rule parse_script_rule l old_metas deps
-            | Ast.InitialScriptRulename(l,deps) ->
-               do_parse_script_rule parse_iscript_rule l old_metas deps
-            | Ast.FinalScriptRulename(l,deps)   ->
-               do_parse_script_rule parse_fscript_rule l old_metas deps
+            | Ast.ScriptRulename(Some s,l,deps) ->
+               do_parse_script_rule parse_script_rule l old_metas deps
+            | Ast.InitialScriptRulename(Some s,l,deps) ->
+               do_parse_script_rule parse_iscript_rule l old_metas deps
+            | Ast.FinalScriptRulename(Some s,l,deps)   ->
+               do_parse_script_rule parse_fscript_rule l old_metas deps
             | _ -> failwith "Malformed rule name" in
 
          let rec loop old_metas starts_with_name =
@@ -1694,21 +1886,28 @@ let parse file =
 
             let (more, rule, metavars, tokens) =
               parse_rule old_metas starts_with_name in
+           let all_metas = metavars @ old_metas in
+
             if more then
-              rule::
-             (loop (metavars @ old_metas) (gen_starts_with_name more tokens))
-            else [rule] in
+             let (all_rules,all_metas) =
+               loop all_metas (gen_starts_with_name more tokens) in
+             (rule::all_rules,all_metas)
+            else ([rule],all_metas) in
+
+         let (all_rules,all_metas) =
+           loop extra_metas (x = PC.TArob) in
 
          (List.fold_left
             (function prev -> function cur -> Common.union_set cur prev)
             iso_files extra_iso_files,
           (* included rules first *)
           List.fold_left (function prev -> function cur -> cur@prev)
-            (loop [] (x = PC.TArob)) (List.rev extra_rules),
-          List.fold_left (@) virt extra_virt (*no dups allowed*))
+            all_rules (List.rev extra_rules),
+          List.fold_left (@) virt extra_virt (*no dups allowed*),
+          (all_metas : 'a list))
       |        _ -> failwith "unexpected code before the first rule\n")
   | (false,[(PC.TArobArob,_)]) | (false,[(PC.TArob,_)]) ->
-      ([],([] : Ast0.parsed_rule list),[] (*virtual rules*))
+      ([],([] : Ast0.parsed_rule list),[] (*virtual rules*), [] (*all metas*))
   | _ -> failwith "unexpected code before the first rule\n" in
   res) in
   parse_loop file
@@ -1716,7 +1915,7 @@ let parse file =
 (* parse to ast0 and then convert to ast *)
 let process file isofile verbose =
   let extra_path = Filename.dirname file in
-  let (iso_files, rules, virt) = parse file in
+  let (iso_files, rules, virt, _metas) = parse file in
   eval_virt virt;
   let std_isos =
     match isofile with
@@ -1727,9 +1926,12 @@ let process file isofile verbose =
   let parsed =
     List.map
       (function
-          Ast0.ScriptRule (a,b,c,d) -> [([],Ast.ScriptRule (a,b,c,d))]
-       | Ast0.InitialScriptRule (a,b,c) -> [([],Ast.InitialScriptRule (a,b,c))]
-       | Ast0.FinalScriptRule (a,b,c) -> [([],Ast.FinalScriptRule (a,b,c))]
+          Ast0.ScriptRule (a,b,c,d,fv,e) ->
+           [([],Ast.ScriptRule (a,b,c,d,fv,e))]
+       | Ast0.InitialScriptRule(a,b,c,d) ->
+           [([],Ast.InitialScriptRule (a,b,c,d))]
+       | Ast0.FinalScriptRule (a,b,c,d) ->
+           [([],Ast.FinalScriptRule (a,b,c,d))]
        | Ast0.CocciRule
            ((minus, metavarsm,
              (iso, dropiso, dependencies, rule_name, exists)),
@@ -1821,18 +2023,17 @@ let process file isofile verbose =
               | Some mv_fp -> [(extra_meta @ metavars, minus_ast); mv_fp])
 (*          Ast0.CocciRule ((minus, metavarsm, (iso, dropiso, dependencies, rule_name, exists)), (plus, metavars))*)
       rules in
+
   let parsed = List.concat parsed in
+  let parsed = Safe_for_multi_decls.safe_for_multi_decls parsed in
   let disjd = Disjdistr.disj parsed in
 
   let (metavars,code,fvs,neg_pos,ua,pos) = Free_vars.free_vars disjd in
   if !Flag_parsing_cocci.show_SP
   then List.iter Pretty_print_cocci.unparse code;
 
-  let grep_tokens =
-    Common.profile_code "get_constants" (* for grep *)
-      (fun () -> Get_constants.get_constants code) in
-  let glimpse_tokens2 =
+  let search_tokens =
     Common.profile_code "get_glimpse_constants" (* for glimpse *)
       (fun () -> Get_constants2.get_constants code neg_pos) in
 
-  (metavars,code,fvs,neg_pos,ua,pos,grep_tokens,glimpse_tokens2)
+  (metavars,code,fvs,neg_pos,ua,pos,search_tokens)