1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <wchar.h>
5
6 #include "varexp.h"
7
8 /*
9
10 copyright (c) 2004, 2006 squell <squell@alumina.nl>
11
12 use, modification, copying and distribution of this software is permitted
13 under the conditions described in the file 'COPYING'.
14
15 an adapted version of a smaller, simpler wildcard match routine to
16 support a primitive form of pattern matching
17
18 the base C version included at the end, if you're interested
19
20 */
21
match(const char * mask,const char * test)22 bool varexp::match(const char *mask, const char *test)
23 {
24 char c, m;
25 const char *flag = &c; // dummy value
26 do {
27 const char* resume[2] = { flag, };
28 do {
29 retry: switch( c=*test++, m=*mask++ ) {
30 default :
31 if( m != c ) goto fail; // double break
32 continue;
33 case '?':
34 int skip; skip = mblen(test-1, MB_CUR_MAX);
35 if(skip > 1) test += skip-1;
36 continue;
37 case '*':
38 if(*resume)
39 flag = 0, var.push_back(pairvec::value_type(test-1, 0));
40 else
41 var.back().second++;
42 resume[0] = mask-1, resume[1] = test;
43 --test;
44 goto retry; // forced continue
45 case '[':
46 if(! (mask=in_set(c, mask)) ) goto fail;
47 }
48 } while(c);
49 fail: mask = resume[0];
50 test = resume[1];
51 } while(c && test);
52 return !(m|c);
53 }
54
55 /*
56 auxilliary code to detect character ranges in expressions
57 uses plain value comparison to detect ranges; not collating sequences.
58
59 issue: refuses to compare non-ascii characters in order to avoid
60 serious problems with UTF-8 strings; varexp should really be lifted
61 to the wchar_t world.
62 */
63
in_set(char c,const char * set)64 const char *varexp::in_set(char c, const char *set)
65 {
66 const char *start = set;
67 int neg = 0, truth = 0;
68 char prev, m;
69 if(*set=='!' || *set=='^') {
70 neg = 1; // match chars NOT in set
71 ++set;
72 }
73 for(prev = 0; (m = *set++) && !(m & 0x80); prev = m) {
74 if(m=='-' && prev && *set!='\0' && *set!=']') {
75 truth |= (c >= prev) && (c <= *set);
76 } else {
77 if(m==']')
78 return (truth^neg)? set : 0;
79 truth |= (m==c);
80 }
81 }
82 return (c == '[')? start : 0; // not a set notation
83 }
84
85 /*
86
87 primitive C version without pattern matching (inefficient)
88
89 int match(const char *mask, const char *test)
90 {
91 char c, m;
92 do {
93 switch( c=*test++, m=*mask++ ) {
94 default :
95 if( m != c ) return 0;
96 case '?':
97 break;
98 case '*':
99 if( match(mask,test-1) ) return 1;
100 --mask;
101 }
102 } while(c);
103 return !m;
104 }
105
106 non-recursive C version without pattern matching
107
108 int match(const char *mask, const char *test)
109 {
110 char c, m;
111 do {
112 const char* resume[2] = { 0, };
113 do {
114 retry: switch( c=*test++, m=*mask++ ) {
115 default :
116 if( m != c ) goto fail; // double break
117 case '?':
118 continue;
119 case '*':
120 resume[0] = mask-1, resume[1] = test;
121 --test;
122 goto retry; // forced continue
123 }
124 } while(c);
125 fail: mask = resume[0];
126 test = resume[1];
127 } while(c && mask);
128 return !(m|c);
129 }
130
131 */
132
133