diff options
Diffstat (limited to 'libbb/process_escape_sequence.c')
-rw-r--r-- | libbb/process_escape_sequence.c | 78 |
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 | ||
19 | char FAST_FUNC bb_process_escape_sequence(const char **ptr) | 19 | char 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 | |||
100 | char* 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 | } | ||