source: trunk/dll/literal.c@ 757

Last change on this file since 757 was 757, checked in by John Small, 18 years ago
  • A bug was fixed which caused hex literals with the high bit set

to be sign extended.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.8 KB
Line 
1
2/***********************************************************************
3
4 $Id: literal.c 757 2007-08-04 02:08:40Z jbs $
5
6 string quoting utilities
7 wildcarding utilities
8
9 Copyright (c) 1993-98 M. Kimes
10 Copyright (c) 2004, 2006 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
18***********************************************************************/
19
20#define INCL_OS2
21#define INCL_WIN
22#include <os2.h>
23
24#include <ctype.h>
25#include <stdlib.h>
26#include <stdio.h>
27#include <string.h>
28
29#include "fm3dll.h"
30
31static PSZ pszSrcFile = __FILE__;
32
33static INT index(const CHAR * s, const CHAR c);
34
35#pragma alloc_text(LITERAL,literal,index,fixup,wildcard)
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 INT wmatch = TRUE;
210
211 while (wmatch && *fcard && *fstr) {
212 switch (*fcard) {
213 case '?': /* character substitution */
214 fcard++;
215 if (fNotFileSpec || (*fstr != '.' && *fstr != '/' && *fstr != '\\'))
216 fstr++; /* skip (match) next character */
217 break;
218
219 case '*':
220 /* find next non-wild character in wildcard */
221 while (*fcard && (*fcard == '?' || *fcard == '*'))
222 fcard++;
223 if (!*fcard) /* if last char of wildcard is *, it matches */
224 return TRUE;
225 /* skip until partition, match, or eos */
226 while (*fstr && toupper(*fstr) != toupper(*fcard) &&
227 (fNotFileSpec || (*fstr != '\\' &&
228 *fstr != '/' && *fstr != '.')))
229 fstr++;
230 if (!fNotFileSpec && !*fstr) /* implicit '.' */
231 if (*fcard == '.')
232 fcard++;
233 break;
234
235 default:
236 if (!fNotFileSpec && ((*fstr == '/' || *fstr == '\\') &&
237 (*fcard == '/' || *fcard == '\\')))
238 wmatch = TRUE;
239 else
240 wmatch = (toupper(*fstr) == toupper(*fcard));
241 fstr++;
242 fcard++;
243 break;
244 }
245 }
246
247 if ((*fcard && *fcard != '*') || *fstr)
248 return 0;
249 else
250 return wmatch;
251}
252
253// fixup - quote literal character array
254
255PSZ fixup(const PCH pachIn, PSZ pszOutBuf, const UINT cBufBytes,
256 const UINT cInBytes)
257{
258 PCH pchIn = pachIn;
259 PCH pchOut = pszOutBuf;
260 PSZ pszTemp;
261 static CHAR szTemp[5] = "\\x"; // Constant prefix
262
263 // input is a character array, not a string - may not be null terminated
264 // cBufBytes is buffer size
265 if (pachIn) {
266 // Ensure room for null and possible \ escape
267 while (pchIn - pachIn < cInBytes && pchOut - pszOutBuf + 2 < cBufBytes) {
268 if (!isprint(*pchIn)) {
269 if (*pchIn == '\r') {
270 *pchOut++ = '\\';
271 *pchOut++ = 'r';
272 }
273 else if (*pchIn == '\n') {
274 *pchOut++ = '\\';
275 *pchOut++ = 'n';
276 }
277 else if (*pchIn == '\b') {
278 *pchOut++ = '\\';
279 *pchOut++ = 'b';
280 }
281 else {
282 sprintf(szTemp + 2, "%02hhx", *pchIn);
283 for (pszTemp = szTemp; *pszTemp;)
284 *pchOut++ = *pszTemp++;
285 }
286 pchIn++;
287 }
288 else if (*pchIn == '\\') {
289 *pchOut++ = '\\';
290 *pchOut++ = '\\';
291 pchIn++;
292 }
293 else
294 *pchOut++ = *pchIn++;
295 } // while
296 } // if pachIn
297 *pchOut = 0;
298 return pszOutBuf;
299}
Note: See TracBrowser for help on using the repository browser.