From 93f8539e0a8f4d2b6c45aea1eaacaef000f36527 Mon Sep 17 00:00:00 2001
From: Young Mo Kang <kym327@gmail.com>
Date: Sat, 27 Feb 2016 19:03:13 -0500
Subject: [PATCH 1/7] Enable multiple char argument to -type

* find/parser.c (insert_type): When the option '-type xyz' supplied by
the user, convert it into '( -type x -o -type y -type z )' option;
that is, prepend [(] predicate, parse a single char, append [-o] and
repeat, and at the end append [)] predicate to close.
* find/tree.c (build_expression_tree): Do not change p_name of the last
predicate if the last predicate is the closing parenthesis [)]
---
 find/parser.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++------------
 find/tree.c   |  3 ++-
 2 files changed, 70 insertions(+), 17 deletions(-)

diff --git a/find/parser.c b/find/parser.c
index 57fb296..b163df3 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -2681,15 +2681,31 @@ insert_type (char **argv, int *arg_ptr,
   struct predicate *our_pred;
   float rate = 0.01;
   const char *typeletter;
+  int typeletter_length, i;
+  const struct parser_table *entry_open, *entry_close, *entry_or;
 
   if (collect_arg (argv, arg_ptr, &typeletter))
     {
-      if (strlen (typeletter) != 1u)
+	/* if the input is '-type lfd', we simply modify the predicate tree to be
+	( -type l -o -type f -o -type d ) */
+      typeletter_length = strlen (typeletter);
+	if (typeletter_length > 1)
 	{
-	  error (EXIT_FAILURE, 0,
-		 _("Arguments to -type should contain only one letter"));
-	  /*NOTREACHED*/
-	  return false;
+	/* More than one letter argument found.
+	Open the parenthesis */
+	entry_open  = find_parser ("(");
+	entry_close = find_parser (")");
+	entry_or = find_parser ("or");
+	assert (entry_open  != NULL);
+	assert (entry_close != NULL);
+	assert (entry_or != NULL);
+
+	our_pred = get_new_pred_chk_op (entry_open, NULL);
+	our_pred->pred_func = pred_openparen;
+	our_pred->p_type = OPEN_PAREN;
+	our_pred->p_prec = NO_PREC;
+	our_pred->need_stat = our_pred->need_type = false;
+	our_pred->p_name = "(";
 	}
 
       /* From a real system here are the counts of files by type:
@@ -2702,10 +2718,11 @@ insert_type (char **argv, int *arg_ptr,
          s         80  1.59e-05
          p         38  7.54e-06
        */
-      {
 	mode_t type_cell;
 
-	switch (typeletter[0])
+	for (i=0; i<typeletter_length; i++)
+  		{
+      switch (typeletter[i])
 	  {
 	  case 'b':			/* block special */
 	    type_cell = S_IFBLK;
@@ -2732,7 +2749,7 @@ insert_type (char **argv, int *arg_ptr,
 	    error (EXIT_FAILURE, 0,
 		   _("-type %c is not supported because symbolic links "
 		     "are not supported on the platform find was compiled on."),
-		   (*typeletter));
+		   typeletter[i]);
 #endif
 	    break;
 	  case 'p':			/* pipe */
@@ -2744,7 +2761,7 @@ insert_type (char **argv, int *arg_ptr,
 	    error (EXIT_FAILURE, 0,
 		   _("-type %c is not supported because FIFOs "
 		     "are not supported on the platform find was compiled on."),
-		   (*typeletter));
+		   typeletter[i]);
 #endif
 	    break;
 	  case 's':			/* socket */
@@ -2756,7 +2773,7 @@ insert_type (char **argv, int *arg_ptr,
 	    error (EXIT_FAILURE, 0,
 		   _("-type %c is not supported because named sockets "
 		     "are not supported on the platform find was compiled on."),
-		   (*typeletter));
+		   typeletter[i]);
 #endif
 	    break;
 	  case 'D':			/* Solaris door */
@@ -2772,17 +2789,21 @@ insert_type (char **argv, int *arg_ptr,
 	    error (EXIT_FAILURE, 0,
 		   _("-type %c is not supported because Solaris doors "
 		     "are not supported on the platform find was compiled on."),
-		   (*typeletter));
+		   typeletter[i]);
 #endif
 	    break;
 	  default:			/* None of the above ... nuke 'em. */
 	    type_cell = 0;
 	    error (EXIT_FAILURE, 0,
-		   _("Unknown argument to -type: %c"), (*typeletter));
+		   _("Unknown argument to -type: %c"), typeletter[i]);
 	    /*NOTREACHED*/
 	    return false;
 	  }
-	our_pred = insert_primary_withpred (entry, which_pred, typeletter);
+    /* 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[].
+    Note sure if the fix is necessary */
+    our_pred = insert_primary_withpred (entry, which_pred, &typeletter[i]);
+    our_pred->p_name = "-type"; 	/* otherwise, its p_name will be "type" */
 	our_pred->est_success_rate = rate;
 
 	/* Figure out if we will need to stat the file, because if we don't
@@ -2800,9 +2821,40 @@ insert_type (char **argv, int *arg_ptr,
 	    our_pred->need_type = true;
 	  }
 	our_pred->args.type = type_cell;
-      }
-      return true;
-    }
+			if (typeletter_length == 1)
+			{
+				return true;
+			}
+			else if (i+1 < typeletter_length)
+			{
+				/* add -o predicate */
+				our_pred = get_new_pred_noarg (entry_or);
+				our_pred->p_name = "-o";
+				our_pred->pred_func = pred_or;
+				our_pred->p_type = BI_OP;
+				our_pred->p_prec = OR_PREC;
+				our_pred->need_stat = false;
+				our_pred->need_type = false;
+				our_pred->need_inum = false;
+				our_pred->arg_text = NULL;
+				our_pred->args.str = NULL;
+				our_pred->side_effects = false;
+				our_pred->no_default_print = false;
+			}
+			else
+			{
+				/* close the parenthesis */
+				our_pred = get_new_pred (entry_close);
+				our_pred->pred_func = pred_closeparen;
+				our_pred->p_type = CLOSE_PAREN;
+				our_pred->p_prec = NO_PREC;
+				our_pred->need_stat = our_pred->need_type = false;
+				our_pred->p_name = ")";
+			}
+     }
+		return true;
+	}
+
   return false;
 }
 
diff --git a/find/tree.c b/find/tree.c
index 8a413f8..834b331 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);
 	    }
 	}
-      else
+			/* w/o this if condition, something funky happens with the form "-type lfd" */
+	     else if(last_pred->parser_entry != find_parser(")"))
 	{
 	  last_pred->p_name = predicate_name;
 
-- 
2.7.0

