Annotation of 43BSDTahoe/usr.bin/ptx.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char *sccsid = "@(#)ptx.c       4.3 (Berkeley) 12/2/87";
                      3: #endif /* not lint */
                      4: 
                      5: /*     permuted title index
                      6:        ptx [-t] [-i ignore] [-o only] [-w num] [-f] [input] [output]
                      7:        Ptx reads the input file and permutes on words in it.
                      8:        It excludes all words in the ignore file.
                      9:        Alternately it includes words in the only file.
                     10:        if neither is given it excludes the words in /usr/lib/eign.
                     11: 
                     12:        The width of the output line can be changed to num
                     13:        characters.  If omitted 72 is default unless troff than 100.
                     14:        the -f flag tells the program to fold the output
                     15:        the -t flag says the output is for troff and the
                     16:        output is then wider.
                     17: 
                     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:        if(sortfile)
                    249:                unlink(sortfile);
                    250:        exit(0);
                    251: }
                    252: 
                    253: msg(s,arg)
                    254: char *s;
                    255: char *arg;
                    256: {
                    257:        fprintf(stderr,"%s %s\n",s,arg);
                    258:        return;
                    259: }
                    260: diag(s,arg)
                    261: char *s, *arg;
                    262: {
                    263: 
                    264:        msg(s,arg);
                    265:        exit(1);
                    266: }
                    267: 
                    268: 
                    269: char *getline()
                    270: {
                    271: 
                    272:        register c;
                    273:        register char *linep;
                    274:        char *endlinep;
                    275: 
                    276: 
                    277:        endlinep= line + mlen;
                    278:        linep = line;
                    279:        /* Throw away leading white space */
                    280: 
                    281:        while(isspace(c=getc(inptr)))
                    282:                ;
                    283:        if(c==EOF)
                    284:                return(0);
                    285:        ungetc(c,inptr);
                    286:        while(( c=getc(inptr)) != EOF) {
                    287:                switch (c) {
                    288: 
                    289:                        case '\t':
                    290:                                if(linep<endlinep)
                    291:                                        *linep++ = ' ';
                    292:                                break;
                    293:                        case '\n':
                    294:                                while(isspace(*--linep));
                    295:                                *++linep = '\n';
                    296:                                return(linep);
                    297:                        default:
                    298:                                if(linep < endlinep)
                    299:                                        *linep++ = c;
                    300:                }
                    301:        }
                    302:        return(0);
                    303: }
                    304: 
                    305: cmpline(pend)
                    306: char *pend;
                    307: {
                    308: 
                    309:        char *pstrt, *pchar, *cp;
                    310:        char **hp;
                    311:        int flag;
                    312: 
                    313:        pchar = line;
                    314:        if(rflag)
                    315:                while(pchar<pend&&!isspace(*pchar))
                    316:                        pchar++;
                    317:        while(pchar<pend){
                    318:        /* eliminate white space */
                    319:                if(isabreak(*pchar++))
                    320:                        continue;
                    321:                pstrt = --pchar;
                    322: 
                    323:                flag = 1;
                    324:                while(flag){
                    325:                        if(isabreak(*pchar)) {
                    326:                                hp = &hasht[hash(pstrt,pchar)];
                    327:                                pchar--;
                    328:                                while(cp = *hp++){
                    329:                                        if(hp == &hasht[MAXT])
                    330:                                                hp = hasht;
                    331:        /* possible match */
                    332:                                        if(cmpword(pstrt,pchar,cp)){
                    333:        /* exact match */
                    334:                                                if(!ignore && only)
                    335:                                                        putline(pstrt,pend);
                    336:                                                flag = 0;
                    337:                                                break;
                    338:                                        }
                    339:                                }
                    340:        /* no match */
                    341:                                if(flag){
                    342:                                        if(ignore || !only)
                    343:                                                putline(pstrt,pend);
                    344:                                        flag = 0;
                    345:                                }
                    346:                        }
                    347:                pchar++;
                    348:                }
                    349:        }
                    350: }
                    351: 
                    352: cmpword(cpp,pend,hpp)
                    353: char *cpp, *pend, *hpp;
                    354: {
                    355:        char c;
                    356: 
                    357:        while(*hpp != '\0'){
                    358:                c = *cpp++;
                    359:                if((isupper(c)?tolower(c):c) != *hpp++)
                    360:                        return(0);
                    361:        }
                    362:        if(--cpp == pend) return(1);
                    363:        return(0);
                    364: }
                    365: 
                    366: putline(strt, end)
                    367: char *strt, *end;
                    368: {
                    369:        char *cp;
                    370: 
                    371:        for(cp=strt; cp<end; cp++)
                    372:                putc(*cp, sortptr);
                    373:        /* Add extra blank before TILDE to sort correctly
                    374:           with -fd option */
                    375:        putc(' ',sortptr);
                    376:        putc(TILDE,sortptr);
                    377:        for (cp=line; cp<strt; cp++)
                    378:                putc(*cp,sortptr);
                    379:        putc('\n',sortptr);
                    380: }
                    381: 
                    382: getsort()
                    383: {
                    384:        register c;
                    385:        register char *tilde, *linep, *ref;
                    386:        char *p1a,*p1b,*p2a,*p2b,*p3a,*p3b,*p4a,*p4b;
                    387:        int w;
                    388:        char *rtrim(), *ltrim();
                    389: 
                    390:        if((sortptr = fopen(sortfile,"r")) == NULL)
                    391:                diag("Cannot open sorted data:",sortfile);
                    392: 
                    393:        halflen = (llen-gutter)/2;
                    394:        linep = line;
                    395:        while((c = getc(sortptr)) != EOF) {
                    396:                switch(c) {
                    397: 
                    398:                case TILDE:
                    399:                        tilde = linep;
                    400:                        break;
                    401: 
                    402:                case '\n':
                    403:                        while(isspace(linep[-1]))
                    404:                                linep--;
                    405:                        ref = tilde;
                    406:                        if(rflag) {
                    407:                                while(ref<linep&&!isspace(*ref))
                    408:                                        ref++;
                    409:                                *ref++ = 0;
                    410:                        }
                    411:                /* the -1 is an overly conservative test to leave
                    412:                   space for the / that signifies truncation*/
                    413:                        p3b = rtrim(p3a=line,tilde,halflen-1);
                    414:                        if(p3b-p3a>halflen-1)
                    415:                                p3b = p3a+halflen-1;
                    416:                        p2a = ltrim(ref,p2b=linep,halflen-1);
                    417:                        if(p2b-p2a>halflen-1)
                    418:                                p2a = p2b-halflen-1;
                    419:                        p1b = rtrim(p1a=p3b+(isspace(p3b[0])!=0),tilde,
                    420:                                w=halflen-(p2b-p2a)-gap);
                    421:                        if(p1b-p1a>w)
                    422:                                p1b = p1a;
                    423:                        p4a = ltrim(ref,p4b=p2a-(isspace(p2a[-1])!=0),
                    424:                                w=halflen-(p3b-p3a)-gap);
                    425:                        if(p4b-p4a>w)
                    426:                                p4a = p4b;
                    427:                        fprintf(outptr,".xx \"");
                    428:                        putout(p1a,p1b);
                    429:        /* tilde-1 to account for extra space before TILDE */
                    430:                        if(p1b!=(tilde-1) && p1a!=p1b)
                    431:                                fprintf(outptr,"/");
                    432:                        fprintf(outptr,"\" \"");
                    433:                        if(p4a==p4b && p2a!=ref && p2a!=p2b)
                    434:                                fprintf(outptr,"/");
                    435:                        putout(p2a,p2b);
                    436:                        fprintf(outptr,"\" \"");
                    437:                        putout(p3a,p3b);
                    438:        /* ++p3b to account for extra blank after TILDE */
                    439:        /* ++p3b to account for extra space before TILDE */
                    440:                        if(p1a==p1b && ++p3b!=tilde)
                    441:                                fprintf(outptr,"/");
                    442:                        fprintf(outptr,"\" \"");
                    443:                        if(p1a==p1b && p4a!=ref && p4a!=p4b)
                    444:                                fprintf(outptr,"/");
                    445:                        putout(p4a,p4b);
                    446:                        if(rflag)
                    447:                                fprintf(outptr,"\" %s\n",tilde);
                    448:                        else
                    449:                                fprintf(outptr,"\"\n");
                    450:                        linep = line;
                    451:                        break;
                    452: 
                    453:                case '"':
                    454:        /* put double " for "  */
                    455:                        *linep++ = c;
                    456:                default:
                    457:                        *linep++ = c;
                    458:                }
                    459:        }
                    460: }
                    461: 
                    462: char *rtrim(a,c,d)
                    463: char *a,*c;
                    464: {
                    465:        char *b,*x;
                    466:        b = c;
                    467:        for(x=a+1; x<=c&&x-a<=d; x++)
                    468:                if((x==c||isspace(x[0]))&&!isspace(x[-1]))
                    469:                        b = x;
                    470:        if(b<c&&!isspace(b[0]))
                    471:                b++;
                    472:        return(b);
                    473: }
                    474: 
                    475: char *ltrim(c,b,d)
                    476: char *c,*b;
                    477: {
                    478:        char *a,*x;
                    479:        a = c;
                    480:        for(x=b-1; x>=c&&b-x<=d; x--)
                    481:                if(!isspace(x[0])&&(x==c||isspace(x[-1])))
                    482:                        a = x;
                    483:        if(a>c&&!isspace(a[-1]))
                    484:                a--;
                    485:        return(a);
                    486: }
                    487: 
                    488: putout(strt,end)
                    489: char *strt, *end;
                    490: {
                    491:        char *cp;
                    492: 
                    493:        cp = strt;
                    494: 
                    495:        for(cp=strt; cp<end; cp++) {
                    496:                putc(*cp,outptr);
                    497:        }
                    498: }
                    499: 
                    500: onintr()
                    501: {
                    502: 
                    503:        if(sortfile)
                    504:                unlink(sortfile);
                    505:        exit(1);
                    506: }
                    507: 
                    508: hash(strtp,endp)
                    509: char *strtp, *endp;
                    510: {
                    511:        char *cp, c;
                    512:        int i, j, k;
                    513: 
                    514:        /* Return zero hash number for single letter words */
                    515:        if((endp - strtp) == 1)
                    516:                return(0);
                    517: 
                    518:        cp = strtp;
                    519:        c = *cp++;
                    520:        i = (isupper(c)?tolower(c):c);
                    521:        c = *cp;
                    522:        j = (isupper(c)?tolower(c):c);
                    523:        i = i*j;
                    524:        cp = --endp;
                    525:        c = *cp--;
                    526:        k = (isupper(c)?tolower(c):c);
                    527:        c = *cp;
                    528:        j = (isupper(c)?tolower(c):c);
                    529:        j = k*j;
                    530: 
                    531:        k = (i ^ (j>>2)) & MASK;
                    532:        return(k);
                    533: }
                    534: 
                    535: storeh(num,strtp)
                    536: int num;
                    537: char *strtp;
                    538: {
                    539:        int i;
                    540: 
                    541:        for(i=num; i<MAXT; i++) {
                    542:                if(hasht[i] == 0) {
                    543:                        hasht[i] = strtp;
                    544:                        return(0);
                    545:                }
                    546:        }
                    547:        for(i=0; i<num; i++) {
                    548:                if(hasht[i] == 0) {
                    549:                        hasht[i] = strtp;
                    550:                        return(0);
                    551:                }
                    552:        }
                    553:        return(1);
                    554: }

unix.superglobalmegacorp.com

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