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 = 4; 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' + 10); 50 *w++ = q; 51 } else { 52 eprintf("invalid escape sequence '\\%c'\n", *r); 53 } 54 } 55 *w = '\0'; 56 57 return w - s; 58 }