Release coccinelle-0.2.3rc1
[bpt/coccinelle.git] / python / yes_pycocci.ml
CommitLineData
9f8e26f4 1(*
ae4735db 2 * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
9f8e26f4
C
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
5636bb2c
C
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
34e49164
C
45open Ast_c
46open Common
47open Pycaml
48open Pycocci_aux
49module StringMap = Map.Make (String)
50
51exception Pycocciexception
52
7f004419
C
53let python_support = true
54
fc1ad971
C
55(* ------------------------------------------------------------------- *)
56(* The following definitions are from
57http://patches.ubuntu.com/by-release/extracted/debian/c/coccinelle/0.1.5dbs-2/01-system-pycaml
58as well as _pycocci_setargs *)
59
60let _pycocci_none () =
61 let builtins = pyeval_getbuiltins () in
62 pyobject_getitem (builtins, pystring_fromstring "None")
63
64let _pycocci_true () =
65 let builtins = pyeval_getbuiltins () in
66 pyobject_getitem (builtins, pystring_fromstring "True")
67
68let _pycocci_false () =
69 let builtins = pyeval_getbuiltins () in
70 pyobject_getitem (builtins, pystring_fromstring "False")
71
72let _pycocci_tuple6 (a,b,c,d,e,f) =
73 pytuple_fromarray ([|a; b; c; d; e; f|])
74
75(* ------------------------------------------------------------------- *)
76
34e49164 77let check_return_value v =
ae4735db 78 if v =*= (pynull ()) then
34e49164
C
79 (pyerr_print ();
80 raise Pycocciexception)
81 else ()
82let check_int_return_value v =
b1b2de81 83 if v =|= -1 then
34e49164
C
84 (pyerr_print ();
85 raise Pycocciexception)
86 else ()
87
88let initialised = ref false
89
fc1ad971 90let coccinelle_module = ref (_pycocci_none ())
34e49164
C
91let cocci_file_name = ref ""
92
93(* dealing with python modules loaded *)
fc1ad971 94let module_map = ref (StringMap.add "__main__" (_pycocci_none ()) StringMap.empty)
34e49164
C
95
96let get_module module_name =
97 StringMap.find module_name (!module_map)
98
99let is_module_loaded module_name =
100 try
101 let _ = get_module module_name in
102 true
103 with Not_found -> false
104
105let 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
34e49164
C
114(* python interaction *)
115let 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
121let 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
128let 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
136let inc_match = ref true
137
138let include_match v =
139 let truth = pyobject_istrue (pytuple_getitem (v, 1)) in
140 check_int_return_value truth;
141 inc_match := truth != 0;
fc1ad971 142 _pycocci_none ()
34e49164
C
143
144let 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
150let build_class cname parent methods pymodule =
151 let cd = pydict_new() in
152 check_return_value cd;
fc1ad971
C
153 let cx = pyclass_new(pytuple_fromsingle (pycocci_get_class_type parent), cd,
154 pystring_fromstring cname) in
34e49164
C
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
fc1ad971
C
161let the_environment = ref []
162
163let has_environment_binding name =
34e49164
C
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
ae4735db 168 let e = List.exists (function (x,y) -> orule =*= x && oname =$= y)
fc1ad971
C
169 !the_environment in
170 if e then _pycocci_true () else _pycocci_false ()
34e49164 171
fc1ad971
C
172let pyoutputinstance = ref (_pycocci_none ())
173let pyoutputdict = ref (_pycocci_none ())
34e49164
C
174
175let get_cocci_file args =
fc1ad971
C
176 pystring_fromstring (!cocci_file_name)
177
178(* initialisation routines *)
179let _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
185let pycocci_init () =
186 (* initialize *)
187 if not !initialised then (
188 initialised := true;
189 Unix.putenv "PYTHONPATH"
190 (Printf.sprintf "%s/coccinelle" (Unix.getenv "HOME"));
ae4735db
C
191 let _ = if not (py_isinitialized () != 0) then
192 (if !Flag.show_misc then Common.pr2 "Initializing python\n%!";
fc1ad971
C
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
ae4735db 207 let (cd, cx) = build_class "Cocci" (!Flag.pyoutput)
fc1ad971
C
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
223let added_variables = ref []
34e49164
C
224
225let build_classes env =
fc1ad971
C
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 ()
34e49164
C
240
241let build_variable name value =
242 let mx = !coccinelle_module in
fc1ad971
C
243 added_variables := name :: !added_variables;
244 check_int_return_value
245 (pydict_setitemstring(pymodule_getdict mx, name, value))
34e49164
C
246
247let contains_binding e (_,(r,m)) =
248 try
ae4735db 249 let _ = List.find (function ((re, rm), _) -> r =*= re && m =$= rm) e in
fc1ad971 250 true
34e49164
C
251 with Not_found -> false
252
253let construct_variables mv e =
254 let find_binding (r,m) =
255 try
ae4735db 256 let elem = List.find (function ((re,rm),_) -> r =*= re && m =$= rm) e in
34e49164
C
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
fc1ad971
C
263 pycocci_instantiate_class "coccilib.elems.Expression"
264 (pytuple_fromsingle (str))
34e49164
C
265 in
266
267 let instantiate_Identifier(x) =
268 let str = pystring_fromstring x in
fc1ad971
C
269 pycocci_instantiate_class "coccilib.elems.Identifier"
270 (pytuple_fromsingle (str))
34e49164
C
271 in
272
273 List.iter (function (py,(r,m)) ->
274 match find_binding (r,m) with
275 None -> ()
5636bb2c 276 | Some (_, Ast_c.MetaExprVal (expr,_)) ->
34e49164
C
277 let expr_repr = instantiate_Expression(expr) in
278 let _ = build_variable py expr_repr in
279 ()
5636bb2c 280 | Some (_, Ast_c.MetaIdVal (id,_)) ->
34e49164
C
281 let id_repr = instantiate_Identifier(id) in
282 let _ = build_variable py id_repr in
283 ()
284 | Some (_, Ast_c.MetaPosValList l) ->
485bce71
C
285 let locs =
286 List.map
287 (function (fname,current_element,(line,col),(line_end,col_end)) ->
fc1ad971
C
288 pycocci_instantiate_class "coccilib.elems.Location"
289 (_pycocci_tuple6
485bce71 290 (pystring_fromstring fname,pystring_fromstring current_element,
34e49164
C
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
305let set_coccifile cocci_file =
306 cocci_file_name := cocci_file;
307 ()
308
ae4735db 309let pyrun_simplestring s =
34e49164
C
310 Pycaml.pyrun_simplestring s
311
ae4735db 312let py_isinitialized () =
34e49164
C
313 Pycaml.py_isinitialized ()
314
315
316let py_finalize () =
317 Pycaml.py_finalize ()