From a40b9db5a4b842fafcf4e5c1e65ce618d7a25df8 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Mon, 15 May 2023 16:49:08 +0100 Subject: [PATCH] Rewrite nexttok() to allow escaped spaces in non-string arguments Useful for file names ``` $ echo "Hello, world!" >'Q:\Projects\Eurovision Song Contest\light show.eep' $ avrdude -qqt avrdude> erase eeprom 0 16 avrdude> # Escape spaces in filenames with a backslash: avrdude> write eeprom Q:\Projects\Eurovision\ Song\ Contest\light\ show.eep:r avrdude> dump eeprom 0 16 0000 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0a ff ff |Hello, world! ..| ``` --- src/term.c | 69 +++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/src/term.c b/src/term.c index c8b68bbb..e98a0f7c 100644 --- a/src/term.c +++ b/src/term.c @@ -117,43 +117,6 @@ struct command cmd[] = { static int spi_mode = 0; -static int nexttok(char *buf, char **tok, char **next) { - unsigned char *q, *n; - - q = (unsigned char *) buf; - while (isspace(*q)) - q++; - - /* isolate first token */ - n = q; - uint8_t quotes = 0; - while (*n && (!isspace(*n) || quotes)) { - // Poor man's quote and escape processing - if (*n == '"' || *n == '\'') - quotes++; - else if(*n == '\\' && n[1]) - n++; - else if (isspace(*n) && (n > q+1) && (n[-1] == '"' || n[-1] == '\'')) - break; - n++; - } - - if (*n) { - *n = 0; - n++; - } - - /* find start of next token */ - while (isspace(*n)) - n++; - - *tok = (char *) q; - *next = (char *) n; - - return 0; -} - - static int hexdump_line(char *buffer, unsigned char *p, int n, int pad) { char *hexdata = "0123456789abcdef"; char *b = buffer; @@ -1078,6 +1041,38 @@ static int cmd_quell(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { return 0; } + +static int nexttok(char *buf, char **tok, char **next) { + unsigned char *q, *r, *w, inquote; + + q = (unsigned char *) buf; + while (isspace(*q)) + q++; + + // Isolate first token + for(inquote = 0, w = r = q; *r && !(isspace(*r) && !inquote); *w++ = *r++) { + // Poor man's quote and escape processing + if(*r == '"' || *r == '\'') + inquote = inquote && *r == inquote? 0: inquote? inquote: *r; + else if(*r == '\\' && isspace(r[1])) // Remove \ before space for file names + r++; + else if(*r == '\\' && r[1]) // Leave other \ to keep C-style, eg, '\n' + *w++ = *r++; + } + if(*r) + r++; + *w = 0; + + // Find start of next token + while (isspace(*r)) + r++; + + *tok = (char *) q; + *next = (char *) r; + + return 0; +} + static int tokenize(char *s, char ***argv) { int i, n, l, nargs; int len, slen;