Dan Kegel : cmd: del /a: move parsing of attributes to helper function, use bitmasks.

Alexandre Julliard julliard at winehq.org
Tue May 24 12:53:50 CDT 2011


Module: wine
Branch: master
Commit: 65b27c9ecd2c80aa91fa0c5425ddfb2f9f2cb37d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=65b27c9ecd2c80aa91fa0c5425ddfb2f9f2cb37d

Author: Dan Kegel <dank at kegel.com>
Date:   Sun May 22 07:59:22 2011 -0700

cmd: del /a: move parsing of attributes to helper function, use bitmasks.

---

 programs/cmd/builtins.c |  111 +++++++++++++++++++++++------------------------
 1 files changed, 54 insertions(+), 57 deletions(-)

diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 944a997..7a6ae72 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -532,6 +532,53 @@ void WCMD_create_dir (void) {
     if (!create_full_path(param1)) WCMD_print_error ();
 }
 
+/* Parse the /A options given by the user on the commandline
+ * into a bitmask of wanted attributes (*wantSet),
+ * and a bitmask of unwanted attributes (*wantClear).
+ */
+static void WCMD_delete_parse_attributes(DWORD *wantSet, DWORD *wantClear) {
+    static const WCHAR parmA[] = {'/','A','\0'};
+    WCHAR *p;
+
+    /* both are strictly 'out' parameters */
+    *wantSet=0;
+    *wantClear=0;
+
+    /* For each /A argument */
+    for (p=strstrW(quals, parmA); p != NULL; p=strstrW(p, parmA)) {
+        /* Skip /A itself */
+        p += 2;
+
+        /* Skip optional : */
+        if (*p == ':') p++;
+
+        /* For each of the attribute specifier chars to this /A option */
+        for (; *p != 0 && *p != '/'; p++) {
+            BOOL negate = FALSE;
+            DWORD mask  = 0;
+
+            if (*p == '-') {
+                negate=TRUE;
+                p++;
+            }
+
+            /* Convert the attribute specifier to a bit in one of the masks */
+            switch (*p) {
+            case 'R': mask = FILE_ATTRIBUTE_READONLY; break;
+            case 'H': mask = FILE_ATTRIBUTE_HIDDEN;   break;
+            case 'S': mask = FILE_ATTRIBUTE_SYSTEM;   break;
+            case 'A': mask = FILE_ATTRIBUTE_ARCHIVE;  break;
+            default:
+                WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
+            }
+            if (negate)
+                *wantClear |= mask;
+            else
+                *wantSet |= mask;
+        }
+    }
+}
+
 /****************************************************************************
  * WCMD_delete
  *
@@ -551,11 +598,14 @@ BOOL WCMD_delete (WCHAR *command, BOOL expectDir) {
     int   argsProcessed = 0;
     WCHAR *argN          = command;
     BOOL  foundAny      = FALSE;
-    static const WCHAR parmA[] = {'/','A','\0'};
     static const WCHAR parmQ[] = {'/','Q','\0'};
     static const WCHAR parmP[] = {'/','P','\0'};
     static const WCHAR parmS[] = {'/','S','\0'};
     static const WCHAR parmF[] = {'/','F','\0'};
+    DWORD wanted_attrs;
+    DWORD unwanted_attrs;
+
+    WCMD_delete_parse_attributes(&wanted_attrs, &unwanted_attrs);
 
     /* If not recursing, clear error flag */
     if (expectDir) errorlevel = 0;
@@ -644,64 +694,11 @@ BOOL WCMD_delete (WCHAR *command, BOOL expectDir) {
             }
             else strcpyW (fpath, fd.cFileName);
             if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
-              BOOL  ok = TRUE;
-              WCHAR *nextA = strstrW (quals, parmA);
+              BOOL ok;
 
               /* Handle attribute matching (/A) */
-              if (nextA != NULL) {
-                ok = FALSE;
-                while (nextA != NULL && !ok) {
-
-                  WCHAR *thisA = (nextA+2);
-                  BOOL  stillOK = TRUE;
-
-                  /* Skip optional : */
-                  if (*thisA == ':') thisA++;
-
-                  /* Parse each of the /A[:]xxx in turn */
-                  while (*thisA && *thisA != '/') {
-                    BOOL negate    = FALSE;
-                    BOOL attribute = FALSE;
-
-                    /* Match negation of attribute first */
-                    if (*thisA == '-') {
-                      negate=TRUE;
-                      thisA++;
-                    }
-
-                    /* Match attribute */
-                    switch (*thisA) {
-                    case 'R': attribute = (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY);
-                              break;
-                    case 'H': attribute = (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN);
-                              break;
-                    case 'S': attribute = (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM);
-                              break;
-                    case 'A': attribute = (fd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE);
-                              break;
-                    default:
-                        WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
-                    }
-
-                    /* Now check result, keeping a running boolean about whether it
-                       matches all parsed attributes so far                         */
-                    if (attribute && !negate) {
-                        stillOK = stillOK;
-                    } else if (!attribute && negate) {
-                        stillOK = stillOK;
-                    } else {
-                        stillOK = FALSE;
-                    }
-                    thisA++;
-                  }
-
-                  /* Save the running total as the final result */
-                  ok = stillOK;
-
-                  /* Step on to next /A set */
-                  nextA = strstrW (nextA+1, parmA);
-                }
-              }
+              ok =  ((fd.dwFileAttributes & wanted_attrs) == wanted_attrs)
+                 && ((fd.dwFileAttributes & unwanted_attrs) == 0);
 
               /* /P means prompt for each file */
               if (ok && strstrW (quals, parmP) != NULL) {




More information about the wine-cvs mailing list