1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
20 * *
21 ***********************************************************************/
22 #pragma prototyped
23
24 /*
25 * D. G. Korn
26 * G. S. Fowler
27 * AT&T Research
28 *
29 * match shell file patterns
30 * this interface is a wrapper on regex
31 *
32 * sh pattern egrep RE description
33 * ---------- -------- -----------
34 * * .* 0 or more chars
35 * ? . any single char
36 * [.] [.] char class
37 * [!.] [^.] negated char class
38 * [[:.:]] [[:.:]] ctype class
39 * [[=.=]] [[=.=]] equivalence class
40 * [[...]] [[...]] collation element
41 * *(.) (.)* 0 or more of
42 * +(.) (.)+ 1 or more of
43 * ?(.) (.)? 0 or 1 of
44 * (.) (.) 1 of
45 * @(.) (.) 1 of
46 * a|b a|b a or b
47 * \# () subgroup back reference [1-9]
48 * a&b a and b
49 * !(.) none of
50 *
51 * \ used to escape metacharacters
52 *
53 * *, ?, (, |, &, ), [, \ must be \'d outside of [...]
54 * only ] must be \'d inside [...]
55 *
56 */
57
58 #include <ast.h>
59 #include <regex.h>
60
61 static struct State_s
62 {
63 regmatch_t* match;
64 int nmatch;
65 } matchstate;
66
67 /*
68 * subgroup match
69 * 0 returned if no match
70 * otherwise number of subgroups matched returned
71 * match group begin offsets are even elements of sub
72 * match group end offsets are odd elements of sub
73 * the matched string is from s+sub[0] up to but not
74 * including s+sub[1]
75 */
76
77 int
strgrpmatch(const char * b,const char * p,int * sub,int n,register int flags)78 strgrpmatch(const char* b, const char* p, int* sub, int n, register int flags)
79 {
80 register regex_t* re;
81 register int* end;
82 register int i;
83 register regflags_t reflags;
84
85 /*
86 * 0 and empty patterns are special
87 */
88
89 if (!p || !b)
90 {
91 if (!p && !b)
92 regcache(NiL, 0, NiL);
93 return 0;
94 }
95 if (!*p)
96 {
97 if (sub && n > 0)
98 sub[0] = sub[1] = 0;
99 return *b == 0;
100 }
101
102 /*
103 * convert flags
104 */
105
106 if (flags & REG_ADVANCE)
107 reflags = flags & ~REG_ADVANCE;
108 else
109 {
110 reflags = REG_SHELL|REG_AUGMENTED;
111 if (!(flags & STR_MAXIMAL))
112 reflags |= REG_MINIMAL;
113 if (flags & STR_GROUP)
114 reflags |= REG_SHELL_GROUP;
115 if (flags & STR_LEFT)
116 reflags |= REG_LEFT;
117 if (flags & STR_RIGHT)
118 reflags |= REG_RIGHT;
119 if (flags & STR_ICASE)
120 reflags |= REG_ICASE;
121 }
122 if (!sub || n <= 0)
123 reflags |= REG_NOSUB;
124 if (!(re = regcache(p, reflags, NiL)))
125 return 0;
126 if (n > matchstate.nmatch)
127 {
128 if (!(matchstate.match = newof(matchstate.match, regmatch_t, n, 0)))
129 return 0;
130 matchstate.nmatch = n;
131 }
132 if (regexec(re, b, n, matchstate.match, reflags & ~(REG_MINIMAL|REG_SHELL_GROUP|REG_LEFT|REG_RIGHT|REG_ICASE)))
133 return 0;
134 if (!sub || n <= 0)
135 return 1;
136 i = re->re_nsub;
137 end = sub + n * 2;
138 for (n = 0; sub < end && n <= i; n++)
139 {
140 *sub++ = matchstate.match[n].rm_so;
141 *sub++ = matchstate.match[n].rm_eo;
142 }
143 return i + 1;
144 }
145
146 /*
147 * compare the string s with the shell pattern p
148 * returns 1 for match 0 otherwise
149 */
150
151 int
strmatch(const char * s,const char * p)152 strmatch(const char* s, const char* p)
153 {
154 return strgrpmatch(s, p, NiL, 0, STR_MAXIMAL|STR_LEFT|STR_RIGHT);
155 }
156
157 /*
158 * leading substring match
159 * first char after end of substring returned
160 * 0 returned if no match
161 *
162 * OBSOLETE: use strgrpmatch()
163 */
164
165 char*
strsubmatch(const char * s,const char * p,int flags)166 strsubmatch(const char* s, const char* p, int flags)
167 {
168 int match[2];
169
170 return strgrpmatch(s, p, match, 1, (flags ? STR_MAXIMAL : 0)|STR_LEFT) ? (char*)s + match[1] : (char*)0;
171 }
172