1: # include <stdio.h> 2: /* 3: * vsort - Sort troff output for versatec to reduce amount of reverse leading 4: */ 5: 6: #define NULL 0 7: 8: double atof(); 9: char *calloc(); 10: 11: FILE *in,*out; 12: 13: int skipfirst = 1; /* skip the first leading so start at top of page */ 14: int cpsize = 02; /* Funny sizes */ 15: struct point_sizes 16: { 17: int stupid_code; 18: int real_code; 19: } point_sizes[] = 20: { 21: 010, 6, 22: 0, 7, 23: 01, 8, 24: 07, 9, 25: 02, 10, 26: 03, 11, 27: 04, 12, 28: 05, 14, 29: 0211, 16, 30: 06, 18, 31: 0212, 20, 32: 0213, 22, 33: 0214, 24, 34: 0215, 28, 35: 0216, 36, 36: 0, 0 37: }; 38: 39: int pagelength = 144 * 11; /* in Leading units */ 40: int pagemod; /* horizontal page number (for versatec) */ 41: #define MODOFF 3672 /* 432 * 8.5 */ 42: 43: int esc, lead, back, verd, mcase, railmag; 44: int col, row; 45: int pstart = 0; /* Means a startline is pending */ 46: 47: int oback, omcase, orailmag, ocol, orow; 48: int opsize = 02; 49: 50: struct lstate 51: { 52: int col; 53: int psize; 54: char railmag; 55: char verd; 56: char back; 57: char mcase; 58: }; 59: 60: struct line 61: { 62: struct line *nextp; 63: struct line *lastp; 64: int len; 65: int row; 66: struct lstate start; 67: struct lstate end; 68: char *codep; 69: }; 70: 71: struct line *head; 72: struct line *tail; 73: struct line cline; 74: 75: #define TBUFLEN 1024 76: char *codep; 77: char tbuf[TBUFLEN]; 78: 79: char wide = 0; 80: char nocutmarks = 0; /* Remove lines that seem to be cut marks. */ 81: 82: #define iscutmark(ch) (ch == 023 || ch == 040 || ch == 061) 83: main(argc, argv) 84: int argc; 85: char *argv[]; 86: { 87: register i; 88: 89: for(i = 3; i < 15; i++) 90: close(i); 91: while (argc > 1 && argv[1][0] == '-') { 92: switch (argv[1][1]) { 93: case 'l': { 94: float f = 144 * atof(argv[1] + 2); 95: if (f < 144) { 96: error("bad length"); 97: exit(1); 98: } 99: pagelength = f; 100: break; 101: } 102: 103: case 'W': 104: wide++; 105: break; 106: 107: case 'c': 108: nocutmarks++; 109: break; 110: } 111: argc--; argv++; 112: } 113: out = stdout; 114: if(argc > 1) 115: { 116: while(--argc) 117: { 118: argv++; 119: if((in=fopen(argv[0], "r")) == NULL) 120: perror("vsort"); 121: else { 122: ofile(); 123: fclose(in); 124: } 125: } 126: } 127: else 128: { 129: in = stdin; 130: ofile(); 131: } 132: exit(0); 133: } 134: 135: ofile() 136: { 137: register int c; 138: static int initialized; 139: 140: while((c = getch()) != -1) { 141: if(!c) 142: continue; 143: if(c & 0200) /* escape (left/right) */ 144: { 145: if(!pstart) 146: stuffc(c); 147: esc += (~c) & 0177; 148: continue; 149: } 150: if(esc) 151: { 152: if(back) 153: esc = -esc; 154: col += esc; 155: esc = 0; 156: } 157: if((c & 0377) < 0100) /* Purely for efficiency */ 158: goto normal_char; 159: switch(c) { 160: case 0100: 161: if(initialized++) { 162: termline(); 163: linesflush(); /* Omit trailing leading. */ 164: return; 165: } 166: row = 0; 167: col = 0; esc = 0; 168: lead = 0; 169: verd = 0; back = 0; mcase = 0; 170: railmag = 0; 171: ocol = 0; 172: orow = 0; 173: oback = 0; omcase = 0; 174: orailmag = 0; 175: if(loadfont(railmag, cpsize) < 0) 176: error("init"); 177: startline(); 178: putc(0100, out); /* Dont stuff it guys */ 179: break; 180: case 0101: /* lower rail */ 181: crail(railmag &= ~01); 182: if(!pstart) 183: stuffc(c); 184: break; 185: case 0102: /* upper rail */ 186: crail(railmag |= 01); 187: if(!pstart) 188: stuffc(c); 189: break; 190: case 0103: /* upper mag */ 191: crail(railmag |= 02); 192: if(!pstart) 193: stuffc(c); 194: break; 195: case 0104: /* lower mag */ 196: crail(railmag &= ~02); 197: if(!pstart) 198: stuffc(c); 199: break; 200: case 0105: /* lower case */ 201: mcase = 0; 202: if(!pstart) 203: stuffc(c); 204: break; 205: case 0106: /* upper case */ 206: mcase = 1; 207: if(!pstart) 208: stuffc(c); 209: break; 210: case 0107: /* escape forward */ 211: back = 0; 212: if(!pstart) 213: stuffc(c); 214: break; 215: case 0110: /* escape backwards */ 216: back = 1; 217: if(!pstart) 218: stuffc(c); 219: break; 220: case 0111: /* stop */ 221: stuffc(c); 222: break; 223: case 0112: /* lead forward */ 224: verd = 0; 225: break; 226: case 0113: /* undefined */ 227: break; 228: case 0114: /* lead backward */ 229: verd = 1; 230: break; 231: case 0115: /* undefined */ 232: case 0116: 233: case 0117: 234: break; 235: default: 236: if((c & 0340) == 0140) /* leading */ 237: { 238: termline(); 239: lead = (~c) & 037; 240: if(verd) 241: lead = -lead; 242: if (skipfirst > 0) { 243: skipfirst--; 244: continue; 245: } 246: row += lead; 247: if (row >= pagelength) { 248: if (wide) { 249: if (pagemod == 3) { 250: allflush(); 251: col %= MODOFF; 252: pagemod = 0; 253: } else { 254: pagemod++; 255: col += MODOFF; 256: row -= pagelength; 257: } 258: } else { 259: allflush(); 260: } 261: } 262: if (wide && row < 0 && pagemod) { 263: pagemod--; 264: col -= MODOFF; 265: row += pagelength; 266: } 267: pstart++; 268: continue; 269: } 270: if((c & 0360) == 0120) /* size change */ 271: { 272: if(!pstart) 273: stuffc(c); 274: col += stupidadj(c & 017, cpsize); 275: loadfont(railmag, c & 017); 276: continue; 277: } 278: if(c & 0300) 279: continue; 280: normal_char: 281: c = (c & 077); 282: stuffc(c); 283: } 284: } /* End of while loop reading chars. */ 285: termline(); 286: linesflush(); /* don't put out trailing leading. */ 287: } 288: 289: 290: int peekc; 291: getch() { 292: register c; 293: if(peekc) { 294: c = peekc; 295: peekc = 0; 296: return(c); 297: } 298: return(getc(in)); 299: } 300: 301: ungetc(c) { 302: peekc = c; 303: } 304: 305: 306: error(s) 307: char *s; 308: { 309: 310: fflush(out); 311: fprintf(stderr, stderr, "vsort: %s\n", s); 312: } 313: 314: crail(nrail) 315: register int nrail; 316: { 317: register int psize; 318: 319: psize = cpsize; 320: loadfont(nrail, psize); 321: } 322: 323: loadfont(fnum, size) 324: register int fnum; 325: register int size; 326: { 327: 328: cpsize = size; 329: return(0); 330: } 331: 332: startline() 333: { 334: 335: if(pstart != 0) { 336: cline.row = row; 337: return; 338: } 339: cline.len = 0; 340: cline.row = row; 341: cline.start.col = col; 342: cline.start.psize = cpsize; 343: cline.start.mcase = mcase; 344: cline.start.back = back; 345: cline.start.verd = verd; 346: cline.start.railmag = railmag; 347: codep = tbuf; 348: } 349: 350: termline() 351: { 352: register struct line *linep; 353: register char *allp; 354: register char *cp; 355: int i; 356: 357: if(pstart != 0) 358: return; 359: if((allp = calloc(sizeof *linep,1)) == ((char *)-1)) 360: error("alloc"); 361: linep = (struct line *)allp; 362: linep->end.col = col; 363: linep->end.psize = cpsize; 364: linep->end.mcase = mcase; 365: linep->end.back = back; 366: linep->end.verd = verd; 367: linep->end.railmag = railmag; 368: linep->start.col = cline.start.col; 369: linep->start.psize = cline.start.psize; 370: linep->start.mcase = cline.start.mcase; 371: linep->start.back = cline.start.back; 372: linep->start.verd = cline.start.verd; 373: linep->start.railmag = cline.start.railmag; 374: linep->len = cline.len; 375: linep->row = row; 376: if((allp = calloc(cline.len,1)) == ((char *)-1)) 377: error("alloc"); 378: linep->codep = allp; 379: cp = tbuf; 380: for(i = 0; i < cline.len; i++) 381: *allp++ = *cp++; 382: sortin(linep); 383: } 384: 385: sortin(linep) 386: register struct line *linep; 387: { 388: register struct line *clp; 389: 390: if((clp = tail) == NULL) { 391: head = tail = linep; 392: linep->lastp = linep->nextp = NULL; 393: return; 394: } 395: while(clp != NULL && clp->row > linep->row) 396: clp = clp->lastp; 397: if(clp == tail) { 398: linep->lastp = tail; 399: linep->nextp = NULL; 400: tail->nextp = linep; 401: tail = linep; 402: } else 403: if(clp == NULL) /* goes at head of list */ { 404: linep->lastp = NULL; 405: linep->nextp = head; 406: head->lastp = linep; 407: head = linep; 408: } else { 409: linep->lastp = clp; 410: linep->nextp = clp->nextp; 411: clp->nextp->lastp = linep; 412: clp->nextp = linep; 413: } 414: } 415: 416: stuffc(code) 417: register int code; 418: { 419: 420: if(pstart != 0) { 421: pstart = 0; 422: startline(); 423: } 424: if(cline.len > TBUFLEN) { 425: termline(); 426: startline(); 427: } 428: *codep++ = code; 429: cline.len++; 430: } 431: 432: 433: allflush() /* Flush all lines, then put out trailing leading. */ 434: { 435: 436: linesflush(); 437: if (row > orow) { 438: ptlead(row - orow); 439: } 440: row -= pagelength; 441: orow = row; 442: } 443: 444: linesflush() 445: { 446: while(head != NULL) 447: sendline(); 448: } 449: 450: sendline() 451: { 452: register char *cp; 453: register struct line *linep; 454: register int i; 455: register int remcutmark; 456: 457: if ((linep = head) == NULL) 458: return; 459: 460: /* Heuristic: if cut marks are present, they are on lines whose 461: * row numbers are <= 24 or >= pagelength-4. 462: * Cut marks are formed from 023's, 040's, or 061's. 463: * There are 2 or 4 of them on a line, and no other characters 464: * are present. cutmark(...) checks this. 465: * Cutmark lines are removed if nocutmarks is true. 466: * Three leading units are removed, too, to compensate for 467: * varian output not being exactly 1584 leading units long. 468: */ 469: #ifdef DUMPLINE 470: dumpline(linep); 471: #endif 472: remcutmark = 0; 473: if (nocutmarks 474: && (linep->row <= 24 || linep->row >= pagelength-4) 475: && cutmark(linep)) { 476: remcutmark++; 477: orow = orow + 3; 478: } 479: if(linep->start.railmag != orailmag) 480: ptrail(linep->start.railmag); 481: if(linep->start.psize != opsize) 482: ptsize(linep->start.psize); 483: if(linep->start.mcase != omcase) 484: ptmcase(); 485: if(linep->row > orow) /* lead forward */ 486: ptlead(linep->row - orow); 487: if(linep->start.col != ocol) 488: ptesc(linep->start.col-ocol); 489: if(linep->start.back != oback) 490: ptback(); 491: cp = linep->codep; 492: if (remcutmark) { 493: for(i = 0; i < linep->len; i++) { 494: if (!iscutmark(*cp)) /* iscutmark is a macro. */ 495: putc(*cp++, out); 496: else 497: cp++; 498: } 499: } else { 500: for(i = 0; i < linep->len; i++) 501: putc(*cp++, out); 502: } 503: 504: orow = linep->row; 505: orailmag = linep->end.railmag; 506: opsize = linep->end.psize; 507: omcase = linep->end.mcase; 508: ocol = linep->end.col; 509: oback = linep->end.back; 510: head = linep->nextp; 511: 512: cfree(linep->codep); 513: cfree(linep); 514: if(head == NULL) 515: tail = NULL; 516: else 517: head->lastp = NULL; 518: } 519: 520: int 521: cutmark(linep) 522: register struct line *linep; 523: { 524: register int i; 525: register int ch; 526: register int dashcount = 0; 527: register int firstdash = 0; 528: 529: for (i = 0; i < linep->len; i++) { 530: ch = linep->codep[i] & 0377; 531: if (ch < 0100) { 532: if (iscutmark(ch)) { 533: if (firstdash == 0) 534: firstdash = ch; 535: if (ch != firstdash) 536: return (0); 537: dashcount++; 538: } else 539: return(0); 540: } 541: } 542: /* Must have 2 or 4 dashes on a line. */ 543: return (dashcount == 4 || dashcount == 2); 544: } 545: 546: ptrail(rlmg) 547: register int rlmg; 548: { 549: 550: if((rlmg & 01) != (orailmag & 01)) 551: putc((rlmg & 01) ? 0102:0101, out); /* rail */ 552: if((rlmg & 02) != (orailmag & 02)) 553: putc((rlmg & 02) ? 0103:0104, out); /* mag */ 554: } 555: 556: ptback() 557: { 558: 559: putc(oback ? 0107:0110, out); 560: oback = !oback; 561: } 562: 563: ptsize(size) 564: register int size; 565: { 566: 567: putc(0120 | (size & 017), out); 568: ptesc(-stupidadj(size, opsize)); 569: } 570: 571: stupidadj(code, lcode) 572: register int code; 573: int lcode; 574: { 575: register struct point_sizes *psp; 576: register struct point_sizes *lpsp; 577: 578: psp = point_sizes; 579: while(psp->real_code != 0) { 580: if((psp->stupid_code & 017) == code) 581: break; 582: psp++; 583: } 584: lpsp = point_sizes; 585: while(lpsp->real_code != 0) { 586: if((lpsp->stupid_code & 017) == lcode) 587: break; 588: lpsp++; 589: } 590: code = 0; 591: if(!(lpsp->stupid_code & 0200) && (psp->stupid_code & 0200)) 592: code = -55; 593: else 594: if((lpsp->stupid_code & 0200) && !(psp->stupid_code & 0200)) 595: code = 55; 596: return(code); 597: } 598: 599: ptmcase() 600: { 601: 602: putc(omcase ? 0105:0106, out); 603: } 604: 605: ptesc(escc) 606: register int escc; 607: { 608: 609: if((escc < 0 && !oback ) || (escc >= 0 && oback)) 610: ptback(); 611: escc = abs(escc); 612: while(escc > 0177) { 613: putc(0200, out); 614: escc -= 0177; 615: } 616: if(escc) 617: putc(0200 | ((~escc) & 0177), out); 618: } 619: 620: ptlead(leadd) 621: register int leadd; 622: { 623: 624: while(leadd > 037) { 625: putc(0140, out); 626: leadd -= 037; 627: } 628: if(leadd) 629: putc(0140 | ((~leadd) & 037), out); 630: } 631: 632: #ifdef DUMPLINE 633: dumpline(linep) 634: register struct line *linep; 635: { 636: int i; 637: 638: fprintf(stderr, "row: %d\n", linep->row); 639: fprintf(stderr, "start.col: %o ", linep->start.col & 0377); 640: fprintf(stderr, ".psize: %o ", linep->start.psize); 641: fprintf(stderr, ".railmag: %o ", linep->start.railmag); 642: fprintf(stderr, ".verd: %o ", linep->start.verd); 643: fprintf(stderr, ".back: %o ", linep->start.back); 644: fprintf(stderr, ".mcase: %o\n", linep->start.mcase); 645: fprintf(stderr, " end.col: %o ", linep->end.col); 646: fprintf(stderr, ".psize: %o ", linep->end.psize); 647: fprintf(stderr, ".railmag: %o ", linep->end.railmag); 648: fprintf(stderr, ".verd: %o ", linep->end.verd); 649: fprintf(stderr, ".back: %o ", linep->end.back); 650: fprintf(stderr, ".mcase: %o\n", linep->end.mcase); 651: fprintf(stderr, "len: %d\t", linep->len); 652: fprintf(stderr, "codep: "); 653: for (i = 0; i < linep->len; i++) 654: fprintf(stderr, "%o ", linep->codep[i] & 0377); 655: fprintf(stderr, "\n\n"); 656: } 657: #endif