287 lines
8.9 KiB
OCaml
287 lines
8.9 KiB
OCaml
(* Yoann Padioleau
|
|
*
|
|
* Copyright (C) 2002-2008 Yoann Padioleau
|
|
* Copyright (C) 2011 Facebook
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License (GPL)
|
|
* version 2 as published by the Free Software Foundation.
|
|
*
|
|
* This program 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
|
|
* file license.txt for more details.
|
|
*)
|
|
open Common
|
|
|
|
module Flag = Flag_parsing_cpp
|
|
module Ast = Ast_cpp
|
|
|
|
module TH = Token_helpers_cpp
|
|
module Parser = Parser_cpp
|
|
module PI = Parse_info
|
|
|
|
open Parser_cpp
|
|
open Token_views_cpp
|
|
|
|
(*****************************************************************************)
|
|
(* Wrappers *)
|
|
(*****************************************************************************)
|
|
let pr2, _pr2_once = Common2.mk_pr2_wrappers Flag_parsing_cpp.verbose_parsing
|
|
|
|
(*****************************************************************************)
|
|
(* Helpers *)
|
|
(*****************************************************************************)
|
|
|
|
(*
|
|
* 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
|
|
* that we don't know yet. If we print everything, then we can easily
|
|
* get lost with too much verbose tracing information. So those
|
|
* functions "filter" some messages. So our heuristics are still good,
|
|
* there is no more (or not that much) hardcoded linux stuff.
|
|
*)
|
|
let msg_gen is_known printer s =
|
|
if not (!Flag.filter_msg)
|
|
then printer s
|
|
else
|
|
if not (is_known s)
|
|
then printer s
|
|
|
|
let pos ii = Parse_info.string_of_info ii
|
|
|
|
(*****************************************************************************)
|
|
(* Some debugging functions *)
|
|
(*****************************************************************************)
|
|
|
|
let pr2_pp s =
|
|
if !Flag.debug_pp
|
|
then Common.pr2 ("PP-" ^ s)
|
|
|
|
let pr2_cplusplus s =
|
|
if !Flag.debug_cplusplus
|
|
then Common.pr2 ("C++-" ^ s)
|
|
|
|
let pr2_typedef s =
|
|
if !Flag.debug_typedef
|
|
then Common.pr2 ("TYPEDEF-" ^ s)
|
|
|
|
|
|
let msg_change_tok tok =
|
|
match tok with
|
|
|
|
(* mostly in parsing_hacks_define.ml *)
|
|
|
|
| TIdent_Define (_s, _ii) ->
|
|
()
|
|
| TOPar_Define (_ii) ->
|
|
()
|
|
| TCommentNewline_DefineEndOfMacro _ ->
|
|
()
|
|
|
|
(* mostly in parsing_hacks.ml *)
|
|
|
|
| TIdent_Typedef (s, ii) ->
|
|
(* todo? also do LP.add_typedef_root s ??? *)
|
|
s +> msg_gen (fun s ->
|
|
match s with
|
|
| "u_char" | "u_short" | "u_int" | "u_long"
|
|
| "u8" | "u16" | "u32" | "u64"
|
|
| "s8" | "s16" | "s32" | "s64"
|
|
| "__u8" | "__u16" | "__u32" | "__u64"
|
|
-> true
|
|
| "acpi_handle" | "acpi_status" -> true
|
|
| "FILE" | "DIR" -> true
|
|
| s when s =~ ".*_t$" -> true
|
|
| _ -> false
|
|
)
|
|
(fun s -> pr2_typedef (spf "promoting %s at %s " s (pos ii)))
|
|
|
|
(* mostly in parsing_hacks_pp.ml *)
|
|
|
|
(* cppext: *)
|
|
|
|
| TComment_Pp (directive, ii) ->
|
|
let s = PI.str_of_info ii in
|
|
(match directive, s with
|
|
| Token_cpp.CppMacro, _ ->
|
|
pr2_pp (spf "MACRO: commented at %s" (pos ii))
|
|
|
|
| Token_cpp.CppDirective, _ when s =~ "#define.*" ->
|
|
pr2_pp (spf "DEFINE: commented at %s" (pos ii));
|
|
| Token_cpp.CppDirective, _ when s =~ "#include.*" ->
|
|
pr2_pp (spf "INCLUDE: commented at %s" (pos ii));
|
|
| Token_cpp.CppDirective, _ when s =~ "#if.*" ->
|
|
pr2_pp (spf "IFDEF: commented at %s" (pos ii));
|
|
| Token_cpp.CppDirective, _ when s =~ "#undef.*" ->
|
|
pr2_pp (spf "UNDEF: commented at %s" (pos ii));
|
|
| Token_cpp.CppDirective, _ ->
|
|
pr2_pp (spf "OTHER: commented directive at %s" (pos ii));
|
|
| _ ->
|
|
(* todo? *)
|
|
()
|
|
)
|
|
|
|
| TOBrace_DefineInit ii ->
|
|
pr2_pp (spf "DEFINE: initializer at %s" (pos ii))
|
|
|
|
| TIdent_MacroString ii ->
|
|
let s = PI.str_of_info ii in
|
|
s +> msg_gen (fun s ->
|
|
match s with
|
|
| "REVISION" | "UTS_RELEASE" | "SIZE_STR" | "DMA_STR"
|
|
-> true
|
|
(* s when s =~ ".*STR.*" -> true *)
|
|
| _ -> false
|
|
)
|
|
(fun s -> pr2_pp (spf "MACRO: string-macro %s at %s " s (pos ii)))
|
|
|
|
| TIdent_MacroStmt ii ->
|
|
pr2_pp (spf "MACRO: stmt-macro at %s" (pos ii));
|
|
|
|
| TIdent_MacroDecl (s, ii) ->
|
|
s +> msg_gen (fun s ->
|
|
match s with
|
|
| "DECLARE_MUTEX" | "DECLARE_COMPLETION" | "DECLARE_RWSEM"
|
|
| "DECLARE_WAITQUEUE" | "DECLARE_WAIT_QUEUE_HEAD"
|
|
| "DEFINE_SPINLOCK" | "DEFINE_TIMER"
|
|
| "DEVICE_ATTR" | "CLASS_DEVICE_ATTR" | "DRIVER_ATTR"
|
|
| "SENSOR_DEVICE_ATTR"
|
|
| "LIST_HEAD"
|
|
| "DECLARE_WORK" | "DECLARE_TASKLET"
|
|
| "PORT_ATTR_RO" | "PORT_PMA_ATTR"
|
|
| "DECLARE_BITMAP"
|
|
-> true
|
|
(*
|
|
| s when s =~ "^DECLARE_.*" -> true
|
|
| s when s =~ ".*_ATTR$" -> true
|
|
| s when s =~ "^DEFINE_.*" -> true
|
|
| s when s =~ "NS_DECL.*" -> true
|
|
*)
|
|
| _ -> false
|
|
)
|
|
(fun _s -> pr2_pp (spf "MACRO: macro-declare at %s" (pos ii)))
|
|
|
|
| Tconst_MacroDeclConst ii ->
|
|
pr2_pp (spf "MACRO: retag const at %s" (pos ii))
|
|
|
|
| TAny_Action ii ->
|
|
pr2_pp (spf "ACTION: retag at %s" (pos ii))
|
|
|
|
| TCPar_EOL ii ->
|
|
pr2_pp (spf "MISC: retagging ) %s" (pos ii))
|
|
|
|
(* mostly in parsing_hacks_cpp.ml *)
|
|
|
|
(* c++ext: *)
|
|
| TComment_Cpp (directive, ii) ->
|
|
let s = PI.str_of_info ii in
|
|
(match directive, s with
|
|
| Token_cpp.CplusplusTemplate, _ ->
|
|
pr2_cplusplus (spf "COM-TEMPLATE: commented at %s" (pos ii))
|
|
| Token_cpp.CplusplusQualifier, _ ->
|
|
pr2_cplusplus (spf "COM-QUALIFIER: commented at %s" (pos ii))
|
|
)
|
|
|
|
| TOPar_CplusplusInit ii ->
|
|
pr2_cplusplus (spf "constructor initializer at %s" (pos ii))
|
|
|
|
| TOCro_new ii | TCCro_new ii ->
|
|
pr2_cplusplus (spf "new [] at %s" (pos ii))
|
|
|
|
| TInf_Template ii | TSup_Template ii ->
|
|
pr2_cplusplus (spf "template <> at %s" (pos ii))
|
|
|
|
| Tchar_Constr ii | Tint_Constr ii | Tfloat_Constr ii | Tdouble_Constr ii
|
|
| Tshort_Constr ii | Tlong_Constr ii | Tbool_Constr ii
|
|
| Tunsigned_Constr ii | Tsigned_Constr ii
|
|
->
|
|
pr2_cplusplus(spf "constructed object builtin at %s" (pos ii));
|
|
| TIdent_TypedefConstr (s, ii) ->
|
|
pr2_cplusplus (spf "constructed object %s at %s" s (pos ii))
|
|
|
|
| TIdent_ClassnameInQualifier (s, ii) ->
|
|
pr2_cplusplus (spf "CLASSNAME: in qualifier context %s at %s " s (pos ii))
|
|
| TIdent_Constructor (s, ii) ->
|
|
pr2_cplusplus (spf "CONSTRUCTOR: found %s at %s " s (pos ii))
|
|
|
|
| TIdent_Templatename (s, ii) ->
|
|
pr2_cplusplus (spf "TEMPLATENAME: found %s at %s" s (pos ii))
|
|
|
|
| TColCol_BeforeTypedef ii ->
|
|
pr2_typedef (spf "RECLASSIF colcol to colcol2 at %s" (pos ii))
|
|
|
|
| TIdent_ClassnameInQualifier_BeforeTypedef (s, ii) ->
|
|
pr2_typedef (spf "RECLASSIF class in qualifier %s at %s" s (pos ii))
|
|
| TIdent_TemplatenameInQualifier_BeforeTypedef (s, ii) ->
|
|
pr2_typedef (spf "RECLASSIF template in qualifier %s at %s" s (pos ii))
|
|
|
|
| _ ->
|
|
raise Todo
|
|
|
|
let msg_context t ctx =
|
|
let ctx_str =
|
|
match ctx with
|
|
| InParameter -> "InParameter"
|
|
| InArgument -> "InArgument"
|
|
| _ -> raise Impossible
|
|
in
|
|
pr2_cplusplus (spf "CONTEXT: %s at %s" ctx_str (pos (TH.info_of_tok t)))
|
|
|
|
|
|
|
|
let change_tok extended_tok tok =
|
|
msg_change_tok tok;
|
|
|
|
(* otherwise parse_c will be lost if don't find a EOF token
|
|
* why? because paren detection had a pb because of
|
|
* some ifdef-exp?
|
|
*)
|
|
if TH.is_eof extended_tok.t
|
|
then pr2 "PB: wierd, I try to tag an EOF token as something else"
|
|
else extended_tok.t <- tok
|
|
|
|
let fresh_tok tok =
|
|
msg_change_tok tok;
|
|
tok
|
|
|
|
(* normally the caller have first filtered the set of tokens to have
|
|
* a clearer "view" to work on
|
|
*)
|
|
let set_as_comment cppkind x =
|
|
assert(not (TH.is_real_comment x.t));
|
|
change_tok x (TComment_Pp (cppkind, TH.info_of_tok x.t))
|
|
|
|
(*****************************************************************************)
|
|
(* The regexp and basic view definitions *)
|
|
(*****************************************************************************)
|
|
|
|
(*
|
|
val regexp_macro: Str.regexp
|
|
val regexp_annot: Str.regexp
|
|
val regexp_declare: Str.regexp
|
|
val regexp_foreach: Str.regexp
|
|
val regexp_typedef: Str.regexp
|
|
*)
|
|
|
|
(* opti: better to built then once and for all, especially regexp_foreach *)
|
|
|
|
let regexp_macro = Str.regexp
|
|
"^[A-Z_][A-Z_0-9]*$"
|
|
|
|
(* linuxext: *)
|
|
let regexp_declare = Str.regexp
|
|
".*DECLARE.*"
|
|
|
|
(* firefoxext: *)
|
|
let regexp_ns_decl_like = Str.regexp
|
|
("\\(" ^
|
|
"NS_DECL_\\|NS_DECLARE_\\|NS_IMPL_\\|" ^
|
|
"NS_IMPLEMENT_\\|NS_INTERFACE_\\|NS_FORWARD_\\|NS_HTML_\\|" ^
|
|
"NS_DISPLAY_\\|NS_IMPL_\\|" ^
|
|
"TX_DECL_\\|DOM_CLASSINFO_\\|NS_CLASSINFO_\\|IMPL_INTERNAL_\\|" ^
|
|
"ON_\\|EVT_\\|NS_UCONV_\\|NS_GENERIC_\\|NS_COM_" ^
|
|
"\\).*")
|
|
|
|
|