linux-kernel-mentees.lists.linuxfoundation.org archive mirror
 help / color / mirror / Atom feed
From: Jaskaran Singh <jaskaransingh7654321@gmail.com>
To: cocci@systeme.lip6.fr
Cc: julia.lawall@inria.fr, jaskaransingh7654321@gmail.com,
	linux-kernel-mentees@lists.linuxfoundation.org
Subject: [Linux-kernel-mentees] [PATCH v3 01/26] parsing_cocci: Add Function Prototype token
Date: Fri, 20 Mar 2020 12:31:32 +0530	[thread overview]
Message-ID: <20200320070157.4206-2-jaskaransingh7654321@gmail.com> (raw)
In-Reply-To: <20200320070157.4206-1-jaskaransingh7654321@gmail.com>

To add the types ParenType and FunctionType to the SmPL AST, a
reduce/reduce conflict with the funproto rule of the SmPL parser
must be resolved. This requires explicitly identifying a function
prototype by use of a token (TFunProto).

While the correct method of identifying a function prototype would be to
check if an identifier is preceded by a return type, it is challenging
to implement. This is because implementing an OCaml function, to
correctly determine a C type in SmPL, without the aid of Yacc, would
have to handle a number of cases (disjunctions, typeof expressions,
etc.).

Thus, a slightly hacky approach is taken to determine a function
prototype with not the best certainty but what works for most cases
in SmPL. If the identifier is preceded by any token that does not
seem to be part of a type, then it is not identified as a function
prototype. Else, it is.

Signed-off-by: Jaskaran Singh <jaskaransingh7654321@gmail.com>
---
 parsing_cocci/parse_cocci.ml          | 97 +++++++++++++++++++++------
 parsing_cocci/parser_cocci_menhir.mly |  9 ++-
 2 files changed, 83 insertions(+), 23 deletions(-)

diff --git a/parsing_cocci/parse_cocci.ml b/parsing_cocci/parse_cocci.ml
index 679d213a..e92a01d0 100644
--- a/parsing_cocci/parse_cocci.ml
+++ b/parsing_cocci/parse_cocci.ml
@@ -295,6 +295,7 @@ let token2c (tok,_) add_clt =
   | PC.TLineEnd(clt) -> "line end"
   | PC.TInvalid -> "invalid"
   | PC.TFunDecl(clt) -> "fundecl"
+  | PC.TFunProto(clt) -> "funproto"
 
   | PC.TIso -> "<=>"
   | PC.TRightIso -> "=>"
@@ -480,7 +481,7 @@ let get_clt (tok,_) =
 
   | PC.TOPar0(_,clt) | PC.TMid0(_,clt) | PC.TAnd0(_,clt) | PC.TCPar0(_,clt)
   | PC.TOEllipsis(clt) | PC.TCEllipsis(clt)
-  | PC.TPOEllipsis(clt) | PC.TPCEllipsis(clt)
+  | PC.TPOEllipsis(clt) | PC.TPCEllipsis(clt) | PC.TFunProto(clt)
   | PC.TFunDecl(clt) | PC.TDirective(_,clt) | PC.TAttr_(clt)
   | PC.TLineEnd(clt) -> clt
   | PC.TVAEllipsis(clt) -> clt
@@ -718,6 +719,7 @@ let update_clt (tok,x) clt =
 
   | PC.TLineEnd(_) -> (PC.TLineEnd(clt),x)
   | PC.TFunDecl(_) -> (PC.TFunDecl(clt),x)
+  | PC.TFunProto(_) -> (PC.TFunProto(clt),x)
   | PC.TTildeExclEq(_) -> (PC.TTildeExclEq(clt),x)
   | PC.TDirective(a,_) -> (PC.TDirective(a,clt),x)
   | PC.TAttr_(_) -> (PC.TAttr_(clt),x)
@@ -925,7 +927,7 @@ let split_token ((tok,_) as t) =
   | PC.TInitialize | PC.TFinalize -> ([t],[t])
   | PC.TPArob clt | PC.TMetaPos(_,_,_,clt) | PC.TMetaCom(_,_,clt) -> split t clt
 
