~ubuntu-branches/ubuntu/saucy/9base/saucy

« back to all changes in this revision

Viewing changes to troff/n3.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
* 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
 * troff3.c
 
3
 * 
 
4
 * macro and string routines, storage allocation
 
5
 */
 
6
 
 
7
#include "tdef.h"
 
8
#include "fns.h"
 
9
#include "ext.h"
 
10
 
 
11
Tchar   *argtop;
 
12
int     pagech = '%';
 
13
int     strflg;
 
14
 
 
15
#define MHASHSIZE       128     /* must be 2**n */
 
16
#define MHASH(x)        ((x>>6)^x) & (MHASHSIZE-1)
 
17
Contab  *mhash[MHASHSIZE];
 
18
 
 
19
 
 
20
Blockp  *blist;         /* allocated blocks for macros and strings */
 
21
int     nblist;         /* how many there are */
 
22
int     bfree = -1;     /* first (possible) free block in the list */
 
23
 
 
24
Contab *contabp = NULL;
 
25
#define MDELTA 500
 
26
int     nm = 0;
 
27
 
 
28
int savname;            /* name of macro/string being defined */
 
29
int savslot;            /* place in Contab of savname */
 
30
int freeslot = -1;      /* first (possible) free slot in contab */
 
31
 
 
32
void prcontab(Contab *p)
 
33
{
 
34
        int i;
 
35
        for (i = 0; i < nm; i++)
 
36
                if (p)
 
37
                        if (p[i].rq != 0)
 
38
                                fprintf(stderr, "slot %d, %-2.2s\n", i, unpair(p[i].rq));
 
39
                        else
 
40
                                fprintf(stderr, "slot %d empty\n", i);
 
41
                else
 
42
                        fprintf(stderr, "slot %d empty\n", i);
 
43
}
 
44
 
 
45
 
 
46
void blockinit(void)
 
47
{
 
48
        blist = (Blockp *) calloc(NBLIST, sizeof(Blockp));
 
49
        if (blist == NULL) {
 
50
                ERROR "not enough room for %d blocks", NBLIST WARN;
 
51
                done2(1);
 
52
        }
 
53
        nblist = NBLIST;
 
54
        blist[0].nextoff = blist[1].nextoff = -1;
 
55
        blist[0].bp = (Tchar *) calloc(BLK, sizeof(Tchar));
 
56
        blist[1].bp = (Tchar *) calloc(BLK, sizeof(Tchar));
 
57
                /* -1 prevents blist[0] from being used; temporary fix */
 
58
                /* for a design botch: offset==0 is overloaded. */
 
59
                /* blist[1] reserved for .rd indicator -- also unused. */
 
60
                /* but someone unwittingly looks at these, so allocate something */
 
61
        bfree = 2;
 
62
}
 
63
 
 
64
 
 
65
char *grow(char *ptr, int num, int size)        /* make array bigger */
 
66
{
 
67
        char *p;
 
68
 
 
69
        if (ptr == NULL)
 
70
                p = (char *) calloc(num, size);
 
71
        else
 
72
                p = (char *) realloc(ptr, num * size);
 
73
        return p;
 
74
}
 
75
 
 
76
void mnspace(void)
 
77
{
 
78
        nm = sizeof(contab)/sizeof(Contab) + MDELTA;
 
79
        freeslot = sizeof(contab)/sizeof(Contab) + 1;
 
80
        contabp = (Contab *) grow((char *) contabp, nm, sizeof(Contab));
 
81
        if (contabp == NULL) {
 
82
                ERROR "not enough memory for namespace of %d marcos", nm WARN;
 
83
                exit(1);
 
84
        }
 
85
        contabp = (Contab *) memcpy((char *) contabp, (char *)contab,
 
86
                                                        sizeof(contab));
 
87
        if (contabp == NULL) {
 
88
                ERROR "Cannot reinitialize macro/request name list" WARN;
 
89
                exit(1);
 
90
        }
 
91
 
 
92
}
 
93
 
 
94
void caseig(void)
 
95
{
 
96
        int i;
 
97
        Offset oldoff = offset;
 
98
 
 
99
        offset = 0;
 
100
        i = copyb();
 
101
        offset = oldoff;
 
102
        if (i != '.')
 
103
                control(i, 1);
 
104
}
 
