From 908f56704ec9e09a53a953490f05962be678a3a0 Mon Sep 17 00:00:00 2001 From: jay Date: Tue, 20 Dec 2005 19:22:28 +0000 Subject: [PATCH] Savannah bug #15195: more helpful error messages for 'find . ( )' or 'find . \!' --- NEWS | 9 ++++++++ doc/find.texi | 10 ++++----- find/defs.h | 7 +++++- find/find.1 | 2 +- find/find.c | 15 +++++++++++-- find/ftsfind.c | 16 ++++++++++---- find/testsuite/Makefile.am | 2 ++ find/testsuite/find.posix/sv-bug-15235.exp | 6 ++++++ find/testsuite/find.posix/sv-bug-15235.xo | 8 +++++++ find/tree.c | 34 ++++++++++++++++++++++-------- find/util.c | 1 + 11 files changed, 88 insertions(+), 22 deletions(-) create mode 100644 find/testsuite/find.posix/sv-bug-15235.exp create mode 100644 find/testsuite/find.posix/sv-bug-15235.xo diff --git a/NEWS b/NEWS index e5fabd1..11f0fc3 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,15 @@ GNU findutils NEWS - User visible changes. -*- outline -*- (allout) * Major changes in release 4.3.1-CVS +Find now follows POSIX rules for determining where directories end and +expressions start. This means that "find \(1 \!2 \, \)" now searches +in the four named directories, rather than trying to parse an +expression. (Savannah bug #15235). + +You now get a more helpful error message when you use command lines +which have missing expressions, such as 'find . ( )' or 'find . !'. + + * Major changes in release 4.3.0 The 4.3.x release series are currently 'development' releases. Please diff --git a/doc/find.texi b/doc/find.texi index 09b315c..2e14059 100644 --- a/doc/find.texi +++ b/doc/find.texi @@ -2679,11 +2679,11 @@ files or directories that should be searched. This list of files to search is followed by a list of expressions describing the files we wish to search for. The first part of the -expression is recognised by the fact that it begins with @samp{-}, -@samp{(}, @samp{)}, @samp{,}, or @samp{!}. Any arguments after it are -the rest of the expression. If no files are given, the current -directory is used. If no expression is given, the expression -@samp{-print} is used. +expression is recognised by the fact that it begins with @samp{-} +followed by some other letters (for example @samp{-print}), or is +either @samp{(} or @samp{!}. Any arguments after it are the rest of +the expression. If no files are given, the current directory is used. +If no expression is given, the expression @samp{-print} is used. @code{find} exits with status zero if all files matched are processed successfully, greater than 0 if errors occur. diff --git a/find/defs.h b/find/defs.h index 38db099..36708ec 100644 --- a/find/defs.h +++ b/find/defs.h @@ -310,6 +310,9 @@ struct predicate /* True if this predicate should display control characters literally */ boolean literal_control_chars; + + /* True if this predicate didn't originate from the user. */ + boolean artificial; /* Information needed by the predicate processor. Next to each member are listed the predicates that use it. */ @@ -511,7 +514,9 @@ void print_optlist PARAMS((FILE *fp, struct predicate *node)); /* tree.c */ struct predicate * -get_expr PARAMS((struct predicate **input, short int prev_prec)); +get_expr PARAMS((struct predicate **input, + short int prev_prec, + const struct predicate *previous_predicate)); boolean opt_expr PARAMS((struct predicate **eval_treep)); boolean mark_stat PARAMS((struct predicate *tree)); boolean mark_type PARAMS((struct predicate *tree)); diff --git a/find/find.1 b/find/find.1 index 43a5ce8..da68774 100644 --- a/find/find.1 +++ b/find/find.1 @@ -31,7 +31,7 @@ source of information. The `\-H', `\-L' and `\-P' options control the treatment of symbolic links. Command-line arguments following these are taken to be names of files or directories to be examined, up to the first argument that -begins with `\-', `(', `)', `,', or `!'. That argument and any +begins with `\-', or the argument `(' or `!'. That argument and any following arguments are taken to be the expression describing what is to be searched for. If no paths are given, the current directory is used. If no expression is given, the expression `\-print' is used diff --git a/find/find.c b/find/find.c index ef2f97d..e1e46bf 100644 --- a/find/find.c +++ b/find/find.c @@ -269,6 +269,7 @@ main (int argc, char **argv) assert(entry_print != NULL); parse_open (entry_open, argv, &argc); + predicates->artificial = true; parse_begin_user_args(argv, argc, last_pred, predicates); pred_sanity_check(last_pred); @@ -299,6 +300,10 @@ main (int argc, char **argv) error (1, 0, _("invalid argument `%s' to `%s'"), argv[i], predicate_name); } + else + { + last_pred->p_name = predicate_name; + } pred_sanity_check(last_pred); pred_sanity_check(predicates); /* XXX: expensive */ @@ -313,6 +318,7 @@ main (int argc, char **argv) predicates = last_pred = predicates->pred_next; free ((char *) cur_pred); parse_print (entry_print, argv, &argc); + last_pred->artificial = true; pred_sanity_check(last_pred); pred_sanity_check(predicates); /* XXX: expensive */ } @@ -329,8 +335,10 @@ main (int argc, char **argv) { /* `( user-supplied-expression ) -print'. */ parse_close (entry_close, argv, &argc); + last_pred->artificial = true; pred_sanity_check(last_pred); parse_print (entry_print, argv, &argc); + last_pred->artificial = true; pred_sanity_check(last_pred); pred_sanity_check(predicates); /* XXX: expensive */ } @@ -345,14 +353,17 @@ main (int argc, char **argv) /* Done parsing the predicates. Build the evaluation tree. */ cur_pred = predicates; - eval_tree = get_expr (&cur_pred, NO_PREC); + eval_tree = get_expr (&cur_pred, NO_PREC, NULL); /* Check if we have any left-over predicates (this fixes * Debian bug #185202). */ if (cur_pred != NULL) { - error (1, 0, _("unexpected extra predicate")); + if (0 == strcmp(cur_pred->p_name, ")")) + error (1, 0, _("you have too many '%s'"), cur_pred->p_name); + else + error (1, 0, _("unexpected extra predicate '%s'"), cur_pred->p_name); } #ifdef DEBUG diff --git a/find/ftsfind.c b/find/ftsfind.c index cb00bd1..6567634 100644 --- a/find/ftsfind.c +++ b/find/ftsfind.c @@ -552,6 +552,7 @@ main (int argc, char **argv) assert(entry_print != NULL); parse_open (entry_open, argv, &argc); + predicates->artificial = true; parse_begin_user_args(argv, argc, last_pred, predicates); pred_sanity_check(last_pred); @@ -582,12 +583,14 @@ main (int argc, char **argv) error (1, 0, _("invalid argument `%s' to `%s'"), argv[i], predicate_name); } - + else + { + last_pred->p_name = predicate_name; + } pred_sanity_check(last_pred); pred_sanity_check(predicates); /* XXX: expensive */ } parse_end_user_args(argv, argc, last_pred, predicates); - if (predicates->pred_next == NULL) { /* No predicates that do something other than set a global variable @@ -612,8 +615,10 @@ main (int argc, char **argv) { /* `( user-supplied-expression ) -print'. */ parse_close (entry_close, argv, &argc); + last_pred->artificial = true; pred_sanity_check(last_pred); parse_print (entry_print, argv, &argc); + last_pred->artificial = true; pred_sanity_check(last_pred); pred_sanity_check(predicates); /* XXX: expensive */ } @@ -628,14 +633,17 @@ main (int argc, char **argv) /* Done parsing the predicates. Build the evaluation tree. */ cur_pred = predicates; - eval_tree = get_expr (&cur_pred, NO_PREC); + eval_tree = get_expr (&cur_pred, NO_PREC, NULL); /* Check if we have any left-over predicates (this fixes * Debian bug #185202). */ if (cur_pred != NULL) { - error (1, 0, _("unexpected extra predicate")); + if (0 == strcmp(cur_pred->p_name, ")")) + error (1, 0, _("you have too many '%s'"), cur_pred->p_name); + else + error (1, 0, _("unexpected extra predicate '%s'"), cur_pred->p_name); } #ifdef DEBUG diff --git a/find/testsuite/Makefile.am b/find/testsuite/Makefile.am index f149987..d9c7825 100644 --- a/find/testsuite/Makefile.am +++ b/find/testsuite/Makefile.am @@ -59,6 +59,7 @@ find.posix/files-not-expressions3.xo \ find.posix/links.xo \ find.posix/sv-bug-11175.xo \ find.posix/sv-bug-12181.xo \ +find.posix/sv-bug-15235.xo \ find.posix/depth1.xo \ find.posix/sizes.xo \ find.posix/name.xo \ @@ -128,6 +129,7 @@ find.posix/files-not-expressions3.exp \ find.posix/links.exp \ find.posix/sv-bug-11175.exp \ find.posix/sv-bug-12181.exp \ +find.posix/sv-bug-15235.exp \ find.posix/depth1.exp \ find.posix/sizes.exp \ find.posix/name.exp \ diff --git a/find/testsuite/find.posix/sv-bug-15235.exp b/find/testsuite/find.posix/sv-bug-15235.exp new file mode 100644 index 0000000..da26c3b --- /dev/null +++ b/find/testsuite/find.posix/sv-bug-15235.exp @@ -0,0 +1,6 @@ +# tests for directory parsing +exec rm -rf \(1 \!2 \, \) +exec mkdir \(1 \!2 \, \) +exec touch \(1/a \!2/b \,/c \)/d +find_start p {\(1 \!2 \, \)} +exec rm -rf \(1 \!2 \, \) diff --git a/find/testsuite/find.posix/sv-bug-15235.xo b/find/testsuite/find.posix/sv-bug-15235.xo new file mode 100644 index 0000000..2852b81 --- /dev/null +++ b/find/testsuite/find.posix/sv-bug-15235.xo @@ -0,0 +1,8 @@ +(1 +(1/a +!2 +!2/b +, +,/c +) +)/d diff --git a/find/tree.c b/find/tree.c index 3230887..0f66169 100644 --- a/find/tree.c +++ b/find/tree.c @@ -59,7 +59,9 @@ static struct predicate *set_new_parent PARAMS((struct predicate *curr, enum pre our caller, so get_expr recurses. */ struct predicate * -get_expr (struct predicate **input, short int prev_prec) +get_expr (struct predicate **input, + short int prev_prec, + const struct predicate* prev_pred) { struct predicate *next = NULL; @@ -77,7 +79,17 @@ get_expr (struct predicate **input, short int prev_prec) break; case CLOSE_PAREN: - error (1, 0, _("invalid expression; you have too many ')'")); + if ( (*input)->artificial ) + { + /* We have reached the end of the user-supplied predicates + * unexpectedly. + */ + error (1, 0, _("expected an expression after '%s'"), prev_pred->p_name); + } + else + { + error (1, 0, _("invalid expression; you have too many ')'")); + } break; case PRIMARY_TYPE: @@ -88,16 +100,17 @@ get_expr (struct predicate **input, short int prev_prec) case UNI_OP: next = *input; *input = (*input)->pred_next; - next->pred_right = get_expr (input, NEGATE_PREC); + next->pred_right = get_expr (input, NEGATE_PREC, next); break; case OPEN_PAREN: + prev_pred = (*input); *input = (*input)->pred_next; if ( (*input)->p_type == CLOSE_PAREN ) { error (1, 0, _("invalid expression; empty parentheses are not allowed.")); } - next = get_expr (input, NO_PREC); + next = get_expr (input, NO_PREC, prev_pred); if ((*input == NULL) || ((*input)->p_type != CLOSE_PAREN)) error (1, 0, _("invalid expression; I was expecting to find a ')' somewhere but did not see one.")); @@ -163,11 +176,14 @@ scan_rest (struct predicate **input, break; case BI_OP: - (*input)->pred_left = tree; - tree = *input; - *input = (*input)->pred_next; - tree->pred_right = get_expr (input, tree->p_prec); - break; + { + struct predicate *prev = (*input); + (*input)->pred_left = tree; + tree = *input; + *input = (*input)->pred_next; + tree->pred_right = get_expr (input, tree->p_prec, prev); + break; + } case CLOSE_PAREN: return tree; diff --git a/find/util.c b/find/util.c index 1063972..d53ddd0 100644 --- a/find/util.c +++ b/find/util.c @@ -93,6 +93,7 @@ get_new_pred (const struct parser_table *entry) last_pred->pred_left = NULL; last_pred->pred_right = NULL; last_pred->literal_control_chars = options.literal_control_chars; + last_pred->artificial = false; return last_pred; } -- 2.11.4.GIT