Release of coccinelle 1.0.0-rc9
[bpt/coccinelle.git] / parsing_c / parse_c.ml
index 0dc4766..bea0efc 100644 (file)
@@ -519,7 +519,28 @@ let rec lexer_function ~pass tr = fun lexbuf ->
           then begin
             incr Stat.nDefinePassing;
             pr2_once ("CPP-DEFINE: inside function, I treat it as comment");
-            let v' = Parser_c.TCommentCpp (Token_c.CppDirective,TH.info_of_tok v)
+            let v' =
+             Parser_c.TCommentCpp (Token_c.CppDirective,TH.info_of_tok v)
+            in
+            tr.passed <- v'::tr.passed;
+            tr.rest       <- Parsing_hacks.comment_until_defeol tr.rest;
+            tr.rest_clean <- Parsing_hacks.drop_until_defeol tr.rest_clean;
+            lexer_function ~pass tr lexbuf
+          end
+          else begin
+            tr.passed <- v::tr.passed;
+            tr.passed_clean <- v::tr.passed_clean;
+            v
+          end
+
+      | Parser_c.TUndef (tok) ->
+          if not (LP.current_context () =*= LP.InTopLevel) &&
+            (!Flag_parsing_c.cpp_directive_passing || (pass >= 2))
+          then begin
+            incr Stat.nUndefPassing;
+            pr2_once ("CPP-UNDEF: inside function, I treat it as comment");
+            let v' =
+             Parser_c.TCommentCpp (Token_c.CppDirective,TH.info_of_tok v)
             in
             tr.passed <- v'::tr.passed;
             tr.rest       <- Parsing_hacks.comment_until_defeol tr.rest;
@@ -544,7 +565,7 @@ let rec lexer_function ~pass tr = fun lexbuf ->
           end
           else begin
             let (v,new_tokens) =
-              Parsing_hacks.tokens_include (info, includes, filename, inifdef) in
+              Parsing_hacks.tokens_include(info, includes, filename, inifdef) in
             let new_tokens_clean =
               new_tokens +> List.filter TH.is_not_comment  in
 
@@ -623,7 +644,6 @@ let get_one_elem ~pass tr (file, filelines) =
 
       let passed_before_error = tr.passed in
       let current = tr.current in
-
       (*  error recovery, go to next synchro point *)
       let (passed', rest') =
         Parsing_recovery_c.find_next_synchro tr.rest tr.passed in
@@ -773,7 +793,10 @@ let init_defs_builtins file_h =
 type info_item =  string * Parser_c.token list
 
 type program2 = toplevel2 list
-     and toplevel2 = Ast_c.toplevel * info_item
+   and extended_program2 = toplevel2 list *
+      (string, Lexer_parser.identkind) Common.scoped_h_env (* type defs *) *
+      (string, Cpp_token_c.define_def) Hashtbl.t (* macro defs *)
+   and toplevel2 = Ast_c.toplevel * info_item
 
 let program_of_program2 xs =
   xs +> List.map fst
@@ -803,7 +826,7 @@ let with_program2 f program2 =
  * tokens_stat record and parsing_stat record.
  *)
 
-let parse_print_error_heuristic2 file =
+let parse_print_error_heuristic2 saved_typedefs saved_macros file =
 
   let filelines = Common.cat_array file in
   let stat = Parsing_stat.default_stat file in
@@ -811,7 +834,8 @@ let parse_print_error_heuristic2 file =
   (* -------------------------------------------------- *)
   (* call lexer and get all the tokens *)
   (* -------------------------------------------------- *)
-  LP.lexer_reset_typedef();
+
+  LP.lexer_reset_typedef saved_typedefs;
   Parsing_hacks.ifdef_paren_cnt := 0;
 
   let toks_orig = tokens file in
@@ -821,7 +845,8 @@ let parse_print_error_heuristic2 file =
   (* expand macros on demand trick, preparation phase *)
   let macros =
     Common.profile_code "MACRO mgmt prep 1" (fun () ->
-      let macros = Hashtbl.copy !_defs in
+      let macros =
+       match saved_macros with None -> Hashtbl.copy !_defs | Some h -> h in
       (* include also builtins as some macros may generate some builtins too
        * like __decl_spec or __stdcall
        *)
@@ -1010,26 +1035,34 @@ let parse_print_error_heuristic2 file =
   in
   let v = loop tr in
   let v = with_program2 Parsing_consistency_c.consistency_checking v in
+  let v =
+    let new_td = ref (Common.clone_scoped_h_env !LP._typedef) in
+    Common.clean_scope_h new_td;
+    (v, !new_td, macros) in
   (v, stat)
 
 
-let time_total_parsing a  =
-  Common.profile_code "TOTAL" (fun () -> parse_print_error_heuristic2 a)
+let time_total_parsing a b =
+  Common.profile_code "TOTAL" (fun () -> parse_print_error_heuristic2 a b)
 
-let parse_print_error_heuristic a  =
-  Common.profile_code "C parsing" (fun () -> time_total_parsing a)
+let parse_print_error_heuristic a b =
+  Common.profile_code "C parsing" (fun () -> time_total_parsing a b)
 
 
 (* alias *)
-let parse_c_and_cpp a = parse_print_error_heuristic a
+let parse_c_and_cpp a =
+  let ((c,_,_),stat) = parse_print_error_heuristic None None a in (c,stat)
+let parse_c_and_cpp_keep_typedefs td macs a =
+  parse_print_error_heuristic td macs a
 
 (*****************************************************************************)
 (* Same but faster cos memoize stuff *)
 (*****************************************************************************)
 let parse_cache file =
-  if not !Flag_parsing_c.use_cache then parse_print_error_heuristic file
+  if not !Flag_parsing_c.use_cache
+  then parse_print_error_heuristic None None file
   else
-  let _ = pr2 "TOFIX" in
+  let _ = pr2 "TOFIX: use_cache is not sensitive to changes in the considered macros, include files, etc" in
   let need_no_changed_files =
     (* should use Sys.argv.(0), would be safer. *)
 
@@ -1042,16 +1075,35 @@ let parse_cache file =
       *)
       !Config.std_h;
       *)
-    ]
-  in
+    ] in
   let need_no_changed_variables =
     (* could add some of the flags of flag_parsing_c.ml *)
-    []
-  in
-  Common.cache_computation_robust
-    file ".ast_raw"
+    [] in
+  Common.cache_computation_robust_in_dir
+    !Flag_parsing_c.cache_prefix file ".ast_raw"
     (need_no_changed_files, need_no_changed_variables) ".depend_raw"
-    (fun () -> parse_print_error_heuristic file)
+    (fun () ->
+      (* check whether to clear the cache *)
+      (match (!Flag_parsing_c.cache_limit,!Flag_parsing_c.cache_prefix) with
+       (None,_) | (_,None) -> ()
+      |        (Some limit,Some prefix) ->
+         let count =
+           Common.cmd_to_list
+             (Printf.sprintf
+                "test -e %s && ls %s/*.ast_raw %s/*.depend_raw | wc -l"
+                prefix prefix prefix) in
+         match count with
+           [c] ->
+             if int_of_string c >= limit
+             then
+               let _ =
+                 Sys.command
+                   (Printf.sprintf "/bin/rm -r %s/*.ast_raw %s/*.depend_raw"
+                      prefix prefix) in
+               ()
+         | _ -> ());
+      (* recompute *)
+      parse_print_error_heuristic None None file)