105
 
 
106
 
 
107
void casern(void)
 
108
{
 
109
        int i, j, k;
 
110
 
 
111
        lgf++;
 
112
        skip();
 
113
        if ((i = getrq()) == 0 || (oldmn = findmn(i)) < 0)
 
114
                return;
 
115
        skip();
 
116
        clrmn(findmn(j = getrq()));
 
117
        if (j) {
 
118
                munhash(&contabp[oldmn]);
 
119
                contabp[oldmn].rq = j;
 
120
                maddhash(&contabp[oldmn]);
 
121
                if (dip != d )
 
122
                        for (k = dilev; k; k--)
 
123
                                if (d[k].curd == i)
 
124
                                        d[k].curd = j;
 
125
        }
 
126
}
 
127
 
 
128
void maddhash(Contab *rp)
 
129
{
 
130
        Contab **hp;
 
131
 
 
132
        if (rp->rq == 0)
 
133
                return;
 
134
        hp = &mhash[MHASH(rp->rq)];
 
135
        rp->link = *hp;
 
136
        *hp = rp;
 
137
}
 
138
 
 
139
void munhash(Contab *mp)
 
140
{       
 
141
        Contab *p;
 
142
        Contab **lp;
 
143
 
 
144
        if (mp->rq == 0)
 
145
                return;
 
146
        lp = &mhash[MHASH(mp->rq)];
 
147
        p = *lp;
 
148
        while (p) {
 
149
                if (p == mp) {
 
150
                        *lp = p->link;
 
151
                        p->link = 0;
 
152
                        return;
 
153
                }
 
154
                lp = &p->link;
 
155
                p = p->link;
 
156
        }
 
157
}
 
158
 
 
159
void mrehash(void)
 
160
{
 
161
        Contab *p;
 
162
        int i;
 
163
 
 
164
        for (i=0; i < MHASHSIZE; i++)
 
165
                mhash[i] = 0;
 
166
        for (p=contabp; p < &contabp[nm]; p++)
 
167
                p->link = 0;
 
168
        for (p=contabp; p < &contabp[nm]; p++) {
 
169
                if (p->rq == 0)
 
170
                        continue;
 
171
                i = MHASH(p->rq);
 
172
                p->link = mhash[i];
 
173
                mhash[i] = p;
 
174
        }
 
175
}
 
176
 
 
177
void caserm(void)
 
178
{
 
179
        int j;
 
180
        int k = 0;
 
181
 
 
182
        lgf++;
 
183
g0:
 
184
        while (!skip() && (j = getrq()) != 0) {
 
185
                if (dip != d)
 
186
                        for (k = dilev; k; k--)
 
187
                                if (d[k].curd == j) {
 
188
                                        ERROR "cannot remove diversion %s during definition",
 
189
                                                                unpair(j) WARN;
 
190
                                        goto g0;
 
191
                                }
 
192
                clrmn(findmn(j));
 
193
        }
 
194
        lgf--;
 
195
}
 
196
 
 
197
 
 
198
void caseas(void)
 
199
{
 
200
        app++;
 
201
        caseds();
 
202
}
 
203
 
 
204
 
 
205
void caseds(void)
 
206
{
 
207
        ds++;
 
208
        casede();
 
209
}
 
210
 
 
211
 
 
212
void caseam(void)
 
213
{
 
214
        app++;
 
215
        casede();
 
216
}
 
217
 
 
218
 
 
219
void casede(void)
 
220
{
 
221
        int i, req;
 
222
        Offset savoff;
 
223
 
 
224
        req = '.';
 
225
        lgf++;
 
226
        skip();
 
227
        if ((i = getrq()) == 0)
 
228
                goto de1;
 
229
        if ((offset = finds(i)) == 0)
 
230
                goto de1;
 
231
        if (newmn)
 
232
                savslot = newmn;
 
233
        else
 
234
                savslot = findmn(i);
 
235
        savname = i;
 
236
        if (ds)
 
237
                copys();
 
238
        else
 
239
                req = copyb();
 
240
        clrmn(oldmn);
 
241
        if (newmn) {
 
242
                if (contabp[newmn].rq)
 
243
                        munhash(&contabp[newmn]);
 
244
                contabp[newmn].rq = i;
 
245
                maddhash(&contabp[newmn]);
 
246
 
 
247
        }
 
248
        if (apptr) {
 
249
                savoff = offset;
 
250
                offset = apptr;
 
251
                wbf((Tchar) IMP);
 
252
                offset = savoff;
 
253
        }
 
254
        offset = dip->op;
 
255
        if (req != '.')
 
256
                control(req, 1);
 
257
de1:
 
258
        ds = app = 0;
 
259
}
 
