+/*
+ * 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
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
%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
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 }
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:
{ (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
{ 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
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
| 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)) }
/*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)
/*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
(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
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
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)) }
/* ---------------------------------------------------------------------- */
| 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 }
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 }
{ 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
{ 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)) }
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));
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:
(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)) }
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 }
{ 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
/* 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)
{ (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 }
| 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 }