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