standardize keyword lines
[unix-history] / usr / src / old / sh / expand.c
CommitLineData
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
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
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
116gmatch(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
161LOCAL 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
186makearg(args)
187 REG STRING args;
188{
189 args->argnxt=gchain;
190 gchain=args;
191}
192