f6e272f9d8b8b5fba321c18b11701856dae83332
[bpt/coccinelle.git] / python / yes_pycocci.ml
1 (*
2 * Copyright 2005-2009, 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 open Ast_c
24 open Common
25 open Pycaml
26 open Pycocci_aux
27 module StringMap = Map.Make (String)
28
29 exception Pycocciexception
30
31 (* ------------------------------------------------------------------- *)
32 (* The following definitions are from
33 http://patches.ubuntu.com/by-release/extracted/debian/c/coccinelle/0.1.5dbs-2/01-system-pycaml
34 as well as _pycocci_setargs *)
35
36 let _pycocci_none () =
37 let builtins = pyeval_getbuiltins () in
38 pyobject_getitem (builtins, pystring_fromstring "None")
39
40 let _pycocci_true () =
41 let builtins = pyeval_getbuiltins () in
42 pyobject_getitem (builtins, pystring_fromstring "True")
43
44 let _pycocci_false () =
45 let builtins = pyeval_getbuiltins () in
46 pyobject_getitem (builtins, pystring_fromstring "False")
47
48 let _pycocci_tuple6 (a,b,c,d,e,f) =
49 pytuple_fromarray ([|a; b; c; d; e; f|])
50
51 (* ------------------------------------------------------------------- *)
52
53 let check_return_value v =
54 if v =*= (pynull ()) then
55 (pyerr_print ();
56 raise Pycocciexception)
57 else ()
58 let check_int_return_value v =
59 if v =|= -1 then
60 (pyerr_print ();
61 raise Pycocciexception)
62 else ()
63
64 let initialised = ref false
65
66 let coccinelle_module = ref (_pycocci_none ())
67 let cocci_file_name = ref ""
68
69 (* dealing with python modules loaded *)
70 let module_map = ref (StringMap.add "__main__" (_pycocci_none ()) StringMap.empty)
71
72 let get_module module_name =
73 StringMap.find module_name (!module_map)
74
75 let is_module_loaded module_name =
76 try
77 let _ = get_module module_name in
78 true
79 with Not_found -> false
80
81 let load_module module_name =
82 if not (is_module_loaded module_name) then
83 let m = pyimport_importmodule module_name in
84 check_return_value m;
85 (module_map := (StringMap.add module_name m (!module_map));
86 m)
87 else get_module module_name
88 (* end python module handling part *)
89
90 (* python interaction *)
91 let split_fqn fqn =
92 let last_period = String.rindex fqn '.' in
93 let module_name = String.sub fqn 0 last_period in
94 let class_name = String.sub fqn (last_period + 1) (String.length fqn - last_period - 1) in
95 (module_name, class_name)
96
97 let pycocci_get_class_type fqn =
98 let (module_name, class_name) = split_fqn fqn in
99 let m = get_module module_name in
100 let attr = pyobject_getattrstring(m, class_name) in
101 check_return_value attr;
102 attr
103
104 let pycocci_instantiate_class fqn args =
105 let class_type = pycocci_get_class_type fqn in
106 let obj = pyobject_callobject(class_type, args) in
107 check_return_value obj;
108 obj
109
110 (* end python interaction *)
111
112 let inc_match = ref true
113
114 let include_match v =
115 let truth = pyobject_istrue (pytuple_getitem (v, 1)) in
116 check_int_return_value truth;
117 inc_match := truth != 0;
118 _pycocci_none ()
119
120 let build_method (mname, camlfunc, args) pymodule classx classdict =
121 let cmx = pymethod_new(pywrap_closure camlfunc, args, classx) in
122 let v = pydict_setitemstring(classdict, mname, cmx) in
123 check_int_return_value v;
124 ()
125
126 let build_class cname parent methods pymodule =
127 let cd = pydict_new() in
128 check_return_value cd;
129 let cx = pyclass_new(pytuple_fromsingle (pycocci_get_class_type parent), cd,
130 pystring_fromstring cname) in
131 check_return_value cx;
132 List.iter (function meth -> build_method meth pymodule cx cd) methods;
133 let v = pydict_setitemstring(pymodule_getdict pymodule, cname, cx) in
134 check_int_return_value v;
135 (cd, cx)
136
137 let the_environment = ref []
138
139 let has_environment_binding name =
140 let a = pytuple_toarray name in
141 let (rule, name) = (Array.get a 1, Array.get a 2) in
142 let orule = pystring_asstring rule in
143 let oname = pystring_asstring name in
144 let e = List.exists (function (x,y) -> orule =$= x && oname =$= y)
145 !the_environment in
146 if e then _pycocci_true () else _pycocci_false ()
147
148 let pyoutputinstance = ref (_pycocci_none ())
149 let pyoutputdict = ref (_pycocci_none ())
150
151 let get_cocci_file args =
152 pystring_fromstring (!cocci_file_name)
153
154 (* initialisation routines *)
155 let _pycocci_setargs argv0 =
156 let argv =
157 pysequence_list (pytuple_fromsingle (pystring_fromstring argv0)) in
158 let sys_mod = load_module "sys" in
159 pyobject_setattrstring (sys_mod, "argv", argv)
160
161 let pycocci_init () =
162 (* initialize *)
163 if not !initialised then (
164 initialised := true;
165 Unix.putenv "PYTHONPATH"
166 (Printf.sprintf "%s/coccinelle" (Unix.getenv "HOME"));
167 let _ = if not (py_isinitialized () != 0) then
168 (if !Flag.show_misc then Common.pr2 "Initializing python\n%!";
169 py_initialize()) in
170
171 (* set argv *)
172 let argv0 = Printf.sprintf "%s%sspatch" (Sys.getcwd ()) (match Sys.os_type with "Win32" -> "\\" | _ -> "/") in
173 let _ = _pycocci_setargs argv0 in
174
175 coccinelle_module := (pymodule_new "coccinelle");
176 module_map := StringMap.add "coccinelle" !coccinelle_module !module_map;
177 let _ = load_module "coccilib.elems" in
178 let _ = load_module "coccilib.output" in
179
180 let module_dictionary = pyimport_getmoduledict() in
181 coccinelle_module := pymodule_new "coccinelle";
182 let mx = !coccinelle_module in
183 let (cd, cx) = build_class "Cocci" (!Flag.pyoutput)
184 [("include_match", include_match, (pynull()));
185 ("has_env_binding", has_environment_binding, (pynull()))] mx in
186 pyoutputinstance := cx;
187 pyoutputdict := cd;
188 let v1 = pydict_setitemstring(module_dictionary, "coccinelle", mx) in
189 check_int_return_value v1;
190 let mypystring = pystring_fromstring !cocci_file_name in
191 let v2 = pydict_setitemstring(cd, "cocci_file", mypystring) in
192 check_int_return_value v2;
193 ()) else
194 ()
195
196 (*let _ = pycocci_init ()*)
197 (* end initialisation routines *)
198
199 let added_variables = ref []
200
201 let build_classes env =
202 let _ = pycocci_init () in
203 inc_match := true;
204 the_environment := env;
205 let mx = !coccinelle_module in
206 let dict = pymodule_getdict mx in
207 List.iter
208 (function
209 "include_match" | "has_env_binding" -> ()
210 | name ->
211 let v = pydict_delitemstring(dict,name) in
212 check_int_return_value v)
213 !added_variables;
214 added_variables := [];
215 ()
216
217 let build_variable name value =
218 let mx = !coccinelle_module in
219 added_variables := name :: !added_variables;
220 check_int_return_value
221 (pydict_setitemstring(pymodule_getdict mx, name, value))
222
223 let contains_binding e (_,(r,m)) =
224 try
225 let _ = List.find (function ((re, rm), _) -> r =$= re && m =$= rm) e in
226 true
227 with Not_found -> false
228
229 let construct_variables mv e =
230 let find_binding (r,m) =
231 try
232 let elem = List.find (function ((re,rm),_) -> r =$= re && m =$= rm) e in
233 Some elem
234 with Not_found -> None
235 in
236
237 let instantiate_Expression(x) =
238 let str = pystring_fromstring (Pycocci_aux.exprrep x) in
239 pycocci_instantiate_class "coccilib.elems.Expression"
240 (pytuple_fromsingle (str))
241 in
242
243 let instantiate_Identifier(x) =
244 let str = pystring_fromstring x in
245 pycocci_instantiate_class "coccilib.elems.Identifier"
246 (pytuple_fromsingle (str))
247 in
248
249 List.iter (function (py,(r,m)) ->
250 match find_binding (r,m) with
251 None -> ()
252 | Some (_, Ast_c.MetaExprVal expr) ->
253 let expr_repr = instantiate_Expression(expr) in
254 let _ = build_variable py expr_repr in
255 ()
256 | Some (_, Ast_c.MetaIdVal id) ->
257 let id_repr = instantiate_Identifier(id) in
258 let _ = build_variable py id_repr in
259 ()
260 | Some (_, Ast_c.MetaPosValList l) ->
261 let locs =
262 List.map
263 (function (fname,current_element,(line,col),(line_end,col_end)) ->
264 pycocci_instantiate_class "coccilib.elems.Location"
265 (_pycocci_tuple6
266 (pystring_fromstring fname,pystring_fromstring current_element,
267 pystring_fromstring (Printf.sprintf "%d" line),
268 pystring_fromstring (Printf.sprintf "%d" col),
269 pystring_fromstring (Printf.sprintf "%d" line_end),
270 pystring_fromstring (Printf.sprintf "%d" col_end)))) l in
271 let pylocs = pytuple_fromarray (Array.of_list locs) in
272 let _ = build_variable py pylocs in
273 ()
274 | Some (_,binding) ->
275 let _ = build_variable py (pystring_fromstring (Pycocci_aux.stringrep binding))
276 in ()
277 ) mv;
278
279 ()
280
281 let set_coccifile cocci_file =
282 cocci_file_name := cocci_file;
283 ()
284
285
286 let pyrun_simplestring s =
287 Pycaml.pyrun_simplestring s
288
289 let py_isinitialized () =
290 Pycaml.py_isinitialized ()
291
292
293 let py_finalize () =
294 Pycaml.py_finalize ()