package pfff

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file parsing_hacks_lib.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
(* 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
module Flag_cpp = Flag_parsing_cpp
module PI = Parse_info

module TH = Token_helpers_cpp

open Parser_cpp
open Token_views_cpp

(*****************************************************************************)
(* Wrappers  *)
(*****************************************************************************)
let pr2, _pr2_once = Common2.mk_pr2_wrappers Flag.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_cpp.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_cpp.debug_pp
  then Common.pr2 ("PP-" ^ s)

let pr2_cplusplus s = 
  if !Flag_cpp.debug_cplusplus
  then Common.pr2 ("C++-" ^ s)

let pr2_typedef s = 
  if !Flag_cpp.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_" ^
   "\\).*")


OCaml

Innovation. Community. Security.