Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * n1.c
3
 *
4
 *	consume options, initialization, main loop,
5
 *	input routines, escape function calling
6
 */
7
 
8
#include "tdef.h"
9
#include "fns.h"
10
#include "ext.h"
11
#include "dwbinit.h"
12
 
13
#include <setjmp.h>
14
#include <time.h>
15
 
16
char	*Version	= "March 11, 1994";
17
 
18
#ifndef DWBVERSION
19
#define DWBVERSION      "???"
20
#endif
21
 
22
char	*DWBfontdir = FONTDIR;
23
char	*DWBntermdir = NTERMDIR;
24
char	*DWBalthyphens = ALTHYPHENS;
25
char	*DWBhomedir = "";
26
 
27
dwbinit dwbpaths[] = {
28
	&DWBfontdir, NULL, 0,
29
	&DWBntermdir, NULL, 0,
30
	&DWBalthyphens, NULL, 0,
31
	&DWBhomedir, NULL, 0,
32
	NULL, nextf, NS,
33
	NULL, NULL, 0
34
};
35
 
36
int	TROFF	= 1;	/* assume we started in troff... */
37
 
38
jmp_buf sjbuf;
39
Offset	ipl[NSO];
40
 
41
static	FILE	*ifile	= stdin;
42
static	FILE	*ifl[NSO];	/* open input file pointers */
43
char	cfname[NSO+1][NS] = {  "stdin" };	/* file name stack */
44
int	cfline[NSO];		/* input line count stack */
45
char	*progname;		/* program name (troff or nroff) */
46
 
47
int	trace = 0;	/* tracing mode: default off */
48
int	trace1 = 0;
49
 
50
main(int argc, char *argv[])
51
{
52
	char *p;
53
	int j;
54
	Tchar i;
55
	char buf[100];
56
 
57
	buf[0] = '\0';		/* make sure it's empty (silly 3b2) */
58
	progname = argv[0];
59
	if ((p = strrchr(progname, '/')) == NULL)
60
		p = progname;
61
	else
62
		p++;
63
	DWBinit(progname, dwbpaths);
64
	if (strcmp(p, "nroff") == 0)
65
		TROFF = 0;
66
#ifdef UNICODE
67
	alphabet = 128;	/* unicode for plan 9 */
68
#endif	/*UNICODE*/
69
	mnspace();
70
	nnspace();
71
	mrehash();
72
	nrehash();
73
	numtabp[NL].val = -1;
74
 
75
	while (--argc > 0 && (++argv)[0][0] == '-')
76
		switch (argv[0][1]) {
77
 
78
		case 'N':	/* ought to be used first... */
79
			TROFF = 0;
80
			break;
81
		case 'd':
82
			fprintf(stderr, "troff/nroff version %s\n", Version);
83
			break;
84
		case 'F':	/* switch font tables from default */
85
			if (argv[0][2] != '\0') {
86
				strcpy(termtab, &argv[0][2]);
87
				strcpy(fontdir, &argv[0][2]);
88
			} else {
89
				argv++; argc--;
90
				strcpy(termtab, argv[0]);
91
				strcpy(fontdir, argv[0]);
92
			}
93
			break;
94
		case 0:
95
			goto start;
96
		case 'i':
97
			stdi++;
98
			break;
99
		case 'n':
100
			npn = atoi(&argv[0][2]);
101
			break;
102
		case 'u':	/* set emboldening amount */
103
			bdtab[3] = atoi(&argv[0][2]);
104
			if (bdtab[3] < 0 || bdtab[3] > 50)
105
				bdtab[3] = 0;
106
			break;
107
		case 's':
108
			if (!(stop = atoi(&argv[0][2])))
109
				stop++;
110
			break;
111
		case 'r':
112
			sprintf(buf + strlen(buf), ".nr %c %s\n",
113
				argv[0][2], &argv[0][3]);
114
			/* not yet cpushback(buf);*/
115
			/* dotnr(&argv[0][2], &argv[0][3]); */
116
			break;
117
		case 'm':
118
			if (mflg++ >= NMF) {
119
				ERROR "Too many macro packages: %s", argv[0] WARN;
120
				break;
121
			}
122
			strcpy(mfiles[nmfi], nextf);
123
			strcat(mfiles[nmfi++], &argv[0][2]);
124
			break;
125
		case 'o':
126
			getpn(&argv[0][2]);
127
			break;
128
		case 'T':
129
			strcpy(devname, &argv[0][2]);
130
			dotT++;
131
			break;
132
		case 'a':
133
			ascii = 1;
134
			break;
135
		case 'h':
136
			hflg++;
137
			break;
138
		case 'e':
139
			eqflg++;
140
			break;
141
		case 'q':
142
			quiet++;
143
			save_tty();
144
			break;
145
		case 'V':
146
			fprintf(stdout, "%croff: DWB %s\n", 
147
					TROFF ? 't' : 'n', DWBVERSION);
148
			exit(0);
149
		case 't':
150
			if (argv[0][2] != '\0')
151
				trace = trace1 = argv[0][2];
152
			break;		/* for the sake of compatibility */
153
		default:
154
			ERROR "unknown option %s", argv[0] WARN;
155
			done(02);
156
		}
157
 
158
start:
159
	/*
160
	 * cpushback maintains a LIFO, so push pack the -r arguments
161
	 * in reverse order to maintain a FIFO in case someone did -rC1 -rC3
162
	 */
163
	if (buf[0]) {
164
		char *p = buf;
165
		while(*p++)
166
			;
167
		while(p > buf) {
168
			while(strncmp(p, ".nr", 3) != 0)
169
				p--;
170
			cpushback(p);
171
			*p-- = '\0';
172
		}
173
	}
174
	argp = argv;
175
	rargc = argc;
176
	nmfi = 0;
177
	init2();
178
	setjmp(sjbuf);
179
loop:
180
	copyf = lgf = nb = nflush = nlflg = 0;
181
	if (ip && rbf0(ip) == 0 && ejf && frame->pframe <= ejl && dip == d) {
182
		nflush++;
183
		trap = 0;
184
		eject((Stack *)0);
185
		goto loop;
186
	}
187
	i = getch();
188
	if (pendt)
189
		goto Lt;
190
	if ((j = cbits(i)) == XPAR) {
191
		copyf++;
192
		tflg++;
193
		while (cbits(i) != '\n')
194
			pchar(i = getch());
195
		tflg = 0;
196
		copyf--;			/* pointless */
197
		goto loop;
198
	}
199
	if (j == cc || j == c2) {
200
		if (j == c2)
201
			nb++;
202
		copyf++;
203
		while ((j = cbits(i = getch())) == ' ' || j == '\t')
204
			;
205
		ch = i;
206
		copyf--;
207
		control(getrq(), 1);
208
		flushi();
209
		goto loop;
210
	}
211
Lt:
212
	ch = i;
213
	text();
214
	if (nlflg)
215
		numtabp[HP].val = 0;
216
	goto loop;
217
}
218
 