260
 
 
261
 
 
262
int findmn(int i)
 
263
{
 
264
        Contab *p;
 
265
 
 
266
        for (p = mhash[MHASH(i)]; p; p = p->link)
 
267
                if (i == p->rq)
 
268
                        return(p - contabp);
 
269
        return(-1);
 
270
}
 
271
 
 
272
 
 
273
void clrmn(int i)
 
274
{
 
275
        if (i >= 0) {
 
276
                if (contabp[i].mx)
 
277
                        ffree(contabp[i].mx);
 
278
                munhash(&contabp[i]);
 
279
                contabp[i].rq = 0;
 
280
                contabp[i].mx = 0;
 
281
                contabp[i].emx = 0;
 
282
                contabp[i].f = 0;
 
283
                if (contabp[i].divsiz != NULL) {
 
284
                        free(contabp[i].divsiz);
 
285
                        contabp[i].divsiz = NULL;
 
286
                }
 
287
                if (freeslot > i)
 
288
                        freeslot = i;
 
289
        }
 
290
}
 
291
 
 
292
void growcontab(void)
 
293
{
 
294
        nm += MDELTA;
 
295
        contabp = (Contab *) grow((char *) contabp , nm, sizeof(Contab));
 
296
        if (contabp == NULL) {
 
297
                ERROR "Too many (%d) string/macro names", nm WARN;
 
298
                done2(02);
 
299
        } else {
 
300
                memset((char *)(contabp) + (nm - MDELTA) * sizeof(Contab),
 
301
                                                0, MDELTA * sizeof(Contab));
 
302
                mrehash();
 
303
        }
 
304
}
 
305
 
 
306
 
 
307
Offset finds(int mn)
 
308
{
 
309
        int i;
 
310
        Offset savip;
 
311
 
 
312
        oldmn = findmn(mn);
 
313
        newmn = 0;
 
314
        apptr = 0;
 
315
        if (app && oldmn >= 0 && contabp[oldmn].mx) {
 
316
                savip = ip;
 
317
                ip = contabp[oldmn].emx;
 
318
                oldmn = -1;
 
319
                apptr = ip;
 
320
                if (!diflg)
 
321
                        ip = incoff(ip);
 
322
                nextb = ip;
 
323
                ip = savip;
 
324
        } else {
 
325
                for (i = freeslot; i < nm; i++) {
 
326
                        if (contabp[i].rq == 0)
 
327
                                break;
 
328
                }
 
329
                if (i == nm) 
 
330
                        growcontab();
 
331
                freeslot = i + 1;
 
332
                if ((nextb = alloc()) == -1) {
 
333
                        app = 0;
 
334
                        if (macerr++ > 1)
 
335
                                done2(02);
 
336
                        if (nextb == 0)
 
337
                                ERROR "Not enough space for string/macro names" WARN;
 
338
                        edone(04);
 
339
                        return(offset = 0);
 
340
                }
 
341
                contabp[i].mx = nextb;
 
342
                if (!diflg) {
 
343
                        newmn = i;
 
344
                        if (oldmn == -1)
 
345
                                contabp[i].rq = -1;
 
346
                } else {
 
347
                        contabp[i].rq = mn;
 
348
                        maddhash(&contabp[i]);
 
349
                }
 
350
        }
 
351
        app = 0;
 
352
        return(offset = nextb);
 
353
}
 
354
 
 
355
int skip(void)
 
356
{
 
357
        Tchar i;
 
358
 
 
359
        while (cbits(i = getch()) == ' ' || ismot(i))
 
360
                ;
 
361
        ch = i;
 
362
        return(nlflg);
 
363
}
 
364
 
 
365
 
 
366
int copyb(void)
 
