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 2004 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 char *xxxvers = "@(#)roff:n1.c 2.13";
43 /*
44 * n1.c
45 *
46 * consume options, initialization, main loop,
47 * input routines, escape function calling
48 */
49
50 #include <ctype.h>
51 #include <signal.h>
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <setjmp.h>
55 #include <time.h>
56 #include <stdarg.h>
57 #include <locale.h>
58 #include <fcntl.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #ifdef EUC
62 #ifdef NROFF
63 #include <stddef.h>
64 #include <limits.h>
65 #endif /* NROFF */
66 #endif /* EUC */
67
68 #include "tdef.h"
69 #include "ext.h"
70
71 #ifdef NROFF
72 #include "tw.h"
73 #endif
74
75 #define MAX_RECURSION_DEPTH 512
76
77 jmp_buf sjbuf;
78 extern void fdprintf(int, char *, ...);
79 extern char *roff_sprintf(char *, char *, ...);
80 filep ipl[NSO];
81 long offl[NSO];
82 long ioff;
83 char *ttyp;
84 char cfname[NSO+1][NS]; /*file name stack*/
85 int cfline[NSO]; /*input line count stack*/
86 char *progname; /* program name (troff) */
87 #ifdef EUC
88 #ifdef NROFF
89 char mbbuf1[MB_LEN_MAX + 1];
90 char *mbbuf1p = mbbuf1;
91 wchar_t twc = 0;
92 #endif /* NROFF */
93 #endif /* EUC */
94
95 #ifdef DEBUG
96 int debug = 0; /*debug flag*/
97 #endif /* DEBUG */
98
99 static char *sprintn(char *, long, int);
100 static int printn(long, int);
101
102 int
main(int argc,char ** argv)103 main(int argc, char **argv)
104 {
105 char *p, *q;
106 int j;
107 tchar i;
108 int eileenct; /*count to test for "Eileen's loop"*/
109 extern void catch(), kcatch();
110 char **oargv, *getenv();
111
112 (void)setlocale(LC_ALL, "");
113 #if !defined(TEXT_DOMAIN)
114 #define TEXT_DOMAIN "SYS_TEST"
115 #endif
116 (void)textdomain(TEXT_DOMAIN);
117 progname = argv[0];
118 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
119 signal(SIGHUP, catch);
120 if (signal(SIGINT, catch) == SIG_IGN) {
121 signal(SIGHUP, SIG_IGN);
122 signal(SIGINT, SIG_IGN);
123 signal(SIGQUIT, SIG_IGN);
124 }
125 signal(SIGPIPE, catch);
126 signal(SIGTERM, kcatch);
127 oargv = argv;
128 strcpy(cfname[0], "<standard input>");
129 mrehash();
130 nrehash();
131 init0();
132 #ifdef EUC
133 #ifdef NROFF
134 (void)localize();
135 #endif /* NROFF */
136 #endif /* EUC */
137 if ((p = getenv("TYPESETTER")) != 0)
138 strcpy(devname, p);
139 while (--argc > 0 && (++argv)[0][0] == '-')
140 switch (argv[0][1]) {
141
142 case 'F': /* switch font tables from default */
143 if (argv[0][2] != '\0') {
144 strcpy(termtab, &argv[0][2]);
145 strcpy(fontfile, &argv[0][2]);
146 } else {
147 argv++; argc--;
148 if (argv[0] != '\0') {
149 strcpy(termtab, argv[0]);
150 strcpy(fontfile, argv[0]);
151 } else
152 errprint(gettext("missing the font directory"));
153 }
154 continue;
155 case 0:
156 goto start;
157 case 'i':
158 stdi++;
159 continue;
160 case 'q':
161 #ifdef NROFF
162 quiet++;
163 save_tty();
164 #else
165 errprint(gettext("-q option ignored in troff"));
166 #endif /* NROFF */
167 continue;
168 case 'n':
169 npn = ctoi(&argv[0][2]);
170 continue;
171 case 'u': /* set emboldening amount */
172 bdtab[3] = ctoi(&argv[0][2]);
173 if (bdtab[3] < 0 || bdtab[3] > 50)
174 bdtab[3] = 0;
175 continue;
176 case 's':
177 if (!(stop = ctoi(&argv[0][2])))
178 stop++;
179 continue;
180 case 't':
181 ptid = 1;
182 continue;
183 case 'r':
184 if (&argv[0][2] != '\0' && strlen(&argv[0][2]) >= 2 && &argv[0][3] != '\0')
185 eibuf = roff_sprintf(ibuf+strlen(ibuf), ".nr %c %s\n",
186 argv[0][2], &argv[0][3]);
187 else
188 errprint(gettext("wrong options"));
189 continue;
190 case 'c':
191 case 'm':
192 if (mflg++ >= NMF) {
193 errprint(gettext("Too many macro packages: %s"),
194 argv[0]);
195 continue;
196 }
197 if (argv[0][2] == '\0') {
198 errprint(gettext("No library provided with -m"));
199 done(02);
200 }
201 if (getenv("TROFFMACS") != '\0') {
202 if (tryfile(getenv("TROFFMACS"), &argv[0][2], nmfi))
203 nmfi++;
204 } else
205 if (tryfile("/usr/share/lib/tmac/", &argv[0][2], nmfi)
206 || tryfile("/usr/share/lib/tmac/tmac.", &argv[0][2], nmfi))
207 nmfi++;
208 else {
209 errprint(gettext("Cannot find library %s\n"),
210 argv[0]);
211 done(02);
212 }
213 continue;
214 case 'o':
215 getpn(&argv[0][2]);
216 continue;
217 case 'T':
218 strcpy(devname, &argv[0][2]);
219 dotT++;
220 continue;
221 #ifdef NROFF
222 case 'h':
223 hflg++;
224 continue;
225 case 'z':
226 no_out++;
227 continue;
228 case 'e':
229 eqflg++;
230 continue;
231 #endif
232 #ifndef NROFF
233 case 'z':
234 no_out++;
235 case 'a':
236 ascii = 1;
237 nofeed++;
238 continue;
239 case 'f':
240 nofeed++;
241 continue;
242 #endif
243 case '#':
244 #ifdef DEBUG
245 debug = ctoi(&argv[0][2]);
246 #else
247 errprint("DEBUG not enabled");
248 #endif /* DEBUG */
249 continue;
250 default:
251 errprint(gettext("unknown option %s"), argv[0]);
252 done(02);
253 }
254
255 start:
256 init1(oargv[0][0]);
257 argp = argv;
258 rargc = argc;
259 nmfi = 0;
260 init2();
261 setjmp(sjbuf);
262 eileenct = 0; /*reset count for "Eileen's loop"*/
263 loop:
264 copyf = lgf = nb = nflush = nlflg = 0;
265 if (ip && rbf0(ip) == 0 && ejf && frame->pframe <= ejl) {
266 nflush++;
267 trap = 0;
268 eject((struct s *)0);
269 #ifdef DEBUG
270 if (debug & DB_LOOP)
271 fdprintf(stderr, "loop: NL=%d, ejf=%d, lss=%d, eileenct=%d\n",
272 numtab[NL].val, ejf, lss, eileenct);
273 #endif /* DEBUG */
274 if (eileenct > 20) {
275 errprint(gettext("job looping; check abuse of macros"));
276 ejf = 0; /*try to break Eileen's loop*/
277 eileenct = 0;
278 } else
279 eileenct++;
280 goto loop;
281 }
282 eileenct = 0; /*reset count for "Eileen's loop"*/
283 i = getch();
284 if (pendt)
285 goto Lt;
286 if ((j = cbits(i)) == XPAR) {
287 copyf++;
288 tflg++;
289 while (cbits(i) != '\n')
290 pchar(i = getch());
291 tflg = 0;
292 copyf--;
293 goto loop;
294 }
295 if (j == cc || j == c2) {
296 if (j == c2)
297 nb++;
298 copyf++;
299 while ((j = cbits(i = getch())) == ' ' || j == '\t')
300 ;
301 ch = i;
302 copyf--;
303 control(getrq(), 1);
304 flushi();
305 goto loop;
306 }
307 Lt:
308 ch = i;
309 text();
310 if (nlflg)
311 numtab[HP].val = 0;
312 goto loop;
313 }
314
315
316 int
tryfile(pat,fn,idx)317 tryfile(pat, fn, idx)
318 char *pat, *fn;
319 int idx;
320 {
321 strcpy(mfiles[idx], pat);
322 strcat(mfiles[idx], fn);
323 if (access(mfiles[idx], 4) == -1)
324 return(0);
325 else return(1);
326 }
327
catch()328 void catch()
329 {
330 done3(01);
331 }
332
333
kcatch()334 void kcatch()
335 {
336 signal(SIGTERM, SIG_IGN);
337 done3(01);
338 }
339
340 int
init0()341 init0()
342 {
343 eibuf = ibufp = ibuf;
344 ibuf[0] = 0;
345 numtab[NL].val = -1;
346 return (0);
347 }
348
349
350 int
init1(a)351 init1(a)
352 char a;
353 {
354 char *p;
355 int i;
356
357 p = tmp_name;
358 if (a == 'a')
359 p = &p[9];
360 if ((ibf = mkstemp(p)) == -1) {
361 errprint(gettext("cannot create temp file."));
362 exit(-1);
363 }
364 unlkp = p;
365 for (i = NTRTAB; --i; )
366 trtab[i] = i;
367 trtab[UNPAD] = ' ';
368 return (0);
369 }
370
371
372 int
init2()373 init2()
374 {
375 int i, j;
376 extern char *setbrk();
377 extern char *ttyname();
378
379 ttyod = 2;
380 if ((ttyp=ttyname(j=0)) != 0 || (ttyp=ttyname(j=1)) != 0 || (ttyp=ttyname(j=2)) != 0)
381 ;
382 else
383 ttyp = "notty";
384 iflg = j;
385 if (ascii)
386 mesg(0);
387 obufp = obuf;
388 ptinit();
389 mchbits();
390 cvtime();
391 numtab[PID].val = getpid();
392 olinep = oline;
393 ioff = 0;
394 numtab[HP].val = init = 0;
395 numtab[NL].val = -1;
396 nfo = 0;
397 ifile = 0;
398 copyf = raw = 0;
399 eibuf = roff_sprintf(ibuf+strlen(ibuf), ".ds .T %s\n", devname);
400 numtab[CD].val = -1; /* compensation */
401 cpushback(ibuf);
402 ibufp = ibuf;
403 nx = mflg;
404 frame = stk = (struct s *)setbrk(DELTA);
405 dip = &d[0];
406 nxf = frame + 1;
407 #ifdef INCORE
408 for (i = 0; i < NEV; i++) {
409 extern tchar corebuf[];
410 *(struct env *)&corebuf[i * sizeof(env)/sizeof(tchar)] = env;
411 }
412 #else
413 for (i = NEV; i--; )
414 write(ibf, (char *) & env, sizeof(env));
415 #endif
416 return (0);
417 }
418
419 int
cvtime()420 cvtime()
421 {
422 time_t tt;
423 struct tm *tm;
424
425 tt = time((time_t *) 0);
426 tm = localtime(&tt);
427 numtab[DY].val = tm->tm_mday;
428 numtab[DW].val = tm->tm_wday + 1;
429 numtab[YR].val = tm->tm_year;
430 numtab[MO].val = tm->tm_mon + 1;
431
432 return (0);
433 }
434
435
436 int
ctoi(s)437 ctoi(s)
438 char *s;
439 {
440 int n;
441
442 while (*s == ' ')
443 s++;
444 n = 0;
445 while (isdigit((unsigned char)*s))
446 n = 10 * n + *s++ - '0';
447 return n;
448 }
449
450
451 int
mesg(f)452 mesg(f)
453 int f;
454 {
455 static int mode;
456 struct stat stbuf;
457
458 if (!f) {
459 stat(ttyp, &stbuf);
460 mode = stbuf.st_mode;
461 chmod(ttyp, mode & ~0122); /* turn off writing for others */
462 } else {
463 if (ttyp && *ttyp && mode)
464 chmod(ttyp, mode);
465 }
466
467 return (0);
468 }
469
470 int
errprint(s,s1,s2,s3,s4,s5)471 errprint(s, s1, s2, s3, s4, s5) /* error message printer */
472 char *s, *s1, *s2, *s3, *s4, *s5;
473 {
474 fdprintf(stderr, "%s: ", progname);
475 fdprintf(stderr, s, s1, s2, s3, s4, s5);
476 if (numtab[CD].val > 0)
477 fdprintf(stderr, gettext("; line %d, file %s"), numtab[CD].val,
478 cfname[ifi]);
479 fdprintf(stderr, "\n");
480 stackdump();
481 #ifdef DEBUG
482 if (debug)
483 abort();
484 #endif /* DEBUG */
485 return (0);
486 }
487
488
489 /*
490 * Scaled down version of C Library printf.
491 * Only %s %u %d (==%u) %o %c %x %D are recognized.
492 */
493 #undef putchar
494 #define putchar(n) (*pfbp++ = (n)) /* NO CHECKING! */
495
496 static char pfbuf[NTM];
497 static char *pfbp = pfbuf;
498 int stderr = 2; /* NOT stdio value */
499
500 void
fdprintf(int fd,char * fmt,...)501 fdprintf(int fd, char *fmt, ...)
502 {
503 int c;
504 char *s;
505 int i;
506 va_list ap;
507
508 pfbp = pfbuf;
509 va_start(ap, fmt);
510 loop:
511 while ((c = *fmt++) != '%') {
512 if (c == '\0') {
513 if (fd == stderr)
514 write(stderr, pfbuf, pfbp - pfbuf);
515 else {
516 *pfbp = 0;
517 pfbp = pfbuf;
518 while (*pfbp) {
519 *obufp++ = *pfbp++;
520 if (obufp >= &obuf[OBUFSZ])
521 flusho();
522 }
523 }
524 va_end(ap);
525 return;
526 }
527 putchar(c);
528 }
529 c = *fmt++;
530 if (c == 'd') {
531 i = va_arg(ap, int);
532 if (i < 0) {
533 putchar('-');
534 i = -i;
535 }
536 printn((long)i, 10);
537 } else if (c == 'u' || c == 'o' || c == 'x')
538 printn(va_arg(ap, long), c == 'o' ? 8 : (c == 'x' ? 16 : 10));
539 else if (c == 'c') {
540 if (c > 0177 || c < 040)
541 putchar('\\');
542 putchar(va_arg(ap, int) & 0177);
543 } else if (c == 's') {
544 s = va_arg(ap, char *);
545 while (c = *s++)
546 putchar(c);
547 } else if (c == 'D') {
548 printn(va_arg(ap, long), 10);
549 } else if (c == 'O') {
550 printn(va_arg(ap, long), 8);
551 }
552 goto loop;
553 }
554
555
556 /*
557 * Print an unsigned integer in base b.
558 */
559 static int
printn(n,b)560 printn(n, b)
561 long n;
562 int b;
563 {
564 long a;
565
566 if (n < 0) { /* shouldn't happen */
567 putchar('-');
568 n = -n;
569 }
570 if (a = n / b)
571 printn(a, b);
572 putchar("0123456789ABCDEF"[(int)(n%b)]);
573
574 return (0);
575 }
576
577 /* scaled down version of library roff_sprintf */
578 /* same limits as fdprintf */
579 /* returns pointer to \0 that ends the string */
580
581 /* VARARGS2 */
roff_sprintf(char * str,char * fmt,...)582 char *roff_sprintf(char *str, char *fmt, ...)
583 {
584 int c;
585 char *s;
586 int i;
587 va_list ap;
588
589 va_start(ap, fmt);
590 loop:
591 while ((c = *fmt++) != '%') {
592 if (c == '\0') {
593 *str = 0;
594 va_end(ap);
595 return str;
596 }
597 *str++ = c;
598 }
599 c = *fmt++;
600 if (c == 'd') {
601 i = va_arg(ap, int);
602 if (i < 0) {
603 *str++ = '-';
604 i = -i;
605 }
606 str = sprintn(str, (long)i, 10);
607 } else if (c == 'u' || c == 'o' || c == 'x')
608 str = sprintn(str, va_arg(ap, long), c == 'o' ? 8 : (c == 'x' ? 16 : 10));
609 else if (c == 'c') {
610 if (c > 0177 || c < 040)
611 *str++ = '\\';
612 *str++ = va_arg(ap, int) & 0177;
613 } else if (c == 's') {
614 s = va_arg(ap, char *);
615 while (c = *s++)
616 *str++ = c;
617 } else if (c == 'D') {
618 str = sprintn(str, va_arg(ap, long), 10);
619 } else if (c == 'O') {
620 str = sprintn(str, va_arg(ap, unsigned) , 8);
621 }
622 goto loop;
623 }
624
625 /*
626 * Print an unsigned integer in base b.
627 */
sprintn(s,n,b)628 static char *sprintn(s, n, b)
629 char *s;
630 long n;
631 int b;
632 {
633 long a;
634
635 if (n < 0) { /* shouldn't happen */
636 *s++ = '-';
637 n = -n;
638 }
639 if (a = n / b)
640 s = sprintn(s, a, b);
641 *s++ = "0123456789ABCDEF"[(int)(n%b)];
642 return s;
643 }
644
645
646 int
control(a,b)647 control(a, b)
648 int a, b;
649 {
650 int j;
651
652 if (a == 0 || (j = findmn(a)) == -1)
653 return(0);
654
655 /*
656 * Attempt to find endless recursion at runtime. Arbitrary
657 * recursion limit of MAX_RECURSION_DEPTH was chosen as
658 * it is extremely unlikely that a correct nroff/troff
659 * invocation would exceed this value.
660 */
661
662 if (frame != stk) {
663 int frame_cnt = 0;
664 struct s *p;
665
666 for (p = frame; p != stk; p = p->pframe)
667 frame_cnt++;
668 if (frame_cnt > MAX_RECURSION_DEPTH) {
669 errprint(
670 gettext("Exceeded maximum stack size (%d) when "
671 "executing macro %c%c. Stack dump follows"),
672 MAX_RECURSION_DEPTH,
673 frame->mname & 0177, (frame->mname >> BYTE) & 0177);
674 edone(02);
675 }
676 }
677
678 #ifdef DEBUG
679 if (debug & DB_MAC)
680 fdprintf(stderr, "control: macro %c%c, contab[%d]\n",
681 a&0177, (a>>BYTE)&0177 ? (a>>BYTE)&0177 : ' ', j);
682 #endif /* DEBUG */
683 if (contab[j].f == 0) {
684 nxf->nargs = 0;
685 if (b)
686 collect();
687 flushi();
688 return pushi((filep)contab[j].mx, a);
689 } else if (b)
690 return((*contab[j].f)(0));
691 else
692 return(0);
693 }
694
695 int
getrq()696 getrq()
697 {
698 int i, j;
699
700 if (((i = getach()) == 0) || ((j = getach()) == 0))
701 goto rtn;
702 i = PAIR(i, j);
703 rtn:
704 return(i);
705 }
706
707 /*
708 * table encodes some special characters, to speed up tests
709 * in getchar, viz FLSS, RPT, f, \b, \n, fc, tabch, ldrch
710 */
711
712 char
713 gchtab[] = {
714 000,004,000,000,010,000,000,000, /* fc, ldr */
715 001,002,001,000,001,000,000,000, /* \b, tab, nl, RPT */
716 000,000,000,000,000,000,000,000,
717 000,001,000,000,000,000,000,000, /* FLSS */
718 000,000,000,000,000,000,000,000,
719 000,000,000,000,000,000,000,000,
720 000,000,000,000,000,000,000,000,
721 000,000,000,000,000,000,000,000,
722 000,000,000,000,000,000,000,000,
723 000,000,000,000,000,000,000,000,
724 000,000,000,000,000,000,000,000,
725 000,000,000,000,000,000,000,000,
726 000,000,000,000,000,000,001,000, /* f */
727 000,000,000,000,000,000,000,000,
728 000,000,000,000,000,000,000,000,
729 000,000,000,000,000,000,000,000,
730 };
731
732 tchar
getch()733 getch()
734 {
735 int k;
736 tchar i, j;
737 tchar setht(), setslant();
738
739 g0:
740 if (i = ch) {
741 #ifdef DEBUG
742 if (debug & DB_GETC)
743 fdprintf(stderr, "getch: ch is %x (%c)\n",
744 ch, (ch&0177) < 040 ? 0177 : ch&0177);
745 #endif /* DEBUG */
746 if (cbits(i) == '\n')
747 nlflg++;
748 ch = 0;
749 return(i);
750 }
751
752 #ifdef DEBUG
753 if (nlflg)
754 if (debug & DB_GETC)
755 fdprintf(stderr,"getch: nlflg is %x\n", nlflg);
756 #endif /* DEBUG */
757 if (nlflg)
758 return('\n');
759 i = getch0();
760 #ifdef DEBUG
761 if (debug & DB_GETC)
762 fdprintf(stderr, "getch: getch0 returns %x (%c)\n",
763 i, (i&0177) < 040 ? 0177 : i&0177);
764 #endif /* DEBUG */
765 if (ismot(i))
766 return(i);
767 k = cbits(i);
768 if (k != ESC) {
769 /*
770 * gchtab[] has only 128 entries
771 * if k is out of the range, it should be
772 * handled as gchtab[k] == 0
773 */
774 if (!isascii(k) || gchtab[k]==0)
775 return(i);
776 if (k == '\n') {
777 if (cbits(i) == '\n') {
778 nlflg++;
779 if (ip == 0)
780 numtab[CD].val++; /* line number */
781 }
782 return(k);
783 }
784 if (k == FLSS) {
785 copyf++;
786 raw++;
787 i = getch0();
788 if (!fi)
789 flss = i;
790 copyf--;
791 raw--;
792 goto g0;
793 }
794 if (k == RPT) {
795 setrpt();
796 goto g0;
797 }
798 if (!copyf) {
799 if (k == 'f' && lg && !lgf) {
800 i = getlg(i);
801 return(i);
802 }
803 if (k == fc || k == tabch || k == ldrch) {
804 if ((i = setfield(k)) == 0)
805 goto g0;
806 else
807 return(i);
808 }
809 if (k == '\b') {
810 i = makem(-width(' ' | chbits));
811 return(i);
812 }
813 }
814 return(i);
815 }
816 k = cbits(j = getch0());
817 if (ismot(j))
818 return(j);
819 switch (k) {
820
821 case 'X': /* \X'...' for copy through */
822 setxon();
823 goto g0;
824 case '\n': /* concealed newline */
825 goto g0;
826 case 'n': /* number register */
827 setn();
828 goto g0;
829 case '*': /* string indicator */
830 setstr();
831 goto g0;
832 case '$': /* argument indicator */
833 seta();
834 goto g0;
835 case '{': /* LEFT */
836 i = LEFT;
837 goto gx;
838 case '}': /* RIGHT */
839 i = RIGHT;
840 goto gx;
841 case '"': /* comment */
842 while (cbits(i = getch0()) != '\n')
843 ;
844 nlflg++;
845 if (ip == 0)
846 numtab[CD].val++;
847 return(i);
848 case ESC: /* double backslash */
849 i = eschar;
850 goto gx;
851 case 'e': /* printable version of current eschar */
852 i = PRESC;
853 goto gx;
854 case ' ': /* unpaddable space */
855 i = UNPAD;
856 goto gx;
857 case '\'': /* \(aa */
858 i = ACUTE;
859 goto gx;
860 case '`': /* \(ga */
861 i = GRAVE;
862 goto gx;
863 case '_': /* \(ul */
864 i = UNDERLINE;
865 goto gx;
866 case '-': /* current font minus */
867 i = MINUS;
868 goto gx;
869 case '&': /* filler */
870 i = FILLER;
871 goto gx;
872 case 'c': /* to be continued */
873 i = CONT;
874 goto gx;
875 case '!': /* transparent indicator */
876 i = XPAR;
877 goto gx;
878 case 't': /* tab */
879 i = '\t';
880 return(i);
881 case 'a': /* leader (SOH) */
882 i = LEADER;
883 return(i);
884 case '%': /* ohc */
885 i = OHC;
886 return(i);
887 case 'g': /* return format of a number register */
888 setaf();
889 goto g0;
890 case 'N': /* absolute character number */
891 i = setabs();
892 goto gx;
893 case '.': /* . */
894 i = '.';
895 gx:
896 setsfbits(i, sfbits(j));
897 return(i);
898 }
899 if (copyf) {
900 *pbp++ = j;
901 return(eschar);
902 }
903 switch (k) {
904
905 case 'p': /* spread */
906 spread++;
907 goto g0;
908 case '(': /* special char name */
909 if ((i = setch()) == 0)
910 goto g0;
911 return(i);
912 case 's': /* size indicator */
913 setps();
914 goto g0;
915 case 'H': /* character height */
916 return(setht());
917 case 'S': /* slant */
918 return(setslant());
919 case 'f': /* font indicator */
920 setfont(0);
921 goto g0;
922 case 'w': /* width function */
923 setwd();
924 goto g0;
925 case 'v': /* vert mot */
926 if (i = vmot())
927 return(i);
928 goto g0;
929 case 'h': /* horiz mot */
930 if (i = hmot())
931 return(i);
932 goto g0;
933 case 'z': /* zero with char */
934 return(setz());
935 case 'l': /* hor line */
936 setline();
937 goto g0;
938 case 'L': /* vert line */
939 setvline();
940 goto g0;
941 case 'D': /* drawing function */
942 setdraw();
943 goto g0;
944 case 'b': /* bracket */
945 setbra();
946 goto g0;
947 case 'o': /* overstrike */
948 setov();
949 goto g0;
950 case 'k': /* mark hor place */
951 if ((k = findr(getsn())) != -1) {
952 numtab[k].val = numtab[HP].val;
953 }
954 goto g0;
955 case '0': /* number space */
956 return(makem(width('0' | chbits)));
957 #ifdef NROFF
958 case '|':
959 case '^':
960 goto g0;
961 #else
962 case '|': /* narrow space */
963 return(makem((int)(EM)/6));
964 case '^': /* half narrow space */
965 return(makem((int)(EM)/12));
966 #endif
967 case 'x': /* extra line space */
968 if (i = xlss())
969 return(i);
970 goto g0;
971 case 'u': /* half em up */
972 case 'r': /* full em up */
973 case 'd': /* half em down */
974 return(sethl(k));
975 default:
976 return(j);
977 }
978 /* NOTREACHED */
979 }
980
981 int
setxon()982 setxon() /* \X'...' for copy through */
983 {
984 tchar xbuf[NC];
985 tchar *i;
986 tchar c;
987 int delim, k;
988
989 if (ismot(c = getch()))
990 return (0);
991 delim = cbits(c);
992 i = xbuf;
993 *i++ = XON;
994 while ((k = cbits(c = getch())) != delim && k != '\n' && i < xbuf+NC-1) {
995 if (k == ' ')
996 setcbits(c, UNPAD);
997 *i++ = c | ZBIT;
998 }
999 *i++ = XOFF;
1000 *i = 0;
1001 pushback(xbuf);
1002
1003 return (0);
1004 }
1005
1006
1007 char ifilt[32] = {
1008 0, 001, 002, 003, 0, 005, 006, 007, 010, 011, 012};
1009
getch0()1010 tchar getch0()
1011 {
1012 int j;
1013 tchar i;
1014 #ifdef EUC
1015 #ifdef NROFF
1016 int n;
1017 int col_index;
1018 #endif /* NROFF */
1019 #endif /* EUC */
1020
1021 again:
1022 if (pbp > lastpbp)
1023 i = *--pbp;
1024 else if (ip) {
1025 #ifdef INCORE
1026 extern tchar corebuf[];
1027 i = corebuf[ip];
1028 if (i == 0)
1029 i = rbf();
1030 else {
1031 if ((++ip & (BLK - 1)) == 0) {
1032 --ip;
1033 (void)rbf();
1034 }
1035 }
1036 #else
1037 i = rbf();
1038 #endif
1039 } else {
1040 if (donef || ndone)
1041 done(0);
1042 if (nx || ibufp >= eibuf) {
1043 if (nfo==0) {
1044 g0:
1045 if (nextfile()) {
1046 if (ip)
1047 goto again;
1048 if (ibufp < eibuf)
1049 goto g2;
1050 }
1051 }
1052 nx = 0;
1053 if ((j = read(ifile, ibuf, IBUFSZ)) <= 0)
1054 goto g0;
1055 ibufp = ibuf;
1056 eibuf = ibuf + j;
1057 if (ip)
1058 goto again;
1059 }
1060 g2:
1061 #ifndef EUC
1062 i = *ibufp++ & 0177;
1063 ioff++;
1064 if (i >= 040 && i < 0177)
1065 #else
1066 #ifndef NROFF
1067 i = *ibufp++ & 0177;
1068 ioff++;
1069 if (i >= 040 && i < 0177)
1070 #else
1071 i = *ibufp++ & 0377;
1072 *mbbuf1p++ = i;
1073 *mbbuf1p = 0;
1074 if (!multi_locale) {
1075 twc = 0;
1076 mbbuf1p = mbbuf1;
1077 } else if ((n = mbtowc(&twc, mbbuf1, MB_CUR_MAX)) <= 0) {
1078 if (mbbuf1p >= mbbuf1 + MB_CUR_MAX) {
1079 i &= ~(MBMASK | CSMASK);
1080 twc = 0;
1081 mbbuf1p = mbbuf1;
1082 *mbbuf1p = 0;
1083 } else {
1084 i |= (MIDDLEOFMB);
1085 }
1086 } else {
1087 if (n > 1)
1088 i |= (LASTOFMB);
1089 else
1090 i |= (BYTE_CHR);
1091 if (isascii(twc)) {
1092 col_index = 0;
1093 } else {
1094 if ((col_index = wcwidth(twc)) < 0)
1095 col_index = 0;
1096 }
1097 setcsbits(i, col_index);
1098 twc = 0;
1099 mbbuf1p = mbbuf1;
1100 }
1101 ioff++;
1102 if (i >= 040 && i != 0177)
1103 #endif /* NROFF */
1104 #endif /* EUC */
1105 goto g4;
1106 if (i != 0177)
1107 i = ifilt[i];
1108 }
1109 if (cbits(i) == IMP && !raw)
1110 goto again;
1111 if ((i == 0 || i == 0177) && !init && !raw) {
1112 goto again;
1113 }
1114 g4:
1115 #ifndef EUC
1116 if (copyf == 0 && (i & ~BYTEMASK) == 0)
1117 #else
1118 #ifndef NROFF
1119 if (copyf == 0 && (i & ~BYTEMASK) == 0)
1120 #else
1121 if (copyf == 0 && (i & ~CHMASK) == 0)
1122 #endif /* NROFF */
1123 #endif /* EUC */
1124 i |= chbits;
1125 #ifdef EUC
1126 #ifdef NROFF
1127 if (multi_locale)
1128 if (i & MBMASK1)
1129 i |= ZBIT;
1130 #endif /* NROFF */
1131 #endif /* EUC */
1132 if (cbits(i) == eschar && !raw)
1133 setcbits(i, ESC);
1134 return(i);
1135 }
1136
1137 int
pushback(b)1138 pushback(b)
1139 tchar *b;
1140 {
1141 tchar *ob = b;
1142
1143 while (*b++)
1144 ;
1145 b--;
1146 while (b > ob && pbp < &pbbuf[NC-3])
1147 *pbp++ = *--b;
1148 if (pbp >= &pbbuf[NC-3]) {
1149 errprint(gettext("pushback overflow"));
1150 done(2);
1151 }
1152
1153 return (0);
1154 }
1155
1156 int
cpushback(b)1157 cpushback(b)
1158 char *b;
1159 {
1160 char *ob = b;
1161
1162 while (*b++)
1163 ;
1164 b--;
1165 while (b > ob && pbp < &pbbuf[NC-3])
1166 *pbp++ = *--b;
1167 if (pbp >= &pbbuf[NC-3]) {
1168 errprint(gettext("cpushback overflow"));
1169 done(2);
1170 }
1171
1172 return (0);
1173 }
1174
1175 int
nextfile()1176 nextfile()
1177 {
1178 char *p;
1179
1180 n0:
1181 if (ifile)
1182 close(ifile);
1183 if (nx || nmfi < mflg) {
1184 p = mfiles[nmfi++];
1185 if (*p != 0)
1186 goto n1;
1187 }
1188 if (ifi > 0) {
1189 if (popf())
1190 goto n0; /* popf error */
1191 return(1); /* popf ok */
1192 }
1193 if (rargc-- <= 0) {
1194 if ((nfo -= mflg) && !stdi)
1195 done(0);
1196 nfo++;
1197 numtab[CD].val = ifile = stdi = mflg = 0;
1198 strcpy(cfname[ifi], "<standard input>");
1199 ioff = 0;
1200 return(0);
1201 }
1202 p = (argp++)[0];
1203 n1:
1204 numtab[CD].val = 0;
1205 if (p[0] == '-' && p[1] == 0) {
1206 ifile = 0;
1207 strcpy(cfname[ifi], "<standard input>");
1208 } else if ((ifile = open(p, 0)) < 0) {
1209 errprint(gettext("cannot open file %s"), p);
1210 nfo -= mflg;
1211 done(02);
1212 } else
1213 strcpy(cfname[ifi],p);
1214 nfo++;
1215 ioff = 0;
1216 return(0);
1217 }
1218
1219
1220 int
popf()1221 popf()
1222 {
1223 int i;
1224 char *p, *q;
1225 extern char *ttyname();
1226
1227 ioff = offl[--ifi];
1228 numtab[CD].val = cfline[ifi]; /*restore line counter*/
1229 ip = ipl[ifi];
1230 if ((ifile = ifl[ifi]) == 0) {
1231 p = xbuf;
1232 q = ibuf;
1233 ibufp = xbufp;
1234 eibuf = xeibuf;
1235 while (q < eibuf)
1236 *q++ = *p++;
1237 return(0);
1238 }
1239 if (lseek(ifile, (long)(ioff & ~(IBUFSZ-1)), 0) == (long) -1
1240 || (i = read(ifile, ibuf, IBUFSZ)) < 0)
1241 return(1);
1242 eibuf = ibuf + i;
1243 ibufp = ibuf;
1244 if (ttyname(ifile) == 0)
1245 /* was >= ... */
1246 if ((ibufp = ibuf + (int)(ioff & (IBUFSZ - 1))) > eibuf)
1247 return(1);
1248 return(0);
1249 }
1250
1251
1252 int
flushi()1253 flushi()
1254 {
1255 if (nflush)
1256 return (0);
1257 ch = 0;
1258 copyf++;
1259 while (!nlflg) {
1260 if (donef && (frame == stk))
1261 break;
1262 getch();
1263 }
1264 copyf--;
1265
1266 return (0);
1267 }
1268
1269
1270 int
getach()1271 getach()
1272 {
1273 tchar i;
1274 int j;
1275
1276 lgf++;
1277 j = cbits(i = getch());
1278 #ifndef EUC
1279 if (ismot(i) || j == ' ' || j == '\n' || j & 0200) {
1280 #else
1281 #ifndef NROFF
1282 if (ismot(i) || j == ' ' || j == '\n' || j & 0200) {
1283 #else
1284 if (ismot(i) || j == ' ' || j == '\n' || j > 0200) {
1285 #endif /* NROFF */
1286 #endif /* EUC */
1287
1288 ch = i;
1289 j = 0;
1290 }
1291 lgf--;
1292 return(j & 0177);
1293 }
1294
1295
1296 int
1297 casenx()
1298 {
1299 lgf++;
1300 skip();
1301 getname();
1302 nx++;
1303 if (nmfi > 0)
1304 nmfi--;
1305 strcpy(mfiles[nmfi], nextf);
1306 nextfile();
1307 nlflg++;
1308 ip = 0;
1309 pendt = 0;
1310 frame = stk;
1311 nxf = frame + 1;
1312
1313 return (0);
1314 }
1315
1316
1317 int
1318 getname()
1319 {
1320 int j, k;
1321 tchar i;
1322
1323 lgf++;
1324 for (k = 0; k < (NS - 1); k++) {
1325 #ifndef EUC
1326 if (((j = cbits(i = getch())) <= ' ') || (j > 0176))
1327 #else
1328 #ifndef NROFF
1329 if (((j = cbits(i = getch())) <= ' ') || (j > 0176))
1330 #else
1331 if (((j = cbits(i = getch())) <= ' ') || (j == 0177))
1332 #endif /* NROFF */
1333 #endif /* EUC */
1334 break;
1335 nextf[k] = j & BYTEMASK;
1336 }
1337 nextf[k] = 0;
1338 ch = i;
1339 lgf--;
1340 return((int)nextf[0]);
1341 }
1342
1343
1344 int
1345 caseso()
1346 {
1347 int i;
1348 char *p, *q;
1349
1350 lgf++;
1351 nextf[0] = 0;
1352 if (skip() || !getname() || ((i = open(nextf, 0)) < 0) || (ifi >= NSO)) {
1353 errprint(gettext("can't open file %s"), nextf);
1354 done(02);
1355 }
1356 strcpy(cfname[ifi+1], nextf);
1357 cfline[ifi] = numtab[CD].val; /*hold line counter*/
1358 numtab[CD].val = 0;
1359 flushi();
1360 ifl[ifi] = ifile;
1361 ifile = i;
1362 offl[ifi] = ioff;
1363 ioff = 0;
1364 ipl[ifi] = ip;
1365 ip = 0;
1366 nx++;
1367 nflush++;
1368 if (!ifl[ifi++]) {
1369 p = ibuf;
1370 q = xbuf;
1371 xbufp = ibufp;
1372 xeibuf = eibuf;
1373 while (p < eibuf)
1374 *q++ = *p++;
1375 }
1376
1377 return (0);
1378 }
1379
1380 int
1381 caself() /* set line number and file */
1382 {
1383 int n;
1384
1385 if (skip())
1386 return (0);
1387 n = atoi();
1388 cfline[ifi] = numtab[CD].val = n - 2;
1389 if (skip())
1390 return (0);
1391 if (getname())
1392 strcpy(cfname[ifi], nextf);
1393
1394 return (0);
1395 }
1396
1397
1398 int
1399 casecf()
1400 { /* copy file without change */
1401 #ifndef NROFF
1402 int fd, n;
1403 char buf[512];
1404 extern int hpos, esc, po;
1405 nextf[0] = 0;
1406 if (skip() || !getname() || (fd = open(nextf, 0)) < 0) {
1407 errprint(gettext("can't open file %s"), nextf);
1408 done(02);
1409 }
1410 tbreak();
1411 /* make it into a clean state, be sure that everything is out */
1412 hpos = po;
1413 esc = un;
1414 ptesc();
1415 ptlead();
1416 ptps();
1417 ptfont();
1418 flusho();
1419 while ((n = read(fd, buf, sizeof buf)) > 0)
1420 write(ptid, buf, n);
1421 close(fd);
1422 #endif
1423 return (0);
1424 }
1425
1426
1427 int
1428 casesy() /* call system */
1429 {
1430 char sybuf[NTM];
1431 int i;
1432
1433 lgf++;
1434 copyf++;
1435 skip();
1436 for (i = 0; i < NTM - 2; i++)
1437 if ((sybuf[i] = getch()) == '\n')
1438 break;
1439 sybuf[i] = 0;
1440 system(sybuf);
1441 copyf--;
1442 lgf--;
1443
1444 return (0);
1445 }
1446
1447
1448 int
1449 getpn(a)
1450 char *a;
1451 {
1452 int n, neg;
1453
1454 if (*a == 0)
1455 return (0);
1456 neg = 0;
1457 for ( ; *a; a++)
1458 switch (*a) {
1459 case '+':
1460 case ',':
1461 continue;
1462 case '-':
1463 neg = 1;
1464 continue;
1465 default:
1466 n = 0;
1467 if (isdigit((unsigned char)*a)) {
1468 do
1469 n = 10 * n + *a++ - '0';
1470 while (isdigit((unsigned char)*a));
1471 a--;
1472 } else
1473 n = 9999;
1474 *pnp++ = neg ? -n : n;
1475 neg = 0;
1476 if (pnp >= &pnlist[NPN-2]) {
1477 errprint(gettext("too many page numbers"));
1478 done3(-3);
1479 }
1480 }
1481 if (neg)
1482 *pnp++ = -9999;
1483 *pnp = -32767;
1484 print = 0;
1485 pnp = pnlist;
1486 if (*pnp != -32767)
1487 chkpn();
1488
1489 return (0);
1490 }
1491
1492
1493 int
1494 setrpt()
1495 {
1496 tchar i, j;
1497
1498 copyf++;
1499 raw++;
1500 i = getch0();
1501 copyf--;
1502 raw--;
1503 if (i < 0 || cbits(j = getch0()) == RPT)
1504 return (0);
1505 i &= BYTEMASK;
1506 while (i>0 && pbp < &pbbuf[NC-3]) {
1507 i--;
1508 *pbp++ = j;
1509 }
1510
1511 return (0);
1512 }
1513
1514
1515 int
1516 casedb()
1517 {
1518 #ifdef DEBUG
1519 debug = 0;
1520 if (skip())
1521 return (0);
1522 noscale++;
1523 debug = max(atoi(), 0);
1524 noscale = 0;
1525 #endif /* DEBUG */
1526
1527 return (0);
1528 }
1529