-  | PC.TFunDecl(clt)
+  | PC.TFunDecl(clt) | PC.TFunProto(clt)
   | PC.TWhen(clt) | PC.TWhenTrue(clt) | PC.TWhenFalse(clt)
   | PC.TAny(clt) | PC.TStrict(clt) | PC.TLineEnd(clt)
   | PC.TEllipsis(clt)
@@ -1006,7 +1008,8 @@ let find_function_names l =
     | _ -> false in
   let rec split acc = function
       [] | [_] -> raise Irrelevant
-    | ((PC.TCPar(_),_) as t1) :: ((PC.TOBrace(_),_) as t2) :: rest ->
+    | ((PC.TCPar(_),_) as t1) :: ((PC.TOBrace(_),_) as t2) :: rest
+    | ((PC.TCPar(_),_) as t1) :: ((PC.TPtVirg(_),_) as t2) :: rest ->
 	(List.rev (t1::acc),(t2::rest))
     | x::xs -> split (x::acc) xs in
   let rec balanced_name level = function
@@ -1024,20 +1027,68 @@ let find_function_names l =
     | t::rest when is_ident t && level = 0 -> rest
     | t::rest when is_ident t || is_mid t -> balanced_name level rest
     | _ -> raise Irrelevant in
-  let rec balanced_args level = function
+  let rec balanced_args level reverse = function
       [] -> raise Irrelevant
     | (PC.TCPar(_),_)::rest ->
-	let level = level - 1 in
-	if level = 0
+	let level = if reverse then level + 1 else level - 1 in
+	if level = 0 && not(reverse)
 	then rest
-	else balanced_args level rest
+	else balanced_args level reverse rest
     | (PC.TOPar(_),_)::rest ->
-	let level = level + 1 in
-	balanced_args level rest
+	let level = if reverse then level - 1 else level + 1 in
+	if level = 0 && reverse
+	then rest
+	else balanced_args level reverse rest
     | (PC.TArobArob,_)::_ | (PC.TArob,_)::_ | (PC.EOF,_)::_ ->
 	raise Irrelevant
-    | t::rest -> balanced_args level rest in
-  let rec loop = function
+    | t::rest -> balanced_args level reverse rest in
+  let rec is_permissible_proto = function
+      [] -> false
+    | (PC.TCPar0(_),_)::
+      ((PC.TMid0(_),_) | (PC.TAnd0(_),_))::
+      (PC.TOPar0(_),_)::_ -> false
+    | (PC.TOPar0(_),_)::rest
+    | (PC.TCPar0(_),_)::rest -> is_permissible_proto rest
+    | x::rest when is_mid x ->
+        let rec loop = function
+          [] -> false
+        | (PC.TOPar0(_),_)::xs -> is_permissible_proto xs
+        | x::xs -> loop xs in
+        loop rest
+    | ((PC.TCPar(_),_)::rest as l) ->
+      let l = balanced_args 0 true l in
+      let x = match l with
+        (PC.TAttr_(_),_)::rest -> is_permissible_proto rest
+      | (PC.TTypeof(_),_)::_ -> true
+      | _ -> false in x
+    | _::((PC.TEq(_),_) | (PC.TNotEq(_),_))::(PC.TWhen(_),_)::_
+    | _::(PC.TWhen(_),_)::_
+    | (PC.TComma(_),_)::_
+    | (PC.TDirective(_),_)::_
+    | (PC.TElse(_),_)::_
+    | (PC.TReturn(_),_)::_
+    | (PC.TMetaStm(_),_)::_
+    | (PC.TMetaExp(_),_)::_
+    | (PC.TMetaId(_),_)::_
+    | (PC.TMetaLocalIdExp(_),_)::_
+    | (PC.TEq(_),_)::_
+    | (PC.TEllipsis(_),_)::_
+    | (PC.TOEllipsis(_),_)::_
+    | (PC.TCEllipsis(_),_)::_
+    | (PC.TPOEllipsis(_),_)::_
+    | (PC.TPCEllipsis(_),_)::_
+    | (PC.TPtVirg(_),_)::_
+    | (PC.TOBrace(_),_)::_
+    | (PC.TCBrace(_),_)::_
+    | (PC.TOPar(_),_)::_
+    | (PC.TIdent(_),_)::_ -> false
+    | _ -> true in
+  let decl_or_proto clt info bef aft =
+    match aft with
+      (PC.TOBrace(_),_)::_ -> (((PC.TFunDecl(clt),info) :: bef), aft)
+    | (PC.TPtVirg(_),_)::_ -> (((PC.TFunProto(clt),info) :: bef), aft)
+    | _ -> raise Irrelevant in
+  let rec loop acc = function
       [] -> []
     | t :: rest ->
 	if is_par t || is_mid t || is_ident t
