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