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
main(int argc,char ** argv)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
outlist(char * s)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
in_olist(int n)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
conv(FILE * fp)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
devcntrl(FILE * fp)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
fileinit(void)398 fileinit(void) /* read in font and code files, etc. */
399 {
400 return (0);
401 }
402
403 int
fontprint(int i)404 fontprint(int i) /* debugging print of font i (0,...) */
405 {
406 return (0);
407 }
408
409 int
loadcode(int n,int nw)410 loadcode(int n, int nw) /* load codetab on position n (0...); #chars is nw */
411 {
412 return (0);
413 }
414
415 int
loadfont(int n,char * s)416 loadfont(int n, char *s) /* load font info for font s on position n (1...) */
417 {
418 return (0);
419 }
420
421 int
error(int f,char * fmt,...)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
t_init(int reinit)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
t_push(void)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
t_pop(void)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
t_page(int n)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
putpage(void)629 putpage(void)
630 {
631 int i, j, k;
632
633 fflush(stdout);
634
635 return (0);
636 }
637
638 int
t_newline(void)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
t_size(int n)648 t_size(int n) /* convert integer to internal size number*/
649 {
650 return (0);
651 }
652
653 int
t_font(char * s)654 t_font(char *s) /* convert string to internal font number */
655 {
656 return (0);
657 }
658
659 int
t_text(char * s)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
t_reset(int c)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
t_trailer(void)704 t_trailer(void)
705 {
706 return (0);
707 }
708
709 int
hgoto(int n)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
hmot(int n)720 hmot(int n) /* generate n units of horizontal motion */
721 {
722 hgoto(hpos + n);
723
724 return (0);
725 }
726
727 int
hflush(void)728 hflush(void) /* actual horizontal output occurs here */
729 {
730 return (0);
731 }
732
733 int
vgoto(int n)734 vgoto(int n)
735 {
736 vpos = n;
737
738 return (0);
739 }
740
741 int
vmot(int n)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
put1s(char * s)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
put1(int c)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
setsize(int n)789 setsize(int n) /* set point size to n (internal) */
790 {
791 return (0);
792 }
793
794 int
t_fp(int n,char * s)795 t_fp(int n, char *s) /* font position n now contains font s */
796 {
797 return (0);
798 }
799
800 int
setfont(int n)801 setfont(int n) /* set font to n */
802 {
803 return (0);
804 }
805
done(void)806 void done(void)
807 {
808 output = 1;
809 putpage();
810 fflush(stdout);
811 exit(0);
812 }
813
814 int
callunix(char line[])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
readch(void)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