unescape.c - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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' + 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 }