X-Git-Url: http://git.hcoop.net/bpt/coccinelle.git/blobdiff_plain/190f1acf3b0fa9403bea541654465a6a00bf3693..97111a47d707638a835d7498276ac6768a052ee8:/main.ml diff --git a/main.ml b/main.ml index 81cacc7..2dca9d2 100644 --- a/main.ml +++ b/main.ml @@ -71,7 +71,6 @@ let distrib_index = ref (None : int option) let distrib_max = ref (None : int option) let mod_distrib = ref false - (*****************************************************************************) (* Profiles *) (*****************************************************************************) @@ -180,6 +179,7 @@ let debug_profile = ( FC.show_binding_in_out; FC.show_dependencies; + Flag_parsing_cocci.keep_ml_script; Flag_parsing_cocci.show_iso_failures; FC.verbose_cocci; @@ -339,13 +339,17 @@ let short_options = [ "-version", Arg.Unit (fun () -> let withpython = if Pycocci.python_support then "with" else "without" in - pr2 (spf "spatch version %s %s Python support" Config.version withpython); + let whichregexp = + if !Regexp.pcre_support then "with PCRE support" + else "with Str regexp support " + in + pr2 (spf "spatch version %s %s Python support and %s" Config.version withpython whichregexp); exit 0; ), " guess what"; "-date", Arg.Unit (fun () -> - pr2 "version: $Date: 2011/03/14 21:16:17 $"; + pr2 "version: $Date$"; raise (Common.UnixExit 0) ), " guess what"; @@ -392,6 +396,8 @@ let other_options = [ [ "-show_diff" , Arg.Set FC.show_diff, " "; "-no_show_diff" , Arg.Clear FC.show_diff, " "; + "-force_diff" , Arg.Set FC.force_diff, + "show diff even if only spacing changes"; "-show_flow" , Arg.Set FC.show_flow, " "; (* works in conjunction with -show_ctl_text *) "-ctl_inline_let", @@ -541,6 +547,11 @@ let other_options = [ " drop all back edges derived from looping constructs - unsafe"; "-no_gotos", Arg.Set Flag_parsing_c.no_gotos, " drop all jumps derived from gotos - unsafe"; + "-no_saved_typedefs", Arg.Clear Flag_cocci.use_saved_typedefs, + " drop all inferred typedefs from one parse of some code to the next"; + + "-ocaml_regexps", Arg.Clear Regexp.pcre_support, + " use OCaml Str regular expressions for constraints"; "-l1", Arg.Clear Flag_parsing_c.label_strategy_2, " "; "-ifdef_to_if", Arg.Set FC.ifdef_to_if, @@ -614,7 +625,16 @@ let other_options = [ [ "-use_cache", Arg.Set Flag_parsing_c.use_cache, " use .ast_raw pre-parsed cached C file"; + "-cache_prefix", + Arg.String (function s -> + Flag_parsing_c.cache_prefix := Some s; + Flag_parsing_c.use_cache := true), + " directory of cached ASTs, sets -use_cache"; (* could use Flag_parsing_c.options_pad instead *) + "-cache_limit", + Arg.Int (function n -> + Flag_parsing_c.cache_limit := Some n), + " maximum number of cached ASTs, sets -use_cache"; ]; @@ -689,9 +709,9 @@ let rec arg_parse_no_fail l f msg = raise Impossible (* -help is specified in speclist *) (* copy paste of Arg.parse. Don't want the default -help msg *) -let arg_parse2 l f msg = +let arg_parse2 l f msg argv = (try - Arg.parse_argv Sys.argv l f msg; + Arg.parse_argv argv l f msg; with | Arg.Bad emsg -> (* eprintf "%s" msg; exit 2; *) if not !ignore_unknown_opt then @@ -804,7 +824,13 @@ let get_files path = else [] in cpp @ ch -let main_action xs = +let rec main_action xs = + let (cocci_files,xs) = + List.partition (function nm -> Filename.check_suffix nm ".cocci") xs in + (match (!cocci_file,cocci_files) with + "",[fl] -> cocci_file := fl + | _,[] -> () + | _ -> failwith "only one .cocci file allowed"); Iteration.base_file_list := xs; let rec toploop = function [] -> raise Impossible @@ -872,7 +898,14 @@ let main_action xs = groups +> List.map (function Kbuild.Group xs -> xs) ) in - + + (* make cache unique in parallel case *) + (match (!distrib_index,!Flag_parsing_c.cache_prefix) with + (Some index,Some str) -> + Flag_parsing_c.cache_prefix := + Some (Printf.sprintf "%s/d%d" str index) + | _ -> ()); + let infiles = match (!distrib_index,!distrib_max) with (None,None) -> infiles @@ -940,21 +973,26 @@ let main_action xs = (cocci_infos,res)) in let outfiles = List.concat outfiles in (match Iteration.get_pending_instance() with - None -> (x,xs,cocci_infos,outfiles) + None -> + (x,xs,cocci_infos,outfiles) | Some (files,virt_rules,virt_ids) -> if outfiles = [] or outfiles = [] or not !FC.show_diff + or !inplace_modif then begin + (if !inplace_modif then generate_outfiles outfiles x xs); Flag.defined_virtual_rules := virt_rules; Flag.defined_virtual_env := virt_ids; Common.erase_temp_files(); Common.clear_pr2_once(); + distrib_index := None; + distrib_max := None; toploop files end else begin Common.pr2 - "Transformation not compatible with iteration. Aborting."; + "Out of place transformation not compatible with iteration. Aborting.\n consider using -no_show_diff or -in_place"; (x,xs,cocci_infos,outfiles) end) in let (x,xs,cocci_infos,outfiles) = toploop xs in @@ -962,21 +1000,26 @@ let main_action xs = Cocci.post_engine cocci_infos; Common.profile_code "Main.result analysis" (fun () -> Ctlcocci_integration.print_bench(); - let outfiles = Cocci.check_duplicate_modif outfiles in - outfiles +> List.iter (fun (infile, outopt) -> - outopt +> Common.do_option (fun outfile -> - if !inplace_modif - then begin - (match !backup_suffix with - Some backup_suffix -> - Common.command2 ("cp "^infile^" "^infile^backup_suffix) - | None -> ()); - Common.command2 ("cp "^outfile^" "^infile); - end; - - if !outplace_modif - then Common.command2 ("cp "^outfile^" "^infile^".cocci_res"); - + generate_outfiles outfiles x xs; + if !compare_with_expected + then Testing.compare_with_expected outfiles) + +and generate_outfiles outfiles x (* front file *) xs (* other files *) = + let outfiles = Cocci.check_duplicate_modif outfiles in + outfiles +> List.iter (fun (infile, outopt) -> + outopt +> Common.do_option (fun outfile -> + if !inplace_modif + then begin + (match !backup_suffix with + Some backup_suffix -> + Common.command2 ("cp "^infile^" "^infile^backup_suffix) + | None -> ()); + Common.command2 ("cp "^outfile^" "^infile); + end; + + if !outplace_modif + then Common.command2 ("cp "^outfile^" "^infile^".cocci_res") + (* potential source of security pb if the /tmp/ file is * a symlink, so simpler to not produce any regular file * (files created by Common.new_temp_file are still ok) @@ -991,27 +1034,24 @@ let main_action xs = end *) )); - if !output_file <> "" && not !compat_mode then - (match outfiles with - | [infile, Some outfile] when infile =$= x && null xs -> - Common.command2 ("cp " ^outfile^ " " ^ !output_file); - | [infile, None] when infile =$= x && null xs -> - Common.command2 ("cp " ^infile^ " " ^ !output_file); - | _ -> - failwith - ("-o can not be applied because there are multiple " ^ - "modified files"); - ); - if !compare_with_expected - then Testing.compare_with_expected outfiles) - - + if !output_file <> "" && not !compat_mode then + (match outfiles with + | [infile, Some outfile] when infile =$= x && null xs -> + Common.command2 ("cp " ^outfile^ " " ^ !output_file) + | [infile, None] when infile =$= x && null xs -> + Common.command2 ("cp " ^infile^ " " ^ !output_file) + | _ -> + failwith + ("-o can not be applied because there are multiple " ^ + "modified files")) + (*****************************************************************************) (* The coccinelle main entry point *) (*****************************************************************************) let main () = begin let arglist = Array.to_list Sys.argv in + let arglist = Command_line.command_line arglist in if not (null (Common.inter_set arglist ["-cocci_file";"-sp_file";"-sp";"-test";"-testall"; @@ -1023,7 +1063,8 @@ let main () = (* Gc.set {(Gc.get ()) with Gc.stack_limit = 1024 * 1024};*) (* this call can set up many global flag variables via the cmd line *) - arg_parse2 (Arg.align all_options) (fun x -> args := x::!args) usage_msg; + arg_parse2 (Arg.align all_options) (fun x -> args := x::!args) usage_msg + (Array.of_list arglist); (* julia hack so that one can override directories specified on * the command line. *)