Annotation of 40BSD/cmd/ptx.c, revision 1.1.1.1

1.1       root        1: static char *sccsid = "@(#)ptx.c       4.1 (Berkeley) 10/1/80";
                      2: #
                      3: 
                      4: /*     permuted title index
                      5:        ptx [-t] [-i ignore] [-o only] [-w num] [-f] [input] [output]
                      6:        Ptx reads the input file and permutes on words in it.
                      7:        It excludes all words in the ignore file.
                      8:        Alternately it includes words in the only file.
                      9:        if neither is given it excludes the words in /usr/lib/eign.
                     10: 
                     11:        The width of the output line can be changed to num
                     12:        characters.  If omitted 72 is default unless troff than 100.
                     13:        the -f flag tells the program to fold the output
                     14:        the -t flag says the output is for troff and the
                     15:        output is then wider.
                     16: 
                     17:       make: cc ptx.c -lS
                     18:        */
                     19: 
                     20: #include <stdio.h>
                     21: #include <ctype.h>
                     22: #include <signal.h>
                     23: #define DEFLTX "/usr/lib/eign"
                     24: #define TILDE 0177
                     25: #define SORT "/usr/bin/sort"
                     26: #define        N 30
                     27: #define        MAX     N*BUFSIZ
                     28: #define LMAX   200
                     29: #define MAXT   2048
                     30: #define MASK   03777
                     31: #define SET    1
                     32: 
                     33: #define isabreak(c) (btable[c])
                     34: 
                     35: extern char *calloc(), *mktemp();
                     36: extern char *getline();
                     37: int status;
                     38: 
                     39: 
                     40: char *hasht[MAXT];
                     41: char line[LMAX];
                     42: char btable[128];
                     43: int ignore;
                     44: int only;
                     45: int llen = 72;
                     46: int gap = 3;
                     47: int gutter = 3;
                     48: int mlen = LMAX;
                     49: int wlen;
                     50: int rflag;
                     51: int halflen;
                     52: char *strtbufp, *endbufp;
                     53: char *empty = "";
                     54: 
                     55: char *infile;
                     56: FILE *inptr = stdin;
                     57: 
                     58: char *outfile;
                     59: FILE *outptr = stdout;
                     60: 
                     61: char *sortfile;        /* output of sort program */
                     62: char nofold[] = {'-', 'd', 't', TILDE, 0};
                     63: char fold[] = {'-', 'd', 'f', 't', TILDE, 0};
                     64: char *sortopt = nofold;
                     65: FILE *sortptr;
                     66: 
                     67: char *bfile;   /*contains user supplied break chars */
                     68: FILE *bptr;
                     69: 
                     70: main(argc,argv)
                     71: int argc;
                     72: char **argv;
                     73: {
                     74:        register int c;
                     75:        register char *bufp;
                     76:        int pid;
                     77:        char *pend;
                     78:        extern onintr();
                     79: 
                     80:        char *xfile;
                     81:        FILE *xptr;
                     82: 
                     83:        if(signal(SIGHUP,onintr)==SIG_IGN)
                     84:                signal(SIGHUP,SIG_IGN);
                     85:        if(signal(SIGINT,onintr)==SIG_IGN)
                     86:                signal(SIGINT,SIG_IGN);
                     87:        signal(SIGPIPE,onintr);
                     88:        signal(SIGTERM,onintr);
                     89: 
                     90: /*     argument decoding       */
                     91: 
                     92:        xfile = DEFLTX;
                     93:        argv++;
                     94:        while(argc>1 && **argv == '-') {
                     95:                switch (*++*argv){
                     96: 
                     97:                case 'r':
                     98:                        rflag++;
                     99:                        break;
                    100:                case 'f':
                    101:                        sortopt = fold;
                    102:                        break;
                    103: 
                    104:                case 'w':
                    105:                        if(argc >= 2) {
                    106:                                argc--;
                    107:                                wlen++;
                    108:                                llen = atoi(*++argv);
                    109:                                if(llen == 0)
                    110:                                        diag("Wrong width:",*argv);
                    111:                                if(llen > LMAX) {
                    112:                                        llen = LMAX;
                    113:                                        msg("Lines truncated to 200 chars.",empty);
                    114:                                }
                    115:                                break;
                    116:                        }
                    117: 
                    118:                case 't':
                    119:                        if(wlen == 0)
                    120:                                llen = 100;
                    121:                        break;
                    122:                case 'g':
                    123:                        if(argc >=2) {
                    124:                                argc--;
                    125:                                gap = gutter = atoi(*++argv);
                    126:                        }
                    127:                        break;
                    128: 
                    129:                case 'i':
                    130:                        if(only) 
                    131:                                diag("Only file already given.",empty);
                    132:                        if (argc>=2){
                    133:                                argc--;
                    134:                                ignore++;
                    135:                                xfile = *++argv;
                    136:                        }
                    137:                        break;
                    138: 
                    139:                case 'o':
                    140:                        if(ignore)
                    141:                                diag("Ignore file already given",empty);
                    142:                        if (argc>=2){
                    143:                                only++;
                    144:                                argc--;
                    145:                                xfile = *++argv;
                    146:                        }
                    147:                        break;
                    148: 
                    149:                case 'b':
                    150:                        if(argc>=2) {
                    151:                                argc--;
                    152:                                bfile = *++argv;
                    153:                        }
                    154:                        break;
                    155: 
                    156:                default:
                    157:                        msg("Illegal argument:",*argv);
                    158:                }
                    159:                argc--;
                    160:                argv++;
                    161:        }
                    162: 
                    163:        if(argc>3)
                    164:                diag("Too many filenames",empty);
                    165:        else if(argc==3){
                    166:                infile = *argv++;
                    167:                outfile = *argv;
                    168:                if((outptr = fopen(outfile,"w")) == NULL)
                    169:                        diag("Cannot open output file:",outfile);
                    170:        } else if(argc==2) {
                    171:                infile = *argv;
                    172:                outfile = 0;
                    173:        }
                    174: 
                    175: 
                    176:        /* Default breaks of blank, tab and newline */
                    177:        btable[' '] = SET;
                    178:        btable['\t'] = SET;
                    179:        btable['\n'] = SET;
                    180:        if(bfile) {
                    181:                if((bptr = fopen(bfile,"r")) == NULL)
                    182:                        diag("Cannot open break char file",bfile);
                    183: 
                    184:                while((c = getc(bptr)) != EOF)
                    185:                        btable[c] = SET;
                    186:        }
                    187: 
                    188: /*     Allocate space for a buffer.  If only or ignore file present
                    189:        read it into buffer. Else read in default ignore file
                    190:        and put resulting words in buffer.
                    191:        */
                    192: 
                    193: 
                    194:        if((strtbufp = calloc(N,BUFSIZ)) == NULL)
                    195:                diag("Out of memory space",empty);
                    196:        bufp = strtbufp;
                    197:        endbufp = strtbufp+MAX;
                    198: 
                    199:        if((xptr = fopen(xfile,"r")) == NULL)
                    200:                diag("Cannot open  file",xfile);
                    201: 
                    202:        while(bufp < endbufp && (c = getc(xptr)) != EOF) {
                    203:                if(isabreak(c)) {
                    204:                        if(storeh(hash(strtbufp,bufp),strtbufp))
                    205:                                diag("Too many words",xfile);
                    206:                        *bufp++ = '\0';
                    207:                        strtbufp = bufp;
                    208:                }
                    209:                else {
                    210:                        *bufp++ = (isupper(c)?tolower(c):c);
                    211:                }
                    212:        }
                    213:        if (bufp >= endbufp)
                    214:                diag("Too many words in file",xfile);
                    215:        endbufp = --bufp;
                    216: 
                    217:        /* open output file for sorting */
                    218: 
                    219:        sortfile = mktemp("/tmp/ptxsXXXXX");
                    220:        if((sortptr = fopen(sortfile, "w")) == NULL)
                    221:                diag("Cannot open output for sorting:",sortfile);
                    222: 
                    223: /*     get a line of data and compare each word for
                    224:        inclusion or exclusion in the sort phase
                    225: */
                    226: 
                    227:        if (infile!=0 && (inptr = fopen(infile,"r")) == NULL)
                    228:                diag("Cannot open data: ",infile);
                    229:        while(pend=getline())
                    230:                cmpline(pend);
                    231:        fclose(sortptr);
                    232: 
                    233:        switch (pid = fork()){
                    234: 
                    235:        case -1:        /* cannot fork */
                    236:                diag("Cannot fork",empty);
                    237: 
                    238:        case 0:         /* child */
                    239:                execl(SORT, SORT, sortopt, "+0", "-1", "+1",
                    240:                        sortfile, "-o", sortfile, 0);
                    241: 
                    242:        default:        /* parent */
                    243:                while(wait(&status) != pid);
                    244:        }
                    245: 
                    246: 
                    247:        getsort();
                    248:        onintr();
                    249: }
                    250: 
                    251: msg(s,arg)
                    252: char *s;
                    253: char *arg;
                    254: {
                    255:        fprintf(stderr,"%s %s\n",s,arg);
                    256:        return;
                    257: }
                    258: diag(s,arg)
                    259: char *s, *arg;
                    260: {
                    261: 
                    262:        msg(s,arg);
                    263:        exit(1);
                    264: }
                    265: 
                    266: 
                    267: char *getline()
                    268: {
                    269: 
                    270:        register c;
                    271:        register char *linep;
                    272:        char *endlinep;
                    273: 
                    274: 
                    275:        endlinep= line + mlen;
                    276:        linep = line;
                    277:        /* Throw away leading white space */
                    278: 
                    279:        while(isspace(c=getc(inptr)))
                    280:                ;
                    281:        if(c==EOF)
                    282:                return(0);
                    283:        ungetc(c,inptr);
                    284:        while(( c=getc(inptr)) != EOF) {
                    285:                switch (c) {
                    286: 
                    287:                        case '\t':
                    288:                                if(linep<endlinep)
                    289:                                        *linep++ = ' ';
                    290:                                break;
                    291:                        case '\n':
                    292:                                while(isspace(*--linep));
                    293:                                *++linep = '\n';
                    294:                                return(linep);
                    295:                        default:
                    296:                                if(linep < endlinep)
                    297:                                        *linep++ = c;
                    298:                }
                    299:        }
                    300:        return(0);
                    301: }
                    302: 
                    303: cmpline(pend)
                    304: char *pend;
                    305: {
                    306: 
                    307:        char *pstrt, *pchar, *cp;
                    308:        char **hp;
                    309:        int flag;
                    310: 
                    311:        pchar = line;
                    312:        if(rflag)
                    313:                while(pchar<pend&&!isspace(*pchar))
                    314:                        pchar++;
                    315:        while(pchar<pend){
                    316:        /* eliminate white space */
                    317:                if(isabreak(*pchar++))
                    318:                        continue;
                    319:                pstrt = --pchar;
                    320: 
                    321:                flag = 1;
                    322:                while(flag){
                    323:                        if(isabreak(*pchar)) {
                    324:                                hp = &hasht[hash(pstrt,pchar)];
                    325:                                pchar--;
                    326:                                while(cp = *hp++){
                    327:                                        if(hp == &hasht[MAXT])
                    328:                                                hp = hasht;
                    329:        /* possible match */
                    330:                                        if(cmpword(pstrt,pchar,cp)){
                    331:        /* exact match */
                    332:                                                if(!ignore && only)
                    333:                                                        putline(pstrt,pend);
                    334:                                                flag = 0;
                    335:                                                break;
                    336:                                        }
                    337:                                }
                    338:        /* no match */
                    339:                                if(flag){
                    340:                                        if(ignore || !only)
                    341:                                                putline(pstrt,pend);
                    342:                                        flag = 0;
                    343:                                }
                    344:                        }
                    345:                pchar++;
                    346:                }
                    347:        }
                    348: }
                    349: 
                    350: cmpword(cpp,pend,hpp)
                    351: char *cpp, *pend, *hpp;
                    352: {
                    353:        char c;
                    354: 
                    355:        while(*hpp != '\0'){
                    356:                c = *cpp++;
                    357:                if((isupper(c)?tolower(c):c) != *hpp++)
                    358:                        return(0);
                    359:        }
                    360:        if(--cpp == pend) return(1);
                    361:        return(0);
                    362: }
                    363: 
                    364: putline(strt, end)
                    365: char *strt, *end;
                    366: {
                    367:        char *cp;
                    368: 
                    369:        for(cp=strt; cp<end; cp++)
                    370:                putc(*cp, sortptr);
                    371:        /* Add extra blank before TILDE to sort correctly
                    372:           with -fd option */
                    373:        putc(' ',sortptr);
                    374:        putc(TILDE,sortptr);
                    375:        for (cp=line; cp<strt; cp++)
                    376:                putc(*cp,sortptr);
                    377:        putc('\n',sortptr);
                    378: }
                    379: 
                    380: getsort()
                    381: {
                    382:        register c;
                    383:        register char *tilde, *linep, *ref;
                    384:        char *p1a,*p1b,*p2a,*p2b,*p3a,*p3b,*p4a,*p4b;
                    385:        int w;
                    386:        char *rtrim(), *ltrim();
                    387: 
                    388:        if((sortptr = fopen(sortfile,"r")) == NULL)
                    389:                diag("Cannot open sorted data:",sortfile);
                    390: 
                    391:        halflen = (llen-gutter)/2;
                    392:        linep = line;
                    393:        while((c = getc(sortptr)) != EOF) {
                    394:                switch(c) {
                    395: 
                    396:                case TILDE:
                    397:                        tilde = linep;
                    398:                        break;
                    399: 
                    400:                case '\n':
                    401:                        while(isspace(linep[-1]))
                    402:                                linep--;
                    403:                        ref = tilde;
                    404:                        if(rflag) {
                    405:                                while(ref<linep&&!isspace(*ref))
                    406:                                        ref++;
                    407:                                *ref++ = 0;
                    408:                        }
                    409:                /* the -1 is an overly conservative test to leave
                    410:                   space for the / that signifies truncation*/
                    411:                        p3b = rtrim(p3a=line,tilde,halflen-1);
                    412:                        if(p3b-p3a>halflen-1)
                    413:                                p3b = p3a+halflen-1;
                    414:                        p2a = ltrim(ref,p2b=linep,halflen-1);
                    415:                        if(p2b-p2a>halflen-1)
                    416:                                p2a = p2b-halflen-1;
                    417:                        p1b = rtrim(p1a=p3b+(isspace(p3b[0])!=0),tilde,
                    418:                                w=halflen-(p2b-p2a)-gap);
                    419:                        if(p1b-p1a>w)
                    420:                                p1b = p1a;
                    421:                        p4a = ltrim(ref,p4b=p2a-(isspace(p2a[-1])!=0),
                    422:                                w=halflen-(p3b-p3a)-gap);
                    423:                        if(p4b-p4a>w)
                    424:                                p4a = p4b;
                    425:                        fprintf(outptr,".xx \"");
                    426:                        putout(p1a,p1b);
                    427:        /* tilde-1 to account for extra space before TILDE */
                    428:                        if(p1b!=(tilde-1) && p1a!=p1b)
                    429:                                fprintf(outptr,"/");
                    430:                        fprintf(outptr,"\" \"");
                    431:                        if(p4a==p4b && p2a!=ref && p2a!=p2b)
                    432:                                fprintf(outptr,"/");
                    433:                        putout(p2a,p2b);
                    434:                        fprintf(outptr,"\" \"");
                    435:                        putout(p3a,p3b);
                    436:        /* ++p3b to account for extra blank after TILDE */
                    437:        /* ++p3b to account for extra space before TILDE */
                    438:                        if(p1a==p1b && ++p3b!=tilde)
                    439:                                fprintf(outptr,"/");
                    440:                        fprintf(outptr,"\" \"");
                    441:                        if(p1a==p1b && p4a!=ref && p4a!=p4b)
                    442:                                fprintf(outptr,"/");
                    443:                        putout(p4a,p4b);
                    444:                        if(rflag)
                    445:                                fprintf(outptr,"\" %s\n",tilde);
                    446:                        else
                    447:                                fprintf(outptr,"\"\n");
                    448:                        linep = line;
                    449:                        break;
                    450: 
                    451:                case '"':
                    452:        /* put double " for "  */
                    453:                        *linep++ = c;
                    454:                default:
                    455:                        *linep++ = c;
                    456:                }
                    457:        }
                    458: }
                    459: 
                    460: char *rtrim(a,c,d)
                    461: char *a,*c;
                    462: {
                    463:        char *b,*x;
                    464:        b = c;
                    465:        for(x=a+1; x<=c&&x-a<=d; x++)
                    466:                if((x==c||isspace(x[0]))&&!isspace(x[-1]))
                    467:                        b = x;
                    468:        if(b<c&&!isspace(b[0]))
                    469:                b++;
                    470:        return(b);
                    471: }
                    472: 
                    473: char *ltrim(c,b,d)
                    474: char *c,*b;
                    475: {
                    476:        char *a,*x;
                    477:        a = c;
                    478:        for(x=b-1; x>=c&&b-x<=d; x--)
                    479:                if(!isspace(x[0])&&(x==c||isspace(x[-1])))
                    480:                        a = x;
                    481:        if(a>c&&!isspace(a[-1]))
                    482:                a--;
                    483:        return(a);
                    484: }
                    485: 
                    486: putout(strt,end)
                    487: char *strt, *end;
                    488: {
                    489:        char *cp;
                    490: 
                    491:        cp = strt;
                    492: 
                    493:        for(cp=strt; cp<end; cp++) {
                    494:                putc(*cp,outptr);
                    495:        }
                    496: }
                    497: 
                    498: onintr()
                    499: {
                    500: 
                    501:        if(*sortfile)
                    502:                unlink(sortfile);
                    503:        exit(1);
                    504: }
                    505: 
                    506: hash(strtp,endp)
                    507: char *strtp, *endp;
                    508: {
                    509:        char *cp, c;
                    510:        int i, j, k;
                    511: 
                    512:        /* Return zero hash number for single letter words */
                    513:        if((endp - strtp) == 1)
                    514:                return(0);
                    515: 
                    516:        cp = strtp;
                    517:        c = *cp++;
                    518:        i = (isupper(c)?tolower(c):c);
                    519:        c = *cp;
                    520:        j = (isupper(c)?tolower(c):c);
                    521:        i = i*j;
                    522:        cp = --endp;
                    523:        c = *cp--;
                    524:        k = (isupper(c)?tolower(c):c);
                    525:        c = *cp;
                    526:        j = (isupper(c)?tolower(c):c);
                    527:        j = k*j;
                    528: 
                    529:        k = (i ^ (j>>2)) & MASK;
                    530:        return(k);
                    531: }
                    532: 
                    533: storeh(num,strtp)
                    534: int num;
                    535: char *strtp;
                    536: {
                    537:        int i;
                    538: 
                    539:        for(i=num; i<MAXT; i++) {
                    540:                if(hasht[i] == 0) {
                    541:                        hasht[i] = strtp;
                    542:                        return(0);
                    543:                }
                    544:        }
                    545:        for(i=0; i<num; i++) {
                    546:                if(hasht[i] == 0) {
                    547:                        hasht[i] = strtp;
                    548:                        return(0);
                    549:                }
                    550:        }
                    551:        return(1);
                    552: }

unix.superglobalmegacorp.com

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