From 54fbef6eff4a76dcbd3665c8755f1996e450d9af Mon Sep 17 00:00:00 2001
From: Young Mo Kang <kym327@gmail.com>
Date: Sun, 6 Mar 2016 02:27:36 -0500
Subject: [PATCH 7/7] Modify -type multi arg support to require comma

'-type x,y,z' will be equivalent to '( -type x -o -type y -o -type z )'
The reason for inserting ',' separator is because in the future we may add
support for more types that require multi-letter letter argument

* NEWS: Modify the description to -type multiple args support
* doc/find.texi: Modify the description
* find/find.1: Modify the descriptiona and example
* find/parser.c (insert_type): Require ',' separator. Output error
if no separator is given between more than two letters of argument.
* find/tree.c (build_expression_tree): Minor modification to comment
* find/testsuite/find.gnu/type.exp: Modify accordingly
* find/testsuite/find.gnu/type.xo: Modify accordingly
---
 NEWS                             |  7 ++++---
 doc/find.texi                    |  6 +++---
 find/find.1                      |  8 ++++----
 find/parser.c                    | 24 +++++++++++++++++++-----
 find/testsuite/find.gnu/type.exp |  2 +-
 find/testsuite/find.gnu/type.xo  |  8 ++++----
 find/tree.c                      |  3 ++-
 7 files changed, 37 insertions(+), 21 deletions(-)

diff --git a/NEWS b/NEWS
index ca9d24b..2838715 100644
--- a/NEWS
+++ b/NEWS
@@ -20,9 +20,10 @@ database is now different to previous versions.  However, you should
 not rely on locate's output appearing in any particular order in any
 case.
 
-The find program will now accept multiple letters as -type arguments.
-For example, to search for files and directories and links all together,
-simply give the option '-type fdl' which will be interpreted as
+The find program will now accept multiple arguments to -type and -xtype
+separated by a comma ',' without any space.. For example, to search for
+files and directories and links all together, simply provide the option
+'-type f,d,l' which will be interpreted as
 '( -type f -o -type d -o -type l )'.
 
 ** Improvements
diff --git a/doc/find.texi b/doc/find.texi
index 9e9ec63..d495cb6 100644
--- a/doc/find.texi
+++ b/doc/find.texi
@@ -1082,9 +1082,9 @@ socket
 door (Solaris)
 @end table
 
-Multiple file types can be provided as a combined list without commas and
-will be interpreted with '-o' in between. For example, '-type fld' is
-interpreted as '( -type f -o -type l -o -type d )'.
+Multiple file types can be provided as a combined list separated by
+a comma ',' and will be interpreted with '-o' in between. For example,
+'-type f,d,l' is interpreted as '( -type f -o -type d -o -type l )'.
 @end deffn
 
 @deffn Test -xtype c
diff --git a/find/find.1 b/find/find.1
index 02c85f0..26fb4de 100644
--- a/find/find.1
+++ b/find/find.1
@@ -956,7 +956,7 @@ door (Solaris)
 .RE
 .IP
 To search for more than one type, you can supply the combined list of
