Coccinelle release 1.0.0c7.
[bpt/coccinelle.git] / parsing_cocci / parser_cocci_menhir.mly
index d90e837..8fc9bed 100644 (file)
@@ -1,3 +1,27 @@
+/*
+ * 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.
+ *
+ * Coccinelle is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, according to version 2 of the License.
+ *
+ * Coccinelle is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Coccinelle.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The authors reserve the right to distribute this or future versions of
+ * Coccinelle under other licenses.
+ */
+
+
 %{
 
 (* Not clear how to allow function declarations to specify a return type
@@ -65,15 +89,15 @@ let tmeta_to_statement (name,pure,clt) =
 
 let tmeta_to_seed_id (name,pure,clt) =
   (coerce_tmeta "an identifier" name
-     (TMetaId(name,Ast.IdNoConstraint,pure,clt))
-     (function TMetaId(_,_,_,_) -> true | _ -> false));
+     (TMetaId(name,Ast.IdNoConstraint,Ast.NoVal,pure,clt))
+     (function TMetaId(_,_,_,_,_) -> true | _ -> false));
   Ast.SeedId name
 
 let tmeta_to_ident (name,pure,clt) =
   (coerce_tmeta "an identifier" name
-     (TMetaId(name,Ast.IdNoConstraint,pure,clt))
-     (function TMetaId(_,_,_,_) -> true | _ -> false));
-  Ast0.wrap(Ast0.MetaId(P.clt2mcode name clt,Ast.IdNoConstraint,pure))
+     (TMetaId(name,Ast.IdNoConstraint,Ast.NoVal,pure,clt))
+     (function TMetaId(_,_,_,_,_) -> true | _ -> false));
+  Ast0.wrap(Ast0.MetaId(P.clt2mcode name clt,Ast.IdNoConstraint,Ast.NoVal,pure))
 %}
 
 %token EOF
@@ -101,12 +125,13 @@ let tmeta_to_ident (name,pure,clt) =
 %token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId
 %token <Ast_cocci.added_string * Data.clt> TPragma
 
-%token <Parse_aux.idinfo>        TMetaId TMetaFunc TMetaLocalFunc
+%token <Parse_aux.midinfo>       TMetaId
+%token <Parse_aux.idinfo>        TMetaFunc TMetaLocalFunc
 %token <Parse_aux.idinfo>        TMetaIterator TMetaDeclarer
 %token <Parse_aux.expinfo>       TMetaErr
 %token <Parse_aux.info>          TMetaParam TMetaStm TMetaStmList TMetaType
 %token <Parse_aux.info>          TMetaInit TMetaDecl TMetaField TMeta
-%token <Parse_aux.list_info>     TMetaParamList TMetaExpList
+%token <Parse_aux.list_info>     TMetaParamList TMetaExpList TMetaInitList
 %token <Parse_aux.list_info>     TMetaFieldList
 %token <Parse_aux.typed_expinfo> TMetaExp TMetaIdExp TMetaLocalIdExp TMetaConst
 %token <Parse_aux.pos_info>      TMetaPos
@@ -380,6 +405,14 @@ metadec:
          let tok = check_meta(Ast.MetaFieldListDecl(arity,name,lenname)) in
          !Data.add_field_list_meta name lenname pure; tok)
        len ids }
+| ar=arity ispure=pure
+    TInitialiser Tlist TOCro len=list_len TCCro
+    ids=comma_list(pure_ident_or_meta_ident) TMPtVirg
+    { P.create_len_metadec ar ispure
+       (fun lenname arity name pure check_meta ->
+         let tok = check_meta(Ast.MetaInitListDecl(arity,name,lenname)) in
+         !Data.add_initlist_meta name lenname pure; tok)
+       len ids }
 
 list_len:
   pure_ident_or_meta_ident { Common.Left $1 }
@@ -389,7 +422,7 @@ list_len:
   TFresh TIdentifier
     { (fun name check_meta seed ->
       let tok = check_meta(Ast.MetaFreshIdDecl(name,seed)) in
-      !Data.add_fresh_id_meta name; tok) }
+      !Data.add_fresh_id_meta name seed; tok) }
 
 /* metavariable kinds with no constraints, etc */
 %inline metakind:
