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
RevLine 
[117]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
[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{
[834]206 const CHAR *fstr = pszBuf;
207 PSZ fcard = pszWildCard;
208 CHAR *tcard;
209 INT wmatch = TRUE;
210 BOOL reverse = FALSE;
[832]211
[551]212 while (wmatch && *fcard && *fstr) {
[834]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] != '*'){
[832]230 fstr = strrev(pszBuf);
231 fcard = strrev(pszWildCard);
[834]232 reverse = TRUE;
[832]233 }
[834]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 == '*'))
[757]244 fcard++;
[834]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;
[2]261
[834]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);
[2]278 }
[832]279 return 0;
280 }
[834]281 else {
282 if (reverse){
283 fstr = strrev(pszBuf);
284 fcard = strrev(pszWildCard);
285 }
[832]286 return wmatch;
287 }
288}
[2]289
[832]290
[117]291// fixup - quote literal character array
[2]292
[551]293PSZ fixup(const PCH pachIn, PSZ pszOutBuf, const UINT cBufBytes,
[757]294 const UINT cInBytes)
[117]295{
[551]296 PCH pchIn = pachIn;
297 PCH pchOut = pszOutBuf;
298 PSZ pszTemp;
[757]299 static CHAR szTemp[5] = "\\x"; // Constant prefix
[2]300
[117]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
[551]305 while (pchIn - pachIn < cInBytes && pchOut - pszOutBuf + 2 < cBufBytes) {
306 if (!isprint(*pchIn)) {
[757]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 {
[759]320 sprintf(szTemp + 2, "%02x", (UCHAR)*pchIn);
[757]321 for (pszTemp = szTemp; *pszTemp;)
322 *pchOut++ = *pszTemp++;
323 }
324 pchIn++;
[2]325 }
[551]326 else if (*pchIn == '\\') {
[757]327 *pchOut++ = '\\';
328 *pchOut++ = '\\';
329 pchIn++;
[2]330 }
[117]331 else
[757]332 *pchOut++ = *pchIn++;
333 } // while
334 } // if pachIn
[117]335 *pchOut = 0;
336 return pszOutBuf;
[2]337}
[795]338
[834]339#pragma alloc_text(LITERAL,literal,index,fixup,wildcard)
[795]340
Note: See TracBrowser for help on using the repository browser.