Coccinelle release-1.0.0-rc11
[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
ae4735db 7let tmpfile = "/tmp/output.c"
34e49164 8
708f4980 9module Ast_to_flow = Control_flow_c_build
91eba41f 10
34e49164
C
11(*****************************************************************************)
12(* Subsystem testing *)
13(*****************************************************************************)
14
ae4735db
C
15let test_tokens_c file =
16 if not (file =~ ".*\\.c")
34e49164
C
17 then pr2 "warning: seems not a .c file";
18
ae4735db 19 Flag_parsing_c.debug_lexer := true;
34e49164
C
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 ()
ae4735db 25
34e49164
C
26
27
28(* ---------------------------------------------------------------------- *)
ae4735db
C
29let test_parse_gen xs ext =
30
34e49164
C
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
413ffc02 36 (*let dirname_opt =
34e49164
C
37 match xs with
38 | [x] when is_directory x -> Some x
39 | _ -> None
413ffc02 40 in*)
34e49164
C
41
42 (* old:
ae4735db 43 let xs = if !Flag.dir then
34e49164
C
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 52
ae4735db 53 fullxs +> List.iter (fun file ->
34e49164
C
54 if not (file =~ (".*\\."^ext))
55 then pr2 ("warning: seems not a ."^ext^" file");
56
57
58 pr2 "";
59 pr2 ("PARSING: " ^ file);
60
978fd7e5 61 let (xs, stat) = Parse_c.parse_c_and_cpp file in
ae4735db 62 xs +> List.iter (fun (ast, (s, toks)) ->
34e49164
C
63 Parse_c.print_commentized toks
64 );
65
66 Common.push2 stat stat_list;
ae4735db
C
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 );
951c7801
C
75
76(* uses an explicit path; to fix
ae4735db 77 dirname_opt +> Common.do_option (fun dirname ->
91eba41f 78 pr2_xxxxxxxxxxxxxxxxx();
34e49164 79 pr2 "regression testing information";
91eba41f 80 pr2_xxxxxxxxxxxxxxxxx();
34e49164
C
81 let str = Str.global_replace (Str.regexp "/") "__" dirname in
82 let def = if !Flag_parsing_c.filter_define_error then "_def_" else "" in
b1b2de81 83 let ext = if ext =$= "c" then "" else ext in
951c7801
C
84 let filename = "score_parsing__" ^str ^ def ^ ext ^ ".marshalled" in
85 if Sys.file_exists filename
86 then
ae4735db 87 Common.regression_testing newscore
951c7801
C
88 (Filename.concat score_path
89 ("score_parsing__" ^str ^ def ^ ext ^ ".marshalled"))
708f4980 90 );
951c7801 91*)
708f4980 92
ae4735db
C
93 if not (null !stat_list)
94 then begin
708f4980
C
95 Parsing_stat.print_recurring_problematic_tokens !stat_list;
96 Parsing_stat.print_parsing_stat_list !stat_list;
97 end;
98 ()
34e49164
C
99
100
fc1ad971 101let test_parse_c xs =
34e49164 102 test_parse_gen xs "c"
ae4735db 103let test_parse_h xs =
34e49164 104 test_parse_gen xs "h"
ae4735db 105let test_parse_ch xs =
34e49164
C
106 test_parse_gen xs "[ch]"
107
ae4735db 108(* could use a simpler parser than heavy parse_c_and_cpp here as there
978fd7e5
C
109 * is no more cpp stuff in the .i files
110 *)
ae4735db 111let test_parse_i xs =
978fd7e5 112 test_parse_gen xs "i"
34e49164
C
113
114
115
116
117
118
119
120(* ---------------------------------------------------------------------- *)
121(* file can be "foo.c" or "foo.c:main" *)
c491d8ee
C
122(* local function that is parameterized by whether to launch gv *)
123let local_test_cfg launchgv file =
ae4735db 124 let (file, specific_func) =
34e49164 125 if file =~ "\\(.*\\.c\\):\\(.*\\)"
ae4735db
C
126 then
127 let (a,b) = matched2 file in
34e49164 128 a, Some b
ae4735db 129 else
34e49164
C
130 file, None
131 in
132
ae4735db 133 if not (file =~ ".*\\.c")
34e49164
C
134 then pr2 "warning: seems not a .c file";
135
978fd7e5 136 let (program, _stat) = Parse_c.parse_c_and_cpp file in
34e49164 137
ae4735db
C
138 program +> List.iter (fun (e,_) ->
139 let toprocess =
34e49164 140 match specific_func, e with
4dfbc1c2
C
141 | None, Ast_c.Definition (defbis,_) ->
142 Some (Ast_c.str_of_name (defbis.Ast_c.f_name))
ae4735db 143 | Some s, Ast_c.Definition (defbis,_) ->
4dfbc1c2
C
144 let nm = Ast_c.str_of_name (defbis.Ast_c.f_name) in
145 if s =$= nm then Some nm else None
146 | _, _ -> None
34e49164 147 in
ae4735db 148
4dfbc1c2
C
149 match toprocess with
150 None -> ()
151 | Some fn -> (* old: Flow_to_ast.test !Flag.show_flow def *)
152 try
34e49164 153 let flow = Ast_to_flow.ast_to_control_flow e in
ae4735db 154 flow +> do_option (fun flow ->
34e49164
C
155 Ast_to_flow.deadcode_detection flow;
156 let flow = Ast_to_flow.annotate_loop_nodes flow in
157
ae4735db 158 let flow' =
34e49164 159(*
ae4735db 160 if !Flag_cocci.show_before_fixed_flow
34e49164
C
161 then flow
162 else Ctlcocci_integration.fix_flow_ctl flow
163*)
164 flow
165 in
4dfbc1c2
C
166 let filename =
167 if launchgv
168 then Filename.temp_file "output" ".dot"
169 else
170 let fl = Filename.chop_extension (Filename.basename file) in
171 fl^":"^fn^".dot" in
c491d8ee 172 Ograph_extended.print_ograph_mutable flow' (filename) launchgv
34e49164
C
173 )
174 with Ast_to_flow.Error (x) -> Ast_to_flow.report_error x
175 )
34e49164 176
c491d8ee
C
177let test_cfg = local_test_cfg true
178
34e49164
C
179
180
ae4735db 181let test_cfg_ifdef file =
978fd7e5 182 let (ast2, _stat) = Parse_c.parse_c_and_cpp file in
91eba41f
C
183 let ast = Parse_c.program_of_program2 ast2 in
184
185 let ast = Cpp_ast_c.cpp_ifdef_statementize ast in
186
ae4735db
C
187 ast +> List.iter (fun e ->
188 (try
91eba41f 189 let flow = Ast_to_flow.ast_to_control_flow e in
ae4735db 190 flow +> do_option (fun flow ->
91eba41f
C
191 Ast_to_flow.deadcode_detection flow;
192 let flow = Ast_to_flow.annotate_loop_nodes flow in
193 Ograph_extended.print_ograph_mutable flow ("/tmp/output.dot") true
194 )
195 with Ast_to_flow.Error (x) -> Ast_to_flow.report_error x
196 )
197 )
198
34e49164 199(* ---------------------------------------------------------------------- *)
ae4735db
C
200let test_parse_unparse infile =
201 if not (infile =~ ".*\\.c")
34e49164
C
202 then pr2 "warning: seems not a .c file";
203
978fd7e5 204 let (program2, _stat) = Parse_c.parse_c_and_cpp infile in
ae4735db 205 let program2_with_ppmethod =
485bce71 206 program2 +> List.map (fun x -> x, Unparse_c.PPnormal)
34e49164 207 in
485bce71 208 Unparse_c.pp_program program2_with_ppmethod tmpfile;
34e49164
C
209 Common.command2 ("cat " ^ tmpfile);
210 (* if want see diff of space => no -b -B *)
211 Common.command2 (spf "diff -u -p %s %s" infile tmpfile);
212 (* +> Transformation.test_simple_trans1;*)
34e49164
C
213 ()
214
215
1eddfd50 216(*
ae4735db 217let parse_and_print_sexp file =
978fd7e5
C
218 let (ast2,_stat) = Parse_c.parse_c_and_cpp file in
219 let ast = Parse_c.program_of_program2 ast2 in
ae4735db 220 let _ast =
978fd7e5
C
221 Type_annoter_c.annotate_program !Type_annoter_c.initial_env ast
222 in
223
224 (*
225 let sexp = Sexp_ast_c.sexp_of_program ast in
226 let s = Sexp.to_string_hum sexp in
227 *)
228 Sexp_ast_c.show_info := false;
229 let s = Sexp_ast_c.string_of_program ast in
230 pr2 s;
231 ()
1eddfd50 232*)
34e49164
C
233
234
ae4735db
C
235let test_type_c infile =
236 if not (infile =~ ".*\\.c")
34e49164
C
237 then pr2 "warning: seems not a .c file";
238
239 Flag_parsing_c.pretty_print_type_info := true;
240
978fd7e5 241 let (program2, _stat) = Parse_c.parse_c_and_cpp infile in
34e49164 242 let _program2 =
ae4735db
C
243 program2
244 +> Common.unzip
245 +> (fun (program, infos) ->
246 Type_annoter_c.annotate_program !Type_annoter_c.initial_env
34e49164
C
247 program +> List.map fst,
248 infos
249 )
250 +> Common.uncurry Common.zip
251 in
ae4735db 252 let program2_with_ppmethod =
485bce71 253 program2 +> List.map (fun x -> x, Unparse_c.PPnormal)
34e49164 254 in
485bce71 255 Unparse_c.pp_program program2_with_ppmethod tmpfile;
34e49164
C
256 Common.command2 ("cat " ^ tmpfile);
257 ();;
258
259
0708f913
C
260(* ---------------------------------------------------------------------- *)
261(* ex: demos/platform_ifdef.c *)
ae4735db 262let test_comment_annotater infile =
978fd7e5 263 let (program2, _stat) = Parse_c.parse_c_and_cpp infile in
0708f913 264 let asts = program2 +> List.map (fun (ast,_) -> ast) in
ae4735db 265 let toks = program2 +> List.map (fun (ast, (s, toks)) -> toks) +>
0708f913
C
266 List.flatten in
267
268 Flag_parsing_c.pretty_print_comment_info := true;
269
270 pr2 "pretty print, before comment annotation: --->";
ae4735db
C
271 Common.adjust_pp_with_indent (fun () ->
272 asts +> List.iter (fun ast ->
0708f913
C
273 Pretty_print_c.pp_toplevel_simple ast;
274 );
275 );
276
277 let _ = Comment_annotater_c.annotate_program toks asts in
278
ae4735db 279 Common.adjust_pp_with_indent (fun () ->
0708f913 280 pr2 "pretty print, after comment annotation: --->";
ae4735db 281 asts +> List.iter (fun ast ->
0708f913
C
282 Pretty_print_c.pp_toplevel_simple ast;
283 );
284 );
285
286
287 ()
ae4735db
C
288
289
34e49164
C
290(* ---------------------------------------------------------------------- *)
291(* used by generic_makefile now *)
ae4735db 292let test_compare_c file1 file2 =
34e49164
C
293 let (correct, diffxs) = Compare_c.compare_default file1 file2 in
294 let res = Compare_c.compare_result_to_bool correct in
ae4735db 295 if res
34e49164
C
296 then raise (Common.UnixExit 0)
297 else raise (Common.UnixExit (-1))
298
299
300let test_compare_c_hardcoded () =
ae4735db
C
301 Compare_c.compare_default
302 "tests/compare1.c"
303 "tests/compare2.c"
34e49164 304 (*
ae4735db
C
305 "tests/equal_modulo1.c"
306 "tests/equal_modulo2.c"
34e49164 307 *)
ae4735db 308 +> Compare_c.compare_result_to_string
34e49164
C
309 +> pr2
310
311
312
91eba41f 313(* ---------------------------------------------------------------------- *)
ae4735db 314let test_attributes file =
91eba41f
C
315 let (ast2, _stat) = Parse_c.parse_c_and_cpp file in
316 let ast = Parse_c.program_of_program2 ast2 in
317
318 Visitor_c.vk_program { Visitor_c.default_visitor_c with
ae4735db 319 Visitor_c.kdef = (fun (k, bigf) (defbis, ii) ->
91eba41f 320 let sattr = Ast_c.s_of_attr defbis.f_attr in
b1b2de81 321 pr2 (spf "%-30s: %s" (Ast_c.str_of_name (defbis.f_name)) sattr);
91eba41f 322 );
ae4735db 323 Visitor_c.kdecl = (fun (k, bigf) decl ->
91eba41f 324 match decl with
ae4735db
C
325 | DeclList (xs, ii) ->
326 xs +> List.iter (fun (onedecl, iicomma) ->
327
91eba41f 328 let sattr = Ast_c.s_of_attr onedecl.v_attr in
ae4735db 329 let idname =
91eba41f 330 match onedecl.v_namei with
b1b2de81 331 | Some (name, ini) -> Ast_c.str_of_name name
91eba41f
C
332 | None -> "novar"
333 in
334 pr2 (spf "%-30s: %s" idname sattr);
335 );
336 | _ -> ()
ae4735db 337
91eba41f
C
338 );
339 } ast;
340 ()
341
342
343let cpp_options () = [
344 Cpp_ast_c.I "/home/yyzhou/pad/linux/include";
ae4735db
C
345] ++
346 Cpp_ast_c.cpp_option_of_cmdline
91eba41f
C
347 (!Flag_parsing_c.cpp_i_opts,!Flag_parsing_c.cpp_d_opts)
348
ae4735db 349let test_cpp file =
91eba41f
C
350 let (ast2, _stat) = Parse_c.parse_c_and_cpp file in
351 let dirname = Filename.dirname file in
352 let ast = Parse_c.program_of_program2 ast2 in
978fd7e5
C
353 let ast = Cpp_ast_c.cpp_expand_include (cpp_options()) dirname ast in
354 let _ast = Cpp_ast_c.cpp_ifdef_statementize ast in
ae4735db
C
355
356
91eba41f
C
357 ()
358
359
360
ae4735db 361(* CONFIG [ch] ? also do for .c ? maybe less needed now that I
978fd7e5
C
362 * add local_macros.
363 *)
ae4735db
C
364let extract_macros ~selection dir =
365 let ext = "h" in
978fd7e5 366 let fullxs = Common.files_of_dir_or_files_no_vcs ext [dir] in
ae4735db
C
367 let macros_and_filename =
368 fullxs +> List.map (fun file ->
978fd7e5
C
369 pr2 (spf "processing: %s" file);
370 let xs = Parse_c.extract_macros file in
371 file, xs
372 )
373 in
374
ae4735db 375 let macros =
978fd7e5 376 if selection
ae4735db 377 then Cpp_analysis_c.extract_dangerous_macros macros_and_filename
978fd7e5
C
378 else macros_and_filename
379 in
ae4735db 380 macros +> List.iter (fun (file, defs) ->
708f4980 381 pr ("/* PARSING: " ^ file ^ " */");
ae4735db 382 defs +> List.iter (fun (s, def) ->
978fd7e5
C
383 let str = Cpp_token_c.string_of_define_def def in
384 pr str;
385 )
386 );
387 ()
388
389
ae4735db 390let test_parse xs =
978fd7e5
C
391
392 Flag_parsing_c.filter_msg_define_error := true;
393 Flag_parsing_c.filter_define_error := true;
394 Flag_parsing_c.verbose_lexing := false;
395 Flag_parsing_c.verbose_parsing := false;
396
ae4735db 397 let dirname_opt =
978fd7e5
C
398 match xs with
399 | [x] when is_directory x -> Some x
400 | _ -> None
401 in
ae4735db 402 dirname_opt +> Common.do_option (fun dir ->
978fd7e5 403
ae4735db 404 let ext = "h" in
978fd7e5
C
405 let fullxs = Common.files_of_dir_or_files_no_vcs ext [dir] in
406
ae4735db
C
407 let macros_and_filename =
408 fullxs +> List.map (fun file ->
978fd7e5
C
409 pr2 (spf "processing: %s" file);
410 let xs = Parse_c.extract_macros file in
411 file, xs
412 )
413 in
ae4735db
C
414 let macros =
415 Cpp_analysis_c.extract_dangerous_macros macros_and_filename
978fd7e5 416 in
ae4735db
C
417 macros +> List.iter (fun (file, xs) ->
418 xs +> List.iter (fun (x, def) ->
419 let (s, params, body) = def in
978fd7e5
C
420 let str = Cpp_token_c.string_of_define_def def in
421 pr str;
422 (* builtins ? *)
423 Hashtbl.replace !Parse_c._defs_builtins s (s, params, body);
708f4980
C
424 );
425 );
426 );
978fd7e5
C
427
428 let ext = "[ch]" in
429
430 let fullxs = Common.files_of_dir_or_files_no_vcs ext xs in
431
432 let stat_list = ref [] in
433 Common.check_stack_nbfiles (List.length fullxs);
434
ae4735db 435 fullxs +> List.iter (fun file ->
978fd7e5
C
436 if not (file =~ (".*\\."^ext))
437 then pr2 ("warning: seems not a ."^ext^" file");
438
439 pr2 "";
440 pr2 ("PARSING: " ^ file);
441
442 let (xs, stat) = Parse_c.parse_c_and_cpp file in
ae4735db 443 xs +> List.iter (fun (ast, (s, toks)) ->
978fd7e5
C
444 Parse_c.print_commentized toks
445 );
446
447 Common.push2 stat stat_list;
448 );
ae4735db
C
449
450 if not (null !stat_list)
451 then begin
978fd7e5
C
452 Parsing_stat.print_recurring_problematic_tokens !stat_list;
453 Parsing_stat.print_parsing_stat_list !stat_list;
454 end;
708f4980
C
455 ()
456
457
91eba41f 458
978fd7e5
C
459
460
461
462
463
34e49164 464(* ---------------------------------------------------------------------- *)
ae4735db 465let test_xxx a =
34e49164
C
466 ()
467
468(*
469 ignore(Parse_c.parse_cpp_define_file "standard.h")
470 pr2 "pr2";
471 pr "pr"
472
473 Format.print_newline();
474 Format.printf "@[<v 5>--@,--@,@[<v 5>--@,--@,@]--@,--@,@]";
475 Format.print_newline();
476 Format.printf "@[<v>(---@[<v>(---@[<v>(---@,)@]@,)@]@,)@]"
477*)
478
479
480
481(*****************************************************************************)
482(* Main entry for Arg *)
483(*****************************************************************************)
484
485let actions () = [
17ba0788 486 "--tokens-c", " <file>",
34e49164 487 Common.mk_action_1_arg test_tokens_c;
17ba0788 488 "--parse-c", " <file or dir>",
34e49164 489 Common.mk_action_n_arg test_parse_c;
17ba0788 490 "--parse-h", " <file or dir>",
34e49164 491 Common.mk_action_n_arg test_parse_h;
17ba0788 492 "--parse-ch", " <file or dir>",
34e49164 493 Common.mk_action_n_arg test_parse_ch;
17ba0788 494 "--parse-i", " <file or dir>",
978fd7e5 495 Common.mk_action_n_arg test_parse_i;
34e49164 496
17ba0788 497 "--parse", " <file or dir>",
708f4980
C
498 Common.mk_action_n_arg test_parse;
499
17ba0788 500 "--show-flow", " <file or file:function>",
c491d8ee 501 Common.mk_action_1_arg (local_test_cfg true);
17ba0788 502 "--control-flow", " <file or file:function>",
c491d8ee 503 Common.mk_action_1_arg (local_test_cfg true);
17ba0788 504 "--control-flow-to-file", " <file or file:function>",
c491d8ee 505 Common.mk_action_1_arg (local_test_cfg false);
17ba0788 506 "--test-cfg-ifdef", " <file>",
91eba41f 507 Common.mk_action_1_arg test_cfg_ifdef;
17ba0788 508 "--parse-unparse", " <file>",
34e49164 509 Common.mk_action_1_arg test_parse_unparse;
17ba0788 510(* "--parse-and-print-sexp", " <file>",
1eddfd50 511 Common.mk_action_1_arg parse_and_print_sexp;*)
17ba0788 512 "--type-c", " <file>",
34e49164 513 Common.mk_action_1_arg test_type_c;
17ba0788 514 "--compare-c", " <file1> <file2>",
34e49164 515 Common.mk_action_2_arg test_compare_c (* result is in unix code *);
17ba0788 516 "--comment-annotater-c", " <file>",
0708f913 517 Common.mk_action_1_arg test_comment_annotater;
34e49164 518
17ba0788 519 "--compare-c-hardcoded", " ",
34e49164
C
520 Common.mk_action_0_arg test_compare_c_hardcoded;
521
17ba0788 522 "--test-attributes", " <file>",
91eba41f 523 Common.mk_action_1_arg test_attributes;
17ba0788 524 "--test-cpp", " <file>",
91eba41f
C
525 Common.mk_action_1_arg test_cpp;
526
17ba0788 527 "--extract-macros", " <file or dir>",
708f4980
C
528 Common.mk_action_1_arg (extract_macros ~selection:false) ;
529
17ba0788 530 "--extract-macros-select", " <file or dir>",
708f4980 531 Common.mk_action_1_arg (extract_macros ~selection:true);
91eba41f
C
532
533
17ba0788 534 "--xxx", " <file1> <>",
34e49164
C
535 Common.mk_action_n_arg test_xxx;
536]
537