X-Git-Url: https://git.hcoop.net/bpt/coccinelle.git/blobdiff_plain/0708f913629519b5dbc99f68b6f3ea5ab068230c..7f339edd551eefcd6c99f379ce91c27df997cfe3:/python/yes_pycocci.ml diff --git a/python/yes_pycocci.ml b/python/yes_pycocci.ml index bb877d5..5637951 100644 --- a/python/yes_pycocci.ml +++ b/python/yes_pycocci.ml @@ -1,25 +1,30 @@ (* -* Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen -* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller -* 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. -*) - - + * 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 @@ -28,24 +33,50 @@ module StringMap = Map.Make (String) exception Pycocciexception -let check_return_value v = - if v = (pynull ()) then +let python_support = true + +(* ------------------------------------------------------------------- *) +(* The following definitions are from +http://patches.ubuntu.com/by-release/extracted/debian/c/coccinelle/0.1.5dbs-2/01-system-pycaml +as well as _pycocci_setargs *) + +let _pycocci_none () = + let builtins = pyeval_getbuiltins () in + pyobject_getitem (builtins, pystring_fromstring "None") + +let _pycocci_true () = + let builtins = pyeval_getbuiltins () in + pyobject_getitem (builtins, pystring_fromstring "True") + +let _pycocci_false () = + let builtins = pyeval_getbuiltins () in + pyobject_getitem (builtins, pystring_fromstring "False") + +let _pycocci_tuple6 (a,b,c,d,e,f) = + pytuple_fromarray ([|a; b; c; d; e; f|]) + +(* ------------------------------------------------------------------- *) + +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 = - if v = -1 then +let check_int_return_value msg v = + if v =|= -1 then (pyerr_print (); + Common.pr2 ("while " ^ msg ^ ":"); raise Pycocciexception) else () let initialised = ref false -let coccinelle_module = ref (pynone ()) +let coccinelle_module = ref (_pycocci_none ()) let cocci_file_name = ref "" (* dealing with python modules loaded *) -let module_map = ref (StringMap.add "__main__" (pynone ()) StringMap.empty) +let module_map = ref (StringMap.add "__main__" (_pycocci_none ()) StringMap.empty) let get_module module_name = StringMap.find module_name (!module_map) @@ -58,39 +89,14 @@ 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 (* end python module handling part *) -(* initialisation routines *) -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%!"; - py_initialize()) in - - (* set argv *) - let argv0 = Printf.sprintf "%s%sspatch" (Sys.getcwd ()) (match Sys.os_type with "Win32" -> "\\" | _ -> "/") in - let _ = pycaml_setargs argv0 in - - coccinelle_module := (pymodule_new "coccinelle"); - module_map := StringMap.add "coccinelle" !coccinelle_module !module_map; - let _ = load_module "coccilib.elems" in - let _ = load_module "coccilib.output" in - ()) else - - () - -(*let _ = pycocci_init ()*) -(* end initialisation routines *) - (* python interaction *) let split_fqn fqn = let last_period = String.rindex fqn '.' in @@ -102,116 +108,210 @@ 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; - pynone () + _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; - 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 dictionary" cd; + let cx = pyclass_new(pytuple_fromsingle (pycocci_get_class_type parent), cd, + pystring_fromstring cname) in + 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 has_environment_binding env name = +let the_environment = ref [] + +let has_environment_binding name = let a = pytuple_toarray name in 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) env in - if e then pytrue () else pyfalse () + let e = List.exists (function (x,y) -> orule =*= x && oname =$= y) + !the_environment in + if e then _pycocci_true () else _pycocci_false () -let pyoutputinstance = ref (pynone ()) -let pyoutputdict = ref (pynone ()) +let pyoutputinstance = ref (_pycocci_none ()) +let pyoutputdict = ref (_pycocci_none ()) let get_cocci_file args = - pystring_fromstring (!cocci_file_name) + pystring_fromstring (!cocci_file_name) + +(* initialisation routines *) +let _pycocci_setargs argv0 = + let argv = + pysequence_list (pytuple_fromsingle (pystring_fromstring argv0)) in + let sys_mod = load_module "sys" in + pyobject_setattrstring (sys_mod, "argv", argv) + +let pycocci_init () = + (* initialize *) + if not !initialised then ( + initialised := true; + (* 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 = Sys.executable_name in + let _ = _pycocci_setargs argv0 in + + coccinelle_module := (pymodule_new "coccinelle"); + module_map := StringMap.add "coccinelle" !coccinelle_module !module_map; + let _ = load_module "coccilib.elems" in + let _ = load_module "coccilib.output" in + + let module_dictionary = pyimport_getmoduledict() in + coccinelle_module := pymodule_new "coccinelle"; + let mx = !coccinelle_module in + 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 "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 "adding python field cocci_file" v2; + ()) else + () + +(*let _ = pycocci_init ()*) +(* end initialisation routines *) + +let added_variables = ref [] let build_classes env = - let _ = pycocci_init () in - let module_dictionary = pyimport_getmoduledict() in - coccinelle_module := pymodule_new "coccinelle"; - let mx = !coccinelle_module in - inc_match := true; - let (cd, cx) = build_class "Cocci" (!Flag.pyoutput) - [("include_match", include_match, (pynull())); - ("has_env_binding", has_environment_binding env, (pynull()))] mx in - pyoutputinstance := cx; - pyoutputdict := cd; - let v1 = pydict_setitemstring(module_dictionary, "coccinelle", mx) in - check_int_return_value v1; - let mypystring = pystring_fromstring !cocci_file_name in - let v2 = pydict_setitemstring(cd, "cocci_file", mypystring) in - check_int_return_value v2; - () + 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" | "exit" -> () + | name -> + let v = pydict_delitemstring(dict,name) in + check_int_return_value ("removing " ^ name ^ " from python coccinelle module") v) + !added_variables; + added_variables := []; + () let build_variable name value = let mx = !coccinelle_module in - check_int_return_value (pydict_setitemstring(pymodule_getdict mx, name, value)) + added_variables := name :: !added_variables; + check_int_return_value ("build python variable " ^ name) + (pydict_setitemstring(pymodule_getdict mx, name, value)) + +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)) = +let contains_binding e (_,(r,m),_) = try - let _ = List.find (function ((re, rm), _) -> r = re && m = rm) e in true + 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)) + 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)) + 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 (function (fname,current_element,(line,col),(line_end,col_end)) -> - pycocci_instantiate_class "coccilib.elems.Location" (pytuple6 + pycocci_instantiate_class "coccilib.elems.Location" + (_pycocci_tuple6 (pystring_fromstring fname,pystring_fromstring current_element, pystring_fromstring (Printf.sprintf "%d" line), pystring_fromstring (Printf.sprintf "%d" col), @@ -221,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 ()