X-Git-Url: https://git.hcoop.net/bpt/coccinelle.git/blobdiff_plain/7f00441914f5b9bd4f845a1c866da65e1946083e..7f339edd551eefcd6c99f379ce91c27df997cfe3:/python/yes_pycocci.ml diff --git a/python/yes_pycocci.ml b/python/yes_pycocci.ml index b507c55..5637951 100644 --- a/python/yes_pycocci.ml +++ b/python/yes_pycocci.ml @@ -1,3 +1,30 @@ +(* + * 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 . + * + * The authors reserve the right to distribute this or future versions of + * Coccinelle under other licenses. + *) + + +# 0 "./yes_pycocci.ml" open Ast_c open Common open Pycaml @@ -30,14 +57,16 @@ let _pycocci_tuple6 (a,b,c,d,e,f) = (* ------------------------------------------------------------------- *) -let check_return_value v = - if v =*= (pynull ()) then +let check_return_value msg v = + if v =*= (pynull ()) then (pyerr_print (); + Common.pr2 ("while " ^ msg ^ ":"); raise Pycocciexception) else () -let check_int_return_value v = +let check_int_return_value msg v = if v =|= -1 then (pyerr_print (); + Common.pr2 ("while " ^ msg ^ ":"); raise Pycocciexception) else () @@ -60,8 +89,9 @@ let is_module_loaded module_name = let load_module module_name = if not (is_module_loaded module_name) then + (* let _ = Sys.command("python3 -c 'import " ^ module_name ^ "'") in *) let m = pyimport_importmodule module_name in - check_return_value m; + check_return_value ("importing module " ^ module_name) m; (module_map := (StringMap.add module_name m (!module_map)); m) else get_module module_name @@ -78,40 +108,46 @@ let pycocci_get_class_type fqn = let (module_name, class_name) = split_fqn fqn in let m = get_module module_name in let attr = pyobject_getattrstring(m, class_name) in - check_return_value attr; + check_return_value "obtaining a python class type" attr; attr let pycocci_instantiate_class fqn args = let class_type = pycocci_get_class_type fqn in - let obj = pyobject_callobject(class_type, args) in - check_return_value obj; + let obj = + pyeval_callobjectwithkeywords(class_type, args, pynull()) in + check_return_value "instantiating a python class" obj; obj (* end python interaction *) let inc_match = ref true +let exited = ref false let include_match v = let truth = pyobject_istrue (pytuple_getitem (v, 1)) in - check_int_return_value truth; + check_int_return_value "testing include_match" truth; inc_match := truth != 0; _pycocci_none () +let sp_exit _ = + exited := true; + _pycocci_none () + let build_method (mname, camlfunc, args) pymodule classx classdict = let cmx = pymethod_new(pywrap_closure camlfunc, args, classx) in let v = pydict_setitemstring(classdict, mname, cmx) in - check_int_return_value v; + check_int_return_value ("building python method " ^ mname) v; () let build_class cname parent methods pymodule = let cd = pydict_new() in - check_return_value cd; + check_return_value "creating a new python dictionary" cd; let cx = pyclass_new(pytuple_fromsingle (pycocci_get_class_type parent), cd, pystring_fromstring cname) in - check_return_value cx; + check_return_value "creating a new python class" cx; List.iter (function meth -> build_method meth pymodule cx cd) methods; let v = pydict_setitemstring(pymodule_getdict pymodule, cname, cx) in - check_int_return_value v; + check_int_return_value ("adding python class " ^ cname) v; (cd, cx) let the_environment = ref [] @@ -121,7 +157,7 @@ let has_environment_binding name = let (rule, name) = (Array.get a 1, Array.get a 2) in let orule = pystring_asstring rule in let oname = pystring_asstring name in - let e = List.exists (function (x,y) -> orule =$= x && oname =$= y) + let e = List.exists (function (x,y) -> orule =*= x && oname =$= y) !the_environment in if e then _pycocci_true () else _pycocci_false () @@ -142,14 +178,17 @@ let pycocci_init () = (* initialize *) if not !initialised then ( initialised := true; - Unix.putenv "PYTHONPATH" - (Printf.sprintf "%s/coccinelle" (Unix.getenv "HOME")); - let _ = if not (py_isinitialized () != 0) then - (if !Flag.show_misc then Common.pr2 "Initializing python\n%!"; + (* use python_path_base as default (overridable) dir for coccilib *) + let python_path_base = Printf.sprintf "%s/coccinelle" (Unix.getenv "HOME") in + let python_path = try Unix.getenv "PYTHONPATH" ^ ":" ^ python_path_base + with Not_found -> python_path_base in + Unix.putenv "PYTHONPATH" python_path; + let _ = if not (py_isinitialized () != 0) then + (if !Flag.show_misc then Common.pr2 "Initializing python\n%!"; py_initialize()) in (* set argv *) - let argv0 = Printf.sprintf "%s%sspatch" (Sys.getcwd ()) (match Sys.os_type with "Win32" -> "\\" | _ -> "/") in + let argv0 = Sys.executable_name in let _ = _pycocci_setargs argv0 in coccinelle_module := (pymodule_new "coccinelle"); @@ -160,16 +199,17 @@ let pycocci_init () = let module_dictionary = pyimport_getmoduledict() in coccinelle_module := pymodule_new "coccinelle"; let mx = !coccinelle_module in - let (cd, cx) = build_class "Cocci" (!Flag.pyoutput) - [("include_match", include_match, (pynull())); + let (cd, cx) = build_class "Cocci" (!Flag.pyoutput) + [("exit", sp_exit, (pynull())); + ("include_match", include_match, (pynull())); ("has_env_binding", has_environment_binding, (pynull()))] mx in pyoutputinstance := cx; pyoutputdict := cd; let v1 = pydict_setitemstring(module_dictionary, "coccinelle", mx) in - check_int_return_value v1; + check_int_return_value "adding coccinelle python module" v1; let mypystring = pystring_fromstring !cocci_file_name in let v2 = pydict_setitemstring(cd, "cocci_file", mypystring) in - check_int_return_value v2; + check_int_return_value "adding python field cocci_file" v2; ()) else () @@ -181,15 +221,16 @@ let added_variables = ref [] let build_classes env = let _ = pycocci_init () in inc_match := true; + exited := false; the_environment := env; let mx = !coccinelle_module in let dict = pymodule_getdict mx in List.iter (function - "include_match" | "has_env_binding" -> () + "include_match" | "has_env_binding" | "exit" -> () | name -> let v = pydict_delitemstring(dict,name) in - check_int_return_value v) + check_int_return_value ("removing " ^ name ^ " from python coccinelle module") v) !added_variables; added_variables := []; () @@ -197,46 +238,74 @@ let build_classes env = let build_variable name value = let mx = !coccinelle_module in added_variables := name :: !added_variables; - check_int_return_value + check_int_return_value ("build python variable " ^ name) (pydict_setitemstring(pymodule_getdict mx, name, value)) -let contains_binding e (_,(r,m)) = +let get_variable name = + let mx = !coccinelle_module in + pystring_asstring + (pyobject_str(pydict_getitemstring(pymodule_getdict mx, name))) + +let contains_binding e (_,(r,m),_) = try - let _ = List.find (function ((re, rm), _) -> r =$= re && m =$= rm) e in + let _ = List.find (function ((re, rm), _) -> r =*= re && m =$= rm) e in true with Not_found -> false let construct_variables mv e = let find_binding (r,m) = try - let elem = List.find (function ((re,rm),_) -> r =$= re && m =$= rm) e in + let elem = List.find (function ((re,rm),_) -> r =*= re && m =$= rm) e in Some elem with Not_found -> None in +(* Only string in this representation, so no point let instantiate_Expression(x) = let str = pystring_fromstring (Pycocci_aux.exprrep x) in pycocci_instantiate_class "coccilib.elems.Expression" (pytuple_fromsingle (str)) in +*) +(* Only string in this representation, so no point let instantiate_Identifier(x) = let str = pystring_fromstring x in pycocci_instantiate_class "coccilib.elems.Identifier" (pytuple_fromsingle (str)) in - - List.iter (function (py,(r,m)) -> +*) + + let instantiate_term_list py printer lst = + let (str,elements) = printer lst in + let str = pystring_fromstring str in + let elements = + pytuple_fromarray + (Array.of_list (List.map pystring_fromstring elements)) in + let repr = + pycocci_instantiate_class "coccilib.elems.TermList" + (pytuple_fromarray (Array.of_list [str;elements])) in + let _ = build_variable py repr in () in + + List.iter (function (py,(r,m),_) -> match find_binding (r,m) with None -> () - | Some (_, Ast_c.MetaExprVal expr) -> +(* | Some (_, Ast_c.MetaExprVal (expr,_)) -> let expr_repr = instantiate_Expression(expr) in let _ = build_variable py expr_repr in - () - | Some (_, Ast_c.MetaIdVal id) -> + () *) + (* | Some (_, Ast_c.MetaIdVal (id,_)) -> let id_repr = instantiate_Identifier(id) in let _ = build_variable py id_repr in - () + () *) + | Some (_, Ast_c.MetaExprListVal (exprlist)) -> + instantiate_term_list py Pycocci_aux.exprlistrep exprlist + | Some (_, Ast_c.MetaParamListVal (paramlist)) -> + instantiate_term_list py Pycocci_aux.paramlistrep paramlist + | Some (_, Ast_c.MetaInitListVal (initlist)) -> + instantiate_term_list py Pycocci_aux.initlistrep initlist + | Some (_, Ast_c.MetaFieldListVal (fieldlist)) -> + instantiate_term_list py Pycocci_aux.fieldlistrep fieldlist | Some (_, Ast_c.MetaPosValList l) -> let locs = List.map @@ -252,21 +321,37 @@ let construct_variables mv e = let _ = build_variable py pylocs in () | Some (_,binding) -> - let _ = build_variable py (pystring_fromstring (Pycocci_aux.stringrep binding)) - in () + let _ = + build_variable py + (pystring_fromstring (Pycocci_aux.stringrep binding)) in + () ) mv; () +let construct_script_variables mv = + List.iter + (function (_,py) -> + let str = + pystring_fromstring + "initial value: consider using coccinelle.varname" in + let _ = build_variable py str in + ()) + mv + +let retrieve_script_variables mv = + List.map (function (_,py) -> get_variable py) mv + let set_coccifile cocci_file = cocci_file_name := cocci_file; () +let pyrun_simplestring s = + let res = Pycaml.pyrun_simplestring s in + check_int_return_value ("running simple python string: " ^ s) res; + res -let pyrun_simplestring s = - Pycaml.pyrun_simplestring s - -let py_isinitialized () = +let py_isinitialized () = Pycaml.py_isinitialized ()