Add poc files
This commit is contained in:
parent
30da2412e3
commit
fa600b98f7
220 changed files with 45679 additions and 0 deletions
235
lang_cpp/parsing/pp_token.ml
Normal file
235
lang_cpp/parsing/pp_token.ml
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
(* Yoann Padioleau
|
||||
*
|
||||
* Copyright (C) 2007, 2008 Ecole des Mines de Nantes
|
||||
* 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 Ast = Ast_cpp
|
||||
module Flag = Flag_parsing_cpp
|
||||
module TH = Token_helpers_cpp
|
||||
module Parser = Parser_cpp
|
||||
module Hack = Parsing_hacks_lib
|
||||
|
||||
open Parser_cpp
|
||||
open Token_views_cpp
|
||||
|
||||
(*****************************************************************************)
|
||||
(* Prelude *)
|
||||
(*****************************************************************************)
|
||||
|
||||
(*
|
||||
* CPP functions working at the token level. See pp_ast.ml for cpp functions
|
||||
* working at the AST level (which is very unusual but makes sense in
|
||||
* the coccinelle context for instance).
|
||||
*
|
||||
* Note that because I use a single lexer to work both at the C and cpp level
|
||||
* there are some inconveniencies.
|
||||
* For instance 'for' is a valid name for a macro parameter and macro
|
||||
* body, but is interpreted in a special way by our single lexer, and
|
||||
* so at some places where I expect a TIdent I need also to
|
||||
* handle special cases and accept Tfor, Tif, etc at those places.
|
||||
*
|
||||
* There are multiple issues related to those keywords incorrect tokens.
|
||||
* Those keywords can be:
|
||||
*
|
||||
* - (1) in the name of the macro as in #define inline
|
||||
* - (2) in a parameter of the macro as in #define foo(char) char x;
|
||||
* - (3) in an argument to a macro call as in IDENT(if);
|
||||
*
|
||||
* Case 1 is easy to fix in define_ident in ???
|
||||
*
|
||||
* Case 2 is easy to fix in define_parse below, where we detect such tokens
|
||||
* in the parameters and then replace their occurence in the body with
|
||||
* a TIdent.
|
||||
*
|
||||
* Case 3 is only an issue when the expanded token is not really used
|
||||
* as usual but used for instance in concatenation as in a ## if
|
||||
* when expanded. In the case the grammar this time will not be happy
|
||||
* so this is also easy to fix in cpp_engine.
|
||||
*)
|
||||
|
||||
(*****************************************************************************)
|
||||
(* Wrappers *)
|
||||
(*****************************************************************************)
|
||||
let pr2, _pr2_once = Common2.mk_pr2_wrappers Flag_parsing_cpp.verbose_parsing
|
||||
|
||||
(*****************************************************************************)
|
||||
(* Types *)
|
||||
(*****************************************************************************)
|
||||
|
||||
(* the tokens in the body of the macro are all ExpandedTok *)
|
||||
type define_body = (unit,string list) either * Parser_cpp.token list
|
||||
|
||||
(* TODO:
|
||||
type define_def = string * define_param * define_body
|
||||
and define_param =
|
||||
| NoParam
|
||||
| Params of string list
|
||||
and define_body =
|
||||
| DefineBody of Parser_c.token list
|
||||
| DefineHint of parsinghack_hint
|
||||
|
||||
and parsinghack_hint =
|
||||
| HintIterator
|
||||
| HintDeclarator
|
||||
| HintMacroString
|
||||
| HintMacroStatement
|
||||
| HintAttribute
|
||||
| HintMacroIdentBuilder
|
||||
*)
|
||||
|
||||
|
||||
(*****************************************************************************)
|
||||
(* Apply macro (using standard.h or other defs) *)
|
||||
(*****************************************************************************)
|
||||
(* cpp-builtin part1, macro, using standard.h or other defs *)
|
||||
|
||||
(* Thanks to this function many stuff are not anymore hardcoded in
|
||||
* OCaml code (but are now hardcoded in standard.h ...)
|
||||
*)
|
||||
let (cpp_engine:
|
||||
(string , Parser.token list) assoc -> Parser.token list -> Parser.token list)
|
||||
= fun env xs ->
|
||||
xs +> List.map (fun tok ->
|
||||
match tok with
|
||||
| TIdent (s,_i1) when List.mem_assoc s env -> Common2.assoc s env
|
||||
| x -> [x]
|
||||
)
|
||||
+> List.flatten
|
||||
|
||||
(*
|
||||
* We apply a macro by generating new ExpandedToken and by
|
||||
* commenting the old macro call.
|
||||
*
|
||||
* no need to take care to substitute the macro name itself
|
||||
* that occurs in the macro definition because the macro name is
|
||||
* after fix_token_define a TDefineIdent, no more a TIdent.
|
||||
*)
|
||||
let apply_macro_defs defs xs =
|
||||
|
||||
let rec apply_macro_defs xs =
|
||||
match xs with
|
||||
| [] -> ()
|
||||
|
||||
(* recognized macro of standard.h (or other) *)
|
||||
| PToken ({t=TIdent (s,_i1);_} as id)::Parenthised (xxs,info_parens)::xs
|
||||
when Hashtbl.mem defs s ->
|
||||
Hack.pr2_pp ("MACRO: found known macro = " ^ s);
|
||||
(match Hashtbl.find defs s with
|
||||
| Left (), bodymacro ->
|
||||
pr2 ("macro without param used before parenthize, wierd: " ^ s);
|
||||
(* ex: PRINTP("NCR53C400 card%s detected\n" ANDP(((struct ... *)
|
||||
Hack.set_as_comment (Token_cpp.CppMacroExpanded) id;
|
||||
id.new_tokens_before <- bodymacro;
|
||||
| Right params, bodymacro ->
|
||||
if List.length params = List.length xxs
|
||||
then
|
||||
let xxs' = xxs +> List.map (fun x ->
|
||||
(tokens_of_paren_ordered x) +> List.map (fun x ->
|
||||
TH.visitor_info_of_tok Ast.make_expanded x.t
|
||||
)
|
||||
) in
|
||||
id.new_tokens_before <-
|
||||
cpp_engine (Common2.zip params xxs') bodymacro
|
||||
|
||||
else begin
|
||||
pr2 ("macro with wrong number of arguments, wierd: " ^ s);
|
||||
id.new_tokens_before <- bodymacro;
|
||||
end;
|
||||
(* important to do that after have apply the macro, otherwise
|
||||
* will pass as argument to the macro some tokens that
|
||||
* are all TCommentCpp
|
||||
*)
|
||||
[Parenthised (xxs, info_parens)] +>
|
||||
iter_token_paren (Hack.set_as_comment Token_cpp.CppMacroExpanded);
|
||||
Hack.set_as_comment Token_cpp.CppMacroExpanded id;
|
||||
|
||||
|
||||
|
||||
);
|
||||
apply_macro_defs xs
|
||||
|
||||
| PToken ({t=TIdent (s,_i1);_} as id)::xs
|
||||
when Hashtbl.mem defs s ->
|
||||
Hack.pr2_pp ("MACRO: found known macro = " ^ s);
|
||||
(match Hashtbl.find defs s with
|
||||
| Right _params, _bodymacro ->
|
||||
pr2 ("macro with params but no parens found, wierd: " ^ s);
|
||||
(* dont apply the macro, perhaps a redefinition *)
|
||||
()
|
||||
| Left (), bodymacro ->
|
||||
(* special case when 1-1 substitution, we reuse the token *)
|
||||
(match bodymacro with
|
||||
| [newtok] ->
|
||||
id.t <- (newtok +> TH.visitor_info_of_tok (fun _ ->
|
||||
TH.info_of_tok id.t))
|
||||
|
||||
| _ ->
|
||||
Hack.set_as_comment Token_cpp.CppMacroExpanded id;
|
||||
id.new_tokens_before <- bodymacro;
|
||||
)
|
||||
);
|
||||
apply_macro_defs xs
|
||||
|
||||
(* recurse *)
|
||||
| (PToken _x)::xs -> apply_macro_defs xs
|
||||
| (Parenthised (xxs, _info_parens))::xs ->
|
||||
xxs +> List.iter apply_macro_defs;
|
||||
apply_macro_defs xs
|
||||
|
||||
in
|
||||
apply_macro_defs xs
|
||||
|
||||
(*****************************************************************************)
|
||||
(* Extracting macros (from a standard.h) *)
|
||||
(*****************************************************************************)
|
||||
|
||||
(* assumes have called fix_tokens_define before, so have TOPar_Define *)
|
||||
let rec define_parse xs =
|
||||
match xs with
|
||||
| [] -> []
|
||||
| TDefine _i1::TIdent_Define (s,_i2)::TOPar_Define _i3::xs ->
|
||||
let (tokparams, _, xs) =
|
||||
xs +> Common2.split_when (function TCPar _ -> true | _ -> false) in
|
||||
let (body, _, xs) =
|
||||
xs +> Common2.split_when
|
||||
(function TCommentNewline_DefineEndOfMacro _ -> true | _ -> false) in
|
||||
let params =
|
||||
tokparams +> Common.map_filter (function
|
||||
| TComma _ -> None
|
||||
| TIdent (s, _) -> Some s
|
||||
| x -> Common2.error_cant_have x
|
||||
) in
|
||||
let body = body +> List.map
|
||||
(TH.visitor_info_of_tok Ast.make_expanded) in
|
||||
let def = (s, (Right params, body)) in
|
||||
def::define_parse xs
|
||||
|
||||
| TDefine _i1::TIdent_Define (s,_i2)::xs ->
|
||||
let (body, _, xs) =
|
||||
xs +> Common2.split_when
|
||||
(function TCommentNewline_DefineEndOfMacro _ -> true | _ -> false) in
|
||||
let body = body +> List.map
|
||||
(TH.visitor_info_of_tok Ast.make_expanded) in
|
||||
let def = (s, (Left (), body)) in
|
||||
def::define_parse xs
|
||||
|
||||
| TDefine _i1::_ ->
|
||||
raise Impossible
|
||||
| _x::xs -> define_parse xs
|
||||
|
||||
|
||||
let extract_macros xs =
|
||||
let cleaner = xs +> List.filter (fun x -> not (TH.is_comment x)) in
|
||||
define_parse cleaner
|
||||
Loading…
Add table
Add a link
Reference in a new issue