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
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(s)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
in_olist(n)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
conv(fp)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
devcntrl(fp)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
fileinit()402 fileinit() /* read in font and code files, etc. */
403 {
404 return (0);
405 }
406
407 int
fontprint(i)408 fontprint(i) /* debugging print of font i (0,...) */
409 {
410 return (0);
411 }
412
413 int
loadcode(n,nw)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
loadfont(n,s)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
error(f,s,a1,a2,a3,a4,a5,a6,a7)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
t_init(reinit)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
t_push()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
t_pop()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
t_page(n)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
putpage()634 putpage()
635 {
636 int i, j, k;
637
638 fflush(stdout);
639
640 return (0);
641 }
642
643 int
t_newline()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
t_size(n)653 t_size(n) /* convert integer to internal size number*/
654 int n;
655 {
656 return (0);
657 }
658
659 int
t_font(s)660 t_font(s) /* convert string to internal font number */
661 char *s;
662 {
663 return (0);
664 }
665
666 int
t_text(s)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
t_reset(c)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
t_trailer()712 t_trailer()
713 {
714 return (0);
715 }
716
717 int
hgoto(n)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
hmot(n)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
hflush()737 hflush() /* actual horizontal output occurs here */
738 {
739 return (0);
740 }
741
742 int
vgoto(n)743 vgoto(n)
744 {
745 vpos = n;
746
747 return (0);
748 }
749
750 int
vmot(n)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
put1s(s)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
put1(c)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
setsize(n)801 setsize(n) /* set point size to n (internal) */
802 int n;
803 {
804 return (0);
805 }
806
807 int
t_fp(n,s)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
setfont(n)816 setfont(n) /* set font to n */
817 int n;
818 {
819 return (0);
820 }
821
done()822 void done()
823 {
824 output = 1;
825 putpage();
826 fflush(stdout);
827 exit(0);
828 }
829
830 int
callunix(line)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
readch()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