219
 
220
 
221
void init2(void)
222
{
223
	int i;
224
	char buf[100];
225
 
226
	for (i = NTRTAB; --i; )
227
		trtab[i] = i;
228
	trtab[UNPAD] = ' ';
229
	iflg = 0;
230
	obufp = obuf;
231
	if (TROFF)
232
		t_ptinit();
233
	else
234
		n_ptinit();
235
	mchbits();
236
	cvtime();
237
	numtabp[PID].val = getpid();
238
	numtabp[HP].val = init = 0;
239
	numtabp[NL].val = -1;
240
	nfo = 0;
241
	copyf = raw = 0;
242
	sprintf(buf, ".ds .T %s\n", devname);
243
	cpushback(buf);
244
	sprintf(buf, ".ds .P %s\n", DWBhomedir);
245
	cpushback(buf);
246
	numtabp[CD].val = -1;	/* compensation */
247
	nx = mflg;
248
	frame = stk = (Stack *)setbrk(STACKSIZE);
249
	dip = &d[0];
250
	nxf = frame + 1;
251
	for (i = 1; i < NEV; i++)	/* propagate the environment */
252
		envcopy(&env[i], &env[0]);
253
	for (i = 0; i < NEV; i++) {
254
		if ((env[i]._word._bufp = (Tchar *)calloc(WDSIZE, sizeof(Tchar))) == NULL) {
255
			ERROR "not enough room for word buffers" WARN;
256
			done2(1);
257
		}
258
		env[i]._word._size = WDSIZE;
259
		if ((env[i]._line._bufp = (Tchar *)calloc(LNSIZE, sizeof(Tchar))) == NULL) {
260
			ERROR "not enough room for line buffers" WARN;
261
			done2(1);
262
		}
263
		env[i]._line._size = LNSIZE;
264
	}
265
	if ((oline = (Tchar *)calloc(OLNSIZE, sizeof(Tchar))) == NULL) {
266
		ERROR "not enough room for line buffers" WARN;
267
		done2(1);
268
	}
269
	olinep = oline;
270
	olnsize = OLNSIZE;
271
	blockinit();
272
}
273
 
