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