Commit | Line | Data |
---|---|---|
f6227721 SL |
1 | #ifndef lint |
2 | static char sccsid[] = "@(#)expand.c 4.5 %G%"; | |
3 | #endif | |
c62d0dbc KM |
4 | |
5 | # | |
6 | /* | |
7 | * UNIX shell | |
8 | * | |
9 | * S. R. Bourne | |
10 | * Bell Telephone Laboratories | |
11 | * | |
12 | */ | |
13 | ||
14 | #include "defs.h" | |
15 | #include <sys/param.h> | |
16 | #include <sys/stat.h> | |
657820b8 | 17 | #include <sys/dir.h> |
c62d0dbc KM |
18 | |
19 | ||
20 | ||
21 | /* globals (file name generation) | |
22 | * | |
23 | * "*" in params matches r.e ".*" | |
24 | * "?" in params matches r.e. "." | |
25 | * "[...]" in params matches character class | |
26 | * "[...a-z...]" in params matches a through z. | |
27 | * | |
28 | */ | |
29 | ||
30 | PROC VOID addg(); | |
31 | ||
32 | ||
33 | INT expand(as,rflg) | |
34 | STRING as; | |
35 | { | |
36 | INT count; | |
37 | DIR *dirf; | |
38 | BOOL dir=0; | |
39 | STRING rescan = 0; | |
40 | REG STRING s, cs; | |
41 | ARGPTR schain = gchain; | |
42 | struct direct *dp; | |
43 | STATBUF statb; | |
44 | ||
45 | IF trapnote&SIGSET THEN return(0); FI | |
46 | ||
47 | s=cs=as; | |
48 | ||
49 | /* check for meta chars */ | |
50 | BEGIN | |
51 | REG BOOL slash; slash=0; | |
52 | WHILE !fngchar(*cs) | |
53 | DO IF *cs++==0 | |
54 | THEN IF rflg ANDF slash THEN break; ELSE return(0) FI | |
55 | ELIF *cs=='/' | |
56 | THEN slash++; | |
57 | FI | |
58 | OD | |
59 | END | |
60 | ||
61 | LOOP IF cs==s | |
62 | THEN s=nullstr; | |
63 | break; | |
64 | ELIF *--cs == '/' | |
65 | THEN *cs=0; | |
66 | IF s==cs THEN s="/" FI | |
67 | break; | |
68 | FI | |
69 | POOL | |
70 | IF stat(s,&statb)>=0 | |
71 | ANDF (statb.st_mode&S_IFMT)==S_IFDIR | |
443e9382 | 72 | ANDF (dirf=opendir(s)) != NULL |
c62d0dbc KM |
73 | THEN dir++; |
74 | FI | |
75 | count=0; | |
76 | IF *cs==0 THEN *cs++=0200 FI | |
77 | IF dir | |
78 | THEN /* check for rescan */ | |
79 | REG STRING rs; rs=cs; | |
80 | ||
81 | REP IF *rs=='/' THEN rescan=rs; *rs=0; gchain=0 FI | |
82 | PER *rs++ DONE | |
83 | ||
22674779 SL |
84 | IF setjmp(INTbuf) == 0 THEN trapjmp[INTR] = 1; FI |
85 | WHILE (trapnote&SIGSET) == 0 ANDF (dp = readdir(dirf)) != NULL | |
c62d0dbc KM |
86 | DO IF (*dp->d_name=='.' ANDF *cs!='.') |
87 | THEN continue; | |
88 | FI | |
89 | IF gmatch(dp->d_name, cs) | |
90 | THEN addg(s,dp->d_name,rescan); count++; | |
91 | FI | |
92 | OD | |
22674779 | 93 | closedir(dirf); trapjmp[INTR] = 0; |
c62d0dbc KM |
94 | |
95 | IF rescan | |
96 | THEN REG ARGPTR rchain; | |
97 | rchain=gchain; gchain=schain; | |
98 | IF count | |
99 | THEN count=0; | |
100 | WHILE rchain | |
101 | DO count += expand(rchain->argval,1); | |
102 | rchain=rchain->argnxt; | |
103 | OD | |
104 | FI | |
105 | *rescan='/'; | |
106 | FI | |
107 | FI | |
108 | ||
109 | BEGIN | |
110 | REG CHAR c; | |
111 | s=as; | |
112 | WHILE c = *s | |
113 | DO *s++=(c&STRIP?c:'/') OD | |
114 | END | |
115 | return(count); | |
116 | } | |
117 | ||
118 | gmatch(s, p) | |
119 | REG STRING s, p; | |
120 | { | |
121 | REG INT scc; | |
122 | CHAR c; | |
123 | ||
124 | IF scc = *s++ | |
125 | THEN IF (scc &= STRIP)==0 | |
126 | THEN scc=0200; | |
127 | FI | |
128 | FI | |
129 | SWITCH c = *p++ IN | |
130 | ||
131 | case '[': | |
132 | {BOOL ok; INT lc; | |
133 | ok=0; lc=077777; | |
134 | WHILE c = *p++ | |
135 | DO IF c==']' | |
136 | THEN return(ok?gmatch(s,p):0); | |
137 | ELIF c==MINUS | |
138 | THEN IF lc<=scc ANDF scc<=(*p++) THEN ok++ FI | |
139 | ELSE IF scc==(lc=(c&STRIP)) THEN ok++ FI | |
140 | FI | |
141 | OD | |
142 | return(0); | |
143 | } | |
144 | ||
145 | default: | |
146 | IF (c&STRIP)!=scc THEN return(0) FI | |
147 | ||
148 | case '?': | |
149 | return(scc?gmatch(s,p):0); | |
150 | ||
151 | case '*': | |
152 | IF *p==0 THEN return(1) FI | |
153 | --s; | |
154 | WHILE *s | |
155 | DO IF gmatch(s++,p) THEN return(1) FI OD | |
156 | return(0); | |
157 | ||
158 | case 0: | |
159 | return(scc==0); | |
160 | ENDSW | |
161 | } | |
162 | ||
163 | LOCAL VOID addg(as1,as2,as3) | |
164 | STRING as1, as2, as3; | |
165 | { | |
166 | REG STRING s1, s2; | |
167 | REG INT c; | |
168 | ||
169 | s2 = locstak()+BYTESPERWORD; | |
170 | ||
171 | s1=as1; | |
172 | WHILE c = *s1++ | |
173 | DO IF (c &= STRIP)==0 | |
174 | THEN *s2++='/'; | |
175 | break; | |
176 | FI | |
177 | *s2++=c; | |
178 | OD | |
179 | s1=as2; | |
180 | WHILE *s2 = *s1++ DO s2++ OD | |
181 | IF s1=as3 | |
182 | THEN *s2++='/'; | |
183 | WHILE *s2++ = *++s1 DONE | |
184 | FI | |
185 | makearg(endstak(s2)); | |
186 | } | |
187 | ||
188 | makearg(args) | |
189 | REG STRING args; | |
190 | { | |
191 | args->argnxt=gchain; | |
192 | gchain=args; | |
193 | } | |
194 |