source: trunk/dll/literal.c@ 1036

Last change on this file since 1036 was 1009, checked in by Steven Levine, 17 years ago

Add xfree xstrdup Fortify support
Add MT capable Fortify scope logic

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.3 KB
Line 
1
2/***********************************************************************
3
4 $Id: literal.c 1009 2008-05-10 07:51:58Z stevenhl $
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
35static PSZ pszSrcFile = __FILE__;
36
37static INT index(const CHAR * s, const CHAR c);
38
39/* Get index of char in string
40 * @parm s string to search
41 * @parm c char to search for
42 * @return 0 relative index of c in s or -1
43 */
44
45static INT index(const CHAR * s, const CHAR c)
46{
47 CHAR *p;
48
49 p = strchr(s, c);
50 if (p == NULL || !*p)
51 return -1;
52 return (INT) (p - s);
53}
54
55/* literal()
56 * Translate a string with \ escape tokens to binary equivalent
57 * Translates in place
58 *
59 * 1. \x1b translates to CHAR(0x1b)
60 * 2. \27 translates to CHAR(27)
61 * 3. \" translates to "
62 * 4. \' translates to '
63 * 5. \\ translates to \
64 * 6. \r translates to carriage return
65 * 7. \n translates to linefeed
66 * 8. \b translates to backspace
67 * 9. \t translates to tab
68 * 10. \a translates to bell
69 * 11. \f translates to formfeed
70 *
71 * Synopsis
72 * *s = "this\x20is\32a test of \\MSC\\CSM\7"
73 * literal(s);
74 *
75 * ( s now equals "this is a test of \MSC\CSM")
76 *
77 * Return converted character count like strlen()
78 * Count does not include terminating nul
79 */
80
81#define HEX "0123456789ABCDEF"
82#define DEC "0123456789"
83
84UINT literal(PSZ pszBuf)
85{
86 INT wpos;
87 INT iBuf;
88 UINT cBufBytes;
89 INT iBufSave;
90 PSZ pszOut;
91 PSZ pszWork;
92 CHAR wchar;
93
94 if (!pszBuf || !*pszBuf)
95 return 0;
96 cBufBytes = strlen(pszBuf) + 1;
97 pszWork = pszOut = xmalloc(cBufBytes + 1, pszSrcFile, __LINE__);
98 if (!pszWork)
99 return 0;
100
101 iBuf = 0; /* set index to first character */
102 while (pszBuf[iBuf]) {
103 switch (pszBuf[iBuf]) {
104 case '\\':
105 switch (pszBuf[iBuf + 1]) {
106 case 'x': /* hexadecimal */
107 wchar = 0;
108 iBuf += 2; /* get past "\x" */
109 if (index(HEX, (CHAR) toupper(pszBuf[iBuf])) != -1) {
110 iBufSave = iBuf;
111 while (((wpos = index(HEX, (CHAR) toupper(pszBuf[iBuf]))) != -1) &&
112 iBuf < iBufSave + 2) {
113 wchar = (CHAR) (wchar << 4) + (CHAR) wpos;
114 iBuf++;
115 }
116 }
117 else
118 wchar = 'x'; /* just an x */
119 iBuf--;
120 *pszOut++ = wchar;
121 break;
122
123 case '\\': /* we want a "\" */
124 iBuf++;
125 *pszOut++ = '\\';
126 break;
127
128 case 't': /* tab CHAR */
129 iBuf++;
130 *pszOut++ = '\t';
131 break;
132
133 case 'n': /* new line */
134 iBuf++;
135 *pszOut++ = '\n';
136 break;
137
138 case 'r': /* carr return */
139 iBuf++;
140 *pszOut++ = '\r';
141 break;
142
143 case 'b': /* back space */
144 iBuf++;
145 *pszOut++ = '\b';
146 break;
147
148 case 'f': /* formfeed */
149 iBuf++;
150 *pszOut++ = '\x0c';
151 break;
152
153 case 'a': /* bell */
154 iBuf++;
155 *pszOut++ = '\07';
156 break;
157
158 case '\'': /* single quote */
159 iBuf++;
160 *pszOut++ = '\'';
161 break;
162
163 case '\"': /* double quote */
164
165 iBuf++;
166 *pszOut++ = '\"';
167 break;
168
169 default: /* decimal */
170 iBuf++; /* get past "\" */
171 wchar = 0;
172 if (index(DEC, pszBuf[iBuf]) != -1) {
173 iBufSave = iBuf;
174 do { /* cvt to binary */
175 wchar = (CHAR) (wchar * 10 + (pszBuf[iBuf++] - 48));
176 } while (index(DEC, pszBuf[iBuf]) != -1 && iBuf < iBufSave + 3);
177 iBuf--;
178 }
179 else
180 wchar = pszBuf[iBuf];
181 *pszOut++ = wchar;
182 break;
183 } // switch
184 break;
185
186 default:
187 *pszOut++ = pszBuf[iBuf];
188 break;
189 } // switch
190 iBuf++;
191 } // while
192 *pszOut = 0; /* Always terminate, even if not string */
193
194 cBufBytes = pszOut - pszWork; /* Calc string length excluding terminator */
195 memcpy(pszBuf, pszWork, cBufBytes + 1); /* Overwrite including terminator */
196 xfree(pszWork, pszSrcFile, __LINE__);
197
198 return cBufBytes; /* Return string length */
199}
200
201/** Check wildcard match
202 * @parm pszBuf Buffer to check
203 * @parm pszWildCard wildcard to match
204 * @parm fNotFileSpec TRUE if generic match else filespec match
205 * @return TRUE if matched else FALSE
206 */
207
208BOOL wildcard(const PSZ pszBuf, const PSZ pszWildCard,
209 const BOOL fNotFileSpec)
210{
211 PSZ fstr = pszBuf;
212 PSZ fcard = pszWildCard;
213
214 while (*fstr && *fcard) {
215 switch (*fcard) {
216 case '*' :
217 {
218 PSZ fstr1;
219
220 // find next non-wild character in wildcard
221 while (*fcard && ( *fcard == '*' || *fcard == '?'))
222 fcard++;
223
224 // if last char of wildcard is *, it matches
225 if (!*fcard)
226 return TRUE;
227
228 fstr1 = fstr;
229 while (*fstr1) {
230 // skip until partition, match, or eos
231 while (*fstr1 && toupper( *fstr1 ) != toupper( *fcard ) &&
232 (fNotFileSpec || ( *fstr1 != '/' && *fstr1 != '\\')))
233 fstr1++;
234
235 if (!*fstr1 || ( !fNotFileSpec && ( *fstr1 == '/' || *fstr1 == '\\')))
236 break;
237
238 if (wildcard( fstr1, fcard, fNotFileSpec ) == TRUE)
239 return TRUE;
240
241 fstr1++;
242 }
243
244 fstr = fstr1;
245 break;
246 }
247
248 case '?' : // character substitution
249 fcard++;
250
251 if (fNotFileSpec || ( *fstr != '.' && *fstr != '/' && *fstr != '\\'))
252 fstr++; // skip (match) next character
253 break;
254
255 default :
256 if (fNotFileSpec || (*fstr != '/' && *fstr != '\\') ||
257 (*fcard != '/' && *fcard != '\\')) {
258 if (toupper( *fstr ) != toupper( *fcard))
259 return FALSE;
260 }
261
262 fcard++;
263 fstr++;
264 break;
265 }
266 }
267
268 if (!*fstr) {
269 // remove trailing * and ?
270 while (*fcard && ( *fcard == '?' || *fcard == '*'))
271 fcard++;
272
273 if (!fNotFileSpec) {
274 // remove trailing .
275 while (*fcard && *fcard == '.')
276 fcard++;
277 }
278 }
279
280 return (*fstr == *fcard);
281}
282
283
284/*BOOL wildcard(const PSZ pszBuf, const PSZ pszWildCard,
285 const BOOL fNotFileSpec)
286{
287 const CHAR *fstr = pszBuf;
288 PSZ fcard = pszWildCard;
289 CHAR *tcard;
290 INT wmatch = TRUE;
291 BOOL reverse = FALSE;
292
293 while (wmatch && *fcard && *fstr) {
294 if (*fcard == '*' && fcard[strlen(fcard) - 1] == '*' && !reverse){
295 tcard = xstrdup(fcard + 1, __FILE__, __LINE__);
296 tcard[strlen(tcard) - 1] = 0;
297 if (!(strchr(tcard, '?')) && !(strchr(tcard, '*'))){
298 if (strstr(fstr, tcard)){ //strstr match for *stuff* pattern no wildcards in "stuff"
299 xfree(tcard, pszSrcFile, __LINE__);
300 return TRUE;
301 }
302 else{
303 xfree(tcard, pszSrcFile, __LINE__);
304 return FALSE;
305 }
306 }
307 xfree(tcard, pszSrcFile, __LINE__);
308 }
309 else //reverse search for *stuff pattern "stuff" can contain wildcards
310 if (*fcard == '*' && fcard[strlen(fcard) - 1] != '*'){
311 fstr = strrev(pszBuf);
312 fcard = strrev(pszWildCard);
313 reverse = TRUE;
314 }
315 switch (*fcard) { //fm2 standard forward search for all other cases
316 case '?': // character substitution /
317 fcard++;
318 if (fNotFileSpec || (*fstr != '.' && *fstr != '/' && *fstr != '\\'))
319 fstr++; // skip (match) next character
320 break;
321
322 case '*':
323 // find next non-wild character in wildcard
324 while (*fcard && (*fcard == '?' || *fcard == '*'))
325 fcard++;
326 if (!*fcard){ // if last char of wildcard is *, it matches
327 if (reverse){
328 fstr = strrev(pszBuf);
329 fcard = strrev(pszWildCard);
330 }
331 return TRUE;
332 }
333 // skip until partition, match, or eos
334 while (*fstr && toupper(*fstr) != toupper(*fcard) &&
335 (fNotFileSpec || (*fstr != '\\' &&
336 *fstr != '/' && *fstr != '.')))
337 fstr++;
338 if (!fNotFileSpec && !*fstr) // implicit '.'
339 if (*fcard == '.')
340 fcard++;
341 break;
342
343 default:
344 if (!fNotFileSpec && ((*fstr == '/' || *fstr == '\\') &&
345 (*fcard == '/' || *fcard == '\\')))
346 wmatch = TRUE;
347 else
348 wmatch = (toupper(*fstr) == toupper(*fcard));
349 fstr++;
350 fcard++;
351 break;
352 }
353 } //while
354
355 if ((*fcard && *fcard != '*') || *fstr){
356 if (reverse){
357 fstr = strrev(pszBuf);
358 fcard = strrev(pszWildCard);
359 }
360 return 0;
361 }
362 else {
363 if (reverse){
364 fstr = strrev(pszBuf);
365 fcard = strrev(pszWildCard);
366 }
367 return wmatch;
368 }
369} */
370
371
372// fixup - quote literal character array
373
374PSZ fixup(const PCH pachIn, PSZ pszOutBuf, const UINT cBufBytes,
375 const UINT cInBytes)
376{
377 PCH pchIn = pachIn;
378 PCH pchOut = pszOutBuf;
379
380 // input is a character array, not a string - may not be null terminated
381 // cBufBytes is buffer size
382 if (pachIn) {
383 // 16 Nov 07 SHL fixme to optimize counting and speed
384 // Ensure room for null and possible \ escape
385 while (pchIn - pachIn < cInBytes) {
386 if (pchOut - pszOutBuf + 4 >= cBufBytes) {
387 *pchOut = 0;
388 Runtime_Error(pszSrcFile, __LINE__, "buffer too small for %s", pszOutBuf);
389 break;
390 }
391
392 if (!isprint(*pchIn)) {
393 if (*pchIn == '\r') {
394 *pchOut++ = '\\';
395 *pchOut++ = 'r';
396 }
397 else if (*pchIn == '\n') {
398 *pchOut++ = '\\';
399 *pchOut++ = 'n';
400 }
401 else if (*pchIn == '\b') {
402 *pchOut++ = '\\';
403 *pchOut++ = 'b';
404 }
405 else {
406 sprintf(pchOut, "\\x%02x", (UCHAR)*pchIn);
407 pchOut += 4;
408 }
409 pchIn++;
410 }
411 else if (*pchIn == '\\') {
412 *pchOut++ = '\\';
413 *pchOut++ = '\\';
414 pchIn++;
415 }
416 else
417 *pchOut++ = *pchIn++;
418 } // while
419
420 } // if pachIn
421 *pchOut = 0;
422 return pszOutBuf;
423}
424
425#pragma alloc_text(LITERAL,literal,index,fixup,wildcard)
426
Note: See TracBrowser for help on using the repository browser.