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