@@ -419,6 +452,11 @@ list_len:
     { (fun arity name pure check_meta ->
       let tok = check_meta(Ast.MetaInitDecl(arity,name)) in
       !Data.add_init_meta name pure; tok) }
+| TInitialiser Tlist
+    { (fun arity name pure check_meta ->
+      let len = Ast.AnyLen in
+      let tok = check_meta(Ast.MetaInitListDecl(arity,name,len)) in
+      !Data.add_initlist_meta name len pure; tok) }
 | TStatement
     { (fun arity name pure check_meta ->
       let tok = check_meta(Ast.MetaStmDecl(arity,name)) in
@@ -593,6 +631,10 @@ signable_types:
     { Ast0.wrap(Ast0.BaseType(Ast.CharType,[P.clt2mcode "char" ty])) }
 | ty=Tshort
     { Ast0.wrap(Ast0.BaseType(Ast.ShortType,[P.clt2mcode "short" ty])) }
+| ty1=Tshort ty2=Tint
+    { Ast0.wrap
+       (Ast0.BaseType
+          (Ast.ShortIntType,[P.clt2mcode "short" ty1;P.clt2mcode "int" ty2])) }
 | ty=Tint
     { Ast0.wrap(Ast0.BaseType(Ast.IntType,[P.clt2mcode "int" ty])) }
 | p=TMetaType
@@ -605,18 +647,33 @@ signable_types:
     let _ = P.check_meta(Ast.MetaTypeDecl(Ast.NONE,nm)) in
     Ast0.wrap(Ast0.MetaType(P.clt2mcode nm (P.id2clt p),
                            Ast0.Impure (*will be ignored*))) }
-| ty=Tlong
-    { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty])) }
+| ty1=Tlong
+    { Ast0.wrap(Ast0.BaseType(Ast.LongType,[P.clt2mcode "long" ty1])) }
+| ty1=Tlong ty2=Tint
+    { Ast0.wrap
+       (Ast0.BaseType
+          (Ast.LongIntType,[P.clt2mcode "long" ty1;P.clt2mcode "int" ty2])) }
 | ty1=Tlong ty2=Tlong
     { Ast0.wrap
        (Ast0.BaseType
           (Ast.LongLongType,
            [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2])) }
+| ty1=Tlong ty2=Tlong ty3=Tint
+    { Ast0.wrap
+       (Ast0.BaseType
+          (Ast.LongLongIntType,
+           [P.clt2mcode "long" ty1;P.clt2mcode "long" ty2;
+             P.clt2mcode "int" ty3])) }
 
 %inline
 non_signable_types:
   ty=Tvoid
     { Ast0.wrap(Ast0.BaseType(Ast.VoidType,[P.clt2mcode "void" ty])) }
+| ty1=Tlong ty2=Tdouble
+    { Ast0.wrap
+       (Ast0.BaseType
+          (Ast.LongDoubleType,
+           [P.clt2mcode "long" ty1;P.clt2mcode "double" ty2])) }
 | ty=Tdouble
     { Ast0.wrap(Ast0.BaseType(Ast.DoubleType,[P.clt2mcode "double" ty])) }
 | ty=Tfloat
@@ -699,6 +756,10 @@ struct_decl_one:
     | TMetaField { P.meta_field $1 }
     | TMetaFieldList { P.meta_field_list $1 }
     | TMeta { tmeta_to_field $1 }
+    | lp=TOPar0 t=midzero_list(struct_decl_one,struct_decl_one) rp=TCPar0
+       { let (mids,code) = t in
+       Ast0.wrap
+         (Ast0.DisjDecl(P.clt2mcode "(" lp,code,mids, P.clt2mcode ")" rp)) }
     | t=ctype d=d_ident pv=TPtVirg
         { let (id,fn) = d in
         Ast0.wrap(Ast0.UnInit(None,fn t,id,P.clt2mcode ";" pv)) }
@@ -777,13 +838,13 @@ minus_body:
     /*ew=loption(error_words)*/
     { match f@b(*@ew*) with
       [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
-    | code -> Top_level.top_level code }
+    | code -> code }
 
 plus_body:
     f=loption(filespec)
     b=loption(plus_start)
     /*ew=loption(error_words)*/
-    { Top_level.top_level (f@b(*@ew*)) }
+    { f@b(*@ew*) }
 
 minus_exp_body:
     f=loption(filespec)
