Release coccinelle-0.2.5-rc2
[bpt/coccinelle.git] / parsing_c / parsing_stat.ml
CommitLineData
0708f913 1(* Yoann Padioleau
ae4735db
C
2 *
3 * Copyright (C) 2010, University of Copenhagen DIKU and INRIA.
0708f913
C
4 * Copyright (C) 2008, 2009 University of Urbana Champaign
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 *
0708f913
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
ae4735db 16open Common
485bce71
C
17
18(* if do .mli:
19val print_parsing_stat_list: parsing_stat list -> unit
20*)
21
22(*****************************************************************************)
23(* Stat *)
24(*****************************************************************************)
25type parsing_stat = {
26 filename: filename;
27 mutable have_timeout: bool;
28
ae4735db 29 mutable correct: int;
485bce71
C
30 mutable bad: int;
31
32 mutable commentized: int; (* by our cpp commentizer *)
33
34 (* if want to know exactly what was passed through, uncomment:
ae4735db 35 *
485bce71 36 * mutable passing_through_lines: int;
ae4735db 37 *
485bce71
C
38 * it differs from bad by starting from the error to
39 * the synchro point instead of starting from start of
40 * function to end of function.
41 *)
42
ae4735db 43 mutable problematic_lines:
91eba41f
C
44 (string list (* ident in error line *) * int (* line_error *)) list;
45
ae4735db 46 }
485bce71 47
ae4735db 48let default_stat file = {
485bce71
C
49 filename = file;
50 have_timeout = false;
51 correct = 0; bad = 0;
52 commentized = 0;
91eba41f 53 problematic_lines = [];
485bce71
C
54 }
55
ae4735db
C
56(* todo: stat per dir ? give in terms of func_or_decl numbers:
57 * nbfunc_or_decl pbs / nbfunc_or_decl total ?/
485bce71 58 *
ae4735db
C
59 * note: cela dit si y'a des fichiers avec des #ifdef dont on connait pas les
60 * valeurs alors on parsera correctement tout le fichier et pourtant y'aura
61 * aucune def et donc aucune couverture en fait.
62 * ==> TODO evaluer les parties non parsé ?
485bce71
C
63 *)
64
ae4735db 65let print_parsing_stat_list ?(verbose=false) = fun statxs ->
485bce71 66 let total = List.length statxs in
ae4735db
C
67 let perfect =
68 statxs
69 +> List.filter (function
485bce71 70 {have_timeout = false; bad = 0} -> true | _ -> false)
ae4735db 71 +> List.length
485bce71
C
72 in
73
74 if verbose then begin
75 pr "\n\n\n---------------------------------------------------------------";
76 pr "pbs with files:";
ae4735db
C
77 statxs
78 +> List.filter (function
79 | {have_timeout = true} -> true
80 | {bad = n} when n > 0 -> true
485bce71 81 | _ -> false)
ae4735db
C
82 +> List.iter (function
83 {filename = file; have_timeout = timeout; bad = n} ->
485bce71
C
84 pr (file ^ " " ^ (if timeout then "TIMEOUT" else i_to_s n));
85 );
86
87 pr "\n\n\n";
88 pr "files with lots of tokens passed/commentized:";
89 let threshold_passed = 100 in
ae4735db
C
90 statxs
91 +> List.filter (function
485bce71
C
92 | {commentized = n} when n > threshold_passed -> true
93 | _ -> false)
ae4735db
C
94 +> List.iter (function
95 {filename = file; commentized = n} ->
485bce71
C
96 pr (file ^ " " ^ (i_to_s n));
97 );
98
99 pr "\n\n\n---------------------------------------------------------------";
100 end;
101
102 pr (
103 (sprintf "NB total files = %d; " total) ^
104 (sprintf "perfect = %d; " perfect) ^
ae4735db
C
105 (sprintf "pbs = %d; " (statxs +> List.filter (function
106 {have_timeout = b; bad = n} when n > 0 -> true | _ -> false)
485bce71 107 +> List.length)) ^
ae4735db
C
108 (sprintf "timeout = %d; " (statxs +> List.filter (function
109 {have_timeout = true; bad = n} -> true | _ -> false)
485bce71
C
110 +> List.length)) ^
111 (sprintf "=========> %d" ((100 * perfect) / total)) ^ "%"
ae4735db 112
485bce71
C
113 );
114 let good = statxs +> List.fold_left (fun acc {correct = x} -> acc+x) 0 in
115 let bad = statxs +> List.fold_left (fun acc {bad = x} -> acc+x) 0 in
116 let passed = statxs +> List.fold_left (fun acc {commentized = x} -> acc+x) 0
117 in
118 let gf, badf = float_of_int good, float_of_int bad in
119 let passedf = float_of_int passed in
120 pr (
121 (sprintf "nb good = %d, nb passed = %d " good passed) ^
113803cf 122 (sprintf "=========> %f" (100.0 *. (passedf /. gf)) ^ "% passed")
485bce71
C
123 );
124 pr (
125 (sprintf "nb good = %d, nb bad = %d " good bad) ^
113803cf 126 (sprintf "=========> %f" (100.0 *. (gf /. (gf +. badf))) ^ "% good"
485bce71
C
127 )
128 )
129
91eba41f
C
130(*****************************************************************************)
131(* Recurring error diagnostic *)
132(*****************************************************************************)
133(* asked/inspired by reviewer of CC'09 *)
134
ae4735db 135let lines_around_error_line ~context (file, line) =
91eba41f 136 let arr = Common.cat_array file in
ae4735db 137
91eba41f
C
138 let startl = max 0 (line - context) in
139 let endl = min (Array.length arr) (line + context) in
ae4735db 140 let res = ref [] in
91eba41f 141
ae4735db 142 for i = startl to endl -1 do
91eba41f
C
143 Common.push2 arr.(i) res
144 done;
145 List.rev !res
146
147
148
ae4735db 149let print_recurring_problematic_tokens xs =
91eba41f 150 let h = Hashtbl.create 101 in
ae4735db
C
151 xs +> List.iter (fun x ->
152 let file = x.filename in
153 x.problematic_lines +> List.iter (fun (xs, line_error) ->
154 xs +> List.iter (fun s ->
91eba41f 155 Common.hupdate_default s
ae4735db 156 (fun (old, example) -> old + 1, example)
91eba41f
C
157 (fun() -> 0, (file, line_error)) h;
158 )));
159 pr2_xxxxxxxxxxxxxxxxx();
160 pr2 ("maybe 10 most problematic tokens");
161 pr2_xxxxxxxxxxxxxxxxx();
162 Common.hash_to_list h
ae4735db 163 +> List.sort (fun (k1,(v1,_)) (k2,(v2,_)) -> compare v2 v1)
91eba41f 164 +> Common.take_safe 10
ae4735db 165 +> List.iter (fun (k,(i, (file_ex, line_ex))) ->
91eba41f
C
166 pr2 (spf "%s: present in %d parsing errors" k i);
167 pr2 ("example: ");
168 let lines = lines_around_error_line ~context:2 (file_ex, line_ex) in
169 lines +> List.iter (fun s -> pr2 (" " ^ s));
ae4735db 170
91eba41f
C
171 );
172 pr2_xxxxxxxxxxxxxxxxx();
173 ()
174
ae4735db 175
91eba41f
C
176
177
485bce71
C
178(*****************************************************************************)
179(* Stat *)
180(*****************************************************************************)
181
ae4735db 182(* Those variables were written for CC09, to evaluate the need for
91eba41f 183 * some of our heuristics and extensions.
ae4735db
C
184 *
185 * coupling: if you add a new var, modify also assoc_stat_number below
91eba41f 186 *)
485bce71
C
187
188let nTypedefInfer = ref 0
189
190let nIncludeGrammar = ref 0
191let nIncludeHack = ref 0
192
ae4735db
C
193let nIteratorGrammar = ref 0
194let nIteratorHeuristic = ref 0
485bce71
C
195
196let nMacroTopDecl = ref 0
197let nMacroStructDecl = ref 0
198let nMacroDecl = ref 0
199let nMacroStmt = ref 0
200let nMacroString = ref 0
201let nMacroHigherOrder = ref 0 (* actions *)
202let nMacrohigherTypeGrammar = ref 0
203let nMacroAttribute = ref 0
204
205let nIfdefTop = ref 0
206let nIfdefStmt = ref 0
207let nIfdefStruct = ref 0
208let nIfdefInitializer = ref 0
209(* nIfdefExpr, nIfdefType *)
210
211let nIfdefFunheader = ref 0
212
213let nIfdefExprPassing = ref 0
214let nIfdefPassing = ref 0
215
216let nIncludePassing = ref 0
3a314143 217let nUndefPassing = ref 0
485bce71
C
218let nDefinePassing = ref 0
219
220let nIfdefZero = ref 0
221let nIfdefVersion = ref 0
222
223
224
225let nGccTypeof = ref 0
226let nGccLongLong = ref 0
227let nGccAsm = ref 0
228let nGccInline = ref 0
229let nGccAttribute = ref 0
230let nGccCaseRange = ref 0
231let nGccMixDecl = ref 0
232let nGccDesignator = ref 0
233let nGccStmtExpr = ref 0
234let nGccConstructor = ref 0
235let nGccEmptyStruct = ref 0
236let nGccNestedFunc = ref 0
237
238let nGccMisc = ref 0
239
240
241
242let nDefineHack = ref 0
243
244let nDefineConstant = ref 0
245let nDefineStmt = ref 0
246let nDefineExpr = ref 0
247(* both below require some heuristic support *)
248let nDefineWhile0 = ref 0
249let nDefineInit = ref 0
250
251let nDefineOther = ref 0
252
253let nUndef = ref 0
254let nPragmaAndCo = ref 0
255
256(* let nDirectiveTop = ref 0 *)
257let nDirectiveStmt = ref 0
258let nDirectiveStruct = ref 0
259let nDirectiveInitializer = ref 0
260
261
262(* from standard.h *)
263let nMacroHint = ref 0
264let nMacroExpand = ref 0
265
266let nNotParsedCorrectly = ref 0
267
ae4735db 268let assoc_stat_number =
485bce71
C
269 [
270 "nTypedefInfer", nTypedefInfer;
271
272 "nIteratorHeuristic", nIteratorHeuristic;
273
274 "nMacroTopDecl", nMacroTopDecl;
275 "nMacroStructDecl", nMacroStructDecl;
276 "nMacroDecl", nMacroDecl;
277 "nMacroStmt", nMacroStmt;
278 "nMacroString", nMacroString;
279 "nMacroHigherOrder", nMacroHigherOrder;
280 "nMacroAttribute", nMacroAttribute;
281
282 "nMacrohigherTypeGrammar", nMacrohigherTypeGrammar;
283
284 "nIfdefTop", nIfdefTop;
285 "nIfdefStmt", nIfdefStmt;
286 "nIfdefStruct", nIfdefStruct;
287 "nIfdefInitializer", nIfdefInitializer;
288
289 "nIfdefFunheader", nIfdefFunheader;
290 "nIfdefZero", nIfdefZero;
291 "nIfdefVersion", nIfdefVersion;
292 "nIfdefExprPassing", nIfdefExprPassing;
293 "nIfdefPassing", nIfdefPassing;
294
295 "nIncludePassing", nIncludePassing;
296 "nDefinePassing", nDefinePassing;
3a314143 297 "nUndefPassing", nUndefPassing;
485bce71
C
298
299 "nMacroExpand", nMacroExpand;
300 "nMacroHint", nMacroHint;
301
302
303 "nGccTypeof", nGccTypeof;
304 "nGccLongLong", nGccLongLong;
305 "nGccAsm", nGccAsm;
306 "nGccInline", nGccInline;
307 "nGccAttribute", nGccAttribute;
308 "nGccCaseRange", nGccCaseRange;
309 "nGccMixDecl", nGccMixDecl;
310 "nGccDesignator", nGccDesignator;
311 "nGccStmtExpr", nGccStmtExpr;
312 "nGccConstructor", nGccConstructor;
313 "nGccEmptyStruct", nGccEmptyStruct;
314 "nGccNestedFunc", nGccNestedFunc;
315
316 "nGccMisc", nGccMisc;
317
318
319 "nDefineHack", nDefineHack;
320
321 "nDefineConstant", nDefineConstant;
322 "nDefineStmt", nDefineStmt;
323 "nDefineExpr", nDefineExpr;
324 "nDefineInit", nDefineInit;
325 "nDefineOther", nDefineOther;
326
327 "nUndef", nUndef;
328 "nPragmaAndCo", nPragmaAndCo;
329
330 "nDirectiveStmt", nDirectiveStmt;
331 "nDirectiveStruct", nDirectiveStruct;
332 "nDirectiveInitializer", nDirectiveInitializer;
333
334 "nNotParsedCorrectly", nNotParsedCorrectly;
335
336
337 (* less *)
338 "nIncludeGrammar", nIncludeGrammar;
339 "nIncludeHack", nIncludeHack;
340
341 "nIteratorGrammar", nIteratorGrammar;
342 ]
343
ae4735db
C
344let print_stat_numbers () =
345 assoc_stat_number +> List.iter (fun (k, vref) ->
485bce71
C
346 pr2 (spf "%-30s -> %d" k !vref);
347 )