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.
24 * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
25 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
26 * This file is part of Coccinelle.
28 * Coccinelle is free software: you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation, according to version 2 of the License.
32 * Coccinelle is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
37 * You should have received a copy of the GNU General Public License
38 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
40 * The authors reserve the right to distribute this or future versions of
41 * Coccinelle under other licenses.
49 module StringMap
= Map.Make
(String
)
51 exception Pycocciexception
53 let python_support = true
55 (* ------------------------------------------------------------------- *)
56 (* The following definitions are from
57 http://patches.ubuntu.com/by-release/extracted/debian/c/coccinelle/0.1.5dbs-2/01-system-pycaml
58 as well as _pycocci_setargs *)
60 let _pycocci_none () =
61 let builtins = pyeval_getbuiltins
() in
62 pyobject_getitem
(builtins, pystring_fromstring
"None")
64 let _pycocci_true () =
65 let builtins = pyeval_getbuiltins
() in
66 pyobject_getitem
(builtins, pystring_fromstring
"True")
68 let _pycocci_false () =
69 let builtins = pyeval_getbuiltins
() in
70 pyobject_getitem
(builtins, pystring_fromstring
"False")
72 let _pycocci_tuple6 (a
,b
,c
,d
,e
,f
) =
73 pytuple_fromarray
([|a
; b
; c
; d
; e
; f
|])
75 (* ------------------------------------------------------------------- *)
77 let check_return_value v
=
78 if v
=*= (pynull
()) then
80 raise Pycocciexception
)
82 let check_int_return_value v
=
85 raise Pycocciexception
)
88 let initialised = ref false
90 let coccinelle_module = ref (_pycocci_none ())
91 let cocci_file_name = ref ""
93 (* dealing with python modules loaded *)
94 let module_map = ref (StringMap.add
"__main__" (_pycocci_none ()) StringMap.empty
)
96 let get_module module_name
=
97 StringMap.find module_name
(!module_map)
99 let is_module_loaded module_name
=
101 let _ = get_module module_name
in
103 with Not_found
-> false
105 let load_module module_name
=
106 if not
(is_module_loaded module_name
) then
107 let m = pyimport_importmodule module_name
in
108 check_return_value m;
109 (module_map := (StringMap.add module_name
m (!module_map));
111 else get_module module_name
112 (* end python module handling part *)
114 (* python interaction *)
116 let last_period = String.rindex fqn '
.'
in
117 let module_name = String.sub fqn
0 last_period in
118 let class_name = String.sub fqn
(last_period + 1) (String.length fqn
- last_period - 1) in
119 (module_name, class_name)
121 let pycocci_get_class_type fqn
=
122 let (module_name, class_name) = split_fqn fqn
in
123 let m = get_module module_name in
124 let attr = pyobject_getattrstring
(m, class_name) in
125 check_return_value attr;
128 let pycocci_instantiate_class fqn args
=
129 let class_type = pycocci_get_class_type fqn
in
130 let obj = pyobject_callobject
(class_type, args
) in
131 check_return_value obj;
134 (* end python interaction *)
136 let inc_match = ref true
138 let include_match v
=
139 let truth = pyobject_istrue
(pytuple_getitem
(v
, 1)) in
140 check_int_return_value truth;
141 inc_match := truth != 0;
144 let build_method (mname
, camlfunc
, args
) pymodule classx classdict
=
145 let cmx = pymethod_new
(pywrap_closure camlfunc
, args
, classx
) in
146 let v = pydict_setitemstring
(classdict
, mname
, cmx) in
147 check_int_return_value v;
150 let build_class cname parent methods pymodule
=
151 let cd = pydict_new
() in
152 check_return_value cd;
153 let cx = pyclass_new
(pytuple_fromsingle
(pycocci_get_class_type parent
), cd,
154 pystring_fromstring cname
) in
155 check_return_value cx;
156 List.iter
(function meth
-> build_method meth pymodule
cx cd) methods
;
157 let v = pydict_setitemstring
(pymodule_getdict pymodule
, cname
, cx) in
158 check_int_return_value v;
161 let the_environment = ref []
163 let has_environment_binding name
=
164 let a = pytuple_toarray name
in
165 let (rule
, name
) = (Array.get
a 1, Array.get
a 2) in
166 let orule = pystring_asstring rule
in
167 let oname = pystring_asstring name
in
168 let e = List.exists
(function (x
,y
) -> orule =*= x
&& oname =$
= y
)
170 if e then _pycocci_true () else _pycocci_false ()
172 let pyoutputinstance = ref (_pycocci_none ())
173 let pyoutputdict = ref (_pycocci_none ())
175 let get_cocci_file args
=
176 pystring_fromstring
(!cocci_file_name)
178 (* initialisation routines *)
179 let _pycocci_setargs argv0
=
181 pysequence_list
(pytuple_fromsingle
(pystring_fromstring argv0
)) in
182 let sys_mod = load_module "sys" in
183 pyobject_setattrstring
(sys_mod, "argv", argv)
185 let pycocci_init () =
187 if not
!initialised then (
189 Unix.putenv
"PYTHONPATH"
190 (Printf.sprintf
"%s/coccinelle" (Unix.getenv
"HOME"));
191 let _ = if not
(py_isinitialized
() != 0) then
192 (if !Flag.show_misc
then Common.pr2
"Initializing python\n%!";
196 let argv0 = Printf.sprintf
"%s%sspatch" (Sys.getcwd
()) (match Sys.os_type
with "Win32" -> "\\" | _ -> "/") in
197 let _ = _pycocci_setargs argv0 in
199 coccinelle_module := (pymodule_new
"coccinelle");
200 module_map := StringMap.add
"coccinelle" !coccinelle_module !module_map;
201 let _ = load_module "coccilib.elems" in
202 let _ = load_module "coccilib.output" in
204 let module_dictionary = pyimport_getmoduledict
() in
205 coccinelle_module := pymodule_new
"coccinelle";
206 let mx = !coccinelle_module in
207 let (cd, cx) = build_class "Cocci" (!Flag.pyoutput
)
208 [("include_match", include_match, (pynull
()));
209 ("has_env_binding", has_environment_binding, (pynull
()))] mx in
210 pyoutputinstance := cx;
212 let v1 = pydict_setitemstring
(module_dictionary, "coccinelle", mx) in
213 check_int_return_value v1;
214 let mypystring = pystring_fromstring
!cocci_file_name in
215 let v2 = pydict_setitemstring
(cd, "cocci_file", mypystring) in
216 check_int_return_value v2;
220 (*let _ = pycocci_init ()*)
221 (* end initialisation routines *)
223 let added_variables = ref []
225 let build_classes env
=
226 let _ = pycocci_init () in
228 the_environment := env
;
229 let mx = !coccinelle_module in
230 let dict = pymodule_getdict
mx in
233 "include_match" | "has_env_binding" -> ()
235 let v = pydict_delitemstring
(dict,name
) in
236 check_int_return_value v)
238 added_variables := [];
241 let build_variable name
value =
242 let mx = !coccinelle_module in
243 added_variables := name
:: !added_variables;
244 check_int_return_value
245 (pydict_setitemstring
(pymodule_getdict
mx, name
, value))
247 let contains_binding e (_,(r
,m)) =
249 let _ = List.find
(function ((re
, rm
), _) -> r
=*= re
&& m =$
= rm
) e in
251 with Not_found
-> false
253 let construct_variables mv
e =
254 let find_binding (r
,m) =
256 let elem = List.find
(function ((re
,rm
),_) -> r
=*= re
&& m =$
= rm
) e in
258 with Not_found
-> None
261 let instantiate_Expression(x
) =
262 let str = pystring_fromstring
(Pycocci_aux.exprrep x
) in
263 pycocci_instantiate_class "coccilib.elems.Expression"
264 (pytuple_fromsingle
(str))
267 let instantiate_Identifier(x
) =
268 let str = pystring_fromstring x
in
269 pycocci_instantiate_class "coccilib.elems.Identifier"
270 (pytuple_fromsingle
(str))
273 List.iter
(function (py
,(r
,m)) ->
274 match find_binding (r
,m) with
276 | Some
(_, Ast_c.MetaExprVal
(expr
,_)) ->
277 let expr_repr = instantiate_Expression(expr
) in
278 let _ = build_variable py
expr_repr in
280 | Some
(_, Ast_c.MetaIdVal
(id
,_)) ->
281 let id_repr = instantiate_Identifier(id
) in
282 let _ = build_variable py
id_repr in
284 | Some
(_, Ast_c.MetaPosValList l
) ->
287 (function (fname
,current_element
,(line
,col
),(line_end
,col_end
)) ->
288 pycocci_instantiate_class "coccilib.elems.Location"
290 (pystring_fromstring fname
,pystring_fromstring current_element
,
291 pystring_fromstring
(Printf.sprintf
"%d" line
),
292 pystring_fromstring
(Printf.sprintf
"%d" col
),
293 pystring_fromstring
(Printf.sprintf
"%d" line_end
),
294 pystring_fromstring
(Printf.sprintf
"%d" col_end
)))) l
in
295 let pylocs = pytuple_fromarray
(Array.of_list
locs) in
296 let _ = build_variable py
pylocs in
298 | Some
(_,binding
) ->
299 let _ = build_variable py
(pystring_fromstring
(Pycocci_aux.stringrep binding
))
305 let set_coccifile cocci_file
=
306 cocci_file_name := cocci_file
;
309 let pyrun_simplestring s
=
310 Pycaml.pyrun_simplestring s
312 let py_isinitialized () =
313 Pycaml.py_isinitialized ()
317 Pycaml.py_finalize ()