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