274
void cvtime(void)
275
{
276
	long tt;
277
	struct tm *ltime;
278
 
279
	time(&tt);
280
	ltime = localtime(&tt);
281
	numtabp[YR].val = ltime->tm_year % 100;
282
	numtabp[YR].fmt = 2;
283
	numtabp[MO].val = ltime->tm_mon + 1;	/* troff uses 1..12 */
284
	numtabp[DY].val = ltime->tm_mday;
285
	numtabp[DW].val = ltime->tm_wday + 1;	/* troff uses 1..7 */
286
}
287
 
288
 
289
 
290
char	errbuf[200];
291
 
292
void errprint(void)	/* error message printer */
293
{
294
	int savecd = numtabp[CD].val;
295
 
296
	if (!nlflg)
297
		numtabp[CD].val++;
298
 
299
	fprintf(stderr, "%s: ", progname);
300
	fputs(errbuf, stderr);
301
	if (cfname[ifi][0])
302
		fprintf(stderr, "; %s:%d", cfname[ifi], numtabp[CD].val);
303
	fputs("\n", stderr);
304
	if (cfname[ifi][0])
305
		stackdump();
306
	numtabp[CD].val = savecd;
307
}
308
 
309
 
310
int control(int a, int b)
311
{
312
	int j, k;
313
	extern Contab *contabp;
314
 
315
	numerr.type = RQERR;
316
	numerr.req = a;
317
	if (a == 0 || (j = findmn(a)) == -1)
318
		return(0);
319
	if (contabp[j].f == 0) {
320
		if (trace & TRMAC)
321
			fprintf(stderr, "invoke macro %s\n", unpair(a));
322
		if (dip != d)
323
			for (k = dilev; k; k--)
324
				if (d[k].curd == a) {
325
					ERROR "diversion %s invokes itself during diversion",
326
								unpair(a) WARN;
327
					edone(0100);
328
				}
329
		nxf->nargs = 0;
330
		if (b)
331
			collect();
332
		flushi();
333
		return pushi(contabp[j].mx, a);	/* BUG??? all that matters is 0/!0 */
334
	}
335
	if (b) {
336
		if (trace & TRREQ)
337
			fprintf(stderr, "invoke request %s\n", unpair(a));
338
		 (*contabp[j].f)();
339
	}
340
	return(0);
341
}
342
 
343
void casept(void)
344
{
345
	int i;
346
 
347
	noscale++;
348
	if (skip())
349
		i = trace1;
350
	else {
351
		i = max(inumb(&trace), 0);
352
		if (nonumb)
353
			i = trace1;
354
	}
355
	trace1 = trace;
356
	trace = i;
357
	noscale = 0;
358
}
359
 
360
 
361
int getrq(void)
362
{
363
	int i, j;
364
 
365
	if ((i = getach()) == 0 || (j = getach()) == 0)
366
		goto rtn;
367
	i = PAIR(i, j);
368
rtn:
369
	return(i);
370
}
371
 
372
/*
373
 * table encodes some special characters, to speed up tests
374
 * in getch, viz FLSS, RPT, f, \b, \n, fc, tabch, ldrch
375
 */
376
 
377
char gchtab[NCHARS] = {
378
	000,004,000,000,010,000,000,000, /* fc, ldr */
379
	001,002,001,000,001,000,000,000, /* \b, tab, nl, RPT */
380
	000,000,000,000,000,000,000,000,
381
	000,001,000,001,000,000,000,000, /* FLSS, ESC */
382
	000,000,000,000,000,000,000,000,
383
	000,000,000,000,000,000,000,000,
384
	000,000,000,000,000,000,000,000,
385
	000,000,000,000,000,000,000,000,
386
	000,000,000,000,000,000,000,000,
387
	000,000,000,000,000,000,000,000,
388
	000,000,000,000,000,000,000,000,
389
	000,000,000,000,000,000,000,000,
390
	000,000,000,000,000,000,001,000, /* f */
391
	000,000,000,000,000,000,000,000,
392
	000,000,000,000,000,000,000,000,
393
	000,000,000,000,000,000,000,000,
394
};
395
 