367
{
 
368
        int i, j, state;
 
369
        Tchar ii;
 
370
        int req, k;
 
371
        Offset savoff;
 
372
        Uchar *p;
 
373
 
 
374
        savoff = 0;
 
375
        if (skip() || !(j = getrq()))
 
376
                j = '.';
 
377
        req = j;
 
378
        p = unpair(j);
 
379
        /* was: k = j >> BYTE; j &= BYTEMASK; */
 
380
        j = p[0];
 
381
        k = p[1];
 
382
        copyf++;
 
383
        flushi();
 
384
        nlflg = 0;
 
385
        state = 1;
 
386
 
 
387
/* state 0      eat up
 
388
 * state 1      look for .
 
389
 * state 2      look for first char of end macro
 
390
 * state 3      look for second char of end macro
 
391
 */
 
392
 
 
393
        while (1) {
 
394
                i = cbits(ii = getch());
 
395
                if (state == 3) {
 
396
                        if (i == k)
 
397
                                break;
 
398
                        if (!k) {
 
399
                                ch = ii;
 
400
                                i = getach();
 
401
                                ch = ii;
 
402
                                if (!i)
 
403
                                        break;
 
404
                        }
 
405
                        state = 0;
 
406
                        goto c0;
 
407
                }
 
408
                if (i == '\n') {
 
409
                        state = 1;
 
410
                        nlflg = 0;
 
411
                        goto c0;
 
412
                }
 
413
                if (state == 1 && i == '.') {
 
414
                        state++;
 
415
                        savoff = offset;
 
416
                        goto c0;
 
417
                }
 
418
                if (state == 2 && i == j) {
 
419
                        state++;
 
420
                        goto c0;
 
421
                }
 
422
                state = 0;
 
423
c0:
 
424
                if (offset)
 
425
                        wbf(ii);
 
426
        }
 
427
        if (offset) {
 
428
                offset = savoff;
 
429
                wbf((Tchar)0);
 
430
        }
 
431
        copyf--;
 
432
        return(req);
 
433
}
 
434
 
 
435
 
 
436
void copys(void)
 
437
{
 
438
        Tchar i;
 
439
 
 
440
        copyf++;
 
441
        if (skip())
 
442
                goto c0;
 
443
        if (cbits(i = getch()) != '"')
 
444
                wbf(i);
 
445
        while (cbits(i = getch()) != '\n')
 
446
                wbf(i);
 
447
c0:
 
448
        wbf((Tchar)0);
 
449
        copyf--;
 
450
}
 
451
 
 
452
 
 
453
Offset alloc(void)      /* return free Offset in nextb */
 
454
{
 
455
        int i, j;
 
456
 
 
457
        for (i = bfree; i < nblist; i++)
 
458
                if (blist[i].nextoff == 0)
 
459
                        break;
 
460
        if (i == nblist) {
 
461
                blist = (Blockp *) realloc((char *) blist, 2 * nblist * sizeof(Blockp));
 
462
                if (blist == NULL) {
 
463
                        ERROR "can't grow blist for string/macro defns" WARN;
 
464
                        done2(2);
 
465
                }
 
466
                nblist *= 2;
 
467
                for (j = i; j < nblist; j++) {
 
468
                        blist[j].nextoff = 0;
 
469
                        blist[j].bp = 0;
 
470
                }
 
471
        }
 
472
        blist[i].nextoff = -1;  /* this block is the end */
 
473
        bfree = i + 1;
 
474
        if (blist[i].bp == 0)
 
475
                blist[i].bp = (Tchar *) calloc(BLK, sizeof(Tchar));
 
476
        if (blist[i].bp == NULL) {
 
477
                ERROR "can't allocate memory for string/macro definitions" WARN;
 
478
                done2(2);
 
479
        }
 
480
        nextb = (Offset) i * BLK;
 
481
        return nextb;
 
482
}
 
483
 
 
484
 
 
485
void ffree(Offset i)    /* free list of blocks starting at blist(o) */
 
486
{                       /* (doesn't actually free the blocks, just the pointers) */
 
487
        int j;
 
488
 
 
489
        for ( ; blist[j = bindex(i)].nextoff != -1; ) {
 
490
                if (bfree > j)
 
491
                        bfree = j;
 
492
                i = blist[j].nextoff;
 
493
                blist[j].nextoff = 0;
 
494
        }
 
495
        blist[j].nextoff = 0;
 
496
}
 
