Annotation of 3BSD/cmd/ptx.c, revision 1.1.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.