source: trunk/dll/literal.c@ 985

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

Update sizes dialog (ticket 44); Make max command line length user settable (ticket 199); use xfree for free in most cases (ticket 212); initial code to check for valid ini file (ticket 102); Some additional refactoring and structure rework; Some documentation updates;

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