Release coccinelle-0.2.0rc1
[bpt/coccinelle.git] / python / yes_pycocci.ml
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
9 let python_support = true
10
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
33 let check_return_value v =
34 if v =*= (pynull ()) then
35 (pyerr_print ();
36 raise Pycocciexception)
37 else ()
38 let check_int_return_value v =
39 if v =|= -1 then
40 (pyerr_print ();
41 raise Pycocciexception)
42 else ()
43
44 let initialised = ref false
45
46 let coccinelle_module = ref (_pycocci_none ())
47 let cocci_file_name = ref ""
48
49 (* dealing with python modules loaded *)
50 let module_map = ref (StringMap.add "__main__" (_pycocci_none ()) StringMap.empty)
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
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;
98 _pycocci_none ()
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;
109 let cx = pyclass_new(pytuple_fromsingle (pycocci_get_class_type parent), cd,
110 pystring_fromstring cname) in
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
117 let the_environment = ref []
118
119 let has_environment_binding name =
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
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 ()
127
128 let pyoutputinstance = ref (_pycocci_none ())
129 let pyoutputdict = ref (_pycocci_none ())
130
131 let get_cocci_file args =
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 []
180
181 let build_classes env =
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 ()
196
197 let build_variable name value =
198 let mx = !coccinelle_module in
199 added_variables := name :: !added_variables;
200 check_int_return_value
201 (pydict_setitemstring(pymodule_getdict mx, name, value))
202
203 let contains_binding e (_,(r,m)) =
204 try
205 let _ = List.find (function ((re, rm), _) -> r =$= re && m =$= rm) e in
206 true
207 with Not_found -> false
208
209 let construct_variables mv e =
210 let find_binding (r,m) =
211 try
212 let elem = List.find (function ((re,rm),_) -> r =$= re && m =$= rm) e in
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
219 pycocci_instantiate_class "coccilib.elems.Expression"
220 (pytuple_fromsingle (str))
221 in
222
223 let instantiate_Identifier(x) =
224 let str = pystring_fromstring x in
225 pycocci_instantiate_class "coccilib.elems.Identifier"
226 (pytuple_fromsingle (str))
227 in
228
229 List.iter (function (py,(r,m)) ->
230 match find_binding (r,m) with
231 None -> ()
232 | Some (_, Ast_c.MetaExprVal expr) ->
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) ->
241 let locs =
242 List.map
243 (function (fname,current_element,(line,col),(line_end,col_end)) ->
244 pycocci_instantiate_class "coccilib.elems.Location"
245 (_pycocci_tuple6
246 (pystring_fromstring fname,pystring_fromstring current_element,
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 ()