(* * Copyright (c) 2013 - present Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. *) open! Utils (* Take as input an ast file and a C or ObjectiveC file such that the ast file corresponds to the compilation of the C file with clang. Parse the ast file into a data structure and translates it into a cfg. *) module L = Logging let buffer_len = 262143 (* This function reads the json file in fname, validates it, and encoded in the AST data structure*) (* defined in Clang_ast_t. *) let validate_decl_from_file fname = try Ag_util.Biniou.from_file ~len:buffer_len Clang_ast_b.read_decl fname with (Invalid_argument "Bi_inbuf.refill_from_channel") -> Logging.out "WARNING: biniou buffer too short, skipping the file\n"; assert false let validate_decl_from_stdin () = try Ag_util.Biniou.from_channel ~len:buffer_len Clang_ast_b.read_decl stdin with (Invalid_argument "Bi_inbuf.refill_from_channel") -> Logging.out "WARNING: biniou buffer too short, skipping the file\n"; assert false let register_perf_stats_report source_file = let stats_dir = Filename.concat Config.results_dir Config.frontend_stats_dir_name in let abbrev_source_file = DB.source_file_encoding source_file in let stats_file = Config.perf_stats_prefix ^ "_" ^ abbrev_source_file ^ ".json" in create_dir Config.results_dir ; create_dir stats_dir ; PerfStats.register_report_at_exit (Filename.concat stats_dir stats_file) let init_global_state_for_capture_and_linters source_file = register_perf_stats_report source_file; DB.Results_dir.init source_file let do_run source_file ast_path = let init_time = Unix.gettimeofday () in let print_elapsed () = let elapsed = Unix.gettimeofday () -. init_time in Logging.out "Elapsed: %07.3f seconds.\n" elapsed in try let ast_filename, ast_decl = match ast_path with | Some path -> path, validate_decl_from_file path | None -> "stdin of " ^ DB.source_file_to_string source_file, validate_decl_from_stdin () in let decl_index, stmt_index, type_index, ivar_to_property_index = Clang_ast_main.index_node_pointers ast_decl in CFrontend_config.pointer_decl_index := decl_index; CFrontend_config.pointer_stmt_index := stmt_index; CFrontend_config.pointer_type_index := type_index; CFrontend_config.ivar_to_property_index := ivar_to_property_index; CFrontend_config.json := ast_filename; Logging.out "Clang frontend action is %s\n" Config.clang_frontend_action_string; Logging.out "Start %s of AST from %s\n" Config.clang_frontend_action_string !CFrontend_config.json; init_global_state_for_capture_and_linters source_file; let translation_unit_context = CFrontend_config.{source_file; lang=Config.clang_lang} in if Config.clang_frontend_do_lint then CFrontend_checkers_main.do_frontend_checks translation_unit_context ast_decl; if Config.clang_frontend_do_capture then CFrontend.do_source_file translation_unit_context ast_decl; Logging.out "End translation AST file %s... OK!@\n" !CFrontend_config.json; print_elapsed (); with (Yojson.Json_error s) as exc -> Logging.err_debug "%s\n" s; print_elapsed (); raise exc let () = let source_file = (match Config.source_file with | Some path -> Logging.set_log_file_identifier (Some (Filename.basename path)); CLocation.check_source_file path; CLocation.source_file_from_path path | None -> Logging.err_debug "Incorrect command line arguments\n"; Config.print_usage_exit ()) in do_run source_file Config.ast_file