497
 
 
498
 
 
499
void wbf(Tchar i)       /* store i into offset, get ready for next one */
 
500
{
 
501
        int j, off;
 
502
 
 
503
        if (!offset)
 
504
                return;
 
505
        j = bindex(offset);
 
506
        if (i == 0)
 
507
                contabp[savslot].emx = offset;
 
508
        off = boffset(offset);
 
509
        blist[j].bp[off++] = i;
 
510
        offset++;
 
511
        if (pastend(offset)) {  /* off the end of this block */
 
512
                if (blist[j].nextoff == -1) {
 
513
                        if ((nextb = alloc()) == -1) {
 
514
                                ERROR "Out of temp file space" WARN;
 
515
                                done2(01);
 
516
                        }
 
517
                        blist[j].nextoff = nextb;
 
518
                }
 
519
                offset = blist[j].nextoff;
 
520
        }
 
521
}
 
522
 
 
523
 
 
524
Tchar rbf(void) /* return next char from blist[] block */
 
525
{
 
526
        Tchar i, j;
 
527
 
 
528
        if (ip == RD_OFFSET) {          /* for rdtty */
 
529
                if (j = rdtty())
 
530
                        return(j);
 
531
                else
 
532
                        return(popi());
 
533
        }
 
534
        
 
535
        i = rbf0(ip);
 
536
        if (i == 0) {
 
537
                if (!app)
 
538
                        i = popi();
 
539
                return(i);
 
540
        }
 
541
        ip = incoff(ip);
 
542
        return(i);
 
543
}
 
544
 
 
545
 
 
546
Offset xxxincoff(Offset p)              /* get next blist[] block */
 
547
{
 
548
        p++;
 
549
        if (pastend(p)) {               /* off the end of this block */
 
550
                if ((p = blist[bindex(p-1)].nextoff) == -1) {   /* and nothing was allocated after it */
 
551
                        ERROR "Bad storage allocation" WARN;
 
552
                        done2(-5);
 
553
                }
 
554
        }
 
555
        return(p);
 
556
}
 
557
 
 
558
 
 
559
Tchar popi(void)
 
560
{
 
561
        Stack *p;
 
562
 
 
563
        if (frame == stk)
 
564
                return(0);
 
565
        if (strflg)
 
566
                strflg--;
 
567
        p = nxf = frame;
 
568
        p->nargs = 0;
 
569
        frame = p->pframe;
 
570
        ip = p->pip;
 
571
        pendt = p->ppendt;
 
572
        lastpbp = p->lastpbp;
 
573
        return(p->pch);
 
574
}
 
575
 
 
576
/*
 
577
 *      test that the end of the allocation is above a certain location
 
578
 *      in memory
 
579
 */
 
580
#define SPACETEST(base, size) \
 
581
        if ((char*)base + size >= (char*)stk+STACKSIZE) \
 
582
                ERROR "Stacksize overflow in n3" WARN
 
583
 
 
584
Offset pushi(Offset newip, int  mname)
 
585
{
 
586
        Stack *p;
 
587
 
 
588
        SPACETEST(nxf, sizeof(Stack));
 
589
        p = nxf;
 
590
        p->pframe = frame;
 
591
        p->pip = ip;
 
592
        p->ppendt = pendt;
 
593
        p->pch = ch;
 
594
        p->lastpbp = lastpbp;
 
595
        p->mname = mname;
 
596
        lastpbp = pbp;
 
597
        pendt = ch = 0;
 
598
        frame = nxf;
 
599
        if (nxf->nargs == 0) 
 
600
                nxf += 1;
 
601
        else 
 
602
                nxf = (Stack *)argtop;
 
603
        return(ip = newip);
 
604
}
 
605
 
 
606
 
 
607
void *setbrk(int x)
 
608
{
 
609
        char *i;
 
610
 
 
611
        if ((i = (char *) calloc(x, 1)) == 0) {
 
612
                ERROR "Core limit reached" WARN;
 
613
                edone(0100);
 
614
        }
 
615
        return(i);
 
616
}
 
