|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.