]> mj.ucw.cz Git - libucw.git/blob - ucw/str-esc.c
The big move. Step #1: Move whole lib/ to ucw/.
[libucw.git] / ucw / str-esc.c
1 /*
2  *      UCW Library -- String Unescaping
3  *
4  *      (c) 2006 Pavel Charvat <pchar@ucw.cz>
5  *      (c) 2007 Martin Mares <mj@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #undef LOCAL_DEBUG
12
13 #include "ucw/lib.h"
14 #include "ucw/string.h"
15 #include "ucw/chartype.h"
16 #include <stdlib.h>
17
18 /* Expands C99-like escape sequences.
19  * It is safe to use the same buffer for both input and output. */
20 char *
21 str_unesc(char *d, const char *s)
22 {
23   while (*s)
24     {
25       if (*s == '\\')
26         switch (s[1])
27           {
28             case 'a': *d++ = '\a'; s += 2; break;
29             case 'b': *d++ = '\b'; s += 2; break;
30             case 'f': *d++ = '\f'; s += 2; break;
31             case 'n': *d++ = '\n'; s += 2; break;
32             case 'r': *d++ = '\r'; s += 2; break;
33             case 't': *d++ = '\t'; s += 2; break;
34             case 'v': *d++ = '\v'; s += 2; break;
35             case '\?': *d++ = '\?'; s += 2; break;
36             case '\'': *d++ = '\''; s += 2; break;
37             case '\"': *d++ = '\"'; s += 2; break;
38             case '\\': *d++ = '\\'; s += 2; break;
39             case 'x':
40               if (!Cxdigit(s[2]))
41                 {
42                   s++;
43                   DBG("\\x used with no following hex digits");
44                 }
45               else
46                 {
47                   char *p;
48                   uns v = strtoul(s + 2, &p, 16);
49                   if (v <= 255)
50                     *d++ = v;
51                   else
52                     DBG("hex escape sequence out of range");
53                   s = (char *)p;
54                 }
55               break;
56             default:
57               if (s[1] >= '0' && s[1] <= '7')
58                 {
59                   uns v = s[1] - '0';
60                   s += 2;
61                   for (uns i = 0; i < 2 && *s >= '0' && *s <= '7'; s++, i++)
62                     v = (v << 3) + *s - '0';
63                   if (v <= 255)
64                     *d++ = v;
65                   else
66                     DBG("octal escape sequence out of range");
67                 }
68               else
69                 *d++ = *s++;
70               break;
71           }
72       else
73         *d++ = *s++;
74     }
75   *d = 0;
76   return d;
77 }
78
79 #ifdef TEST
80
81 #include <stdio.h>
82 #include <string.h>
83
84 int main(int argc, char **argv)
85 {
86   if (argc < 2)
87     return 1;
88
89   char tmp[strlen(argv[1]) + 1];
90   int len = str_unesc(tmp, argv[1]) - tmp;
91
92   char hex[2*len + 1];
93   mem_to_hex(hex, tmp, len, ' ');
94   puts(hex);
95
96   return 0;
97 }
98
99 #endif