-type letters without commas.
+type letters separated by a comma `,'.
 .IP "\-uid \fIn\fR"
 File's numeric user ID is \fIn\fR.
 
@@ -2092,15 +2092,15 @@ already found project3/.svn), but ensures sibling directories
 
 .P
 .nf
-.B find /tmp -type fdl
+.B find /tmp -type f,d,l
 .fi
 
-Search for any files, links, and directories in the directory
+Search for any files, directories, ane links in the directory
 .B /tmp
 , which is equivalent to
 
 .nf
-.B find /tmep \e( -type f -o -type l -o -type d \e)
+.B find /tmep \e( -type f -o -type d -o -type l \e)
 .fi
 
 .SH EXIT STATUS
diff --git a/find/parser.c b/find/parser.c
index a9b688e..b805fb8 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -2686,8 +2686,8 @@ insert_type (char **argv, int *arg_ptr,
 
   if (collect_arg (argv, arg_ptr, &typeletter))
     {
-	/* if the input is '-type lfd', we simply modify the predicate tree to be
-	( -type l -o -type f -o -type d ) */
+	/* if the input is '-type f,d,l', we simply modify the predicate tree to be
+	( -type f -o -type d -o -type l ) */
       typeletter_length = strlen (typeletter);
 	if (typeletter_length > 1)
 	{
@@ -2792,7 +2792,7 @@ insert_type (char **argv, int *arg_ptr,
 		   typeletter[i]);
 #endif
 	    break;
-	  default:			/* None of the above ... nuke 'em. */
+      default:			/* None of the above ... nuke 'em. */
 	    type_cell = 0;
 	    error (EXIT_FAILURE, 0,
 		   _("Unknown argument to -type: %c"), typeletter[i]);
@@ -2800,11 +2800,11 @@ insert_type (char **argv, int *arg_ptr,
 	    return false;
 	  }
     /* NOTE: the arg_text field will not be a single char unless the last one.
-    To fix it, one will need to go through the hassle of allocating and freeing memory, because pred->arg_text is just a string pointer to argv[].
+    To fix it, one will need to go through the hassle of allocating and
+    freeing memory, because pred->arg_text is just a string pointer to argv[].
     Not sure if the fix is necessary */
     our_pred = insert_primary_withpred (entry, which_pred, &typeletter[i]);
 	our_pred->est_success_rate = rate;
-
 	/* Figure out if we will need to stat the file, because if we don't
 	 * need to follow symlinks, we can avoid a stat call by using
 	 * struct dirent.d_type.
@@ -2822,6 +2822,20 @@ insert_type (char **argv, int *arg_ptr,
             our_pred->p_name = "-type";
 	  }
 	our_pred->args.type = type_cell;
+      /* Make sure there is a comma separator if any */
+      if (typeletter[i+1] == ',')
+      {
+          /* Separator found; proceed. */
+          i++;
+      }
+      else if (typeletter[i+1] != '\0')
+      {
+          /* No separator found */
+          type_cell = 0;
+          error (EXIT_FAILURE, 0,
+            _("Must separate multiple arguments to -type using: ,"));
+          return false;
+      }
 			if (typeletter_length == 1)
 			{
 				return true;
diff --git a/find/testsuite/find.gnu/type.exp b/find/testsuite/find.gnu/type.exp
index 3bced86..9757377 100644
--- a/find/testsuite/find.gnu/type.exp
+++ b/find/testsuite/find.gnu/type.exp
@@ -7,4 +7,4 @@ exec mkdir tmp/directory
 exec ln -s /etc/passwd tmp/link
 exec ln -s /NOSUCHFILE tmp/broken_link
 
-find_start p { tmp/file tmp/directory tmp/link tmp/broken_link -type fl -printf "type is fl: %p\n" , \! -type fl -printf "type is not fl: %p\n" }
+find_start p { tmp/file tmp/directory tmp/link tmp/broken_link -type f,l -printf "type is f,l: %p\n" , \! -type f,l -printf "type is not f,l: %p\n" }
diff --git a/find/testsuite/find.gnu/type.xo b/find/testsuite/find.gnu/type.xo
index 42b13ed..b41c16b 100644
--- a/find/testsuite/find.gnu/type.xo
+++ b/find/testsuite/find.gnu/type.xo
@@ -1,4 +1,4 @@
-type is fl: tmp/file
-type is fl: tmp/link
-type is fl: tmp/broken_link
-type is not fl: tmp/directory
+type is f,l: tmp/file
+type is f,l: tmp/link
+type is f,l: tmp/broken_link
+type is not f,l: tmp/directory
diff --git a/find/tree.c b/find/tree.c
index 834b331..91b27b1 100644
--- a/find/tree.c
+++ b/find/tree.c
@@ -1332,7 +1332,8 @@ build_expression_tree (int argc, char *argv[], int end_of_leading_options)
 	      usage (EXIT_FAILURE);
 	    }
 	}
-			/* w/o this if condition, something funky happens with the form "-type lfd" */
+			/* w/o this if condition, something funky happen
+             * when multiple arguments are provided */
 	     else if(last_pred->parser_entry != find_parser(")"))
 	{
 	  last_pred->p_name = predicate_name;
-- 
2.7.0

