5 let score_path = "/home/pad/c-yacfe/tmp"
7 let tmpfile = "/tmp/output.c"
9 module Ast_to_flow
= Control_flow_c_build
11 (*****************************************************************************)
12 (* Subsystem testing *)
13 (*****************************************************************************)
15 let test_tokens_c file
=
16 if not
(file
=~
".*\\.c")
17 then pr2
"warning: seems not a .c file";
19 Flag_parsing_c.debug_lexer
:= true;
20 Flag_parsing_c.verbose_lexing
:= true;
21 Flag_parsing_c.verbose_parsing
:= true;
23 Parse_c.tokens file
+> List.iter
(fun x
-> pr2_gen x
);
28 (* ---------------------------------------------------------------------- *)
29 let test_parse_gen xs ext
=
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;
38 | [x] when is_directory x -> Some x
43 let xs = if !Flag.dir then
44 process_output_to_list ("find " ^ x ^" -name \"*.c\"") else x::xs in
46 let fullxs = Common.files_of_dir_or_files_no_vcs ext
xs in
48 let stat_list = ref [] in
49 let newscore = Common.empty_score
() in
51 Common.check_stack_nbfiles
(List.length
fullxs);
53 fullxs +> List.iter
(fun file
->
54 if not
(file
=~
(".*\\."^ext
))
55 then pr2
("warning: seems not a ."^ext^
" file");
59 pr2
("PARSING: " ^ file
);
61 let (xs, stat
) = Parse_c.parse_c_and_cpp file
in
62 xs +> List.iter
(fun (ast
, (s
, toks
)) ->
63 Parse_c.print_commentized toks
66 Common.push2 stat
stat_list;
68 sprintf
"bad = %d, timeout = %B"
69 stat
.Parsing_stat.bad stat
.Parsing_stat.have_timeout
71 if stat
.Parsing_stat.bad
=|= 0 && not stat
.Parsing_stat.have_timeout
72 then Hashtbl.add
newscore file
(Common.Ok
)
73 else Hashtbl.add
newscore file
(Common.Pb
s)
76 (* uses an explicit path; to fix
77 dirname_opt +> Common.do_option (fun dirname ->
78 pr2_xxxxxxxxxxxxxxxxx();
79 pr2 "regression testing information";
80 pr2_xxxxxxxxxxxxxxxxx();
81 let str = Str.global_replace (Str.regexp "/") "__" dirname in
82 let def = if !Flag_parsing_c.filter_define_error then "_def_" else "" in
83 let ext = if ext =$= "c" then "" else ext in
84 let filename = "score_parsing__" ^str ^ def ^ ext ^ ".marshalled" in
85 if Sys.file_exists filename
87 Common.regression_testing newscore
88 (Filename.concat score_path
89 ("score_parsing__" ^str ^ def ^ ext ^ ".marshalled"))
93 if not
(null
!stat_list)
95 Parsing_stat.print_recurring_problematic_tokens
!stat_list;
96 Parsing_stat.print_parsing_stat_list
!stat_list;
101 let test_parse_c xs =
102 test_parse_gen xs "c"
103 let test_parse_h xs =
104 test_parse_gen xs "h"
105 let test_parse_ch xs =
106 test_parse_gen xs "[ch]"
108 (* could use a simpler parser than heavy parse_c_and_cpp here as there
109 * is no more cpp stuff in the .i files
111 let test_parse_i xs =
112 test_parse_gen xs "i"
120 (* ---------------------------------------------------------------------- *)
121 (* file can be "foo.c" or "foo.c:main" *)
122 (* local function that is parameterized by whether to launch gv *)
123 let local_test_cfg launchgv file
=
124 let (file
, specific_func
) =
125 if file
=~
"\\(.*\\.c\\):\\(.*\\)"
127 let (a
,b
) = matched2 file
in
133 if not
(file
=~
".*\\.c")
134 then pr2
"warning: seems not a .c file";
136 let (program
, _stat
) = Parse_c.parse_c_and_cpp file
in
138 program
+> List.iter
(fun (e
,_
) ->
140 match specific_func
, e
with
141 | None
, Ast_c.Definition
(defbis
,_
) ->
142 Some
(Ast_c.str_of_name
(defbis
.Ast_c.f_name
))
143 | Some
s, Ast_c.Definition
(defbis
,_
) ->
144 let nm = Ast_c.str_of_name
(defbis
.Ast_c.f_name
) in
145 if s =$
= nm then Some
nm else None
151 | Some fn
-> (* old: Flow_to_ast.test !Flag.show_flow def *)
153 let flow = Ast_to_flow.ast_to_control_flow e
in
154 flow +> do_option
(fun flow ->
155 Ast_to_flow.deadcode_detection
flow;
156 let flow = Ast_to_flow.annotate_loop_nodes
flow in
160 if !Flag_cocci.show_before_fixed_flow
162 else Ctlcocci_integration.fix_flow_ctl flow
168 then Filename.temp_file
"output" ".dot"
170 let fl = Filename.chop_extension
(Filename.basename file
) in
172 Ograph_extended.print_ograph_mutable
flow'
(filename) launchgv
174 with Ast_to_flow.Error
(x
) -> Ast_to_flow.report_error x
177 let test_cfg = local_test_cfg true
181 let test_cfg_ifdef file
=
182 let (ast2
, _stat
) = Parse_c.parse_c_and_cpp file
in
183 let ast = Parse_c.program_of_program2 ast2
in
185 let ast = Cpp_ast_c.cpp_ifdef_statementize
ast in
187 ast +> List.iter
(fun e
->
189 let flow = Ast_to_flow.ast_to_control_flow e
in
190 flow +> do_option
(fun flow ->
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
195 with Ast_to_flow.Error
(x
) -> Ast_to_flow.report_error x
199 (* ---------------------------------------------------------------------- *)
200 let test_parse_unparse infile
=
201 if not
(infile
=~
".*\\.c")
202 then pr2
"warning: seems not a .c file";
204 let (program2
, _stat
) = Parse_c.parse_c_and_cpp infile
in
205 let program2_with_ppmethod =
206 program2
+> List.map
(fun x
-> x
, Unparse_c.PPnormal
)
208 Unparse_c.pp_program
program2_with_ppmethod tmpfile;
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;*)
217 let parse_and_print_sexp file =
218 let (ast2,_stat) = Parse_c.parse_c_and_cpp file in
219 let ast = Parse_c.program_of_program2 ast2 in
221 Type_annoter_c.annotate_program !Type_annoter_c.initial_env ast
225 let sexp = Sexp_ast_c.sexp_of_program ast in
226 let s = Sexp.to_string_hum sexp in
228 Sexp_ast_c.show_info
:= false;
229 let s = Sexp_ast_c.string_of_program
ast in
235 let test_type_c infile
=
236 if not
(infile
=~
".*\\.c")
237 then pr2
"warning: seems not a .c file";
239 Flag_parsing_c.pretty_print_type_info
:= true;
241 let (program2
, _stat
) = Parse_c.parse_c_and_cpp infile
in
245 +> (fun (program
, infos
) ->
246 Type_annoter_c.annotate_program
!Type_annoter_c.initial_env
247 program
+> List.map fst
,
250 +> Common.uncurry
Common.zip
252 let program2_with_ppmethod =
253 program2
+> List.map
(fun x
-> x
, Unparse_c.PPnormal
)
255 Unparse_c.pp_program
program2_with_ppmethod tmpfile;
256 Common.command2
("cat " ^
tmpfile);
260 (* ---------------------------------------------------------------------- *)
261 (* ex: demos/platform_ifdef.c *)
262 let test_comment_annotater infile
=
263 let (program2
, _stat
) = Parse_c.parse_c_and_cpp infile
in
264 let asts = program2
+> List.map
(fun (ast,_
) -> ast) in
265 let toks = program2
+> List.map
(fun (ast, (s, toks)) -> toks) +>
268 Flag_parsing_c.pretty_print_comment_info
:= true;
270 pr2
"pretty print, before comment annotation: --->";
271 Common.adjust_pp_with_indent
(fun () ->
272 asts +> List.iter
(fun ast ->
273 Pretty_print_c.pp_toplevel_simple
ast;
277 let _ = Comment_annotater_c.annotate_program
toks asts in
279 Common.adjust_pp_with_indent
(fun () ->
280 pr2
"pretty print, after comment annotation: --->";
281 asts +> List.iter
(fun ast ->
282 Pretty_print_c.pp_toplevel_simple
ast;
290 (* ---------------------------------------------------------------------- *)
291 (* used by generic_makefile now *)
292 let test_compare_c file1 file2
=
293 let (correct
, diffxs
) = Compare_c.compare_default file1 file2
in
294 let res = Compare_c.compare_result_to_bool correct
in
296 then raise
(Common.UnixExit
0)
297 else raise
(Common.UnixExit
(-1))
300 let test_compare_c_hardcoded () =
301 Compare_c.compare_default
305 "tests/equal_modulo1.c"
306 "tests/equal_modulo2.c"
308 +> Compare_c.compare_result_to_string
313 (* ---------------------------------------------------------------------- *)
314 let test_attributes file
=
315 let (ast2
, _stat
) = Parse_c.parse_c_and_cpp file
in
316 let ast = Parse_c.program_of_program2 ast2
in
318 Visitor_c.vk_program
{ Visitor_c.default_visitor_c
with
319 Visitor_c.kdef
= (fun (k
, bigf
) (defbis
, ii
) ->
320 let sattr = Ast_c.s_of_attr defbis
.f_attr
in
321 pr2
(spf
"%-30s: %s" (Ast_c.str_of_name
(defbis
.f_name
)) sattr);
323 Visitor_c.kdecl
= (fun (k
, bigf
) decl
->
325 | DeclList
(xs, ii
) ->
326 xs +> List.iter
(fun (onedecl
, iicomma
) ->
328 let sattr = Ast_c.s_of_attr onedecl
.v_attr
in
330 match onedecl
.v_namei
with
331 | Some
(name
, ini
) -> Ast_c.str_of_name name
334 pr2
(spf
"%-30s: %s" idname sattr);
343 let cpp_options () = [
344 Cpp_ast_c.I
"/home/yyzhou/pad/linux/include";
346 Cpp_ast_c.cpp_option_of_cmdline
347 (!Flag_parsing_c.cpp_i_opts
,!Flag_parsing_c.cpp_d_opts
)
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
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
361 (* CONFIG [ch] ? also do for .c ? maybe less needed now that I
364 let extract_macros ~selection dir
=
366 let fullxs = Common.files_of_dir_or_files_no_vcs
ext [dir
] in
367 let macros_and_filename =
368 fullxs +> List.map
(fun file
->
369 pr2
(spf
"processing: %s" file
);
370 let xs = Parse_c.extract_macros file
in
377 then Cpp_analysis_c.extract_dangerous_macros
macros_and_filename
378 else macros_and_filename
380 macros +> List.iter
(fun (file
, defs
) ->
381 pr
("/* PARSING: " ^ file ^
" */");
382 defs
+> List.iter
(fun (s, def) ->
383 let str = Cpp_token_c.string_of_define_def
def in
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;
399 | [x
] when is_directory x
-> Some x
402 dirname_opt +> Common.do_option
(fun dir
->
405 let fullxs = Common.files_of_dir_or_files_no_vcs
ext [dir
] in
407 let macros_and_filename =
408 fullxs +> List.map
(fun file
->
409 pr2
(spf
"processing: %s" file
);
410 let xs = Parse_c.extract_macros file
in
415 Cpp_analysis_c.extract_dangerous_macros
macros_and_filename
417 macros +> List.iter
(fun (file
, xs) ->
418 xs +> List.iter
(fun (x
, def) ->
419 let (s, params
, body
) = def in
420 let str = Cpp_token_c.string_of_define_def
def in
423 Hashtbl.replace
!Parse_c._defs_builtins
s (s, params
, body
);
430 let fullxs = Common.files_of_dir_or_files_no_vcs
ext xs in
432 let stat_list = ref [] in
433 Common.check_stack_nbfiles
(List.length
fullxs);
435 fullxs +> List.iter
(fun file
->
436 if not
(file
=~
(".*\\."^
ext))
437 then pr2
("warning: seems not a ."^
ext^
" file");
440 pr2
("PARSING: " ^ file
);
442 let (xs, stat
) = Parse_c.parse_c_and_cpp file
in
443 xs +> List.iter
(fun (ast, (s, toks)) ->
444 Parse_c.print_commentized
toks
447 Common.push2 stat
stat_list;
450 if not
(null
!stat_list)
452 Parsing_stat.print_recurring_problematic_tokens
!stat_list;
453 Parsing_stat.print_parsing_stat_list
!stat_list;
464 (* ---------------------------------------------------------------------- *)
469 ignore(Parse_c.parse_cpp_define_file "standard.h")
473 Format.print_newline();
474 Format.printf "@[<v 5>--@,--@,@[<v 5>--@,--@,@]--@,--@,@]";
475 Format.print_newline();
476 Format.printf "@[<v>(---@[<v>(---@[<v>(---@,)@]@,)@]@,)@]"
481 (*****************************************************************************)
482 (* Main entry for Arg *)
483 (*****************************************************************************)
486 "--tokens-c", " <file>",
487 Common.mk_action_1_arg
test_tokens_c;
488 "--parse-c", " <file or dir>",
489 Common.mk_action_n_arg
test_parse_c;
490 "--parse-h", " <file or dir>",
491 Common.mk_action_n_arg
test_parse_h;
492 "--parse-ch", " <file or dir>",
493 Common.mk_action_n_arg
test_parse_ch;
494 "--parse-i", " <file or dir>",
495 Common.mk_action_n_arg
test_parse_i;
497 "--parse", " <file or dir>",
498 Common.mk_action_n_arg
test_parse;
500 "--show-flow", " <file or file:function>",
501 Common.mk_action_1_arg
(local_test_cfg true);
502 "--control-flow", " <file or file:function>",
503 Common.mk_action_1_arg
(local_test_cfg true);
504 "--control-flow-to-file", " <file or file:function>",
505 Common.mk_action_1_arg
(local_test_cfg false);
506 "--test-cfg-ifdef", " <file>",
507 Common.mk_action_1_arg
test_cfg_ifdef;
508 "--parse-unparse", " <file>",
509 Common.mk_action_1_arg
test_parse_unparse;
510 (* "--parse-and-print-sexp", " <file>",
511 Common.mk_action_1_arg parse_and_print_sexp;*)
512 "--type-c", " <file>",
513 Common.mk_action_1_arg
test_type_c;
514 "--compare-c", " <file1> <file2>",
515 Common.mk_action_2_arg
test_compare_c (* result is in unix code *);
516 "--comment-annotater-c", " <file>",
517 Common.mk_action_1_arg
test_comment_annotater;
519 "--compare-c-hardcoded", " ",
520 Common.mk_action_0_arg
test_compare_c_hardcoded;
522 "--test-attributes", " <file>",
523 Common.mk_action_1_arg
test_attributes;
524 "--test-cpp", " <file>",
525 Common.mk_action_1_arg
test_cpp;
527 "--extract-macros", " <file or dir>",
528 Common.mk_action_1_arg
(extract_macros ~selection
:false) ;
530 "--extract-macros-select", " <file or dir>",
531 Common.mk_action_1_arg
(extract_macros ~selection
:true);
534 "--xxx", " <file1> <>",
535 Common.mk_action_n_arg
test_xxx;