Annotation of 40BSD/cmd/sh/expand.c, revision 1.1.1.1

1.1       root        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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.