1 /*
2 
3  *      Copyright (c) 1984, 1985, 1986 AT&T
4  *      All Rights Reserved
5 
6  *      THIS IS UNPUBLISHED PROPRIETARY SOURCE
7  *      CODE OF AT&T.
8  *      The copyright notice above does not
9  *      evidence any actual or intended
10  *      publication of such source code.
11 
12  */
13 /* @(#)gmatch.c	1.1 */
14 
15 /*
16  *  gmatch - match Shell expression patterns
17  *
18  *   David Korn
19  *   AT&T Bell Laboratories
20  *   Room 5D-112
21  *   Murray Hill, N. J. 07974
22  *   Tel. x7975
23  *
24  *  Derived from Bourne Shell
25  */
26 
27 /*
28  * gmatch compares the string s with the shell pattern p.
29  * returns 1 for match, 0 otherwise.
30  * The ESCAPE character is used to remove special meaning in pattern only.
31  */
32 
33 #define ESCAPE	'\\'
34 
35 #ifdef MULTIBYTE
36 # include	"national.h"
37 # define C_MASK (3<<(7*ESS_MAXCHAR))	/* character classes */
38 # define peekchar(x)	(_save=x,_c=getchar(x),x=_save,_c)
39 # define getchar(x)	ja_getchar((unsigned char**)(&(x)))
40 int ja_getchar();
41 static char	*_save;
42 static int	_c;
43 #else
44 # define getchar(x)	(*x++)
45 # define peekchar(x)	(*x)
46 #endif /* MULTIBYTE */
47 
48 gmatch(s, p)
49 #ifdef MULTIBYTE
50 char *p;
51 #else
52 register char *p;
53 #endif /* MULTIBYTE */
54 char *s;
55 {
56 	register int 	scc,c;
57 	register int d;
58 	char *olds;
59 	while((olds=s,scc = getchar(s)))
60 	{
61 		switch(c = getchar(p))
62 		{
63 			case '[':
64 			{
65 				char ok = 0;
66 				int lc = -1;
67 				int notflag=0;
68 				if(*p == '!' )
69 				{
70 					notflag=1;
71 					p++;
72 				}
73 				while(c = getchar(p))
74 				{
75 					if(c==']' && lc>=0)
76 						return(ok?gmatch(s,p):0);
77 					else if(c=='-' && lc>=0 && *p!=']')
78 						/*character range */
79 					{
80 						c = getchar(p);
81 #ifdef MULTIBYTE
82 						/* must be in same char set */
83 						if((c&C_MASK) != (lc&C_MASK))
84 						{
85 							int match;
86 							match = (scc==c||scc==lc);
87 					 		if(notflag)
88 							{
89 								if(!match)
90 									ok++;
91 								else
92 									return(0);
93 							}
94 							else
95 							{
96 								if(match)
97 									ok++;
98 							}
99 							lc = c;
100 						}
101 #endif /* MULTIBYTE */
102 						if(notflag)
103 						{
104 							if(lc>scc || scc>c)
105 								ok++;
106 							else
107 								return(0);
108 						}
109 						else
110 							if(lc<scc && scc<=c)
111 								ok++;
112 					}
113 					else
114 					{
115 						if(c == ESCAPE)
116 							c = *p++;
117 				 		if(notflag)
118 						{
119 							if(scc!=c)
120 								ok++;
121 							else
122 								return(0);
123 						}
124 						else
125 						{
126 							if(scc==c)
127 								ok++;
128 						}
129 						lc = c;
130 					}
131 				}
132 				return(0);
133 			}
134 			case '\\':
135 				c = getchar(p);	/* need exact match */
136 			default:
137 				if(c != scc)
138 					return(0);
139 			case '?':
140 				break;
141 			case '*':
142 			/* several asterisks are the same as one */
143 				while(*p=='*' )
144 					p++;
145 				if(*p==0)
146 					return(1);
147 				d = scc;
148 				c = peekchar(p);
149 				scc = (c!='?' && c !='[');
150 				if(c==ESCAPE)
151 					c = *(p+1);
152 				while(d)
153 				{
154 					if(scc && c != d)
155 						;
156 					else if(gmatch(olds,p))
157 						return(1);
158 					olds = s;
159 					d = getchar(s);
160 
161 				}
162 				return(0);
163 
164 			case 0:
165 				return(scc==0);
166 		}
167 	}
168 	while(*p == '*')
169 		p++;
170 	return(*p==0);
171 }
172 
173 #ifdef MULTIBYTE
174 
175 /*
176  * This character read from one to three bytes and returns a character
177  * The character set designation is in the bits defined by C_MASK
178  */
179 
180 int ja_getchar(address)
181 unsigned char **address;
182 {
183 	register unsigned char *cp = *(unsigned char**)address;
184 	register int c = *cp++;
185 	register int size;
186 	int d;
187 	if(size = echarset(c))
188 	{
189 		d = (size==1?c:0);
190 		c = size;
191 		size = in_csize(c);
192 		c <<= 7*(ESS_MAXCHAR-size);
193 		if(d)
194 		{
195 			size--;
196 			c = (c<<7) | (d&~HIGHBIT);
197 		}
198 		while(size-- >0)
199 			c = (c<<7) | ((*cp++)&~HIGHBIT);
200 	}
201 	*address = cp;
202 	return(c);
203 }
204 #endif /*MULTIBYTE*/
205