396
int realcbits(Tchar c)	/* return character bits, or MOTCH if motion */
397
{
398
	if (ismot(c))
399
		return MOTCH;
400
	else
401
		return c & 0xFFFF;
402
}
403
 
404
Tchar getch(void)
405
{
406
	int k;
407
	Tchar i, j;
408
 
409
g0:
410
	if (ch) {
411
		i = ch;
412
		if (cbits(i) == '\n')
413
			nlflg++;
414
		ch = 0;
415
		return(i);
416
	}
417
 
418
	if (nlflg)
419
		return('\n');
420
	i = getch0();
421
	if (ismot(i))
422
		return(i);
423
	k = cbits(i);
424
	if (k >= sizeof(gchtab)/sizeof(gchtab[0]) || gchtab[k] == 0)	/* nothing special */
425
		return(i);
426
	if (k != ESC) {
427
		if (k == '\n') {
428
			nlflg++;
429
			if (ip == 0)
430
				numtabp[CD].val++; /* line number */
431
			return(k);
432
		}
433
		if (k == FLSS) {
434
			copyf++; 
435
			raw++;
436
			i = getch0();
437
			if (!fi)
438
				flss = i;
439
			copyf--; 
440
			raw--;
441
			goto g0;
442
		}
443
		if (k == RPT) {
444
			setrpt();
445
			goto g0;
446
		}
447
		if (!copyf) {
448
			if (k == 'f' && lg && !lgf) {
449
				i = getlg(i);
450
				return(i);
451
			}
452
			if (k == fc || k == tabch || k == ldrch) {
453
				if ((i = setfield(k)) == 0)
454
					goto g0; 
455
				else 
456
					return(i);
457
			}
458
			if (k == '\b') {
459
				i = makem(-width(' ' | chbits));
460
				return(i);
461
			}
462
		}
463
		return(i);
464
	}
465
 
466
	k = cbits(j = getch0());
467
	if (ismot(j))
468
		return(j);
469
 
470
	switch (k) {
471
	case 'n':	/* number register */
472
		setn();
473
		goto g0;
474
	case '$':	/* argument indicator */
475
		seta();
476
		goto g0;
477
	case '*':	/* string indicator */
478
		setstr();
479
		goto g0;
480
	case '{':	/* LEFT */
481
		i = LEFT;
482
		goto gx;
483
	case '}':	/* RIGHT */
484
		i = RIGHT;
485
		goto gx;
486
	case '"':	/* comment */
487
		while (cbits(i = getch0()) != '\n')
488
			;
489
		if (ip == 0)
490
			numtabp[CD].val++; /* line number */
491
		nlflg++;
492
		return(i);
493
 
494
/* experiment: put it here instead of copy mode */
495
	case '(':	/* special char name \(xx */
496
	case 'C':	/* 		\C'...' */
497
		if ((i = setch(k)) == 0)
498
			goto g0;
499
		goto gx;
500
 
501
	case ESC:	/* double backslash */
502
		i = eschar;
503
		goto gx;
504
	case 'e':	/* printable version of current eschar */
505
		i = PRESC;
506
		goto gx;
507
	case '\n':	/* concealed newline */
508
		numtabp[CD].val++;
509
		goto g0;
510
	case ' ':	/* unpaddable space */
511
		i = UNPAD;
512
		goto gx;
513
	case '\'':	/* \(aa */
514
		i = ACUTE;
515
		goto gx;
516
	case '`':	/* \(ga */
517
		i = GRAVE;
518
		goto gx;
519
	case '_':	/* \(ul */
520
		i = UNDERLINE;
521
		goto gx;
522
	case '-':	/* current font minus */
523
		i = MINUS;
524
		goto gx;
525
	case '&':	/* filler */
526
		i = FILLER;
527
		goto gx;
528
	case 'c':	/* to be continued */
529
		i = CONT;
530
		goto gx;
531
	case '!':	/* transparent indicator */
532
		i = XPAR;
533
		goto gx;
534
	case 't':	/* tab */
535
		i = '\t';
536
		return(i);
537
	case 'a':	/* leader (SOH) */
538
/* old:		*pbp++ = LEADER; goto g0; */
539
		i = LEADER;
540
		return i;
541
	case '%':	/* ohc */
542
		i = OHC;
543
		return(i);
544
	case 'g':	/* return format of a number register */
545
		setaf();	/* should this really be in copy mode??? */
546
		goto g0;
547
	case '.':	/* . */
548
		i = '.';
549
gx:
550
		setsfbits(i, sfbits(j));
551
		return(i);
552
	}
553
	if (copyf) {
554
		*pbp++ = j;
555
		return(eschar);
556
	}
557
	switch (k) {
558
 
559
	case 'f':	/* font indicator */
560
		setfont(0);
561
		goto g0;
562
	case 's':	/* size indicator */
563
		setps();
564
		goto g0;
565
	case 'v':	/* vert mot */
566
		numerr.type = numerr.escarg = 0; numerr.esc = k;
567
		if (i = vmot()) {
568
			return(i);
569
		}
570
		goto g0;
571
	case 'h': 	/* horiz mot */
572
		numerr.type = numerr.escarg = 0; numerr.esc = k;
573
		if (i = hmot())
574
			return(i);
575
		goto g0;
576
	case '|':	/* narrow space */
577
		if (NROFF)
578
			goto g0;
579
		return(makem((int)(EM)/6));
580
	case '^':	/* half narrow space */
581
		if (NROFF)
582
			goto g0;
583
		return(makem((int)(EM)/12));
584
	case 'w':	/* width function */
585
		setwd();
586
		goto g0;
587
	case 'p':	/* spread */
588
		spread++;
589
		goto g0;
590
	case 'N':	/* absolute character number */
591
		numerr.type = numerr.escarg = 0; numerr.esc = k;
592
		if ((i = setabs()) == 0)
593
			goto g0;
594
		return i;
595
	case 'H':	/* character height */
596
		numerr.type = numerr.escarg = 0; numerr.esc = k;
597
		return(setht());
598
	case 'S':	/* slant */
599
		numerr.type = numerr.escarg = 0; numerr.esc = k;
600
		return(setslant());
601
	case 'z':	/* zero with char */
602
		return(setz());
603
	case 'l':	/* hor line */
604
		numerr.type = numerr.escarg = 0; numerr.esc = k;
605
		setline();
606
		goto g0;
607
	case 'L':	/* vert line */
608
		numerr.type = numerr.escarg = 0; numerr.esc = k;
609
		setvline();
610
		goto g0;
611
	case 'D':	/* drawing function */
612
		numerr.type = numerr.escarg = 0; numerr.esc = k;
613
		setdraw();
614
		goto g0;
615
	case 'X':	/* \X'...' for copy through */
616
		setxon();
617
		goto g0;
618
	case 'b':	/* bracket */
619
		setbra();
620
		goto g0;
621
	case 'o':	/* overstrike */
622
		setov();
623
		goto g0;
624
	case 'k':	/* mark hor place */
625
		if ((k = findr(getsn())) != -1) {
626
			numtabp[k].val = numtabp[HP].val;
627
		}
628
		goto g0;
629
	case '0':	/* number space */
630
		return(makem(width('0' | chbits)));
631
	case 'x':	/* extra line space */
632
		numerr.type = numerr.escarg = 0; numerr.esc = k;
633
		if (i = xlss())
634
			return(i);
635
		goto g0;
636
	case 'u':	/* half em up */
637
	case 'r':	/* full em up */
638
	case 'd':	/* half em down */
639
		return(sethl(k));
640
	default:
641
		return(j);
642
	}
643
	/* NOTREACHED */
644
}
645
 
