2 * Copyright 2010, INRIA, University of Copenhagen
3 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
4 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
5 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
6 * This file is part of Coccinelle.
8 * Coccinelle is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, according to version 2 of the License.
12 * Coccinelle is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
29 module StringMap
= Map.Make
(String
)
31 exception Pycocciexception
33 let python_support = true
35 (* ------------------------------------------------------------------- *)
36 (* The following definitions are from
37 http://patches.ubuntu.com/by-release/extracted/debian/c/coccinelle/0.1.5dbs-2/01-system-pycaml
38 as well as _pycocci_setargs *)
40 let _pycocci_none () =
41 let builtins = pyeval_getbuiltins
() in
42 pyobject_getitem
(builtins, pystring_fromstring
"None")
44 let _pycocci_true () =
45 let builtins = pyeval_getbuiltins
() in
46 pyobject_getitem
(builtins, pystring_fromstring
"True")
48 let _pycocci_false () =
49 let builtins = pyeval_getbuiltins
() in
50 pyobject_getitem
(builtins, pystring_fromstring
"False")
52 let _pycocci_tuple6 (a
,b
,c
,d
,e
,f
) =
53 pytuple_fromarray
([|a
; b
; c
; d
; e
; f
|])
55 (* ------------------------------------------------------------------- *)
57 let check_return_value v
=
58 if v
=*= (pynull
()) then
60 raise Pycocciexception
)
62 let check_int_return_value v
=
65 raise Pycocciexception
)
68 let initialised = ref false
70 let coccinelle_module = ref (_pycocci_none ())
71 let cocci_file_name = ref ""
73 (* dealing with python modules loaded *)
74 let module_map = ref (StringMap.add
"__main__" (_pycocci_none ()) StringMap.empty
)
76 let get_module module_name
=
77 StringMap.find module_name
(!module_map)
79 let is_module_loaded module_name
=
81 let _ = get_module module_name
in
83 with Not_found
-> false
85 let load_module module_name
=
86 if not
(is_module_loaded module_name
) then
87 let m = pyimport_importmodule module_name
in
89 (module_map := (StringMap.add module_name
m (!module_map));
91 else get_module module_name
92 (* end python module handling part *)
94 (* python interaction *)
96 let last_period = String.rindex fqn '
.'
in
97 let module_name = String.sub fqn
0 last_period in
98 let class_name = String.sub fqn
(last_period + 1) (String.length fqn
- last_period - 1) in
99 (module_name, class_name)
101 let pycocci_get_class_type fqn
=
102 let (module_name, class_name) = split_fqn fqn
in
103 let m = get_module module_name in
104 let attr = pyobject_getattrstring
(m, class_name) in
105 check_return_value attr;
108 let pycocci_instantiate_class fqn args
=
109 let class_type = pycocci_get_class_type fqn
in
111 pyeval_callobjectwithkeywords
(class_type, args
, pynull
()) in
112 check_return_value obj;
115 (* end python interaction *)
117 let inc_match = ref true
119 let include_match v
=
120 let truth = pyobject_istrue
(pytuple_getitem
(v
, 1)) in
121 check_int_return_value truth;
122 inc_match := truth != 0;
125 let build_method (mname
, camlfunc
, args
) pymodule classx classdict
=
126 let cmx = pymethod_new
(pywrap_closure camlfunc
, args
, classx
) in
127 let v = pydict_setitemstring
(classdict
, mname
, cmx) in
128 check_int_return_value v;
131 let build_class cname parent methods pymodule
=
132 let cd = pydict_new
() in
133 check_return_value cd;
134 let cx = pyclass_new
(pytuple_fromsingle
(pycocci_get_class_type parent
), cd,
135 pystring_fromstring cname
) in
136 check_return_value cx;
137 List.iter
(function meth
-> build_method meth pymodule
cx cd) methods
;
138 let v = pydict_setitemstring
(pymodule_getdict pymodule
, cname
, cx) in
139 check_int_return_value v;
142 let the_environment = ref []
144 let has_environment_binding name
=
145 let a = pytuple_toarray name
in
146 let (rule
, name
) = (Array.get
a 1, Array.get
a 2) in
147 let orule = pystring_asstring rule
in
148 let oname = pystring_asstring name
in
149 let e = List.exists
(function (x
,y
) -> orule =*= x
&& oname =$
= y
)
151 if e then _pycocci_true () else _pycocci_false ()
153 let pyoutputinstance = ref (_pycocci_none ())
154 let pyoutputdict = ref (_pycocci_none ())
156 let get_cocci_file args
=
157 pystring_fromstring
(!cocci_file_name)
159 (* initialisation routines *)
160 let _pycocci_setargs argv0
=
162 pysequence_list
(pytuple_fromsingle
(pystring_fromstring argv0
)) in
163 let sys_mod = load_module "sys" in
164 pyobject_setattrstring
(sys_mod, "argv", argv)
166 let pycocci_init () =
168 if not
!initialised then (
170 Unix.putenv
"PYTHONPATH"
171 (Printf.sprintf
"%s/coccinelle" (Unix.getenv
"HOME"));
172 let _ = if not
(py_isinitialized
() != 0) then
173 (if !Flag.show_misc
then Common.pr2
"Initializing python\n%!";
177 let argv0 = Printf.sprintf
"%s%sspatch" (Sys.getcwd
()) (match Sys.os_type
with "Win32" -> "\\" | _ -> "/") in
178 let _ = _pycocci_setargs argv0 in
180 coccinelle_module := (pymodule_new
"coccinelle");
181 module_map := StringMap.add
"coccinelle" !coccinelle_module !module_map;
182 let _ = load_module "coccilib.elems" in
183 let _ = load_module "coccilib.output" in
185 let module_dictionary = pyimport_getmoduledict
() in
186 coccinelle_module := pymodule_new
"coccinelle";
187 let mx = !coccinelle_module in
188 let (cd, cx) = build_class "Cocci" (!Flag.pyoutput
)
189 [("include_match", include_match, (pynull
()));
190 ("has_env_binding", has_environment_binding, (pynull
()))] mx in
191 pyoutputinstance := cx;
193 let v1 = pydict_setitemstring
(module_dictionary, "coccinelle", mx) in
194 check_int_return_value v1;
195 let mypystring = pystring_fromstring
!cocci_file_name in
196 let v2 = pydict_setitemstring
(cd, "cocci_file", mypystring) in
197 check_int_return_value v2;
201 (*let _ = pycocci_init ()*)
202 (* end initialisation routines *)
204 let added_variables = ref []
206 let build_classes env
=
207 let _ = pycocci_init () in
209 the_environment := env
;
210 let mx = !coccinelle_module in
211 let dict = pymodule_getdict
mx in
214 "include_match" | "has_env_binding" -> ()
216 let v = pydict_delitemstring
(dict,name
) in
217 check_int_return_value v)
219 added_variables := [];
222 let build_variable name
value =
223 let mx = !coccinelle_module in
224 added_variables := name
:: !added_variables;
225 check_int_return_value
226 (pydict_setitemstring
(pymodule_getdict
mx, name
, value))
228 let get_variable name
=
229 let mx = !coccinelle_module in
231 (pyobject_str
(pydict_getitemstring
(pymodule_getdict
mx, name
)))
233 let contains_binding e (_,(r
,m),_) =
235 let _ = List.find
(function ((re
, rm
), _) -> r
=*= re
&& m =$
= rm
) e in
237 with Not_found
-> false
239 let construct_variables mv
e =
240 let find_binding (r
,m) =
242 let elem = List.find
(function ((re
,rm
),_) -> r
=*= re
&& m =$
= rm
) e in
244 with Not_found
-> None
247 let instantiate_Expression(x
) =
248 let str = pystring_fromstring
(Pycocci_aux.exprrep x
) in
249 pycocci_instantiate_class "coccilib.elems.Expression"
250 (pytuple_fromsingle
(str))
253 let instantiate_Identifier(x
) =
254 let str = pystring_fromstring x
in
255 pycocci_instantiate_class "coccilib.elems.Identifier"
256 (pytuple_fromsingle
(str))
259 List.iter
(function (py
,(r
,m),_) ->
260 match find_binding (r
,m) with
262 | Some
(_, Ast_c.MetaExprVal
(expr
,_)) ->
263 let expr_repr = instantiate_Expression(expr
) in
264 let _ = build_variable py
expr_repr in
266 | Some
(_, Ast_c.MetaIdVal
(id
,_)) ->
267 let id_repr = instantiate_Identifier(id
) in
268 let _ = build_variable py
id_repr in
270 | Some
(_, Ast_c.MetaPosValList l
) ->
273 (function (fname
,current_element
,(line
,col
),(line_end
,col_end
)) ->
274 pycocci_instantiate_class "coccilib.elems.Location"
276 (pystring_fromstring fname
,pystring_fromstring current_element
,
277 pystring_fromstring
(Printf.sprintf
"%d" line
),
278 pystring_fromstring
(Printf.sprintf
"%d" col
),
279 pystring_fromstring
(Printf.sprintf
"%d" line_end
),
280 pystring_fromstring
(Printf.sprintf
"%d" col_end
)))) l
in
281 let pylocs = pytuple_fromarray
(Array.of_list
locs) in
282 let _ = build_variable py
pylocs in
284 | Some
(_,binding
) ->
287 (pystring_fromstring
(Pycocci_aux.stringrep binding
)) in
293 let construct_script_variables mv
=
297 let str = pystring_fromstring
"initial value" in
298 pycocci_instantiate_class "coccilib.elems.Identifier"
299 (pytuple_fromsingle
(str)) in
300 let _ = build_variable py
vl in
304 let retrieve_script_variables mv
=
305 List.map
(function (_,py
) -> get_variable py
) mv
307 let set_coccifile cocci_file
=
308 cocci_file_name := cocci_file
;
311 let pyrun_simplestring s
=
312 let res = Pycaml.pyrun_simplestring s
in
313 check_int_return_value res;
316 let py_isinitialized () =
317 Pycaml.py_isinitialized ()
321 Pycaml.py_finalize ()