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