ta.c revision 217:758a5315b0d7
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/*
48output language from troff:
49all numbers are character strings
50
51sn	size in points
52fn	font as number from 1-n
53cx	ascii character x
54Cxyz	funny char xyz. terminated by white space
55Hn	go to absolute horizontal position n
56Vn	go to absolute vertical position n (down is positive)
57hn	go n units horizontally (relative)
58vn	ditto vertically
59nnc	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)
62w	paddable word space - no action needed
63nb a	end of line (information only -- no action needed)
64	b = space before line, a = after
65pn	begin page n
66#...\n	comment
67Dt ...\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 ...
74x ...\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
96int	output	= 0;	/* do we do output at all? */
97int	nolist	= 0;	/* output page list if > 0 */
98int	olist[20];	/* pairs of page numbers */
99
100int	erase	= 1;
101float	aspect	= 1.5;	/* default aspect ratio */
102int	wflag	= 0;	/* wait, looping, for new input if on */
103void	(*sigint)();
104void	(*sigquit)();
105void	done();
106
107struct dev dev;
108struct font *fontbase[NFONT];
109short	psizes[]	={ 11, 16, 22, 36, 0};	/* approx sizes available */
110short	*pstab		= psizes;
111int	nsizes	= 1;
112int	nfonts;
113int	smnt;	/* index of first special font */
114int	nchtab;
115char	*chname;
116short	*chtab;
117char	*fitab[NFONT];
118char	*widthtab[NFONT];	/* widtab would be a better name */
119char	*codetab[NFONT];	/* device codes */
120
121#define	FATAL	1
122#define	BMASK	0377
123int	dbg	= 0;
124int	res	= 972;		/* input assumed computed according to this resolution */
125				/* initial value to avoid 0 divide */
126FILE	*tf	= stdout;	/* output file */
127char	*fontdir	= "/usr/lib/font";
128extern char devname[];
129
130FILE *fp = stdin;	/* input file pointer */
131
132int	nowait = 0;	/* 0 => wait at bottom of each page */
133
134int
135main(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
179int
180outlist(s)	/* process list of page numbers to be printed */
181char *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
218int
219in_olist(n)	/* is n in olist? */
220int 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
232int
233conv(fp)
234FILE *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
362int
363devcntrl(fp)	/* interpret device control functions */
364FILE *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
401int
402fileinit()	/* read in font and code files, etc. */
403{
404	return (0);
405}
406
407int
408fontprint(i)	/* debugging print of font i (0,...) */
409{
410	return (0);
411}
412
413int
414loadcode(n, nw)	/* load codetab on position n (0...); #chars is nw */
415int n, nw;
416{
417	return (0);
418}
419
420int
421loadfont(n, s)	/* load font info for font s on position n (1...) */
422int n;
423char *s;
424{
425	return (0);
426}
427
428int
429error(f, s, a1, a2, a3, a4, a5, a6, a7)
430char *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
448char	devname[20]	= "hp2621";
449
450#define	ESC	033
451#define	HOME	'H'
452#define	CLEAR	'J'
453#define	FF	014
454
455int	size	= 1;
456int	font	= 1;		/* current font */
457int	hpos;		/* horizontal position where we are supposed to be next (left = 0) */
458int	vpos;		/* current vertical position (down positive) */
459
460int	horig;		/* h origin of current block; hpos rel to this */
461int	vorig;		/* v origin of current block; vpos rel to this */
462
463int	DX	= 10;	/* step size in x for drawing */
464int	DY	= 10;	/* step size in y for drawing */
465int	drawdot	= '.';	/* draw with this character */
466int	drawsize = 1;	/* shrink by this factor when drawing */
467
468int
469t_init(reinit)	/* initialize device */
470int 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
482struct state {
483	int	ssize;
484	int	sfont;
485	int	shpos;
486	int	svpos;
487	int	shorig;
488	int	svorig;
489};
490struct	state	state[MAXSTATE];
491struct	state	*statep = state;
492
493int
494t_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
513int
514t_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
528int	np;	/* number of pages seen */
529int	npmax;	/* high-water mark of np */
530int	pgnum[40];	/* their actual numbers */
531long	pgadr[40];	/* their seek addresses */
532
533int
534t_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
633int
634putpage()
635{
636	int i, j, k;
637
638	fflush(stdout);
639
640	return (0);
641}
642
643int
644t_newline()	/* do whatever for the end of a line */
645{
646	printf("\n");
647	hpos = 0;
648
649	return (0);
650}
651
652int
653t_size(n)	/* convert integer to internal size number*/
654int n;
655{
656	return (0);
657}
658
659int
660t_font(s)	/* convert string to internal font number */
661char *s;
662{
663	return (0);
664}
665
666int
667t_text(s)	/* print string s as text */
668char *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
698int
699t_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
711int
712t_trailer()
713{
714	return (0);
715}
716
717int
718hgoto(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
727int
728hmot(n)	/* generate n units of horizontal motion */
729int n;
730{
731	hgoto(hpos + n);
732
733	return (0);
734}
735
736int
737hflush()	/* actual horizontal output occurs here */
738{
739	return (0);
740}
741
742int
743vgoto(n)
744{
745	vpos = n;
746
747	return (0);
748}
749
750int
751vmot(n)	/* generate n units of vertical motion */
752int n;
753{
754	vgoto(vpos + n);	/* ignores rounding */
755
756	return (0);
757}
758
759int
760put1s(s)	/* s is a funny char name */
761char *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
789int
790put1(c)	/* output char c */
791int c;
792{
793	if (!output)
794		return (0);
795	putc(c, stdout);
796
797	return (0);
798}
799
800int
801setsize(n)	/* set point size to n (internal) */
802int n;
803{
804	return (0);
805}
806
807int
808t_fp(n, s)	/* font position n now contains font s */
809int n;
810char *s;
811{
812	return (0);
813}
814
815int
816setfont(n)	/* set font to n */
817int n;
818{
819	return (0);
820}
821
822void done()
823{
824	output = 1;
825	putpage();
826	fflush(stdout);
827	exit(0);
828}
829
830int
831callunix(line)
832char 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
851int
852readch(){
853	char c;
854	if (read(2,&c,1)<1) c=0;
855	return(c);
856}
857
858char *spectab[] ={
859	"em", "-",
860	"hy", "-",
861	"en", "-",
862	"ru", "_",
863	"l.", ".",
864	"br", "|",
865	"vr", "|",
866	"fm", "'",
867	"or", "|",
868	0, 0,
869};
870