source: trunk/dll/literal.c@ 959

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

Use xfree where appropriate. Check that buffer exists following all xmallocs. Stopped at eas.c with xfree checking. One remaining xmalloc without test in dirsize.c

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