source: trunk/dll/literal.c@ 832

Last change on this file since 832 was 832, checked in by Gregg Young, 18 years ago

Initial implimentation of a more flexible mask matching system to address multiple "." in file names

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