--- libutil/unescape.c | 98 ++++++++++++++++++++++-------------------------------- 1 file changed, 39 insertions(+), 59 deletions(-) diff --git a/libutil/unescape.c b/libutil/unescape.c index d1503e6..bed2c61 100644 --- a/libutil/unescape.c +++ b/libutil/unescape.c _AT_@ -1,74 +1,54 @@ /* See LICENSE file for copyright and license details. */ +#include <ctype.h> #include <string.h> #include "../util.h" +#define isoctal(c) ('0' <= c && c <= '7') + size_t unescape(char *s) { - size_t len, i, off, m, factor, q; - - len = strlen(s); + static const char escapes[256] = { + ['"'] = '"', + ['\''] = '\'', + ['\\'] = '\\', + ['a'] = '\a', + ['b'] = '\b', + ['E'] = 033, + ['e'] = 033, + ['f'] = '\f', + ['n'] = '\n', + ['r'] = '\r', + ['t'] = '\t', + ['v'] = '\v' + }; + size_t m, q; + char *r, *w; - for (i = 0; i < len; i++) { - if (s[i] != '\\') + for (r = w = s; *r;) { + if (*r != '\\') { + *w++ = *r++; continue; - off = 0; - - switch (s[i + 1]) { - case '\\': s[i] = '\\'; off++; break; - case '\'': s[i] = '\'', off++; break; - case '"': s[i] = '"', off++; break; - case 'a': s[i] = '\a'; off++; break; - case 'b': s[i] = '\b'; off++; break; - case 'e': s[i] = 033; off++; break; - case 'f': s[i] = '\f'; off++; break; - case 'n': s[i] = '\n'; off++; break; - case 'r': s[i] = '\r'; off++; break; - case 't': s[i] = '\t'; off++; break; - case 'v': s[i] = '\v'; off++; break; - case 'x': - /* "\xH[H]" hexadecimal escape */ - for (m = i + 2; m < i + 1 + 3 && m < len; m++) - if ((s[m] < '0' && s[m] > '9') && - (s[m] < 'A' && s[m] > 'F') && - (s[m] < 'a' && s[m] > 'f')) - break; - if (m == i + 2) - eprintf("invalid escape sequence '\\%c'\n", s[i + 1]); - off += m - i - 1; - for (--m, q = 0, factor = 1; m > i + 1; m--) { - if (s[m] >= '0' && s[m] <= '9') - q += (s[m] - '0') * factor; - else if (s[m] >= 'A' && s[m] <= 'F') - q += ((s[m] - 'A') + 10) * factor; - else if (s[m] >= 'a' && s[m] <= 'f') - q += ((s[m] - 'a') + 10) * factor; - factor *= 16; - } - s[i] = q; - break; - case '\0': + } + r++; + if (!*r) { eprintf("null escape sequence\n"); - default: - /* "\O[OOO]" octal escape */ - for (m = i + 1; m < i + 1 + 4 && m < len; m++) - if (s[m] < '0' || s[m] > '7') - break; - if (m == i + 1) - eprintf("invalid escape sequence '\\%c'\n", s[i + 1]); - off += m - i - 1; - for (--m, q = 0, factor = 1; m > i; m--) { - q += (s[m] - '0') * factor; - factor *= 8; - } - s[i] = (q > 255) ? 255 : q; + } else if (escapes[*r & 255]) { + *w++ = escapes[*r++ & 255]; + } else if (isoctal(*r)) { + for (q = 0, m = 4; m && isoctal(*r); m--, r++) + q = q * 8 + (*r & 7); + *w++ = q > 255 ? 255 : q; + } else if (*r == 'x' && isxdigit(r[1])) { + r++; + for (q = 0, m = 2; m && isxdigit(*r); m--, r++) + q = q * 16 + (*r & 15) + 9 * !!isalpha(*r); + *w++ = q; + } else { + eprintf("invalid escape sequence '\\%c'\n", *r); } - - for (m = i + 1; m <= len - off; m++) - s[m] = s[m + off]; - len -= off; } - return len; + return w - s; } -- 2.11.0Received on Sun Feb 05 2017 - 00:44:35 CET
This archive was generated by hypermail 2.3.0 : Sun Feb 05 2017 - 00:48:18 CET