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