n3.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
n3.c (16259B) | |
--- | |
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 … | |
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, … | |
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 s… | |
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… | |
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 %… | |
189 unpair(j… | |
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(Conta… | |
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… | |
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 * … | |
462 if (blist == NULL) { | |
463 ERROR "can't grow blist for string/macro defns" … | |
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 definition… | |
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 … | |
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) { /* … | |
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].m… | |
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 ar… | |
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 i… | |
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, li… | |
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 && cbi… | |
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, … | |
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(sizeo… | |
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('%'… | |
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… | |
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 } |