BSD 3 development
[unix-history] / usr / src / cmd / troff / n3.c
CommitLineData
28140ad0
BJ
1#include "tdef.h"
2extern
3#include "d.h"
4extern
5#include "v.h"
6#ifdef NROFF
7extern
8#include "tw.h"
9#endif
10#include "s.h"
11
12/*
13troff3.c
14
15macro and string routines, storage allocation
16*/
17
18unsigned blist[NBLIST];
19extern struct s *frame, *stk, *nxf;
20extern filep ip;
21extern filep offset;
22extern filep nextb;
23extern char *enda;
24
25extern int ch;
26extern int ibf;
27extern int lgf;
28extern int copyf;
29extern int ch0;
30extern int app;
31extern int ds;
32extern int nlflg;
33extern int *argtop;
34extern int *ap;
35extern int nchar;
36extern int pendt;
37extern int rchar;
38extern int dilev;
39extern int nonumb;
40extern int lt;
41extern int nrbits;
42extern int nform;
43extern int fmt[];
44extern int oldmn;
45extern int newmn;
46extern int macerr;
47extern filep apptr;
48extern int diflg;
49extern filep woff;
50extern filep roff;
51extern int wbfi;
52extern int po;
53extern int *cp;
54extern int xxx;
55int pagech = '%';
56int strflg;
57extern struct contab {
58 int rq;
59 union {
60 int (*f)();
61 unsigned mx;
62 }x;
63}contab[NM];
64#ifndef VMUNIX
65int wbuf[BLK];
66int rbuf[BLK];
67#else
68int *wbuf;
69int *rbuf;
70int Buf[NBLIST*BLK];
71#endif
72
73caseig(){
74 register i;
75
76 offset = 0;
77 if((i = copyb()) != '.')control(i,1);
78}
79casern(){
80 register i,j;
81
82 lgf++;
83 skip();
84 if(((i=getrq())==0) || ((oldmn=findmn(i)) < 0))return;
85 skip();
86 clrmn(findmn(j=getrq()));
87 if(j)contab[oldmn].rq = (contab[oldmn].rq & MMASK) | j;
88}
89caserm(){
90 lgf++;
91 while(!skip()){
92 clrmn(findmn(getrq()));
93 }
94}
95caseas(){
96 app++;
97 caseds();
98}
99caseds(){
100 ds++;
101 casede();
102}
103caseam(){
104 app++;
105 casede();
106}
107casede(){
108 register i, req;
109 register filep savoff;
110 extern filep finds();
111
112 if(dip != d)wbfl();
113 req = '.';
114 lgf++;
115 skip();
116 if((i=getrq())==0)goto de1;
117 if((offset=finds(i)) == 0)goto de1;
118 if(ds)copys();
119 else req = copyb();
120 wbfl();
121 clrmn(oldmn);
122 if(newmn)contab[newmn].rq = i | MMASK;
123 if(apptr){
124 savoff = offset;
125 offset = apptr;
126 wbt(IMP);
127 offset = savoff;
128 }
129 offset = dip->op;
130 if(req != '.')control(req,1);
131de1:
132 ds = app = 0;
133 return;
134}
135findmn(i)
136int i;
137{
138 register j;
139
140 for(j=0;j<NM;j++){
141 if(i == (contab[j].rq & ~MMASK))break;
142 }
143 if(j==NM)j = -1;
144 return(j);
145}
146clrmn(i)
147int i;
148{
149 extern filep boff();
150 if(i >= 0){
151 if(contab[i].rq & MMASK)ffree(((filep)contab[i].x.mx)<<BLKBITS);
152 contab[i].rq = 0;
153 contab[i].x.mx = 0;
154 }
155}
156filep finds(mn)
157int mn;
158{
159 register i;
160 extern filep boff();
161 register filep savip;
162 extern filep alloc();
163 extern filep incoff();
164
165 oldmn = findmn(mn);
166 newmn = 0;
167 apptr = (filep)0;
168 if(app && (oldmn >= 0) && (contab[oldmn].rq & MMASK)){
169 savip = ip;
170 ip = (((filep)contab[oldmn].x.mx)<<BLKBITS);
171 oldmn = -1;
172 while((i=rbf()) != 0);
173 apptr = ip;
174 if(!diflg)ip = incoff(ip);
175 nextb = ip;
176 ip = savip;
177 }else{
178 for(i=0;i<NM;i++){
179 if(contab[i].rq == 0)break;
180 }
181 if((i==NM) ||
182 (nextb = alloc()) == 0){
183 app = 0;
184 if(macerr++ > 1)done2(02);
185 prstr("Too many string/macro names.\n");
186 edone(04);
187 return(offset = 0);
188 }
189 contab[i].x.mx = (unsigned)(nextb>>BLKBITS);
190 if(!diflg){
191 newmn = i;
192 if(oldmn == -1)contab[i].rq = -1;
193 }else{
194 contab[i].rq = mn | MMASK;
195 }
196 }
197
198 app = 0;
199 return(offset = nextb);
200}
201skip(){
202 register i;
203
204 while(((i=getch()) & CMASK) == ' ');
205 ch=i;
206 return(nlflg);
207}
208copyb()
209{
210 register i, j, k;
211 int ii, req, state;
212 filep savoff;
213
214 if(skip() || !(j=getrq()))j = '.';
215 req = j;
216 k = j>>BYTE;
217 j &= BMASK;
218 copyf++;
219 flushi();
220 nlflg = 0;
221 state = 1;
222 while(1){
223 i = (ii = getch()) & CMASK;
224 if(state == 3){
225 if(i == k)break;
226 if(!k){
227 ch = ii;
228 i = getach();
229 ch = ii;
230 if(!i)break;
231 }
232 state = 0;
233 goto c0;
234 }
235 if(i == '\n'){
236 state = 1;
237 nlflg = 0;
238 goto c0;
239 }
240 if((state == 1) && (i == '.')){
241 state++;
242 savoff = offset;
243 goto c0;
244 }
245 if((state == 2) && (i == j)){
246 state++;
247 goto c0;
248 }
249 state = 0;
250c0:
251 if(offset)wbf(ii);
252 }
253 if(offset){
254 wbfl();
255 offset = savoff;
256 wbt(0);
257 }
258 copyf--;
259 return(req);
260}
261copys()
262{
263 register i;
264
265 copyf++;
266 if(skip())goto c0;
267 if(((i=getch()) & CMASK) != '"')wbf(i);
268 while(((i=getch()) & CMASK) != '\n')wbf(i);
269c0:
270 wbt(0);
271 copyf--;
272}
273filep alloc()
274{
275 register i;
276 extern filep boff();
277 filep j;
278
279 for(i=0;i<NBLIST;i++){
280 if(blist[i] == 0)break;
281 }
282 if(i==NBLIST){
283 j = 0;
284 }else{
285 blist[i] = -1;
286 if((j = boff(i)) < NEV*EVS)j = 0;
287 }
288 return(nextb = j);
289}
290ffree(i)
291filep i;
292{
293 register j;
294
295 while((blist[j = blisti(i)]) != -1){
296 i = ((filep)blist[j])<<BLKBITS;
297 blist[j] = 0;
298 }
299 blist[j] = 0;
300}
301filep boff(i)
302int i;
303{
304 return(((filep)i)*BLK + NEV*EVS);
305}
306wbt(i)
307int i;
308{
309 wbf(i);
310 wbfl();
311}
312wbf(i)
313int i;
314{
315 register j;
316
317 if(!offset)return;
318 if(!woff){
319 woff = offset;
320#ifdef VMUNIX
321 wbuf = &Buf[woff];
322#endif
323 wbfi = 0;
324 }
325 wbuf[wbfi++] = i;
326 if(!((++offset) & (BLK-1))){
327 wbfl();
328 if(blist[j = blisti(--offset)] == -1){
329 if(alloc() == 0){
330 prstr("Out of temp file space.\n");
331 done2(01);
332 }
333 blist[j] = (unsigned)(nextb>>BLKBITS);
334 }
335 offset = ((filep)blist[j])<<BLKBITS;
336 }
337 if(wbfi >= BLK)wbfl();
338}
339wbfl(){
340 if(woff == 0)return;
341#ifndef VMUNIX
342 lseek(ibf, ((long)woff) * sizeof(int), 0);
343 write(ibf, (char *)wbuf, wbfi * sizeof(int));
344#endif
345 if((woff & (~(BLK-1))) == (roff & (~(BLK-1))))roff = -1;
346 woff = 0;
347}
348blisti(i)
349filep i;
350{
351 return((i-NEV*EVS)/(BLK));
352}
353rbf(){
354 register i;
355 extern filep incoff();
356
357 if((i=rbf0(ip)) == 0){
358 if(!app)i = popi();
359 }else{
360 ip = incoff(ip);
361 }
362 return(i);
363}
364rbf0(p)
365filep p;
366{
367 register filep i;
368
369 if((i = (p & (~(BLK-1)))) != roff){
370 roff = i;
371#ifndef VMUNIX
372 lseek(ibf, ((long)roff) * sizeof(int), 0);
373 if(read(ibf, (char *)rbuf, BLK * sizeof(int)) == 0)return(0);
374#else
375 rbuf = &Buf[roff];
376#endif
377 }
378 return(rbuf[p & (BLK-1)]);
379}
380filep incoff(p)
381filep p;
382{
383 register i;
384 register filep j;
385 if(!((j = (++p)) & (BLK-1))){
386 if((i = blist[blisti(--p)]) == -1){
387 prstr("Bad storage allocation.\n");
388 done2(-5);
389 }
390 j = ((filep)i)<<BLKBITS;
391 }
392 return(j);
393}
394popi(){
395 register struct s *p;
396
397 if(frame == stk)return(0);
398 if(strflg)strflg--;
399 p = nxf = frame;
400 p->nargs = 0;
401 frame = p->pframe;
402 ip = p->pip;
403 nchar = p->pnchar;
404 rchar = p->prchar;
405 pendt = p->ppendt;
406 ap = p->pap;
407 cp = p->pcp;
408 ch0 = p->pch0;
409 return(p->pch);
410}
411pushi(newip)
412filep newip;
413{
414 register struct s *p;
415 extern char *setbrk();
416
417 if((enda - sizeof(struct s)) < (char *)nxf)setbrk(DELTA);
418 p = nxf;
419 p->pframe = frame;
420 p->pip = ip;
421 p->pnchar = nchar;
422 p->prchar = rchar;
423 p->ppendt = pendt;
424 p->pap = ap;
425 p->pcp = cp;
426 p->pch0 = ch0;
427 p->pch = ch;
428 cp = ap = 0;
429 nchar = rchar = pendt = ch0 = ch = 0;
430 frame = nxf;
431 if(nxf->nargs == 0) nxf += 1;
432 else nxf = (struct s *)argtop;
433 return(ip = newip);
434}
435char *setbrk(x)
436int x;
437{
438 register char *i;
439 char *sbrk();
440
441 if((i = sbrk(x)) == MAXPTR){
442 prstrfl("Core limit reached.\n");
443 edone(0100);
444 }else{
445 enda = i + x;
446 }
447 return(i);
448}
449getsn(){
450 register i;
451
452 if((i=getach()) == 0)return(0);
453 if(i == '(')return(getrq());
454 else return(i);
455}
456setstr(){
457 register i;
458
459 lgf++;
460 if(((i=getsn()) == 0) ||
461 ((i=findmn(i)) == -1) ||
462 !(contab[i].rq & MMASK)){
463 lgf--;
464 return(0);
465 }else{
466 if((enda-2) < (char *)nxf)setbrk(DELTA);
467 nxf->nargs = 0;
468 strflg++;
469 lgf--;
470 return(pushi(((filep)contab[i].x.mx)<<BLKBITS));
471 }
472}
473collect()
474{
475 register i;
476 register int *strp;
477 int *lim;
478 int **argpp, **argppend;
479 int quote;
480 struct s *savnxf;
481
482 copyf++;
483 nxf->nargs = 0;
484 savnxf = nxf;
485 if(skip())goto rtn;
486 lim = (int *)(nxf = savnxf + sizeof(struct s)/sizeof(savnxf));
487 strflg = 0;
488 if((argppend =
489 (argpp = (int **)savnxf+(sizeof(struct s)/sizeof(int **))) + 9)
490 > (int **)enda)setbrk(DELTA);
491 strp = (int *)argppend;
492 for(i=8; i>=0; i--)argpp[i] = 0;
493 while((argpp != argppend) && (!skip())){
494 *argpp++ = strp;
495 quote = 0;
496 if(((i = getch()) & CMASK) == '"')quote++;
497 else ch = i;
498 while(1){
499 i = getch();
500 if( nlflg ||
501 ((!quote) && ((i & CMASK) == ' ')))break;
502 if(quote && ((i & CMASK) == '"') &&
503 (((i=getch()) & CMASK) != '"')){
504 ch = i;
505 break;
506 }
507 *strp++ = i;
508 if(strflg && (strp >= lim)){
509 prstrfl("Macro argument too long.\n");
510 copyf--;
511 edone(004);
512 }
513 if((enda-4) <= (char *)strp)setbrk(DELTA);
514 }
515 *strp++ = 0;
516 }
517 nxf = savnxf;
518 nxf->nargs = argpp -(int **)(nxf + 1);
519 argtop = strp;
520rtn:
521 copyf--;
522}
523seta()
524{
525 register i;
526
527 if(((i = (getch() & CMASK) - '0') > 0) &&
528 (i <= 9) && (i <= frame->nargs))ap = *((int **)frame + i-1 + (sizeof(struct s)/sizeof(int **)));
529}
530caseda(){
531 app++;
532 casedi();
533}
534casedi(){
535 register i, j;
536 register *k;
537
538 lgf++;
539 if(skip() || ((i=getrq()) == 0)){
540 if(dip != d)wbt(0);
541 if(dilev > 0){
542 v.dn = dip->dnl;
543 v.dl = dip->maxl;
544 dip = &d[--dilev];
545 offset = dip->op;
546 }
547 goto rtn;
548 }
549 if(++dilev == NDI){
550 --dilev;
551 prstr("Cannot divert.\n");
552 edone(02);
553 }
554 if(dip != d)wbt(0);
555 diflg++;
556 dip = &d[dilev];
557 dip->op = finds(i);
558 dip->curd = i;
559 clrmn(oldmn);
560 k = (int *)&dip->dnl;
561 for(j=0; j<10; j++)k[j] = 0; /*not op and curd*/
562rtn:
563 app = 0;
564 diflg = 0;
565}
566casedt(){
567 lgf++;
568 dip->dimac = dip->ditrap = dip->ditf = 0;
569 skip();
570 dip->ditrap = vnumb((int *)0);
571 if(nonumb)return;
572 skip();
573 dip->dimac = getrq();
574}
575casetl(){
576 register i, j;
577 int w1, w2, w3, delim;
578 filep begin;
579 extern width(), pchar();
580
581 dip->nls = 0;
582 skip();
583 if(dip != d)wbfl();
584 if((offset = begin = alloc()) == 0)return;
585 if((delim = getch()) & MOT){
586 ch = delim;
587 delim = '\'';
588 }else delim &= CMASK;
589 if(!nlflg)
590 while(((i = getch()) & CMASK) != '\n'){
591 if((i & CMASK) == delim)i = IMP;
592 wbf(i);
593 }
594 wbf(IMP);wbf(IMP);wbt(0);
595
596 w1 = hseg(width,begin);
597 w2 = hseg(width,(filep)0);
598 w3 = hseg(width,(filep)0);
599 offset = dip->op;
600#ifdef NROFF
601 if(!offset)horiz(po);
602#endif
603 hseg(pchar,begin);
604 if(w2 || w3)horiz(j=quant((lt - w2)/2-w1,HOR));
605 hseg(pchar,(filep)0);
606 if(w3){
607 horiz(lt-w1-w2-w3-j);
608 hseg(pchar,(filep)0);
609 }
610 newline(0);
611 if(dip != d){if(dip->dnl > dip->hnl)dip->hnl = dip->dnl;}
612 else{if(v.nl > dip->hnl)dip->hnl = v.nl;}
613 ffree(begin);
614}
615casepc(){
616 pagech = chget(IMP);
617}
618hseg(f,p)
619int (*f)();
620filep p;
621{
622 register acc, i;
623 static filep q;
624
625 acc = 0;
626 if(p)q = p;
627 while(1){
628 i = rbf0(q);
629 q = incoff(q);
630 if(!i || (i == IMP))return(acc);
631 if((i & CMASK) == pagech){
632 nrbits = i & ~CMASK;
633 nform = fmt[findr('%')];
634 acc += fnumb(v.pn,f);
635 }else acc += (*f)(i);
636 }
637}
638casepm(){
639 register i, k;
640 register char *p;
641 int xx, cnt, kk, tot;
642 filep j;
643 char *kvt();
644 char pmline[10];
645
646 kk = cnt = 0;
647 tot = !skip();
648 for(i = 0; i<NM; i++){
649 if(!((xx = contab[i].rq) & MMASK))continue;
650 p = pmline;
651 j = (((filep)contab[i].x.mx)<<BLKBITS);
652 k = 1;
653 while((j = blist[blisti(j)]) != -1){k++; j <<= BLKBITS;}
654 cnt++;
655 kk += k;
656 if(!tot){
657 *p++ = xx & 0177;
658 if(!(*p++ = (xx >> BYTE) & 0177))*(p-1) = ' ';
659 *p++ = ' ';
660 kvt(k,p);
661 prstr(pmline);
662 }
663 }
664 if(tot || (cnt > 1)){
665 kvt(kk,pmline);
666 prstr(pmline);
667 }
668}
669char *kvt(k,p)
670int k;
671char *p;
672{
673 if(k>=100)*p++ = k/100 + '0';
674 if(k>=10)*p++ = (k%100)/10 + '0';
675 *p++ = k%10 + '0';
676 *p++ = '\n';
677 *p = 0;
678 return(p);
679}
680dummy(){}