2 * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
3 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
4 * This file is part of Coccinelle.
6 * Coccinelle is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, according to version 2 of the License.
10 * Coccinelle is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
27 module StringMap
= Map.Make
(String
)
29 exception Pycocciexception
31 let python_support = true
33 (* ------------------------------------------------------------------- *)
34 (* The following definitions are from
35 http://patches.ubuntu.com/by-release/extracted/debian/c/coccinelle/0.1.5dbs-2/01-system-pycaml
36 as well as _pycocci_setargs *)
38 let _pycocci_none () =
39 let builtins = pyeval_getbuiltins
() in
40 pyobject_getitem
(builtins, pystring_fromstring
"None")
42 let _pycocci_true () =
43 let builtins = pyeval_getbuiltins
() in
44 pyobject_getitem
(builtins, pystring_fromstring
"True")
46 let _pycocci_false () =
47 let builtins = pyeval_getbuiltins
() in
48 pyobject_getitem
(builtins, pystring_fromstring
"False")
50 let _pycocci_tuple6 (a
,b
,c
,d
,e
,f
) =
51 pytuple_fromarray
([|a
; b
; c
; d
; e
; f
|])
53 (* ------------------------------------------------------------------- *)
55 let check_return_value v
=
56 if v
=*= (pynull
()) then
58 raise Pycocciexception
)
60 let check_int_return_value v
=
63 raise Pycocciexception
)
66 let initialised = ref false
68 let coccinelle_module = ref (_pycocci_none ())
69 let cocci_file_name = ref ""
71 (* dealing with python modules loaded *)
72 let module_map = ref (StringMap.add
"__main__" (_pycocci_none ()) StringMap.empty
)
74 let get_module module_name
=
75 StringMap.find module_name
(!module_map)
77 let is_module_loaded module_name
=
79 let _ = get_module module_name
in
81 with Not_found
-> false
83 let load_module module_name
=
84 if not
(is_module_loaded module_name
) then
85 let m = pyimport_importmodule module_name
in
87 (module_map := (StringMap.add module_name
m (!module_map));
89 else get_module module_name
90 (* end python module handling part *)
92 (* python interaction *)
94 let last_period = String.rindex fqn '
.'
in
95 let module_name = String.sub fqn
0 last_period in
96 let class_name = String.sub fqn
(last_period + 1) (String.length fqn
- last_period - 1) in
97 (module_name, class_name)
99 let pycocci_get_class_type fqn
=
100 let (module_name, class_name) = split_fqn fqn
in
101 let m = get_module module_name in
102 let attr = pyobject_getattrstring
(m, class_name) in
103 check_return_value attr;
106 let pycocci_instantiate_class fqn args
=
107 let class_type = pycocci_get_class_type fqn
in
108 let obj = pyobject_callobject
(class_type, args
) in
109 check_return_value obj;
112 (* end python interaction *)
114 let inc_match = ref true
116 let include_match v
=
117 let truth = pyobject_istrue
(pytuple_getitem
(v
, 1)) in
118 check_int_return_value truth;
119 inc_match := truth != 0;
122 let build_method (mname
, camlfunc
, args
) pymodule classx classdict
=
123 let cmx = pymethod_new
(pywrap_closure camlfunc
, args
, classx
) in
124 let v = pydict_setitemstring
(classdict
, mname
, cmx) in
125 check_int_return_value v;
128 let build_class cname parent methods pymodule
=
129 let cd = pydict_new
() in
130 check_return_value cd;
131 let cx = pyclass_new
(pytuple_fromsingle
(pycocci_get_class_type parent
), cd,
132 pystring_fromstring cname
) in
133 check_return_value cx;
134 List.iter
(function meth
-> build_method meth pymodule
cx cd) methods
;
135 let v = pydict_setitemstring
(pymodule_getdict pymodule
, cname
, cx) in
136 check_int_return_value v;
139 let the_environment = ref []
141 let has_environment_binding name
=
142 let a = pytuple_toarray name
in
143 let (rule
, name
) = (Array.get
a 1, Array.get
a 2) in
144 let orule = pystring_asstring rule
in
145 let oname = pystring_asstring name
in
146 let e = List.exists
(function (x
,y
) -> orule =*= x
&& oname =$
= y
)
148 if e then _pycocci_true () else _pycocci_false ()
150 let pyoutputinstance = ref (_pycocci_none ())
151 let pyoutputdict = ref (_pycocci_none ())
153 let get_cocci_file args
=
154 pystring_fromstring
(!cocci_file_name)
156 (* initialisation routines *)
157 let _pycocci_setargs argv0
=
159 pysequence_list
(pytuple_fromsingle
(pystring_fromstring argv0
)) in
160 let sys_mod = load_module "sys" in
161 pyobject_setattrstring
(sys_mod, "argv", argv)
163 let pycocci_init () =
165 if not
!initialised then (
167 Unix.putenv
"PYTHONPATH"
168 (Printf.sprintf
"%s/coccinelle" (Unix.getenv
"HOME"));
169 let _ = if not
(py_isinitialized
() != 0) then
170 (if !Flag.show_misc
then Common.pr2
"Initializing python\n%!";
174 let argv0 = Printf.sprintf
"%s%sspatch" (Sys.getcwd
()) (match Sys.os_type
with "Win32" -> "\\" | _ -> "/") in
175 let _ = _pycocci_setargs argv0 in
177 coccinelle_module := (pymodule_new
"coccinelle");
178 module_map := StringMap.add
"coccinelle" !coccinelle_module !module_map;
179 let _ = load_module "coccilib.elems" in
180 let _ = load_module "coccilib.output" in
182 let module_dictionary = pyimport_getmoduledict
() in
183 coccinelle_module := pymodule_new
"coccinelle";
184 let mx = !coccinelle_module in
185 let (cd, cx) = build_class "Cocci" (!Flag.pyoutput
)
186 [("include_match", include_match, (pynull
()));
187 ("has_env_binding", has_environment_binding, (pynull
()))] mx in
188 pyoutputinstance := cx;
190 let v1 = pydict_setitemstring
(module_dictionary, "coccinelle", mx) in
191 check_int_return_value v1;
192 let mypystring = pystring_fromstring
!cocci_file_name in
193 let v2 = pydict_setitemstring
(cd, "cocci_file", mypystring) in
194 check_int_return_value v2;
198 (*let _ = pycocci_init ()*)
199 (* end initialisation routines *)
201 let added_variables = ref []
203 let build_classes env
=
204 let _ = pycocci_init () in
206 the_environment := env
;
207 let mx = !coccinelle_module in
208 let dict = pymodule_getdict
mx in
211 "include_match" | "has_env_binding" -> ()
213 let v = pydict_delitemstring
(dict,name
) in
214 check_int_return_value v)
216 added_variables := [];
219 let build_variable name
value =
220 let mx = !coccinelle_module in
221 added_variables := name
:: !added_variables;
222 check_int_return_value
223 (pydict_setitemstring
(pymodule_getdict
mx, name
, value))
225 let contains_binding e (_,(r
,m)) =
227 let _ = List.find
(function ((re
, rm
), _) -> r
=*= re
&& m =$
= rm
) e in
229 with Not_found
-> false
231 let construct_variables mv
e =
232 let find_binding (r
,m) =
234 let elem = List.find
(function ((re
,rm
),_) -> r
=*= re
&& m =$
= rm
) e in
236 with Not_found
-> None
239 let instantiate_Expression(x
) =
240 let str = pystring_fromstring
(Pycocci_aux.exprrep x
) in
241 pycocci_instantiate_class "coccilib.elems.Expression"
242 (pytuple_fromsingle
(str))
245 let instantiate_Identifier(x
) =
246 let str = pystring_fromstring x
in
247 pycocci_instantiate_class "coccilib.elems.Identifier"
248 (pytuple_fromsingle
(str))
251 List.iter
(function (py
,(r
,m)) ->
252 match find_binding (r
,m) with
254 | Some
(_, Ast_c.MetaExprVal expr
) ->
255 let expr_repr = instantiate_Expression(expr
) in
256 let _ = build_variable py
expr_repr in
258 | Some
(_, Ast_c.MetaIdVal id
) ->
259 let id_repr = instantiate_Identifier(id
) in
260 let _ = build_variable py
id_repr in
262 | Some
(_, Ast_c.MetaPosValList l
) ->
265 (function (fname
,current_element
,(line
,col
),(line_end
,col_end
)) ->
266 pycocci_instantiate_class "coccilib.elems.Location"
268 (pystring_fromstring fname
,pystring_fromstring current_element
,
269 pystring_fromstring
(Printf.sprintf
"%d" line
),
270 pystring_fromstring
(Printf.sprintf
"%d" col
),
271 pystring_fromstring
(Printf.sprintf
"%d" line_end
),
272 pystring_fromstring
(Printf.sprintf
"%d" col_end
)))) l
in
273 let pylocs = pytuple_fromarray
(Array.of_list
locs) in
274 let _ = build_variable py
pylocs in
276 | Some
(_,binding
) ->
277 let _ = build_variable py
(pystring_fromstring
(Pycocci_aux.stringrep binding
))
283 let set_coccifile cocci_file
=
284 cocci_file_name := cocci_file
;
287 let pyrun_simplestring s
=
288 Pycaml.pyrun_simplestring s
290 let py_isinitialized () =
291 Pycaml.py_isinitialized ()
295 Pycaml.py_finalize ()