1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 /* 43 * drive hp2621 terminal 44 * just to see stuff quickly. like troff -a 45 */ 46 47 /* 48 output language from troff: 49 all numbers are character strings 50 51 sn size in points 52 fn font as number from 1-n 53 cx ascii character x 54 Cxyz funny char xyz. terminated by white space 55 Hn go to absolute horizontal position n 56 Vn go to absolute vertical position n (down is positive) 57 hn go n units horizontally (relative) 58 vn ditto vertically 59 nnc move right nn (exactly 2 digits!), then print c 60 (this wart is an optimization that shrinks output file size 61 about 35% and run-time about 15% while preserving ascii-ness) 62 w paddable word space - no action needed 63 nb a end of line (information only -- no action needed) 64 b = space before line, a = after 65 pn begin page n 66 #...\n comment 67 Dt ...\n draw operation 't': 68 Dl x y line from here by x,y 69 Dc d circle of diameter d with left side here 70 De x y ellipse of axes x,y with left side here 71 Da x y u v arc counter-clockwise from here to u,v from center 72 with center x,y from here 73 D~ x y x y ... wiggly line by x,y then x,y ... 74 x ...\n device control functions: 75 x i init 76 x T s name of device is s 77 x r n h v resolution is n/inch 78 h = min horizontal motion, v = min vert 79 x p pause (can restart) 80 x s stop -- done for ever 81 x t generate trailer 82 x f n s font position n contains font s 83 x H n set character height to n 84 x S n set character slant to n 85 86 Subcommands like "i" are often spelled out like "init". 87 */ 88 89 #include <stdio.h> 90 #include <signal.h> 91 #include <ctype.h> 92 93 #include "dev.h" 94 #define NFONT 10 95 96 int output = 0; /* do we do output at all? */ 97 int nolist = 0; /* output page list if > 0 */ 98 int olist[20]; /* pairs of page numbers */ 99 100 int erase = 1; 101 float aspect = 1.5; /* default aspect ratio */ 102 int wflag = 0; /* wait, looping, for new input if on */ 103 void (*sigint)(); 104 void (*sigquit)(); 105 void done(); 106 107 struct dev dev; 108 struct font *fontbase[NFONT]; 109 short psizes[] ={ 11, 16, 22, 36, 0}; /* approx sizes available */ 110 short *pstab = psizes; 111 int nsizes = 1; 112 int nfonts; 113 int smnt; /* index of first special font */ 114 int nchtab; 115 char *chname; 116 short *chtab; 117 char *fitab[NFONT]; 118 char *widthtab[NFONT]; /* widtab would be a better name */ 119 char *codetab[NFONT]; /* device codes */ 120 121 #define FATAL 1 122 #define BMASK 0377 123 int dbg = 0; 124 int res = 972; /* input assumed computed according to this resolution */ 125 /* initial value to avoid 0 divide */ 126 FILE *tf = stdout; /* output file */ 127 char *fontdir = "/usr/lib/font"; 128 extern char devname[]; 129 130 FILE *fp = stdin; /* input file pointer */ 131 132 int nowait = 0; /* 0 => wait at bottom of each page */ 133 134 int 135 main(int argc, char **argv) 136 { 137 char buf[BUFSIZ]; 138 139 setbuf(stdout, buf); 140 while (argc > 1 && argv[1][0] == '-') { 141 switch (argv[1][1]) { 142 case 'a': 143 aspect = atof(&argv[1][2]); 144 break; 145 case 'e': 146 erase = 0; 147 break; 148 case 'o': 149 outlist(&argv[1][2]); 150 break; 151 case 'd': 152 dbg = atoi(&argv[1][2]); 153 if (dbg == 0) dbg = 1; 154 break; 155 case 'w': /* no wait at bottom of page */ 156 nowait = 1; 157 break; 158 } 159 argc--; 160 argv++; 161 } 162 163 if (argc <= 1) 164 conv(stdin); 165 else 166 while (--argc > 0) { 167 if (strcmp(*++argv, "-") == 0) 168 fp = stdin; 169 else if ((fp = fopen(*argv, "r")) == NULL) 170 error(FATAL, "can't open %s", *argv); 171 conv(fp); 172 fclose(fp); 173 } 174 done(); 175 176 return (0); 177 } 178 179 int 180 outlist(s) /* process list of page numbers to be printed */ 181 char *s; 182 { 183 int n1, n2, i; 184 185 nolist = 0; 186 while (*s) { 187 n1 = 0; 188 if (isdigit((unsigned char)*s)) 189 do 190 n1 = 10 * n1 + *s++ - '0'; 191 while (isdigit((unsigned char)*s)); 192 else 193 n1 = -9999; 194 n2 = n1; 195 if (*s == '-') { 196 s++; 197 n2 = 0; 198 if (isdigit((unsigned char)*s)) 199 do 200 n2 = 10 * n2 + *s++ - '0'; 201 while (isdigit((unsigned char)*s)); 202 else 203 n2 = 9999; 204 } 205 olist[nolist++] = n1; 206 olist[nolist++] = n2; 207 if (*s != '\0') 208 s++; 209 } 210 olist[nolist] = 0; 211 if (dbg) 212 for (i=0; i<nolist; i += 2) 213 printf("%3d %3d\n", olist[i], olist[i+1]); 214 215 return (0); 216 } 217 218 int 219 in_olist(n) /* is n in olist? */ 220 int n; 221 { 222 int i; 223 224 if (nolist == 0) 225 return(1); /* everything is included */ 226 for (i = 0; i < nolist; i += 2) 227 if (n >= olist[i] && n <= olist[i+1]) 228 return(1); 229 return(0); 230 } 231 232 int 233 conv(fp) 234 FILE *fp; 235 { 236 int c, k; 237 int m, n, i, n1, m1; 238 char str[100], buf[300]; 239 240 while ((c = getc(fp)) != EOF) { 241 switch (c) { 242 case '\n': /* when input is text */ 243 case ' ': 244 case 0: /* occasional noise creeps in */ 245 break; 246 case '{': /* push down current environment */ 247 t_push(); 248 break; 249 case '}': 250 t_pop(); 251 break; 252 case '0': case '1': case '2': case '3': case '4': 253 case '5': case '6': case '7': case '8': case '9': 254 /* two motion digits plus a character */ 255 hmot((c-'0')*10 + getc(fp)-'0'); 256 put1(getc(fp)); 257 break; 258 case 'c': /* single ascii character */ 259 put1(getc(fp)); 260 break; 261 case 'C': 262 fscanf(fp, "%s", str); 263 put1s(str); 264 break; 265 case 't': /* straight text */ 266 fgets(buf, sizeof(buf), fp); 267 t_text(buf); 268 break; 269 case 'D': /* draw function */ 270 fgets(buf, sizeof(buf), fp); 271 switch (buf[0]) { 272 case 'l': /* draw a line */ 273 sscanf(buf+1, "%d %d", &n, &m); 274 drawline(n, m, "."); 275 break; 276 case 'c': /* circle */ 277 sscanf(buf+1, "%d", &n); 278 drawcirc(n); 279 break; 280 case 'e': /* ellipse */ 281 sscanf(buf+1, "%d %d", &m, &n); 282 drawellip(m, n); 283 break; 284 case 'a': /* arc */ 285 sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1); 286 drawarc(n, m, n1, m1); 287 break; 288 case '~': /* wiggly line */ 289 drawwig(buf+1); 290 break; 291 default: 292 error(FATAL, "unknown drawing function %s\n", buf); 293 break; 294 } 295 break; 296 case 's': 297 fscanf(fp, "%d", &n); /* ignore fractional sizes */ 298 setsize(t_size(n)); 299 break; 300 case 'f': 301 fscanf(fp, "%s", str); 302 setfont(t_font(str)); 303 break; 304 case 'H': /* absolute horizontal motion */ 305 /* fscanf(fp, "%d", &n); */ 306 while ((c = getc(fp)) == ' ') 307 ; 308 k = 0; 309 do { 310 k = 10 * k + c - '0'; 311 } while (isdigit(c = getc(fp))); 312 ungetc(c, fp); 313 hgoto(k); 314 break; 315 case 'h': /* relative horizontal motion */ 316 /* fscanf(fp, "%d", &n); */ 317 while ((c = getc(fp)) == ' ') 318 ; 319 k = 0; 320 do { 321 k = 10 * k + c - '0'; 322 } while (isdigit(c = getc(fp))); 323 ungetc(c, fp); 324 hmot(k); 325 break; 326 case 'w': /* word space */ 327 putc(' ', stdout); 328 break; 329 case 'V': 330 fscanf(fp, "%d", &n); 331 vgoto(n); 332 break; 333 case 'v': 334 fscanf(fp, "%d", &n); 335 vmot(n); 336 break; 337 case 'p': /* new page */ 338 fscanf(fp, "%d", &n); 339 t_page(n); 340 break; 341 case 'n': /* end of line */ 342 while (getc(fp) != '\n') 343 ; 344 t_newline(); 345 break; 346 case '#': /* comment */ 347 while (getc(fp) != '\n') 348 ; 349 break; 350 case 'x': /* device control */ 351 devcntrl(fp); 352 break; 353 default: 354 error(!FATAL, "unknown input character %o %c\n", c, c); 355 done(); 356 } 357 } 358 359 return (0); 360 } 361 362 int 363 devcntrl(fp) /* interpret device control functions */ 364 FILE *fp; 365 { 366 char str[20]; 367 int c, n; 368 369 fscanf(fp, "%s", str); 370 switch (str[0]) { /* crude for now */ 371 case 'i': /* initialize */ 372 fileinit(); 373 t_init(0); 374 break; 375 case 'T': /* device name */ 376 fscanf(fp, "%s", devname); 377 break; 378 case 't': /* trailer */ 379 t_trailer(); 380 break; 381 case 'p': /* pause -- can restart */ 382 t_reset('p'); 383 break; 384 case 's': /* stop */ 385 t_reset('s'); 386 break; 387 case 'r': /* resolution assumed when prepared */ 388 fscanf(fp, "%d", &res); 389 break; 390 case 'f': /* font used */ 391 fscanf(fp, "%d %s", &n, str); 392 loadfont(n, str); 393 break; 394 } 395 while (getc(fp) != '\n') /* skip rest of input line */ 396 ; 397 398 return (0); 399 } 400 401 int 402 fileinit() /* read in font and code files, etc. */ 403 { 404 return (0); 405 } 406 407 int 408 fontprint(i) /* debugging print of font i (0,...) */ 409 { 410 return (0); 411 } 412 413 int 414 loadcode(n, nw) /* load codetab on position n (0...); #chars is nw */ 415 int n, nw; 416 { 417 return (0); 418 } 419 420 int 421 loadfont(n, s) /* load font info for font s on position n (1...) */ 422 int n; 423 char *s; 424 { 425 return (0); 426 } 427 428 int 429 error(f, s, a1, a2, a3, a4, a5, a6, a7) 430 char *s; 431 { 432 fprintf(stderr, "ta: "); 433 fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7); 434 fprintf(stderr, "\n"); 435 if (f) 436 exit(1); 437 438 return (0); 439 } 440 441 442 /* 443 Here beginneth all the stuff that really depends 444 on the 202 (we hope). 445 */ 446 447 448 char devname[20] = "hp2621"; 449 450 #define ESC 033 451 #define HOME 'H' 452 #define CLEAR 'J' 453 #define FF 014 454 455 int size = 1; 456 int font = 1; /* current font */ 457 int hpos; /* horizontal position where we are supposed to be next (left = 0) */ 458 int vpos; /* current vertical position (down positive) */ 459 460 int horig; /* h origin of current block; hpos rel to this */ 461 int vorig; /* v origin of current block; vpos rel to this */ 462 463 int DX = 10; /* step size in x for drawing */ 464 int DY = 10; /* step size in y for drawing */ 465 int drawdot = '.'; /* draw with this character */ 466 int drawsize = 1; /* shrink by this factor when drawing */ 467 468 int 469 t_init(reinit) /* initialize device */ 470 int reinit; 471 { 472 int i, j; 473 474 fflush(stdout); 475 hpos = vpos = 0; 476 477 return (0); 478 } 479 480 #define MAXSTATE 5 481 482 struct state { 483 int ssize; 484 int sfont; 485 int shpos; 486 int svpos; 487 int shorig; 488 int svorig; 489 }; 490 struct state state[MAXSTATE]; 491 struct state *statep = state; 492 493 int 494 t_push() /* begin a new block */ 495 { 496 hflush(); 497 statep->ssize = size; 498 statep->sfont = font; 499 statep->shorig = horig; 500 statep->svorig = vorig; 501 statep->shpos = hpos; 502 statep->svpos = vpos; 503 horig = hpos; 504 vorig = vpos; 505 hpos = vpos = 0; 506 if (statep++ >= state+MAXSTATE) 507 error(FATAL, "{ nested too deep"); 508 hpos = vpos = 0; 509 510 return (0); 511 } 512 513 int 514 t_pop() /* pop to previous state */ 515 { 516 if (--statep < state) 517 error(FATAL, "extra }"); 518 size = statep->ssize; 519 font = statep->sfont; 520 hpos = statep->shpos; 521 vpos = statep->svpos; 522 horig = statep->shorig; 523 vorig = statep->svorig; 524 525 return (0); 526 } 527 528 int np; /* number of pages seen */ 529 int npmax; /* high-water mark of np */ 530 int pgnum[40]; /* their actual numbers */ 531 long pgadr[40]; /* their seek addresses */ 532 533 int 534 t_page(n) /* do whatever new page functions */ 535 { 536 long ftell(); 537 int c, m, i; 538 char buf[100], *bp; 539 540 pgnum[np++] = n; 541 pgadr[np] = ftell(fp); 542 if (np > npmax) 543 npmax = np; 544 if (output == 0) { 545 output = in_olist(n); 546 t_init(1); 547 return (0); 548 } 549 /* have just printed something, and seen p<n> for next one */ 550 putpage(); 551 fflush(stdout); 552 if (nowait) 553 return (0); 554 555 next: 556 for (bp = buf; (*bp = readch()); ) 557 if (*bp++ == '\n') 558 break; 559 *bp = 0; 560 switch (buf[0]) { 561 case 0: 562 done(); 563 break; 564 case '\n': 565 output = in_olist(n); 566 t_init(1); 567 return (0); 568 case '!': 569 callunix(&buf[1]); 570 fputs("!\n", stderr); 571 break; 572 case 'e': 573 erase = 1 - erase; 574 break; 575 case 'w': 576 wflag = 1 - wflag; 577 break; 578 case 'a': 579 aspect = atof(&buf[1]); 580 break; 581 case '-': 582 case 'p': 583 m = atoi(&buf[1]) + 1; 584 if (fp == stdin) { 585 fputs("you can't; it's not a file\n", stderr); 586 break; 587 } 588 if (np - m <= 0) { 589 fputs("too far back\n", stderr); 590 break; 591 } 592 np -= m; 593 fseek(fp, pgadr[np], 0); 594 output = 1; 595 t_init(1); 596 return (0); 597 case '0': case '1': case '2': case '3': case '4': 598 case '5': case '6': case '7': case '8': case '9': 599 m = atoi(&buf[0]); 600 for (i = 0; i < npmax; i++) 601 if (m == pgnum[i]) 602 break; 603 if (i >= npmax || fp == stdin) { 604 fputs("you can't\n", stderr); 605 break; 606 } 607 np = i + 1; 608 fseek(fp, pgadr[np], 0); 609 output = 1; 610 t_init(1); 611 return (0); 612 case 'o': 613 outlist(&buf[1]); 614 output = 0; 615 t_init(1); 616 return (0); 617 case '?': 618 fputs("!cmd unix cmd\n", stderr); 619 fputs("p print this page again\n", stderr); 620 fputs("-n go back n pages\n", stderr); 621 fputs("n print page n (previously printed)\n", stderr); 622 fputs("o... set the -o output list to ...\n", stderr); 623 fputs("en n=0 -> don't erase; n=1 -> erase\n", stderr); 624 fputs("an sets aspect ratio to n\n", stderr); 625 break; 626 default: 627 fputs("?\n", stderr); 628 break; 629 } 630 goto next; 631 } 632 633 int 634 putpage() 635 { 636 int i, j, k; 637 638 fflush(stdout); 639 640 return (0); 641 } 642 643 int 644 t_newline() /* do whatever for the end of a line */ 645 { 646 printf("\n"); 647 hpos = 0; 648 649 return (0); 650 } 651 652 int 653 t_size(n) /* convert integer to internal size number*/ 654 int n; 655 { 656 return (0); 657 } 658 659 int 660 t_font(s) /* convert string to internal font number */ 661 char *s; 662 { 663 return (0); 664 } 665 666 int 667 t_text(s) /* print string s as text */ 668 char *s; 669 { 670 int c, w=0; 671 char str[100]; 672 673 if (!output) 674 return (0); 675 while ((c = *s++) != '\n') { 676 if (c == '\\') { 677 switch (c = *s++) { 678 case '\\': 679 case 'e': 680 put1('\\'); 681 break; 682 case '(': 683 str[0] = *s++; 684 str[1] = *s++; 685 str[2] = '\0'; 686 put1s(str); 687 break; 688 } 689 } else { 690 put1(c); 691 } 692 hmot(w); 693 } 694 695 return (0); 696 } 697 698 int 699 t_reset(c) 700 { 701 int n; 702 703 output = 1; 704 fflush(stdout); 705 if (c == 's') 706 t_page(9999); 707 708 return (0); 709 } 710 711 int 712 t_trailer() 713 { 714 return (0); 715 } 716 717 int 718 hgoto(n) 719 { 720 hpos = n; /* this is where we want to be */ 721 /* before printing a character, */ 722 /* have to make sure it's true */ 723 724 return (0); 725 } 726 727 int 728 hmot(n) /* generate n units of horizontal motion */ 729 int n; 730 { 731 hgoto(hpos + n); 732 733 return (0); 734 } 735 736 int 737 hflush() /* actual horizontal output occurs here */ 738 { 739 return (0); 740 } 741 742 int 743 vgoto(n) 744 { 745 vpos = n; 746 747 return (0); 748 } 749 750 int 751 vmot(n) /* generate n units of vertical motion */ 752 int n; 753 { 754 vgoto(vpos + n); /* ignores rounding */ 755 756 return (0); 757 } 758 759 int 760 put1s(s) /* s is a funny char name */ 761 char *s; 762 { 763 int i; 764 char *p; 765 extern char *spectab[]; 766 static char prev[10] = ""; 767 static int previ; 768 769 if (!output) 770 return (0); 771 if (strcmp(s, prev) != 0) { 772 previ = -1; 773 for (i = 0; spectab[i] != 0; i += 2) 774 if (strcmp(spectab[i], s) == 0) { 775 strcpy(prev, s); 776 previ = i; 777 break; 778 } 779 } 780 if (previ >= 0) { 781 for (p = spectab[previ+1]; *p; p++) 782 putc(*p, stdout); 783 } else 784 prev[0] = 0; 785 786 return (0); 787 } 788 789 int 790 put1(c) /* output char c */ 791 int c; 792 { 793 if (!output) 794 return (0); 795 putc(c, stdout); 796 797 return (0); 798 } 799 800 int 801 setsize(n) /* set point size to n (internal) */ 802 int n; 803 { 804 return (0); 805 } 806 807 int 808 t_fp(n, s) /* font position n now contains font s */ 809 int n; 810 char *s; 811 { 812 return (0); 813 } 814 815 int 816 setfont(n) /* set font to n */ 817 int n; 818 { 819 return (0); 820 } 821 822 void done() 823 { 824 output = 1; 825 putpage(); 826 fflush(stdout); 827 exit(0); 828 } 829 830 int 831 callunix(line) 832 char line[]; 833 { 834 int rc, status, unixpid; 835 if( (unixpid=fork())==0 ) { 836 signal(SIGINT,sigint); signal(SIGQUIT,sigquit); 837 close(0); dup(2); 838 execl("/bin/sh", "-sh", "-c", line, 0); 839 exit(255); 840 } 841 else if(unixpid == -1) 842 return (0); 843 else{ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); 844 while( (rc = wait(&status)) != unixpid && rc != -1 ) ; 845 signal(SIGINT,(void(*)())done); signal(SIGQUIT,(void(*)())sigquit); 846 } 847 848 return (0); 849 } 850 851 int 852 readch(){ 853 char c; 854 if (read(2,&c,1)<1) c=0; 855 return(c); 856 } 857 858 char *spectab[] ={ 859 "em", "-", 860 "hy", "-", 861 "en", "-", 862 "ru", "_", 863 "l.", ".", 864 "br", "|", 865 "vr", "|", 866 "fm", "'", 867 "or", "|", 868 0, 0, 869 }; 870