617
 
 
618
 
 
619
int getsn(void)
 
620
{
 
621
        int i;
 
622
 
 
623
        if ((i = getach()) == 0)
 
624
                return(0);
 
625
        if (i == '(')
 
626
                return(getrq());
 
627
        else 
 
628
                return(i);
 
629
}
 
630
 
 
631
 
 
632
Offset setstr(void)
 
633
{
 
634
        int i, j;
 
635
 
 
636
        lgf++;
 
637
        if ((i = getsn()) == 0 || (j = findmn(i)) == -1 || !contabp[j].mx) {
 
638
                lgf--;
 
639
                return(0);
 
640
        } else {
 
641
                SPACETEST(nxf, sizeof(Stack));
 
642
                nxf->nargs = 0;
 
643
                strflg++;
 
644
                lgf--;
 
645
                return pushi(contabp[j].mx, i);
 
646
        }
 
647
}
 
648
 
 
649
 
 
650
 
 
651
void collect(void)
 
652
{
 
653
        int j;
 
654
        Tchar i, *strp, *lim, **argpp, **argppend;
 
655
        int quote;
 
656
        Stack *savnxf;
 
657
 
 
658
        copyf++;
 
659
        nxf->nargs = 0;
 
660
        savnxf = nxf;
 
661
        if (skip())
 
662
                goto rtn;
 
663
 
 
664
        {
 
665
                char *memp;
 
666
                memp = (char *)savnxf;
 
667
                /*
 
668
                 *      1 s structure for the macro descriptor
 
669
                 *      APERMAC Tchar *'s for pointers into the strings
 
670
                 *      space for the Tchar's themselves
 
671
                 */
 
672
                memp += sizeof(Stack);
 
673
                /*
 
674
                 *      CPERMAC = the total # of characters for ALL arguments
 
675
                 */
 
676
#define CPERMAC 200
 
677
#define APERMAC 9
 
678
                memp += APERMAC * sizeof(Tchar *);
 
679
                memp += CPERMAC * sizeof(Tchar);
 
680
                nxf = (Stack *)memp;
 
681
        }
 
682
        lim = (Tchar *)nxf;
 
683
        argpp = (Tchar **)(savnxf + 1);
 
684
        argppend = &argpp[APERMAC];
 
685
        SPACETEST(argppend, sizeof(Tchar *));
 
686
        strp = (Tchar *)argppend;
 
687
        /*
 
688
         *      Zero out all the string pointers before filling them in.
 
689
         */
 
690
        for (j = 0; j < APERMAC; j++)
 
691
                argpp[j] = 0;
 
692
        /* ERROR "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x, lim=0x%x",
 
693
         *      savnxf, nxf, argpp, strp, lim WARN;
 
694
         */
 
695
        strflg = 0;
 
696
        while (argpp != argppend && !skip()) {
 
697
                *argpp++ = strp;
 
698
                quote = 0;
 
699
                if (cbits(i = getch()) == '"')
 
700
                        quote++;
 
701
                else 
 
702
                        ch = i;
 
703
                while (1) {
 
704
                        i = getch();
 
705
/* fprintf(stderr, "collect %c %d\n", cbits(i), cbits(i)); */
 
706
                        if (nlflg || (!quote && argpp != argppend && cbits(i) == ' '))
 
707
                                break;  /* collects rest into $9 */
 
708
                        if (   quote
 
709
                            && cbits(i) == '"'
 
710
                            && cbits(i = getch()) != '"') {
 
711
                                ch = i;
 
712
                                break;
 
713
                        }
 
714
                        *strp++ = i;
 
715
                        if (strflg && strp >= lim) {
 
716
                                /* ERROR "strp=0x%x, lim = 0x%x", strp, lim WARN; */
 
717
                                ERROR "Macro argument too long" WARN;
 
718
                                copyf--;
 
719
                                edone(004);
 
720
                        }
 
721
                        SPACETEST(strp, 3 * sizeof(Tchar));
 
722
                }
 
723
                *strp++ = 0;
 
724
        }
 
725
        nxf = savnxf;
 
726
        nxf->nargs = argpp - (Tchar **)(savnxf + 1);
 
727
        argtop = strp;
 
728
rtn:
 
729
        copyf--;
 
730
}
 
