permit multiline comments and strings in macros
[bpt/coccinelle.git] / parsing_c / parsing_hacks.ml
index c3ac6b7..0e96e67 100644 (file)
@@ -45,7 +45,6 @@ let msg_gen cond is_known printer s =
       if not (is_known s)
       then printer s
 
-
 (* In the following, there are some harcoded names of types or macros
  * but they are not used by our heuristics! They are just here to
  * enable to detect false positive by printing only the typedef/macros
@@ -426,11 +425,11 @@ let rec define_line_1 acc xs =
   | TDefine ii::xs ->
       let line = Ast_c.line_of_info ii in
       let acc = (TDefine ii) :: acc in
-      define_line_2 acc line ii xs
+      define_line_2 acc ((=|=) line) ii xs
   | TUndef ii::xs ->
       let line = Ast_c.line_of_info ii in
       let acc = (TUndef ii) :: acc in
-      define_line_2 acc line ii xs
+      define_line_2 acc ((=|=) line) ii xs
   | TCppEscapedNewline ii::xs ->
       pr2 ("SUSPICIOUS: a \\ character appears outside of a #define at");
       pr2 (Ast_c.strloc_of_info ii);
@@ -438,14 +437,14 @@ let rec define_line_1 acc xs =
       define_line_1 acc xs
   | x::xs -> define_line_1 (x::acc) xs
 
-and define_line_2 acc line lastinfo xs =
+and define_line_2 acc lineOk lastinfo xs =
   match xs with
   | [] ->
       (* should not happened, should meet EOF before *)
       pr2 "PB: WEIRD";
       List.rev (mark_end_define lastinfo::acc)
   | x::xs ->
-      let line' = TH.line_of_tok x in
+      let line = TH.line_of_tok x in
       let info = TH.info_of_tok x in
 
       (match x with
@@ -454,12 +453,16 @@ and define_line_2 acc line lastinfo xs =
          let acc = (EOF ii) :: acc in
           define_line_1 acc xs
       | TCppEscapedNewline ii ->
-          if (line' <> line) then pr2 "PB: WEIRD: not same line number";
+          if not (lineOk line) then pr2 "PB: WEIRD: not same line number";
          let acc = (TCommentSpace ii) :: acc in
-          define_line_2 acc (line+1) info xs
+          define_line_2 acc ((=|=) (line + 1)) info xs
+      | TComment _ when lineOk line ->
+          define_line_2 (x::acc) (function x -> true) info xs
+      | TString _ when lineOk line ->
+          define_line_2 (x::acc) (function x -> true) info xs
       | x ->
-          if line' =|= line
-          then define_line_2 (x::acc) line info xs
+          if lineOk line
+          then define_line_2 (x::acc) ((=|=) line) info xs
           else
            (* Put end of line token before the newline.  A newline at least
               must be there because the line changed and because we saw a
@@ -917,6 +920,7 @@ let rec find_string_macro_paren xs =
           xs +> List.iter (fun tok ->
             match tok with
             | PToken({tok = TIdent (s,_)} as id) ->
+
                 msg_stringification s;
                 id.tok <- TMacroString (s, TH.info_of_tok id.tok);
             | _ -> ()
@@ -1032,7 +1036,7 @@ let rec find_macro_paren xs =
 
   (* string macro variable, before case *)
   | PToken ({tok = (TString _ | TMacroString _)})::PToken ({tok = TIdent (s,_)} as id)
-      ::xs ->
+      ::xs when not !Flag.c_plus_plus ->
 
       msg_stringification s;
       id.tok <- TMacroString (s, TH.info_of_tok id.tok);
@@ -1250,6 +1254,7 @@ let rec find_macro_lineparen xs =
              | TCBrace _ when ctx <> InFunction -> false
              | TPtVirg _
              | TDotDot _
+             | TWhy _
                -> false
              | tok when TH.is_binary_operator tok -> false
 
@@ -1299,6 +1304,7 @@ let rec find_macro_lineparen xs =
             | TCBrace _ when ctx <> InFunction -> false
             | TPtVirg _
             | TDotDot _
+            | TWhy _
                 -> false
             | tok when TH.is_binary_operator tok -> false
 
@@ -1360,6 +1366,7 @@ let rec find_macro_lineparen xs =
             | TPtVirg _ -> false
             | TOr _ -> false
             | TCBrace _ when ctx <> InFunction -> false
+            | TWhy _ -> false
             | tok when TH.is_binary_operator tok -> false
 
             | _ -> true
@@ -1700,9 +1707,17 @@ let not_struct_enum = function
   | (Parser_c.Tstruct _ | Parser_c.Tunion _ | Parser_c.Tenum _)::_ -> false
   | _ -> true
 
-let pointer = function
-    TMul _ -> true
-  | TAnd _ when !Flag.c_plus_plus -> true
+let pointer ?(followed_by=fun _ -> true) 
+    ?(followed_by_more=fun _ -> true) ts = 
+  let rec loop ts = 
+    match ts with
+    | TMul _ :: rest -> loop rest
+    | TAnd _ :: rest when !Flag.c_plus_plus -> loop rest
+    | t :: ts' -> followed_by t && followed_by_more ts' 
+    | [] -> failwith "unexpected end of token stream" in
+  match ts with
+  | TMul _ :: rest -> loop rest
+  | TAnd _ :: rest when !Flag.c_plus_plus -> loop rest
   | _ -> false
 
 let ident = function
@@ -1715,7 +1730,7 @@ let is_type = function
   | Tchar _
   | Tfloat _
   | Tdouble _
-      (* christia: not sure what these are? *)
+
   | Tsize_t _
   | Tssize_t _
   | Tptrdiff_t _
@@ -1766,13 +1781,19 @@ let paren_before_comma l =
 
 let lookahead2 ~pass next before =
   match (next, before) with
-    
+      
   (* c++ hacks *)
   (* yy xx(   and in function *)
   | TOPar i1::_,              TIdent(s,i2)::TypedefIdent _::_
       when !Flag.c_plus_plus && (LP.current_context () = (LP.InFunction)) ->
         pr2_cpp("constructed_object: "  ^s);
         TOParCplusplusInit i1
+  | TOPar i1::_,              TIdent(s,i2)::ptr
+      when !Flag.c_plus_plus 
+         && pointer ~followed_by:(function TypedefIdent _ -> true | _ -> false) ptr
+         && (LP.current_context () = (LP.InFunction)) ->
+        pr2_cpp("constructed_object: "  ^s);
+        TOParCplusplusInit i1
   | TypedefIdent(s,i)::TOPar i1::_,_
       when !Flag.c_plus_plus && (LP.current_context () = (LP.InFunction)) ->
        TIdent(s,i)
@@ -1801,80 +1822,110 @@ let lookahead2 ~pass next before =
       TypedefIdent (s, i1)
 
        (* christia *)
-       (* xx const tt *)
-  | (TIdent (s, i1)::(Tconst _|Tvolatile _|Trestrict _)::type_::_  , _) when not_struct_enum before
-      && is_type type_
-        ->
 
+       (* delete[] *)
+  | (TOCro i1 :: _, Tdelete _ :: _) 
+    when !Flag.c_plus_plus ->
+      TCommentCpp (Token_c.CppDirective, i1)
+       (* delete[] *)
+  | (TCCro i1 :: _, Tdelete _ :: _) 
+    when !Flag.c_plus_plus ->
+      TCommentCpp (Token_c.CppDirective, i1)
+
+       (* extern "_" tt *)
+  | ((TString ((s, _), i1) | TMacroString (s, i1)) :: _ , Textern _ :: _) 
+    when !Flag.c_plus_plus ->
+         TCommentCpp (Token_c.CppDirective, i1)
+
+       (* ) const { *)
+  | (Tconst i1 :: TOBrace _ :: _ , TCPar _ :: _) 
+    when !Flag.c_plus_plus ->
+         TCommentCpp (Token_c.CppDirective, i1)
+
+       (* xx const tt *)
+  | (TIdent (s, i1)::(Tconst _|Tvolatile _|Trestrict _)::type_::_  , _) 
+    when not_struct_enum before
+       && is_type type_ ->
          TCommentCpp (Token_c.CppDirective, i1)
 
        (* xx struct *)
-  | (TIdent (s, i1)::Tstruct _::_  , _) when not_struct_enum before
-        ->
+  | (TIdent (s, i1)::Tstruct _::_  , _) 
+    when not_struct_enum before ->
          TCommentCpp (Token_c.CppDirective, i1)
 
        (* xx tt *)
-  | (TIdent (s, i1)::type_::_  , _) when not_struct_enum before
-      && is_type type_
-        ->
+  | (TIdent (s, i1)::type_::_  , _) 
+    when not_struct_enum before
+       && is_type type_ ->
          TCommentCpp (Token_c.CppDirective, i1)
 
        (* tt xx yy *)
-  | (TIdent (s, i1)::TIdent (s2, i2)::_  , seen::_) when not_struct_enum before
-      && is_type seen
-        ->
+  | (TIdent (s, i1)::TIdent (s2, i2)::_  , seen::_) 
+    when not_struct_enum before
+       && is_type seen ->
          if is_macro s2 then
            TIdent (s, i1)
          else
            TCommentCpp (Token_c.CppDirective, i1)
 
-  | (TIdent (s2, i2)::_  , TIdent (s, i1)::seen::_) when not_struct_enum before
-      && is_macro s2 && is_type seen
-        ->
+        (* exception to next rule *)
+  | (TIdent (s2, i2)::TOPar _::_ , TIdent (s1, i1)::seen::_)
+    when not_struct_enum before
+        && is_macro s2 && is_type seen ->
+          TIdent (s2, i2)
+
+  | (TIdent (s2, i2)::_  , TIdent (s, i1)::seen::_) 
+    when not_struct_enum before
+       && is_macro s2 && is_type seen ->
          TCommentCpp (Token_c.CppDirective, i2)
 
        (* tt xx * *)
-  | (TIdent (s, i1)::ptr::_  , seen::_) when not_struct_enum before
-      && pointer ptr && is_type seen
-        ->
+  | (TIdent (s, i1)::ptr  , seen::_) 
+    when not_struct_enum before
+       && pointer ptr && is_type seen ->
          TCommentCpp (Token_c.CppDirective, i1)
 
        (* tt * xx yy *)
-  | (TIdent (s, i1)::TIdent(s2, i2)::_  , ptr::_) when not_struct_enum before
-      && pointer ptr
-        ->
+  | (TIdent (s, i1)::TIdent(s2, i2)::_  , ptr
+    when not_struct_enum before
+       && pointer ptr ->
          if is_macro s2 then
            TIdent (s, i1)
          else
            TCommentCpp (Token_c.CppDirective, i1)
 
+  (* exception to next rule *)
+  | (TIdent (s2, i2)::TOPar _::_ , TIdent (s1, i1)::ptr)
+      when not_struct_enum before
+        && is_macro s2 && pointer ptr ->
+    TIdent (s2, i2)
        (* tt * xx yy *)
-  | (TIdent(s2, i2)::_  , TIdent (s, i1)::ptr::_) when not_struct_enum before
-      && is_macro s2 && pointer ptr
-        ->
+  | (TIdent(s2, i2)::_  , TIdent (s, i1)::ptr
+    when not_struct_enum before
+       && is_macro s2 && pointer ptr ->
          TCommentCpp (Token_c.CppDirective, i2)
 
         (* exception to next rule *)
-  | (TIdent(s2, i2)::TOPar _ :: _ , TIdent(s, i1)::seen::_) when not_struct_enum before
-      && is_macro s2 && is_type seen
-        ->
+  | (TIdent(s2, i2)::TOPar _ :: _ , TIdent(s, i1)::seen::_) 
+    when not_struct_enum before
+       && is_macro s2 && is_type seen ->
          TIdent(s2, i2)
        (* tt xx yy *)
-  | (TIdent(s2, i2)::_  , TIdent(s, i1)::seen::_) when not_struct_enum before
-      && is_macro s2 && is_type seen
-        ->
+  | (TIdent(s2, i2)::_  , TIdent(s, i1)::seen::_) 
+    when not_struct_enum before
+       && is_macro s2 && is_type seen ->
          TCommentCpp (Token_c.CppDirective, i2)
 
   (*  xx * yy      AND  in paramdecl *)
-  | (TIdent (s, i1)::ptr::TIdent (s2, i2)::_ , _)
+  | (TIdent (s, i1)::ptr , _)
     when not_struct_enum before && (LP.current_context() =*= LP.InParameter)
-      && pointer ptr && ok_typedef s
-      ->
-
+       && pointer ~followed_by:(function TIdent _ -> true | _ -> false) ptr
+       && ok_typedef s ->
       msg_typedef s i1 14; LP.add_typedef_root s;
       TypedefIdent (s, i1)
 
-  (* xx yy ( *)
+  (* xx MM ( *)
+  (* exception to next rule *)
   | (TIdent (s, i1)::TIdent (s2, i2)::TOPar _::_  , _) when not_struct_enum before
       && ok_typedef s && is_macro s2
         ->
@@ -1918,8 +1969,9 @@ let lookahead2 ~pass next before =
 
   (* xx* [,)] *)
   (* specialcase:  [,(] xx* [,)] *)
-  | (TIdent (s, i1)::ptr::(TComma _|TCPar _)::_ , (*(TComma _|TOPar _)::*)_ )
-    when pointer ptr && not_struct_enum before
+  | (TIdent (s, i1)::ptr , (*(TComma _|TOPar _)::*)_ )
+    when pointer ~followed_by:(function TComma _ |TCPar _ -> true | _ -> false) ptr
+       && not_struct_enum before
         (* && !LP._lexer_hint = Some LP.ParameterDeclaration *)
       && ok_typedef s
     ->
@@ -1963,9 +2015,10 @@ let lookahead2 ~pass next before =
 
 
   (* xx * const *)
-  | (TIdent (s, i1)::ptr::(Tconst _ | Tvolatile _|Trestrict _)::_ , _ )
-      when pointer ptr && not_struct_enum before
-      && ok_typedef s
+  | (TIdent (s, i1)::ptr , _ )
+      when pointer ~followed_by:(function Tconst _ | Tvolatile _ | Trestrict _ -> true | _ -> false) ptr
+         && not_struct_enum before
+         && ok_typedef s
       ->
 
       (* && !LP._lexer_hint = Some LP.ParameterDeclaration *)
@@ -2007,9 +2060,10 @@ let lookahead2 ~pass next before =
   (*------------------------------------------------------------*)
 
   (* static xx * yy  *)
-  | (TIdent (s, i1)::ptr::TIdent (s2, i2)::_ ,
+  | (TIdent (s, i1)::ptr ,
      (Tregister _|Tstatic _  |Tvolatile _|Tconst _|Trestrict _)::_) when
-      pointer ptr && ok_typedef s
+      pointer ~followed_by:(function TIdent _ -> true | _ -> false) ptr
+        && ok_typedef s
         ->
 
       msg_typedef s i1 13; LP.add_typedef_root s;
@@ -2019,9 +2073,11 @@ let lookahead2 ~pass next before =
 
 
   (*  xx * yy,      AND  in paramdecl *)
-  | (TIdent (s, i1)::ptr::TIdent (s2, i2)::TComma _::_ , _)
+  | (TIdent (s, i1)::ptr , _)
     when not_struct_enum before && (LP.current_context() =*= LP.InParameter)
-      && pointer ptr && ok_typedef s
+       && pointer ~followed_by:(function TIdent _ -> true | _ -> false)
+              ~followed_by_more:(function TComma _ :: _ -> true | _ -> false) ptr
+       && ok_typedef s
       ->
 
       msg_typedef s i1 14; LP.add_typedef_root s;
@@ -2031,28 +2087,34 @@ let lookahead2 ~pass next before =
   (*  xx * yy ;     AND in Toplevel, except when have = before  *)
   | (TIdent (s, i1)::TMul _::TIdent (s2, i2)::TPtVirg _::_ , TEq _::_) ->
       TIdent (s, i1)
-  | (TIdent (s, i1)::ptr::TIdent (s2, i2)::TPtVirg _::_ , _)
-    when not_struct_enum before && pointer ptr &&
-      (LP.is_top_or_struct (LP.current_context ()))
+  | (TIdent (s, i1)::ptr , _)
+    when not_struct_enum before 
+       && pointer ~followed_by:(function TIdent _ -> true | _ -> false)
+              ~followed_by_more:(function TPtVirg _ :: _ -> true | _ -> false) ptr
+       && (LP.is_top_or_struct (LP.current_context ()))
       ->
 
       msg_typedef s i1 15; LP.add_typedef_root s;
       TypedefIdent (s, i1)
 
   (*  xx * yy ,     AND in Toplevel  *)
-  | (TIdent (s, i1)::ptr::TIdent (s2, i2)::TComma _::_ , _)
+  | (TIdent (s, i1)::ptr , _)
     when not_struct_enum before && (LP.current_context () =*= LP.InTopLevel)
-      && ok_typedef s && pointer ptr
+       && ok_typedef s 
+       && pointer ~followed_by:(function TIdent _ -> true | _ -> false)
+              ~followed_by_more:(function TComma _ :: _ -> true | _ -> false) ptr
       ->
 
       msg_typedef s i1 16; LP.add_typedef_root s;
       TypedefIdent (s, i1)
 
   (*  xx * yy (     AND in Toplevel  *)
-  | (TIdent (s, i1)::ptr::TIdent (s2, i2)::TOPar _::_ , _)
+  | (TIdent (s, i1)::ptr , _)
     when not_struct_enum before
-      && (LP.is_top_or_struct (LP.current_context ()))
-      && ok_typedef s && pointer ptr
+       && (LP.is_top_or_struct (LP.current_context ()))
+       && ok_typedef s 
+       && pointer ~followed_by:(function TIdent _ -> true | _ -> false)
+              ~followed_by_more:(function TOPar _ :: _ -> true | _ -> false) ptr
       ->
 
       msg_typedef s i1 17; LP.add_typedef_root s;
@@ -2060,10 +2122,12 @@ let lookahead2 ~pass next before =
 
   (* xx * yy [ *)
   (* todo? enough ? cos in struct def we can have some expression ! *)
-  | (TIdent (s, i1)::ptr::TIdent (s2, i2)::TOCro _::_ , _)
-    when not_struct_enum before &&
-      (LP.is_top_or_struct (LP.current_context ()))
-      && ok_typedef s && pointer ptr
+  | (TIdent (s, i1)::ptr , _)
+    when not_struct_enum before 
+       && (LP.is_top_or_struct (LP.current_context ()))
+       && ok_typedef s 
+       && pointer ~followed_by:(function TIdent _ -> true | _ -> false)
+              ~followed_by_more:(function TOCro _ :: _ -> true | _ -> false) ptr
       ->
 
       msg_typedef s i1 18;  LP.add_typedef_root s;
@@ -2093,9 +2157,11 @@ let lookahead2 ~pass next before =
      *)
 
   (*  xx * yy =  *)
-  | (TIdent (s, i1)::ptr::TIdent (s2, i2)::TEq _::_ , _)
+  | (TIdent (s, i1)::ptr , _)
     when not_struct_enum before
-      && ok_typedef s && pointer ptr
+       && ok_typedef s 
+       && pointer ~followed_by:(function TIdent _ -> true | _ -> false)
+              ~followed_by_more:(function TEq _ :: _ -> true | _ -> false) ptr
       ->
 
       msg_typedef s i1 21; LP.add_typedef_root s;
@@ -2103,9 +2169,11 @@ let lookahead2 ~pass next before =
 
 
   (*  xx * yy)      AND in paramdecl *)
-  | (TIdent (s, i1)::ptr::TIdent (s2, i2)::TCPar _::_ , _)
-      when not_struct_enum before && (LP.current_context () =*= LP.InParameter)
-      && ok_typedef s && pointer ptr
+  | (TIdent (s, i1)::ptr , _)
+    when not_struct_enum before && (LP.current_context () =*= LP.InParameter)
+       && ok_typedef s 
+       && pointer ~followed_by:(function TIdent _ -> true | _ -> false)
+              ~followed_by_more:(function TCPar _ :: _ -> true | _ -> false) ptr
         ->
 
       msg_typedef s i1 22; LP.add_typedef_root s;
@@ -2113,9 +2181,11 @@ let lookahead2 ~pass next before =
 
 
   (*  xx * yy; *) (* wrong ? *)
-  | (TIdent (s, i1)::ptr::TIdent (s2, i2)::TPtVirg _::_ ,
-     (TOBrace _| TPtVirg _)::_)  when not_struct_enum before
-      && ok_typedef s & pointer ptr
+  | (TIdent (s, i1)::ptr ,
+     (TOBrace _| TPtVirg _)::_) when not_struct_enum before
+       && ok_typedef s 
+       && pointer ~followed_by:(function TIdent _ -> true | _ -> false)
+              ~followed_by_more:(function TPtVirg _ :: _ -> true | _ -> false) ptr
         ->
 
       msg_typedef s i1 23;  LP.add_typedef_root s;
@@ -2124,9 +2194,11 @@ let lookahead2 ~pass next before =
 
 
   (*  xx * yy,  and ';' before xx *) (* wrong ? *)
-  | (TIdent (s, i1)::ptr::TIdent (s2, i2)::TComma _::_ ,
+  | (TIdent (s, i1)::ptr ,
      (TOBrace _| TPtVirg _)::_) when
-      ok_typedef s && pointer ptr
+      ok_typedef s 
+       && pointer ~followed_by:(function TIdent _ -> true | _ -> false)
+              ~followed_by_more:(function TComma _ :: _ -> true | _ -> false) ptr
     ->
 
       msg_typedef s i1 24; LP.add_typedef_root s;
@@ -2134,10 +2206,11 @@ let lookahead2 ~pass next before =
 
 
   (* xx_t * yy *)
-  | (TIdent (s, i1)::ptr::TIdent (s2, i2)::_ , _)
+  | (TIdent (s, i1)::ptr , _)
       when s ==~ regexp_typedef && not_struct_enum before
         (* struct user_info_t sometimes *)
-      && ok_typedef s && pointer ptr
+       && ok_typedef s 
+        && pointer ~followed_by:(function TIdent _ -> true | _ -> false) ptr
         ->
 
       msg_typedef s i1 25; LP.add_typedef_root s;
@@ -2145,12 +2218,21 @@ let lookahead2 ~pass next before =
 
   (*  xx ** yy *)  (* wrong ? *)
   | (TIdent (s, i1)::TMul _::TMul _::TIdent (s2, i2)::_ , _)
+    when not_struct_enum before
+       && (LP.current_context() =*= LP.InParameter)
+       && ok_typedef s
+    ->
+
+      msg_typedef s i1 26; LP.add_typedef_root s;
+      TypedefIdent (s, i1)
+
+  (*  xx ** yy *)  (* wrong ? *)
+  | (TIdent (s, i1)::TMul _::TMul _::TIdent (s2, i2)::_ , (TOBrace _ | TPtVirg _)::_)
     when not_struct_enum before
         (* && !LP._lexer_hint = Some LP.ParameterDeclaration *)
        && ok_typedef s
        (* christia : this code catches 'a * *b' which is wrong 
         *)
-       && true
     ->
 
       msg_typedef s i1 26; LP.add_typedef_root s;
@@ -2224,8 +2306,10 @@ let lookahead2 ~pass next before =
 
 
   (*  (xx * ) yy *)
-  | (TIdent (s, i1)::ptr::TCPar _::TIdent (s2, i2)::_ , (TOPar info)::_)
-    when ok_typedef s && pointer ptr
+  | (TIdent (s, i1)::ptr, (TOPar info)::_)
+    when ok_typedef s 
+       && pointer ~followed_by:(function TCPar _ -> true | _ -> false)
+              ~followed_by_more:(function TIdent _ :: _ -> true | _ -> false) ptr
         ->
 
       msg_typedef s i1 32; LP.add_typedef_root s;