646
void setxon(void)	/* \X'...' for copy through */
647
{
648
	Tchar xbuf[NC];
649
	Tchar *i;
650
	Tchar c;
651
	int delim, k;
652
 
653
	if (ismot(c = getch()))
654
		return;
655
	delim = cbits(c);
656
	i = xbuf;
657
	*i++ = XON | chbits;
658
	while ((k = cbits(c = getch())) != delim && k != '\n' && i < xbuf+NC-1) {
659
		if (k == ' ')
660
			setcbits(c, WORDSP);
661
		*i++ = c | ZBIT;
662
	}
663
	*i++ = XOFF | chbits;
664
	*i = 0;
665
	pushback(xbuf);
666
}
667
 
668
 
669
char	ifilt[32] = { 0, 001, 002, 003, 0, 005, 006, 007, 010, 011, 012 };
670
 
671
Tchar getch0(void)
672
{
673
	Tchar i;
674
 
675
again:
676
	if (pbp > lastpbp)
677
		i = *--pbp;
678
	else if (ip) {
679
		/* i = rbf(); */
680
		i = rbf0(ip);
681
		if (i == 0)
682
			i = rbf();
683
		else {
684
			++ip;
685
			if (pastend(ip)) {
686
				--ip;
687
				rbf();
688
			}
689
		}
690
	} else {
691
		if (donef || ndone)
692
			done(0);
693
		if (nx || 1) {	/* BUG: was ibufp >= eibuf, so EOF test is wrong */
694
			if (nfo < 0)
695
				ERROR "in getch0, nfo = %d", nfo WARN;
696
			if (nfo == 0) {
697
g0:
698
				if (nextfile()) {
699
					if (ip)
700
						goto again;
701
				}
702
			}
703
			nx = 0;
704
#ifdef UNICODE
705
			if (MB_CUR_MAX > 1)
706
				i = get1ch(ifile);
707
			else
708
#endif	/*UNICODE*/
709
				i = getc(ifile);
710
			if (i == EOF)
711
				goto g0;
712
			if (ip)
713
				goto again;
714
		}
715
		if (i >= 040)			/* zapped: && i < 0177 */
716
			goto g4;
717
		i = ifilt[i];
718
	}
719
	if (cbits(i) == IMP && !raw)
720
		goto again;
721
	if (i == 0 && !init && !raw) {		/* zapped:  || i == 0177 */
722
		goto again;
723
	}
724
g4:
725
	if (ismot(i))
726
		return i;
727
	if (copyf == 0 && sfbits(i) == 0)
728
		i |= chbits;
729
	if (cbits(i) == eschar && !raw)
730
		setcbits(i, ESC);
731
	return(i);
732
}
733
 
