source: trunk/dll/literal.c@ 1570

Last change on this file since 1570 was 1438, checked in by Gregg Young, 16 years ago

Improved drivebar changes; Added AddBackslashToPath() to remove repeatative code. replaced "
" with PCSZ variable; ANY_OBJ added the DosAlloc... (experimental)

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