Commit | Line | Data |
---|---|---|
34e49164 C |
1 | (* |
2 | * Copyright 2005-2008, 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) -> | |
485bce71 C |
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, | |
34e49164 C |
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 () |