30 #define BOL '^' // start-of-line anchor
31 #define EOL '$' // end-of-line anchor
32 #define ANY '.' // matches any character
33 #define CCL '[' // start a character class
34 #define CCLEND ']' // end a character class
35 #define NCCL '^' // negates character class if 1st character
36 #define CLOSURE '*' // Kleene closure (matches 0 or more)
37 #define PCLOSE '+' // Positive closure (1 or more)
38 #define OPT '?' // Optional closure (0 or 1)
42 kBOL = (0x8000 |
'^'),
43 kEOL = (0x8000 |
'$'),
44 kANY = (0x8000 |
'.'),
45 kCCL = (0x8000 |
'['),
46 kOPT = (0x8000 |
'?'),
47 kCLOSE = (0x8000 |
'*'),
48 kPCLOSE = (0x8000 |
'+'),
54 #define ISHEXDIGIT(x) isxdigit((unsigned char)x)
56 #define ISHEXDIGIT(x) (isdigit(x) \
57 || ('a'<=(x) && (x)<='f') \
58 || ('A'<=(x) && (x)<='F') )
61 #define ISOCTDIGIT(x) ('0'<=(x) && (x)<='7')
64 #define MAPSIZE 16 // need this many Pattern_t elements for
72 inline void ADVANCE(
const Pattern_t*& pat)
74 if (*pat++ == (Pattern_t) kCCL)
85 #ifdef SETBIT // from Rtypes.h
89 static void SETBIT(
unsigned char b, Pattern_t* map)
91 map[b >> 4] |= 1 << (b & 0x0f);
96 static int TSTBIT(
unsigned char b,
const Pattern_t* map)
98 return map[b >> 4] & (1 << (b & 0x0f));
103 #define E_NONE 0 // Possible return values from pat_err
104 #define E_ILLEGAL 1 // Set in Makepat() to indicate prob-
105 #define E_NOMEM 2 // lems that came up while making the
106 #define E_PAT 3 // pattern template.
110 static const char* doccl(Pattern_t*,
const char*);
111 static int hex2bin(
int);
112 static int oct2bin(
int);
113 static int omatch(
const char**,
size_t*,
const Pattern_t*,
const char*);
114 static const char* patcmp(
const char*,
size_t,
const Pattern_t*,
const char*);
115 static int esc(
const char**);
129 int Makepat(
const char* exp,
135 int theError = E_ILLEGAL;
140 if (*exp == CLOSURE || *exp == PCLOSE || *exp == OPT)
151 if (cur >= &pat[maxpat - 1])
goto exit;
155 *cur = (Pattern_t)kANY;
161 *cur = (cur == pat) ? (Pattern_t)kBOL : (
unsigned char)*exp;
167 *cur = (!exp[1]) ? (Pattern_t)kEOL : (
unsigned char)*exp;
173 if (((cur - pat) + MAPSIZE) >= maxpat)
176 *cur++ = (Pattern_t)kCCL;
177 exp = doccl(cur, exp);
178 if (*exp != CCLEND)
goto exit;
195 memmove( prev+1, prev, (cur-prev)*
sizeof(*cur));
196 *prev = (Pattern_t) (*exp == OPT) ? kOPT :
197 (*exp == PCLOSE) ? kPCLOSE :
210 *cur = (Pattern_t)kEND;
220 const char *Matchs(
const char* str,
222 const Pattern_t* pat,
223 const char** startpat)
226 const char* endp = 0;
227 if (*pat == (Pattern_t)kBOL) {
229 endp = patcmp(str, slen, pat+1, str);
232 const char* start = str;
233 while ((endp = patcmp(str, slen, pat, start)) == 0 && slen != 0)
244 static const char *doccl(Pattern_t* map,
const char* src)
249 negative = (*src == NCCL);
252 memset(map, 0, MAPSIZE*
sizeof(*map));
254 while (*src && *src != CCLEND) {
255 int isCCL = (*src == CCL);
256 unsigned char first = esc(&src);
258 if (isCCL && *src && *src == CCLEND) {
262 if (*src ==
'-' && src[1] && src[1] != CCLEND) {
264 unsigned char last = esc(&src);
265 if (first <= last)
while (first < last ) SETBIT(++first, map);
266 else while (last < first) SETBIT(last++, map);
271 for (
int i = MAPSIZE; --i >= 0;)
287 static const char *patcmp(
const char* str,
289 const Pattern_t* pat,
295 while (*pat != (Pattern_t)kEND) {
296 if (*pat == (Pattern_t)kOPT) {
301 omatch(&str, &slen, ++pat, start);
304 }
else if (*pat != (Pattern_t)kCLOSE &&
305 *pat != (Pattern_t)kPCLOSE) {
310 if (!omatch(&str, &slen, pat, start))
316 if (*pat++ == (Pattern_t)kPCLOSE)
317 if (!omatch(&str, &slen, pat, start))
322 const char* bocl = str;
323 while (slen && omatch(&str, &slen, pat, start))
326 if (*pat == (Pattern_t)kEND)
339 while ((end = patcmp(str, slen, pat, start)) == 0) {
341 if (str < bocl)
break;
369 static int omatch(
const char** strp,
371 const Pattern_t* pat,
376 case kBOL:
return (*strp == start);
379 case kEOL:
return (*slenp == 0);
383 case kANY:
if (**strp ==
'\n')
return 0;
387 case kCCL:
if (*slenp == 0 || !TSTBIT(**strp, pat + 1))
return 0;
391 default:
if (*slenp == 0 || (
unsigned char) **strp != *pat)
return 0;
406 static int hex2bin(
int c)
408 return (isdigit(c) ? (c)-
'0': ((toupper((
unsigned char)c))-
'A')+10) & 0xf;
415 static int oct2bin(
int c)
417 return ( ((c)-
'0') & 0x7 );
438 static int esc(
const char** s)
446 switch (toupper((
unsigned char)**s)) {
447 case '\0': rval =
'\\';
break;
448 case 'B': rval =
'\b';
break;
449 case 'F': rval =
'\f';
break;
450 case 'N': rval =
'\n';
break;
451 case 'R': rval =
'\r';
break;
452 case 'S': rval =
' ';
break;
453 case 'T': rval =
'\t';
break;
454 case 'E': rval =
'\033';
break;
458 rval = toupper((
unsigned char)rval) -
'@';
464 if (ISHEXDIGIT(**s)) {
465 rval = hex2bin((
unsigned char) *(*s)++);
467 if (ISHEXDIGIT(**s)) {
469 rval |= hex2bin((
unsigned char) *(*s)++);
475 if (!ISOCTDIGIT(**s))
478 rval = oct2bin(*(*s)++);
479 if (ISOCTDIGIT(**s)) {
481 rval |= oct2bin(*(*s)++);
483 if (ISOCTDIGIT(**s)) {
485 rval |= oct2bin(*(*s)++);
493 return (
unsigned char)rval;