Patch from Rogelio Serrano to defer checking whether the tty exists until
[oweals/busybox.git] / libbb / process_escape_sequence.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Utility routines.
4  *
5  * Copyright (C) Manuel Novoa III <mjn3@codepoet.org>
6  * and Vladimir Oleynik <dzo@simtreas.ru>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  *
22  *
23  */
24
25 #include <stdio.h>
26 #include <limits.h>
27 #include <ctype.h>
28 #include "libbb.h"
29
30 #define WANT_HEX_ESCAPES 1
31
32 /* Usual "this only works for ascii compatible encodings" disclaimer. */
33 #undef _tolower
34 #define _tolower(X) ((X)|((char) 0x20))
35
36 char bb_process_escape_sequence(const char **ptr)
37 {
38         static const char charmap[] = {
39                 'a',  'b',  'f',  'n',  'r',  't',  'v',  '\\', 0,
40                 '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' };
41
42         const char *p;
43         const char *q;
44         unsigned int num_digits;
45         unsigned int r;
46         unsigned int n;
47         unsigned int d;
48         unsigned int base;
49
50         num_digits = n = 0;
51         base = 8;
52         q = *ptr;
53
54 #ifdef WANT_HEX_ESCAPES
55         if (*q == 'x') {
56                 ++q;
57                 base = 16;
58                 ++num_digits;
59         }
60 #endif
61
62         do {
63                 d = (unsigned int)(*q - '0');
64 #ifdef WANT_HEX_ESCAPES
65                 if (d >= 10) {
66                         d = ((unsigned int)(_tolower(*q) - 'a')) + 10;
67                 }
68 #endif
69
70                 if (d >= base) {
71 #ifdef WANT_HEX_ESCAPES
72                         if ((base == 16) && (!--num_digits)) {
73 /*                              return '\\'; */
74                                 --q;
75                         }
76 #endif
77                         break;
78                 }
79
80                 r = n * base + d;
81                 if (r > UCHAR_MAX) {
82                         break;
83                 }
84
85                 n = r;
86                 ++q;
87         } while (++num_digits < 3);
88
89         if (num_digits == 0) {  /* mnemonic escape sequence? */
90                 p = charmap;
91                 do {
92                         if (*p == *q) {
93                                 q++;
94                                 break;
95                         }
96                 } while (*++p);
97                 n = *(p+(sizeof(charmap)/2));
98         }
99
100         *ptr = q;
101
102         return (char) n;
103 }
104
105 /* END CODE */
106 /*
107 Local Variables:
108 c-file-style: "linux"
109 c-basic-offset: 4
110 tab-width: 4
111 End:
112 */