@@ -791,13 +852,13 @@ minus_exp_body:
     /*ew=loption(error_words)*/
     { match f@[b](*@ew*) with
       [] -> raise (Semantic_cocci.Semantic "minus slice can't be empty")
-    | code -> Top_level.top_level code }
+    | code -> code }
 
 plus_exp_body:
     f=loption(filespec)
     b=top_eexpr
     /*ew=loption(error_words)*/
-    { Top_level.top_level (f@[b](*@ew*)) }
+    { f@[b](*@ew*) }
 
 filespec:
   TMinusFile TPlusFile
@@ -830,14 +891,17 @@ includes:
                              (P.drop_bef clt))) }
 | TUndef TLineEnd
     { let (clt,ident) = $1 in
+      let aft = P.get_aft clt in (* move stuff after the define to the ident *)
       Ast0.wrap
       (Ast0.Undef
-        (P.clt2mcode "#undef" clt,
+        (P.clt2mcode "#undef" (P.drop_aft clt),
          (match ident with
-           TMetaId((nm,constraints,pure,clt)) ->
-             Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
-         | TIdent(nm_pure) ->
-             Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
+           TMetaId((nm,constraints,seed,pure,clt)) ->
+             let clt = P.set_aft aft clt in
+             Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure))
+         | TIdent((nm,clt)) ->
+             let clt = P.set_aft aft clt in
+             Ast0.wrap(Ast0.Id(P.clt2mcode nm clt))
          | _ ->
              raise
                (Semantic_cocci.Semantic
@@ -861,15 +925,19 @@ includes:
 defineop:
   TDefine
     { let (clt,ident) = $1 in
+      let aft = P.get_aft clt in (* move stuff after the define to the ident *)
       function body ->
        Ast0.wrap
          (Ast0.Define
-            (P.clt2mcode "#define" clt,
+            (P.clt2mcode "#define" (P.drop_aft clt),
              (match ident with
-               TMetaId((nm,constraints,pure,clt)) ->
-                 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
-             | TIdent(nm_pure) ->
-                 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
+               TMetaId((nm,constraints,seed,pure,clt)) ->
+                 let clt = P.set_aft aft clt in
+                 Ast0.wrap
+                   (Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure))
+             | TIdent((nm,clt)) ->
+                 let clt = P.set_aft aft clt in
+                 Ast0.wrap(Ast0.Id(P.clt2mcode nm clt))
              | _ ->
                  raise
                    (Semantic_cocci.Semantic
@@ -878,25 +946,28 @@ defineop:
              body)) }
 | TDefineParam define_param_list_option TCPar
     { let (clt,ident,parenoff,parencol) = $1 in
+      let aft = P.get_aft clt in (* move stuff after the define to the ( *)
       (* clt is the start of the #define itself *)
       let (arity,line,lline,offset,col,strbef,straft,pos) = clt in
       let lp =
        P.clt2mcode "("
-         (arity,line,lline,parenoff,parencol,[],[],Ast0.NoMetaPos) in
+         (arity,line,lline,parenoff,parencol,[],[],[]) in
       function body ->
        Ast0.wrap
          (Ast0.Define
-            (P.clt2mcode "#define" clt,
+            (P.clt2mcode "#define" (P.drop_aft clt),
              (match ident with
-               TMetaId((nm,constraints,pure,clt)) ->
-                 Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure))
-             | TIdent(nm_pure) ->
-                 Ast0.wrap(Ast0.Id(P.id2mcode nm_pure))
+               TMetaId((nm,constraints,seed,pure,clt)) ->
+                 Ast0.wrap
+                   (Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure))
+             | TIdent((nm,clt)) ->
+                 Ast0.wrap(Ast0.Id(P.clt2mcode nm clt))
              | _ ->
                  raise
                    (Semantic_cocci.Semantic
                       "unexpected name for a #define")),
-             Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" $3)),body)) }
+             (let clt = P.set_aft aft $3 in
+             Ast0.wrap (Ast0.DParams (lp,$2,P.clt2mcode ")" clt))),body)) }
 
 /* ---------------------------------------------------------------------- */
 
@@ -1018,7 +1089,7 @@ statement:
 | TMeta { tmeta_to_statement $1}
 | TMetaStm
     { P.meta_stm $1 }
-| expr TPtVirg
+| option(expr) TPtVirg
     { P.exp_stm $1 $2 }
 | TIf TOPar eexpr TCPar single_statement %prec TIf
     { P.ifthen $1 $2 $3 $4 $5 }
@@ -1074,7 +1145,7 @@ what about statement metavariables? */
 rule_elem_statement:
   one_decl_var
     { Ast0.wrap(Ast0.Decl((Ast0.default_info(),Ast0.context_befaft()),$1)) }
-| expr TPtVirg { P.exp_stm $1 $2 }
+| option(expr) TPtVirg { P.exp_stm $1 $2 }
 | TReturn eexpr TPtVirg { P.ret_exp $1 $2 $3 }
 | TReturn TPtVirg { P.ret $1 $2 }
 | TBreak TPtVirg { P.break $1 $2 }
@@ -1263,6 +1334,18 @@ initialize2:
     { Ast0.wrap(Ast0.InitGccExt($1,P.clt2mcode "=" $2,$3)) }
 | mident TDotDot initialize2
     { Ast0.wrap(Ast0.InitGccName($1,P.clt2mcode ":" $2,$3)) } /* in old kernel */
+  | TMetaInit
+      {let (nm,pure,clt) = $1 in
+      Ast0.wrap(Ast0.MetaInit(P.clt2mcode nm clt,pure)) }
+  | TMetaInitList
+      {let (nm,lenname,pure,clt) = $1 in
+      let nm = P.clt2mcode nm clt in
+      let lenname =
+       match lenname with
+         Ast.AnyLen -> Ast0.AnyListLen
+       | Ast.MetaLen nm -> Ast0.MetaListLen(P.clt2mcode nm clt)
+       | Ast.CstLen n -> Ast0.CstListLen n in
+      Ast0.wrap(Ast0.MetaInitList(nm,lenname,pure)) }
 
 designator:
  | TDot disj_ident
@@ -1537,9 +1620,26 @@ postfix_expr(r,pe):
      { Ast0.wrap(Ast0.FunCall($1,P.clt2mcode "(" $2,
                              $3,
                              P.clt2mcode ")" $4)) }
+ /*(* gccext: also called compound literals *)
+   empty case causes conflicts */
+ | TOPar ctype TCPar TOBrace initialize_list TCBrace
+     { let init =
+       if P.struct_initializer $5
+       then
+        let il = P.drop_dot_commas $5 in
+        Ast0.wrap
+          (Ast0.InitList(P.clt2mcode "{" $4,il,P.clt2mcode "}" $6,false))
+       else
+        Ast0.wrap
+          (Ast0.InitList(P.clt2mcode "{" $4,$5,P.clt2mcode "}" $6,true)) in
+     Ast0.wrap
+       (Ast0.Constructor(P.clt2mcode "(" $1, $2, P.clt2mcode ")" $3, init)) }
 
 primary_expr(recurser,primary_extra):
    func_ident   { Ast0.wrap(Ast0.Ident($1)) }
+ | TAndLog ident
+     { let op = P.clt2mcode Ast.GetRefLabel $1 in
+     Ast0.wrap(Ast0.Unary(Ast0.wrap(Ast0.Ident($2)), op)) }
  | TInt
      { let (x,clt) = $1 in
      Ast0.wrap(Ast0.Constant (P.clt2mcode (Ast.Int x) clt)) }
@@ -1638,8 +1738,15 @@ pure_ident_or_meta_ident_with_seed:
 
 seed_elem:
   TString { let (x,_) = $1 in Ast.SeedString x }
-| TMetaId { let (x,_,_,_) = $1 in Ast.SeedId x }
+| TMetaId { let (x,_,_,_,_) = $1 in Ast.SeedId x }
 | TMeta {failwith "tmeta"}
+| TVirtual TDot pure_ident
+    { let nm = ("virtual",P.id2name $3) in
+     Iteration.parsed_virtual_identifiers :=
+       Common.union_set [snd nm]
+        !Iteration.parsed_virtual_identifiers;
+    try Ast.SeedString (List.assoc (snd nm) !Flag.defined_virtual_env)
+    with Not_found -> Ast.SeedId nm }
 | TRuleName TDot pure_ident
     { let nm = ($1,P.id2name $3) in
       P.check_meta(Ast.MetaIdDecl(Ast.NONE,nm));
@@ -1694,14 +1801,14 @@ regexp_eqid:
            then failwith "constraints not allowed in iso file");
           (if !Data.in_generating
            then failwith "constraints not allowed in a generated rule file");
-          let (s,_) = re in Ast.IdRegExp (s,Str.regexp s)
+          let (s,_) = re in Ast.IdRegExp (s,Regexp.regexp s)
         }
  | TTildeExclEq re=TString
          { (if !Data.in_iso
            then failwith "constraints not allowed in iso file");
           (if !Data.in_generating
            then failwith "constraints not allowed in a generated rule file");
-          let (s,_) = re in Ast.IdNotRegExp (s,Str.regexp s)
+          let (s,_) = re in Ast.IdNotRegExp (s,Regexp.regexp s)
         }
 
 not_eqid:
@@ -1831,7 +1938,8 @@ not_pos:
                 (function mv -> Ast.MetaPosDecl(Ast.NONE,mv)))
             l }
 
-func_ident: ident { $1 }
+func_ident:
+       ident { $1 }
      | TMetaFunc
          { let (nm,constraints,pure,clt) = $1 in
         Ast0.wrap(Ast0.MetaFunc(P.clt2mcode nm clt,constraints,pure)) }
@@ -1852,15 +1960,15 @@ fn_ident: disj_ident { $1 }
 ident: pure_ident
          { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
      | TMetaId
-         { let (nm,constraints,pure,clt) = $1 in
-         Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+         { let (nm,constraints,seed,pure,clt) = $1 in
+         Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure)) }
 
 mident: pure_ident
          { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
      | TMeta { tmeta_to_ident $1 }
      | TMetaId
-         { let (nm,constraints,pure,clt) = $1 in
-         Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+         { let (nm,constraints,seed,pure,clt) = $1 in
+         Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,seed,pure)) }
 
 disj_ident:
        mident { $1 }
@@ -1878,14 +1986,14 @@ decl_ident:
          { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
      | TMetaDeclarer
          { let (nm,constraints,pure,clt) = $1 in
-         Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+         Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,Ast.NoVal,pure)) }
 
 iter_ident:
        TIteratorId
          { Ast0.wrap(Ast0.Id(P.id2mcode $1)) }
      | TMetaIterator
          { let (nm,constraints,pure,clt) = $1 in
-         Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,pure)) }
+         Ast0.wrap(Ast0.MetaId(P.clt2mcode nm clt,constraints,Ast.NoVal,pure)) }
 
 typedef_ident:
        pure_ident
