xref: /netbsd-src/external/cddl/osnet/dist/lib/libgen/common/gmatch.c (revision ba2539a9805a0544ff82c0003cc02fe1eee5603d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1988 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 /*LINTLIBRARY*/
33 
34 #ifdef illumos
35 #pragma weak gmatch = _gmatch
36 #endif
37 
38 #ifdef illumos
39 #include "gen_synonyms.h"
40 #endif
41 #include <sys/types.h>
42 #include <libgen.h>
43 #include <stdlib.h>
44 #include <limits.h>
45 #ifdef illumos
46 #include <widec.h>
47 #include "_range.h"
48 #else
49 #include <ctype.h>
50 /* DOODAD */ static int multibyte = 0;
51 #define WCHAR_CSMASK    0x30000000
52 #define valid_range(c1, c2) \
53     (((c1) & WCHAR_CSMASK) == ((c2) & WCHAR_CSMASK) && \
54     ((c1) > 0xff || !iscntrl((int)c1)) && ((c2) > 0xff || \
55     !iscntrl((int)c2)))
56 #endif
57 
58 #define	Popwchar(p, c) \
59 	n = mbtowc(&cl, p, MB_LEN_MAX); \
60 	c = cl; \
61 	if (n <= 0) \
62 		return (0); \
63 	p += n
64 
65 int gmatch(const char *, const char *);
66 int
gmatch(const char * s,const char * p)67 gmatch(const char *s, const char *p)
68 {
69 	const char	*olds;
70 	wchar_t		scc, c;
71 	int 		n;
72 	wchar_t		cl;
73 
74 	olds = s;
75 	n = mbtowc(&cl, s, MB_LEN_MAX);
76 	if (n <= 0) {
77 		s++;
78 		scc = n;
79 	} else {
80 		scc = cl;
81 		s += n;
82 	}
83 	n = mbtowc(&cl, p, MB_LEN_MAX);
84 	if (n < 0)
85 		return (0);
86 	if (n == 0)
87 		return (scc == 0);
88 	p += n;
89 	c = cl;
90 
91 	switch (c) {
92 	case '[':
93 		if (scc <= 0)
94 			return (0);
95 	{
96 			int ok;
97 			wchar_t lc = 0;
98 			int notflag = 0;
99 
100 			ok = 0;
101 			if (*p == '!') {
102 				notflag = 1;
103 				p++;
104 			}
105 			Popwchar(p, c);
106 			do
107 			{
108 				if (c == '-' && lc && *p != ']') {
109 					Popwchar(p, c);
110 					if (c == '\\') {
111 						Popwchar(p, c);
112 					}
113 					if (notflag) {
114 						if (!multibyte ||
115 						    valid_range(lc, c)) {
116 							if (scc < lc || scc > c)
117 								ok++;
118 							else
119 								return (0);
120 						}
121 					} else {
122 						if (!multibyte ||
123 						    valid_range(lc, c))
124 							if (lc <= scc &&
125 							    scc <= c)
126 								ok++;
127 					}
128 				} else if (c == '\\') {
129 					/* skip to quoted character */
130 					Popwchar(p, c);
131 				}
132 				lc = c;
133 				if (notflag) {
134 					if (scc != lc)
135 						ok++;
136 					else
137 						return (0);
138 				}
139 				else
140 				{
141 					if (scc == lc)
142 						ok++;
143 				}
144 				Popwchar(p, c);
145 			} while (c != ']');
146 			return (ok ? gmatch(s, p) : 0);
147 		}
148 
149 	case '\\':
150 		/* skip to quoted character and see if it matches */
151 		Popwchar(p, c);
152 
153 	default:
154 		if (c != scc)
155 			return (0);
156 			/*FALLTHRU*/
157 
158 	case '?':
159 		return (scc > 0 ? gmatch(s, p) : 0);
160 
161 	case '*':
162 		while (*p == '*')
163 			p++;
164 
165 		if (*p == 0)
166 			return (1);
167 		s = olds;
168 		while (*s) {
169 			if (gmatch(s, p))
170 				return (1);
171 			n = mbtowc(&cl, s, MB_LEN_MAX);
172 			if (n < 0)
173 				/* skip past illegal byte sequence */
174 				s++;
175 			else
176 				s += n;
177 		}
178 		return (0);
179 	}
180 }
181