source: trunk/dll/literal.c@ 1438

Last change on this file since 1438 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
RevLine 
[117]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
[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
[1416]20 24 Apr 09 SHL Rework wildcard for clarity
[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
[1183]32#include "fm3dll.h"
[907]33#include "errutil.h" // Dos_Error...
[1160]34#include "literal.h"
[1183]35#include "wrappers.h" // xmalloc
[1039]36#include "fortify.h"
[1438]37#include "init.h" // Strings
[2]38
[351]39static PSZ pszSrcFile = __FILE__;
40
[551]41static INT index(const CHAR * s, const CHAR c);
[117]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 */
[2]48
[551]49static INT index(const CHAR * s, const CHAR c)
[117]50{
[551]51 CHAR *p;
[2]52
[551]53 p = strchr(s, c);
54 if (p == NULL || !*p)
55 return -1;
56 return (INT) (p - s);
[2]57}
58
[409]59/* literal()
60 * Translate a string with \ escape tokens to binary equivalent
[117]61 * Translates in place
62 *
[2]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")
[298]80 *
[409]81 * Return converted character count like strlen()
82 * Count does not include terminating nul
[2]83 */
84
85#define HEX "0123456789ABCDEF"
86#define DEC "0123456789"
87
[117]88UINT literal(PSZ pszBuf)
89{
[551]90 INT wpos;
91 INT iBuf;
92 UINT cBufBytes;
93 INT iBufSave;
94 PSZ pszOut;
95 PSZ pszWork;
96 CHAR wchar;
[2]97
[551]98 if (!pszBuf || !*pszBuf)
[2]99 return 0;
[117]100 cBufBytes = strlen(pszBuf) + 1;
[551]101 pszWork = pszOut = xmalloc(cBufBytes + 1, pszSrcFile, __LINE__);
[959]102 if (!pszWork)
103 return 0;
[2]104
[757]105 iBuf = 0; /* set index to first character */
[551]106 while (pszBuf[iBuf]) {
107 switch (pszBuf[iBuf]) {
108 case '\\':
109 switch (pszBuf[iBuf + 1]) {
[757]110 case 'x': /* hexadecimal */
[871]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;
[2]126
[757]127 case '\\': /* we want a "\" */
[871]128 iBuf++;
129 *pszOut++ = '\\';
130 break;
[2]131
[757]132 case 't': /* tab CHAR */
[871]133 iBuf++;
134 *pszOut++ = '\t';
135 break;
[2]136
[757]137 case 'n': /* new line */
[871]138 iBuf++;
139 *pszOut++ = '\n';
140 break;
[2]141
[757]142 case 'r': /* carr return */
[871]143 iBuf++;
144 *pszOut++ = '\r';
145 break;
[2]146
[757]147 case 'b': /* back space */
[871]148 iBuf++;
149 *pszOut++ = '\b';
150 break;
[2]151
[757]152 case 'f': /* formfeed */
[871]153 iBuf++;
154 *pszOut++ = '\x0c';
155 break;
[2]156
[757]157 case 'a': /* bell */
[871]158 iBuf++;
159 *pszOut++ = '\07';
160 break;
[2]161
[757]162 case '\'': /* single quote */
[871]163 iBuf++;
164 *pszOut++ = '\'';
165 break;
[2]166
[757]167 case '\"': /* double quote */
[2]168
[871]169 iBuf++;
170 *pszOut++ = '\"';
171 break;
[757]172
173 default: /* decimal */
[871]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;
[757]187 } // switch
[551]188 break;
189
190 default:
191 *pszOut++ = pszBuf[iBuf];
192 break;
[757]193 } // switch
[551]194 iBuf++;
[757]195 } // while
196 *pszOut = 0; /* Always terminate, even if not string */
[2]197
[757]198 cBufBytes = pszOut - pszWork; /* Calc string length excluding terminator */
199 memcpy(pszBuf, pszWork, cBufBytes + 1); /* Overwrite including terminator */
[1039]200 free(pszWork);
[2]201
[757]202 return cBufBytes; /* Return string length */
[2]203}
204
[999]205/** Check wildcard match
[117]206 * @parm pszBuf Buffer to check
207 * @parm pszWildCard wildcard to match
[1416]208 * @parm fIgnorePathSep TRUE if match ignores path separators
[117]209 * @return TRUE if matched else FALSE
[1416]210 * @fixme need to rework to scan from right to left if not ignoring path separators
[117]211 */
[2]212
[1416]213BOOL wildcard(const PSZ pszBufIn, const PSZ pszWildCardIn,
214 const BOOL fIgnorePathSep)
[999]215{
[1416]216 PSZ pszBuf = pszBufIn;
217 PSZ pszWild = pszWildCardIn;
[999]218
[1416]219 while (*pszBuf && *pszWild) {
220 switch (*pszWild) {
[999]221 case '*' :
222 {
[1416]223 PSZ pszLook;
[999]224
225 // find next non-wild character in wildcard
[1416]226 while (*pszWild && ( *pszWild == '*' || *pszWild == '?'))
227 pszWild++;
[999]228
[1416]229 // if last char of wildcard is *, got match
230 if (!*pszWild)
[999]231 return TRUE;
232
[1416]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++;
[999]239
[1416]240 // If eos or path separator (maybe), stop scan
241 if (!*pszLook || (!fIgnorePathSep && (*pszLook == '/' || *pszLook == '\\')))
[999]242 break;
243
[1416]244 // Not ignoring path separators, match next path component
245 if (wildcard(pszLook, pszWild, fIgnorePathSep) == TRUE)
[999]246 return TRUE;
247
[1416]248 pszLook++;
249 } // while
[999]250
[1416]251 pszBuf = pszLook;
[999]252 break;
253 }
254
255 case '?' : // character substitution
[1416]256 pszWild++;
[999]257
[1416]258 if (fIgnorePathSep || (*pszBuf != '.' && *pszBuf != '/' && *pszBuf != '\\'))
259 pszBuf++; // skip (match) next character
[999]260 break;
261
262 default :
[1416]263 if (fIgnorePathSep || (*pszBuf != '/' && *pszBuf != '\\') ||
264 (*pszWild != '/' && *pszWild != '\\')) {
265 if (toupper( *pszBuf ) != toupper( *pszWild))
[999]266 return FALSE;
267 }
268
[1416]269 pszWild++;
270 pszBuf++;
[999]271 break;
[1416]272 } // switch
273 } // while
[999]274
[1416]275 if (!*pszBuf) {
276 // Skip trailing * and ?
277 while (*pszWild && (*pszWild == '?' || *pszWild == '*'))
278 pszWild++;
[999]279
[1416]280 if (!fIgnorePathSep) {
[999]281 // remove trailing .
[1416]282 while (*pszWild && *pszWild == '.')
283 pszWild++;
[999]284 }
285 }
286
[1416]287 return (*pszBuf == *pszWild);
[999]288}
289
[117]290// fixup - quote literal character array
[2]291
[551]292PSZ fixup(const PCH pachIn, PSZ pszOutBuf, const UINT cBufBytes,
[871]293 const UINT cInBytes)
[117]294{
[551]295 PCH pchIn = pachIn;
296 PCH pchOut = pszOutBuf;
[2]297
[117]298 // input is a character array, not a string - may not be null terminated
299 // cBufBytes is buffer size
300 if (pachIn) {
[871]301 // 16 Nov 07 SHL fixme to optimize counting and speed
[117]302 // Ensure room for null and possible \ escape
[871]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
[551]310 if (!isprint(*pchIn)) {
[871]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 {
[1438]324 sprintf(pchOut, "%sx%02x", PCSZ_BACKSLASH, (UCHAR)*pchIn);
[871]325 pchOut += 4;
326 }
327 pchIn++;
[2]328 }
[551]329 else if (*pchIn == '\\') {
[871]330 *pchOut++ = '\\';
331 *pchOut++ = '\\';
332 pchIn++;
[2]333 }
[117]334 else
[871]335 *pchOut++ = *pchIn++;
336 } // while
337
338 } // if pachIn
[117]339 *pchOut = 0;
340 return pszOutBuf;
[2]341}
[795]342
[834]343#pragma alloc_text(LITERAL,literal,index,fixup,wildcard)
[795]344
Note: See TracBrowser for help on using the repository browser.