@@ -1046,26 +1097,30 @@ let find_function_names l =
 	    try
 	      let (bef,aft) = split [] (t::rest) in
 	      let rest = balanced_name 0 bef in
+              (match aft with
+                (PC.TPtVirg(_),_)::_
+                 when not(is_permissible_proto acc) -> raise Irrelevant
+              | _ ->
 	      (match rest with
 		(PC.TOPar(_),_)::_ ->
-		  (match balanced_args 0 rest with
+		  (match balanced_args 0 false rest with
 		    [] ->
 		      let (_,info) as h = List.hd bef in
 		      let clt = get_clt h in
-		      (((PC.TFunDecl(clt),info) :: bef), aft)
+                      decl_or_proto clt info bef aft
 		  | (PC.TAttr_(_),_)::rest ->
-		      (match balanced_args 0 rest with
+		      (match balanced_args 0 false rest with
 			[] ->
 			  let (_,info) as h = List.hd bef in
 			  let clt = get_clt h in
-			  (((PC.TFunDecl(clt),info) :: bef), aft)
+                          decl_or_proto clt info bef aft
 		      | _ -> raise Irrelevant)
 		  | _ -> raise Irrelevant)
-	      | _ -> raise Irrelevant)
+	      | _ -> raise Irrelevant))
 	    with Irrelevant -> ([t],rest) in
-	  t @ (loop rest)
-	else t :: (loop rest) in
-  loop l
+          t @ (loop (t @ acc) rest)
+        else t :: (loop (t :: acc) rest) in
+  loop [] l
 
 (* ----------------------------------------------------------------------- *)
 (* an attribute is an identifier that precedes another identifier and
@@ -1168,6 +1223,8 @@ let detect_types in_meta_decls l =
 	delim::newid::id::(loop false infn (ident::type_names) rest)
     | ((PC.TFunDecl(_),_) as fn)::rest ->
 	fn::(loop false 1 type_names rest)
+    | ((PC.TFunProto(_),_) as fn)::rest ->
+	fn::(loop false 1 type_names rest)
     | ((PC.TOPar(_),_) as lp)::rest when infn > 0 ->
 	lp::(loop false (infn + 1) type_names rest)
     | ((PC.TCPar(_),_) as rp)::rest when infn > 0 ->
@@ -1252,7 +1309,7 @@ let token2line (tok,_) =
   | PC.TMetaDParamList(_,_,_,_,clt) | PC.TMetaFunc(_,_,_,clt)
   | PC.TMetaLocalFunc(_,_,_,clt) | PC.TMetaPos(_,_,_,clt) | PC.TMetaCom(_,_,clt)
 
-  | PC.TFunDecl(clt)
+  | PC.TFunDecl(clt) | PC.TFunProto(clt)
   | PC.TWhen(clt) | PC.TWhenTrue(clt) | PC.TWhenFalse(clt)
   | PC.TAny(clt) | PC.TStrict(clt) | PC.TEllipsis(clt)
 
diff --git a/parsing_cocci/parser_cocci_menhir.mly b/parsing_cocci/parser_cocci_menhir.mly
index 9e6c8a08..26958f63 100644
--- a/parsing_cocci/parser_cocci_menhir.mly
+++ b/parsing_cocci/parser_cocci_menhir.mly
@@ -239,7 +239,8 @@ let inline_id aft = function
 
 %token <Data.clt> TVAEllipsis
 %token <Data.clt> TIf TElse TWhile TFor TDo TSwitch TCase TDefault TReturn
-%token <Data.clt> TBreak TContinue TGoto TSizeof TTypeof TFunDecl Tdecimal Texec
+%token <Data.clt> TBreak TContinue TGoto TSizeof TTypeof TFunDecl TFunProto
+%token <Data.clt> Tdecimal Texec
 %token <string * Data.clt> TIdent TTypeId TDeclarerId TIteratorId TSymId
 %token <Ast_cocci.added_string * Data.clt> TDirective
 %token <Data.clt> TAttr_
@@ -1439,7 +1440,8 @@ reverse_separated_nonempty_llist(separator, X):
 
 funproto:
   s=ioption(storage) i=ioption(Tinline) t=ctype
-  id=fn_ident lp=TOPar arglist=arg_list(name_opt_decl) rp=TCPar pt=TPtVirg
+  TFunProto id=fn_ident
+  lp=TOPar arglist=arg_list(name_opt_decl) rp=TCPar pt=TPtVirg
       { let s = match s with None -> [] | Some s -> [Ast0.FStorage s] in
         let i =
 	  match i with
@@ -1453,7 +1455,8 @@ funproto:
 	      P.clt2mcode "(" lp, args, vararg, P.clt2mcode ")" rp,
 	      P.clt2mcode ";" pt)) }
 | i=Tinline s=storage t=ctype
