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