731
 
 
732
 
 
733
void seta(void)
 
734
{
 
735
        int i;
 
736
 
 
737
        i = cbits(getch()) - '0';
 
738
        if (i > 0 && i <= APERMAC && i <= frame->nargs)
 
739
                pushback(*(((Tchar **)(frame + 1)) + i - 1));
 
740
}
 
741
 
 
742
 
 
743
void caseda(void)
 
744
{
 
745
        app++;
 
746
        casedi();
 
747
}
 
748
 
 
749
void casegd(void)
 
750
{
 
751
        int i, j;
 
752
 
 
753
        skip();
 
754
        if ((i = getrq()) == 0)
 
755
                return;
 
756
        if ((j = findmn(i)) >= 0) {
 
757
                if (contabp[j].divsiz != NULL) {
 
758
                        numtabp[DN].val = contabp[j].divsiz->dix;
 
759
                        numtabp[DL].val = contabp[j].divsiz->diy;
 
760
                }
 
761
        }
 
762
}
 
763
 
 
764
#define FINDDIV(o) if ((o =  findmn(dip->curd)) < 0) \
 
765
                        ERROR "lost diversion %s", unpair(dip->curd) WARN
 
766
 
 
767
void casedi(void)
 
768
{
 
769
        int i, j, *k;
 
770
 
 
771
        lgf++;
 
772
        if (skip() || (i = getrq()) == 0) {
 
773
                if (dip != d) {
 
774
                        FINDDIV(savslot);
 
775
                        wbf((Tchar)0);
 
776
                }
 
777
                if (dilev > 0) {
 
778
                        numtabp[DN].val = dip->dnl;
 
779
                        numtabp[DL].val = dip->maxl;
 
780
                        FINDDIV(j);
 
781
                        if ((contabp[j].divsiz = (Divsiz *) malloc(sizeof(Divsiz))) == NULL) {
 
782
                                ERROR "Cannot alloc diversion size" WARN;
 
783
                                done2(1);
 
784
                        } else {
 
785
                                contabp[j].divsiz->dix = numtabp[DN].val;
 
786
                                contabp[j].divsiz->diy = numtabp[DL].val;
 
787
                        }
 
788
                        dip = &d[--dilev];
 
789
                        offset = dip->op;
 
790
                }
 
791
                goto rtn;
 
792
        }
 
793
        if (++dilev == NDI) {
 
794
                --dilev;
 
795
                ERROR "Diversions nested too deep" WARN;
 
796
                edone(02);
 
797
        }
 
798
        if (dip != d) {
 
799
                FINDDIV(j);
 
800
                savslot = j;
 
801
                wbf((Tchar)0);
 
802
        }
 
803
        diflg++;
 
804
        dip = &d[dilev];
 
805
        dip->op = finds(i);
 
806
        dip->curd = i;
 
807
        clrmn(oldmn);
 
808
        k = (int *) & dip->dnl;
 
809
        for (j = 0; j < 10; j++)
 
810
                k[j] = 0;       /*not op and curd*/
 
811
rtn:
 
812
        app = 0;
 
813
        diflg = 0;
 
814
}
 
815
 
 
816
 
 
817
void casedt(void)
 
818
{
 
819
        lgf++;
 
820
        dip->dimac = dip->ditrap = dip->ditf = 0;
 
821
        skip();
 
822
        dip->ditrap = vnumb((int *)0);
 
823
        if (nonumb)
 
824
                return;
 
825
        skip();
 
826
        dip->dimac = getrq();
 
827
}
 
828
 
 
829
#define LNSIZE 4000
 
830
void casetl(void)
 
