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