source: trunk/dll/literal.c@ 871

Last change on this file since 871 was 871, checked in by Steven Levine, 18 years ago

Correct hex edit buffer sizing to avoid data loss
Detect and report overflows in fixup()

  • 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 871 2007-11-17 01:13:23Z stevenhl $
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#define INCL_OS2
23#define INCL_WIN
24#include <os2.h>
25
26#include <ctype.h>
27#include <stdlib.h>
28#include <stdio.h>
29#include <string.h>
30
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
97 iBuf = 0; /* set index to first character */
98 while (pszBuf[iBuf]) {
99 switch (pszBuf[iBuf]) {
100 case '\\':
101 switch (pszBuf[iBuf + 1]) {
102 case 'x': /* hexadecimal */
103 wchar = 0;
104 iBuf += 2; /* get past "\x" */
105 if (index(HEX, (CHAR) toupper(pszBuf[iBuf])) != -1) {
106 iBufSave = iBuf;
107 while (((wpos = index(HEX, (CHAR) toupper(pszBuf[iBuf]))) != -1) &&
108 iBuf < iBufSave + 2) {
109 wchar = (CHAR) (wchar << 4) + (CHAR) wpos;
110 iBuf++;
111 }
112 }
113 else
114 wchar = 'x'; /* just an x */
115 iBuf--;
116 *pszOut++ = wchar;
117 break;
118
119 case '\\': /* we want a "\" */
120 iBuf++;
121 *pszOut++ = '\\';
122 break;
123
124 case 't': /* tab CHAR */
125 iBuf++;
126 *pszOut++ = '\t';
127 break;
128
129 case 'n': /* new line */
130 iBuf++;
131 *pszOut++ = '\n';
132 break;
133
134 case 'r': /* carr return */
135 iBuf++;
136 *pszOut++ = '\r';
137 break;
138
139 case 'b': /* back space */
140 iBuf++;
141 *pszOut++ = '\b';
142 break;
143
144 case 'f': /* formfeed */
145 iBuf++;
146 *pszOut++ = '\x0c';
147 break;
148
149 case 'a': /* bell */
150 iBuf++;
151 *pszOut++ = '\07';
152 break;
153
154 case '\'': /* single quote */
155 iBuf++;
156 *pszOut++ = '\'';
157 break;
158
159 case '\"': /* double quote */
160
161 iBuf++;
162 *pszOut++ = '\"';
163 break;
164
165 default: /* decimal */
166 iBuf++; /* get past "\" */
167 wchar = 0;
168 if (index(DEC, pszBuf[iBuf]) != -1) {
169 iBufSave = iBuf;
170 do { /* cvt to binary */
171 wchar = (CHAR) (wchar * 10 + (pszBuf[iBuf++] - 48));
172 } while (index(DEC, pszBuf[iBuf]) != -1 && iBuf < iBufSave + 3);
173 iBuf--;
174 }
175 else
176 wchar = pszBuf[iBuf];
177 *pszOut++ = wchar;
178 break;
179 } // switch
180 break;
181
182 default:
183 *pszOut++ = pszBuf[iBuf];
184 break;
185 } // switch
186 iBuf++;
187 } // while
188 *pszOut = 0; /* Always terminate, even if not string */
189
190 cBufBytes = pszOut - pszWork; /* Calc string length excluding terminator */
191 memcpy(pszBuf, pszWork, cBufBytes + 1); /* Overwrite including terminator */
192 free(pszWork);
193
194 return cBufBytes; /* Return string length */
195}
196
197/* Check wildcard match
198 * @parm pszBuf Buffer to check
199 * @parm pszWildCard wildcard to match
200 * @parm fNotFileSpec TRUE if generic match else filespec match
201 * @return TRUE if matched else FALSE
202 */
203
204BOOL wildcard(const PSZ pszBuf, const PSZ pszWildCard,
205 const BOOL fNotFileSpec)
206{
207 const CHAR *fstr = pszBuf;
208 PSZ fcard = pszWildCard;
209 CHAR *tcard;
210 INT wmatch = TRUE;
211 BOOL reverse = FALSE;
212
213 while (wmatch && *fcard && *fstr) {
214 if (*fcard == '*' && fcard[strlen(fcard) - 1] == '*' && !reverse){
215 tcard = xstrdup(fcard + 1, __FILE__, __LINE__);
216 tcard[strlen(tcard) - 1] = 0;
217 if (!(strchr(tcard, '?')) && !(strchr(tcard, '*'))){
218 if (strstr(fstr, tcard)){ //strstr match for *stuff* pattern no wildcards in "stuff"
219 xfree(tcard);
220 return TRUE;
221 }
222 else{
223 xfree(tcard);
224 return FALSE;
225 }
226 }
227 xfree(tcard);
228 }
229 else //reverse search for *stuff pattern "stuff" can contain wildcards
230 if (*fcard == '*' && fcard[strlen(fcard) - 1] != '*'){
231 fstr = strrev(pszBuf);
232 fcard = strrev(pszWildCard);
233 reverse = TRUE;
234 }
235 switch (*fcard) { //fm2 standard forward search for all other cases
236 case '?': /* character substitution */
237 fcard++;
238 if (fNotFileSpec || (*fstr != '.' && *fstr != '/' && *fstr != '\\'))
239 fstr++; /* skip (match) next character */
240 break;
241
242 case '*':
243 /* find next non-wild character in wildcard */
244 while (*fcard && (*fcard == '?' || *fcard == '*'))
245 fcard++;
246 if (!*fcard){ /* if last char of wildcard is *, it matches */
247 if (reverse){
248 fstr = strrev(pszBuf);
249 fcard = strrev(pszWildCard);
250 }
251 return TRUE;
252 }
253 /* skip until partition, match, or eos */
254 while (*fstr && toupper(*fstr) != toupper(*fcard) &&
255 (fNotFileSpec || (*fstr != '\\' &&
256 *fstr != '/' && *fstr != '.')))
257 fstr++;
258 if (!fNotFileSpec && !*fstr) /* implicit '.' */
259 if (*fcard == '.')
260 fcard++;
261 break;
262
263 default:
264 if (!fNotFileSpec && ((*fstr == '/' || *fstr == '\\') &&
265 (*fcard == '/' || *fcard == '\\')))
266 wmatch = TRUE;
267 else
268 wmatch = (toupper(*fstr) == toupper(*fcard));
269 fstr++;
270 fcard++;
271 break;
272 }
273 } //while
274
275 if ((*fcard && *fcard != '*') || *fstr){
276 if (reverse){
277 fstr = strrev(pszBuf);
278 fcard = strrev(pszWildCard);
279 }
280 return 0;
281 }
282 else {
283 if (reverse){
284 fstr = strrev(pszBuf);
285 fcard = strrev(pszWildCard);
286 }
287 return wmatch;
288 }
289}
290
291
292// fixup - quote literal character array
293
294PSZ fixup(const PCH pachIn, PSZ pszOutBuf, const UINT cBufBytes,
295 const UINT cInBytes)
296{
297 PCH pchIn = pachIn;
298 PCH pchOut = pszOutBuf;
299
300 // input is a character array, not a string - may not be null terminated
301 // cBufBytes is buffer size
302 if (pachIn) {
303 // 16 Nov 07 SHL fixme to optimize counting and speed
304 // Ensure room for null and possible \ escape
305 while (pchIn - pachIn < cInBytes) {
306 if (pchOut - pszOutBuf + 4 >= cBufBytes) {
307 *pchOut = 0;
308 Runtime_Error(pszSrcFile, __LINE__, "buffer too small for %s", pszOutBuf);
309 break;
310 }
311
312 if (!isprint(*pchIn)) {
313 if (*pchIn == '\r') {
314 *pchOut++ = '\\';
315 *pchOut++ = 'r';
316 }
317 else if (*pchIn == '\n') {
318 *pchOut++ = '\\';
319 *pchOut++ = 'n';
320 }
321 else if (*pchIn == '\b') {
322 *pchOut++ = '\\';
323 *pchOut++ = 'b';
324 }
325 else {
326 sprintf(pchOut, "\\x%02x", (UCHAR)*pchIn);
327 pchOut += 4;
328 }
329 pchIn++;
330 }
331 else if (*pchIn == '\\') {
332 *pchOut++ = '\\';
333 *pchOut++ = '\\';
334 pchIn++;
335 }
336 else
337 *pchOut++ = *pchIn++;
338 } // while
339
340 } // if pachIn
341 *pchOut = 0;
342 return pszOutBuf;
343}
344
345#pragma alloc_text(LITERAL,literal,index,fixup,wildcard)
346
Note: See TracBrowser for help on using the repository browser.