734
 
735
#ifdef UNICODE
736
Tchar get1ch(FILE *fp)	/* get one "character" from input, figure out what alphabet */
737
{
738
	wchar_t wc;
739
	char buf[100], *p;
740
	int i, n, c;
741
 
742
	n = c = 0;
743
	for (i = 0, p = buf; i < MB_CUR_MAX; i++) {
744
		if ((c = getc(fp)) == EOF)
745
			return c;
746
		*p++ = c;
747
		if ((n = mbtowc(&wc, buf, p-buf)) >= 0)
748
			break;
749
	}
750
	if (n == 1)	/* real ascii, presumably */
751
		return wc;
752
	if (n == 0)
753
		return p[-1];	/* illegal, but what else to do? */
754
	if (c == EOF)
755
		return EOF;
756
	*p = 0;
757
	return chadd(buf, MBchar, Install);	/* add name even if haven't seen it */
758
}
759
#endif	/*UNICODE*/
760
 
761
void pushback(Tchar *b)
762
{
763
	Tchar *ob = b;
764
 
765
	while (*b++)
766
		;
767
	b--;
768
	while (b > ob && pbp < &pbbuf[NC-3])
769
		*pbp++ = *--b;
770
	if (pbp >= &pbbuf[NC-3]) {
771
		ERROR "pushback overflow" WARN;
772
		done(2);
773
	}
774
}
775
 
776
void cpushback(char *b)
777
{
778
	char *ob = b;
779
 
780
	while (*b++)
781
		;
782
	b--;
783
	while (b > ob && pbp < &pbbuf[NC-3])
784
		*pbp++ = *--b;
785
	if (pbp >= &pbbuf[NC-3]) {
786
		ERROR "cpushback overflow" WARN;
787
		done(2);
788
	}
789
}
790
 
791
int nextfile(void)
792
{
793
	char *p;
794
 
795
n0:
796
	if (ifile != stdin)
797
		fclose(ifile);
798
	if (ifi > 0 && !nx) {
799
		if (popf())
800
			goto n0; /* popf error */
801
		return(1);	 /* popf ok */
802
	}
803
	if (nx || nmfi < mflg) {
804
		p = mfiles[nmfi++];
805
		if (*p != 0)
806
			goto n1;
807
	}
808
	if (rargc-- <= 0) {
809
		if ((nfo -= mflg) && !stdi) {
810
			done(0);
811
}
812
		nfo++;
813
		numtabp[CD].val = stdi = mflg = 0;
814
		ifile = stdin;
815
		strcpy(cfname[ifi], "stdin");
816
		return(0);
817
	}
818
	p = (argp++)[0];
819
	if (rargc >= 0)
820
		cfname[ifi][0] = 0;
821
n1:
822
	numtabp[CD].val = 0;
823
	if (p[0] == '-' && p[1] == 0) {
824
		ifile = stdin;
825
		strcpy(cfname[ifi], "stdin");
826
	} else if ((ifile = fopen(p, "r")) == NULL) {
827
		ERROR "cannot open file %s", p WARN;
828
		nfo -= mflg;
829
		done(02);
830
	} else
831
		strcpy(cfname[ifi],p);
832
	nfo++;
833
	return(0);
834
}
835
 
