Commit | Line | Data |
---|---|---|
0708f913 | 1 | (* Yoann Padioleau |
ae4735db C |
2 | * |
3 | * Copyright (C) 2010, University of Copenhagen DIKU and INRIA. | |
0708f913 | 4 | * Copyright (C) 2007, 2008, 2009 Ecole des Mines de Nantes |
34e49164 C |
5 | * |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License (GPL) | |
8 | * version 2 as published by the Free Software Foundation. | |
ae4735db | 9 | * |
34e49164 C |
10 | * This program 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 | * file license.txt for more details. | |
14 | *) | |
15 | open Common | |
16 | ||
708f4980 C |
17 | (*****************************************************************************) |
18 | (* Wrappers *) | |
19 | (*****************************************************************************) | |
20 | let pr2, pr2_once = Common.mk_pr2_wrappers Flag_parsing_c.verbose_parsing | |
21 | ||
34e49164 C |
22 | (*****************************************************************************) |
23 | (* Abstract line *) | |
24 | (*****************************************************************************) | |
25 | ||
26 | (* todo?: al_expr doit enlever les infos de type ? et doit remettre en | |
ae4735db | 27 | * emptyAnnot ? |
978fd7e5 C |
28 | |
29 | No! Keeping the type information is important to ensuring that variables | |
30 | of different type and declared in different places do not seem to match | |
31 | each other. On the other hand, we don't want to keep around the | |
32 | information about whether the expression is a test expression, because a | |
33 | term that is a test expression should match one that is not. The test | |
34 | information is only useful for matching to the CTL. | |
35 | ||
34e49164 C |
36 | *) |
37 | ||
38 | (* drop all info information *) | |
39 | ||
ae4735db | 40 | let strip_info_visitor _ = |
978fd7e5 C |
41 | let drop_test ty = |
42 | let (ty,_) = !ty in | |
43 | ref (ty,Ast_c.NotTest) in | |
44 | ||
34e49164 C |
45 | { Visitor_c.default_visitor_c_s with |
46 | Visitor_c.kinfo_s = | |
47 | (* traversal should be deterministic... *) | |
ae4735db | 48 | (let ctr = ref 0 in |
34e49164 | 49 | (function (k,_) -> |
b1b2de81 | 50 | function i -> ctr := !ctr + 1; Ast_c.al_info_cpp !ctr i)); |
34e49164 | 51 | |
ae4735db | 52 | Visitor_c.kexpr_s = (fun (k,_) e -> |
708f4980 | 53 | let (e', ty), ii' = k e in |
978fd7e5 | 54 | (e', drop_test ty), ii' (* keep type - jll *) |
34e49164 C |
55 | ); |
56 | ||
57 | (* | |
ae4735db | 58 | Visitor_c.ktype_s = (fun (k,_) ft -> |
34e49164 C |
59 | let ft' = k ft in |
60 | match Ast_c.unwrap_typeC ft' with | |
ae4735db | 61 | | Ast_c.TypeName (s,_typ) -> |
34e49164 C |
62 | Ast_c.TypeName (s, Ast_c.noTypedefDef()) +> Ast_c.rewrap_typeC ft' |
63 | | _ -> ft' | |
64 | ||
65 | ); | |
66 | *) | |
ae4735db | 67 | |
34e49164 C |
68 | } |
69 | ||
70 | let al_expr x = Visitor_c.vk_expr_s (strip_info_visitor()) x | |
413ffc02 C |
71 | let al_declaration x = Visitor_c.vk_decl_s (strip_info_visitor()) x |
72 | let al_field x = Visitor_c.vk_struct_field_s (strip_info_visitor()) x | |
34e49164 C |
73 | let al_statement x = Visitor_c.vk_statement_s (strip_info_visitor()) x |
74 | let al_type x = Visitor_c.vk_type_s (strip_info_visitor()) x | |
113803cf | 75 | let al_init x = Visitor_c.vk_ini_s (strip_info_visitor()) x |
8f657093 | 76 | let al_inits x = Visitor_c.vk_inis_s (strip_info_visitor()) x |
34e49164 C |
77 | let al_param x = Visitor_c.vk_param_s (strip_info_visitor()) x |
78 | let al_params x = Visitor_c.vk_params_s (strip_info_visitor()) x | |
79 | let al_arguments x = Visitor_c.vk_arguments_s (strip_info_visitor()) x | |
91eba41f | 80 | let al_fields x = Visitor_c.vk_struct_fields_s (strip_info_visitor()) x |
c491d8ee | 81 | let al_name x = Visitor_c.vk_name_s (strip_info_visitor()) x |
91eba41f C |
82 | |
83 | let al_node x = Visitor_c.vk_node_s (strip_info_visitor()) x | |
34e49164 C |
84 | |
85 | let al_program x = List.map (Visitor_c.vk_toplevel_s (strip_info_visitor())) x | |
91eba41f C |
86 | let al_ii x = Visitor_c.vk_ii_s (strip_info_visitor()) x |
87 | ||
88 | ||
89 | ||
90 | ||
978fd7e5 C |
91 | let strip_inh_info_visitor _ = (* for inherited metavariables *) |
92 | let drop_test_lv ty = | |
93 | let (ty,_) = !ty in | |
94 | let ty = | |
95 | match ty with | |
96 | None -> None | |
97 | | Some (ty,_) -> Some (ty,Ast_c.NotLocalVar) in | |
98 | ref (ty,Ast_c.NotTest) in | |
99 | ||
100 | { Visitor_c.default_visitor_c_s with | |
101 | Visitor_c.kinfo_s = | |
102 | (* traversal should be deterministic... *) | |
ae4735db | 103 | (let ctr = ref 0 in |
978fd7e5 C |
104 | (function (k,_) -> |
105 | function i -> ctr := !ctr + 1; Ast_c.al_info_cpp !ctr i)); | |
106 | ||
ae4735db | 107 | Visitor_c.kexpr_s = (fun (k,_) e -> |
978fd7e5 C |
108 | let (e', ty), ii' = k e in |
109 | (e', drop_test_lv ty), ii' (* keep type - jll *) | |
110 | ); | |
111 | ||
112 | (* | |
ae4735db | 113 | Visitor_c.ktype_s = (fun (k,_) ft -> |
978fd7e5 C |
114 | let ft' = k ft in |
115 | match Ast_c.unwrap_typeC ft' with | |
ae4735db | 116 | | Ast_c.TypeName (s,_typ) -> |
978fd7e5 C |
117 | Ast_c.TypeName (s, Ast_c.noTypedefDef()) +> Ast_c.rewrap_typeC ft' |
118 | | _ -> ft' | |
119 | ||
120 | ); | |
121 | *) | |
ae4735db | 122 | |
978fd7e5 C |
123 | } |
124 | ||
125 | let al_inh_expr x = Visitor_c.vk_expr_s (strip_inh_info_visitor()) x | |
413ffc02 | 126 | let al_inh_declaration x = Visitor_c.vk_decl_s (strip_inh_info_visitor()) x |
190f1acf C |
127 | let al_inh_field x = Visitor_c.vk_struct_field_s (strip_inh_info_visitor()) x |
128 | let al_inh_field_list x = | |
129 | Visitor_c.vk_struct_fields_s (strip_inh_info_visitor()) x | |
978fd7e5 C |
130 | let al_inh_statement x = Visitor_c.vk_statement_s (strip_inh_info_visitor()) x |
131 | let al_inh_type x = Visitor_c.vk_type_s (strip_inh_info_visitor()) x | |
132 | let al_inh_init x = Visitor_c.vk_ini_s (strip_inh_info_visitor()) x | |
8f657093 | 133 | let al_inh_inits x = Visitor_c.vk_inis_s (strip_inh_info_visitor()) x |
978fd7e5 C |
134 | let al_inh_arguments x = Visitor_c.vk_arguments_s (strip_inh_info_visitor()) x |
135 | ||
91eba41f | 136 | |
34e49164 C |
137 | |
138 | let semi_strip_info_visitor = (* keep position information *) | |
978fd7e5 C |
139 | let drop_test ty = |
140 | let (ty,_) = !ty in | |
141 | ref (ty,Ast_c.NotTest) in | |
142 | ||
34e49164 | 143 | { Visitor_c.default_visitor_c_s with |
b1b2de81 | 144 | Visitor_c.kinfo_s = (fun (k,_) i -> Ast_c.semi_al_info_cpp i); |
34e49164 | 145 | |
ae4735db | 146 | Visitor_c.kexpr_s = (fun (k,_) e -> |
34e49164 | 147 | let (e', ty),ii' = k e in |
978fd7e5 | 148 | (e', drop_test ty), ii' (* keep type - jll *) |
34e49164 | 149 | ); |
ae4735db | 150 | |
34e49164 C |
151 | } |
152 | ||
ae4735db | 153 | let semi_al_expr = Visitor_c.vk_expr_s semi_strip_info_visitor |
413ffc02 C |
154 | let semi_al_declaration = Visitor_c.vk_decl_s semi_strip_info_visitor |
155 | let semi_al_field = Visitor_c.vk_struct_field_s semi_strip_info_visitor | |
190f1acf | 156 | let semi_al_fields = Visitor_c.vk_struct_fields_s semi_strip_info_visitor |
34e49164 C |
157 | let semi_al_statement = Visitor_c.vk_statement_s semi_strip_info_visitor |
158 | let semi_al_type = Visitor_c.vk_type_s semi_strip_info_visitor | |
113803cf | 159 | let semi_al_init = Visitor_c.vk_ini_s semi_strip_info_visitor |
8f657093 | 160 | let semi_al_inits = Visitor_c.vk_inis_s semi_strip_info_visitor |
34e49164 C |
161 | let semi_al_param = Visitor_c.vk_param_s semi_strip_info_visitor |
162 | let semi_al_params = Visitor_c.vk_params_s semi_strip_info_visitor | |
163 | let semi_al_arguments = Visitor_c.vk_arguments_s semi_strip_info_visitor | |
164 | ||
b1b2de81 C |
165 | let semi_al_program = |
166 | List.map (Visitor_c.vk_toplevel_s semi_strip_info_visitor) | |
34e49164 | 167 | |
91eba41f C |
168 | |
169 | ||
170 | ||
0708f913 | 171 | (* really strip, do not keep position nor anything specificities, true |
002099fc | 172 | * abstracted form. This is used outside coccinelle in Yacfe and aComment *) |
ae4735db | 173 | let real_strip_info_visitor _ = |
91eba41f C |
174 | { Visitor_c.default_visitor_c_s with |
175 | Visitor_c.kinfo_s = (fun (k,_) i -> | |
b1b2de81 | 176 | Ast_c.real_al_info_cpp i |
91eba41f C |
177 | ); |
178 | ||
ae4735db | 179 | Visitor_c.kexpr_s = (fun (k,_) e -> |
91eba41f C |
180 | let (e', ty),ii' = k e in |
181 | (e', Ast_c.noType()), ii' | |
182 | ); | |
183 | ||
184 | (* | |
ae4735db | 185 | Visitor_c.ktype_s = (fun (k,_) ft -> |
91eba41f C |
186 | let ft' = k ft in |
187 | match Ast_c.unwrap_typeC ft' with | |
ae4735db | 188 | | Ast_c.TypeName (s,_typ) -> |
91eba41f C |
189 | Ast_c.TypeName (s, Ast_c.noTypedefDef()) +> Ast_c.rewrap_typeC ft' |
190 | | _ -> ft' | |
191 | ||
192 | ); | |
193 | *) | |
ae4735db | 194 | |
91eba41f C |
195 | } |
196 | ||
197 | let real_al_expr x = Visitor_c.vk_expr_s (real_strip_info_visitor()) x | |
993936c0 | 198 | let real_al_arguments x = Visitor_c.vk_arguments_s (real_strip_info_visitor()) x |
91eba41f C |
199 | let real_al_node x = Visitor_c.vk_node_s (real_strip_info_visitor()) x |
200 | let real_al_type x = Visitor_c.vk_type_s (real_strip_info_visitor()) x | |
993936c0 C |
201 | let real_al_decl x = Visitor_c.vk_decl_s (real_strip_info_visitor()) x |
202 | let real_al_init x = Visitor_c.vk_ini_s (real_strip_info_visitor()) x | |
203 | let real_al_inits x = Visitor_c.vk_inis_s (real_strip_info_visitor()) x | |
190f1acf C |
204 | let real_al_statement x = Visitor_c.vk_statement_s (real_strip_info_visitor()) x |
205 | let real_al_def x = Visitor_c.vk_toplevel_s (real_strip_info_visitor()) x | |
91eba41f | 206 | |
34e49164 C |
207 | (*****************************************************************************) |
208 | (* Extract infos *) | |
209 | (*****************************************************************************) | |
210 | ||
ae4735db | 211 | let extract_info_visitor recursor x = |
34e49164 | 212 | let globals = ref [] in |
ae4735db | 213 | let visitor = |
34e49164 C |
214 | { |
215 | Visitor_c.default_visitor_c with | |
216 | Visitor_c.kinfo = (fun (k, _) i -> Common.push2 i globals) | |
217 | } in | |
218 | begin | |
219 | recursor visitor x; | |
220 | !globals | |
221 | end | |
222 | ||
223 | let ii_of_decl = extract_info_visitor Visitor_c.vk_decl | |
413ffc02 | 224 | let ii_of_field = extract_info_visitor Visitor_c.vk_struct_field |
34e49164 C |
225 | let ii_of_node = extract_info_visitor Visitor_c.vk_node |
226 | let ii_of_expr = extract_info_visitor Visitor_c.vk_expr | |
227 | let ii_of_stmt = extract_info_visitor Visitor_c.vk_statement | |
228 | let ii_of_args = extract_info_visitor Visitor_c.vk_args_splitted | |
229 | let ii_of_type = extract_info_visitor Visitor_c.vk_type | |
230 | let ii_of_ini = extract_info_visitor Visitor_c.vk_ini | |
c491d8ee | 231 | let ii_of_inis = extract_info_visitor Visitor_c.vk_inis_splitted |
34e49164 C |
232 | let ii_of_param = extract_info_visitor Visitor_c.vk_param |
233 | let ii_of_params = extract_info_visitor Visitor_c.vk_params_splitted | |
c491d8ee | 234 | let ii_of_enum_fields = extract_info_visitor Visitor_c.vk_enum_fields_splitted |
34e49164 | 235 | let ii_of_struct_fields = extract_info_visitor Visitor_c.vk_struct_fields |
485bce71 C |
236 | (*let ii_of_struct_field = extract_info_visitor Visitor_c.vk_struct_field*) |
237 | let ii_of_struct_fieldkinds = extract_info_visitor Visitor_c.vk_struct_fieldkinds | |
34e49164 | 238 | let ii_of_cst = extract_info_visitor Visitor_c.vk_cst |
ae4735db | 239 | let ii_of_define_params = |
34e49164 | 240 | extract_info_visitor Visitor_c.vk_define_params_splitted |
485bce71 | 241 | let ii_of_toplevel = extract_info_visitor Visitor_c.vk_toplevel |
34e49164 | 242 | |
91eba41f C |
243 | (*****************************************************************************) |
244 | (* Max min, range *) | |
485bce71 | 245 | (*****************************************************************************) |
ae4735db | 246 | let max_min_ii_by_pos xs = |
34e49164 C |
247 | match xs with |
248 | | [] -> failwith "empty list, max_min_ii_by_pos" | |
249 | | [x] -> (x, x) | |
ae4735db | 250 | | x::xs -> |
b1b2de81 | 251 | let pos_leq p1 p2 = (Ast_c.compare_pos p1 p2) =|= (-1) in |
ae4735db | 252 | xs +> List.fold_left (fun (maxii,minii) e -> |
34e49164 C |
253 | let maxii' = if pos_leq maxii e then e else maxii in |
254 | let minii' = if pos_leq e minii then e else minii in | |
255 | maxii', minii' | |
256 | ) (x,x) | |
257 | ||
258 | let info_to_fixpos ii = | |
259 | match Ast_c.pinfo_of_info ii with | |
260 | Ast_c.OriginTok pi -> Ast_cocci.Real pi.Common.charpos | |
261 | | Ast_c.ExpandedTok (_,(pi,offset)) -> | |
262 | Ast_cocci.Virt (pi.Common.charpos,offset) | |
263 | | Ast_c.FakeTok (_,(pi,offset)) -> | |
264 | Ast_cocci.Virt (pi.Common.charpos,offset) | |
265 | | Ast_c.AbstractLineTok pi -> failwith "unexpected abstract" | |
ae4735db C |
266 | |
267 | let max_min_by_pos xs = | |
34e49164 C |
268 | let (i1, i2) = max_min_ii_by_pos xs in |
269 | (info_to_fixpos i1, info_to_fixpos i2) | |
270 | ||
ae4735db | 271 | let lin_col_by_pos xs = |
34e49164 | 272 | (* put min before max; no idea why they are backwards above *) |
951c7801 C |
273 | let non_fake = List.filter (function ii -> not (Ast_c.is_fake ii)) xs in |
274 | let (i2, i1) = max_min_ii_by_pos non_fake in | |
34e49164 C |
275 | let posf x = Ast_c.col_of_info x in |
276 | let mposf x = Ast_c.col_of_info x + String.length (Ast_c.str_of_info x) in | |
485bce71 | 277 | (Ast_c.file_of_info i1,!Flag.current_element, |
34e49164 C |
278 | (Ast_c.line_of_info i1, posf i1), (Ast_c.line_of_info i2, mposf i2)) |
279 | ||
280 | ||
91eba41f C |
281 | |
282 | ||
283 | ||
ae4735db | 284 | let min_pinfo_of_node node = |
91eba41f C |
285 | let ii = ii_of_node node in |
286 | let (maxii, minii) = max_min_ii_by_pos ii in | |
287 | Ast_c.parse_info_of_info minii | |
288 | ||
289 | ||
ae4735db C |
290 | let (range_of_origin_ii: Ast_c.info list -> (int * int) option) = |
291 | fun ii -> | |
91eba41f | 292 | let ii = List.filter Ast_c.is_origintok ii in |
ae4735db | 293 | try |
91eba41f C |
294 | let (max, min) = max_min_ii_by_pos ii in |
295 | assert(Ast_c.is_origintok max); | |
296 | assert(Ast_c.is_origintok min); | |
297 | let strmax = Ast_c.str_of_info max in | |
ae4735db | 298 | Some |
91eba41f | 299 | (Ast_c.pos_of_info min, Ast_c.pos_of_info max + String.length strmax) |
ae4735db | 300 | with _ -> |
91eba41f | 301 | None |
0708f913 C |
302 | |
303 | ||
304 | (*****************************************************************************) | |
305 | (* Ast getters *) | |
306 | (*****************************************************************************) | |
307 | ||
ae4735db | 308 | let names_of_parameters_in_def def = |
0708f913 | 309 | match def.Ast_c.f_old_c_style with |
ae4735db | 310 | | Some _ -> |
0708f913 C |
311 | pr2_once "names_of_parameters_in_def: f_old_c_style not handled"; |
312 | [] | |
ae4735db | 313 | | None -> |
0708f913 C |
314 | let ftyp = def.Ast_c.f_type in |
315 | let (ret, (params, bwrap)) = ftyp in | |
ae4735db | 316 | params +> Common.map_filter (fun (param,ii) -> |
0708f913 C |
317 | Ast_c.name_of_parameter param |
318 | ) | |
319 | ||
ae4735db C |
320 | let names_of_parameters_in_macro xs = |
321 | xs +> List.map (fun (xx, ii) -> | |
0708f913 C |
322 | let (s, ii2) = xx in |
323 | s | |
324 | ) | |
708f4980 C |
325 | |
326 | ||
327 | ||
328 | (* only used in ast_to_flow, so move it ? *) | |
ae4735db C |
329 | let rec stmt_elems_of_sequencable xs = |
330 | xs +> Common.map (fun x -> | |
708f4980 C |
331 | match x with |
332 | | Ast_c.StmtElem e -> [e] | |
333 | | Ast_c.CppDirectiveStmt _ | |
ae4735db C |
334 | | Ast_c.IfdefStmt _ |
335 | -> | |
708f4980 C |
336 | pr2_once ("stmt_elems_of_sequencable: filter a directive"); |
337 | [] | |
ae4735db | 338 | | Ast_c.IfdefStmt2 (_ifdef, xxs) -> |
708f4980 | 339 | pr2 ("stmt_elems_of_sequencable: IfdefStm2 TODO?"); |
ae4735db | 340 | xxs +> List.map (fun xs -> |
708f4980 C |
341 | let xs' = stmt_elems_of_sequencable xs in |
342 | xs' | |
343 | ) +> List.flatten | |
344 | ) +> List.flatten | |
ae4735db C |
345 | |
346 | ||
708f4980 | 347 |