date and time created 82/05/07 19:37:29 by mckusick
[unix-history] / usr / src / old / sh / expand.c
CommitLineData
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
28PROC VOID addg();
29
30
31INT 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
115gmatch(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
160LOCAL 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
185makearg(args)
186 REG STRING args;
187{
188 args->argnxt=gchain;
189 gchain=args;
190}
191