Skip to content

Commit

Permalink
Add unescape2(), migrate some unescape() users over.
Browse files Browse the repository at this point in the history
  • Loading branch information
landley committed Apr 14, 2020
1 parent 64aa0f9 commit 71ae0e1
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 48 deletions.
23 changes: 23 additions & 0 deletions lib/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions lib/lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
46 changes: 8 additions & 38 deletions toys/posix/echo.c
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand All @@ -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);
}
}

Expand Down
16 changes: 6 additions & 10 deletions toys/posix/find.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 71ae0e1

Please sign in to comment.