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