From 48ca1a50d576548455082ce98eb3f5d2541676f3 Mon Sep 17 00:00:00 2001 From: Daniel Beer Date: Sat, 10 Apr 2010 16:33:21 +1200 Subject: [PATCH] Allow quoted strings in commands. --- mspdebug.man | 5 +++ parse.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 89 insertions(+), 5 deletions(-) diff --git a/mspdebug.man b/mspdebug.man index a5d1652..6cbf58a 100644 --- a/mspdebug.man +++ b/mspdebug.man @@ -92,6 +92,11 @@ Display a brief help message and exit. MSPDebug can accept commands either through an interactive prompt, or non-interactively when specified on the command line. The supported commands are listed below. + +Commands take arguments separated by spaces. Any text string enclosed +in double-quotation marks is considered to be a single argument, even +if it contains space characters. Within a quoted string, the usual +C-style backslash substitutions can be used. .IP "\fB=\fR \fIexpression\fR" Evaluate an address expression and show both its value, and the result when the value is looked up in reverse in the current symbol diff --git a/parse.c b/parse.c index 61655cb..ffb1d09 100644 --- a/parse.c +++ b/parse.c @@ -85,7 +85,10 @@ int is_interactive(void) char *get_arg(char **text) { char *start; + char *rewrite; char *end; + int qstate = 0; + int qval = 0; if (!text) return NULL; @@ -97,14 +100,90 @@ char *get_arg(char **text) if (!*start) return NULL; + /* We've found the start of the argument. Parse it. */ end = start; - while (*end && !isspace(*end)) + rewrite = start; + while (*end) { + switch (qstate) { + case 0: /* Bare */ + if (isspace(*end)) + goto out; + else if (*end == '"') + qstate = 1; + else + *(rewrite++) = *end; + break; + + case 1: /* In quotes */ + if (*end == '"') + qstate = 0; + else if (*end == '\\') + qstate = 2; + else + *(rewrite++) = *end; + break; + + case 2: /* Backslash */ + if (*end == '\\') + *(rewrite++) = '\\'; + else if (*end == 'n') + *(rewrite++) = '\n'; + else if (*end == 'r') + *(rewrite++) = '\r'; + else if (*end == 't') + *(rewrite++) = '\t'; + else if (*end >= '0' && *end <= '3') { + qstate = 30; + qval = *end - '0'; + } else if (*end == 'x') { + qstate = 40; + qval = 0; + } else + *(rewrite++) = *end; + + if (qstate == 2) + qstate = 1; + break; + + case 30: /* Octal */ + case 31: + if (*end >= '0' && *end <= '7') + qval = (qval << 3) | (*end - '0'); + + if (qstate == 31) { + *(rewrite++) = qval; + qstate = 1; + } else { + qstate++; + } + break; + + case 40: /* Hex */ + case 41: + if (isdigit(*end)) + qval = (qval << 4) | (*end - '0'); + else if (isupper(*end)) + qval = (qval << 4) | (*end - 'A' + 10); + else if (islower(*end)) + qval = (qval << 4) | (*end - 'a' + 10); + + if (qstate == 41) { + *(rewrite++) = qval; + qstate = 1; + } else { + qstate++; + } + break; + } + + end++; + } + out: + /* Leave the text pointer at the end of the next argument */ + while (*end && isspace(*end)) end++; - if (*end) - while (*end && isspace(*end)) - *(end++) = 0; - + *rewrite = 0; *text = end; return start; }