source: trunk/dll/literal.c@ 1039

Last change on this file since 1039 was 1039, checked in by Gregg Young, 17 years ago

Removed unnecessary xfrees and included fortify.h where needed; moved several misplaced (x)frees;

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.9 KB
Line 
1
2/***********************************************************************
3
4 $Id: literal.c 1039 2008-07-05 22:16:21Z gyoung $
5
6 string quoting utilities
7 wildcarding utilities
8
9 Copyright (c) 1993-98 M. Kimes
10 Copyright (c) 2004, 2007 Steven H.Levine
11
12 Archive containers
13
14 01 Aug 04 SHL Rework fixup to avoid overflows
15 16 Jun 06 SHL liternal: comments
16 22 Jul 06 SHL Check more run time errors
17 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
18 16 Nov 07 SHL Report fixup buffer overflow
19 29 Feb 08 GKY Use xfree where appropriate
20 15 Mar 08 KOMH Fix wildcard for multiple dots
21
22***********************************************************************/
23
24#include <stdlib.h>
25#include <string.h>
26#include <ctype.h>
27
28#define INCL_OS2
29#define INCL_WIN
30#define INCL_LONGLONG // dircnrs.h
31
32#include "errutil.h" // Dos_Error...
33#include "fm3dll.h"
34#include "fortify.h"
35
36static PSZ pszSrcFile = __FILE__;
37
38static INT index(const CHAR * s, const CHAR c);
39
40/* Get index of char in string
41 * @parm s string to search
42 * @parm c char to search for
43 * @return 0 relative index of c in s or -1
44 */
45
46static INT index(const CHAR * s, const CHAR c)
47{
48 CHAR *p;
49
50 p = strchr(s, c);
51 if (p == NULL || !*p)
52 return -1;
53 return (INT) (p - s);
54}
55
56/* literal()
57 * Translate a string with \ escape tokens to binary equivalent
58 * Translates in place
59 *
60 * 1. \x1b translates to CHAR(0x1b)
61 * 2. \27 translates to CHAR(27)
62 * 3. \" translates to "
63 * 4. \' translates to '
64 * 5. \\ translates to \
65 * 6. \r translates to carriage return
66 * 7. \n translates to linefeed
67 * 8. \b translates to backspace
68 * 9. \t translates to tab
69 * 10. \a translates to bell
70 * 11. \f translates to formfeed
71 *
72 * Synopsis
73 * *s = "this\x20is\32a test of \\MSC\\CSM\7"
74 * literal(s);
75 *
76 * ( s now equals "this is a test of \MSC\CSM")
77 *
78 * Return converted character count like strlen()
79 * Count does not include terminating nul
80 */
81
82#define HEX "0123456789ABCDEF"
83#define DEC "0123456789"
84
85UINT literal(PSZ pszBuf)
86{
87 INT wpos;
88 INT iBuf;
89 UINT cBufBytes;
90 INT iBufSave;
91 PSZ pszOut;
92 PSZ pszWork;
93 CHAR wchar;
94
95 if (!pszBuf || !*pszBuf)
96 return 0;
97 cBufBytes = strlen(pszBuf) + 1;
98 pszWork = pszOut = xmalloc(cBufBytes + 1, pszSrcFile, __LINE__);
99 if (!pszWork)
100 return 0;
101
102 iBuf = 0; /* set index to first character */
103 while (pszBuf[iBuf]) {
104 switch (pszBuf[iBuf]) {
105 case '\\':
106 switch (pszBuf[iBuf + 1]) {
107 case 'x': /* hexadecimal */
108 wchar = 0;
109 iBuf += 2; /* get past "\x" */
110 if (index(HEX, (CHAR) toupper(pszBuf[iBuf])) != -1) {
111 iBufSave = iBuf;
112 while (((wpos = index(HEX, (CHAR) toupper(pszBuf[iBuf]))) != -1) &&
113 iBuf < iBufSave + 2) {
114 wchar = (CHAR) (wchar << 4) + (CHAR) wpos;
115 iBuf++;
116 }
117 }
118 else
119 wchar = 'x'; /* just an x */
120 iBuf--;
121 *pszOut++ = wchar;
122 break;
123
124 case '\\': /* we want a "\" */
125 iBuf++;
126 *pszOut++ = '\\';
127 break;
128
129 case 't': /* tab CHAR */
130 iBuf++;
131 *pszOut++ = '\t';
132 break;
133
134 case 'n': /* new line */
135 iBuf++;
136 *pszOut++ = '\n';
137 break;
138
139 case 'r': /* carr return */
140 iBuf++;
141 *pszOut++ = '\r';
142 break;
143
144 case 'b': /* back space */
145 iBuf++;
146 *pszOut++ = '\b';
147 break;
148
149 case 'f': /* formfeed */
150 iBuf++;
151 *pszOut++ = '\x0c';
152 break;
153
154 case 'a': /* bell */
155 iBuf++;
156 *pszOut++ = '\07';
157 break;
158
159 case '\'': /* single quote */
160 iBuf++;
161 *pszOut++ = '\'';
162 break;
163
164 case '\"': /* double quote */
165
166 iBuf++;
167 *pszOut++ = '\"';
168 break;
169
170 default: /* decimal */
171 iBuf++; /* get past "\" */
172 wchar = 0;
173 if (index(DEC, pszBuf[iBuf]) != -1) {
174 iBufSave = iBuf;
175 do { /* cvt to binary */
176 wchar = (CHAR) (wchar * 10 + (pszBuf[iBuf++] - 48));
177 } while (index(DEC, pszBuf[iBuf]) != -1 && iBuf < iBufSave + 3);
178 iBuf--;
179 }
180 else
181 wchar = pszBuf[iBuf];
182 *pszOut++ = wchar;
183 break;
184 } // switch
185 break;
186
187 default:
188 *pszOut++ = pszBuf[iBuf];
189 break;
190 } // switch
191 iBuf++;
192 } // while
193 *pszOut = 0; /* Always terminate, even if not string */
194
195 cBufBytes = pszOut - pszWork; /* Calc string length excluding terminator */
196 memcpy(pszBuf, pszWork, cBufBytes + 1); /* Overwrite including terminator */
197 free(pszWork);
198
199 return cBufBytes; /* Return string length */
200}
201
202/** Check wildcard match
203 * @parm pszBuf Buffer to check
204 * @parm pszWildCard wildcard to match
205 * @parm fNotFileSpec TRUE if generic match else filespec match
206 * @return TRUE if matched else FALSE
207 */
208
209BOOL wildcard(const PSZ pszBuf, const PSZ pszWildCard,
210 const BOOL fNotFileSpec)
211{
212 PSZ fstr = pszBuf;
213 PSZ fcard = pszWildCard;
214
215 while (*fstr && *fcard) {
216 switch (*fcard) {
217 case '*' :
218 {
219 PSZ fstr1;
220
221 // find next non-wild character in wildcard
222 while (*fcard && ( *fcard == '*' || *fcard == '?'))
223 fcard++;
224
225 // if last char of wildcard is *, it matches
226 if (!*fcard)
227 return TRUE;
228
229 fstr1 = fstr;
230 while (*fstr1) {
231 // skip until partition, match, or eos
232 while (*fstr1 && toupper( *fstr1 ) != toupper( *fcard ) &&
233 (fNotFileSpec || ( *fstr1 != '/' && *fstr1 != '\\')))
234 fstr1++;
235
236 if (!*fstr1 || ( !fNotFileSpec && ( *fstr1 == '/' || *fstr1 == '\\')))
237 break;
238
239 if (wildcard( fstr1, fcard, fNotFileSpec ) == TRUE)
240 return TRUE;
241
242 fstr1++;
243 }
244
245 fstr = fstr1;
246 break;
247 }
248
249 case '?' : // character substitution
250 fcard++;
251
252 if (fNotFileSpec || ( *fstr != '.' && *fstr != '/' && *fstr != '\\'))
253 fstr++; // skip (match) next character
254 break;
255
256 default :
257 if (fNotFileSpec || (*fstr != '/' && *fstr != '\\') ||
258 (*fcard != '/' && *fcard != '\\')) {
259 if (toupper( *fstr ) != toupper( *fcard))
260 return FALSE;
261 }
262
263 fcard++;
264 fstr++;
265 break;
266 }
267 }
268
269 if (!*fstr) {
270 // remove trailing * and ?
271 while (*fcard && ( *fcard == '?' || *fcard == '*'))
272 fcard++;
273
274 if (!fNotFileSpec) {
275 // remove trailing .
276 while (*fcard && *fcard == '.')
277 fcard++;
278 }
279 }
280
281 return (*fstr == *fcard);
282}
283
284// fixup - quote literal character array
285
286PSZ fixup(const PCH pachIn, PSZ pszOutBuf, const UINT cBufBytes,
287 const UINT cInBytes)
288{
289 PCH pchIn = pachIn;
290 PCH pchOut = pszOutBuf;
291
292 // input is a character array, not a string - may not be null terminated
293 // cBufBytes is buffer size
294 if (pachIn) {
295 // 16 Nov 07 SHL fixme to optimize counting and speed
296 // Ensure room for null and possible \ escape
297 while (pchIn - pachIn < cInBytes) {
298 if (pchOut - pszOutBuf + 4 >= cBufBytes) {
299 *pchOut = 0;
300 Runtime_Error(pszSrcFile, __LINE__, "buffer too small for %s", pszOutBuf);
301 break;
302 }
303
304 if (!isprint(*pchIn)) {
305 if (*pchIn == '\r') {
306 *pchOut++ = '\\';
307 *pchOut++ = 'r';
308 }
309 else if (*pchIn == '\n') {
310 *pchOut++ = '\\';
311 *pchOut++ = 'n';
312 }
313 else if (*pchIn == '\b') {
314 *pchOut++ = '\\';
315 *pchOut++ = 'b';
316 }
317 else {
318 sprintf(pchOut, "\\x%02x", (UCHAR)*pchIn);
319 pchOut += 4;
320 }
321 pchIn++;
322 }
323 else if (*pchIn == '\\') {
324 *pchOut++ = '\\';
325 *pchOut++ = '\\';
326 pchIn++;
327 }
328 else
329 *pchOut++ = *pchIn++;
330 } // while
331
332 } // if pachIn
333 *pchOut = 0;
334 return pszOutBuf;
335}
336
337#pragma alloc_text(LITERAL,literal,index,fixup,wildcard)
338
Note: See TracBrowser for help on using the repository browser.