Release coccinelle-0.2.3rc1
[bpt/coccinelle.git] / python / yes_pycocci.ml
1 (*
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.
5 *
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.
9 *
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.
14 *
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/>.
17 *
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
20 *)
21
22
23 (*
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.
27 *
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.
31 *
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.
36 *
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/>.
39 *
40 * The authors reserve the right to distribute this or future versions of
41 * Coccinelle under other licenses.
42 *)
43
44
45 open Ast_c
46 open Common
47 open Pycaml
48 open Pycocci_aux
49 module StringMap = Map.Make (String)
50
51 exception Pycocciexception
52
53 let python_support = true
54
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 *)
59
60 let _pycocci_none () =
61 let builtins = pyeval_getbuiltins () in
62 pyobject_getitem (builtins, pystring_fromstring "None")
63
64 let _pycocci_true () =
65 let builtins = pyeval_getbuiltins () in
66 pyobject_getitem (builtins, pystring_fromstring "True")
67
68 let _pycocci_false () =
69 let builtins = pyeval_getbuiltins () in
70 pyobject_getitem (builtins, pystring_fromstring "False")
71
72 let _pycocci_tuple6 (a,b,c,d,e,f) =
73 pytuple_fromarray ([|a; b; c; d; e; f|])
74
75 (* ------------------------------------------------------------------- *)
76
77 let check_return_value v =
78 if v =*= (pynull ()) then
79 (pyerr_print ();
80 raise Pycocciexception)
81 else ()
82 let check_int_return_value v =
83 if v =|= -1 then
84 (pyerr_print ();
85 raise Pycocciexception)
86 else ()
87
88 let initialised = ref false
89
90 let coccinelle_module = ref (_pycocci_none ())
91 let cocci_file_name = ref ""
92
93 (* dealing with python modules loaded *)
94 let module_map = ref (StringMap.add "__main__" (_pycocci_none ()) StringMap.empty)
95
96 let get_module module_name =
97 StringMap.find module_name (!module_map)
98
99 let is_module_loaded module_name =
100 try
101 let _ = get_module module_name in
102 true
103 with Not_found -> false
104
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));
110 m)
111 else get_module module_name
112 (* end python module handling part *)
113
114 (* python interaction *)
115 let split_fqn fqn =
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)
120
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;
126 attr
127
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;
132 obj
133
134 (* end python interaction *)
135
136 let inc_match = ref true
137
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;
142 _pycocci_none ()
143
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;
148 ()
149
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;
159 (cd, cx)
160
161 let the_environment = ref []
162
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)
169 !the_environment in
170 if e then _pycocci_true () else _pycocci_false ()
171
172 let pyoutputinstance = ref (_pycocci_none ())
173 let pyoutputdict = ref (_pycocci_none ())
174
175 let get_cocci_file args =
176 pystring_fromstring (!cocci_file_name)
177
178 (* initialisation routines *)
179 let _pycocci_setargs argv0 =
180 let argv =
181 pysequence_list (pytuple_fromsingle (pystring_fromstring argv0)) in
182 let sys_mod = load_module "sys" in
183 pyobject_setattrstring (sys_mod, "argv", argv)
184
185 let pycocci_init () =
186 (* initialize *)
187 if not !initialised then (
188 initialised := true;
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%!";
193 py_initialize()) in
194
195 (* set argv *)
196 let argv0 = Printf.sprintf "%s%sspatch" (Sys.getcwd ()) (match Sys.os_type with "Win32" -> "\\" | _ -> "/") in
197 let _ = _pycocci_setargs argv0 in
198
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
203
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;
211 pyoutputdict := cd;
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;
217 ()) else
218 ()
219
220 (*let _ = pycocci_init ()*)
221 (* end initialisation routines *)
222
223 let added_variables = ref []
224
225 let build_classes env =
226 let _ = pycocci_init () in
227 inc_match := true;
228 the_environment := env;
229 let mx = !coccinelle_module in
230 let dict = pymodule_getdict mx in
231 List.iter
232 (function
233 "include_match" | "has_env_binding" -> ()
234 | name ->
235 let v = pydict_delitemstring(dict,name) in
236 check_int_return_value v)
237 !added_variables;
238 added_variables := [];
239 ()
240
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))
246
247 let contains_binding e (_,(r,m)) =
248 try
249 let _ = List.find (function ((re, rm), _) -> r =*= re && m =$= rm) e in
250 true
251 with Not_found -> false
252
253 let construct_variables mv e =
254 let find_binding (r,m) =
255 try
256 let elem = List.find (function ((re,rm),_) -> r =*= re && m =$= rm) e in
257 Some elem
258 with Not_found -> None
259 in
260
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))
265 in
266
267 let instantiate_Identifier(x) =
268 let str = pystring_fromstring x in
269 pycocci_instantiate_class "coccilib.elems.Identifier"
270 (pytuple_fromsingle (str))
271 in
272
273 List.iter (function (py,(r,m)) ->
274 match find_binding (r,m) with
275 None -> ()
276 | Some (_, Ast_c.MetaExprVal (expr,_)) ->
277 let expr_repr = instantiate_Expression(expr) in
278 let _ = build_variable py expr_repr in
279 ()
280 | Some (_, Ast_c.MetaIdVal (id,_)) ->
281 let id_repr = instantiate_Identifier(id) in
282 let _ = build_variable py id_repr in
283 ()
284 | Some (_, Ast_c.MetaPosValList l) ->
285 let locs =
286 List.map
287 (function (fname,current_element,(line,col),(line_end,col_end)) ->
288 pycocci_instantiate_class "coccilib.elems.Location"
289 (_pycocci_tuple6
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
297 ()
298 | Some (_,binding) ->
299 let _ = build_variable py (pystring_fromstring (Pycocci_aux.stringrep binding))
300 in ()
301 ) mv;
302
303 ()
304
305 let set_coccifile cocci_file =
306 cocci_file_name := cocci_file;
307 ()
308
309 let pyrun_simplestring s =
310 Pycaml.pyrun_simplestring s
311
312 let py_isinitialized () =
313 Pycaml.py_isinitialized ()
314
315
316 let py_finalize () =
317 Pycaml.py_finalize ()