Coccinelle release 1.0.0-rc4
[bpt/coccinelle.git] / parsing_c / parse_c.ml
index afbffcb..c47afda 100644 (file)
@@ -108,7 +108,7 @@ let print_bad line_error (start_line, end_line) filelines  =
 (* Stats on what was passed/commentized  *)
 (*****************************************************************************)
 
-let commentized xs = xs +> Common.map_filter (function
+let commentized xs = xs +> Common.tail_map_filter (function
   | Parser_c.TCommentCpp (cppkind, ii) ->
       let s = Ast_c.str_of_info ii in
       let legal_passing =
@@ -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
 
@@ -613,7 +634,7 @@ let get_one_elem ~pass tr (file, filelines) =
       (* Call parser *)
       (* -------------------------------------------------- *)
       Common.profile_code_exclusif "YACC" (fun () ->
-        Left (Parser_c.celem (lexer_function ~pass tr) lexbuf_fake)
+       Left (Parser_c.celem (lexer_function ~pass tr) lexbuf_fake)
       )
     with e ->
       LP.restore_typedef_state();
@@ -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
@@ -691,7 +711,7 @@ let find_optional_macro_to_expand2 ~defs toks =
 
   let defs = Common.hash_of_list defs in
 
-  let toks = toks +> Common.map (function
+  let toks = toks +> Common.tail_map (function
 
     (* special cases to undo *)
     | Parser_c.TMacroIterator (s, ii) ->
@@ -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,7 @@ 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 +844,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 +1034,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. *)
 
@@ -1048,10 +1080,11 @@ let parse_cache file =
     (* could add some of the flags of flag_parsing_c.ml *)
     []
   in
-  Common.cache_computation_robust
+  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 () -> parse_print_error_heuristic None None file)