home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / sh / expand.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-12  |  2.9 KB  |  191 lines

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