[PATCH] find ! ... (operator -not)

Denis Vlasenko vda.linux at googlemail.com
Fri Feb 2 21:43:56 UTC 2007


On Friday 02 February 2007 16:01, Natanael Copa wrote:
> Hi,
> 
> Attatched is a patch for support of the '!' operator for find.
> 
> I created another macro ALLOC_TEST for actions that can be inverted with
> '!'. They are not really actions (like -print) but tests (like -name).
> 
> It should not touch anything unless you have enabled the
> FEATURE_FIND_NOT config option.

parse_params():
invert_flag is never reset to 0. This must be a bug -
"not" shouldn't be applied to the second -name here, I think
(did not check it versus GNU find, tho...):
find ! -name '*.a' -o -name '*.b'


Now, to more cosmetic matters:


+#define LOGIC_XOR(a, b) ( (!(a)) != (!(b)) )
                         ACTS(print)
                         ACTS(name,  const char *pattern;)
 USE_FEATURE_FIND_PRINT0(ACTS(print0))
@@ -120,7 +124,13 @@
                cur_action = -1;
                do {
                        ap = app[++cur_action];
-               } while (ap && (rc = ap->f(fileName, statbuf, ap)));
+               } while (ap &&
+#if ENABLE_FEATURE_FIND_NOT
+                       (rc = LOGIC_XOR(ap->f(fileName, statbuf, ap), ap->invert))
+#else
+                       (rc = ap->f(fileName, statbuf, ap))
+#endif
+               );


This is obscure. I propose to do this instead - much easier to read:


        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) return rc;
                }
        }
        return rc;



+#if ENABLE_FEATURE_FIND_NOT
+               else if (strcmp(arg, "!") == 0
+                       USE_DESKTOP(|| strcmp(arg, "-not") == 0)
+               ) invert_flag = 1;
+#endif

Don't torture code reader please :) How about this?

+#if ENABLE_FEATURE_FIND_NOT
+               else if (strcmp(arg, "!") == 0
+                       USE_DESKTOP(|| strcmp(arg, "-not") == 0)
+               ) {
+                       invert_flag = 1;
+               }
+#endif



        action* alloc_action(int sizeof_struct, action_fp f
                USE_FEATURE_FIND_NOT(, int invert)
        )
        {
                action *ap;
                appp[cur_group] = xrealloc(appp[cur_group], (cur_action+2) * sizeof(*appp));
                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; )
                return ap;
        }
#define ALLOC_ACTION(name) (action_##name*)alloc_action(sizeof(action_##name), (action_fp) func_##name USE_FEATURE_FIND_NOT(, 0))

#define ALLOC_TEST(name) (action_##name*)alloc_action(sizeof(action_##name), (action_fp) func_##name USE_FEATURE_FIND_NOT(, invert_flag))


You do not need to pass "int invert" to alloc_action. Just use invert_flag
in alloc_action body, and forcefully reset invert_flag = 0 whenever
you are about to do ALLOC_ACTION, like when you handle -print.
(GNU find doesn't error out on "find ! -print", it simply ignores "!").

Care to produce updated patch?
--
vda



More information about the busybox mailing list