@ -25,25 +25,17 @@ type file_data =
; mutable cfg : Cfg . t option }
(* * get the path to the tenv file, which either one tenv file per source file or a global tenv file *)
let tenv_filename file_base =
let per_source_tenv_filename = DB . filename_add_suffix file_base " .tenv " in
let tenv_of_source source =
let source_dir = DB . source_dir_from_source_file source in
let per_source_tenv_filename = DB . source_dir_get_internal_file source_dir " .tenv " in
if Sys . file_exists ( DB . filename_to_string per_source_tenv_filename ) = ` Yes then
per_source_tenv_filename
else DB . global_tenv_fname
module FilenameHash = Hashtbl . Make ( struct
type t = DB . filename
let equal file1 file2 = DB . equal_filename file1 file2
let hash = Hashtbl . hash
end )
(* * create a new file_data *)
let new_file_data source cg_fname =
let file_base = DB . chop_extension cg_fname in
let tenv_file = tenv_filename file_base in
let new_file_data source =
let tenv_file = tenv_of_source source in
(* Do not fill in tenv and cfg as they can be quite large. This makes calls to fork ( ) cheaper
until we start filling out these fields . * )
{ source
@ -52,52 +44,21 @@ let new_file_data source cg_fname =
; cfg = None (* Cfg.load_cfg_from_file cfg_file *) }
let create_file_data table source cg_fname =
match FilenameHash. find table cg_fnam e with
let create_file_data table source =
match SourceFile. Hash . find table sourc e with
| file_data ->
file_data
| exception Not_found ->
let file_data = new_file_data source cg_fname in
FilenameHash. add table cg_fnam e file_data ;
let file_data = new_file_data source in
SourceFile. Hash . add table sourc e file_data ;
file_data
type t =
{ cg : Cg . t (* * global call graph *)
; proc_map : file_data Typ . Procname . Hash . t (* * map from procedure name to file data *)
; file_map : file_data FilenameHash . t (* * map from cg fname to file data *)
{ proc_map : file_data Typ . Procname . Hash . t (* * map from procedure name to file data *)
; file_map : file_data SourceFile . Hash . t (* * map from source files to file data *)
; source_file : SourceFile . t (* * source file being analyzed *) }
(* * add call graph from fname in the spec db,
with relative tenv and cfg , to the execution environment * )
let add_cg exe_env source =
let cg_fname = DB . source_dir_get_internal_file ( DB . source_dir_from_source_file source ) " .cg " in
match Cg . load_from_file cg_fname with
| None ->
L . internal_error " Error: cannot load %s@. " ( DB . filename_to_string cg_fname )
| Some cg ->
let defined_procs = Cg . get_defined_nodes cg in
let duplicate_procs_to_print =
List . filter_map defined_procs ~ f : ( fun pname ->
match Attributes . find_file_capturing_procedure pname with
| None ->
None
| Some ( source_captured , origin ) ->
let multiply_defined = SourceFile . compare source source_captured < > 0 in
if multiply_defined then Cg . remove_node_defined cg pname ;
if multiply_defined && origin < > ` Include then Some ( pname , source_captured )
else None )
in
if Config . dump_duplicate_symbols then
Out_channel . with_file ( Config . results_dir ^/ Config . duplicates_filename )
~ append : true ~ perm : 0o666 ~ f : ( fun outc ->
let fmt = F . formatter_of_out_channel outc in
List . iter duplicate_procs_to_print ~ f : ( fun ( pname , source_captured ) ->
F . fprintf fmt " @.DUPLICATE_SYMBOLS source: %a source_captured:%a pname:%a@. "
SourceFile . pp source SourceFile . pp source_captured Typ . Procname . pp pname ) ) ;
Cg . extend exe_env . cg cg
let get_file_data exe_env pname =
try Some ( Typ . Procname . Hash . find exe_env . proc_map pname ) with Not_found ->
let source_file_opt =
@ -112,9 +73,7 @@ let get_file_data exe_env pname =
Some proc_attributes . ProcAttributes . source_file_captured
in
let get_file_data_for_source source_file =
let source_dir = DB . source_dir_from_source_file source_file in
let cg_fname = DB . source_dir_get_internal_file source_dir " .cg " in
let file_data = create_file_data exe_env . file_map source_file cg_fname in
let file_data = create_file_data exe_env . file_map source_file in
Typ . Procname . Hash . replace exe_env . proc_map pname file_data ;
file_data
in
@ -184,13 +143,7 @@ let get_proc_desc exe_env pname =
let mk source_file =
let exe_env =
{ cg = Cg . create ( SourceFile . invalid _ _ FILE__ )
; proc_map = Typ . Procname . Hash . create 17
; file_map = FilenameHash . create 1
; source_file }
in
add_cg exe_env source_file ; exe_env
{ proc_map = Typ . Procname . Hash . create 17 ; file_map = SourceFile . Hash . create 1 ; source_file }
(* * [iter_files f exe_env] applies [f] to the filename and tenv and cfg for each file in [exe_env] *)