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