Release coccinelle-0.2.2-rc1
[bpt/coccinelle.git] / main.ml
diff --git a/main.ml b/main.ml
index 94ee0bf..b96cba4 100644 (file)
--- a/main.ml
+++ b/main.ml
@@ -1,23 +1,23 @@
 (*
-* Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
-* Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
-* This file is part of Coccinelle.
-* 
-* Coccinelle is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, according to version 2 of the License.
-* 
-* Coccinelle is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-* 
-* You should have received a copy of the GNU General Public License
-* along with Coccinelle.  If not, see <http://www.gnu.org/licenses/>.
-* 
-* The authors reserve the right to distribute this or future versions of
-* Coccinelle under other licenses.
-*)
+ * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
+ * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
+ * This file is part of Coccinelle.
+ *
+ * Coccinelle is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, according to version 2 of the License.
+ *
+ * Coccinelle is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Coccinelle.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The authors reserve the right to distribute this or future versions of
+ * Coccinelle under other licenses.
+ *)
 
 
 open Common
@@ -72,8 +72,54 @@ let mod_distrib   = ref false
 (*****************************************************************************)
 
 (* pair of  (list of flags to set true, list of flags to set false *)
+let very_quiet_profile = (
+  [
+  ],
+  [
+    (* FC.show_diff;   just leave this as it is *)
+
+    Common.print_to_stderr;
+    Flag.show_misc;
+    Flag.show_trying;
+    Flag.show_transinfo;
+
+    FC.show_c;
+    FC.show_cocci;
+    FC.show_flow;
+    FC.show_before_fixed_flow;
+    FC.show_ctl_tex;
+    FC.show_ctl_text;
+    FC.show_binding_in_out;
+
+    FC.verbose_cocci;
+
+    Flag_parsing_c.show_parsing_error;
+
+    Flag_parsing_c.verbose_lexing;
+    Flag_parsing_c.verbose_parsing;
+    Flag_parsing_c.verbose_type;
+    Flag_parsing_c.verbose_cfg;
+    Flag_parsing_c.verbose_unparsing;
+    Flag_parsing_c.verbose_visit;
+    Flag_parsing_c.verbose_cpp_ast;
+
+    Flag_matcher.verbose_matcher;
+    Flag_matcher.debug_engine;
+
+    Flag_parsing_c.debug_unparsing;
+
+    Flag_parsing_cocci.show_SP;
+    Flag_parsing_cocci.show_iso_failures;
+
+    Flag_ctl.verbose_ctl_engine;
+    Flag_ctl.verbose_match;
+
+
+  ])
+
 let quiet_profile = (
   [
+    Common.print_to_stderr
   ],
   [
     (* FC.show_diff;   just leave this as it is *)
@@ -120,6 +166,7 @@ let quiet_profile = (
 work properly *)
 let debug_profile = (
   [
+    Common.print_to_stderr;
     Flag.show_misc;
     Flag.show_transinfo;
 
@@ -162,6 +209,7 @@ let debug_profile = (
 let pad_profile = (
   [
     FC.show_diff;
+    Common.print_to_stderr;
   ],
   [
 
@@ -248,7 +296,9 @@ let short_options = [
   "  causes local include files to be used";
   "-include_headers", Arg.Set include_headers,
   "    process header files independently";
-  "-I",   Arg.String (function x -> FC.include_path := Some x),
+  "-I",   Arg.String (fun x ->
+                       FC.include_path:= x::!FC.include_path
+                    ),
   "  <dir> containing the header files (optional)";
 
   "-preprocess", Arg.Set preprocess,
@@ -259,9 +309,12 @@ let short_options = [
   "-dir", Arg.Set dir,
   "    <dir> process all files in directory recursively";
 
-  "-use_glimpse", Arg.Set Flag.use_glimpse,
+  "-use_glimpse", Arg.Unit (function _ -> Flag.scanner := Flag.Glimpse),
   "    works with -dir, use info generated by glimpseindex";
-  "-patch", Arg.String (function s -> Flag.patch := Some s),
+  "-use_google", Arg.String (function s -> Flag.scanner := Flag.Google s),
+  "    find relevant files using google code search";
+  "-patch",
+    Arg.String (function s -> Flag.patch := Some (Cocci.normalize_path s)),
   ("    <dir> path name with respect to which a patch should be created\n"^
    "    \"\" for a file in the current directory");
   "-kbuild_info", Arg.Set_string kbuild_info,
@@ -271,13 +324,14 @@ let short_options = [
 
 
   "-version",   Arg.Unit (fun () ->
-    pr2 (spf "spatch version: %s" Config.version);
+    let withpython = if Pycocci.python_support then "with" else "without" in
+    pr2 (spf "spatch version %s %s Python support" Config.version withpython);
     exit 0;
   ),
     "  guess what";
 
   "-date",   Arg.Unit (fun () ->
-    pr2 "version: $Date: 2009/07/21 08:21:29 $";
+    pr2 "version: $Date: 2010/03/05 21:12:11 $";
     raise (Common.UnixExit 0)
     ),
   "   guess what";
@@ -358,7 +412,10 @@ let other_options = [
        Flag_ctl.graphical_trace := true; Flag_ctl.gt_without_label := true),
        "  remove graph label (requires option -graphical_trace)";
 
-    "-parse_error_msg", Arg.Set Flag_parsing_c.verbose_parsing, " ";
+    "-parse_error_msg", Arg.Set Flag_parsing_c.show_parsing_error, " ";
+    "-verbose_parsing",
+       Arg.Unit (fun _ -> Flag_parsing_c.verbose_parsing := true;
+        Flag_parsing_c.show_parsing_error := true), " ";
     "-type_error_msg",  Arg.Set Flag_parsing_c.verbose_type, " ";
     (* could also use Flag_parsing_c.options_verbose *)
   ];
@@ -402,6 +459,7 @@ let other_options = [
   [
     (* todo: other profile ? *)
     "-quiet",   Arg.Unit (fun () -> run_profile quiet_profile), " ";
+    "-very_quiet",   Arg.Unit (fun () -> run_profile very_quiet_profile), " ";
     "-debug",   Arg.Unit (fun () -> run_profile debug_profile), " ";
     "-pad",     Arg.Unit (fun () -> run_profile pad_profile),   " ";
 
@@ -436,9 +494,8 @@ let other_options = [
 
 
   "change of algorithm options",
-  "", 
-  [  
-(* no popl in official version
+  "",
+  [
     "-popl", Arg.Set FC.popl,
     "    simplified SmPL, for the popl paper";
 
@@ -451,16 +508,20 @@ let other_options = [
     Arg.Unit
     (function _ -> FC.popl := true; Flag_popl.keep_all_wits := true),
     "    simplified SmPL, for the popl paper";
-*)
 
     "-hrule", Arg.String
     (function s ->
       Flag.make_hrule := Some s; FC.include_options := FC.I_NO_INCLUDES),
     "    semantic patch generation";
 
+    "-keep_comments", Arg.Set Flag_parsing_c.keep_comments,
+    "   keep comments around removed code";
+
     "-loop",              Arg.Set Flag_ctl.loop_in_src_code,    " ";
     "-no_loops",          Arg.Set Flag_parsing_c.no_loops,
     "   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";
 
     "-l1",                Arg.Clear Flag_parsing_c.label_strategy_2, " ";
     "-ifdef_to_if",       Arg.Set FC.ifdef_to_if,
@@ -477,7 +538,7 @@ let other_options = [
 
 
     "-disallow_nested_exps", Arg.Set Flag_matcher.disallow_nested_exps,
-       "disallow an expresion pattern from matching a term and its subterm";
+       " disallow an expresion pattern from matching a term and its subterm";
     "-disable_worth_trying_opt", Arg.Clear FC.worth_trying_opt,
     "  ";
     "-only_return_is_error_exit",
@@ -500,6 +561,8 @@ let other_options = [
     "  spacing of + code follows the conventions of Linux";
     "-smpl_spacing", Arg.Unit Flag_parsing_c.set_smpl_spacing,
     "  spacing of + code follows the semantic patch";
+    "-D", Arg.String Flag.set_defined_virtual_rules,
+    "  indicate that a virtual rule should be considered to be matched";
   ];
 
   "misc options",
@@ -635,8 +698,8 @@ let glimpse_filter (coccifile, isofile) dir =
     Cocci.sp_of_file coccifile (Some isofile) in
   match query with
     None -> pr2 "no glimpse keyword inferred from snippet"; None
-  | Some query ->
-      let suffixes = if !include_headers then ["c";"h"] else ["c"] in
+  | Some [query] ->
+      (let suffixes = if !include_headers then ["c";"h"] else ["c"] in
       pr2 ("glimpse request = " ^ query);
       let command = spf "glimpse -y -H %s -N -W -w '%s'" dir query in
       let (glimpse_res,stat) = Common.cmd_to_list_and_status command in
@@ -646,8 +709,8 @@ let glimpse_filter (coccifile, isofile) dir =
            (glimpse_res +>
             List.filter
               (fun file -> List.mem (Common.filesuffix file) suffixes))
-      |        _ -> None (* error, eg due to pattern too big *)
-
+      |        _ -> None (* error, eg due to pattern too big *))
+  | _ -> failwith "not possible"
 
 (*****************************************************************************)
 (* Main action *)
@@ -672,7 +735,7 @@ let main_action xs =
        if !dir && !Flag.patch =*= None
        then
          (match xs with
-         | [] -> Flag.patch := Some x
+         | [] -> Flag.patch := Some (Cocci.normalize_path x)
          | _ ->
              pr2
                ("warning: patch output can only be created when only one\n"^
@@ -681,7 +744,7 @@ let main_action xs =
 
         let infiles =
           Common.profile_code "Main.infiles computation" (fun () ->
-           match !dir, !kbuild_info, !Flag.use_glimpse with
+           match !dir, !kbuild_info, !Flag.scanner = Flag.Glimpse with
             (* glimpse *)
             | false, _, true ->
                 failwith "-use_glimpse works only with -dir"
@@ -769,6 +832,7 @@ let main_action xs =
                pr2 ("HANDLING: " ^ (join " " cfiles));
                Common.timeout_function_opt !FC.timeout (fun () ->
                  Common.report_if_take_time 10 (join " " cfiles) (fun () ->
+                   (*let s = profile_diagnostic() in*)
                     (* Unix.sleep 1; *)
                     try
                      let optfile =
@@ -784,6 +848,10 @@ let main_action xs =
                    with
                      | Common.UnixExit x -> raise (Common.UnixExit x)
                      | e ->
+                         (*pr2 "previous";
+                         pr2 s;
+                         pr2 "new";
+                         pr2(profile_diagnostic());*)
                          if !dir
                          then begin
                            pr2 ("EXN:" ^ Printexc.to_string e);
@@ -848,7 +916,7 @@ let main () =
     let arglist = Array.to_list Sys.argv in
 
     if not (null (Common.inter_set arglist
-                    ["-cocci_file";"-sp_file";"-test";"-testall";
+                    ["-cocci_file";"-sp_file";"-sp";"-test";"-testall";
                       "-test_okfailed";"-test_regression_okfailed"]))
     then run_profile quiet_profile;
 
@@ -873,8 +941,8 @@ let main () =
             chosen
           end
         else List.hd !args in
-      if !FC.include_path =*= None
-      then FC.include_path := Some (Filename.concat chosen_dir "include"));
+      if !FC.include_path =*= []
+      then FC.include_path := [Filename.concat chosen_dir "include"]);
 
     args := List.rev !args;
 
@@ -905,11 +973,18 @@ let main () =
     (* The test framework. Works with tests/ or .ok and .failed  *)
     (* --------------------------------------------------------- *)
     | [x] when !test_mode    ->
-        FC.include_path := Some "tests/include";
-        Testing.testone x !compare_with_expected
+       begin
+         try
+           let prefix = "tests/" in
+              FC.include_path := [prefix^"include"];
+              Testing.testone prefix x !compare_with_expected
+         with _ ->
+            FC.include_path := ["include"];
+            Testing.testone "" x !compare_with_expected
+       end
 
     | []  when !test_all ->
-        FC.include_path := Some "tests/include";
+        FC.include_path := ["tests/include"];
         if !expected_score_file <> ""
         then Testing.testall ~expected_score_file:!expected_score_file ()
         else Testing.testall ()
@@ -946,8 +1021,7 @@ let main () =
     (* --------------------------------------------------------- *)
     (* This is the main entry *)
     (* --------------------------------------------------------- *)
-    | x::xs ->
-        main_action (x::xs)
+    | x::xs -> main_action (x::xs)
 
     (* --------------------------------------------------------- *)
     (* empty entry *)