source: trunk/dll/literal.c@ 1416

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

The palettes and system clock now work from the config toolbar (Ticket 352); Steven's cleanup of wildcard code.

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