~ubuntu-branches/ubuntu/oneiric/9base/oneiric

« back to all changes in this revision

Viewing changes to troff/n1.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-11-07 12:25:14 UTC
  • mfrom: (6.2.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091107122514-tcw4u4ha2w2xbbnn
Tags: 1:4-1
* Adding maintainer homepage field to control.
* Marking maintainer homepage field to be also included in binary
  packages and changelog.
* Adding README.source.
* Merging upstream version 4.
* Adding sh4 to explicit architecture list (Closes: #545772).
* Moving maintainer homepage field from control to copyright.
* Updating README.source.
* Updating homepage field in control.
* Removing manpage patch, went upstream.
* Removing kfreebsd.patch, went upstream.
* Generalizing manpage moving in rules.
* Moving base directory from /usr/lib/9base to /usr/lib/plan9 for
  consistency reasons.
* Prefixing manpages with plan9 instead of 9base for consistency
  reasons.
* Bumping versioned build-depends on debhelper.
* Making internal mkMAP and sendcover scripts executable.
* Adding patch to adjust shebang in newly included troff commands.
* Updating lintian-overrides.
* Making buildd-depends on quilt versioned.

Show diffs side-by-side

added added

removed removed

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