Commit | Line | Data |
---|---|---|
f10d52e6 JO |
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 | int wbuf[BLK]; | |
65 | int rbuf[BLK]; | |
66 | ||
67 | caseig(){ | |
68 | register i; | |
69 | ||
70 | offset = 0; | |
71 | if((i = copyb()) != '.')control(i,1); | |
72 | } | |
73 | casern(){ | |
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 | } | |
83 | caserm(){ | |
84 | lgf++; | |
85 | while(!skip()){ | |
86 | clrmn(findmn(getrq())); | |
87 | } | |
88 | } | |
89 | caseas(){ | |
90 | app++; | |
91 | caseds(); | |
92 | } | |
93 | caseds(){ | |
94 | ds++; | |
95 | casede(); | |
96 | } | |
97 | caseam(){ | |
98 | app++; | |
99 | casede(); | |
100 | } | |
101 | casede(){ | |
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); | |
125 | de1: | |
126 | ds = app = 0; | |
127 | return; | |
128 | } | |
129 | findmn(i) | |
130 | int 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 | } | |
140 | clrmn(i) | |
141 | int 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 | } | |
150 | filep finds(mn) | |
151 | int 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 | } | |
195 | skip(){ | |
196 | register i; | |
197 | ||
198 | while(((i=getch()) & CMASK) == ' '); | |
199 | ch=i; | |
200 | return(nlflg); | |
201 | } | |
202 | copyb() | |
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; | |
244 | c0: | |
245 | if(offset)wbf(ii); | |
246 | } | |
247 | if(offset){ | |
248 | wbfl(); | |
249 | offset = savoff; | |
250 | wbt(0); | |
251 | } | |
252 | copyf--; | |
253 | return(req); | |
254 | } | |
255 | copys() | |
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); | |
263 | c0: | |
264 | wbt(0); | |
265 | copyf--; | |
266 | } | |
267 | filep 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 | } | |
284 | ffree(i) | |
285 | filep 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 | } | |
295 | filep boff(i) | |
296 | int i; | |
297 | { | |
298 | return(((filep)i)*BLK + NEV*EVS); | |
299 | } | |
300 | wbt(i) | |
301 | int i; | |
302 | { | |
303 | wbf(i); | |
304 | wbfl(); | |
305 | } | |
306 | wbf(i) | |
307 | int 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 | } | |
330 | wbfl(){ | |
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 | } | |
337 | blisti(i) | |
338 | filep i; | |
339 | { | |
340 | return((i-NEV*EVS)/(BLK)); | |
341 | } | |
342 | rbf(){ | |
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 | } | |
353 | rbf0(p) | |
354 | filep 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 | } | |
365 | filep incoff(p) | |
366 | filep 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 | } | |
379 | popi(){ | |
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 | } | |
396 | pushi(newip) | |
397 | filep 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 | } | |
420 | char *setbrk(x) | |
421 | int 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 | } | |
434 | getsn(){ | |
435 | register i; | |
436 | ||
437 | if((i=getach()) == 0)return(0); | |
438 | if(i == '(')return(getrq()); | |
439 | else return(i); | |
440 | } | |
441 | setstr(){ | |
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 | } | |
458 | collect() | |
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 **))) + (sizeof(struct s)-1)) | |
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; | |
505 | rtn: | |
506 | copyf--; | |
507 | } | |
508 | seta() | |
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 | } | |
515 | caseda(){ | |
516 | app++; | |
517 | casedi(); | |
518 | } | |
519 | casedi(){ | |
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*/ | |
547 | rtn: | |
548 | app = 0; | |
549 | diflg = 0; | |
550 | } | |
551 | casedt(){ | |
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 | } | |
560 | casetl(){ | |
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 | } | |
600 | casepc(){ | |
601 | pagech = chget(IMP); | |
602 | } | |
603 | hseg(f,p) | |
604 | int (*f)(); | |
605 | filep 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 | } | |
623 | casepm(){ | |
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 | } | |
654 | char *kvt(k,p) | |
655 | int k; | |
656 | char *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 | } | |
665 | dummy(){} |