@@ -2004,7 +2112,7 @@ when_body_sequence.
 
 /* doesn't allow only ... */
 minus_start:
-  fundecl                { [Ast0.wrap(Ast0.DECL($1))] }
+  fundecl                { [Ast0.wrap(Ast0.OTHER($1))] }
 | ctype                  { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Ty($1))))] }
 | top_init          { [Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.TopInit($1))))] }
 | toplevel_seq_startne(toplevel_after_dots_init)
@@ -2062,7 +2170,7 @@ plus_start:
                                           { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
 | expr plus_after_exp
                      { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
-| fundecl plus_after_stm                     { Ast0.wrap(Ast0.DECL($1))::$2 }
+| fundecl plus_after_stm                     { Ast0.wrap(Ast0.OTHER($1))::$2 }
 | decl_statement_expr plus_after_stm
                 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
 
@@ -2075,14 +2183,14 @@ plus_after_dots:
 | TNothing plus_after_exp                                                {$2}
 | expr plus_after_exp
                      { (Ast0.wrap(Ast0.OTHER(Ast0.wrap(Ast0.Exp($1)))))::$2 }
-| fundecl plus_after_stm                     { Ast0.wrap(Ast0.DECL($1))::$2 }
+| fundecl plus_after_stm                     { Ast0.wrap(Ast0.OTHER($1))::$2 }
 | decl_statement_expr plus_after_stm
                 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }
 
 plus_after_stm:
   /* empty */                                                            {[]}
 | stm_dots plus_after_dots                { (Ast0.wrap(Ast0.OTHER($1)))::$2 }
-| fundecl plus_after_stm                     { Ast0.wrap(Ast0.DECL($1))::$2 }
+| fundecl plus_after_stm                     { Ast0.wrap(Ast0.OTHER($1))::$2 }
 | decl_statement plus_after_stm
                 { (List.map (function x -> Ast0.wrap(Ast0.OTHER(x))) $1)@$2 }