Hugh McMaster : regedit: Tokenize command-line input.

Alexandre Julliard julliard at winehq.org
Thu Jun 23 11:15:24 CDT 2016


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

Author: Hugh McMaster <hugh.mcmaster at outlook.com>
Date:   Wed Jun 22 12:59:13 2016 +0000

regedit: Tokenize command-line input.

Signed-off-by: Hugh McMaster <hugh.mcmaster at outlook.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/regedit/regedit.c | 247 ++++++++++++++++++++-------------------------
 1 file changed, 109 insertions(+), 138 deletions(-)

diff --git a/programs/regedit/regedit.c b/programs/regedit/regedit.c
index 175e926..d2ed891 100644
--- a/programs/regedit/regedit.c
+++ b/programs/regedit/regedit.c
@@ -56,81 +56,23 @@ static const char *usage =
     "regedit.\n";
 
 typedef enum {
-    ACTION_UNDEF, ACTION_ADD, ACTION_EXPORT, ACTION_DELETE
+    ACTION_ADD, ACTION_EXPORT, ACTION_DELETE
 } REGEDIT_ACTION;
 
-/******************************************************************************
- * Copies file name from command line string to the buffer.
- * Rewinds the command line string pointer to the next non-space character
- * after the file name.
- * Buffer contains an empty string if no filename was found;
- *
- * params:
- * command_line - command line current position pointer
- *      where *s[0] is the first symbol of the file name.
- * file_name - buffer to write the file name to.
- */
-static void get_file_name(CHAR **command_line, CHAR *file_name)
-{
-    CHAR *s = *command_line;
-    int pos = 0;                /* position of pointer "s" in *command_line */
-    file_name[0] = 0;
-
-    if (!s[0]) {
-        return;
-    }
-
-    if (s[0] == '"') {
-        s++;
-        (*command_line)++;
-        while(s[0] != '"') {
-            if (!s[0]) {
-                fprintf(stderr, "regedit: Unexpected end of file name!\n");
-                exit(1);
-            }
-            s++;
-            pos++;
-        }
-    } else {
-        while(s[0] && !isspace(s[0])) {
-            s++;
-            pos++;
-        }
-    }
-    memcpy(file_name, *command_line, pos * sizeof((*command_line)[0]));
-    /* Terminate the string and remove the trailing backslash */
-    if (pos > 0 && file_name[pos - 1] == '\\') {
-        file_name[pos - 1] = '\0';
-    } else {
-        file_name[pos] = '\0';
-    }
-
-    if (s[0]) {
-        s++;
-        pos++;
-    }
-    while(s[0] && isspace(s[0])) {
-        s++;
-        pos++;
-    }
-    (*command_line) += pos;
-}
-
-static BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
+static BOOL PerformRegAction(REGEDIT_ACTION action, char **argv, int *i)
 {
     switch (action) {
     case ACTION_ADD: {
-            CHAR filename[MAX_PATH];
+            char *filename = argv[*i];
             FILE *reg_file;
 
-            get_file_name(&s, filename);
             if (!filename[0]) {
                 fprintf(stderr, "regedit: No file name was specified\n");
                 fprintf(stderr,usage);
                 exit(1);
             }
 
-            while(filename[0]) {
+            if (filename[0]) {
                 char* realname = NULL;
 
                 if (strcmp(filename, "-") == 0)
@@ -167,14 +109,12 @@ static BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
                     HeapFree(GetProcessHeap(),0,realname);
                     fclose(reg_file);
                 }
-                get_file_name(&s, filename);
             }
             break;
         }
     case ACTION_DELETE: {
-            CHAR reg_key_name[KEY_MAX_LEN];
+            char *reg_key_name = argv[*i];
 
-            get_file_name(&s, reg_key_name);
             if (!reg_key_name[0]) {
                 fprintf(stderr, "regedit: No registry key was specified for removal\n");
                 fprintf(stderr,usage);
@@ -188,11 +128,9 @@ static BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
             break;
         }
     case ACTION_EXPORT: {
-            CHAR filename[MAX_PATH];
+            char *filename = argv[*i];
             WCHAR* filenameW;
 
-            filename[0] = '\0';
-            get_file_name(&s, filename);
             if (!filename[0]) {
                 fprintf(stderr, "regedit: No filename was specified\n");
                 fprintf(stderr,usage);
@@ -200,11 +138,10 @@ static BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
             }
 
             filenameW = GetWideString(filename);
-            if (s[0]) {
-                CHAR reg_key_name[KEY_MAX_LEN];
+            if (filenameW[0]) {
+                char *reg_key_name = argv[++(*i)];
                 WCHAR* reg_key_nameW;
 
-                get_file_name(&s, reg_key_name);
                 reg_key_nameW = GetWideString(reg_key_name);
                 export_registry_key(filenameW, reg_key_nameW, REG_FORMAT_4);
                 HeapFree(GetProcessHeap(), 0, reg_key_nameW);
@@ -222,83 +159,117 @@ static BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
     return TRUE;
 }
 
+char *get_token(char *input, char **next)
+{
+    char *ch = input;
+    char *str;
+
+    while (*ch && isspace(*ch))
+        ch++;
+
+    str = ch;
+
+    if (*ch == '"') {
+        ch++;
+        str = ch;
+        for (;;) {
+            while (*ch && (*ch != '"'))
+                ch++;
+
+            if (!*ch)
+                break;
+
+            if (*(ch - 1) == '\\') {
+                ch++;
+                continue;
+            }
+            break;
+        }
+    }
+    else {
+        while (*ch && !isspace(*ch))
+            ch++;
+    }
+
+    if (*ch) {
+        *ch = 0;
+        ch++;
+    }
+
+    *next = ch;
+    return str;
+}
+
 BOOL ProcessCmdLine(LPSTR lpCmdLine)
 {
-    REGEDIT_ACTION action = ACTION_UNDEF;
-    LPSTR s = lpCmdLine;        /* command line pointer */
-    CHAR ch = *s;               /* current character */
+    char *s = lpCmdLine;
+    char **argv;
+    char *tok;
+    int argc = 0, i = 1;
+    REGEDIT_ACTION action = ACTION_ADD;
 
-    while (ch && ((ch == '-') || (ch == '/'))) {
-        char chu;
-        char ch2;
+    if (!*lpCmdLine)
+        return FALSE;
 
+    while (*s) {
+        if (isspace(*s))
+            i++;
         s++;
-        ch = *s;
-        if (!ch || isspace(ch))
+    }
+
+    s = lpCmdLine;
+    argv = HeapAlloc(GetProcessHeap(), 0, i * sizeof(char *));
+
+    for (i = 0; *s; i++)
+    {
+        tok = get_token(s, &s);
+        argv[i] = HeapAlloc(GetProcessHeap(), 0, strlen(tok) + 1);
+        strcpy(argv[i], tok);
+        argc++;
+    }
+
+    for (i = 0; i < argc; i++)
+    {
+        if (argv[i][0] != '/' && argv[i][0] != '-')
+            break; /* No flags specified. */
+
+        if (!argv[i][1] && argv[i][0] == '-')
+            break; /* '-' is a filename. It indicates we should use stdin. */
+
+        if (argv[i][1] && argv[i][2] && argv[i][2] != ':')
+            break; /* This is a file path beginning with '/'. */
+
+        switch (toupper(argv[i][1]))
         {
-            /* '-' is a file name. It indicates we should use stdin */
-            s--;
+        case '?':
+            fprintf(stderr, usage);
+            exit(0);
             break;
-        }
-        ch2 = *(s+1);
-        chu = toupper(ch);
-        if (!ch2 || isspace(ch2)) {
-            if (chu == 'S' || chu == 'V') {
-                /* ignore these switches */
-            } else {
-                switch (chu) {
-                case 'D':
-                    action = ACTION_DELETE;
-                    break;
-                case 'E':
-                    action = ACTION_EXPORT;
-                    break;
-                case '?':
-                    fprintf(stderr,usage);
-                    exit(0);
-                    break;
-                default:
-                    fprintf(stderr, "regedit: Invalid or unrecognized switch [/%c]\n", chu);
-                    exit(1);
-                    break;
-                }
-            }
-            s++;
-        } else {
-            if (ch2 == ':') {
-                switch (chu) {
-                case 'L':
-                    /* fall through */
-                case 'R':
-                    s += 2;
-                    while (*s && !isspace(*s)) {
-                        s++;
-                    }
-                    break;
-                default:
-                    fprintf(stderr, "regedit: Invalid or unrecognized switch [/%c]\n", chu);
-                    exit(1);
-                    break;
-                }
-            } else {
-                /* this is a file name, starting from '/' */
-                s--;
-                break;
-            }
-        }
-        /* skip spaces to the next parameter */
-        ch = *s;
-        while (ch && isspace(ch)) {
-            s++;
-            ch = *s;
+        case 'D':
+            action = ACTION_DELETE;
+            break;
+        case 'E':
+            action = ACTION_EXPORT;
+            break;
+        case 'L':
+        case 'R':
+            /* unhandled */;
+            break;
+        case 'S':
+        case 'V':
+            /* ignored */;
+            break;
+        default:
+            fprintf(stderr, "regedit: Invalid switch [%ls]\n", argv[i]);
+            exit(1);
         }
     }
 
-    if (*s && action == ACTION_UNDEF)
-        action = ACTION_ADD;
+    PerformRegAction(action, argv, &i);
 
-    if (action == ACTION_UNDEF)
-        return FALSE;
+    for (i = 0; i < argc; i++)
+        HeapFree(GetProcessHeap(), 0, argv[i]);
+    HeapFree(GetProcessHeap(), 0, argv);
 
-    return PerformRegAction(action, s);
+    return TRUE;
 }




More information about the wine-cvs mailing list