@ -13,35 +13,6 @@
module L = Logging
module F = Format
(* This module, unused by default, generates random c files with procedure calls *)
module Codegen = struct
let num_files = 5000
let num_functions = 1000
let calls_per_fun = 5
let fun_nr = ref 0
let gen () =
for file_nr = 1 to num_files do
let fname = Printf . sprintf " file%04d.c " file_nr in
let fmt = open_out fname in
for _ = 1 to num_functions do
incr fun_nr ;
let num_calls = if ! fun_nr = 1 then 0 else Random . int calls_per_fun in
Printf . fprintf fmt " void f%04d() { \n " ! fun_nr ;
for _ = 1 to num_calls do
let callee_nr = 1 + Random . int ( max 1 ( num_calls - 1 ) ) in
Printf . fprintf fmt " f%04d(); \n " callee_nr
done ;
Printf . fprintf fmt " } \n " ;
done ;
close_out fmt
done
let dont () =
gen () ;
exit 0
end
(* * command line option: if true, run the analysis in checker mode *)
let checkers = ref false
@ -255,7 +226,7 @@ let () = (* parse command-line arguments *)
let analyze_exe_env exe_env =
let init_time = Unix . gettimeofday () in
L . log_progress_ simple " . " ;
L . log_progress_ file () ;
Specs . clear_spec_tbl () ;
Random . self_init () ;
let line_reader = Printer . LineReader . create () in
@ -273,16 +244,6 @@ let analyze_exe_env exe_env =
L . out " Interprocedural footprint analysis terminated in %f sec@. " elapsed
end
let output_json_file_stats num_files num_procs num_lines =
let file_stats =
` Assoc [ ( " files " , ` Int num_files ) ;
( " procedures " , ` Int num_procs ) ;
( " lines " , ` Int num_lines ) ] in
(* write stats file to disk, intentionally overwriting old file if it already exists *)
let f = open_out ( Filename . concat ! Config . results_dir Config . proc_stats_filename ) in
Yojson . Basic . pretty_to_channel f file_stats
(* * Create an exe_env from a cluster. *)
let exe_env_from_cluster cluster =
let _ exe_env = Exe_env . create () in
@ -293,28 +254,14 @@ let exe_env_from_cluster cluster =
exe_env
(* * Analyze a cluster of files *)
let analyze_cluster cluster_num tot_clusters ( cluster : Cluster . t ) =
let cluster_num_ref = ref cluster_num in
incr cluster_num_ref ;
let analyze_cluster cluster_num ( cluster : Cluster . t ) =
let exe_env = exe_env_from_cluster cluster in
let defined_procs = Cg . get_defined_nodes ( Exe_env . get_cg exe_env ) in
let num_procs = IList . length defined_procs in
L . err " @.Processing cluster #%d /%d with %d procedures@."
!cluster_num_ref tot_clusters num_procs ;
L . err " @.Processing cluster #%d with %d procedures@."
(cluster_num + 1 ) num_procs ;
analyze_exe_env exe_env
let process_cluster_cmdline_exit () =
match ! cluster_cmdline with
| None -> ()
| Some fname ->
( match Cluster . load_from_file ( DB . filename_from_string fname ) with
| None ->
L . err " Cannot find cluster file %s@. " fname ;
exit 0
| Some ( nr , tot_nr , cluster ) ->
analyze_cluster ( nr - 1 ) tot_nr cluster ;
exit 0 )
let open_output_file f fname =
try
let cout = open_out fname in
@ -355,17 +302,19 @@ let teardown_logging analyzer_out_of analyzer_err_of =
close_output_file analyzer_err_of ;
end
(* * Compute clusters.
Each cluster will contain only the name of the directory for a file . * )
let compute_clusters clusters =
Cluster . print_clusters clusters ;
let num_files = IList . length clusters in
let output_json_makefile_stats clusters =
let clusters_to_analyze =
IList . filter ClusterMakefile . cluster_should_be_analyzed clusters in
let num_files = IList . length clusters_to_analyze in
let num_procs = 0 (* can't compute it at this stage *) in
let num_lines = 0 in
output_json_file_stats num_files num_procs num_lines ;
if ! makefile_cmdline < > " "
then ClusterMakefile . create_cluster_makefile_and_exit clusters ! makefile_cmdline ;
clusters
let file_stats =
` Assoc [ ( " files " , ` Int num_files ) ;
( " procedures " , ` Int num_procs ) ;
( " lines " , ` Int num_lines ) ] in
(* write stats file to disk, intentionally overwriting old file if it already exists *)
let f = open_out ( Filename . concat ! Config . results_dir Config . proc_stats_filename ) in
Yojson . Basic . pretty_to_channel f file_stats
let print_prolog () =
match ! cluster_cmdline with
@ -373,6 +322,13 @@ let print_prolog () =
L . stdout " Starting analysis (Infer version %s)@. " Version . versionString ;
| Some clname -> L . stdout " Cluster %s@. " clname
let process_cluster_cmdline fname =
match Cluster . load_from_file ( DB . filename_from_string fname ) with
| None ->
L . err " Cannot find cluster file %s@. " fname
| Some ( nr , cluster ) ->
analyze_cluster ( nr - 1 ) cluster
let () =
print_prolog () ;
RegisterCheckers . register () ;
@ -383,15 +339,28 @@ let () =
let analyzer_out_of , analyzer_err_of = setup_logging () in
if ( ! Config . curr_language = Config . C_CPP ) then Mleak_buckets . init_buckets ! ml_buckets_arg ;
let finish_logging () =
teardown_logging analyzer_out_of analyzer_err_of in
process_cluster_cmdline_exit () ;
let source_dirs = DB . find_source_dirs () in
L . err " Found %d source files in %s@. " ( IList . length source_dirs ) ! Config . results_dir ;
let clusters = compute_clusters source_dirs in
match ! cluster_cmdline with
| Some fname ->
process_cluster_cmdline fname ;
finish_logging ()
| None ->
let clusters = DB . find_source_dirs () in
L . err " Found %d source files in %s@. "
( IList . length clusters ) ! Config . results_dir ;
if ! makefile_cmdline < > " "
then
ClusterMakefile . create_cluster_makefile clusters ! makefile_cmdline
else
begin
IList . iteri
( fun i cluster -> analyze_cluster i cluster )
clusters ;
L . stdout " Analysis finished in %as@. " pp_elapsed_time ()
end ;
output_json_makefile_stats clusters ;
finish_logging ()
let tot_clusters = IList . length clusters in
IList . iter ( analyze_cluster 0 tot_clusters ) clusters ;
teardown_logging analyzer_out_of analyzer_err_of ;
if ! cluster_cmdline = None then L . stdout " Analysis finished in %as@. " pp_elapsed_time ()