@@ -119,18 +119,14 @@ let option_spec_list =
119119 ; " --osekids" , Arg. Set_string OilUtil. osek_ids, " "
120120 ]
121121
122- (* * List of C files to consider. *)
123- let cFileNames = ref []
124122
125- (* * Parse arguments and fill [cFileNames] and [jsonFiles ]. Print help if needed. *)
123+ (* * Parse arguments and fill [arg_files ]. Print help if needed. *)
126124let parse_arguments () =
127- let jsonRegex = Str. regexp " .+\\ .json$" in
128- let recordFile fname =
129- if Str. string_match jsonRegex fname 0
130- then Goblintutil. jsonFiles := fname :: ! Goblintutil. jsonFiles
131- else cFileNames := fname :: ! cFileNames
125+ let anon_arg filename =
126+ arg_files := filename :: ! arg_files
132127 in
133- Arg. parse option_spec_list recordFile " Look up options using 'goblint --help'." ;
128+ Arg. parse option_spec_list anon_arg " Look up options using 'goblint --help'." ;
129+ arg_files := List. rev ! arg_files; (* reverse files to get given order *)
134130 if ! writeconffile <> " " then (GobConfig. write_file ! writeconffile; raise Exit )
135131
136132(* * Initialize some globals in other modules. *)
@@ -151,15 +147,15 @@ let handle_flags () =
151147 set_string " outfile" " "
152148
153149(* * Use gcc to preprocess a file. Returns the path to the preprocessed file. *)
154- let preprocess_one_file cppflags fname =
150+ let basic_preprocess ~ all_cppflags fname =
155151 (* The actual filename of the preprocessed sourcefile *)
156152 let nname = Filename. concat ! Goblintutil. tempDirName (Filename. basename fname) in
157153 if Sys. file_exists (get_string " tempDir" ) then
158154 nname
159155 else
160156 (* Preprocess using cpp. *)
161157 (* ?? what is __BLOCKS__? is it ok to just undef? this? http://en.wikipedia.org/wiki/Blocks_(C_language_extension) *)
162- let command = Config. cpp ^ " --undef __BLOCKS__ " ^ cppflags ^ " \" " ^ fname ^ " \" -o \" " ^ nname ^ " \" " in
158+ let command = Config. cpp ^ " --undef __BLOCKS__ " ^ String. join " " ( List. map Filename. quote all_cppflags) ^ " \" " ^ fname ^ " \" -o \" " ^ nname ^ " \" " in
163159 if get_bool " dbg.verbose" then print_endline command;
164160
165161 (* if something goes wrong, we need to clean up and exit *)
@@ -173,7 +169,7 @@ let preprocess_one_file cppflags fname =
173169(* * Preprocess all files. Return list of preprocessed files and the temp directory name. *)
174170let preprocess_files () =
175171 (* Preprocessor flags *)
176- let cppflags = ref (get_string " cppflags" ) in
172+ let cppflags = ref (get_string_list " cppflags" ) in
177173
178174 (* the base include directory *)
179175 let custom_include_dirs =
@@ -213,37 +209,6 @@ let preprocess_files () =
213209
214210 include_dirs := custom_include_dirs @ ! include_dirs;
215211
216- (* reverse the files again *)
217- cFileNames := List. rev ! cFileNames;
218-
219- (* If the first file given is a Makefile, we use it to combine files *)
220- if ! cFileNames <> [] then (
221- let firstFile = List. first ! cFileNames in
222- if Filename. basename firstFile = " Makefile" then (
223- let makefile = firstFile in
224- let path = Filename. dirname makefile in
225- (* make sure the Makefile exists or try to generate it *)
226- if not (Sys. file_exists makefile) then (
227- print_endline (" Given " ^ makefile ^ " does not exist!" );
228- let configure = Filename. concat path " configure" in
229- if Sys. file_exists configure then (
230- print_endline (" Trying to run " ^ configure ^ " to generate Makefile" );
231- let exit_code, output = MakefileUtil. exec_command ~path " ./configure" in
232- print_endline (configure ^ MakefileUtil. string_of_process_status exit_code ^ " . Output: " ^ output);
233- if not (Sys. file_exists makefile) then failwith (" Running " ^ configure ^ " did not generate a Makefile - abort!" )
234- ) else failwith (" Could neither find given " ^ makefile ^ " nor " ^ configure ^ " - abort!" )
235- );
236- let _ = MakefileUtil. run_cilly path in
237- let file = MakefileUtil. (find_file_by_suffix path comb_suffix) in
238- cFileNames := file :: (List. drop 1 ! cFileNames);
239- );
240- );
241-
242- cFileNames := find_custom_include " stdlib.c" :: ! cFileNames;
243-
244- if get_bool " ana.sv-comp.functions" then
245- cFileNames := find_custom_include " sv-comp.c" :: ! cFileNames;
246-
247212 (* If we analyze a kernel module, some special includes are needed. *)
248213 if get_bool " kernel" then (
249214 let kernel_roots = [
@@ -261,7 +226,7 @@ let preprocess_files () =
261226
262227 let preconf = find_custom_include " linux/goblint_preconf.h" in
263228 let autoconf = Filename. concat kernel_dir " linux/kconfig.h" in
264- cppflags := " -D__KERNEL__ -U__i386__ -D__x86_64__ " ^ ! cppflags;
229+ cppflags := " -D__KERNEL__" :: " -U__i386__" :: " -D__x86_64__" :: ! cppflags;
265230 include_files := preconf :: autoconf :: ! include_files;
266231 (* These are not just random permutations of directories, but based on USERINCLUDE from the
267232 * Linux kernel Makefile (in the root directory of the kernel distribution). *)
@@ -271,17 +236,48 @@ let preprocess_files () =
271236 ]
272237 );
273238
274- let includes =
275- String. join " " (List. map (fun include_dir -> " -I " ^ include_dir) ! include_dirs) ^
276- " " ^
277- String. join " " (List. map (fun include_file -> " -include " ^ include_file) ! include_files)
239+ let include_args =
240+ List. flatten (List. map (fun include_dir -> [" -I" ; include_dir]) ! include_dirs) @
241+ List. flatten (List. map (fun include_file -> [" -include" ; include_file]) ! include_files)
278242 in
279243
280- let cppflags = ! cppflags ^ " " ^ includes in
244+ let all_cppflags = ! cppflags @ include_args in
281245
282246 (* preprocess all the files *)
283247 if get_bool " dbg.verbose" then print_endline " Preprocessing files." ;
284- List. rev_map (preprocess_one_file cppflags) ! cFileNames
248+
249+ let rec preprocess_arg_file = function
250+ | filename when Filename. basename filename = " Makefile" ->
251+ let comb_file = MakefileUtil. generate_and_combine filename in
252+ [basic_preprocess ~all_cppflags comb_file]
253+
254+ | filename when Filename. basename filename = CompilationDatabase. basename ->
255+ CompilationDatabase. load_and_preprocess ~all_cppflags filename
256+
257+ | filename when Sys. is_directory filename ->
258+ let dir_files = Sys. readdir filename in
259+ if Array. mem CompilationDatabase. basename dir_files then (* prefer compilation database to Makefile in case both exist, because compilation database is more robust *)
260+ preprocess_arg_file (Filename. concat filename CompilationDatabase. basename)
261+ else if Array. mem " Makefile" dir_files then
262+ preprocess_arg_file (Filename. concat filename " Makefile" )
263+ else
264+ [] (* don't recurse for anything else *)
265+
266+ | filename when Filename. extension filename = " .json" ->
267+ [] (* ignore other JSON files for contain analysis *)
268+
269+ | filename ->
270+ [basic_preprocess ~all_cppflags filename]
271+ in
272+
273+ let extra_arg_files = ref [] in
274+
275+ extra_arg_files := find_custom_include " stdlib.c" :: ! extra_arg_files;
276+
277+ if get_bool " ana.sv-comp.functions" then
278+ extra_arg_files := find_custom_include " sv-comp.c" :: ! extra_arg_files;
279+
280+ List. flatten (List. map preprocess_arg_file (! extra_arg_files @ ! arg_files))
285281
286282(* * Possibly merge all postprocessed files *)
287283let merge_preprocessed cpp_file_names =
0 commit comments