831
{
 
832
        int j;
 
833
        int w[3];
 
834
        Tchar buf[LNSIZE];
 
835
        Tchar *tp;
 
836
        Tchar i, delim;
 
837
 
 
838
        /*
 
839
         * bug fix
 
840
         *
 
841
         * if .tl is the first thing in the file, the p1
 
842
         * doesn't come out, also the pagenumber will be 0
 
843
         *
 
844
         * tends too confuse the device filter (and the user as well)
 
845
         */
 
846
        if (dip == d && numtabp[NL].val == -1)
 
847
                newline(1);
 
848
        dip->nls = 0;
 
849
        skip();
 
850
        if (ismot(delim = getch())) {
 
851
                ch = delim;
 
852
                delim = '\'';
 
853
        } else 
 
854
                delim = cbits(delim);
 
855
        tp = buf;
 
856
        numtabp[HP].val = 0;
 
857
        w[0] = w[1] = w[2] = 0;
 
858
        j = 0;
 
859
        while (cbits(i = getch()) != '\n') {
 
860
                if (cbits(i) == cbits(delim)) {
 
861
                        if (j < 3)
 
862
                                w[j] = numtabp[HP].val;
 
863
                        numtabp[HP].val = 0;
 
864
                        if (w[j] != 0)
 
865
                                *tp++ = WORDSP;
 
866
                        j++;
 
867
                        *tp++ = 0;
 
868
                } else {
 
869
                        if (cbits(i) == pagech) {
 
870
                                setn1(numtabp[PN].val, numtabp[findr('%')].fmt,
 
871
                                      i&SFMASK);
 
872
                                continue;
 
873
                        }
 
874
                        numtabp[HP].val += width(i);
 
875
                        if (tp < &buf[LNSIZE-10]) {
 
876
                                if (cbits(i) == ' ' && *tp != WORDSP)
 
877
                                        *tp++ = WORDSP;
 
878
                                *tp++ = i;
 
879
                        } else {
 
880
                                ERROR "Overflow in casetl" WARN;
 
881
                        }
 
882
                }
 
883
        }
 
884
        if (j<3)
 
885
                w[j] = numtabp[HP].val;
 
886
        *tp++ = 0;
 
887
        *tp++ = 0;
 
888
        *tp = 0;
 
889
        tp = buf;
 
890
        if (NROFF)
 
891
                horiz(po);
 
892
        while (i = *tp++)
 
893
                pchar(i);
 
894
        if (w[1] || w[2])
 
895
                horiz(j = quant((lt - w[1]) / 2 - w[0], HOR));
 
896
        while (i = *tp++)
 
897
                pchar(i);
 
898
        if (w[2]) {
 
899
                horiz(lt - w[0] - w[1] - w[2] - j);
 
900
                while (i = *tp++)
 
901
                        pchar(i);
 
902
        }
 
903
        newline(0);
 
904
        if (dip != d) {
 
905
                if (dip->dnl > dip->hnl)
 
906
                        dip->hnl = dip->dnl;
 
907
        } else {
 
908
                if (numtabp[NL].val > dip->hnl)
 
909
                        dip->hnl = numtabp[NL].val;
 
910
        }
 
911
}
 
912
 
 
913
 
 
914
void casepc(void)
 
915
{
 
916
        pagech = chget(IMP);
 
917
}
 
918
 
 
919
 
 
920
void casepm(void)
 
921
{
 
922
        int i, k;
 
923
        int xx, cnt, tcnt, kk, tot;
 
924
        Offset j;
 
925
 
 
926
        kk = cnt = tcnt = 0;
 
927
        tot = !skip();
 
928
        stackdump();
 
929
        for (i = 0; i < nm; i++) {
 
930
                if ((xx = contabp[i].rq) == 0 || contabp[i].mx == 0)
 
931
                        continue;
 
932
                tcnt++;
 
933
                j = contabp[i].mx;
 
934
                for (k = 1; (j = blist[bindex(j)].nextoff) != -1; )
 
935
                        k++; 
 
936
                cnt++;
 
937
                kk += k;
 
938
                if (!tot)
 
939
                        fprintf(stderr, "%-2.2s %d\n", unpair(xx), k);
 
940
        }
 
941
        fprintf(stderr, "pm: total %d, macros %d, space %d\n", tcnt, cnt, kk);
 
942
}
 
943
 
 
944
void stackdump(void)    /* dumps stack of macros in process */
 
945
{
 
946
        Stack *p;
 
947
 
 
948
        if (frame != stk) {
 
949
                fprintf(stderr, "stack: ");
 
950
                for (p = frame; p != stk; p = p->pframe)
 
951
                        fprintf(stderr, "%s ", unpair(p->mname));
 
952
                fprintf(stderr, "\n");
 
953
        }
 
954
}