]> git.ipfire.org Git - thirdparty/bash.git/blob - lib/glob/gmisc.c
Bash-4.2 distribution sources and documentation
[thirdparty/bash.git] / lib / glob / gmisc.c
1 /* gmisc.c -- miscellaneous pattern matching utility functions for Bash.
2
3 Copyright (C) 2010 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne-Again SHell.
6
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <config.h>
22
23 #include "bashtypes.h"
24
25 #if defined (HAVE_UNISTD_H)
26 # include <unistd.h>
27 #endif
28
29 #include "bashansi.h"
30 #include "shmbutil.h"
31
32 #include "stdc.h"
33
34 #ifndef LPAREN
35 # define LPAREN '('
36 #endif
37 #ifndef RPAREN
38 # define RPAREN ')'
39 #endif
40
41 #if defined (HANDLE_MULTIBYTE)
42 #define WLPAREN L'('
43 #define WRPAREN L')'
44
45 /* Return 1 of the first character of WSTRING could match the first
46 character of pattern WPAT. Wide character version. */
47 int
48 match_pattern_wchar (wpat, wstring)
49 wchar_t *wpat, *wstring;
50 {
51 wchar_t wc;
52
53 if (*wstring == 0)
54 return (0);
55
56 switch (wc = *wpat++)
57 {
58 default:
59 return (*wstring == wc);
60 case L'\\':
61 return (*wstring == *wpat);
62 case L'?':
63 return (*wpat == WLPAREN ? 1 : (*wstring != L'\0'));
64 case L'*':
65 return (1);
66 case L'+':
67 case L'!':
68 case L'@':
69 return (*wpat == WLPAREN ? 1 : (*wstring == wc));
70 case L'[':
71 return (*wstring != L'\0');
72 }
73 }
74
75 int
76 wmatchlen (wpat, wmax)
77 wchar_t *wpat;
78 size_t wmax;
79 {
80 wchar_t wc, *wbrack;
81 int matlen, t, in_cclass, in_collsym, in_equiv;
82
83 if (*wpat == 0)
84 return (0);
85
86 matlen = in_cclass = in_collsym = in_equiv = 0;
87 while (wc = *wpat++)
88 {
89 switch (wc)
90 {
91 default:
92 matlen++;
93 break;
94 case L'\\':
95 if (*wpat == 0)
96 return ++matlen;
97 else
98 {
99 matlen++;
100 wpat++;
101 }
102 break;
103 case L'?':
104 if (*wpat == WLPAREN)
105 return (matlen = -1); /* XXX for now */
106 else
107 matlen++;
108 break;
109 case L'*':
110 return (matlen = -1);
111 case L'+':
112 case L'!':
113 case L'@':
114 if (*wpat == WLPAREN)
115 return (matlen = -1); /* XXX for now */
116 else
117 matlen++;
118 break;
119 case L'[':
120 /* scan for ending `]', skipping over embedded [:...:] */
121 wbrack = wpat;
122 wc = *wpat++;
123 do
124 {
125 if (wc == 0)
126 {
127 matlen += wpat - wbrack - 1; /* incremented below */
128 break;
129 }
130 else if (wc == L'\\')
131 {
132 wc = *wpat++;
133 if (*wpat == 0)
134 break;
135 }
136 else if (wc == L'[' && *wpat == L':') /* character class */
137 {
138 wpat++;
139 in_cclass = 1;
140 }
141 else if (in_cclass && wc == L':' && *wpat == L']')
142 {
143 wpat++;
144 in_cclass = 0;
145 }
146 else if (wc == L'[' && *wpat == L'.') /* collating symbol */
147 {
148 wpat++;
149 if (*wpat == L']') /* right bracket can appear as collating symbol */
150 wpat++;
151 in_collsym = 1;
152 }
153 else if (in_collsym && wc == L'.' && *wpat == L']')
154 {
155 wpat++;
156 in_collsym = 0;
157 }
158 else if (wc == L'[' && *wpat == L'=') /* equivalence class */
159 {
160 wpat++;
161 if (*wpat == L']') /* right bracket can appear as equivalence class */
162 wpat++;
163 in_equiv = 1;
164 }
165 else if (in_equiv && wc == L'=' && *wpat == L']')
166 {
167 wpat++;
168 in_equiv = 0;
169 }
170 }
171 while ((wc = *wpat++) != L']');
172 matlen++; /* bracket expression can only match one char */
173 break;
174 }
175 }
176
177 return matlen;
178 }
179 #endif
180
181 /* Return 1 of the first character of STRING could match the first
182 character of pattern PAT. Used to avoid n2 calls to strmatch(). */
183 int
184 match_pattern_char (pat, string)
185 char *pat, *string;
186 {
187 char c;
188
189 if (*string == 0)
190 return (0);
191
192 switch (c = *pat++)
193 {
194 default:
195 return (*string == c);
196 case '\\':
197 return (*string == *pat);
198 case '?':
199 return (*pat == LPAREN ? 1 : (*string != '\0'));
200 case '*':
201 return (1);
202 case '+':
203 case '!':
204 case '@':
205 return (*pat == LPAREN ? 1 : (*string == c));
206 case '[':
207 return (*string != '\0');
208 }
209 }
210
211 int
212 umatchlen (pat, max)
213 char *pat;
214 size_t max;
215 {
216 char c, *brack;
217 int matlen, t, in_cclass, in_collsym, in_equiv;
218
219 if (*pat == 0)
220 return (0);
221
222 matlen = in_cclass = in_collsym = in_equiv = 0;
223 while (c = *pat++)
224 {
225 switch (c)
226 {
227 default:
228 matlen++;
229 break;
230 case '\\':
231 if (*pat == 0)
232 return ++matlen;
233 else
234 {
235 matlen++;
236 pat++;
237 }
238 break;
239 case '?':
240 if (*pat == LPAREN)
241 return (matlen = -1); /* XXX for now */
242 else
243 matlen++;
244 break;
245 case '*':
246 return (matlen = -1);
247 case '+':
248 case '!':
249 case '@':
250 if (*pat == LPAREN)
251 return (matlen = -1); /* XXX for now */
252 else
253 matlen++;
254 break;
255 case '[':
256 /* scan for ending `]', skipping over embedded [:...:] */
257 brack = pat;
258 c = *pat++;
259 do
260 {
261 if (c == 0)
262 {
263 matlen += pat - brack - 1; /* incremented below */
264 break;
265 }
266 else if (c == '\\')
267 {
268 c = *pat++;
269 if (*pat == 0)
270 break;
271 }
272 else if (c == '[' && *pat == ':') /* character class */
273 {
274 pat++;
275 in_cclass = 1;
276 }
277 else if (in_cclass && c == ':' && *pat == ']')
278 {
279 pat++;
280 in_cclass = 0;
281 }
282 else if (c == '[' && *pat == '.') /* collating symbol */
283 {
284 pat++;
285 if (*pat == ']') /* right bracket can appear as collating symbol */
286 pat++;
287 in_collsym = 1;
288 }
289 else if (in_collsym && c == '.' && *pat == ']')
290 {
291 pat++;
292 in_collsym = 0;
293 }
294 else if (c == '[' && *pat == '=') /* equivalence class */
295 {
296 pat++;
297 if (*pat == ']') /* right bracket can appear as equivalence class */
298 pat++;
299 in_equiv = 1;
300 }
301 else if (in_equiv && c == '=' && *pat == ']')
302 {
303 pat++;
304 in_equiv = 0;
305 }
306 }
307 while ((c = *pat++) != ']');
308 matlen++; /* bracket expression can only match one char */
309 break;
310 }
311 }
312
313 return matlen;
314 }