Release coccinelle-0.2.4
[bpt/coccinelle.git] / python / yes_pycocci.ml
CommitLineData
9bc82bae
C
1(*
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.
7 *
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.
11 *
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.
16 *
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/>.
19 *
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
22 *)
23
24
25(*
26 * Copyright 2010, INRIA, University of Copenhagen
27 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
28 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
29 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
30 * This file is part of Coccinelle.
31 *
32 * Coccinelle is free software: you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License as published by
34 * the Free Software Foundation, according to version 2 of the License.
35 *
36 * Coccinelle is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU General Public License for more details.
40 *
41 * You should have received a copy of the GNU General Public License
42 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
43 *
44 * The authors reserve the right to distribute this or future versions of
45 * Coccinelle under other licenses.
46 *)
47
48
c491d8ee
C
49(*
50 * Copyright 2010, INRIA, University of Copenhagen
51 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
52 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
53 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
54 * This file is part of Coccinelle.
55 *
56 * Coccinelle is free software: you can redistribute it and/or modify
57 * it under the terms of the GNU General Public License as published by
58 * the Free Software Foundation, according to version 2 of the License.
59 *
60 * Coccinelle is distributed in the hope that it will be useful,
61 * but WITHOUT ANY WARRANTY; without even the implied warranty of
62 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63 * GNU General Public License for more details.
64 *
65 * You should have received a copy of the GNU General Public License
66 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
67 *
68 * The authors reserve the right to distribute this or future versions of
69 * Coccinelle under other licenses.
70 *)
71
72
34e49164
C
73open Ast_c
74open Common
75open Pycaml
76open Pycocci_aux
77module StringMap = Map.Make (String)
78
79exception Pycocciexception
80
7f004419
C
81let python_support = true
82
fc1ad971
C
83(* ------------------------------------------------------------------- *)
84(* The following definitions are from
85http://patches.ubuntu.com/by-release/extracted/debian/c/coccinelle/0.1.5dbs-2/01-system-pycaml
86as well as _pycocci_setargs *)
87
88let _pycocci_none () =
89 let builtins = pyeval_getbuiltins () in
90 pyobject_getitem (builtins, pystring_fromstring "None")
91
92let _pycocci_true () =
93 let builtins = pyeval_getbuiltins () in
94 pyobject_getitem (builtins, pystring_fromstring "True")
95
96let _pycocci_false () =
97 let builtins = pyeval_getbuiltins () in
98 pyobject_getitem (builtins, pystring_fromstring "False")
99
100let _pycocci_tuple6 (a,b,c,d,e,f) =
101 pytuple_fromarray ([|a; b; c; d; e; f|])
102
103(* ------------------------------------------------------------------- *)
104
34e49164 105let check_return_value v =
ae4735db 106 if v =*= (pynull ()) then
34e49164
C
107 (pyerr_print ();
108 raise Pycocciexception)
109 else ()
110let check_int_return_value v =
b1b2de81 111 if v =|= -1 then
34e49164
C
112 (pyerr_print ();
113 raise Pycocciexception)
114 else ()
115
116let initialised = ref false
117
fc1ad971 118let coccinelle_module = ref (_pycocci_none ())
34e49164
C
119let cocci_file_name = ref ""
120
121(* dealing with python modules loaded *)
fc1ad971 122let module_map = ref (StringMap.add "__main__" (_pycocci_none ()) StringMap.empty)
34e49164
C
123
124let get_module module_name =
125 StringMap.find module_name (!module_map)
126
127let is_module_loaded module_name =
128 try
129 let _ = get_module module_name in
130 true
131 with Not_found -> false
132
133let load_module module_name =
134 if not (is_module_loaded module_name) then
135 let m = pyimport_importmodule module_name in
136 check_return_value m;
137 (module_map := (StringMap.add module_name m (!module_map));
138 m)
139 else get_module module_name
140(* end python module handling part *)
141
34e49164
C
142(* python interaction *)
143let split_fqn fqn =
144 let last_period = String.rindex fqn '.' in
145 let module_name = String.sub fqn 0 last_period in
146 let class_name = String.sub fqn (last_period + 1) (String.length fqn - last_period - 1) in
147 (module_name, class_name)
148
149let pycocci_get_class_type fqn =
150 let (module_name, class_name) = split_fqn fqn in
151 let m = get_module module_name in
152 let attr = pyobject_getattrstring(m, class_name) in
153 check_return_value attr;
154 attr
155
156let pycocci_instantiate_class fqn args =
157 let class_type = pycocci_get_class_type fqn in
413ffc02
C
158 let obj =
159 pyeval_callobjectwithkeywords(class_type, args, pynull()) in
34e49164
C
160 check_return_value obj;
161 obj
162
163(* end python interaction *)
164
165let inc_match = ref true
166
167let include_match v =
168 let truth = pyobject_istrue (pytuple_getitem (v, 1)) in
169 check_int_return_value truth;
170 inc_match := truth != 0;
fc1ad971 171 _pycocci_none ()
34e49164
C
172
173let build_method (mname, camlfunc, args) pymodule classx classdict =
174 let cmx = pymethod_new(pywrap_closure camlfunc, args, classx) in
175 let v = pydict_setitemstring(classdict, mname, cmx) in
176 check_int_return_value v;
177 ()
178
179let build_class cname parent methods pymodule =
180 let cd = pydict_new() in
181 check_return_value cd;
fc1ad971
C
182 let cx = pyclass_new(pytuple_fromsingle (pycocci_get_class_type parent), cd,
183 pystring_fromstring cname) in
34e49164
C
184 check_return_value cx;
185 List.iter (function meth -> build_method meth pymodule cx cd) methods;
186 let v = pydict_setitemstring(pymodule_getdict pymodule, cname, cx) in
187 check_int_return_value v;
188 (cd, cx)
189
fc1ad971
C
190let the_environment = ref []
191
192let has_environment_binding name =
34e49164
C
193 let a = pytuple_toarray name in
194 let (rule, name) = (Array.get a 1, Array.get a 2) in
195 let orule = pystring_asstring rule in
196 let oname = pystring_asstring name in
ae4735db 197 let e = List.exists (function (x,y) -> orule =*= x && oname =$= y)
fc1ad971
C
198 !the_environment in
199 if e then _pycocci_true () else _pycocci_false ()
34e49164 200
fc1ad971
C
201let pyoutputinstance = ref (_pycocci_none ())
202let pyoutputdict = ref (_pycocci_none ())
34e49164
C
203
204let get_cocci_file args =
fc1ad971
C
205 pystring_fromstring (!cocci_file_name)
206
207(* initialisation routines *)
208let _pycocci_setargs argv0 =
209 let argv =
210 pysequence_list (pytuple_fromsingle (pystring_fromstring argv0)) in
211 let sys_mod = load_module "sys" in
212 pyobject_setattrstring (sys_mod, "argv", argv)
213
214let pycocci_init () =
215 (* initialize *)
216 if not !initialised then (
217 initialised := true;
218 Unix.putenv "PYTHONPATH"
219 (Printf.sprintf "%s/coccinelle" (Unix.getenv "HOME"));
ae4735db
C
220 let _ = if not (py_isinitialized () != 0) then
221 (if !Flag.show_misc then Common.pr2 "Initializing python\n%!";
fc1ad971
C
222 py_initialize()) in
223
224 (* set argv *)
225 let argv0 = Printf.sprintf "%s%sspatch" (Sys.getcwd ()) (match Sys.os_type with "Win32" -> "\\" | _ -> "/") in
226 let _ = _pycocci_setargs argv0 in
227
228 coccinelle_module := (pymodule_new "coccinelle");
229 module_map := StringMap.add "coccinelle" !coccinelle_module !module_map;
230 let _ = load_module "coccilib.elems" in
231 let _ = load_module "coccilib.output" in
232
233 let module_dictionary = pyimport_getmoduledict() in
234 coccinelle_module := pymodule_new "coccinelle";
235 let mx = !coccinelle_module in
ae4735db 236 let (cd, cx) = build_class "Cocci" (!Flag.pyoutput)
fc1ad971
C
237 [("include_match", include_match, (pynull()));
238 ("has_env_binding", has_environment_binding, (pynull()))] mx in
239 pyoutputinstance := cx;
240 pyoutputdict := cd;
241 let v1 = pydict_setitemstring(module_dictionary, "coccinelle", mx) in
242 check_int_return_value v1;
243 let mypystring = pystring_fromstring !cocci_file_name in
244 let v2 = pydict_setitemstring(cd, "cocci_file", mypystring) in
245 check_int_return_value v2;
246 ()) else
247 ()
248
249(*let _ = pycocci_init ()*)
250(* end initialisation routines *)
251
252let added_variables = ref []
34e49164
C
253
254let build_classes env =
fc1ad971
C
255 let _ = pycocci_init () in
256 inc_match := true;
257 the_environment := env;
258 let mx = !coccinelle_module in
259 let dict = pymodule_getdict mx in
260 List.iter
261 (function
262 "include_match" | "has_env_binding" -> ()
263 | name ->
264 let v = pydict_delitemstring(dict,name) in
265 check_int_return_value v)
266 !added_variables;
267 added_variables := [];
268 ()
34e49164
C
269
270let build_variable name value =
271 let mx = !coccinelle_module in
fc1ad971
C
272 added_variables := name :: !added_variables;
273 check_int_return_value
274 (pydict_setitemstring(pymodule_getdict mx, name, value))
34e49164 275
413ffc02
C
276let get_variable name =
277 let mx = !coccinelle_module in
278 pystring_asstring
279 (pyobject_str(pydict_getitemstring(pymodule_getdict mx, name)))
280
174d1640 281let contains_binding e (_,(r,m),_) =
34e49164 282 try
ae4735db 283 let _ = List.find (function ((re, rm), _) -> r =*= re && m =$= rm) e in
fc1ad971 284 true
34e49164
C
285 with Not_found -> false
286
287let construct_variables mv e =
288 let find_binding (r,m) =
289 try
ae4735db 290 let elem = List.find (function ((re,rm),_) -> r =*= re && m =$= rm) e in
34e49164
C
291 Some elem
292 with Not_found -> None
293 in
294
295 let instantiate_Expression(x) =
296 let str = pystring_fromstring (Pycocci_aux.exprrep x) in
fc1ad971
C
297 pycocci_instantiate_class "coccilib.elems.Expression"
298 (pytuple_fromsingle (str))
34e49164
C
299 in
300
301 let instantiate_Identifier(x) =
302 let str = pystring_fromstring x in
fc1ad971
C
303 pycocci_instantiate_class "coccilib.elems.Identifier"
304 (pytuple_fromsingle (str))
34e49164
C
305 in
306
174d1640 307 List.iter (function (py,(r,m),_) ->
34e49164
C
308 match find_binding (r,m) with
309 None -> ()
5636bb2c 310 | Some (_, Ast_c.MetaExprVal (expr,_)) ->
34e49164
C
311 let expr_repr = instantiate_Expression(expr) in
312 let _ = build_variable py expr_repr in
313 ()
5636bb2c 314 | Some (_, Ast_c.MetaIdVal (id,_)) ->
34e49164
C
315 let id_repr = instantiate_Identifier(id) in
316 let _ = build_variable py id_repr in
317 ()
318 | Some (_, Ast_c.MetaPosValList l) ->
485bce71
C
319 let locs =
320 List.map
321 (function (fname,current_element,(line,col),(line_end,col_end)) ->
fc1ad971
C
322 pycocci_instantiate_class "coccilib.elems.Location"
323 (_pycocci_tuple6
485bce71 324 (pystring_fromstring fname,pystring_fromstring current_element,
34e49164
C
325 pystring_fromstring (Printf.sprintf "%d" line),
326 pystring_fromstring (Printf.sprintf "%d" col),
327 pystring_fromstring (Printf.sprintf "%d" line_end),
328 pystring_fromstring (Printf.sprintf "%d" col_end)))) l in
329 let pylocs = pytuple_fromarray (Array.of_list locs) in
330 let _ = build_variable py pylocs in
331 ()
332 | Some (_,binding) ->
413ffc02
C
333 let _ =
334 build_variable py
335 (pystring_fromstring (Pycocci_aux.stringrep binding)) in
336 ()
34e49164
C
337 ) mv;
338
339 ()
340
413ffc02
C
341let construct_script_variables mv =
342 List.iter
343 (function (_,py) ->
344 let vl =
345 let str = pystring_fromstring "initial value" in
346 pycocci_instantiate_class "coccilib.elems.Identifier"
347 (pytuple_fromsingle (str)) in
348 let _ = build_variable py vl in
349 ())
350 mv
351
352let retrieve_script_variables mv =
353 List.map (function (_,py) -> get_variable py) mv
354
34e49164
C
355let set_coccifile cocci_file =
356 cocci_file_name := cocci_file;
357 ()
358
ae4735db 359let pyrun_simplestring s =
90aeb998
C
360 let res = Pycaml.pyrun_simplestring s in
361 check_int_return_value res;
362 res
34e49164 363
ae4735db 364let py_isinitialized () =
34e49164
C
365 Pycaml.py_isinitialized ()
366
367
368let py_finalize () =
369 Pycaml.py_finalize ()