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