(*
* 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 .
*
* The authors reserve the right to distribute this or future versions of
* Coccinelle under other licenses.
*)
(*
* 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 .
*
* The authors reserve the right to distribute this or future versions of
* Coccinelle under other licenses.
*)
(*
* 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 .
*
* The authors reserve the right to distribute this or future versions of
* Coccinelle under other licenses.
*)
open Ast_c
open Common
open Pycaml
open Pycocci_aux
module StringMap = Map.Make (String)
exception Pycocciexception
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 v =
if v =*= (pynull ()) then
(pyerr_print ();
raise Pycocciexception)
else ()
let check_int_return_value v =
if v =|= -1 then
(pyerr_print ();
raise Pycocciexception)
else ()
let initialised = ref false
let coccinelle_module = ref (_pycocci_none ())
let cocci_file_name = ref ""
(* dealing with python modules loaded *)
let module_map = ref (StringMap.add "__main__" (_pycocci_none ()) StringMap.empty)
let get_module module_name =
StringMap.find module_name (!module_map)
let is_module_loaded module_name =
try
let _ = get_module module_name in
true
with Not_found -> false
let load_module module_name =
if not (is_module_loaded module_name) then
let m = pyimport_importmodule module_name in
check_return_value m;
(module_map := (StringMap.add module_name m (!module_map));
m)
else get_module module_name
(* end python module handling part *)
(* python interaction *)
let split_fqn fqn =
let last_period = String.rindex fqn '.' in
let module_name = String.sub fqn 0 last_period in
let class_name = String.sub fqn (last_period + 1) (String.length fqn - last_period - 1) in
(module_name, class_name)
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;
attr
let pycocci_instantiate_class fqn args =
let class_type = pycocci_get_class_type fqn in
let obj =
pyeval_callobjectwithkeywords(class_type, args, pynull()) in
check_return_value obj;
obj
(* end python interaction *)
let inc_match = ref true
let include_match v =
let truth = pyobject_istrue (pytuple_getitem (v, 1)) in
check_int_return_value truth;
inc_match := truth != 0;
_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;
()
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;
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;
(cd, cx)
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)
!the_environment in
if e then _pycocci_true () else _pycocci_false ()
let pyoutputinstance = ref (_pycocci_none ())
let pyoutputdict = ref (_pycocci_none ())
let get_cocci_file args =
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;
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 _ = _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)
[("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;
let mypystring = pystring_fromstring !cocci_file_name in
let v2 = pydict_setitemstring(cd, "cocci_file", mypystring) in
check_int_return_value v2;
()) else
()
(*let _ = pycocci_init ()*)
(* end initialisation routines *)
let added_variables = ref []
let build_classes env =
let _ = pycocci_init () in
inc_match := true;
the_environment := env;
let mx = !coccinelle_module in
let dict = pymodule_getdict mx in
List.iter
(function
"include_match" | "has_env_binding" -> ()
| name ->
let v = pydict_delitemstring(dict,name) in
check_int_return_value v)
!added_variables;
added_variables := [];
()
let build_variable name value =
let mx = !coccinelle_module in
added_variables := name :: !added_variables;
check_int_return_value
(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),_) =
try
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
Some elem
with Not_found -> None
in
let instantiate_Expression(x) =
let str = pystring_fromstring (Pycocci_aux.exprrep x) in
pycocci_instantiate_class "coccilib.elems.Expression"
(pytuple_fromsingle (str))
in
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),_) ->
match find_binding (r,m) with
None -> ()
| Some (_, Ast_c.MetaExprVal (expr,_)) ->
let expr_repr = instantiate_Expression(expr) in
let _ = build_variable py expr_repr in
()
| Some (_, Ast_c.MetaIdVal (id,_)) ->
let id_repr = instantiate_Identifier(id) in
let _ = build_variable py id_repr in
()
| 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"
(_pycocci_tuple6
(pystring_fromstring fname,pystring_fromstring current_element,
pystring_fromstring (Printf.sprintf "%d" line),
pystring_fromstring (Printf.sprintf "%d" col),
pystring_fromstring (Printf.sprintf "%d" line_end),
pystring_fromstring (Printf.sprintf "%d" col_end)))) l in
let pylocs = pytuple_fromarray (Array.of_list locs) in
let _ = build_variable py pylocs in
()
| Some (_,binding) ->
let _ =
build_variable py
(pystring_fromstring (Pycocci_aux.stringrep binding)) in
()
) mv;
()
let construct_script_variables mv =
List.iter
(function (_,py) ->
let vl =
let str = pystring_fromstring "initial value" in
pycocci_instantiate_class "coccilib.elems.Identifier"
(pytuple_fromsingle (str)) in
let _ = build_variable py vl 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 res;
res
let py_isinitialized () =
Pycaml.py_isinitialized ()
let py_finalize () =
Pycaml.py_finalize ()