+(*
+ * Copyright 2012, INRIA
+ * Julia Lawall, Gilles Muller
+ * Copyright 2010-2011, 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.
+ *)
+
+
(* exports everything, used only by parser_cocci_menhir.mly *)
module Ast0 = Ast0_cocci
module Ast = Ast_cocci
(* types for metavariable tokens *)
type info = Ast.meta_name * Ast0.pure * Data.clt
+type midinfo =
+ Ast.meta_name * Data.iconstraints * Ast.seed * Ast0.pure * Data.clt
type idinfo = Ast.meta_name * Data.iconstraints * Ast0.pure * Data.clt
type expinfo = Ast.meta_name * Data.econstraints * Ast0.pure * Data.clt
type tyinfo = Ast.meta_name * Ast0.typeC list * Ast0.pure * Data.clt
-type list_info = Ast.meta_name * Ast.meta_name option * Ast0.pure * Data.clt
+type list_info = Ast.meta_name * Ast.list_len * Ast0.pure * Data.clt
type typed_expinfo =
Ast.meta_name * Data.econstraints * Ast0.pure *
Type_cocci.typeC list option * Data.clt
type pos_info = Ast.meta_name * Data.pconstraints * Ast.meta_collect * Data.clt
-
let get_option fn = function
None -> None
| Some x -> Some (fn x)
-let make_info line logical_line offset col strbef straft =
+let make_info line logical_line offset col strbef straft isSymbol =
let new_pos_info =
{Ast0.line_start = line; Ast0.line_end = line;
Ast0.logical_start = logical_line; Ast0.logical_end = logical_line;
{ Ast0.pos_info = new_pos_info;
Ast0.attachable_start = true; Ast0.attachable_end = true;
Ast0.mcode_start = []; Ast0.mcode_end = [];
- Ast0.strings_before = strbef; Ast0.strings_after = straft; }
+ Ast0.strings_before = strbef; Ast0.strings_after = straft;
+ Ast0.isSymbolIdent = isSymbol; }
let clt2info (_,line,logical_line,offset,col,strbef,straft,pos) =
- make_info line logical_line offset col strbef straft
+ make_info line logical_line offset col strbef straft false
let drop_bef (arity,line,lline,offset,col,strbef,straft,pos) =
(arity,line,lline,offset,col,[],straft,pos)
let drop_aft (arity,line,lline,offset,col,strbef,straft,pos) =
(arity,line,lline,offset,col,strbef,[],pos)
+(* used for #define, to put aft on ident/( *)
+let get_aft (arity,line,lline,offset,col,strbef,straft,pos) = straft
+
+let set_aft aft (arity,line,lline,offset,col,strbef,_,pos) =
+ (arity,line,lline,offset,col,strbef,aft,pos)
+
let drop_pos (arity,line,lline,offset,col,strbef,straft,pos) =
- (arity,line,lline,offset,col,strbef,straft,Ast0.NoMetaPos)
+ (arity,line,lline,offset,col,strbef,straft,[])
-let clt2mcode str = function
+let clt2mcode_ext str isSymbol = function
(Data.MINUS,line,lline,offset,col,strbef,straft,pos) ->
- (str,Ast0.NONE,make_info line lline offset col strbef straft,
- Ast0.MINUS(ref([],Ast0.default_token_info)),ref pos,-1)
+ (str,Ast0.NONE,make_info line lline offset col strbef straft isSymbol,
+ Ast0.MINUS(ref(Ast.NOREPLACEMENT,Ast0.default_token_info)),ref pos,-1)
| (Data.OPTMINUS,line,lline,offset,col,strbef,straft,pos) ->
- (str,Ast0.OPT,make_info line lline offset col strbef straft,
- Ast0.MINUS(ref([],Ast0.default_token_info)),ref pos,-1)
+ (str,Ast0.OPT,make_info line lline offset col strbef straft isSymbol,
+ Ast0.MINUS(ref(Ast.NOREPLACEMENT,Ast0.default_token_info)),ref pos,-1)
| (Data.UNIQUEMINUS,line,lline,offset,col,strbef,straft,pos) ->
- (str,Ast0.UNIQUE,make_info line lline offset col strbef straft,
- Ast0.MINUS(ref([],Ast0.default_token_info)),ref pos,-1)
+ (str,Ast0.UNIQUE,make_info line lline offset col strbef straft isSymbol,
+ Ast0.MINUS(ref(Ast.NOREPLACEMENT,Ast0.default_token_info)),ref pos,-1)
| (Data.PLUS,line,lline,offset,col,strbef,straft,pos) ->
- (str,Ast0.NONE,make_info line lline offset col strbef straft,
+ (str,Ast0.NONE,make_info line lline offset col strbef straft isSymbol,
Ast0.PLUS(Ast.ONE),ref pos,-1)
| (Data.PLUSPLUS,line,lline,offset,col,strbef,straft,pos) ->
- (str,Ast0.NONE,make_info line lline offset col strbef straft,
+ (str,Ast0.NONE,make_info line lline offset col strbef straft isSymbol,
Ast0.PLUS(Ast.MANY),ref pos,-1)
| (Data.CONTEXT,line,lline,offset,col,strbef,straft,pos) ->
- (str,Ast0.NONE,make_info line lline offset col strbef straft,
+ (str,Ast0.NONE,make_info line lline offset col strbef straft isSymbol,
Ast0.CONTEXT(ref(Ast.NOTHING,
Ast0.default_token_info,Ast0.default_token_info)),
ref pos,-1)
| (Data.OPT,line,lline,offset,col,strbef,straft,pos) ->
- (str,Ast0.OPT,make_info line lline offset col strbef straft,
+ (str,Ast0.OPT,make_info line lline offset col strbef straft isSymbol,
Ast0.CONTEXT(ref(Ast.NOTHING,
Ast0.default_token_info,Ast0.default_token_info)),
ref pos,-1)
| (Data.UNIQUE,line,lline,offset,col,strbef,straft,pos) ->
- (str,Ast0.UNIQUE,make_info line lline offset col strbef straft,
+ (str,Ast0.UNIQUE,make_info line lline offset col strbef straft isSymbol,
Ast0.CONTEXT(ref(Ast.NOTHING,
Ast0.default_token_info,Ast0.default_token_info)),
ref pos,-1)
+let clt2mcode name clt = clt2mcode_ext name false clt
let id2name (name, clt) = name
let id2clt (name, clt) = clt
let id2mcode (name, clt) = clt2mcode name clt
+let sym2mcode (name, clt) = clt2mcode_ext name true clt
let mkdots str (dot,whencode) =
match str with
| ("...",Some [w]) -> Ast0.wrap(Ast0.Ddots(clt2mcode str dot, Some w))
| _ -> failwith "cannot happen"
+let mkddots_one str (dot,whencode) =
+ match str with
+ "..." -> Ast0.wrap(Ast0.Ddots(clt2mcode str dot, whencode))
+ | _ -> failwith "cannot happen"
+
let mkpdots str dot =
match str with
"..." -> Ast0.wrap(Ast0.Pdots(clt2mcode str dot))
(function inner -> function cur -> Type_cocci.Pointer(inner))
ty m
+let arrayify ty ar =
+ List.fold_right
+ (function (l,i,r) ->
+ function rest ->
+ Ast0.wrap (Ast0.Array(rest,clt2mcode "[" l,i,clt2mcode "]" r)))
+ ar ty
+
(* Left is <=>, Right is =>. Collect <=>s. *)
(* The parser should have done this, with precedences. But whatever... *)
-let iso_adjust fn first rest =
+let iso_adjust first_fn fn first rest =
let rec loop = function
[] -> [[]]
| (Common.Left x)::rest ->
front::after -> []::(fn x::front)::after
| _ -> failwith "not possible") in
match loop rest with
- front::after -> (fn first::front)::after
+ front::after -> (first_fn first::front)::after
| _ -> failwith "not possible"
-let check_meta tok =
- let lookup rule name =
- try
- let info = Hashtbl.find Data.all_metadecls rule in
- List.find (function mv -> Ast.get_meta_name mv = (rule,name)) info
- with
- Not_found ->
- raise
- (Semantic_cocci.Semantic
- ("bad rule "^rule^" or bad variable "^name)) in
- match tok with
- Ast.MetaIdDecl(Ast.NONE,(rule,name)) ->
+let lookup rule name =
+ try
+ let info = Hashtbl.find Data.all_metadecls rule in
+ List.find (function mv -> Ast.get_meta_name mv = (rule,name)) info
+ with
+ Not_found ->
+ raise
+ (Semantic_cocci.Semantic("bad rule "^rule^" or bad variable "^name))
+
+let check_meta_tyopt type_irrelevant = function
+ Ast.MetaMetaDecl(Ast.NONE,(rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaMetaDecl(_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaIdDecl(Ast.NONE,(rule,name)) ->
(match lookup rule name with
Ast.MetaIdDecl(_,_) | Ast.MetaFreshIdDecl(_,_) -> ()
| _ ->
raise
(Semantic_cocci.Semantic
"can't inherit the freshness of an identifier")
- | Ast.MetaListlenDecl((rule,name)) ->
+ | Ast.MetaTypeDecl(Ast.NONE,(rule,name)) ->
(match lookup rule name with
- Ast.MetaListlenDecl(_) -> ()
+ Ast.MetaTypeDecl(_,_) -> ()
| _ ->
raise
(Semantic_cocci.Semantic
("incompatible inheritance declaration "^name)))
- | Ast.MetaTypeDecl(Ast.NONE,(rule,name)) ->
+ | Ast.MetaInitDecl(Ast.NONE,(rule,name)) ->
(match lookup rule name with
- Ast.MetaTypeDecl(_,_) -> ()
+ Ast.MetaInitDecl(_,_) -> ()
| _ ->
raise
(Semantic_cocci.Semantic
("incompatible inheritance declaration "^name)))
- | Ast.MetaInitDecl(Ast.NONE,(rule,name)) ->
+ | Ast.MetaInitListDecl(Ast.NONE,(rule,name),len_name) ->
(match lookup rule name with
- Ast.MetaInitDecl(_,_) -> ()
+ Ast.MetaInitListDecl(_,_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaListlenDecl((rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaListlenDecl(_) -> ()
| _ ->
raise
(Semantic_cocci.Semantic
raise
(Semantic_cocci.Semantic
("incompatible inheritance declaration "^name)))
+ | Ast.MetaConstDecl(Ast.NONE,(rule,name),ty) ->
+ (match lookup rule name with
+ Ast.MetaConstDecl(_,_,ty1) when type_irrelevant or ty = ty1 -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
| Ast.MetaErrDecl(Ast.NONE,(rule,name)) ->
(match lookup rule name with
Ast.MetaErrDecl(_,_) -> ()
("incompatible inheritance declaration "^name)))
| Ast.MetaExpDecl(Ast.NONE,(rule,name),ty) ->
(match lookup rule name with
- Ast.MetaExpDecl(_,_,ty1) when ty = ty1 -> ()
+ Ast.MetaExpDecl(_,_,ty1) when type_irrelevant or ty = ty1 -> ()
| _ ->
raise
(Semantic_cocci.Semantic
("incompatible inheritance declaration "^name)))
| Ast.MetaIdExpDecl(Ast.NONE,(rule,name),ty) ->
(match lookup rule name with
- Ast.MetaIdExpDecl(_,_,ty1) when ty = ty1 -> ()
+ Ast.MetaIdExpDecl(_,_,ty1) when type_irrelevant or ty = ty1 -> ()
| _ ->
raise
(Semantic_cocci.Semantic
("incompatible inheritance declaration "^name)))
| Ast.MetaLocalIdExpDecl(Ast.NONE,(rule,name),ty) ->
(match lookup rule name with
- Ast.MetaLocalIdExpDecl(_,_,ty1) when ty = ty1 -> ()
+ Ast.MetaLocalIdExpDecl(_,_,ty1) when type_irrelevant or ty = ty1 -> ()
| _ ->
raise
(Semantic_cocci.Semantic
raise
(Semantic_cocci.Semantic
("incompatible inheritance declaration "^name)))
+ | Ast.MetaDeclDecl(Ast.NONE,(rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaDeclDecl(_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaFieldDecl(Ast.NONE,(rule,name)) ->
+ (match lookup rule name with
+ Ast.MetaFieldDecl(_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
+ | Ast.MetaFieldListDecl(Ast.NONE,(rule,name),len_name) ->
+ (match lookup rule name with
+ Ast.MetaFieldListDecl(_,_,_) -> ()
+ | _ ->
+ raise
+ (Semantic_cocci.Semantic
+ ("incompatible inheritance declaration "^name)))
| Ast.MetaStmDecl(Ast.NONE,(rule,name)) ->
(match lookup rule name with
Ast.MetaStmDecl(_,_) -> ()
raise
(Semantic_cocci.Semantic
("incompatible inheritance declaration "^name)))
- | Ast.MetaConstDecl(Ast.NONE,(rule,name),ty) ->
- (match lookup rule name with
- Ast.MetaConstDecl(_,_,ty1) when ty = ty1 -> ()
- | _ ->
- raise
- (Semantic_cocci.Semantic
- ("incompatible inheritance declaration "^name)))
| Ast.MetaPosDecl(Ast.NONE,(rule,name)) ->
(match lookup rule name with
Ast.MetaPosDecl(_,_) ->
- if not (List.mem rule !Data.inheritable_positions)
+ if not (List.mem rule !Data.inheritable_positions) &&
+ not !Data.ignore_patch_or_match
then
raise
(Semantic_cocci.Semantic
raise
(Semantic_cocci.Semantic ("arity not allowed on imported declaration"))
+let check_meta m = check_meta_tyopt false m
+
+let check_inherited_constraint meta_name fn =
+ match meta_name with
+ (None,_) -> failwith "constraint must be an inherited variable"
+ | (Some rule,name) ->
+ let i = (rule,name) in
+ check_meta_tyopt true (fn i);
+ i
+
let create_metadec ar ispure kindfn ids current_rule =
List.concat
(List.map
kindfn ar rule ispure checker)
ids)
+
+let create_metadec_virt ar ispure kindfn ids current_rule =
+ List.concat
+ (List.map
+ (function nm ->
+ let checker = function x -> [Common.Right x] in
+ kindfn ar nm ispure checker !Flag.defined_virtual_env)
+ ids)
+
let create_fresh_metadec kindfn ids current_rule =
List.concat
(List.map
ids)
let create_len_metadec ar ispure kindfn lenid ids current_rule =
- let lendec =
- create_metadec Ast.NONE Ast0.Impure
- (fun _ name _ check_meta -> check_meta(Ast.MetaListlenDecl(name)))
- [lenid] current_rule in
- let lenname =
- match lendec with
- [Common.Left (Ast.MetaListlenDecl(x))] -> x
- | [Common.Right (Ast.MetaListlenDecl(x))] -> x
- | _ -> failwith "unexpected length declaration" in
+ let (lendec,lenname) =
+ match lenid with
+ Common.Left lenid ->
+ let lendec =
+ create_metadec Ast.NONE Ast0.Impure
+ (fun _ name _ check_meta -> check_meta(Ast.MetaListlenDecl(name)))
+ [lenid] current_rule in
+ let lenname =
+ match lendec with
+ [Common.Left (Ast.MetaListlenDecl(x))] -> Ast.MetaLen x
+ | [Common.Right (Ast.MetaListlenDecl(x))] -> Ast.MetaLen x
+ | _ -> failwith "unexpected length declaration" in
+ (lendec,lenname)
+ | Common.Right n -> ([],Ast.CstLen n) in
lendec@(create_metadec ar ispure (kindfn lenname) ids current_rule)
(* ---------------------------------------------------------------------- *)
List.map (function "..." -> Ast.IncDots | s -> Ast.IncPath s) elements
(* ---------------------------------------------------------------------- *)
-(* statements *)
+(* declarations and statements *)
+
+let meta_decl name =
+ let (nm,pure,clt) = name in
+ Ast0.wrap(Ast0.MetaDecl(clt2mcode nm clt,pure))
+
+let meta_field name =
+ let (nm,pure,clt) = name in
+ Ast0.wrap(Ast0.MetaField(clt2mcode nm clt,pure))
+
+let meta_field_list name =
+ let (nm,lenname,pure,clt) = name in
+ let lenname =
+ match lenname with
+ Ast.AnyLen -> Ast0.AnyListLen
+ | Ast.MetaLen nm -> Ast0.MetaListLen(clt2mcode nm clt)
+ | Ast.CstLen n -> Ast0.CstListLen n in
+ Ast0.wrap(Ast0.MetaFieldList(clt2mcode nm clt,lenname,pure))
let meta_stm name =
let (nm,pure,clt) = name in
(* ---------------------------------------------------------------------- *)
-let make_iso_rule_name_result n =
- (try let _ = Hashtbl.find Data.all_metadecls n in
- raise (Semantic_cocci.Semantic ("repeated rule name"))
- with Not_found -> ());
- Ast.CocciRulename (Some n,Ast.NoDep,[],[],Ast.Undetermined,false (*discarded*))
-
-let make_cocci_rule_name_result nm d i a e ee =
- match nm with
+let check_rule_name = function
Some nm ->
let n = id2name nm in
(try let _ = Hashtbl.find Data.all_metadecls n in
raise (Semantic_cocci.Semantic ("repeated rule name"))
- with Not_found -> ());
- Ast.CocciRulename (Some n,d,i,a,e,ee)
- | None -> Ast.CocciRulename (None,d,i,a,e,ee)
+ with Not_found -> Some n)
+ | None -> None
+
+let make_iso_rule_name_result n =
+ (try let _ = Hashtbl.find Data.all_metadecls n in
+ raise (Semantic_cocci.Semantic ("repeated rule name"))
+ with Not_found -> ());
+ Ast.CocciRulename
+ (Some n,Ast.NoDep,[],[],Ast.Undetermined,false (*discarded*))
+
+let fix_dependencies d =
+ let rec loop inverted = function
+ Ast0.Dep s when inverted -> Ast.AntiDep s
+ | Ast0.Dep s -> Ast.Dep s
+ | Ast0.AntiDep d -> loop (not inverted) d
+ | Ast0.EverDep s when inverted -> Ast.NeverDep s
+ | Ast0.EverDep s -> Ast.EverDep s
+ | Ast0.NeverDep s when inverted -> Ast.EverDep s
+ | Ast0.NeverDep s -> Ast.NeverDep s
+ | Ast0.AndDep(d1,d2) when inverted ->
+ Ast.OrDep(loop inverted d1,loop inverted d2)
+ | Ast0.AndDep(d1,d2) ->
+ Ast.AndDep(loop inverted d1,loop inverted d2)
+ | Ast0.OrDep(d1,d2) when inverted ->
+ Ast.AndDep(loop inverted d1,loop inverted d2)
+ | Ast0.OrDep(d1,d2) ->
+ Ast.OrDep(loop inverted d1,loop inverted d2)
+ | Ast0.NoDep -> Ast.NoDep
+ | Ast0.FailDep -> Ast.FailDep in
+ loop false d
+
+let make_cocci_rule_name_result nm d i a e ee =
+ Ast.CocciRulename (check_rule_name nm,fix_dependencies d,i,a,e,ee)
let make_generated_rule_name_result nm d i a e ee =
- match nm with
- Some nm ->
- let n = id2name nm in
- (try let _ = Hashtbl.find Data.all_metadecls n in
- raise (Semantic_cocci.Semantic ("repeated rule name"))
- with Not_found -> ());
- Ast.GeneratedRulename (Some n,d,i,a,e,ee)
- | None -> Ast.GeneratedRulename (None,d,i,a,e,ee)
+ Ast.GeneratedRulename (check_rule_name nm,fix_dependencies d,i,a,e,ee)
-let make_script_rule_name_result lang deps =
+let make_script_rule_name_result lang nm deps =
let l = id2name lang in
- Ast.ScriptRulename (l,deps)
+ Ast.ScriptRulename (check_rule_name nm,l,fix_dependencies deps)
-let make_initial_script_rule_name_result lang =
+let make_initial_script_rule_name_result lang deps =
let l = id2name lang in
- Ast.InitialScriptRulename(l)
+ Ast.InitialScriptRulename(None,l,fix_dependencies deps)
-let make_final_script_rule_name_result lang =
+let make_final_script_rule_name_result lang deps =
let l = id2name lang in
- Ast.FinalScriptRulename(l)
+ Ast.FinalScriptRulename(None,l,fix_dependencies deps)
(* Allows type alone only when it is void and only when there is only one
parameter. This avoids ambiguity problems in the parser. *)
(Ast0.get_line t))
| _ -> ())
l
+
+(* ---------------------------------------------------------------------- *)
+(* decide whether an init list is ordered or unordered *)
+
+let struct_initializer initlist =
+ let rec loop i =
+ match Ast0.unwrap i with
+ Ast0.InitGccExt _ -> true
+ | Ast0.InitGccName _ -> true
+ | Ast0.OptIni i | Ast0.UniqueIni i -> loop i
+ | Ast0.MetaInit _ | Ast0.MetaInitList _ -> false (* ambiguous... *)
+ | _ -> false in
+ let l = Ast0.undots initlist in
+ (l = []) or (List.exists loop l)
+
+let drop_dot_commas initlist =
+ match Ast0.unwrap initlist with
+ Ast0.DOTS(l) ->
+ let rec loop after_comma = function
+ [] -> []
+ | x::xs ->
+ (match Ast0.unwrap x with
+ Ast0.Idots(dots,whencode) -> x :: (loop true xs)
+ | Ast0.IComma(comma) when after_comma -> (*drop*) loop false xs
+ | _ -> x :: (loop false xs)) in
+ Ast0.rewrap initlist (Ast0.DOTS(loop false l))
+ | _ -> failwith "not supported"