aboutsummaryrefslogtreecommitdiff
path: root/libbb/process_escape_sequence.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbb/process_escape_sequence.c')
-rw-r--r--libbb/process_escape_sequence.c78
1 files changed, 47 insertions, 31 deletions
diff --git a/libbb/process_escape_sequence.c b/libbb/process_escape_sequence.c
index 82cbe10dc..346ecfa1e 100644
--- a/libbb/process_escape_sequence.c
+++ b/libbb/process_escape_sequence.c
@@ -18,52 +18,42 @@
18 18
19char FAST_FUNC bb_process_escape_sequence(const char **ptr) 19char FAST_FUNC bb_process_escape_sequence(const char **ptr)
20{ 20{
21 /* bash builtin "echo -e '\ec'" interprets \e as ESC,
22 * but coreutils "/bin/echo -e '\ec'" does not.
23 * manpages tend to support coreutils way.
24 * Update: coreutils added support for \e on 28 Oct 2009. */
25 static const char charmap[] ALIGN1 = {
26 'a', 'b', 'e', 'f', 'n', 'r', 't', 'v', '\\', 0,
27 '\a', '\b', 27, '\f', '\n', '\r', '\t', '\v', '\\', '\\' };
28
29 const char *p;
30 const char *q; 21 const char *q;
31 unsigned num_digits; 22 unsigned num_digits;
32 unsigned r;
33 unsigned n; 23 unsigned n;
34 unsigned d;
35 unsigned base; 24 unsigned base;
36 25
37 num_digits = n = 0; 26 num_digits = n = 0;
38 base = 8; 27 base = 8;
39 q = *ptr; 28 q = *ptr;
40 29
41#ifdef WANT_HEX_ESCAPES 30 if (WANT_HEX_ESCAPES && *q == 'x') {
42 if (*q == 'x') {
43 ++q; 31 ++q;
44 base = 16; 32 base = 16;
45 ++num_digits; 33 ++num_digits;
46 } 34 }
47#endif
48 35
49 /* bash requires leading 0 in octal escapes: 36 /* bash requires leading 0 in octal escapes:
50 * \02 works, \2 does not (prints \ and 2). 37 * \02 works, \2 does not (prints \ and 2).
51 * We treat \2 as a valid octal escape sequence. */ 38 * We treat \2 as a valid octal escape sequence. */
52 do { 39 do {
53 d = (unsigned char)(*q) - '0'; 40 unsigned r;
54#ifdef WANT_HEX_ESCAPES 41#if !WANT_HEX_ESCAPES
55 if (d >= 10) { 42 unsigned d = (unsigned char)(*q) - '0';
56 d = (unsigned char)(_tolower(*q)) - 'a' + 10; 43#else
57 } 44 unsigned d = (unsigned char)_tolower(*q) - '0';
45 if (d >= 10)
46 d += ('0' - 'a' + 10);
58#endif 47#endif
59
60 if (d >= base) { 48 if (d >= base) {
61#ifdef WANT_HEX_ESCAPES 49 if (WANT_HEX_ESCAPES && base == 16) {
62 if ((base == 16) && (!--num_digits)) { 50 --num_digits;
63/* return '\\'; */ 51 if (num_digits == 0) {
64 --q; 52 /* \x<bad_char>: return '\',
53 * leave ptr pointing to x */
54 return '\\';
55 }
65 } 56 }
66#endif
67 break; 57 break;
68 } 58 }
69 59
@@ -76,21 +66,47 @@ char FAST_FUNC bb_process_escape_sequence(const char **ptr)
76 ++q; 66 ++q;
77 } while (++num_digits < 3); 67 } while (++num_digits < 3);
78 68
79 if (num_digits == 0) { /* mnemonic escape sequence? */ 69 if (num_digits == 0) {
80 p = charmap; 70 /* Not octal or hex escape sequence.
71 * Is it one-letter one? */
72
73 /* bash builtin "echo -e '\ec'" interprets \e as ESC,
74 * but coreutils "/bin/echo -e '\ec'" does not.
75 * Manpages tend to support coreutils way.
76 * Update: coreutils added support for \e on 28 Oct 2009. */
77 static const char charmap[] ALIGN1 = {
78 'a', 'b', 'e', 'f', 'n', 'r', 't', 'v', '\\', '\0',
79 '\a', '\b', 27, '\f', '\n', '\r', '\t', '\v', '\\', '\\',
80 };
81 const char *p = charmap;
81 do { 82 do {
82 if (*p == *q) { 83 if (*p == *q) {
83 q++; 84 q++;
84 break; 85 break;
85 } 86 }
86 } while (*++p); 87 } while (*++p != '\0');
87 /* p points to found escape char or NUL, 88 /* p points to found escape char or NUL,
88 * advance it and find what it translates to */ 89 * advance it and find what it translates to.
89 p += sizeof(charmap) / 2; 90 * Note that \NUL and unrecognized sequence \z return '\'
90 n = *p; 91 * and leave ptr pointing to NUL or z. */
92 n = p[sizeof(charmap) / 2];
91 } 93 }
92 94
93 *ptr = q; 95 *ptr = q;
94 96
95 return (char) n; 97 return (char) n;
96} 98}
99
100char* FAST_FUNC strcpy_and_process_escape_sequences(char *dst, const char *src)
101{
102 while (1) {
103 char c, c1;
104 c = c1 = *src++;
105 if (c1 == '\\')
106 c1 = bb_process_escape_sequence(&src);
107 *dst = c1;
108 if (c == '\0')
109 return dst;
110 dst++;
111 }
112}