2 * Copyright 2012, INRIA
3 * Julia Lawall, Gilles Muller
4 * Copyright 2010-2011, INRIA, University of Copenhagen
5 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
6 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
7 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
8 * This file is part of Coccinelle.
10 * Coccinelle is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, according to version 2 of the License.
14 * Coccinelle is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
22 * The authors reserve the right to distribute this or future versions of
23 * Coccinelle under other licenses.
27 #
0 "./yes_pycocci.ml"
32 module StringMap
= Map.Make
(String
)
34 exception Pycocciexception
36 let python_support = true
38 (* ------------------------------------------------------------------- *)
39 (* The following definitions are from
40 http://patches.ubuntu.com/by-release/extracted/debian/c/coccinelle/0.1.5dbs-2/01-system-pycaml
41 as well as _pycocci_setargs *)
43 let _pycocci_none () =
44 let builtins = pyeval_getbuiltins
() in
45 pyobject_getitem
(builtins, pystring_fromstring
"None")
47 let _pycocci_true () =
48 let builtins = pyeval_getbuiltins
() in
49 pyobject_getitem
(builtins, pystring_fromstring
"True")
51 let _pycocci_false () =
52 let builtins = pyeval_getbuiltins
() in
53 pyobject_getitem
(builtins, pystring_fromstring
"False")
55 let _pycocci_tuple6 (a
,b
,c
,d
,e
,f
) =
56 pytuple_fromarray
([|a
; b
; c
; d
; e
; f
|])
58 (* ------------------------------------------------------------------- *)
60 let check_return_value msg v
=
61 if v
=*= (pynull
()) then
63 Common.pr2
("while " ^ msg ^
":");
64 raise Pycocciexception
)
66 let check_int_return_value msg v
=
69 Common.pr2
("while " ^ msg ^
":");
70 raise Pycocciexception
)
73 let initialised = ref false
75 let coccinelle_module = ref (_pycocci_none ())
76 let cocci_file_name = ref ""
78 (* dealing with python modules loaded *)
79 let module_map = ref (StringMap.add
"__main__" (_pycocci_none ()) StringMap.empty
)
81 let get_module module_name
=
82 StringMap.find module_name
(!module_map)
84 let is_module_loaded module_name
=
86 let _ = get_module module_name
in
88 with Not_found
-> false
90 let load_module module_name
=
91 if not
(is_module_loaded module_name
) then
92 (* let _ = Sys.command("python3 -c 'import " ^ module_name ^ "'") in *)
93 let m = pyimport_importmodule module_name
in
94 check_return_value ("importing module " ^ module_name
) m;
95 (module_map := (StringMap.add module_name
m (!module_map));
97 else get_module module_name
98 (* end python module handling part *)
100 (* python interaction *)
102 let last_period = String.rindex fqn '
.'
in
103 let module_name = String.sub fqn
0 last_period in
104 let class_name = String.sub fqn
(last_period + 1) (String.length fqn
- last_period - 1) in
105 (module_name, class_name)
107 let pycocci_get_class_type fqn
=
108 let (module_name, class_name) = split_fqn fqn
in
109 let m = get_module module_name in
110 let attr = pyobject_getattrstring
(m, class_name) in
111 check_return_value "obtaining a python class type" attr;
114 let pycocci_instantiate_class fqn args
=
115 let class_type = pycocci_get_class_type fqn
in
117 pyeval_callobjectwithkeywords
(class_type, args
, pynull
()) in
118 check_return_value "instantiating a python class" obj;
121 (* end python interaction *)
123 let inc_match = ref true
124 let exited = ref false
126 let include_match v
=
127 let truth = pyobject_istrue
(pytuple_getitem
(v
, 1)) in
128 check_int_return_value "testing include_match" truth;
129 inc_match := truth != 0;
136 let build_method (mname
, camlfunc
, args
) pymodule classx classdict
=
137 let cmx = pymethod_new
(pywrap_closure camlfunc
, args
, classx
) in
138 let v = pydict_setitemstring
(classdict
, mname
, cmx) in
139 check_int_return_value ("building python method " ^ mname
) v;
142 let build_class cname parent methods pymodule
=
143 let cd = pydict_new
() in
144 check_return_value "creating a new python dictionary" cd;
145 let cx = pyclass_new
(pytuple_fromsingle
(pycocci_get_class_type parent
), cd,
146 pystring_fromstring cname
) in
147 check_return_value "creating a new python class" cx;
148 List.iter
(function meth
-> build_method meth pymodule
cx cd) methods
;
149 let v = pydict_setitemstring
(pymodule_getdict pymodule
, cname
, cx) in
150 check_int_return_value ("adding python class " ^ cname
) v;
153 let the_environment = ref []
155 let has_environment_binding name
=
156 let a = pytuple_toarray name
in
157 let (rule
, name
) = (Array.get
a 1, Array.get
a 2) in
158 let orule = pystring_asstring rule
in
159 let oname = pystring_asstring name
in
160 let e = List.exists
(function (x
,y
) -> orule =*= x
&& oname =$
= y
)
162 if e then _pycocci_true () else _pycocci_false ()
164 let pyoutputinstance = ref (_pycocci_none ())
165 let pyoutputdict = ref (_pycocci_none ())
167 let get_cocci_file args
=
168 pystring_fromstring
(!cocci_file_name)
170 (* initialisation routines *)
171 let _pycocci_setargs argv0
=
173 pysequence_list
(pytuple_fromsingle
(pystring_fromstring argv0
)) in
174 let sys_mod = load_module "sys" in
175 pyobject_setattrstring
(sys_mod, "argv", argv)
177 let pycocci_init () =
179 if not
!initialised then (
181 (* use python_path_base as default (overridable) dir for coccilib *)
182 let python_path_base = Printf.sprintf
"%s/coccinelle" (Unix.getenv
"HOME") in
183 let python_path = try Unix.getenv
"PYTHONPATH" ^
":" ^
python_path_base
184 with Not_found
-> python_path_base in
185 Unix.putenv
"PYTHONPATH" python_path;
186 let _ = if not
(py_isinitialized
() != 0) then
187 (if !Flag.show_misc
then Common.pr2
"Initializing python\n%!";
191 let argv0 = Sys.executable_name
in
192 let _ = _pycocci_setargs argv0 in
194 coccinelle_module := (pymodule_new
"coccinelle");
195 module_map := StringMap.add
"coccinelle" !coccinelle_module !module_map;
196 let _ = load_module "coccilib.elems" in
197 let _ = load_module "coccilib.output" in
199 let module_dictionary = pyimport_getmoduledict
() in
200 coccinelle_module := pymodule_new
"coccinelle";
201 let mx = !coccinelle_module in
202 let (cd, cx) = build_class "Cocci" (!Flag.pyoutput
)
203 [("exit", sp_exit, (pynull
()));
204 ("include_match", include_match, (pynull
()));
205 ("has_env_binding", has_environment_binding, (pynull
()))] mx in
206 pyoutputinstance := cx;
208 let v1 = pydict_setitemstring
(module_dictionary, "coccinelle", mx) in
209 check_int_return_value "adding coccinelle python module" v1;
210 let mypystring = pystring_fromstring
!cocci_file_name in
211 let v2 = pydict_setitemstring
(cd, "cocci_file", mypystring) in
212 check_int_return_value "adding python field cocci_file" v2;
216 (*let _ = pycocci_init ()*)
217 (* end initialisation routines *)
219 let added_variables = ref []
221 let build_classes env
=
222 let _ = pycocci_init () in
225 the_environment := env
;
226 let mx = !coccinelle_module in
227 let dict = pymodule_getdict
mx in
230 "include_match" | "has_env_binding" | "exit" -> ()
232 let v = pydict_delitemstring
(dict,name
) in
233 check_int_return_value ("removing " ^ name ^
" from python coccinelle module") v)
235 added_variables := [];
238 let build_variable name
value =
239 let mx = !coccinelle_module in
240 added_variables := name
:: !added_variables;
241 check_int_return_value ("build python variable " ^ name
)
242 (pydict_setitemstring
(pymodule_getdict
mx, name
, value))
244 let get_variable name
=
245 let mx = !coccinelle_module in
247 (pyobject_str
(pydict_getitemstring
(pymodule_getdict
mx, name
)))
249 let contains_binding e (_,(r
,m),_) =
251 let _ = List.find
(function ((re
, rm
), _) -> r
=*= re
&& m =$
= rm
) e in
253 with Not_found
-> false
255 let construct_variables mv
e =
256 let find_binding (r
,m) =
258 let elem = List.find
(function ((re
,rm
),_) -> r
=*= re
&& m =$
= rm
) e in
260 with Not_found
-> None
263 (* Only string in this representation, so no point
264 let instantiate_Expression(x) =
265 let str = pystring_fromstring (Pycocci_aux.exprrep x) in
266 pycocci_instantiate_class "coccilib.elems.Expression"
267 (pytuple_fromsingle (str))
271 (* Only string in this representation, so no point
272 let instantiate_Identifier(x) =
273 let str = pystring_fromstring x in
274 pycocci_instantiate_class "coccilib.elems.Identifier"
275 (pytuple_fromsingle (str))
279 let instantiate_term_list py printer lst
=
280 let (str,elements
) = printer lst
in
281 let str = pystring_fromstring
str in
284 (Array.of_list
(List.map pystring_fromstring
elements)) in
286 pycocci_instantiate_class "coccilib.elems.TermList"
287 (pytuple_fromarray
(Array.of_list
[str;elements])) in
288 let _ = build_variable py
repr in () in
290 List.iter
(function (py
,(r
,m),_) ->
291 match find_binding (r
,m) with
293 (* | Some (_, Ast_c.MetaExprVal (expr,_)) ->
294 let expr_repr = instantiate_Expression(expr) in
295 let _ = build_variable py expr_repr in
297 (* | Some (_, Ast_c.MetaIdVal (id,_)) ->
298 let id_repr = instantiate_Identifier(id) in
299 let _ = build_variable py id_repr in
301 | Some
(_, Ast_c.MetaExprListVal
(exprlist
)) ->
302 instantiate_term_list py
Pycocci_aux.exprlistrep exprlist
303 | Some
(_, Ast_c.MetaParamListVal
(paramlist
)) ->
304 instantiate_term_list py
Pycocci_aux.paramlistrep paramlist
305 | Some
(_, Ast_c.MetaInitListVal
(initlist
)) ->
306 instantiate_term_list py
Pycocci_aux.initlistrep initlist
307 | Some
(_, Ast_c.MetaFieldListVal
(fieldlist
)) ->
308 instantiate_term_list py
Pycocci_aux.fieldlistrep fieldlist
309 | Some
(_, Ast_c.MetaPosValList l
) ->
312 (function (fname
,current_element
,(line
,col
),(line_end
,col_end
)) ->
313 pycocci_instantiate_class "coccilib.elems.Location"
315 (pystring_fromstring fname
,pystring_fromstring current_element
,
316 pystring_fromstring
(Printf.sprintf
"%d" line
),
317 pystring_fromstring
(Printf.sprintf
"%d" col
),
318 pystring_fromstring
(Printf.sprintf
"%d" line_end
),
319 pystring_fromstring
(Printf.sprintf
"%d" col_end
)))) l
in
320 let pylocs = pytuple_fromarray
(Array.of_list
locs) in
321 let _ = build_variable py
pylocs in
323 | Some
(_,binding
) ->
326 (pystring_fromstring
(Pycocci_aux.stringrep binding
)) in
332 let construct_script_variables mv
=
337 "initial value: consider using coccinelle.varname" in
338 let _ = build_variable py
str in
342 let retrieve_script_variables mv
=
343 List.map
(function (_,py
) -> get_variable py
) mv
345 let set_coccifile cocci_file
=
346 cocci_file_name := cocci_file
;
349 let pyrun_simplestring s
=
350 let res = Pycaml.pyrun_simplestring s
in
351 check_int_return_value ("running simple python string: " ^ s
) res;
354 let py_isinitialized () =
355 Pycaml.py_isinitialized ()
359 Pycaml.py_finalize ()