Commit | Line | Data |
---|---|---|
657820b8 | 1 | /* expand.c 4.4 83/07/01 */ |
c62d0dbc KM |
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> | |
657820b8 | 15 | #include <sys/dir.h> |
c62d0dbc KM |
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 | |
443e9382 | 70 | ANDF (dirf=opendir(s)) != NULL |
c62d0dbc KM |
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 | ||
22674779 SL |
82 | IF setjmp(INTbuf) == 0 THEN trapjmp[INTR] = 1; FI |
83 | WHILE (trapnote&SIGSET) == 0 ANDF (dp = readdir(dirf)) != NULL | |
c62d0dbc KM |
84 | DO IF (*dp->d_name=='.' ANDF *cs!='.') |
85 | THEN continue; | |
86 | FI | |
87 | IF gmatch(dp->d_name, cs) | |
88 | THEN addg(s,dp->d_name,rescan); count++; | |
89 | FI | |
90 | OD | |
22674779 | 91 | closedir(dirf); trapjmp[INTR] = 0; |
c62d0dbc KM |
92 | |
93 | IF rescan | |
94 | THEN REG ARGPTR rchain; | |
95 | rchain=gchain; gchain=schain; | |
96 | IF count | |
97 | THEN count=0; | |
98 | WHILE rchain | |
99 | DO count += expand(rchain->argval,1); | |
100 | rchain=rchain->argnxt; | |
101 | OD | |
102 | FI | |
103 | *rescan='/'; | |
104 | FI | |
105 | FI | |
106 | ||
107 | BEGIN | |
108 | REG CHAR c; | |
109 | s=as; | |
110 | WHILE c = *s | |
111 | DO *s++=(c&STRIP?c:'/') OD | |
112 | END | |
113 | return(count); | |
114 | } | |
115 | ||
116 | gmatch(s, p) | |
117 | REG STRING s, p; | |
118 | { | |
119 | REG INT scc; | |
120 | CHAR c; | |
121 | ||
122 | IF scc = *s++ | |
123 | THEN IF (scc &= STRIP)==0 | |
124 | THEN scc=0200; | |
125 | FI | |
126 | FI | |
127 | SWITCH c = *p++ IN | |
128 | ||
129 | case '[': | |
130 | {BOOL ok; INT lc; | |
131 | ok=0; lc=077777; | |
132 | WHILE c = *p++ | |
133 | DO IF c==']' | |
134 | THEN return(ok?gmatch(s,p):0); | |
135 | ELIF c==MINUS | |
136 | THEN IF lc<=scc ANDF scc<=(*p++) THEN ok++ FI | |
137 | ELSE IF scc==(lc=(c&STRIP)) THEN ok++ FI | |
138 | FI | |
139 | OD | |
140 | return(0); | |
141 | } | |
142 | ||
143 | default: | |
144 | IF (c&STRIP)!=scc THEN return(0) FI | |
145 | ||
146 | case '?': | |
147 | return(scc?gmatch(s,p):0); | |
148 | ||
149 | case '*': | |
150 | IF *p==0 THEN return(1) FI | |
151 | --s; | |
152 | WHILE *s | |
153 | DO IF gmatch(s++,p) THEN return(1) FI OD | |
154 | return(0); | |
155 | ||
156 | case 0: | |
157 | return(scc==0); | |
158 | ENDSW | |
159 | } | |
160 | ||
161 | LOCAL VOID addg(as1,as2,as3) | |
162 | STRING as1, as2, as3; | |
163 | { | |
164 | REG STRING s1, s2; | |
165 | REG INT c; | |
166 | ||
167 | s2 = locstak()+BYTESPERWORD; | |
168 | ||
169 | s1=as1; | |
170 | WHILE c = *s1++ | |
171 | DO IF (c &= STRIP)==0 | |
172 | THEN *s2++='/'; | |
173 | break; | |
174 | FI | |
175 | *s2++=c; | |
176 | OD | |
177 | s1=as2; | |
178 | WHILE *s2 = *s1++ DO s2++ OD | |
179 | IF s1=as3 | |
180 | THEN *s2++='/'; | |
181 | WHILE *s2++ = *++s1 DONE | |
182 | FI | |
183 | makearg(endstak(s2)); | |
184 | } | |
185 | ||
186 | makearg(args) | |
187 | REG STRING args; | |
188 | { | |
189 | args->argnxt=gchain; | |
190 | gchain=args; | |
191 | } | |
192 |