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 <stdarg.h> 89 #include <signal.h> 90 #include <ctype.h> 91 92 #include "dev.h" 93 #define NFONT 10 94 95 int output = 0; /* do we do output at all? */ 96 int nolist = 0; /* output page list if > 0 */ 97 int olist[20]; /* pairs of page numbers */ 98 99 int erase = 1; 100 float aspect = 1.5; /* default aspect ratio */ 101 int wflag = 0; /* wait, looping, for new input if on */ 102 void (*sigint)(int); 103 void (*sigquit)(int); 104 void done(void); 105 int error(int, char *, ...); 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(char *s) /* process list of page numbers to be printed */ 181 { 182 int n1, n2, i; 183 184 nolist = 0; 185 while (*s) { 186 n1 = 0; 187 if (isdigit((unsigned char)*s)) 188 do 189 n1 = 10 * n1 + *s++ - '0'; 190 while (isdigit((unsigned char)*s)); 191 else 192 n1 = -9999; 193 n2 = n1; 194 if (*s == '-') { 195 s++; 196 n2 = 0; 197 if (isdigit((unsigned char)*s)) 198 do 199 n2 = 10 * n2 + *s++ - '0'; 200 while (isdigit((unsigned char)*s)); 201 else 202 n2 = 9999; 203 } 204 olist[nolist++] = n1; 205 olist[nolist++] = n2; 206 if (*s != '\0') 207 s++; 208 } 209 olist[nolist] = 0; 210 if (dbg) 211 for (i=0; i<nolist; i += 2) 212 printf("%3d %3d\n", olist[i], olist[i+1]); 213 214 return (0); 215 } 216 217 int 218 in_olist(int n) /* is n in olist? */ 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(FILE *fp) 232 { 233 int c, k; 234 int m, n, i, n1, m1; 235 char str[100], buf[300]; 236 237 while ((c = getc(fp)) != EOF) { 238 switch (c) { 239 case '\n': /* when input is text */ 240 case ' ': 241 case 0: /* occasional noise creeps in */ 242 break; 243 case '{': /* push down current environment */ 244 t_push(); 245 break; 246 case '}': 247 t_pop(); 248 break; 249 case '0': case '1': case '2': case '3': case '4': 250 case '5': case '6': case '7': case '8': case '9': 251 /* two motion digits plus a character */ 252 hmot((c-'0')*10 + getc(fp)-'0'); 253 put1(getc(fp)); 254 break; 255 case 'c': /* single ascii character */ 256 put1(getc(fp)); 257 break; 258 case 'C': 259 fscanf(fp, "%s", str); 260 put1s(str); 261 break; 262 case 't': /* straight text */ 263 fgets(buf, sizeof(buf), fp); 264 t_text(buf); 265 break; 266 case 'D': /* draw function */ 267 fgets(buf, sizeof(buf), fp); 268 switch (buf[0]) { 269 case 'l': /* draw a line */ 270 sscanf(buf+1, "%d %d", &n, &m); 271 drawline(n, m, "."); 272 break; 273 case 'c': /* circle */ 274 sscanf(buf+1, "%d", &n); 275 drawcirc(n); 276 break; 277 case 'e': /* ellipse */ 278 sscanf(buf+1, "%d %d", &m, &n); 279 drawellip(m, n); 280 break; 281 case 'a': /* arc */ 282 sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1); 283 drawarc(n, m, n1, m1); 284 break; 285 case '~': /* wiggly line */ 286 drawwig(buf+1); 287 break; 288 default: 289 error(FATAL, "unknown drawing function %s\n", buf); 290 break; 291 } 292 break; 293 case 's': 294 fscanf(fp, "%d", &n); /* ignore fractional sizes */ 295 setsize(t_size(n)); 296 break; 297 case 'f': 298 fscanf(fp, "%s", str); 299 setfont(t_font(str)); 300 break; 301 case 'H': /* absolute horizontal motion */ 302 /* fscanf(fp, "%d", &n); */ 303 while ((c = getc(fp)) == ' ') 304 ; 305 k = 0; 306 do { 307 k = 10 * k + c - '0'; 308 } while (isdigit(c = getc(fp))); 309 ungetc(c, fp); 310 hgoto(k); 311 break; 312 case 'h': /* relative horizontal motion */ 313 /* fscanf(fp, "%d", &n); */ 314 while ((c = getc(fp)) == ' ') 315 ; 316 k = 0; 317 do { 318 k = 10 * k + c - '0'; 319 } while (isdigit(c = getc(fp))); 320 ungetc(c, fp); 321 hmot(k); 322 break; 323 case 'w': /* word space */ 324 putc(' ', stdout); 325 break; 326 case 'V': 327 fscanf(fp, "%d", &n); 328 vgoto(n); 329 break; 330 case 'v': 331 fscanf(fp, "%d", &n); 332 vmot(n); 333 break; 334 case 'p': /* new page */ 335 fscanf(fp, "%d", &n); 336 t_page(n); 337 break; 338 case 'n': /* end of line */ 339 while (getc(fp) != '\n') 340 ; 341 t_newline(); 342 break; 343 case '#': /* comment */ 344 while (getc(fp) != '\n') 345 ; 346 break; 347 case 'x': /* device control */ 348 devcntrl(fp); 349 break; 350 default: 351 error(!FATAL, "unknown input character %o %c\n", c, c); 352 done(); 353 } 354 } 355 356 return (0); 357 } 358 359 int 360 devcntrl(FILE *fp) /* interpret device control functions */ 361 { 362 char str[20]; 363 int c, n; 364 365 fscanf(fp, "%s", str); 366 switch (str[0]) { /* crude for now */ 367 case 'i': /* initialize */ 368 fileinit(); 369 t_init(0); 370 break; 371 case 'T': /* device name */ 372 fscanf(fp, "%s", devname); 373 break; 374 case 't': /* trailer */ 375 t_trailer(); 376 break; 377 case 'p': /* pause -- can restart */ 378 t_reset('p'); 379 break; 380 case 's': /* stop */ 381 t_reset('s'); 382 break; 383 case 'r': /* resolution assumed when prepared */ 384 fscanf(fp, "%d", &res); 385 break; 386 case 'f': /* font used */ 387 fscanf(fp, "%d %s", &n, str); 388 loadfont(n, str); 389 break; 390 } 391 while (getc(fp) != '\n') /* skip rest of input line */ 392 ; 393 394 return (0); 395 } 396 397 int 398 fileinit(void) /* read in font and code files, etc. */ 399 { 400 return (0); 401 } 402 403 int 404 fontprint(int i) /* debugging print of font i (0,...) */ 405 { 406 return (0); 407 } 408 409 int 410 loadcode(int n, int nw) /* load codetab on position n (0...); #chars is nw */ 411 { 412 return (0); 413 } 414 415 int 416 loadfont(int n, char *s) /* load font info for font s on position n (1...) */ 417 { 418 return (0); 419 } 420 421 int 422 error(int f, char *fmt, ...) 423 { 424 va_list ap; 425 426 fprintf(stderr, "ta: "); 427 va_start(ap, fmt); 428 (void) vfprintf(stderr, fmt, ap); 429 va_end(ap); 430 fprintf(stderr, "\n"); 431 if (f) 432 exit(1); 433 434 return (0); 435 } 436 437 438 /* 439 Here beginneth all the stuff that really depends 440 on the 202 (we hope). 441 */ 442 443 444 char devname[20] = "hp2621"; 445 446 #define ESC 033 447 #define HOME 'H' 448 #define CLEAR 'J' 449 #define FF 014 450 451 int size = 1; 452 int font = 1; /* current font */ 453 int hpos; /* horizontal position where we are supposed to be next (left = 0) */ 454 int vpos; /* current vertical position (down positive) */ 455 456 int horig; /* h origin of current block; hpos rel to this */ 457 int vorig; /* v origin of current block; vpos rel to this */ 458 459 int DX = 10; /* step size in x for drawing */ 460 int DY = 10; /* step size in y for drawing */ 461 int drawdot = '.'; /* draw with this character */ 462 int drawsize = 1; /* shrink by this factor when drawing */ 463 464 int 465 t_init(int reinit) /* initialize device */ 466 { 467 int i, j; 468 469 fflush(stdout); 470 hpos = vpos = 0; 471 472 return (0); 473 } 474 475 #define MAXSTATE 5 476 477 struct state { 478 int ssize; 479 int sfont; 480 int shpos; 481 int svpos; 482 int shorig; 483 int svorig; 484 }; 485 struct state state[MAXSTATE]; 486 struct state *statep = state; 487 488 int 489 t_push(void) /* begin a new block */ 490 { 491 hflush(); 492 statep->ssize = size; 493 statep->sfont = font; 494 statep->shorig = horig; 495 statep->svorig = vorig; 496 statep->shpos = hpos; 497 statep->svpos = vpos; 498 horig = hpos; 499 vorig = vpos; 500 hpos = vpos = 0; 501 if (statep++ >= state+MAXSTATE) 502 error(FATAL, "{ nested too deep"); 503 hpos = vpos = 0; 504 505 return (0); 506 } 507 508 int 509 t_pop(void) /* pop to previous state */ 510 { 511 if (--statep < state) 512 error(FATAL, "extra }"); 513 size = statep->ssize; 514 font = statep->sfont; 515 hpos = statep->shpos; 516 vpos = statep->svpos; 517 horig = statep->shorig; 518 vorig = statep->svorig; 519 520 return (0); 521 } 522 523 int np; /* number of pages seen */ 524 int npmax; /* high-water mark of np */ 525 int pgnum[40]; /* their actual numbers */ 526 long pgadr[40]; /* their seek addresses */ 527 528 int 529 t_page(int n) /* do whatever new page functions */ 530 { 531 long ftell(); 532 int c, m, i; 533 char buf[100], *bp; 534 535 pgnum[np++] = n; 536 pgadr[np] = ftell(fp); 537 if (np > npmax) 538 npmax = np; 539 if (output == 0) { 540 output = in_olist(n); 541 t_init(1); 542 return (0); 543 } 544 /* have just printed something, and seen p<n> for next one */ 545 putpage(); 546 fflush(stdout); 547 if (nowait) 548 return (0); 549 550 next: 551 for (bp = buf; (*bp = readch()); ) 552 if (*bp++ == '\n') 553 break; 554 *bp = 0; 555 switch (buf[0]) { 556 case 0: 557 done(); 558 break; 559 case '\n': 560 output = in_olist(n); 561 t_init(1); 562 return (0); 563 case '!': 564 callunix(&buf[1]); 565 fputs("!\n", stderr); 566 break; 567 case 'e': 568 erase = 1 - erase; 569 break; 570 case 'w': 571 wflag = 1 - wflag; 572 break; 573 case 'a': 574 aspect = atof(&buf[1]); 575 break; 576 case '-': 577 case 'p': 578 m = atoi(&buf[1]) + 1; 579 if (fp == stdin) { 580 fputs("you can't; it's not a file\n", stderr); 581 break; 582 } 583 if (np - m <= 0) { 584 fputs("too far back\n", stderr); 585 break; 586 } 587 np -= m; 588 fseek(fp, pgadr[np], 0); 589 output = 1; 590 t_init(1); 591 return (0); 592 case '0': case '1': case '2': case '3': case '4': 593 case '5': case '6': case '7': case '8': case '9': 594 m = atoi(&buf[0]); 595 for (i = 0; i < npmax; i++) 596 if (m == pgnum[i]) 597 break; 598 if (i >= npmax || fp == stdin) { 599 fputs("you can't\n", stderr); 600 break; 601 } 602 np = i + 1; 603 fseek(fp, pgadr[np], 0); 604 output = 1; 605 t_init(1); 606 return (0); 607 case 'o': 608 outlist(&buf[1]); 609 output = 0; 610 t_init(1); 611 return (0); 612 case '?': 613 fputs("!cmd unix cmd\n", stderr); 614 fputs("p print this page again\n", stderr); 615 fputs("-n go back n pages\n", stderr); 616 fputs("n print page n (previously printed)\n", stderr); 617 fputs("o... set the -o output list to ...\n", stderr); 618 fputs("en n=0 -> don't erase; n=1 -> erase\n", stderr); 619 fputs("an sets aspect ratio to n\n", stderr); 620 break; 621 default: 622 fputs("?\n", stderr); 623 break; 624 } 625 goto next; 626 } 627 628 int 629 putpage(void) 630 { 631 int i, j, k; 632 633 fflush(stdout); 634 635 return (0); 636 } 637 638 int 639 t_newline(void) /* do whatever for the end of a line */ 640 { 641 printf("\n"); 642 hpos = 0; 643 644 return (0); 645 } 646 647 int 648 t_size(int n) /* convert integer to internal size number*/ 649 { 650 return (0); 651 } 652 653 int 654 t_font(char *s) /* convert string to internal font number */ 655 { 656 return (0); 657 } 658 659 int 660 t_text(char *s) /* print string s as text */ 661 { 662 int c, w=0; 663 char str[100]; 664 665 if (!output) 666 return (0); 667 while ((c = *s++) != '\n') { 668 if (c == '\\') { 669 switch (c = *s++) { 670 case '\\': 671 case 'e': 672 put1('\\'); 673 break; 674 case '(': 675 str[0] = *s++; 676 str[1] = *s++; 677 str[2] = '\0'; 678 put1s(str); 679 break; 680 } 681 } else { 682 put1(c); 683 } 684 hmot(w); 685 } 686 687 return (0); 688 } 689 690 int 691 t_reset(int c) 692 { 693 int n; 694 695 output = 1; 696 fflush(stdout); 697 if (c == 's') 698 t_page(9999); 699 700 return (0); 701 } 702 703 int 704 t_trailer(void) 705 { 706 return (0); 707 } 708 709 int 710 hgoto(int n) 711 { 712 hpos = n; /* this is where we want to be */ 713 /* before printing a character, */ 714 /* have to make sure it's true */ 715 716 return (0); 717 } 718 719 int 720 hmot(int n) /* generate n units of horizontal motion */ 721 { 722 hgoto(hpos + n); 723 724 return (0); 725 } 726 727 int 728 hflush(void) /* actual horizontal output occurs here */ 729 { 730 return (0); 731 } 732 733 int 734 vgoto(int n) 735 { 736 vpos = n; 737 738 return (0); 739 } 740 741 int 742 vmot(int n) /* generate n units of vertical motion */ 743 { 744 vgoto(vpos + n); /* ignores rounding */ 745 746 return (0); 747 } 748 749 int 750 put1s(char *s) /* s is a funny char name */ 751 { 752 int i; 753 char *p; 754 extern char *spectab[]; 755 static char prev[10] = ""; 756 static int previ; 757 758 if (!output) 759 return (0); 760 if (strcmp(s, prev) != 0) { 761 previ = -1; 762 for (i = 0; spectab[i] != 0; i += 2) 763 if (strcmp(spectab[i], s) == 0) { 764 strcpy(prev, s); 765 previ = i; 766 break; 767 } 768 } 769 if (previ >= 0) { 770 for (p = spectab[previ+1]; *p; p++) 771 putc(*p, stdout); 772 } else 773 prev[0] = 0; 774 775 return (0); 776 } 777 778 int 779 put1(int c) /* output char c */ 780 { 781 if (!output) 782 return (0); 783 putc(c, stdout); 784 785 return (0); 786 } 787 788 int 789 setsize(int n) /* set point size to n (internal) */ 790 { 791 return (0); 792 } 793 794 int 795 t_fp(int n, char *s) /* font position n now contains font s */ 796 { 797 return (0); 798 } 799 800 int 801 setfont(int n) /* set font to n */ 802 { 803 return (0); 804 } 805 806 void done(void) 807 { 808 output = 1; 809 putpage(); 810 fflush(stdout); 811 exit(0); 812 } 813 814 int 815 callunix(char line[]) 816 { 817 int rc, status, unixpid; 818 if( (unixpid=fork())==0 ) { 819 signal(SIGINT,sigint); signal(SIGQUIT,sigquit); 820 close(0); dup(2); 821 execl("/bin/sh", "-sh", "-c", line, 0); 822 exit(255); 823 } 824 else if(unixpid == -1) 825 return (0); 826 else{ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); 827 while( (rc = wait(&status)) != unixpid && rc != -1 ) ; 828 signal(SIGINT,(void(*)())done); signal(SIGQUIT,sigquit); 829 } 830 831 return (0); 832 } 833 834 int 835 readch(void) 836 { 837 char c; 838 if (read(2,&c,1)<1) c=0; 839 return(c); 840 } 841 842 char *spectab[] ={ 843 "em", "-", 844 "hy", "-", 845 "en", "-", 846 "ru", "_", 847 "l.", ".", 848 "br", "|", 849 "vr", "|", 850 "fm", "'", 851 "or", "|", 852 0, 0, 853 }; 854