114478Ssam #ifndef lint
2*35683Sbostic static char sccsid[] = "@(#)expand.c 4.6 09/22/88";
314478Ssam #endif
46691Smckusick
56691Smckusick #
66691Smckusick /*
76691Smckusick * UNIX shell
86691Smckusick *
96691Smckusick * S. R. Bourne
106691Smckusick * Bell Telephone Laboratories
116691Smckusick *
126691Smckusick */
136691Smckusick
146691Smckusick #include "defs.h"
156691Smckusick #include <sys/param.h>
166691Smckusick #include <sys/stat.h>
1713559Ssam #include <sys/dir.h>
186691Smckusick
196691Smckusick
206691Smckusick
216691Smckusick /* globals (file name generation)
226691Smckusick *
236691Smckusick * "*" in params matches r.e ".*"
246691Smckusick * "?" in params matches r.e. "."
256691Smckusick * "[...]" in params matches character class
266691Smckusick * "[...a-z...]" in params matches a through z.
276691Smckusick *
286691Smckusick */
296691Smckusick
306691Smckusick PROC VOID addg();
316691Smckusick
326691Smckusick
expand(as,rflg)336691Smckusick INT expand(as,rflg)
346691Smckusick STRING as;
356691Smckusick {
366691Smckusick INT count;
376691Smckusick DIR *dirf;
386691Smckusick BOOL dir=0;
396691Smckusick STRING rescan = 0;
406691Smckusick REG STRING s, cs;
416691Smckusick ARGPTR schain = gchain;
426691Smckusick struct direct *dp;
436691Smckusick STATBUF statb;
446691Smckusick
456691Smckusick IF trapnote&SIGSET THEN return(0); FI
466691Smckusick
476691Smckusick s=cs=as;
486691Smckusick
496691Smckusick /* check for meta chars */
506691Smckusick BEGIN
516691Smckusick REG BOOL slash; slash=0;
526691Smckusick WHILE !fngchar(*cs)
536691Smckusick DO IF *cs++==0
546691Smckusick THEN IF rflg ANDF slash THEN break; ELSE return(0) FI
556691Smckusick ELIF *cs=='/'
566691Smckusick THEN slash++;
576691Smckusick FI
586691Smckusick OD
596691Smckusick END
606691Smckusick
616691Smckusick LOOP IF cs==s
626691Smckusick THEN s=nullstr;
636691Smckusick break;
646691Smckusick ELIF *--cs == '/'
656691Smckusick THEN *cs=0;
666691Smckusick IF s==cs THEN s="/" FI
676691Smckusick break;
686691Smckusick FI
696691Smckusick POOL
706691Smckusick IF stat(s,&statb)>=0
716691Smckusick ANDF (statb.st_mode&S_IFMT)==S_IFDIR
7211751Ssam ANDF (dirf=opendir(s)) != NULL
736691Smckusick THEN dir++;
746691Smckusick FI
756691Smckusick count=0;
766691Smckusick IF *cs==0 THEN *cs++=0200 FI
776691Smckusick IF dir
786691Smckusick THEN /* check for rescan */
796691Smckusick REG STRING rs; rs=cs;
806691Smckusick
816691Smckusick REP IF *rs=='/' THEN rescan=rs; *rs=0; gchain=0 FI
826691Smckusick PER *rs++ DONE
836691Smckusick
8412992Ssam IF setjmp(INTbuf) == 0 THEN trapjmp[INTR] = 1; FI
8512992Ssam WHILE (trapnote&SIGSET) == 0 ANDF (dp = readdir(dirf)) != NULL
866691Smckusick DO IF (*dp->d_name=='.' ANDF *cs!='.')
876691Smckusick THEN continue;
886691Smckusick FI
896691Smckusick IF gmatch(dp->d_name, cs)
906691Smckusick THEN addg(s,dp->d_name,rescan); count++;
916691Smckusick FI
926691Smckusick OD
9312992Ssam closedir(dirf); trapjmp[INTR] = 0;
946691Smckusick
956691Smckusick IF rescan
966691Smckusick THEN REG ARGPTR rchain;
976691Smckusick rchain=gchain; gchain=schain;
986691Smckusick IF count
996691Smckusick THEN count=0;
1006691Smckusick WHILE rchain
1016691Smckusick DO count += expand(rchain->argval,1);
1026691Smckusick rchain=rchain->argnxt;
1036691Smckusick OD
1046691Smckusick FI
1056691Smckusick *rescan='/';
1066691Smckusick FI
1076691Smckusick FI
1086691Smckusick
1096691Smckusick BEGIN
1106691Smckusick REG CHAR c;
1116691Smckusick s=as;
1126691Smckusick WHILE c = *s
1136691Smckusick DO *s++=(c&STRIP?c:'/') OD
1146691Smckusick END
1156691Smckusick return(count);
1166691Smckusick }
1176691Smckusick
gmatch(s,p)1186691Smckusick gmatch(s, p)
1196691Smckusick REG STRING s, p;
1206691Smckusick {
1216691Smckusick REG INT scc;
1226691Smckusick CHAR c;
1236691Smckusick
1246691Smckusick IF scc = *s++
1256691Smckusick THEN IF (scc &= STRIP)==0
1266691Smckusick THEN scc=0200;
1276691Smckusick FI
1286691Smckusick FI
1296691Smckusick SWITCH c = *p++ IN
1306691Smckusick
1316691Smckusick case '[':
1326691Smckusick {BOOL ok; INT lc;
1336691Smckusick ok=0; lc=077777;
1346691Smckusick WHILE c = *p++
1356691Smckusick DO IF c==']'
1366691Smckusick THEN return(ok?gmatch(s,p):0);
1376691Smckusick ELIF c==MINUS
1386691Smckusick THEN IF lc<=scc ANDF scc<=(*p++) THEN ok++ FI
1396691Smckusick ELSE IF scc==(lc=(c&STRIP)) THEN ok++ FI
1406691Smckusick FI
1416691Smckusick OD
1426691Smckusick return(0);
1436691Smckusick }
1446691Smckusick
1456691Smckusick default:
1466691Smckusick IF (c&STRIP)!=scc THEN return(0) FI
1476691Smckusick
1486691Smckusick case '?':
1496691Smckusick return(scc?gmatch(s,p):0);
1506691Smckusick
1516691Smckusick case '*':
1526691Smckusick IF *p==0 THEN return(1) FI
1536691Smckusick --s;
1546691Smckusick WHILE *s
1556691Smckusick DO IF gmatch(s++,p) THEN return(1) FI OD
1566691Smckusick return(0);
1576691Smckusick
1586691Smckusick case 0:
1596691Smckusick return(scc==0);
1606691Smckusick ENDSW
1616691Smckusick }
1626691Smckusick
addg(as1,as2,as3)1636691Smckusick LOCAL VOID addg(as1,as2,as3)
1646691Smckusick STRING as1, as2, as3;
1656691Smckusick {
1666691Smckusick REG STRING s1, s2;
1676691Smckusick REG INT c;
1686691Smckusick
1696691Smckusick s2 = locstak()+BYTESPERWORD;
1706691Smckusick
1716691Smckusick s1=as1;
1726691Smckusick WHILE c = *s1++
1736691Smckusick DO IF (c &= STRIP)==0
1746691Smckusick THEN *s2++='/';
1756691Smckusick break;
1766691Smckusick FI
1776691Smckusick *s2++=c;
1786691Smckusick OD
1796691Smckusick s1=as2;
1806691Smckusick WHILE *s2 = *s1++ DO s2++ OD
1816691Smckusick IF s1=as3
1826691Smckusick THEN *s2++='/';
1836691Smckusick WHILE *s2++ = *++s1 DONE
1846691Smckusick FI
185*35683Sbostic makearg((ARGPTR)endstak(s2));
1866691Smckusick }
1876691Smckusick
makearg(args)1886691Smckusick makearg(args)
189*35683Sbostic REG ARGPTR args;
1906691Smckusick {
1916691Smckusick args->argnxt=gchain;
1926691Smckusick gchain=args;
1936691Smckusick }
1946691Smckusick
195