1 #ifndef lint
2 static char sccsid[] = "@(#)tc.c	1.2	(CWI)	1.2	85/03/26";
3 #endif lint
4 /*
5  *	drive 4014 scope
6  */
7 
8 /*
9 output language from troff:
10 all numbers are character strings
11 
12 sn	size in points
13 fn	font as number from 1-n
14 cx	ascii character x
15 Cxyz	funny char xyz. terminated by white space
16 Hn	go to absolute horizontal position n
17 Vn	go to absolute vertical position n (down is positive)
18 hn	go n units horizontally (relative)
19 vn	ditto vertically
20 nnc	move right nn, then print c (exactly 2 digits!)
21 		(this wart is an optimization that shrinks output file size
22 		 about 35% and run-time about 15% while preserving ascii-ness)
23 Dt ...\n	draw operation 't':
24 	Dl x y		line from here by x,y
25 	Dc d		circle of diameter d with left side here
26 	De x y		ellipse of axes x,y with left side here
27 	Da x y r	arc counter-clockwise by x,y of radius r
28 	D~ x y x y ...	wiggly line by x,y then x,y ...
29 nb a	end of line (information only -- no action needed)
30 	b = space before line, a = after
31 p	new page begins -- set v to 0
32 #...\n	comment
33 x ...\n	device control functions:
34 	x i	init
35 	x T s	name of device is s
36 	x r n h v	resolution is n/inch
37 		h = min horizontal motion, v = min vert
38 	x p	pause (can restart)
39 	x s	stop -- done for ever
40 	x t	generate trailer
41 	x f n s	font position n contains font s
42 	x H n	set character height to n
43 	x S n	set slant to N
44 
45 	Subcommands like "i" are often spelled out like "init".
46 */
47 
48 #include	<stdio.h>
49 #include	<signal.h>
50 #include	<ctype.h>
51 
52 #include "../dev.h"
53 #define	NFONT	10
54 
55 int	output	= 0;	/* do we do output at all? */
56 int	nolist	= 0;	/* output page list if > 0 */
57 int	olist[20];	/* pairs of page numbers */
58 
59 int	erase	= 1;
60 float	aspect	= 1.5;	/* default aspect ratio */
61 int	(*sigint)();
62 int	(*sigquit)();
63 
64 struct dev dev;
65 struct font *fontbase[NFONT];
66 short	psizes[]	={ 11, 16, 22, 36, 0};	/* approx sizes available */
67 short	*pstab		= psizes;
68 int	nsizes	= 4;
69 int	pscode[]	={ ';', ':', '9', '8'};
70 int	nfonts;
71 int	smnt;	/* index of first special font */
72 int	nchtab;
73 char	*chname;
74 short	*chtab;
75 char	*fitab[NFONT];
76 char	*widthtab[NFONT];	/* widtab would be a better name */
77 char	*codetab[NFONT];	/* device codes */
78 
79 #define	FATAL	1
80 #define	BMASK	0377
81 int	keepon 	= 0;
82 int	dbg	= 0;
83 long	lineno	= 0;
84 int	res	= 972;		/* input assumed computed according to this resolution */
85 				/* initial value to avoid 0 divide */
86 FILE	*tf	= stdout;	/* output file */
87 char	*fontdir	= "/usr/lib/font";
88 extern char devname[];
89 
90 FILE *fp	= stdin;	/* input file pointer */
91 
92 main(argc, argv)
93 char *argv[];
94 {
95 	char buf[BUFSIZ];
96 	float atof();
97 	int done();
98 
99 	setbuf(stdout, buf);
100 	while (argc > 1 && argv[1][0] == '-') {
101 		switch (argv[1][1]) {
102 		case 'T':
103 			if (strcmp(&argv[1][2], "cat") == 0) {	/* use the old one */
104 				if (fork() == 0) {
105 					execv("/usr/bin/oldtc", argv);
106 					fprintf(stderr, "tc: can't find oldtc\n");
107 				}
108 				wait();
109 				exit(1);
110 			}
111 			break;
112 		case 'a':
113 			aspect = atof(&argv[1][2]);
114 			break;
115 		case 'e':
116 			erase = 0;
117 			break;
118 		case 'o':
119 			outlist(&argv[1][2]);
120 			break;
121 		case 'd':
122 			dbg = atoi(&argv[1][2]);
123 			if (dbg == 0) dbg = 1;
124 			break;
125 		case 'c':
126 			keepon = 1;
127 			break;
128 		}
129 		argc--;
130 		argv++;
131 	}
132 
133 	sigint = signal(SIGINT, done);
134 	sigquit = signal(SIGQUIT, SIG_IGN);
135 	if (argc <= 1)
136 		conv(stdin);
137 	else
138 		while (--argc > 0) {
139 			if (strcmp(*++argv, "-") == 0)
140 				fp = stdin;
141 			else if ((fp = fopen(*argv, "r")) == NULL)
142 				error(FATAL, "can't open %s", *argv);
143 			conv(fp);
144 			fclose(fp);
145 		}
146 	done();
147 }
148 
149 outlist(s)	/* process list of page numbers to be printed */
150 char *s;
151 {
152 	int n1, n2, i;
153 
154 	nolist = 0;
155 	while (*s) {
156 		n1 = 0;
157 		if (isdigit(*s))
158 			do
159 				n1 = 10 * n1 + *s++ - '0';
160 			while (isdigit(*s));
161 		else
162 			n1 = -9999;
163 		n2 = n1;
164 		if (*s == '-') {
165 			s++;
166 			n2 = 0;
167 			if (isdigit(*s))
168 				do
169 					n2 = 10 * n2 + *s++ - '0';
170 				while (isdigit(*s));
171 			else
172 				n2 = 9999;
173 		}
174 		olist[nolist++] = n1;
175 		olist[nolist++] = n2;
176 		if (*s != '\0')
177 			s++;
178 	}
179 	olist[nolist] = 0;
180 	if (dbg)
181 		for (i=0; i<nolist; i += 2)
182 			printf("%3d %3d\n", olist[i], olist[i+1]);
183 }
184 
185 in_olist(n)	/* is n in olist? */
186 int n;
187 {
188 	int i;
189 
190 	if (nolist == 0)
191 		return(1);	/* everything is included */
192 	for (i = 0; i < nolist; i += 2)
193 		if (n >= olist[i] && n <= olist[i+1])
194 			return(1);
195 	return(0);
196 }
197 
198 conv(fp)
199 register FILE *fp;
200 {
201 	register int c, k;
202 	int m, n, i, n1, m1;
203 	char str[100], buf[300];
204 
205 	while ((c = getc(fp)) != EOF) {
206 		switch (c) {
207 		case '\n':	/* when input is text */
208 			lineno++;
209 		case ' ':
210 		case 0:		/* occasional noise creeps in */
211 			break;
212 		case '{':	/* push down current environment */
213 			t_push();
214 			break;
215 		case '}':
216 			t_pop();
217 			break;
218 		case '0': case '1': case '2': case '3': case '4':
219 		case '5': case '6': case '7': case '8': case '9':
220 			/* two motion digits plus a character */
221 			hmot((c-'0')*10 + getc(fp)-'0');
222 			put1(getc(fp));
223 			break;
224 		case 'c':	/* single ascii character */
225 			put1(getc(fp));
226 			break;
227 		case 'C':
228 			fscanf(fp, "%s", str);
229 			put1s(str);
230 			break;
231 		case 't':	/* straight text */
232 			fgets(buf, sizeof(buf), fp);
233 			lineno++;
234 			t_text(buf);
235 			break;
236 		case 'D':	/* draw function */
237 			fgets(buf, sizeof(buf), fp);
238 			lineno++;
239 			switch (buf[0]) {
240 			case 'l':	/* draw a line */
241 				sscanf(buf+1, "%d %d", &n, &m);
242 				drawline(n, m, ".");
243 				break;
244 			case 'c':	/* circle */
245 				sscanf(buf+1, "%d", &n);
246 				drawcirc(n);
247 				break;
248 			case 'e':	/* ellipse */
249 				sscanf(buf+1, "%d %d", &m, &n);
250 				drawellip(m, n);
251 				break;
252 			case 'a':	/* arc */
253 				sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
254 				drawarc(n, m, n1, m1);
255 				break;
256 			case '~':	/* wiggly line */
257 				drawwig(buf+1);
258 				break;
259 			default:
260 				error(FATAL, "unknown drawing function %s\n", buf);
261 				break;
262 			}
263 			break;
264 		case 's':
265 			fscanf(fp, "%d", &n);	/* ignore fractional sizes */
266 			setsize(t_size(n));
267 			break;
268 		case 'f':
269 			fscanf(fp, "%s", str);
270 			setfont(t_font(str));
271 			break;
272 		case 'H':	/* absolute horizontal motion */
273 			/* fscanf(fp, "%d", &n); */
274 			while ((c = getc(fp)) == ' ')
275 				;
276 			k = 0;
277 			do {
278 				k = 10 * k + c - '0';
279 			} while (isdigit(c = getc(fp)));
280 			ungetc(c, fp);
281 			hgoto(k);
282 			break;
283 		case 'h':	/* relative horizontal motion */
284 			/* fscanf(fp, "%d", &n); */
285 			while ((c = getc(fp)) == ' ')
286 				;
287 			k = 0;
288 			do {
289 				k = 10 * k + c - '0';
290 			} while (isdigit(c = getc(fp)));
291 			ungetc(c, fp);
292 			hmot(k);
293 			break;
294 		case 'w':	/* word space */
295 			break;
296 		case 'V':
297 			fscanf(fp, "%d", &n);
298 			vgoto(n);
299 			break;
300 		case 'v':
301 			fscanf(fp, "%d", &n);
302 			vmot(n);
303 			break;
304 		case 'p':	/* new page */
305 			fscanf(fp, "%d", &n);
306 			t_page(n);
307 			break;
308 		case 'n':	/* end of line */
309 			while (getc(fp) != '\n')
310 				;
311 			t_newline();
312 			break;
313 		case '#':	/* comment */
314 			while (getc(fp) != '\n')
315 				;
316 			lineno++;
317 			break;
318 		case 'x':	/* device control */
319 			devcntrl(fp);
320 			lineno++;
321 			break;
322 		default:
323 			error(!FATAL, "unknown input character %o %c\n", c, c);
324 			while (getc(fp) != '\n')
325 				;
326 		}
327 	}
328 }
329 
330 devcntrl(fp)	/* interpret device control functions */
331 FILE *fp;
332 {
333 	char str[20];
334 	int c, n;
335 
336 	fscanf(fp, "%s", str);
337 	switch (str[0]) {	/* crude for now */
338 	case 'i':	/* initialize */
339 		fileinit();
340 		t_init(0);
341 		break;
342 	case 'T':	/* device name */
343 		fscanf(fp, "%s", devname);
344 		break;
345 	case 't':	/* trailer */
346 		t_trailer();
347 		break;
348 	case 'p':	/* pause -- can restart */
349 		t_reset('p');
350 		break;
351 	case 's':	/* stop */
352 		t_reset('s');
353 		break;
354 	case 'r':	/* resolution assumed when prepared */
355 		fscanf(fp, "%d", &res);
356 		break;
357 	case 'f':	/* font used */
358 		fscanf(fp, "%d %s", &n, str);
359 		loadfont(n, str);
360 		break;
361 	}
362 	while (getc(fp) != '\n')	/* skip rest of input line */
363 		;
364 }
365 
366 fileinit()	/* read in font and code files, etc. */
367 {
368 }
369 
370 fontprint(i)	/* debugging print of font i (0,...) */
371 {
372 }
373 
374 loadcode(n, nw)	/* load codetab on position n (0...); #chars is nw */
375 int n, nw;
376 {
377 }
378 
379 loadfont(n, s)	/* load font info for font s on position n (1...) */
380 int n;
381 char *s;
382 {
383 }
384 
385 #define	ESC	033
386 #define	MAXY	(3071-100)
387 #define	US	037	/* text mode */
388 #define	GS	035	/* graphics mode */
389 #define	FF	014
390 
391 error(f, s, a1, a2, a3, a4, a5, a6, a7) {
392 	fprintf(stderr, "%c%c%c", US, ESC, ';');	/* reset terminal sensibly */
393 	fprintf(stderr, "tc: ");
394 	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
395 	fprintf(stderr, " near line %ld\n", lineno);
396 	if (f)
397 		done(2);
398 }
399 
400 
401 /*
402 	Here beginneth all the stuff that really depends
403 	on the 202 (we hope).
404 */
405 
406 
407 char	devname[20]	= "4014";
408 
409 #define	oput(c)	if (output) putchar(c); else;
410 
411 int	stopped = 0;
412 int	ohx	= -1;
413 int	ohy	= -1;
414 int	oxb	= -1;
415 int	oly	= -1;
416 int	olx	= -1;
417 int	skip;
418 int	size	= 1;
419 int	font	= 1;		/* current font */
420 int	hpos;		/* horizontal position where we are supposed to be next (left = 0) */
421 int	vpos;		/* current vertical position (down positive) */
422 
423 int	horig;		/* h origin of current block; hpos rel to this */
424 int	vorig;		/* v origin of current block; vpos rel to this */
425 
426 int	DX	= 10;	/* step size in x for drawing */
427 int	DY	= 10;	/* step size in y for drawing */
428 int	drawdot	= '.';	/* draw with this character */
429 int	drawsize = 1;	/* shrink by this factor when drawing */
430 
431 t_init(reinit)	/* initialize device */
432 int reinit;
433 {
434 	fflush(stdout);
435 	stopped = 0;
436 	if (erase) {
437 		oput(ESC);
438 		oput(FF);
439 		oput(US);
440 	}
441 	hpos = vpos = 0;
442 	setsize(t_size(10));	/* start somewhere */
443 	sendpt();
444 }
445 
446 #define	MAXSTATE	5
447 
448 struct state {
449 	int	ssize;
450 	int	sfont;
451 	int	shpos;
452 	int	svpos;
453 	int	shorig;
454 	int	svorig;
455 };
456 struct	state	state[MAXSTATE];
457 struct	state	*statep = state;
458 
459 t_push()	/* begin a new block */
460 {
461 	hflush();
462 	statep->ssize = size;
463 	statep->sfont = font;
464 	statep->shorig = horig;
465 	statep->svorig = vorig;
466 	statep->shpos = hpos;
467 	statep->svpos = vpos;
468 	horig = hpos;
469 	vorig = vpos;
470 	hpos = vpos = 0;
471 	if (statep++ >= state+MAXSTATE)
472 		error(FATAL, "{ nested too deep");
473 	hpos = vpos = 0;
474 }
475 
476 t_pop()	/* pop to previous state */
477 {
478 	if (--statep < state)
479 		error(FATAL, "extra }");
480 	size = statep->ssize;
481 	font = statep->sfont;
482 	hpos = statep->shpos;
483 	vpos = statep->svpos;
484 	horig = statep->shorig;
485 	vorig = statep->svorig;
486 }
487 
488 int	np;	/* number of pages seen */
489 int	npmax;	/* high-water mark of np */
490 int	pgnum[100];	/* their actual numbers */
491 long	pgadr[100];	/* their seek addresses */
492 
493 t_page(n)	/* do whatever new page functions */
494 {
495 	long ftell();
496 	int c, m, i;
497 	char buf[100], *bp;
498 
499 	pgnum[np++] = n;
500 	pgadr[np] = ftell(fp);
501 	if (np > npmax)
502 		npmax = np;
503 	if (output == 0) {
504 		output = in_olist(n);
505 		t_init(1);
506 		return;
507 	}
508 	/* have just printed something, and seen p<n> for next one */
509 	vgoto(11 * res - 100);
510 	sendpt();
511 	oput(US);
512 	fflush(stdout);
513 
514 
515 	if (keepon) {
516 		t_init(1);
517 		return;
518 	}
519   next:
520 	for (bp = buf; (*bp = readch()); )
521 		if (*bp++ == '\n')
522 			break;
523 	*bp = 0;
524 	switch (buf[0]) {
525 	case 0:
526 	case 'q':
527 		done();
528 		break;
529 	case '\n':
530 		if (stopped)
531 			done();
532 		output = in_olist(n);
533 		t_init(1);
534 		return;
535 	case '!':
536 		callunix(&buf[1]);
537 		fputs("!\n", stderr);
538 		break;
539 	case 'e':
540 		erase = 1 - erase;
541 		break;
542 	case 'a':
543 		aspect = atof(&buf[1]);
544 		break;
545 	case '-':
546 	case 'p':
547 		m = atoi(&buf[1]) + 1;
548 		if (fp == stdin) {
549 			fputs("you can't; it's not a file\n", stderr);
550 			break;
551 		}
552 		if (np - m <= 0) {
553 			fputs("too far back\n", stderr);
554 			break;
555 		}
556 		np -= m;
557 		fseek(fp, pgadr[np], 0);
558 		output = 1;
559 		t_init(1);
560 		return;
561 	case '0': case '1': case '2': case '3': case '4':
562 	case '5': case '6': case '7': case '8': case '9':
563 		m = atoi(&buf[0]);
564 		for (i = 0; i < npmax; i++)
565 			if (m == pgnum[i])
566 				break;
567 		if (i >= npmax || fp == stdin) {
568 			fputs("you can't\n", stderr);
569 			break;
570 		}
571 		np = i + 1;
572 		fseek(fp, pgadr[np], 0);
573 		output = 1;
574 		t_init(1);
575 		return;
576 	case 'o':
577 		outlist(&buf[1]);
578 		output = 0;
579 		t_init(1);
580 		return;
581 	case '?':
582 		fputs("!cmd	unix cmd\n", stderr);
583 		fputs("p	print this page again\n", stderr);
584 		fputs("-n	go back n pages\n", stderr);
585 		fputs("n	print page n (previously printed)\n", stderr);
586 		fputs("o...	set the -o output list to ...\n", stderr);
587 		fputs("q	quit\n", stderr);
588 		fputs("en	n=0 -> don't erase; n=1 -> erase\n", stderr);
589 		fputs("an	sets aspect ratio to n\n", stderr);
590 		break;
591 	default:
592 		fputs("?\n", stderr);
593 		break;
594 	}
595 	goto next;
596 }
597 
598 t_newline()	/* do whatever for the end of a line */
599 {
600 	hpos = 0;
601 }
602 
603 t_size(n)	/* convert integer to internal size number*/
604 int n;
605 {
606 	int i;
607 
608 	if (n <= pstab[0])
609 		return(1);
610 	else if (n >= pstab[nsizes-1])
611 		return(nsizes);
612 	for (i = 0; n > pstab[i]; i++)
613 		;
614 	return(i+1);
615 }
616 
617 t_font(s)	/* convert string to internal font number */
618 char *s;
619 {
620 	int n;
621 
622 	n = atoi(s);
623 	if (n < 1 || n > nfonts)
624 		n = 1;
625 	return(n);
626 }
627 
628 t_text(s)	/* print string s as text */
629 char *s;
630 {
631 	int c, w;
632 	char str[100];
633 
634 	if (!output)
635 		return;
636 	w = res / 2 * pstab[size-1] / 72;
637 	while ((c = *s++) != '\n') {
638 		if (c == '\\') {
639 			switch (c = *s++) {
640 			case '\\':
641 			case 'e':
642 				put1('\\');
643 				break;
644 			case '(':
645 				str[0] = *s++;
646 				str[1] = *s++;
647 				str[2] = '\0';
648 				put1s(str);
649 				break;
650 			}
651 		} else {
652 			put1(c);
653 		}
654 		hmot(w);
655 	}
656 }
657 
658 t_reset(c)
659 {
660 	int n;
661 
662 	output = 1;
663 	fflush(stdout);
664 	if (c == 's') {
665 		stopped = 1;
666 		t_page(9999);
667 	}
668 }
669 
670 t_trailer()
671 {
672 }
673 
674 hgoto(n)
675 {
676 	hpos = n;	/* this is where we want to be */
677 			/* before printing a character, */
678 			/* have to make sure it's true */
679 }
680 
681 hmot(n)	/* generate n units of horizontal motion */
682 int n;
683 {
684 	hgoto(hpos + n);
685 }
686 
687 hflush()	/* actual horizontal output occurs here */
688 {
689 	if (output)
690 		sendpt();
691 }
692 
693 vgoto(n)
694 {
695 	vpos = n;
696 }
697 
698 vmot(n)	/* generate n units of vertical motion */
699 int n;
700 {
701 	vgoto(vpos + n);	/* ignores rounding */
702 }
703 
704 put1s(s)	/* s is a funny char name */
705 char *s;
706 {
707 	int i;
708 	char *p;
709 	extern char *spectab[];
710 	static char prev[10] = "";
711 	static int previ;
712 
713 	if (!output)
714 		return;
715 	if (strcmp(s, prev) != 0) {
716 		previ = -1;
717 		for (i = 0; spectab[i] != 0; i += 2)
718 			if (strcmp(spectab[i], s) == 0) {
719 				strcpy(prev, s);
720 				previ = i;
721 				break;
722 			}
723 	}
724 	if (previ >= 0) {
725 		hflush();
726 		oput(US);
727 		for (p = spectab[previ+1]; *p; p++)
728 			oput(*p);
729 	} else
730 		prev[0] = 0;
731 }
732 
733 put1(c)	/* output char c */
734 int c;
735 {
736 	if (!output)
737 		return;
738 	hflush();
739 	oput(US);
740 	oput(c);
741 }
742 
743 setsize(n)	/* set point size to n (internal) */
744 int n;
745 {
746 
747 	if (!output)
748 		return;
749 	if (n == size)
750 		return;	/* already there */
751 	oput(ESC);
752 	oput(pscode[n-1]);
753 	size = n;
754 }
755 
756 t_fp(n, s)	/* font position n now contains font s */
757 int n;
758 char *s;
759 {
760 }
761 
762 setfont(n)	/* set font to n */
763 int n;
764 {
765 }
766 
767 done()
768 {
769 	output = 1;
770 	hgoto(0);
771 	vgoto(11 * res - 100);	/* bottom of page */
772 	sendpt();
773 	oput(US);
774 	oput(ESC);
775 	oput(';');
776 	oput(US);
777 	fflush(stdout);
778 	exit(0);
779 }
780 
781 callunix(line)
782 char line[];
783 {
784 	int rc, status, unixpid;
785 	if( (unixpid=fork())==0 ) {
786 		signal(SIGINT,sigint); signal(SIGQUIT,sigquit);
787 		close(0); dup(2);
788 		execl("/bin/sh", "-sh", "-c", line, 0);
789 		exit(255);
790 	}
791 	else if(unixpid == -1)
792 		return;
793 	else{	signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN);
794 		while( (rc = wait(&status)) != unixpid && rc != -1 ) ;
795 		signal(SIGINT, done); signal(SIGQUIT,sigquit);
796 	}
797 }
798 readch(){
799 	char c;
800 	if (read(2,&c,1)<1) c=0;
801 	return(c);
802 }
803 sendpt(){
804 	int hy,xb,ly,hx,lx;
805 	int xx, yy;
806 	float fx, fy;
807 
808 
809 	fx = hpos + horig;
810 	fy = vpos + vorig;
811 	xx = (fx * MAXY / 11) / res * aspect + 0.5;
812 	yy = MAXY - (fy * MAXY / 11) / res + 0.5;
813 	oput(GS);
814 	hy = ((yy>>7) & 037);
815 	xb = ((xx & 03) + ((yy<<2) & 014) & 017);
816 	ly = ((yy>>2) & 037);
817 	hx = ((xx>>7) & 037);
818 	lx = ((xx>>2) & 037);
819 	if(hy != ohy)oput(hy | 040);
820 	if(xb != oxb)oput(xb | 0140);
821 	if((ly != oly) || (hx != ohx) || (xb != oxb))
822 		oput(ly | 0140);
823 	if(hx != ohx)oput(hx | 040);
824 	oput(lx | 0100);
825 	ohy = hy;
826 	oxb = xb;
827 	oly = ly;
828 	ohx = hx;
829 	olx = lx;
830 }
831 
832 char *spectab[] ={
833 	"em", "--",
834 	"en", "-",
835 	"hy", "-",
836 	"ff", "ff",
837 	"fi", "fi",
838 	"fl", "fl",
839 	"Fi", "ffi",
840 	"Fl", "ffl",
841 	"ct", "\033\016Z\bM\033\017",	/*cent sign*/
842 	"de", "\033\016J\033\017",	/*degree*/
843 	"dg", "\033\016M\b_\033\017",	/*dagger*/
844 	"rg", "\033\016O\b&\033\017",	/*registered*/
845 	"bu", "\033\016O\b~\033\017",	/*bullet*/
846 	"fm", "'",
847 	"co", "\033\016O\b#\033\017",	/*copyright*/
848 	"sq", "\033\016L\033\017",	/*square*/
849 	"*q", "\033\016(\bM\033\017",	/*psi*/
850 	"*h", "\033\016o\b_\033\017",	/*theta*/
851 	"*n", "v\b)",	/*nu*/
852 	"*m", "\033\016V\b,\033\017",	/*mu*/
853 	"*l", "\033\016)\b?\033\017",	/*lambda*/
854 	"*i", "\033\016I\033\017",	/*iota*/
855 	"*z", "S\b\033\016Z\033\017",	/*zeta*/
856 	"*s", "o\b\'",	/*sigma*/
857 	"*d", "o\b\033\0165\033\017",	/*delta*/
858 	"*b", "\033\016b\033\017",	/*beta*/
859 	"*c", "\033\016e\bc\033\017",	/*xi*/
860 	"*y", "j\b\033\016C\033\017",	/*eta*/
861 	"*f", "\033\016O\bM\033\017",	/*phi*/
862 	"*u", "\033\016(\033\017",	/*upsilon*/
863 	"*k", "\033\016k\033\017",	/*kappa*/
864 	"*p", "T\b\033\016S\033\017",	/*pi*/
865 	"da", "\033\016U\033\017",	/*down arrow*/
866 	"*a", "\033\016A\033\017",	/*alpha*/
867 	"or", "|",
868 	"*x", "l\b/",	/*chi*/
869 	"*e", "\033\016E\033\017",	/*epsilon*/
870 	"*o", "\033\016O\033\017",	/*omicron*/
871 	"<-", "\033\016[\033\017",	/*left arrow*/
872 	"*r", "\033\016R\033\017",	/*rho*/
873 	"ua", "\033\016Y\033\017",	/*up arrow*/
874 	"*t", "\033\016N\033\017",	/*tau*/
875 	"ul", "_",
876 	"ru", "_",
877 	"\\_", "_",
878 	"*Q", "I\b\033\016(\033\017",	/*Psi*/
879 	"bs", "\033\016O\bJ\033\017",	/*bell system sign*/
880 	"if", "\033\016W\bX\033\017",	/*infinity*/
881 	"*g", "`\b/",	/*gamma*/
882 	"ip", "\033\016X\bF\033\017",	/*improper superset*/
883 	"pt", "\033\016A\033\017",	/*proportional to*/
884 	"rh", "\033\016\\\b]\033\017",	/*right hand*/
885 	"*w", "\033\016W\033\017",	/*omega*/
886 	"gr", "\033\016G\033\017",	/*gradient*/
887 	"*F", "I\033\016\bO\033\017",	/*Phi*/
888 	"*H", "O\b=",	/*Theta*/
889 	"*W", "O\b_",	/*Omega*/
890 	"cu", "\033\016V\033\017",	/*cup (union)*/
891 	"rn", "\033\016@\033\017",	/*root en*/
892 	"ts", "s",	/*terminal sigma*/
893 	"*L", "\033\016)\bK\033\017",	/*Lambda*/
894 	"\\-", "-",
895 	"*G", "\033\016S\bK\033\017",	/*Gamma*/
896 	"is", "\033\016i\033\017",	/*integral sign*/
897 	"Sl", "l",
898 	"*P", "\033\016t\b'\033\017",	/*Pi*/
899 	"sb", "\033\016Z\033\017",	/*subset of*/
900 	"sp", "\033\016X\033\017",	/*superset of*/
901 	"ap", "\033\016T\033\017",	/*approximates*/
902 	"pd", "o\b`",	/*partial derivative*/
903 	"*D", "\033\016H\033\017",	/*Delta*/
904 	"sr", "\033\016I\b'\033\017",	/*square root*/
905 	"*S", ">\b\033\016F\b@\033\017",	/*Sigma*/
906 	"~~", "\033\016T\bF\033\017",	/*approx =*/
907 	"*C", "\033\016_\bF\b@\033\017",	/*Xi*/
908 	"sl", "/",
909 	"ca", "\033\016C\033\017",	/*cap (intersection)*/
910 	"U", "\033\016y\033\017",	/*Upsilon*/
911 	"no", "\033\016|\033\017",	/*not*/
912 	"rc", "|",	/*right ceiling (rt of ")*/
913 	"lt", "|",	/*left top (of big curly)*/
914 	"bv", "|",	/*bold vertical*/
915 	"lk", "|",	/*left center of big curly bracket*/
916 	"lb", "|",	/*left bottom*/
917 	"rt", "|",	/*right top*/
918 	"rk", "|",	/*right center of big curly bracket*/
919 	"rb", "|",	/*right bot*/
920 	"rf", "|",	/*right floor (rb of ")*/
921 	"lf", "|",	/*left floor (left bot of big sq bract)*/
922 	"lc", "|",	/*left ceiling (lt of ")*/
923 	"mu", "\033\016=\033\017",	/*multiply*/
924 	"di", "\033\016+\033\017",	/*divide*/
925 	"+-", "+\b_",	/*plus-minus*/
926 	"<=", "\033\016$\033\017",	/*<=*/
927 	">=", "\033\016^\033\017",	/*>=*/
928 	"==", "=\b_",	/*identically equal*/
929 	"!=", "\033\016*\033\017",	/*not equal*/
930 	"aa", "'",
931 	"ga", "`",
932 	"lh", "\033\016|\b[\033\017",	/*left hand*/
933 	"mo", "\033\016c\b_\033\017",	/*member of*/
934 	"es", "\033\016O\b/\033\017",	/*empty set*/
935 	"dd", "\033\016%\bM\033\017",	/*dbl dagger*/
936 	"br", "|",	/*box rule*/
937 	"vr", "|",	/* vertical rule */
938 	"ib", "\033\016Z\bF\033\017",	/*improper subset*/
939 	"ci", "\033\016O\033\017",	/*circle*/
940 	"eq", "=",
941 	"pl", "+",
942 	"mi", "-",
943 	"12", "1/2",
944 	"14", "1/4",
945 	"34", "3/4",
946 	"->", "\033\016]\033\017",	/*right arrow*/
947 	"sc", "g\b\033\016C\033\017",	/*section mark*/
948 	"**", "*",
949 	"l.", ".",
950 	"L.", ".",
951 	"bx", "[\b]",
952 	"ob", "o",	/* open bullet */
953 	"cd", ",",	/* cedilla */
954 	"..", "\033\016!\033\017",	/* umlaut */
955 	0, 0,
956 };
957