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