Release coccinelle-0.1.6
[bpt/coccinelle.git] / python / .#yes_pycocci.ml.1.2
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
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 open Ast_c
24 open Common
25 open Pycaml
26 open Pycocci_aux
27 module StringMap = Map.Make (String)
28
29 exception Pycocciexception
30
31 let check_return_value v =
32 if v = (pynull ()) then
33 (pyerr_print ();
34 raise Pycocciexception)
35 else ()
36 let check_int_return_value v =
37 if v = -1 then
38 (pyerr_print ();
39 raise Pycocciexception)
40 else ()
41
42 let initialised = ref false
43
44 let coccinelle_module = ref (pynone ())
45 let cocci_file_name = ref ""
46
47 (* dealing with python modules loaded *)
48 let module_map = ref (StringMap.add "__main__" (pynone ()) StringMap.empty)
49
50 let get_module module_name =
51 StringMap.find module_name (!module_map)
52
53 let is_module_loaded module_name =
54 try
55 let _ = get_module module_name in
56 true
57 with Not_found -> false
58
59 let load_module module_name =
60 if not (is_module_loaded module_name) then
61 let m = pyimport_importmodule module_name in
62 check_return_value m;
63 (module_map := (StringMap.add module_name m (!module_map));
64 m)
65 else get_module module_name
66 (* end python module handling part *)
67
68 (* initialisation routines *)
69 let pycocci_init () =
70 (* initialize *)
71 if not !initialised then (
72 initialised := true;
73 Unix.putenv "PYTHONPATH"
74 (Printf.sprintf "%s/coccinelle" (Unix.getenv "HOME"));
75 let _ = if not (py_isinitialized () != 0) then
76 (if !Flag.show_misc then Common.pr2 "Initializing python\n%!";
77 py_initialize()) in
78
79 (* set argv *)
80 let argv0 = Printf.sprintf "%s%sspatch" (Sys.getcwd ()) (match Sys.os_type with "Win32" -> "\\" | _ -> "/") in
81 let _ = pycaml_setargs argv0 in
82
83 coccinelle_module := (pymodule_new "coccinelle");
84 module_map := StringMap.add "coccinelle" !coccinelle_module !module_map;
85 let _ = load_module "coccilib.elems" in
86 let _ = load_module "coccilib.output" in
87 ()) else
88
89 ()
90
91 (*let _ = pycocci_init ()*)
92 (* end initialisation routines *)
93
94 (* python interaction *)
95 let split_fqn fqn =
96 let last_period = String.rindex fqn '.' in
97 let module_name = String.sub fqn 0 last_period in
98 let class_name = String.sub fqn (last_period + 1) (String.length fqn - last_period - 1) in
99 (module_name, class_name)
100
101 let pycocci_get_class_type fqn =
102 let (module_name, class_name) = split_fqn fqn in
103 let m = get_module module_name in
104 let attr = pyobject_getattrstring(m, class_name) in
105 check_return_value attr;
106 attr
107
108 let pycocci_instantiate_class fqn args =
109 let class_type = pycocci_get_class_type fqn in
110 let obj = pyobject_callobject(class_type, args) in
111 check_return_value obj;
112 obj
113
114 (* end python interaction *)
115
116 let inc_match = ref true
117
118 let include_match v =
119 let truth = pyobject_istrue (pytuple_getitem (v, 1)) in
120 check_int_return_value truth;
121 inc_match := truth != 0;
122 pynone ()
123
124 let build_method (mname, camlfunc, args) pymodule classx classdict =
125 let cmx = pymethod_new(pywrap_closure camlfunc, args, classx) in
126 let v = pydict_setitemstring(classdict, mname, cmx) in
127 check_int_return_value v;
128 ()
129
130 let build_class cname parent methods pymodule =
131 let cd = pydict_new() in
132 check_return_value cd;
133 let cx = pyclass_new(pytuple_fromsingle (pycocci_get_class_type parent), cd, pystring_fromstring cname) in
134 check_return_value cx;
135 List.iter (function meth -> build_method meth pymodule cx cd) methods;
136 let v = pydict_setitemstring(pymodule_getdict pymodule, cname, cx) in
137 check_int_return_value v;
138 (cd, cx)
139
140 let has_environment_binding env name =
141 let a = pytuple_toarray name in
142 let (rule, name) = (Array.get a 1, Array.get a 2) in
143 let orule = pystring_asstring rule in
144 let oname = pystring_asstring name in
145 let e = List.exists (function (x,y) -> orule = x && oname = y) env in
146 if e then pytrue () else pyfalse ()
147
148 let pyoutputinstance = ref (pynone ())
149 let pyoutputdict = ref (pynone ())
150
151 let get_cocci_file args =
152 pystring_fromstring (!cocci_file_name)
153
154 let build_classes env =
155 let _ = pycocci_init () in
156 let module_dictionary = pyimport_getmoduledict() in
157 coccinelle_module := pymodule_new "coccinelle";
158 let mx = !coccinelle_module in
159 inc_match := true;
160 let (cd, cx) = build_class "Cocci" (!Flag.pyoutput)
161 [("include_match", include_match, (pynull()));
162 ("has_env_binding", has_environment_binding env, (pynull()))] mx in
163 pyoutputinstance := cx;
164 pyoutputdict := cd;
165 let v1 = pydict_setitemstring(module_dictionary, "coccinelle", mx) in
166 check_int_return_value v1;
167 let mypystring = pystring_fromstring !cocci_file_name in
168 let v2 = pydict_setitemstring(cd, "cocci_file", mypystring) in
169 check_int_return_value v2;
170 ()
171
172 let build_variable name value =
173 let mx = !coccinelle_module in
174 check_int_return_value (pydict_setitemstring(pymodule_getdict mx, name, value))
175
176 let contains_binding e (_,(r,m)) =
177 try
178 let _ = List.find (function ((re, rm), _) -> r = re && m = rm) e in true
179 with Not_found -> false
180
181 let construct_variables mv e =
182 let find_binding (r,m) =
183 try
184 let elem = List.find (function ((re,rm),_) -> r = re && m = rm) e in
185 Some elem
186 with Not_found -> None
187 in
188
189 let instantiate_Expression(x) =
190 let str = pystring_fromstring (Pycocci_aux.exprrep x) in
191 pycocci_instantiate_class "coccilib.elems.Expression" (pytuple_fromsingle (str))
192 in
193
194 let instantiate_Identifier(x) =
195 let str = pystring_fromstring x in
196 pycocci_instantiate_class "coccilib.elems.Identifier" (pytuple_fromsingle (str))
197 in
198
199 List.iter (function (py,(r,m)) ->
200 match find_binding (r,m) with
201 None -> ()
202 | Some (_, Ast_c.MetaExprVal ((expr, _), info_list)) ->
203 let expr_repr = instantiate_Expression(expr) in
204 let _ = build_variable py expr_repr in
205 ()
206 | Some (_, Ast_c.MetaIdVal id) ->
207 let id_repr = instantiate_Identifier(id) in
208 let _ = build_variable py id_repr in
209 ()
210 | Some (_, Ast_c.MetaPosValList l) ->
211 let locs =
212 List.map
213 (function (fname,current_element,(line,col),(line_end,col_end)) ->
214 pycocci_instantiate_class "coccilib.elems.Location" (pytuple6
215 (pystring_fromstring fname,pystring_fromstring current_element,
216 pystring_fromstring (Printf.sprintf "%d" line),
217 pystring_fromstring (Printf.sprintf "%d" col),
218 pystring_fromstring (Printf.sprintf "%d" line_end),
219 pystring_fromstring (Printf.sprintf "%d" col_end)))) l in
220 let pylocs = pytuple_fromarray (Array.of_list locs) in
221 let _ = build_variable py pylocs in
222 ()
223 | Some (_,binding) ->
224 let _ = build_variable py (pystring_fromstring (Pycocci_aux.stringrep binding))
225 in ()
226 ) mv;
227
228 ()
229
230 let set_coccifile cocci_file =
231 cocci_file_name := cocci_file;
232 ()
233
234
235 let pyrun_simplestring s =
236 Pycaml.pyrun_simplestring s
237
238 let py_isinitialized () =
239 Pycaml.py_isinitialized ()
240
241
242 let py_finalize () =
243 Pycaml.py_finalize ()