-  id=fn_ident lp=TOPar arglist=arg_list(name_opt_decl) rp=TCPar pt=TPtVirg
+  TFunProto id=fn_ident
+  lp=TOPar arglist=arg_list(name_opt_decl) rp=TCPar pt=TPtVirg
       { let s = [Ast0.FStorage s] in
         let i = [Ast0.FInline (P.clt2mcode "inline" i)] in
 	let t = [Ast0.FType t] in
-- 
2.21.1

_______________________________________________
Linux-kernel-mentees mailing list
Linux-kernel-mentees@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees

  reply	other threads:[~2020-03-20  7:02 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-20  7:01 [Linux-kernel-mentees] [PATCH v3 00/26] cocci: Add ParenType/FunctionType to SmPL ASTs Jaskaran Singh
2020-03-20  7:01 ` Jaskaran Singh [this message]
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 02/26] parsing_cocci: AST: Add ParenType and FunctionType " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 03/26] parsing_cocci: parser: Add direct_declarator/direct_abstract_d rules Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 04/26] parsing_cocci: visitor_ast0: Add cases for ParenType/FunctionType Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 05/26] parsing_cocci: visitor_ast: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 06/26] parsing_cocci: arity: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 07/26] parsing_cocci: index: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 08/26] parsing_cocci: context_neg: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 09/26] parsing_cocci: unparse_ast0: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 10/26] parsing_cocci: single_statement: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 11/26] parsing_cocci: function_prototypes: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 12/26] parsing_cocci: check_meta: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 13/26] parsing_cocci: iso_pattern: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 14/26] parsing_cocci: adjust_pragmas: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 15/26] parsing_cocci: compute_lines: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 16/26] parsing_cocci: ast0toast: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 17/26] parsing_cocci: type_cocci: Add ParenType/FunctionType to types Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 18/26] parsing_cocci: unify_ast: Add cases for ParenType/FunctionType Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 19/26] parsing_cocci: disjdistr: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 20/26] parsing_cocci: ast_cocci: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 21/26] parsing_cocci: pretty_print_cocci: Print ParenType/FunctionType Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 22/26] parsing_c: unparse_cocci: " Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 23/26] engine: Match A.ParenType and A.FunctionType Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 24/26] tools: spgen: Add cases for ParenType/FunctionType Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 25/26] cocci: Remove Ast_cocci.FunctionPointer Jaskaran Singh
2020-03-20  7:01 ` [Linux-kernel-mentees] [PATCH v3 26/26] tests: Add test case for array of function pointers Jaskaran Singh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200320070157.4206-2-jaskaransingh7654321@gmail.com \
    --to=jaskaransingh7654321@gmail.com \
    --cc=cocci@systeme.lip6.fr \
    --cc=julia.lawall@inria.fr \
    --cc=linux-kernel-mentees@lists.linuxfoundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).