unescape.c - sbase - suckless unix tools | |
git clone git://git.suckless.org/sbase | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
unescape.c (1123B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include <ctype.h> | |
3 #include <string.h> | |
4 | |
5 #include "../util.h" | |
6 | |
7 #define is_odigit(c) ('0' <= c && c <= '7') | |
8 | |
9 size_t | |
10 unescape(char *s) | |
11 { | |
12 static const char escapes[256] = { | |
13 ['"'] = '"', | |
14 ['\''] = '\'', | |
15 ['\\'] = '\\', | |
16 ['a'] = '\a', | |
17 ['b'] = '\b', | |
18 ['E'] = 033, | |
19 ['e'] = 033, | |
20 ['f'] = '\f', | |
21 ['n'] = '\n', | |
22 ['r'] = '\r', | |
23 ['t'] = '\t', | |
24 ['v'] = '\v' | |
25 }; | |
26 size_t m, q; | |
27 char *r, *w; | |
28 | |
29 for (r = w = s; *r;) { | |
30 if (*r != '\\') { | |
31 *w++ = *r++; | |
32 continue; | |
33 } | |
34 r++; | |
35 if (!*r) { | |
36 eprintf("null escape sequence\n"); | |
37 } else if (escapes[(unsigned char)*r]) { | |
38 *w++ = escapes[(unsigned char)*r++]; | |
39 } else if (is_odigit(*r)) { | |
40 for (q = 0, m = 3; m && is_odigit(*r); m--, r++) | |
41 q = q * 8 + (*r - '0'); | |
42 *w++ = MIN(q, 255); | |
43 } else if (*r == 'x' && isxdigit(r[1])) { | |
44 r++; | |
45 for (q = 0, m = 2; m && isxdigit(*r); m--, r++) | |
46 if (isdigit(*r)) | |
47 q = q * 16 + (*r - '0'); | |
48 else | |
49 q = q * 16 + (tolower(*r) - 'a' … | |
50 *w++ = q; | |
51 } else { | |
52 eprintf("invalid escape sequence '\\%c'\n", *r); | |
53 } | |
54 } | |
55 *w = '\0'; | |
56 | |
57 return w - s; | |
58 } |