Introduction
Introduction Statistics Contact Development Disclaimer Help
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 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.