|
|
1.1 root 1: /*
2: * drive hp2621 terminal
3: * there is some bug here that blows up on vaxes.
4: */
5:
6: /*
7: output language from troff:
8: all numbers are character strings
9:
10: sn size in points
11: fn font as number from 1-n
12: cx ascii character x
13: Cxyz funny char xyz. terminated by white space
14: Hn go to absolute horizontal position n
15: Vn go to absolute vertical position n (down is positive)
16: hn go n units horizontally (relative)
17: vn ditto vertically
18: nnc move right nn, then print c (exactly 2 digits!)
19: (this wart is an optimization that shrinks output file size
20: about 35% and run-time about 15% while preserving ascii-ness)
21: dt ...\n draw operation 't':
22: d/ dx dy c line from here to dx,dy using c
23: dO r circle of radius r centered here
24: dE rx ry ellipse of semi-axes rx, ry centered here
25: dA dx1 dy1 dx2 dy2 arc counter-clockwise with center here
26: from dx1,dy1 to dx2,dy2.
27: nb a end of line (information only -- no action needed)
28: b = space before line, a = after
29: p new page begins -- set v to 0
30: #...\n comment
31: x ...\n device control functions:
32: x i init
33: x T s name of device is s
34: x r n h v resolution is n/inch
35: h = min horizontal motion, v = min vert
36: x p pause (can restart)
37: x s stop -- done for ever
38: x t generate trailer
39: x f n s font position n contains font s
40:
41: Subcommands like "i" are often spelled out like "init".
42: */
43:
44: #include <stdio.h>
45: #include <signal.h>
46: #include <ctype.h>
47:
48: #include "dev.h"
49: #define NFONT 10
50:
51: int keepon = 0;
52: int output = 0; /* do we do output at all? */
53: int nolist = 0; /* output page list if > 0 */
54: int olist[20]; /* pairs of page numbers */
55:
56: int erase = 1;
57: float aspect = 1.5; /* default aspect ratio */
58: int wflag = 0; /* wait, looping, for new input if on */
59: int (*sigint)();
60: int (*sigquit)();
61:
62: struct dev dev;
63: struct font *fontbase[NFONT];
64: short psizes[] ={ 11, 16, 22, 36, 0}; /* approx sizes available */
65: short *pstab = psizes;
66: int nsizes = 1;
67: int pscode[] ={ ';', ':', '9', '8'};
68: int nfonts;
69: int smnt; /* index of first special font */
70: int nchtab;
71: char *chname;
72: short *chtab;
73: char *fitab[NFONT];
74: char *widthtab[NFONT]; /* widtab would be a better name */
75: char *codetab[NFONT]; /* device codes */
76:
77: #define FATAL 1
78: #define BMASK 0377
79: int dbg = 0;
80: int res = 972; /* input assumed computed according to this resolution */
81: /* initial value to avoid 0 divide */
82: char *typesetter = "/dev/202"; /* typesetter device */
83: FILE *tf = stdout; /* output file */
84: char *fontdir = "/usr/lib/font";
85: extern char devname[];
86:
87: int hscale = 75;
88: int vscale = 100;
89: FILE *fp = stdin; /* input file pointer */
90:
91: main(argc, argv)
92: char *argv[];
93: {
94: char buf[BUFSIZ];
95: int done();
96: float atof();
97:
98: setbuf(stdout, buf);
99: while (argc > 1 && argv[1][0] == '-') {
100: switch (argv[1][1]) {
101: case 'h':
102: hscale = atoi(&argv[1][2]);
103: break;
104: case 'v':
105: vscale = atoi(&argv[1][2]);
106: break;
107: case 'a':
108: aspect = atof(&argv[1][2]);
109: break;
110: case 'e':
111: erase = 0;
112: break;
113: case 'o':
114: outlist(&argv[1][2]);
115: break;
116: case 'd':
117: dbg = atoi(&argv[1][2]);
118: if (dbg == 0) dbg = 1;
119: break;
120: case 'c':
121: keepon = 1;
122: break;
123: }
124: argc--;
125: argv++;
126: }
127:
128: if (argc <= 1)
129: conv(stdin);
130: else
131: while (--argc > 0) {
132: if (strcmp(*++argv, "-") == 0)
133: fp = stdin;
134: else if ((fp = fopen(*argv, "r")) == NULL)
135: error(FATAL, "can't open %s", *argv);
136: conv(fp);
137: fclose(fp);
138: }
139: done();
140: }
141:
142: outlist(s) /* process list of page numbers to be printed */
143: char *s;
144: {
145: int n1, n2, i;
146:
147: nolist = 0;
148: while (*s) {
149: n1 = 0;
150: if (isdigit(*s))
151: do
152: n1 = 10 * n1 + *s++ - '0';
153: while (isdigit(*s));
154: else
155: n1 = -9999;
156: n2 = n1;
157: if (*s == '-') {
158: s++;
159: n2 = 0;
160: if (isdigit(*s))
161: do
162: n2 = 10 * n2 + *s++ - '0';
163: while (isdigit(*s));
164: else
165: n2 = 9999;
166: }
167: olist[nolist++] = n1;
168: olist[nolist++] = n2;
169: if (*s != '\0')
170: s++;
171: }
172: olist[nolist] = 0;
173: if (dbg)
174: for (i=0; i<nolist; i += 2)
175: printf("%3d %3d\n", olist[i], olist[i+1]);
176: }
177:
178: in_olist(n) /* is n in olist? */
179: int n;
180: {
181: int i;
182:
183: if (nolist == 0)
184: return(1); /* everything is included */
185: for (i = 0; i < nolist; i += 2)
186: if (n >= olist[i] && n <= olist[i+1])
187: return(1);
188: return(0);
189: }
190:
191: conv(fp)
192: register FILE *fp;
193: {
194: register int c, k;
195: int m, n, i, n1, m1;
196: char str[100], buf[300];
197:
198: while ((c = getc(fp)) != EOF) {
199: switch (c) {
200: case '\n': /* when input is text */
201: case ' ':
202: case 0: /* occasional noise creeps in */
203: break;
204: case '{': /* push down current environment */
205: t_push();
206: break;
207: case '}':
208: t_pop();
209: break;
210: case '0': case '1': case '2': case '3': case '4':
211: case '5': case '6': case '7': case '8': case '9':
212: /* two motion digits plus a character */
213: hmot((c-'0')*10 + getc(fp)-'0');
214: put1(getc(fp));
215: break;
216: case 'c': /* single ascii character */
217: put1(getc(fp));
218: break;
219: case 'C':
220: fscanf(fp, "%s", str);
221: put1s(str);
222: break;
223: case 't': /* straight text */
224: fgets(buf, sizeof(buf), fp);
225: t_text(buf);
226: break;
227: case 'D': /* draw function */
228: fgets(buf, sizeof(buf), fp);
229: switch (buf[0]) {
230: case 'l': /* draw a line */
231: sscanf(buf+1, "%d %d", &n, &m);
232: drawline(n, m, ".");
233: break;
234: case 'c': /* circle */
235: sscanf(buf+1, "%d", &n);
236: drawcirc(n);
237: break;
238: case 'e': /* ellipse */
239: sscanf(buf+1, "%d %d", &m, &n);
240: drawellip(m, n);
241: break;
242: case 'a': /* arc */
243: sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
244: drawarc(n, m, n1, m1);
245: break;
246: case '~': /* wiggly line */
247: drawwig(buf+1);
248: break;
249: default:
250: error(FATAL, "unknown drawing function %s\n", buf);
251: break;
252: }
253: break;
254: case 's':
255: fscanf(fp, "%d", &n); /* ignore fractional sizes */
256: setsize(t_size(n));
257: break;
258: case 'f':
259: fscanf(fp, "%s", str);
260: setfont(t_font(str));
261: break;
262: case 'H': /* absolute horizontal motion */
263: /* fscanf(fp, "%d", &n); */
264: while ((c = getc(fp)) == ' ')
265: ;
266: k = 0;
267: do {
268: k = 10 * k + c - '0';
269: } while (isdigit(c = getc(fp)));
270: ungetc(c, fp);
271: hgoto(k);
272: break;
273: case 'h': /* relative horizontal motion */
274: /* fscanf(fp, "%d", &n); */
275: while ((c = getc(fp)) == ' ')
276: ;
277: k = 0;
278: do {
279: k = 10 * k + c - '0';
280: } while (isdigit(c = getc(fp)));
281: ungetc(c, fp);
282: hmot(k);
283: break;
284: case 'w': /* word space */
285: break;
286: case 'V':
287: fscanf(fp, "%d", &n);
288: vgoto(n);
289: break;
290: case 'v':
291: fscanf(fp, "%d", &n);
292: vmot(n);
293: break;
294: case 'p': /* new page */
295: fscanf(fp, "%d", &n);
296: t_page(n);
297: break;
298: case 'n': /* end of line */
299: while (getc(fp) != '\n')
300: ;
301: t_newline();
302: break;
303: case '#': /* comment */
304: while (getc(fp) != '\n')
305: ;
306: break;
307: case 'x': /* device control */
308: devcntrl(fp);
309: break;
310: default:
311: error(!FATAL, "unknown input character %o %c\n", c, c);
312: done();
313: }
314: }
315: }
316:
317: devcntrl(fp) /* interpret device control functions */
318: FILE *fp;
319: {
320: char str[20];
321: int c, n;
322:
323: fscanf(fp, "%s", str);
324: switch (str[0]) { /* crude for now */
325: case 'i': /* initialize */
326: fileinit();
327: t_init(0);
328: break;
329: case 'T': /* device name */
330: fscanf(fp, "%s", devname);
331: break;
332: case 't': /* trailer */
333: t_trailer();
334: break;
335: case 'p': /* pause -- can restart */
336: t_reset('p');
337: break;
338: case 's': /* stop */
339: t_reset('s');
340: break;
341: case 'r': /* resolution assumed when prepared */
342: fscanf(fp, "%d", &res);
343: break;
344: case 'f': /* font used */
345: fscanf(fp, "%d %s", &n, str);
346: loadfont(n, str);
347: break;
348: }
349: while (getc(fp) != '\n') /* skip rest of input line */
350: ;
351: }
352:
353: fileinit() /* read in font and code files, etc. */
354: {
355: }
356:
357: fontprint(i) /* debugging print of font i (0,...) */
358: {
359: }
360:
361: loadcode(n, nw) /* load codetab on position n (0...); #chars is nw */
362: int n, nw;
363: {
364: }
365:
366: loadfont(n, s) /* load font info for font s on position n (1...) */
367: int n;
368: char *s;
369: {
370: }
371:
372: error(f, s, a1, a2, a3, a4, a5, a6, a7) {
373: fprintf(stderr, "hc: ");
374: fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
375: fprintf(stderr, "\n");
376: if (f)
377: exit(1);
378: }
379:
380:
381: /*
382: Here beginneth all the stuff that really depends
383: on the 202 (we hope).
384: */
385:
386:
387: char devname[20] = "hp2621";
388:
389: #define ESC 033
390: #define HOME 'H'
391: #define CLEAR 'J'
392: #define FF 014
393:
394: #define PGHEIGHT 100 /* could be larger */
395: #define PGWIDTH 100 /* ditto */
396: /* should map input into a larger thing, then print window */
397: char pagebuf[PGHEIGHT][PGWIDTH];
398: int minh = PGWIDTH;
399: int maxh = 0;
400: int minv = PGHEIGHT;
401: int maxv = 0;
402:
403:
404: int size = 1;
405: int font = 1; /* current font */
406: int hpos; /* horizontal position where we are supposed to be next (left = 0) */
407: int vpos; /* current vertical position (down positive) */
408:
409: int horig; /* h origin of current block; hpos rel to this */
410: int vorig; /* v origin of current block; vpos rel to this */
411:
412: int DX = 10; /* step size in x for drawing */
413: int DY = 10; /* step size in y for drawing */
414: int drawdot = '.'; /* draw with this character */
415: int drawsize = 1; /* shrink by this factor when drawing */
416:
417: t_init(reinit) /* initialize device */
418: int reinit;
419: {
420: int i, j;
421:
422: fflush(stdout);
423: hpos = vpos = 0;
424: for (i = 0; i < PGHEIGHT; i++)
425: for (j = 0; j < PGWIDTH; j++)
426: pagebuf[i][j] = ' ';
427: minh = PGWIDTH;
428: maxh = 0;
429: minv = PGHEIGHT;
430: maxv = 0;
431: }
432:
433: #define MAXSTATE 5
434:
435: struct state {
436: int ssize;
437: int sfont;
438: int shpos;
439: int svpos;
440: int shorig;
441: int svorig;
442: };
443: struct state state[MAXSTATE];
444: struct state *statep = state;
445:
446: t_push() /* begin a new block */
447: {
448: hflush();
449: statep->ssize = size;
450: statep->sfont = font;
451: statep->shorig = horig;
452: statep->svorig = vorig;
453: statep->shpos = hpos;
454: statep->svpos = vpos;
455: horig = hpos;
456: vorig = vpos;
457: hpos = vpos = 0;
458: if (statep++ >= state+MAXSTATE)
459: error(FATAL, "{ nested too deep");
460: hpos = vpos = 0;
461: }
462:
463: t_pop() /* pop to previous state */
464: {
465: if (--statep < state)
466: error(FATAL, "extra }");
467: size = statep->ssize;
468: font = statep->sfont;
469: hpos = statep->shpos;
470: vpos = statep->svpos;
471: horig = statep->shorig;
472: vorig = statep->svorig;
473: }
474:
475: int np; /* number of pages seen */
476: int npmax; /* high-water mark of np */
477: int pgnum[40]; /* their actual numbers */
478: long pgadr[40]; /* their seek addresses */
479:
480: t_page(n) /* do whatever new page functions */
481: {
482: long ftell();
483: int c, m, i;
484: char buf[100], *bp;
485:
486: pgnum[np++] = n;
487: pgadr[np] = ftell(fp);
488: if (np > npmax)
489: npmax = np;
490: if (output == 0) {
491: output = in_olist(n);
492: t_init(1);
493: return;
494: }
495: /* have just printed something, and seen p<n> for next one */
496: putpage();
497: fflush(stdout);
498:
499: if (keepon) {
500: t_init(1);
501: return;
502: }
503: next:
504: for (bp = buf; (*bp = readch()); )
505: if (*bp++ == '\n')
506: break;
507: *bp = 0;
508: switch (buf[0]) {
509: case 0:
510: done();
511: break;
512: case '\n':
513: output = in_olist(n);
514: t_init(1);
515: return;
516: case '!':
517: callunix(&buf[1]);
518: fputs("!\n", stderr);
519: break;
520: case 'e':
521: erase = 1 - erase;
522: break;
523: case 'w':
524: wflag = 1 - wflag;
525: break;
526: case 'a':
527: aspect = atof(&buf[1]);
528: break;
529: case '-':
530: case 'p':
531: m = atoi(&buf[1]) + 1;
532: if (fp == stdin) {
533: fputs("you can't; it's not a file\n", stderr);
534: break;
535: }
536: if (np - m <= 0) {
537: fputs("too far back\n", stderr);
538: break;
539: }
540: np -= m;
541: fseek(fp, pgadr[np], 0);
542: output = 1;
543: t_init(1);
544: return;
545: case '0': case '1': case '2': case '3': case '4':
546: case '5': case '6': case '7': case '8': case '9':
547: m = atoi(&buf[0]);
548: for (i = 0; i < npmax; i++)
549: if (m == pgnum[i])
550: break;
551: if (i >= npmax || fp == stdin) {
552: fputs("you can't\n", stderr);
553: break;
554: }
555: np = i + 1;
556: fseek(fp, pgadr[np], 0);
557: output = 1;
558: t_init(1);
559: return;
560: case 'o':
561: outlist(&buf[1]);
562: output = 0;
563: t_init(1);
564: return;
565: case '?':
566: fputs("!cmd unix cmd\n", stderr);
567: fputs("p print this page again\n", stderr);
568: fputs("-n go back n pages\n", stderr);
569: fputs("n print page n (previously printed)\n", stderr);
570: fputs("o... set the -o output list to ...\n", stderr);
571: fputs("en n=0 -> don't erase; n=1 -> erase\n", stderr);
572: fputs("an sets aspect ratio to n\n", stderr);
573: break;
574: default:
575: fputs("?\n", stderr);
576: break;
577: }
578: goto next;
579: }
580:
581: putpage()
582: {
583: int i, j, k;
584:
585: fflush(stdout);
586: for (i = minv; i <= maxv; i++) {
587: for (k = maxh; pagebuf[i][k] == ' '; k--)
588: ;
589: if (k > minh + 78)
590: k = minh + 78;
591: for (j = minh; j <= k; j++)
592: putchar(pagebuf[i][j]);
593: putchar('\n');
594: }
595: fflush(stdout);
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: }
607:
608: t_font(s) /* convert string to internal font number */
609: char *s;
610: {
611: }
612:
613: t_text(s) /* print string s as text */
614: char *s;
615: {
616: int c, w;
617: char str[100];
618:
619: if (!output)
620: return;
621: while ((c = *s++) != '\n') {
622: if (c == '\\') {
623: switch (c = *s++) {
624: case '\\':
625: case 'e':
626: put1('\\');
627: break;
628: case '(':
629: str[0] = *s++;
630: str[1] = *s++;
631: str[2] = '\0';
632: put1s(str);
633: break;
634: }
635: } else {
636: put1(c);
637: }
638: hmot(w);
639: }
640: }
641:
642: t_reset(c)
643: {
644: int n;
645:
646: output = 1;
647: fflush(stdout);
648: }
649:
650: t_trailer()
651: {
652: }
653:
654: hgoto(n)
655: {
656: hpos = n; /* this is where we want to be */
657: /* before printing a character, */
658: /* have to make sure it's true */
659: }
660:
661: hmot(n) /* generate n units of horizontal motion */
662: int n;
663: {
664: hgoto(hpos + n);
665: }
666:
667: hflush() /* actual horizontal output occurs here */
668: {
669: }
670:
671: vgoto(n)
672: {
673: vpos = n;
674: }
675:
676: vmot(n) /* generate n units of vertical motion */
677: int n;
678: {
679: vgoto(vpos + n); /* ignores rounding */
680: }
681:
682: put1s(s) /* s is a funny char name */
683: char *s;
684: {
685: int i;
686: char *p;
687: extern char *spectab[];
688: static char prev[10] = "";
689: static int previ;
690:
691: if (!output)
692: return;
693: if (strcmp(s, prev) != 0) {
694: previ = -1;
695: for (i = 0; spectab[i] != 0; i += 2)
696: if (strcmp(spectab[i], s) == 0) {
697: strcpy(prev, s);
698: previ = i;
699: break;
700: }
701: }
702: if (previ >= 0) {
703: for (p = spectab[previ+1]; *p; p++)
704: store(*p);
705: } else
706: prev[0] = 0;
707: }
708:
709: put1(c) /* output char c */
710: int c;
711: {
712: if (!output)
713: return;
714: store(c);
715: }
716:
717: setsize(n) /* set point size to n (internal) */
718: int n;
719: {
720: }
721:
722: t_fp(n, s) /* font position n now contains font s */
723: int n;
724: char *s;
725: {
726: }
727:
728: setfont(n) /* set font to n */
729: int n;
730: {
731: }
732:
733: done()
734: {
735: output = 1;
736: putpage();
737: fflush(stdout);
738: exit(0);
739: }
740:
741: callunix(line)
742: char line[];
743: {
744: int rc, status, unixpid;
745: if( (unixpid=fork())==0 ) {
746: signal(SIGINT,sigint); signal(SIGQUIT,sigquit);
747: close(0); dup(2);
748: execl("/bin/sh", "-sh", "-c", line, 0);
749: exit(255);
750: }
751: else if(unixpid == -1)
752: return;
753: else{ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN);
754: while( (rc = wait(&status)) != unixpid && rc != -1 ) ;
755: signal(SIGINT,done); signal(SIGQUIT,sigquit);
756: }
757: }
758:
759: readch ()
760: {
761: int c;
762: static FILE *rcf;
763: static nbol; /* 0 if at beginning of a line */
764:
765: if (rcf == NULL) {
766: rcf = fopen ("/dev/tty", "r");
767: setbuf (rcf, NULL);
768: }
769:
770: if (!nbol)
771: fprintf (stderr, "hc: "); /* issue prompt */
772: if ((c = getc (rcf)) == EOF)
773: return 0;
774: nbol = (c != '\n');
775: return c;
776: }
777:
778: store(c)
779: {
780: int i, j;
781:
782: i = hpos / hscale;
783: j = vpos / vscale;
784: if (i >= PGWIDTH)
785: i = PGWIDTH - 1;
786: if (j >= PGHEIGHT)
787: j = PGHEIGHT - 1;
788: /* note the reversal! */
789: pagebuf[j][i] = c;
790: if (i > maxh)
791: maxh = i;
792: if (i < minh)
793: minh = i;
794: if (j > maxv)
795: maxv = j;
796: if (j < minv)
797: minv = j;
798: }
799:
800: char *spectab[] ={
801: "em", "-",
802: "hy", "-",
803: "bu", "o",
804: "mu", "x",
805: "sq", "[]",
806: "en", "-",
807: "ru", "_",
808: "l.", ".",
809: "br", "|",
810: "vr", "|",
811: "fm", "'",
812: "or", "|",
813: "pl", "+",
814: "ci", "O",
815: "**", "*",
816: 0, 0,
817: };
818:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.