Commit | Line | Data |
---|---|---|
28140ad0 BJ |
1 | #include "tdef.h" |
2 | extern | |
3 | #include "d.h" | |
4 | extern | |
5 | #include "v.h" | |
6 | #ifdef NROFF | |
7 | extern | |
8 | #include "tw.h" | |
9 | #endif | |
10 | #include "s.h" | |
11 | ||
12 | /* | |
13 | troff3.c | |
14 | ||
15 | macro and string routines, storage allocation | |
16 | */ | |
17 | ||
18 | unsigned blist[NBLIST]; | |
19 | extern struct s *frame, *stk, *nxf; | |
20 | extern filep ip; | |
21 | extern filep offset; | |
22 | extern filep nextb; | |
23 | extern char *enda; | |
24 | ||
25 | extern int ch; | |
26 | extern int ibf; | |
27 | extern int lgf; | |
28 | extern int copyf; | |
29 | extern int ch0; | |
30 | extern int app; | |
31 | extern int ds; | |
32 | extern int nlflg; | |
33 | extern int *argtop; | |
34 | extern int *ap; | |
35 | extern int nchar; | |
36 | extern int pendt; | |
37 | extern int rchar; | |
38 | extern int dilev; | |
39 | extern int nonumb; | |
40 | extern int lt; | |
41 | extern int nrbits; | |
42 | extern int nform; | |
43 | extern int fmt[]; | |
44 | extern int oldmn; | |
45 | extern int newmn; | |
46 | extern int macerr; | |
47 | extern filep apptr; | |
48 | extern int diflg; | |
49 | extern filep woff; | |
50 | extern filep roff; | |
51 | extern int wbfi; | |
52 | extern int po; | |
53 | extern int *cp; | |
54 | extern int xxx; | |
55 | int pagech = '%'; | |
56 | int strflg; | |
57 | extern struct contab { | |
58 | int rq; | |
59 | union { | |
60 | int (*f)(); | |
61 | unsigned mx; | |
62 | }x; | |
63 | }contab[NM]; | |
64 | #ifndef VMUNIX | |
65 | int wbuf[BLK]; | |
66 | int rbuf[BLK]; | |
67 | #else | |
68 | int *wbuf; | |
69 | int *rbuf; | |
70 | int Buf[NBLIST*BLK]; | |
71 | #endif | |
72 | ||
73 | caseig(){ | |
74 | register i; | |
75 | ||
76 | offset = 0; | |
77 | if((i = copyb()) != '.')control(i,1); | |
78 | } | |
79 | casern(){ | |
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 | } | |
89 | caserm(){ | |
90 | lgf++; | |
91 | while(!skip()){ | |
92 | clrmn(findmn(getrq())); | |
93 | } | |
94 | } | |
95 | caseas(){ | |
96 | app++; | |
97 | caseds(); | |
98 | } | |
99 | caseds(){ | |
100 | ds++; | |
101 | casede(); | |
102 | } | |
103 | caseam(){ | |
104 | app++; | |
105 | casede(); | |
106 | } | |
107 | casede(){ | |
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); | |
131 | de1: | |
132 | ds = app = 0; | |
133 | return; | |
134 | } | |
135 | findmn(i) | |
136 | int 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 | } | |
146 | clrmn(i) | |
147 | int 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 | } | |
156 | filep finds(mn) | |
157 | int 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 | } | |
201 | skip(){ | |
202 | register i; | |
203 | ||
204 | while(((i=getch()) & CMASK) == ' '); | |
205 | ch=i; | |
206 | return(nlflg); | |
207 | } | |
208 | copyb() | |
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; | |
250 | c0: | |
251 | if(offset)wbf(ii); | |
252 | } | |
253 | if(offset){ | |
254 | wbfl(); | |
255 | offset = savoff; | |
256 | wbt(0); | |
257 | } | |
258 | copyf--; | |
259 | return(req); | |
260 | } | |
261 | copys() | |
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); | |
269 | c0: | |
270 | wbt(0); | |
271 | copyf--; | |
272 | } | |
273 | filep 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 | } | |
290 | ffree(i) | |
291 | filep 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 | } | |
301 | filep boff(i) | |
302 | int i; | |
303 | { | |
304 | return(((filep)i)*BLK + NEV*EVS); | |
305 | } | |
306 | wbt(i) | |
307 | int i; | |
308 | { | |
309 | wbf(i); | |
310 | wbfl(); | |
311 | } | |
312 | wbf(i) | |
313 | int 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 | } | |
339 | wbfl(){ | |
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 | } | |
348 | blisti(i) | |
349 | filep i; | |
350 | { | |
351 | return((i-NEV*EVS)/(BLK)); | |
352 | } | |
353 | rbf(){ | |
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 | } | |
364 | rbf0(p) | |
365 | filep 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 | } | |
380 | filep incoff(p) | |
381 | filep 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 | } | |
394 | popi(){ | |
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 | } | |
411 | pushi(newip) | |
412 | filep 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 | } | |
435 | char *setbrk(x) | |
436 | int 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 | } | |
449 | getsn(){ | |
450 | register i; | |
451 | ||
452 | if((i=getach()) == 0)return(0); | |
453 | if(i == '(')return(getrq()); | |
454 | else return(i); | |
455 | } | |
456 | setstr(){ | |
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 | } | |
473 | collect() | |
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; | |
520 | rtn: | |
521 | copyf--; | |
522 | } | |
523 | seta() | |
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 | } | |
530 | caseda(){ | |
531 | app++; | |
532 | casedi(); | |
533 | } | |
534 | casedi(){ | |
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*/ | |
562 | rtn: | |
563 | app = 0; | |
564 | diflg = 0; | |
565 | } | |
566 | casedt(){ | |
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 | } | |
575 | casetl(){ | |
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 | } | |
615 | casepc(){ | |
616 | pagech = chget(IMP); | |
617 | } | |
618 | hseg(f,p) | |
619 | int (*f)(); | |
620 | filep 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 | } | |
638 | casepm(){ | |
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 | } | |
669 | char *kvt(k,p) | |
670 | int k; | |
671 | char *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 | } | |
680 | dummy(){} |