Annotation of 3BSD/cmd/ptx.c, revision 1.1

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

unix.superglobalmegacorp.com

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