From cf787cf3a54f21e643d760dc3f893233ecce4ad5 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Sun, 4 Feb 2007 17:11:25 +0000 Subject: [PATCH] find: support for ! --- findutils/Config.in | 18 ++++++++++++++++++ findutils/find.c | 45 +++++++++++++++++++++++++++++++++++++-------- shell/msh.c | 2 +- 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/findutils/Config.in b/findutils/Config.in index 73ce36f51..e5f82986d 100644 --- a/findutils/Config.in +++ b/findutils/Config.in @@ -90,6 +90,24 @@ config FEATURE_FIND_USER help Support the 'find -user' option for searching by username or uid. +config FEATURE_FIND_NOT + bool "Enable the 'not' (!) operator" + default y + depends on FIND + help + Support the '!' operator to invert the test results. If 'Enable + full-blown desktop' is enabled, then will also the non-POSIX + '-not' be supported. + +config FEATURE_FIND_NOT + bool "Enable the 'not' (!) operator" + default y + depends on FIND + help + Support the '!' operator to invert the test results. If 'Enable + full-blown desktop' is enabled, then will also the non-POSIX + '-not' be supported. + config GREP bool "grep" default n diff --git a/findutils/find.c b/findutils/find.c index bfdd84497..5645b5a4d 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -55,6 +55,9 @@ typedef int (*action_fp)(const char *fileName, struct stat *statbuf, void *); typedef struct { action_fp f; +#if ENABLE_FEATURE_FIND_NOT + smallint invert; +#endif } action; #define ACTS(name, arg...) typedef struct { action a; arg; } action_##name; #define ACTF(name) static int func_##name(const char *fileName, struct stat *statbuf, action_##name* ap) @@ -118,12 +121,20 @@ static int exec_actions(action ***appp, const char *fileName, struct stat *statb cur_group = -1; while ((app = appp[++cur_group])) { cur_action = -1; - do { + while (1) { ap = app[++cur_action]; - } while (ap && (rc = ap->f(fileName, statbuf, ap))); - if (!ap) { - /* all actions in group were successful */ - break; + if (!ap) { + /* all actions in group were successful */ + return rc; + } + rc = ap->f(fileName, statbuf, ap); +#if ENABLE_FEATURE_FIND_NOT + if (ap->invert) rc = !rc; +#endif + if (!rc) { + /* current group failed, try next */ + break; + } } } return rc; @@ -331,6 +342,7 @@ static action*** parse_params(char **argv) action*** appp; unsigned cur_group = 0; unsigned cur_action = 0; + USE_FEATURE_FIND_NOT( smallint invert_flag = 0; ) action* alloc_action(int sizeof_struct, action_fp f) { @@ -339,11 +351,12 @@ static action*** parse_params(char **argv) appp[cur_group][cur_action++] = ap = xmalloc(sizeof_struct); appp[cur_group][cur_action] = NULL; ap->f = f; + USE_FEATURE_FIND_NOT( ap->invert = invert_flag; ) return ap; } #define ALLOC_ACTION(name) (action_##name*)alloc_action(sizeof(action_##name), (action_fp) func_##name) - appp = xzalloc(2 * sizeof(*appp)); /* appp[0],[1] == NULL */ + appp = xzalloc(2 * sizeof(appp[0])); /* appp[0],[1] == NULL */ // Actions have side effects and return a true or false value // We implement: -print, -print0, -exec @@ -367,27 +380,39 @@ static action*** parse_params(char **argv) if (strcmp(arg, "-a") == 0 USE_DESKTOP(|| strcmp(arg, "-and") == 0) ) { - /* no special handling required */ + USE_FEATURE_FIND_NOT( invert_flag = 0; ) + /* no further special handling required */ } else if (strcmp(arg, "-o") == 0 USE_DESKTOP(|| strcmp(arg, "-or") == 0) ) { /* start new OR group */ + USE_FEATURE_FIND_NOT( invert_flag = 0; ) cur_group++; appp = xrealloc(appp, (cur_group+2) * sizeof(*appp)); - appp[cur_group] = NULL; + /*appp[cur_group] = NULL; - already NULL */ appp[cur_group+1] = NULL; cur_action = 0; } +#if ENABLE_FEATURE_FIND_NOT + else if (LONE_CHAR(arg, '!') + USE_DESKTOP(|| strcmp(arg, "-not") == 0) + ) { + invert_flag = 1; + } +#endif /* --- Tests and actions --- */ else if (strcmp(arg, "-print") == 0) { need_print = 0; + /* GNU find ignores '!' here: "find ! -print" */ + USE_FEATURE_FIND_NOT( invert_flag = 0; ) (void) ALLOC_ACTION(print); } #if ENABLE_FEATURE_FIND_PRINT0 else if (strcmp(arg, "-print0") == 0) { need_print = 0; + USE_FEATURE_FIND_NOT( invert_flag = 0; ) (void) ALLOC_ACTION(print0); } #endif @@ -471,6 +496,7 @@ static action*** parse_params(char **argv) int i; action_exec *ap; need_print = 0; + USE_FEATURE_FIND_NOT( invert_flag = 0; ) ap = ALLOC_ACTION(exec); ap->exec_argv = ++argv; /* first arg after -exec */ ap->exec_argc = 0; @@ -524,6 +550,7 @@ static action*** parse_params(char **argv) argv = endarg; } else if (strcmp(arg, "-prune") == 0) { + USE_FEATURE_FIND_NOT( invert_flag = 0; ) (void) ALLOC_ACTION(prune); } else if (strcmp(arg, "-size") == 0) { @@ -555,6 +582,8 @@ int find_main(int argc, char **argv) for (firstopt = 1; firstopt < argc; firstopt++) { if (argv[firstopt][0] == '-') break; + if (ENABLE_FEATURE_FIND_NOT && LONE_CHAR(argv[firstopt], '!')) + break; #if ENABLE_DESKTOP if (LONE_CHAR(argv[firstopt], '(')) break; diff --git a/shell/msh.c b/shell/msh.c index 817b84093..a2da540b3 100644 --- a/shell/msh.c +++ b/shell/msh.c @@ -1278,7 +1278,7 @@ struct op *scantree(struct op *head) DBGPRINTF5(("SCANTREE: checking node %p\n", head)); - if ((head->type != TDOT) && (strcmp(".", head->words[0]) == 0)) { + if ((head->type != TDOT) && LONE_CHAR(head->words[0], '.')) { DBGPRINTF5(("SCANTREE: dot found in node %p\n", head)); return head; }