From 71ae0e1617218820f405bbf79d5d5dc89d5772ee Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 13 Apr 2020 19:45:09 -0500 Subject: Add unescape2(), migrate some unescape() users over. --- lib/lib.c | 23 +++++++++++++++++++++++ lib/lib.h | 1 + toys/posix/echo.c | 46 ++++++++-------------------------------------- toys/posix/find.c | 16 ++++++---------- 4 files changed, 38 insertions(+), 48 deletions(-) diff --git a/lib/lib.c b/lib/lib.c index 364ce07e..4fa358c0 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -436,6 +436,29 @@ int unescape(char c) return (idx == -1) ? 0 : to[idx]; } +// parse next character advancing pointer. echo requires leading 0 in octal esc +int unescape2(char **c, int echo) +{ + int idx = *((*c)++), i, off; + + if (idx != '\\' || !**c) return idx; + if (**c == 'c') return 31&*(++*c); + for (i = 0; i<4; i++) { + if (sscanf(*c, (char *[]){"0%3o%n"+!echo, "x%2x%n", "u%4x%n", "U%6x%n"}[i], + &idx, &off)) + { + *c += off; + + return idx; + } + } + + if (-1 == (idx = stridx("\\abeEfnrtv'\"?", **c))) return '\\'; + ++*c; + + return "\\\a\b\033\033\f\n\r\t\v'\"?"[idx]; +} + // If string ends with suffix return pointer to start of suffix in string, // else NULL char *strend(char *str, char *suffix) diff --git a/lib/lib.h b/lib/lib.h index 3200dc32..60c800ca 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -234,6 +234,7 @@ char *strlower(char *s); char *strafter(char *haystack, char *needle); char *chomp(char *s); int unescape(char c); +int unescape2(char **c, int echo); char *strend(char *str, char *suffix); int strstart(char **a, char *b); int strcasestart(char **a, char *b); diff --git a/toys/posix/echo.c b/toys/posix/echo.c index c78c2c01..b546e94b 100644 --- a/toys/posix/echo.c +++ b/toys/posix/echo.c @@ -41,12 +41,10 @@ config ECHO void echo_main(void) { - int i = 0, out; - char *arg, *c; + int i = 0; + char *arg, *c, out[8]; - for (;;) { - arg = toys.optargs[i]; - if (!arg) break; + while ((arg = toys.optargs[i])) { if (i++) putchar(' '); // Should we output arg verbatim? @@ -58,40 +56,12 @@ void echo_main(void) // Handle -e - for (c = arg;;) { - if (!(out = *(c++))) break; + for (c = arg; *c; ) { + unsigned u; - // handle \escapes - if (out == '\\' && *c) { - int slash = *(c++), n = unescape(slash); - - if (n) out = n; - else if (slash=='c') return; - else if (slash=='0') { - out = 0; - while (*c>='0' && *c<='7' && n++<3) out = (out*8)+*(c++)-'0'; - } else if (slash=='x') { - out = 0; - while (n++<2) { - if (*c>='0' && *c<='9') out = (out*16)+*(c++)-'0'; - else { - int temp = tolower(*c); - if (temp>='a' && temp<='f') { - out = (out*16)+temp-'a'+10; - c++; - } else { - if (n==1) { - --c; - out = '\\'; - } - break; - } - } - } - // Slash in front of unknown character, print literal. - } else c--; - } - putchar(out); + if (*c == '\\' && c[1] == 'c') return; + if ((u = unescape2(&c, 1))<128) putchar(u); + else printf("%.*s", (int)wcrtomb(out, u, 0), out); } } diff --git a/toys/posix/find.c b/toys/posix/find.c index 3fb97b1c..9b688d46 100644 --- a/toys/posix/find.c +++ b/toys/posix/find.c @@ -585,16 +585,12 @@ static int do_find(struct dirtree *new) if (check) for (fmt = ss[1]; *fmt; fmt++) { // Print the parts that aren't escapes if (*fmt == '\\') { - int slash = *++fmt, n = unescape(slash); - - if (n) ch = n; - else if (slash=='c') break; - else if (slash=='0') { - ch = 0; - while (*fmt>='0' && *fmt<='7' && n++<3) ch=(ch*8)+*(fmt++)-'0'; - --fmt; - } else error_exit("bad \\%c", *fmt); - putchar(ch); + unsigned u; + + if (fmt[1] == 'c') break; + if ((u = unescape2(&fmt, 0))<128) putchar(u); + else printf("%.*s", (int)wcrtomb(buf, u, 0), buf); + fmt--; } else if (*fmt != '%') putchar(*fmt); else if (*++fmt == '%') putchar('%'); else { -- cgit v1.2.3