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