836
 
837
popf(void)
838
{
839
	--ifi;
840
	if (ifi < 0) {
841
		ERROR "popf went negative" WARN;
842
		return 1;
843
	}
844
	numtabp[CD].val = cfline[ifi];	/* restore line counter */
845
	ip = ipl[ifi];			/* input pointer */
846
	ifile = ifl[ifi];		/* input FILE * */
847
	return(0);
848
}
849
 
850
 
851
void flushi(void)
852
{
853
	if (nflush)
854
		return;
855
	ch = 0;
856
	copyf++;
857
	while (!nlflg) {
858
		if (donef && frame == stk)
859
			break;
860
		getch();
861
	}
862
	copyf--;
863
}
864
 
865
/*
866
 * return 16-bit, ascii/alphabetic character, ignore chars with more bits,
867
 * (internal names), spaces and special cookies (below 040).
868
 * Leave STX ETX ENQ ACK and BELL in to maintain compatibility with v7 troff.
869
 */
870
getach(void)
871
{
872
	Tchar i;
873
	int j;
874
 
875
	lgf++;
876
	j = cbits(i = getch());
877
        if (ismot(i)
878
	    || j > SHORTMASK
879
	    || (j <= 040 && j != 002	/*STX*/
880
			&& j != 003	/*ETX*/
881
			&& j != 005	/*ENQ*/
882
			&& j != 006	/*ACK*/
883
			&& j != 007)) {	/*BELL*/
884
		ch = i;
885
		j = 0;
886
	}
887
	lgf--;
888
	return j;
889
}
890
 
891
 
892
void casenx(void)
893
{
894
	lgf++;
895
	skip();
896
	getname();
897
	nx++;
898
	if (nmfi > 0)
899
		nmfi--;
900
	strcpy(mfiles[nmfi], nextf);
901
	nextfile();
902
	nlflg++;
903
	ip = 0;
904
	pendt = 0;
905
	frame = stk;
906
	nxf = frame + 1;
907
}
908
 
909
 
910
getname(void)
911
{
912
	int j, k;
913
 
914
	lgf++;
915
	for (k = 0; k < NS - 1; k++) {
916
		j = getach();
917
		if (!j)
918
			break;
919
		nextf[k] = j;
920
	}
921
	nextf[k] = 0;
922
	lgf--;
923
	return(nextf[0]);
924
}
925
 
926
 
927
void caseso(void)
928
{
929
	FILE *fp;
930
 
931
	lgf++;
932
	nextf[0] = 0;
933
	fp = NULL;
934
	if (skip() || !getname() || (fp = fopen(nextf, "r")) == NULL || ifi >= NSO) {
935
		ERROR "can't open file %s", nextf WARN;
936
		done(02);
937
	}
938
	strcpy(cfname[ifi+1], nextf);
939
	cfline[ifi] = numtabp[CD].val;		/*hold line counter*/
940
	numtabp[CD].val = 0;
941
	flushi();
942
	ifl[ifi] = ifile;
943
	ifile = fp;
944
	ipl[ifi] = ip;
945
	ip = 0;
946
	nx++;
947
	nflush++;
948
	ifi++;
949
}
950
 
951
void caself(void)	/* set line number and file */
952
{
953
	int n;
954
 
955
	if (skip())
956
		return;
957
	n = atoi0();
958
	if (!nonumb)
959
		cfline[ifi] = numtabp[CD].val = n - 1;
960
	if (!skip())
961
		if (getname()) {	/* eats '\n' ? */
962
			strcpy(cfname[ifi], nextf);
963
			if (!nonumb)
964
				numtabp[CD].val--;
965
		}
966
}
967
 
968
void cpout(FILE *fin, char *token)
969
{
970
	int n;
971
	char buf[1024];
972
 
973
	if (token) {	/* BUG: There should be no NULL bytes in input */
974
		char *newl = buf;
975
		while ((fgets(buf, sizeof buf, fin)) != NULL) {
976
			if (newl) {
977
				numtabp[CD].val++; /* line number */
978
				if (strcmp(token, buf) == 0)
979
					return;
980
			}
981
			newl = strchr(buf, '\n');
982
			fputs(buf, ptid);
983
		}
984
	} else {
985
		while ((n = fread(buf, sizeof *buf, sizeof buf, fin)) > 0)
986
			fwrite(buf, n, 1, ptid);
987
		fclose(fin);
988
	}
989
}
990
 
