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