source: trunk/dll/literal.c@ 834

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

Improved file filtering logic to match last extention for file associations (types) (reverse character by character matching) and optionally search for complete strings within a file name (strstr matching).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.0 KB
Line 
1
2/***********************************************************************
3
4 $Id: literal.c 834 2007-09-12 19:20:07Z gyoung $
5
6 string quoting utilities
7 wildcarding utilities
8
9 Copyright (c) 1993-98 M. Kimes
10 Copyright (c) 2004, 2006 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
19***********************************************************************/
20
21#define INCL_OS2
22#define INCL_WIN
23#include <os2.h>
24
25#include <ctype.h>
26#include <stdlib.h>
27#include <stdio.h>
28#include <string.h>
29
30#include "fm3dll.h"
31
32static PSZ pszSrcFile = __FILE__;
33
34static INT index(const CHAR * s, const CHAR c);
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 */
41
42static INT index(const CHAR * s, const CHAR c)
43{
44 CHAR *p;
45
46 p = strchr(s, c);
47 if (p == NULL || !*p)
48 return -1;
49 return (INT) (p - s);
50}
51
52/* literal()
53 * Translate a string with \ escape tokens to binary equivalent
54 * Translates in place
55 *
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")
73 *
74 * Return converted character count like strlen()
75 * Count does not include terminating nul
76 */
77
78#define HEX "0123456789ABCDEF"
79#define DEC "0123456789"
80
81UINT literal(PSZ pszBuf)
82{
83 INT wpos;
84 INT iBuf;
85 UINT cBufBytes;
86 INT iBufSave;
87 PSZ pszOut;
88 PSZ pszWork;
89 CHAR wchar;
90
91 if (!pszBuf || !*pszBuf)
92 return 0;
93 cBufBytes = strlen(pszBuf) + 1;
94 pszWork = pszOut = xmalloc(cBufBytes + 1, pszSrcFile, __LINE__);
95
96 iBuf = 0; /* set index to first character */
97 while (pszBuf[iBuf]) {
98 switch (pszBuf[iBuf]) {
99 case '\\':
100 switch (pszBuf[iBuf + 1]) {
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;
117
118 case '\\': /* we want a "\" */
119 iBuf++;
120 *pszOut++ = '\\';
121 break;
122
123 case 't': /* tab CHAR */
124 iBuf++;
125 *pszOut++ = '\t';
126 break;
127
128 case 'n': /* new line */
129 iBuf++;
130 *pszOut++ = '\n';
131 break;
132
133 case 'r': /* carr return */
134 iBuf++;
135 *pszOut++ = '\r';
136 break;
137
138 case 'b': /* back space */
139 iBuf++;
140 *pszOut++ = '\b';
141 break;
142
143 case 'f': /* formfeed */
144 iBuf++;
145 *pszOut++ = '\x0c';
146 break;
147
148 case 'a': /* bell */
149 iBuf++;
150 *pszOut++ = '\07';
151 break;
152
153 case '\'': /* single quote */
154 iBuf++;
155 *pszOut++ = '\'';
156 break;
157
158 case '\"': /* double quote */
159
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
179 break;
180
181 default:
182 *pszOut++ = pszBuf[iBuf];
183 break;
184 } // switch
185 iBuf++;
186 } // while
187 *pszOut = 0; /* Always terminate, even if not string */
188
189 cBufBytes = pszOut - pszWork; /* Calc string length excluding terminator */
190 memcpy(pszBuf, pszWork, cBufBytes + 1); /* Overwrite including terminator */
191 free(pszWork);
192
193 return cBufBytes; /* Return string length */
194}
195
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 */
202
203BOOL wildcard(const PSZ pszBuf, const PSZ pszWildCard,
204 const BOOL fNotFileSpec)
205{
206 const CHAR *fstr = pszBuf;
207 PSZ fcard = pszWildCard;
208 CHAR *tcard;
209 INT wmatch = TRUE;
210 BOOL reverse = FALSE;
211
212 while (wmatch && *fcard && *fstr) {
213 if (*fcard == '*' && fcard[strlen(fcard) - 1] == '*' && !reverse){
214 tcard = xstrdup(fcard + 1, __FILE__, __LINE__);
215 tcard[strlen(tcard) - 1] = 0;
216 if (!(strchr(tcard, '?')) && !(strchr(tcard, '*'))){
217 if (strstr(fstr, tcard)){ //strstr match for *stuff* pattern no wildcards in "stuff"
218 xfree(tcard);
219 return TRUE;
220 }
221 else{
222 xfree(tcard);
223 return FALSE;
224 }
225 }
226 xfree(tcard);
227 }
228 else //reverse search for *stuff pattern "stuff" can contain wildcards
229 if (*fcard == '*' && fcard[strlen(fcard) - 1] != '*'){
230 fstr = strrev(pszBuf);
231 fcard = strrev(pszWildCard);
232 reverse = TRUE;
233 }
234 switch (*fcard) { //fm2 standard forward search for all other cases
235 case '?': /* character substitution */
236 fcard++;
237 if (fNotFileSpec || (*fstr != '.' && *fstr != '/' && *fstr != '\\'))
238 fstr++; /* skip (match) next character */
239 break;
240
241 case '*':
242 /* find next non-wild character in wildcard */
243 while (*fcard && (*fcard == '?' || *fcard == '*'))
244 fcard++;
245 if (!*fcard){ /* if last char of wildcard is *, it matches */
246 if (reverse){
247 fstr = strrev(pszBuf);
248 fcard = strrev(pszWildCard);
249 }
250 return TRUE;
251 }
252 /* skip until partition, match, or eos */
253 while (*fstr && toupper(*fstr) != toupper(*fcard) &&
254 (fNotFileSpec || (*fstr != '\\' &&
255 *fstr != '/' && *fstr != '.')))
256 fstr++;
257 if (!fNotFileSpec && !*fstr) /* implicit '.' */
258 if (*fcard == '.')
259 fcard++;
260 break;
261
262 default:
263 if (!fNotFileSpec && ((*fstr == '/' || *fstr == '\\') &&
264 (*fcard == '/' || *fcard == '\\')))
265 wmatch = TRUE;
266 else
267 wmatch = (toupper(*fstr) == toupper(*fcard));
268 fstr++;
269 fcard++;
270 break;
271 }
272 } //while
273
274 if ((*fcard && *fcard != '*') || *fstr){
275 if (reverse){
276 fstr = strrev(pszBuf);
277 fcard = strrev(pszWildCard);
278 }
279 return 0;
280 }
281 else {
282 if (reverse){
283 fstr = strrev(pszBuf);
284 fcard = strrev(pszWildCard);
285 }
286 return wmatch;
287 }
288}
289
290
291// fixup - quote literal character array
292
293PSZ fixup(const PCH pachIn, PSZ pszOutBuf, const UINT cBufBytes,
294 const UINT cInBytes)
295{
296 PCH pchIn = pachIn;
297 PCH pchOut = pszOutBuf;
298 PSZ pszTemp;
299 static CHAR szTemp[5] = "\\x"; // Constant prefix
300
301 // input is a character array, not a string - may not be null terminated
302 // cBufBytes is buffer size
303 if (pachIn) {
304 // Ensure room for null and possible \ escape
305 while (pchIn - pachIn < cInBytes && pchOut - pszOutBuf + 2 < cBufBytes) {
306 if (!isprint(*pchIn)) {
307 if (*pchIn == '\r') {
308 *pchOut++ = '\\';
309 *pchOut++ = 'r';
310 }
311 else if (*pchIn == '\n') {
312 *pchOut++ = '\\';
313 *pchOut++ = 'n';
314 }
315 else if (*pchIn == '\b') {
316 *pchOut++ = '\\';
317 *pchOut++ = 'b';
318 }
319 else {
320 sprintf(szTemp + 2, "%02x", (UCHAR)*pchIn);
321 for (pszTemp = szTemp; *pszTemp;)
322 *pchOut++ = *pszTemp++;
323 }
324 pchIn++;
325 }
326 else if (*pchIn == '\\') {
327 *pchOut++ = '\\';
328 *pchOut++ = '\\';
329 pchIn++;
330 }
331 else
332 *pchOut++ = *pchIn++;
333 } // while
334 } // if pachIn
335 *pchOut = 0;
336 return pszOutBuf;
337}
338
339#pragma alloc_text(LITERAL,literal,index,fixup,wildcard)
340
Note: See TracBrowser for help on using the repository browser.