FireBirdLib - Topfield TMS PVR TAP Programming Library
ansicstr.c
Go to the documentation of this file.
1#include <ctype.h>
2#include "libFireBird.h"
3
4//Taken from GNU bash-4.3, strtrans.c
5
6/* Convert STRING by expanding the escape sequences specified by the
7 ANSI C standard. If SAWC is non-null, recognize `\c' and use that
8 as a string terminator. If we see \c, set *SAWC to 1 before
9 returning. LEN is the length of STRING. If (FLAGS&1) is non-zero,
10 that we're translating a string for `echo -e', and therefore should not
11 treat a single quote as a character that may be escaped with a backslash.
12 If (FLAGS&2) is non-zero, we're expanding for the parser and want to
13 quote CTLESC and CTLNUL with CTLESC. If (flags&4) is non-zero, we want
14 to remove the backslash before any unrecognized escape sequence. */
15
16#define CTLESC '\001'
17#define CTLNUL '\177'
18#define ESC '\033'
19#define TOUPPER(c) (islower(c) ? toupper(c) : (c))
20#define TOCTRL(x) (TOUPPER(x) & 037)
21#define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
22#define OCTVALUE(c) ((c) - '0')
23#define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
24#define ISXDIGIT(c) (ISDIGIT((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
25
26#define HEXVALUE(c) \
27 (((c) >= 'a' && (c) <= 'f') \
28 ? (c)-'a'+10 \
29 : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0')
30
31
32char *ansicstr (const char *string, int len, int flags, int *sawc, int *rlen)
33{
34 TRACEENTER();
35
36 int c, temp;
37 char *ret, *r;
38 const char *s;
39
40 if(rlen) *rlen = 0;
41 if(sawc) *sawc = 0;
42
43 if((string == 0) || (len == 0) || (*string == '\0'))
44 {
45 TRACEEXIT();
46 return NULL;
47 }
48
49 ret = (char*)TAP_MemAlloc(4*len + 1);
50 if(ret == NULL)
51 {
52 TRACEEXIT();
53 return NULL;
54 }
55
56 for(r = ret, s = string; s && *s;)
57 {
58 c = *s++;
59 if (c != '\\' || *s == '\0')
60 *r++ = c;
61 else
62 {
63 switch (c = *s++)
64 {
65 case 'a': c = '\a'; break;
66 case 'v': c = '\v'; break;
67 case 'b': c = '\b'; break;
68 case 'e':
69 case 'E': c = ESC; break;
70 case 'f': c = '\f'; break;
71 case 'n': c = '\n'; break;
72 case 'r': c = '\r'; break;
73 case 't': c = '\t'; break;
74 case '1':
75 case '2':
76 case '3':
77 case '4':
78 case '5':
79 case '6':
80 case '7':
81 {
82 if(flags & 1)
83 {
84 *r++ = '\\';
85 break;
86 }
87 }
88 /* no break */
89
90 case '0':
91 {
92 /* If (FLAGS & 1), we're translating a string for echo -e (or
93 the equivalent xpg_echo option), so we obey the SUSv3/
94 POSIX-2001 requirement and accept 0-3 octal digits after
95 a leading `0'. */
96 temp = 2 + ((flags & 1) && (c == '0'));
97 for (c -= '0'; ISOCTAL (*s) && temp--; s++)
98 c = (c * 8) + OCTVALUE (*s);
99 c &= 0xFF;
100 break;
101 }
102
103 case 'x': /* Hex digit -- non-ANSI */
104 {
105 if ((flags & 2) && *s == '{')
106 {
107 flags |= 16; /* internal flag value */
108 s++;
109 }
110 /* Consume at least two hex characters */
111 for (temp = 2, c = 0; ISXDIGIT ((unsigned char)*s) && temp--; s++)
112 c = (c * 16) + HEXVALUE (*s);
113
114 /* DGK says that after a `\x{' ksh93 consumes ISXDIGIT chars
115 until a non-xdigit or `}', so potentially more than two
116 chars are consumed. */
117
118 if (flags & 16)
119 {
120 for ( ; ISXDIGIT ((unsigned char)*s); s++)
121 c = (c * 16) + HEXVALUE (*s);
122 flags &= ~16;
123 if (*s == '}')
124 s++;
125 }
126 /* \x followed by non-hex digits is passed through unchanged */
127 else if (temp == 2)
128 {
129 *r++ = '\\';
130 c = 'x';
131 }
132 c &= 0xFF;
133 break;
134 }
135
136 //case 'u':
137 //case 'U':
138 //{
139 // temp = (c == 'u') ? 4 : 8; /* \uNNNN \UNNNNNNNN */
140 //
141 // for(v = 0; ISXDIGIT((byte)*s) && temp--; s++)
142 // v = (v * 16) + HEXVALUE(*s);
143 //
144 // if(temp == ((c == 'u') ? 4 : 8))
145 // {
146 // *r++ = '\\'; /* c remains unchanged */
147 // break;
148 // }
149 // else if(v <= 0x7f) /* <= 0x7f translates directly */
150 // {
151 // c = v;
152 // break;
153 // }
154 // else
155 // {
156 // temp = u32cconv(v, r);
157 // r += temp;
158 // continue;
159 // }
160 //}
161
162 case '\\':
163 break;
164
165 case '\'':
166 case '"':
167 case '?':
168 {
169 if(flags & 1)
170 *r++ = '\\';
171 break;
172 }
173
174 case 'c':
175 {
176 if(sawc)
177 {
178 *sawc = 1;
179 *r = '\0';
180 if(rlen) *rlen = r - ret;
181 return ret;
182 }
183 else if((flags & 1) == 0 && *s == 0)
184 ; /* pass \c through */
185 else if((flags & 1) == 0 && (c = *s))
186 {
187 s++;
188 if((flags & 2) && c == '\\' && c == *s)
189 s++; /* Posix requires $'\c\\' do backslash escaping */
190 c = TOCTRL(c);
191 break;
192 }
193 }
194 /* no break */
195
196 default:
197 {
198 if((flags & 4) == 0)
199 *r++ = '\\';
200 break;
201 }
202 }
203
204 if ((flags & 2) && (c == CTLESC || c == CTLNUL))
205 *r++ = CTLESC;
206 *r++ = c;
207 }
208 }
209
210 *r = '\0';
211 if(rlen) *rlen = r - ret;
212
213 TRACEEXIT();
214 return ret;
215}
char * ansicstr(const char *string, int len, int flags, int *sawc, int *rlen)
Definition: ansicstr.c:32
#define ISXDIGIT(c)
Definition: ansicstr.c:24
#define ESC
Definition: ansicstr.c:18
#define TOCTRL(x)
Definition: ansicstr.c:20
#define OCTVALUE(c)
Definition: ansicstr.c:22
#define HEXVALUE(c)
Definition: ansicstr.c:26
#define ISOCTAL(c)
Definition: ansicstr.c:21
#define CTLESC
Definition: ansicstr.c:16
#define CTLNUL
Definition: ansicstr.c:17
#define TRACEEXIT()
Definition: libFireBird.h:1244
#define TRACEENTER()
Definition: libFireBird.h:1243