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