991
void casecf(void)
992
{	/* copy file without change */
993
	FILE *fd;
994
	char *eof, *p;
995
	extern int hpos, esc, po;
996
 
997
	/* this may not make much sense in nroff... */
998
 
999
	lgf++;
1000
	nextf[0] = 0;
1001
	if (!skip() && getname()) {
1002
		if (strncmp("<<", nextf, 2) != 0) {
1003
			if ((fd = fopen(nextf, "r")) == NULL) {
1004
				ERROR "can't open file %s", nextf WARN;
1005
				done(02);
1006
			}
1007
			eof = (char *) NULL;
1008
		} else {	/* current file */
1009
			if (pbp > lastpbp || ip) {
1010
				ERROR "casecf: not reading from file" WARN;
1011
				done(02);
1012
			}
1013
			eof = &nextf[2];
1014
			if (!*eof)  {
1015
				ERROR "casecf: missing end of input token" WARN;
1016
				done(02);
1017
			}
1018
			p = eof;
1019
			while(*++p)
1020
				;
1021
			*p++ = '\n';
1022
			*p = 0;
1023
			fd = ifile;
1024
		}
1025
	} else {
1026
		ERROR "casecf: no argument" WARN;
1027
		lgf--;
1028
		return;
1029
	}
1030
	lgf--;
1031
 
1032
	/* make it into a clean state, be sure that everything is out */
1033
	tbreak();
1034
	hpos = po;
1035
	esc = 0;
1036
	ptesc();	/* to left margin */
1037
	esc = un;
1038
	ptesc();
1039
	ptlead();
1040
	ptps();
1041
	ptfont();
1042
	flusho();
1043
	cpout(fd, eof);
1044
	ptps();
1045
	ptfont();
1046
}
1047
 
1048
void getline(char *s, int n)	/* get rest of input line into s */
1049
{
1050
	int i;
1051
 
1052
	lgf++;
1053
	copyf++;
1054
	skip();
1055
	for (i = 0; i < n-1; i++)
1056
		if ((s[i] = cbits(getch())) == '\n' || s[i] == RIGHT)
1057
			break;
1058
	s[i] = 0;
1059
	copyf--;
1060
	lgf--;
1061
}
1062
 
1063
void casesy(void)	/* call system */
1064
{
1065
	char sybuf[NTM];
1066
 
1067
	getline(sybuf, NTM);
1068
	system(sybuf);
1069
}
1070
 
1071
 
1072
void getpn(char *a)
1073
{
1074
	int n, neg;
1075
 
1076
	if (*a == 0)
1077
		return;
1078
	neg = 0;
1079
	for ( ; *a; a++)
1080
		switch (*a) {
1081
		case '+':
1082
		case ',':
1083
			continue;
1084
		case '-':
1085
			neg = 1;
1086
			continue;
1087
		default:
1088
			n = 0;
1089
			if (isdigit(*a)) {
1090
				do
1091
					n = 10 * n + *a++ - '0';
1092
				while (isdigit(*a));
1093
				a--;
1094
			} else
1095
				n = 9999;
1096
			*pnp++ = neg ? -n : n;
1097
			neg = 0;
1098
			if (pnp >= &pnlist[NPN-2]) {
1099
				ERROR "too many page numbers" WARN;
1100
				done3(-3);
1101
			}
1102
		}
1103
	if (neg)
1104
		*pnp++ = -9999;
1105
	*pnp = -INT_MAX;
1106
	print = 0;
1107
	pnp = pnlist;
1108
	if (*pnp != -INT_MAX)
1109
		chkpn();
1110
}
1111
 
1112
 
1113
void setrpt(void)
1114
{
1115
	Tchar i, j;
1116
 
1117
	copyf++;
1118
	raw++;
1119
	i = getch0();
1120
	copyf--;
1121
	raw--;
1122
	if ((long) i < 0 || cbits(j = getch0()) == RPT)
1123
		return;
1124
	while (i > 0 && pbp < &pbbuf[NC-3]) {
1125
		i--;
1126
		*pbp++ = j;
1127
	}
1128
}