Release coccinelle-0.1.8
[bpt/coccinelle.git] / parsing_c / lib_parsing_c.ml
CommitLineData
0708f913
C
1(* Yoann Padioleau
2 *
3 * Copyright (C) 2007, 2008, 2009 Ecole des Mines de Nantes
34e49164
C
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License (GPL)
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * file license.txt for more details.
13 *)
14open Common
15
708f4980
C
16(*****************************************************************************)
17(* Wrappers *)
18(*****************************************************************************)
19let pr2, pr2_once = Common.mk_pr2_wrappers Flag_parsing_c.verbose_parsing
20
34e49164
C
21(*****************************************************************************)
22(* Abstract line *)
23(*****************************************************************************)
24
25(* todo?: al_expr doit enlever les infos de type ? et doit remettre en
26 * emptyAnnot ?
27 *)
28
29(* drop all info information *)
30
31let strip_info_visitor _ =
32 { Visitor_c.default_visitor_c_s with
33 Visitor_c.kinfo_s =
34 (* traversal should be deterministic... *)
35 (let ctr = ref 0 in
36 (function (k,_) ->
b1b2de81 37 function i -> ctr := !ctr + 1; Ast_c.al_info_cpp !ctr i));
34e49164
C
38
39 Visitor_c.kexpr_s = (fun (k,_) e ->
708f4980 40 let (e', ty), ii' = k e in
34e49164
C
41 (e', Ast_c.noType()(*ref !ty*)), ii' (* keep type - jll *)
42 );
43
44(*
45 Visitor_c.ktype_s = (fun (k,_) ft ->
46 let ft' = k ft in
47 match Ast_c.unwrap_typeC ft' with
48 | Ast_c.TypeName (s,_typ) ->
49 Ast_c.TypeName (s, Ast_c.noTypedefDef()) +> Ast_c.rewrap_typeC ft'
50 | _ -> ft'
51
52 );
53*)
54
55 }
56
57let al_expr x = Visitor_c.vk_expr_s (strip_info_visitor()) x
58let al_statement x = Visitor_c.vk_statement_s (strip_info_visitor()) x
59let al_type x = Visitor_c.vk_type_s (strip_info_visitor()) x
113803cf 60let al_init x = Visitor_c.vk_ini_s (strip_info_visitor()) x
34e49164
C
61let al_param x = Visitor_c.vk_param_s (strip_info_visitor()) x
62let al_params x = Visitor_c.vk_params_s (strip_info_visitor()) x
63let al_arguments x = Visitor_c.vk_arguments_s (strip_info_visitor()) x
91eba41f
C
64let al_fields x = Visitor_c.vk_struct_fields_s (strip_info_visitor()) x
65
66let al_node x = Visitor_c.vk_node_s (strip_info_visitor()) x
34e49164
C
67
68let al_program x = List.map (Visitor_c.vk_toplevel_s (strip_info_visitor())) x
91eba41f
C
69let al_ii x = Visitor_c.vk_ii_s (strip_info_visitor()) x
70
71
72
73
74
34e49164
C
75
76let semi_strip_info_visitor = (* keep position information *)
77 { Visitor_c.default_visitor_c_s with
b1b2de81 78 Visitor_c.kinfo_s = (fun (k,_) i -> Ast_c.semi_al_info_cpp i);
34e49164
C
79
80 Visitor_c.kexpr_s = (fun (k,_) e ->
81 let (e', ty),ii' = k e in
82 (e', Ast_c.noType()(*ref !ty*)), ii' (* keep type - jll *)
83 );
84
85 }
86
87let semi_al_expr = Visitor_c.vk_expr_s semi_strip_info_visitor
88let semi_al_statement = Visitor_c.vk_statement_s semi_strip_info_visitor
89let semi_al_type = Visitor_c.vk_type_s semi_strip_info_visitor
113803cf 90let semi_al_init = Visitor_c.vk_ini_s semi_strip_info_visitor
34e49164
C
91let semi_al_param = Visitor_c.vk_param_s semi_strip_info_visitor
92let semi_al_params = Visitor_c.vk_params_s semi_strip_info_visitor
93let semi_al_arguments = Visitor_c.vk_arguments_s semi_strip_info_visitor
94
b1b2de81
C
95let semi_al_program =
96 List.map (Visitor_c.vk_toplevel_s semi_strip_info_visitor)
34e49164 97
91eba41f
C
98
99
100
0708f913
C
101(* really strip, do not keep position nor anything specificities, true
102 * abstracted form. *)
91eba41f
C
103let real_strip_info_visitor _ =
104 { Visitor_c.default_visitor_c_s with
105 Visitor_c.kinfo_s = (fun (k,_) i ->
b1b2de81 106 Ast_c.real_al_info_cpp i
91eba41f
C
107 );
108
109 Visitor_c.kexpr_s = (fun (k,_) e ->
110 let (e', ty),ii' = k e in
111 (e', Ast_c.noType()), ii'
112 );
113
114(*
115 Visitor_c.ktype_s = (fun (k,_) ft ->
116 let ft' = k ft in
117 match Ast_c.unwrap_typeC ft' with
118 | Ast_c.TypeName (s,_typ) ->
119 Ast_c.TypeName (s, Ast_c.noTypedefDef()) +> Ast_c.rewrap_typeC ft'
120 | _ -> ft'
121
122 );
123*)
124
125 }
126
127let real_al_expr x = Visitor_c.vk_expr_s (real_strip_info_visitor()) x
128let real_al_node x = Visitor_c.vk_node_s (real_strip_info_visitor()) x
129let real_al_type x = Visitor_c.vk_type_s (real_strip_info_visitor()) x
130
131
34e49164
C
132(*****************************************************************************)
133(* Extract infos *)
134(*****************************************************************************)
135
136let extract_info_visitor recursor x =
137 let globals = ref [] in
138 let visitor =
139 {
140 Visitor_c.default_visitor_c with
141 Visitor_c.kinfo = (fun (k, _) i -> Common.push2 i globals)
142 } in
143 begin
144 recursor visitor x;
145 !globals
146 end
147
148let ii_of_decl = extract_info_visitor Visitor_c.vk_decl
149let ii_of_node = extract_info_visitor Visitor_c.vk_node
150let ii_of_expr = extract_info_visitor Visitor_c.vk_expr
151let ii_of_stmt = extract_info_visitor Visitor_c.vk_statement
152let ii_of_args = extract_info_visitor Visitor_c.vk_args_splitted
153let ii_of_type = extract_info_visitor Visitor_c.vk_type
154let ii_of_ini = extract_info_visitor Visitor_c.vk_ini
155let ii_of_param = extract_info_visitor Visitor_c.vk_param
156let ii_of_params = extract_info_visitor Visitor_c.vk_params_splitted
157let ii_of_struct_fields = extract_info_visitor Visitor_c.vk_struct_fields
485bce71
C
158(*let ii_of_struct_field = extract_info_visitor Visitor_c.vk_struct_field*)
159let ii_of_struct_fieldkinds = extract_info_visitor Visitor_c.vk_struct_fieldkinds
34e49164
C
160let ii_of_cst = extract_info_visitor Visitor_c.vk_cst
161let ii_of_define_params =
162 extract_info_visitor Visitor_c.vk_define_params_splitted
485bce71 163let ii_of_toplevel = extract_info_visitor Visitor_c.vk_toplevel
34e49164 164
91eba41f
C
165(*****************************************************************************)
166(* Max min, range *)
485bce71 167(*****************************************************************************)
34e49164
C
168let max_min_ii_by_pos xs =
169 match xs with
170 | [] -> failwith "empty list, max_min_ii_by_pos"
171 | [x] -> (x, x)
172 | x::xs ->
b1b2de81 173 let pos_leq p1 p2 = (Ast_c.compare_pos p1 p2) =|= (-1) in
34e49164
C
174 xs +> List.fold_left (fun (maxii,minii) e ->
175 let maxii' = if pos_leq maxii e then e else maxii in
176 let minii' = if pos_leq e minii then e else minii in
177 maxii', minii'
178 ) (x,x)
179
180let info_to_fixpos ii =
181 match Ast_c.pinfo_of_info ii with
182 Ast_c.OriginTok pi -> Ast_cocci.Real pi.Common.charpos
183 | Ast_c.ExpandedTok (_,(pi,offset)) ->
184 Ast_cocci.Virt (pi.Common.charpos,offset)
185 | Ast_c.FakeTok (_,(pi,offset)) ->
186 Ast_cocci.Virt (pi.Common.charpos,offset)
187 | Ast_c.AbstractLineTok pi -> failwith "unexpected abstract"
188
189let max_min_by_pos xs =
190 let (i1, i2) = max_min_ii_by_pos xs in
191 (info_to_fixpos i1, info_to_fixpos i2)
192
193let lin_col_by_pos xs =
194 (* put min before max; no idea why they are backwards above *)
195 let (i2, i1) = max_min_ii_by_pos xs in
196 let posf x = Ast_c.col_of_info x in
197 let mposf x = Ast_c.col_of_info x + String.length (Ast_c.str_of_info x) in
485bce71 198 (Ast_c.file_of_info i1,!Flag.current_element,
34e49164
C
199 (Ast_c.line_of_info i1, posf i1), (Ast_c.line_of_info i2, mposf i2))
200
201
91eba41f
C
202
203
204
205let min_pinfo_of_node node =
206 let ii = ii_of_node node in
207 let (maxii, minii) = max_min_ii_by_pos ii in
208 Ast_c.parse_info_of_info minii
209
210
211let (range_of_origin_ii: Ast_c.info list -> (int * int) option) =
212 fun ii ->
213 let ii = List.filter Ast_c.is_origintok ii in
214 try
215 let (max, min) = max_min_ii_by_pos ii in
216 assert(Ast_c.is_origintok max);
217 assert(Ast_c.is_origintok min);
218 let strmax = Ast_c.str_of_info max in
219 Some
220 (Ast_c.pos_of_info min, Ast_c.pos_of_info max + String.length strmax)
221 with _ ->
222 None
0708f913
C
223
224
225(*****************************************************************************)
226(* Ast getters *)
227(*****************************************************************************)
228
229let names_of_parameters_in_def def =
230 match def.Ast_c.f_old_c_style with
231 | Some _ ->
232 pr2_once "names_of_parameters_in_def: f_old_c_style not handled";
233 []
234 | None ->
235 let ftyp = def.Ast_c.f_type in
236 let (ret, (params, bwrap)) = ftyp in
237 params +> Common.map_filter (fun (param,ii) ->
238 Ast_c.name_of_parameter param
239 )
240
241let names_of_parameters_in_macro xs =
242 xs +> List.map (fun (xx, ii) ->
243 let (s, ii2) = xx in
244 s
245 )
708f4980
C
246
247
248
249(* only used in ast_to_flow, so move it ? *)
250let rec stmt_elems_of_sequencable xs =
251 xs +> Common.map (fun x ->
252 match x with
253 | Ast_c.StmtElem e -> [e]
254 | Ast_c.CppDirectiveStmt _
255 | Ast_c.IfdefStmt _
256 ->
257 pr2_once ("stmt_elems_of_sequencable: filter a directive");
258 []
259 | Ast_c.IfdefStmt2 (_ifdef, xxs) ->
260 pr2 ("stmt_elems_of_sequencable: IfdefStm2 TODO?");
261 xxs +> List.map (fun xs ->
262 let xs' = stmt_elems_of_sequencable xs in
263 xs'
264 ) +> List.flatten
265 ) +> List.flatten
266
267
268