Release coccinelle-0.2.3rc1
[bpt/coccinelle.git] / engine / pattern_c.ml
index 89abfb4..fd7b11a 100644 (file)
  *)
 
 
+(*
+ * Copyright 2005-2010, 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.
+ *)
+
+
 (* Yoann Padioleau
  *
  * Copyright (C) 2006, 2007 Ecole des Mines de Nantes
@@ -362,51 +384,101 @@ module XMATCH = struct
           else None
 
       | None ->
-          let valu' =
-            match valu with
-              Ast_c.MetaIdVal a        -> Ast_c.MetaIdVal a
-            | Ast_c.MetaFuncVal a      -> Ast_c.MetaFuncVal a
-            | Ast_c.MetaLocalFuncVal a -> Ast_c.MetaLocalFuncVal a (*more?*)
-            | Ast_c.MetaExprVal a ->
-               Ast_c.MetaExprVal
-                 (if strip
-                 then Lib_parsing_c.al_expr a
-                 else Lib_parsing_c.semi_al_expr a)
-            | Ast_c.MetaExprListVal a ->
-               Ast_c.MetaExprListVal
-                 (if strip
-                 then Lib_parsing_c.al_arguments a
-                 else Lib_parsing_c.semi_al_arguments a)
-
-            | Ast_c.MetaStmtVal a ->
-               Ast_c.MetaStmtVal
-                 (if strip
-                 then Lib_parsing_c.al_statement a
-                 else Lib_parsing_c.semi_al_statement a)
-            | Ast_c.MetaTypeVal a ->
-               Ast_c.MetaTypeVal
-                 (if strip
-                 then Lib_parsing_c.al_type a
-                 else Lib_parsing_c.semi_al_type a)
-
-            | Ast_c.MetaInitVal a ->
-               Ast_c.MetaInitVal
-                 (if strip
-                 then Lib_parsing_c.al_init a
-                 else Lib_parsing_c.semi_al_init a)
-
-            | Ast_c.MetaListlenVal a -> Ast_c.MetaListlenVal a
-
-            | Ast_c.MetaParamVal a -> failwith "not handling MetaParamVal"
-            | Ast_c.MetaParamListVal a ->
-               Ast_c.MetaParamListVal
-                 (if strip
-                 then Lib_parsing_c.al_params a
-                 else Lib_parsing_c.semi_al_params a)
-
-            | Ast_c.MetaPosVal (pos1,pos2) -> Ast_c.MetaPosVal (pos1,pos2)
-            | Ast_c.MetaPosValList l -> Ast_c.MetaPosValList l
-          in Some (tin.binding +> Common.insert_assoc (k, valu'))
+         let success valu' =
+           Some (tin.binding +> Common.insert_assoc (k, valu')) in
+          (match valu with
+            Ast_c.MetaIdVal (a,c)    ->
+             (* c is a negated constraint *)
+             let rec loop = function
+                 [] -> success(Ast_c.MetaIdVal(a,[]))
+               | c::cs ->
+                   let tmp =
+                     Common.optionise
+                       (fun () -> tin.binding0 +> List.assoc c) in
+                   (match tmp with
+                     Some (Ast_c.MetaIdVal(v,_)) ->
+                       if a =$= v
+                       then None (* failure *)
+                       else success(Ast_c.MetaIdVal(a,[]))
+                   | Some _ -> failwith "Not possible"
+                   | None -> success(Ast_c.MetaIdVal(a,[]))) in
+             loop c
+          | Ast_c.MetaFuncVal a      ->
+             success(Ast_c.MetaFuncVal a)
+          | Ast_c.MetaLocalFuncVal a ->
+             success(Ast_c.MetaLocalFuncVal a) (*more?*)
+          | Ast_c.MetaExprVal (a,c) ->
+             (* c in the value is only to prepare for the future in which
+                we figure out how to have subterm constraints on unbound
+                variables.  Now an environment will only contain expression
+                values with empty constraints, as all constraints are
+                resolved at binding time *)
+             let stripped =
+               if strip
+               then Lib_parsing_c.al_expr a
+               else Lib_parsing_c.semi_al_expr a in
+             let inh_stripped = Lib_parsing_c.al_inh_expr a in
+             let rec loop = function
+                 [] -> success(Ast_c.MetaExprVal(stripped,[]))
+               | c::cs ->
+                   let tmp =
+                     Common.optionise
+                       (fun () -> tin.binding0 +> List.assoc c) in
+                   (match tmp with
+                     Some (Ast_c.MetaExprVal(v,_)) ->
+                       if C_vs_c.subexpression_of_expression inh_stripped v
+                       then loop cs (* forget satisfied constraints *)
+                       else None (* failure *)
+                   | Some _ -> failwith "not possible"
+                     (* fail if this should be a subterm of something that
+                        doesn't exist *)
+                   | None -> None) in
+             loop c
+          | Ast_c.MetaExprListVal a ->
+             success
+               (Ast_c.MetaExprListVal
+                  (if strip
+                  then Lib_parsing_c.al_arguments a
+                  else Lib_parsing_c.semi_al_arguments a))
+               
+          | Ast_c.MetaStmtVal a ->
+             success
+               (Ast_c.MetaStmtVal
+                  (if strip
+                  then Lib_parsing_c.al_statement a
+                  else Lib_parsing_c.semi_al_statement a))
+          | Ast_c.MetaTypeVal a ->
+             success
+               (Ast_c.MetaTypeVal
+                  (if strip
+                  then Lib_parsing_c.al_type a
+                  else Lib_parsing_c.semi_al_type a))
+               
+          | Ast_c.MetaInitVal a ->
+             success
+               (Ast_c.MetaInitVal
+                  (if strip
+                  then Lib_parsing_c.al_init a
+                  else Lib_parsing_c.semi_al_init a))
+               
+          | Ast_c.MetaListlenVal a -> success(Ast_c.MetaListlenVal a)
+               
+          | Ast_c.MetaParamVal a ->
+             success
+               (Ast_c.MetaParamVal
+                  (if strip
+                  then Lib_parsing_c.al_param a
+                  else Lib_parsing_c.semi_al_param a))
+          | Ast_c.MetaParamListVal a ->
+             success
+               (Ast_c.MetaParamListVal
+                  (if strip
+                  then Lib_parsing_c.al_params a
+                  else Lib_parsing_c.semi_al_params a))
+               
+          | Ast_c.MetaPosVal (pos1,pos2) ->
+             success(Ast_c.MetaPosVal (pos1,pos2))
+          | Ast_c.MetaPosValList l -> success (Ast_c.MetaPosValList l))
 
   let envf keep inherited = fun (k, valu, get_max_min) f tin ->
     let x = Ast_cocci.unwrap_mcode k in