Release coccinelle-0.1.8
[bpt/coccinelle.git] / parsing_c / test_parsing_c.ml
CommitLineData
34e49164
C
1open Common
2
91eba41f
C
3open Ast_c
4
34e49164
C
5let score_path = "/home/pad/c-yacfe/tmp"
6
7let tmpfile = "/tmp/output.c"
8
708f4980 9module Ast_to_flow = Control_flow_c_build
91eba41f 10
34e49164
C
11(*****************************************************************************)
12(* Subsystem testing *)
13(*****************************************************************************)
14
15let test_tokens_c file =
16 if not (file =~ ".*\\.c")
17 then pr2 "warning: seems not a .c file";
18
19 Flag_parsing_c.debug_lexer := true;
20 Flag_parsing_c.verbose_lexing := true;
21 Flag_parsing_c.verbose_parsing := true;
22
23 Parse_c.tokens file +> List.iter (fun x -> pr2_gen x);
24 ()
25
26
27
28(* ---------------------------------------------------------------------- *)
29let test_parse_gen xs ext =
30
31 Flag_parsing_c.debug_typedef := true;
32 Flag_parsing_c.debug_cpp := true;
33 Flag_parsing_c.debug_etdt := false;
34 Flag_parsing_c.filter_msg := true;
35
36 let dirname_opt =
37 match xs with
38 | [x] when is_directory x -> Some x
39 | _ -> None
40 in
41
42 (* old:
43 let xs = if !Flag.dir then
44 process_output_to_list ("find " ^ x ^" -name \"*.c\"") else x::xs in
45 *)
485bce71 46 let fullxs = Common.files_of_dir_or_files_no_vcs ext xs in
34e49164
C
47
48 let stat_list = ref [] in
49 let newscore = Common.empty_score () in
50
485bce71 51 Common.check_stack_nbfiles (List.length fullxs);
34e49164
C
52
53 fullxs +> List.iter (fun file ->
54 if not (file =~ (".*\\."^ext))
55 then pr2 ("warning: seems not a ."^ext^" file");
56
57
58 pr2 "";
59 pr2 ("PARSING: " ^ file);
60
61 let (xs, stat) = Parse_c.parse_print_error_heuristic file in
62 xs +> List.iter (fun (ast, (s, toks)) ->
63 Parse_c.print_commentized toks
64 );
65
66 Common.push2 stat stat_list;
67 let s =
68 sprintf "bad = %d, timeout = %B"
485bce71 69 stat.Parsing_stat.bad stat.Parsing_stat.have_timeout
34e49164 70 in
b1b2de81 71 if stat.Parsing_stat.bad =|= 0 && not stat.Parsing_stat.have_timeout
34e49164
C
72 then Hashtbl.add newscore file (Common.Ok)
73 else Hashtbl.add newscore file (Common.Pb s)
74 );
75
34e49164 76 dirname_opt +> Common.do_option (fun dirname ->
91eba41f 77 pr2_xxxxxxxxxxxxxxxxx();
34e49164 78 pr2 "regression testing information";
91eba41f 79 pr2_xxxxxxxxxxxxxxxxx();
34e49164
C
80 let str = Str.global_replace (Str.regexp "/") "__" dirname in
81 let def = if !Flag_parsing_c.filter_define_error then "_def_" else "" in
b1b2de81 82 let ext = if ext =$= "c" then "" else ext in
34e49164
C
83 Common.regression_testing newscore
84 (Filename.concat score_path
85 ("score_parsing__" ^str ^ def ^ ext ^ ".marshalled"))
708f4980
C
86 );
87
88 if not (null !stat_list)
89 then begin
90 Parsing_stat.print_recurring_problematic_tokens !stat_list;
91 Parsing_stat.print_parsing_stat_list !stat_list;
92 end;
93 ()
34e49164
C
94
95
96let test_parse_c xs =
97 test_parse_gen xs "c"
98let test_parse_h xs =
99 test_parse_gen xs "h"
100let test_parse_ch xs =
101 test_parse_gen xs "[ch]"
102
103
708f4980
C
104(* ---------------------------------------------------------------------- *)
105
106let test_parse xs =
107
108 Flag_parsing_c.filter_msg_define_error := true;
109 Flag_parsing_c.filter_define_error := true;
110 Flag_parsing_c.verbose_lexing := false;
111 Flag_parsing_c.verbose_parsing := false;
112
113 let dirname_opt =
114 match xs with
115 | [x] when is_directory x -> Some x
116 | _ -> None
117 in
118 dirname_opt +> Common.do_option (fun dir ->
119
120 let ext = "h" in
121 let fullxs = Common.files_of_dir_or_files_no_vcs ext [dir] in
122 fullxs +> List.iter (fun file ->
123 let xs = Parse_c.parse_cpp_define_file file in
124 xs +> List.iter (fun (x, def) ->
125 let (s, params, body) = def in
126 Hashtbl.replace !Parse_c._defs s (s, params, body);
127 );
128 );
129 );
130
131 let ext = "[ch]" in
132
133 let fullxs = Common.files_of_dir_or_files_no_vcs ext xs in
134
135 let stat_list = ref [] in
136 Common.check_stack_nbfiles (List.length fullxs);
137
138 fullxs +> List.iter (fun file ->
139 if not (file =~ (".*\\."^ext))
140 then pr2 ("warning: seems not a ."^ext^" file");
34e49164 141
708f4980
C
142 pr2 "";
143 pr2 ("PARSING: " ^ file);
144
145 let (xs, stat) = Parse_c.parse_print_error_heuristic file in
146 xs +> List.iter (fun (ast, (s, toks)) ->
147 Parse_c.print_commentized toks
148 );
149
150 Common.push2 stat stat_list;
151 );
152
153 if not (null !stat_list)
154 then begin
155 Parsing_stat.print_recurring_problematic_tokens !stat_list;
156 Parsing_stat.print_parsing_stat_list !stat_list;
157 end;
158 ()
34e49164
C
159
160
161
162
163
164
165
166
167
168(* ---------------------------------------------------------------------- *)
169(* file can be "foo.c" or "foo.c:main" *)
170let test_cfg file =
34e49164
C
171 let (file, specific_func) =
172 if file =~ "\\(.*\\.c\\):\\(.*\\)"
173 then
174 let (a,b) = matched2 file in
175 a, Some b
176 else
177 file, None
178 in
179
180 if not (file =~ ".*\\.c")
181 then pr2 "warning: seems not a .c file";
182
183 let (program, _stat) = Parse_c.parse_print_error_heuristic file in
184
185 program +> List.iter (fun (e,_) ->
186 let toprocess =
187 match specific_func, e with
188 | None, _ -> true
485bce71 189 | Some s, Ast_c.Definition (defbis,_) ->
b1b2de81 190 s =$= Ast_c.str_of_name (defbis.Ast_c.f_name)
34e49164
C
191 | _, _ -> false
192 in
193
194 if toprocess
195 then
196 (* old: Flow_to_ast.test !Flag.show_flow def *)
197 (try
198 let flow = Ast_to_flow.ast_to_control_flow e in
199 flow +> do_option (fun flow ->
200 Ast_to_flow.deadcode_detection flow;
201 let flow = Ast_to_flow.annotate_loop_nodes flow in
202
203 let flow' =
204(*
205 if !Flag_cocci.show_before_fixed_flow
206 then flow
207 else Ctlcocci_integration.fix_flow_ctl flow
208*)
209 flow
210 in
485bce71
C
211 let filename = Filename.temp_file "output" ".dot" in
212 Ograph_extended.print_ograph_mutable flow' (filename) true
34e49164
C
213 )
214 with Ast_to_flow.Error (x) -> Ast_to_flow.report_error x
215 )
216 )
217
218
219
91eba41f
C
220let test_cfg_ifdef file =
221 let (ast2, _stat) = Parse_c.parse_print_error_heuristic file in
222 let ast = Parse_c.program_of_program2 ast2 in
223
224 let ast = Cpp_ast_c.cpp_ifdef_statementize ast in
225
226 ast +> List.iter (fun e ->
227 (try
228 let flow = Ast_to_flow.ast_to_control_flow e in
229 flow +> do_option (fun flow ->
230 Ast_to_flow.deadcode_detection flow;
231 let flow = Ast_to_flow.annotate_loop_nodes flow in
232 Ograph_extended.print_ograph_mutable flow ("/tmp/output.dot") true
233 )
234 with Ast_to_flow.Error (x) -> Ast_to_flow.report_error x
235 )
236 )
237
34e49164
C
238(* ---------------------------------------------------------------------- *)
239let test_parse_unparse infile =
240 if not (infile =~ ".*\\.c")
241 then pr2 "warning: seems not a .c file";
242
34e49164
C
243 let (program2, _stat) = Parse_c.parse_print_error_heuristic infile in
244 let program2_with_ppmethod =
485bce71 245 program2 +> List.map (fun x -> x, Unparse_c.PPnormal)
34e49164 246 in
485bce71 247 Unparse_c.pp_program program2_with_ppmethod tmpfile;
34e49164
C
248 Common.command2 ("cat " ^ tmpfile);
249 (* if want see diff of space => no -b -B *)
250 Common.command2 (spf "diff -u -p %s %s" infile tmpfile);
251 (* +> Transformation.test_simple_trans1;*)
34e49164
C
252 ()
253
254
255
256
257let test_type_c infile =
258 if not (infile =~ ".*\\.c")
259 then pr2 "warning: seems not a .c file";
260
261 Flag_parsing_c.pretty_print_type_info := true;
262
263 let (program2, _stat) = Parse_c.parse_print_error_heuristic infile in
264 let _program2 =
265 program2
266 +> Common.unzip
267 +> (fun (program, infos) ->
91eba41f 268 Type_annoter_c.annotate_program !Type_annoter_c.initial_env
34e49164
C
269 program +> List.map fst,
270 infos
271 )
272 +> Common.uncurry Common.zip
273 in
34e49164 274 let program2_with_ppmethod =
485bce71 275 program2 +> List.map (fun x -> x, Unparse_c.PPnormal)
34e49164 276 in
485bce71 277 Unparse_c.pp_program program2_with_ppmethod tmpfile;
34e49164
C
278 Common.command2 ("cat " ^ tmpfile);
279 ();;
280
281
0708f913
C
282(* ---------------------------------------------------------------------- *)
283(* ex: demos/platform_ifdef.c *)
284let test_comment_annotater infile =
285 let (program2, _stat) = Parse_c.parse_print_error_heuristic infile in
286 let asts = program2 +> List.map (fun (ast,_) -> ast) in
287 let toks = program2 +> List.map (fun (ast, (s, toks)) -> toks) +>
288 List.flatten in
289
290 Flag_parsing_c.pretty_print_comment_info := true;
291
292 pr2 "pretty print, before comment annotation: --->";
293 Common.adjust_pp_with_indent (fun () ->
294 asts +> List.iter (fun ast ->
295 Pretty_print_c.pp_toplevel_simple ast;
296 );
297 );
298
299 let _ = Comment_annotater_c.annotate_program toks asts in
300
301 Common.adjust_pp_with_indent (fun () ->
302 pr2 "pretty print, after comment annotation: --->";
303 asts +> List.iter (fun ast ->
304 Pretty_print_c.pp_toplevel_simple ast;
305 );
306 );
307
308
309 ()
310
311
34e49164
C
312(* ---------------------------------------------------------------------- *)
313(* used by generic_makefile now *)
314let test_compare_c file1 file2 =
315 let (correct, diffxs) = Compare_c.compare_default file1 file2 in
316 let res = Compare_c.compare_result_to_bool correct in
317 if res
318 then raise (Common.UnixExit 0)
319 else raise (Common.UnixExit (-1))
320
321
322let test_compare_c_hardcoded () =
323 Compare_c.compare_default
324 "tests/compare1.c"
325 "tests/compare2.c"
326 (*
327 "tests/equal_modulo1.c"
328 "tests/equal_modulo2.c"
329 *)
330 +> Compare_c.compare_result_to_string
331 +> pr2
332
333
334
91eba41f
C
335(* ---------------------------------------------------------------------- *)
336let test_attributes file =
337 let (ast2, _stat) = Parse_c.parse_c_and_cpp file in
338 let ast = Parse_c.program_of_program2 ast2 in
339
340 Visitor_c.vk_program { Visitor_c.default_visitor_c with
341 Visitor_c.kdef = (fun (k, bigf) (defbis, ii) ->
342 let sattr = Ast_c.s_of_attr defbis.f_attr in
b1b2de81 343 pr2 (spf "%-30s: %s" (Ast_c.str_of_name (defbis.f_name)) sattr);
91eba41f
C
344 );
345 Visitor_c.kdecl = (fun (k, bigf) decl ->
346 match decl with
347 | DeclList (xs, ii) ->
348 xs +> List.iter (fun (onedecl, iicomma) ->
349
350 let sattr = Ast_c.s_of_attr onedecl.v_attr in
351 let idname =
352 match onedecl.v_namei with
b1b2de81 353 | Some (name, ini) -> Ast_c.str_of_name name
91eba41f
C
354 | None -> "novar"
355 in
356 pr2 (spf "%-30s: %s" idname sattr);
357 );
358 | _ -> ()
359
360 );
361 } ast;
362 ()
363
364
365let cpp_options () = [
366 Cpp_ast_c.I "/home/yyzhou/pad/linux/include";
367] ++
368 Cpp_ast_c.cpp_option_of_cmdline
369 (!Flag_parsing_c.cpp_i_opts,!Flag_parsing_c.cpp_d_opts)
370
371let test_cpp file =
372 let (ast2, _stat) = Parse_c.parse_c_and_cpp file in
373 let dirname = Filename.dirname file in
374 let ast = Parse_c.program_of_program2 ast2 in
375 let _ast' = Cpp_ast_c.cpp_expand_include (cpp_options()) dirname ast in
376
377 ()
378
379
380
708f4980
C
381let extract_macros ~selection x =
382 (* CONFIG [ch] ? also do for .c ? maybe less needed now that I
383 * add local_macros.
384 *)
385
386 let ext = "h" in
387 let fullxs = Common.files_of_dir_or_files_no_vcs ext [x] in
388 fullxs +> List.iter (fun file ->
389
390 pr ("/* PARSING: " ^ file ^ " */");
391 let xs = Parse_c.parse_cpp_define_file file in
392 xs +> List.iter (fun (x, def) ->
393 let (s, params, body) = def in
394 assert(s = x);
395 (match params, body with
396 | Cpp_token_c.NoParam, Cpp_token_c.DefineBody [Parser_c.TInt _]
397 | Cpp_token_c.NoParam, Cpp_token_c.DefineBody [] ->
398 ()
399 | _ ->
400
401 let s1 =
402 match params with
403 | Cpp_token_c.NoParam -> spf "#define %s " s
404 | Cpp_token_c.Params xs ->
405 spf "#define %s(%s) "
406 s (Common.join "," xs)
407 in
408 let s2, bodytoks =
409 match body with
410 | Cpp_token_c.DefineHint _ ->
411 failwith "weird, hint in regular header file"
412 | Cpp_token_c.DefineBody xs ->
413 Common.join " " (xs +> List.map Token_helpers.str_of_tok),
414 xs
415 in
416
417 let print =
418 match () with
419 | () when s ==~ Parsing_hacks.regexp_annot -> true
420 | () when List.exists (function
421 | Parser_c.Tattribute _ -> true
422 | _ -> false) bodytoks -> true
423 | () -> false
424 in
425 if print || not selection then pr (s1 ^ s2)
426 );
427 );
428 );
429 ()
430
431
91eba41f 432
34e49164
C
433(* ---------------------------------------------------------------------- *)
434let test_xxx a =
435 ()
436
437(*
438 ignore(Parse_c.parse_cpp_define_file "standard.h")
439 pr2 "pr2";
440 pr "pr"
441
442 Format.print_newline();
443 Format.printf "@[<v 5>--@,--@,@[<v 5>--@,--@,@]--@,--@,@]";
444 Format.print_newline();
445 Format.printf "@[<v>(---@[<v>(---@[<v>(---@,)@]@,)@]@,)@]"
446*)
447
448
449
450(*****************************************************************************)
451(* Main entry for Arg *)
452(*****************************************************************************)
453
454let actions () = [
455 "-tokens_c", " <file>",
456 Common.mk_action_1_arg test_tokens_c;
457 "-parse_c", " <file or dir>",
458 Common.mk_action_n_arg test_parse_c;
459 "-parse_h", " <file or dir>",
460 Common.mk_action_n_arg test_parse_h;
461 "-parse_ch", " <file or dir>",
462 Common.mk_action_n_arg test_parse_ch;
463
708f4980
C
464 "-parse", " <file or dir>",
465 Common.mk_action_n_arg test_parse;
466
34e49164
C
467 "-show_flow", " <file or file:function>",
468 Common.mk_action_1_arg test_cfg;
469 "-control_flow", " <file or file:function>",
470 Common.mk_action_1_arg test_cfg;
91eba41f
C
471 "-test_cfg_ifdef", " <file>",
472 Common.mk_action_1_arg test_cfg_ifdef;
34e49164
C
473 "-parse_unparse", " <file>",
474 Common.mk_action_1_arg test_parse_unparse;
475 "-type_c", " <file>",
476 Common.mk_action_1_arg test_type_c;
477 "-compare_c", " <file1> <file2>",
478 Common.mk_action_2_arg test_compare_c (* result is in unix code *);
0708f913
C
479 "-comment_annotater_c", " <file>",
480 Common.mk_action_1_arg test_comment_annotater;
34e49164
C
481
482 "-compare_c_hardcoded", " ",
483 Common.mk_action_0_arg test_compare_c_hardcoded;
484
91eba41f
C
485 "-test_attributes", " <file>",
486 Common.mk_action_1_arg test_attributes;
487 "-test_cpp", " <file>",
488 Common.mk_action_1_arg test_cpp;
489
708f4980
C
490 "-extract_macros", " <file or dir>",
491 Common.mk_action_1_arg (extract_macros ~selection:false) ;
492
493 "-extract_macros_select", " <file or dir>",
494 Common.mk_action_1_arg (extract_macros ~selection:true);
91eba41f
C
495
496
34e49164
C
497 "-xxx", " <file1> <>",
498 Common.mk_action_n_arg test_xxx;
499]
500