source: trunk/dll/literal.c@ 1047

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

Minor code cleanup

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