source: trunk/dll/literal.c@ 1039

Last change on this file since 1039 was 1039, checked in by Gregg Young, 17 years ago

Removed unnecessary xfrees and included fortify.h where needed; moved several misplaced (x)frees;

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