n3.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  1. /*
  2. * troff3.c
  3. *
  4. * macro and string routines, storage allocation
  5. */
  6. #include "tdef.h"
  7. #include "fns.h"
  8. #include "ext.h"
  9. Tchar *argtop;
  10. int pagech = '%';
  11. int strflg;
  12. #define MHASHSIZE 128 /* must be 2**n */
  13. #define MHASH(x) ((x>>6)^x) & (MHASHSIZE-1)
  14. Contab *mhash[MHASHSIZE];
  15. Blockp *blist; /* allocated blocks for macros and strings */
  16. int nblist; /* how many there are */
  17. int bfree = -1; /* first (possible) free block in the list */
  18. Contab *contabp = NULL;
  19. #define MDELTA 500
  20. int nm = 0;
  21. int savname; /* name of macro/string being defined */
  22. int savslot; /* place in Contab of savname */
  23. int freeslot = -1; /* first (possible) free slot in contab */
  24. void prcontab(Contab *p)
  25. {
  26. int i;
  27. for (i = 0; i < nm; i++)
  28. if (p)
  29. if (p[i].rq != 0)
  30. fprintf(stderr, "slot %d, %-2.2s\n", i, unpair(p[i].rq));
  31. else
  32. fprintf(stderr, "slot %d empty\n", i);
  33. else
  34. fprintf(stderr, "slot %d empty\n", i);
  35. }
  36. void blockinit(void)
  37. {
  38. blist = (Blockp *) calloc(NBLIST, sizeof(Blockp));
  39. if (blist == NULL) {
  40. ERROR "not enough room for %d blocks", NBLIST WARN;
  41. done2(1);
  42. }
  43. nblist = NBLIST;
  44. blist[0].nextoff = blist[1].nextoff = -1;
  45. blist[0].bp = (Tchar *) calloc(BLK, sizeof(Tchar));
  46. blist[1].bp = (Tchar *) calloc(BLK, sizeof(Tchar));
  47. /* -1 prevents blist[0] from being used; temporary fix */
  48. /* for a design botch: offset==0 is overloaded. */
  49. /* blist[1] reserved for .rd indicator -- also unused. */
  50. /* but someone unwittingly looks at these, so allocate something */
  51. bfree = 2;
  52. }
  53. char *grow(char *ptr, int num, int size) /* make array bigger */
  54. {
  55. char *p, new;
  56. if (ptr == NULL)
  57. p = (char *) calloc(num, size);
  58. else
  59. p = (char *) realloc(ptr, num * size);
  60. return p;
  61. }
  62. void mnspace(void)
  63. {
  64. nm = sizeof(contab)/sizeof(Contab) + MDELTA;
  65. freeslot = sizeof(contab)/sizeof(Contab) + 1;
  66. contabp = (Contab *) grow((char *) contabp, nm, sizeof(Contab));
  67. if (contabp == NULL) {
  68. ERROR "not enough memory for namespace of %d marcos", nm WARN;
  69. exit(1);
  70. }
  71. contabp = (Contab *) memcpy((char *) contabp, (char *)contab,
  72. sizeof(contab));
  73. if (contabp == NULL) {
  74. ERROR "Cannot reinitialize macro/request name list" WARN;
  75. exit(1);
  76. }
  77. }
  78. void caseig(void)
  79. {
  80. int i;
  81. Offset oldoff = offset;
  82. offset = 0;
  83. i = copyb();
  84. offset = oldoff;
  85. if (i != '.')
  86. control(i, 1);
  87. }
  88. void casern(void)
  89. {
  90. int i, j, k;
  91. lgf++;
  92. skip();
  93. if ((i = getrq()) == 0 || (oldmn = findmn(i)) < 0)
  94. return;
  95. skip();
  96. clrmn(findmn(j = getrq()));
  97. if (j) {
  98. munhash(&contabp[oldmn]);
  99. contabp[oldmn].rq = j;
  100. maddhash(&contabp[oldmn]);
  101. if (dip != d )
  102. for (k = dilev; k; k--)
  103. if (d[k].curd == i)
  104. d[k].curd = j;
  105. }
  106. }
  107. void maddhash(Contab *rp)
  108. {
  109. Contab **hp;
  110. if (rp->rq == 0)
  111. return;
  112. hp = &mhash[MHASH(rp->rq)];
  113. rp->link = *hp;
  114. *hp = rp;
  115. }
  116. void munhash(Contab *mp)
  117. {
  118. Contab *p;
  119. Contab **lp;
  120. if (mp->rq == 0)
  121. return;
  122. lp = &mhash[MHASH(mp->rq)];
  123. p = *lp;
  124. while (p) {
  125. if (p == mp) {
  126. *lp = p->link;
  127. p->link = 0;
  128. return;
  129. }
  130. lp = &p->link;
  131. p = p->link;
  132. }
  133. }
  134. void mrehash(void)
  135. {
  136. Contab *p;
  137. int i;
  138. for (i=0; i < MHASHSIZE; i++)
  139. mhash[i] = 0;
  140. for (p=contabp; p < &contabp[nm]; p++)
  141. p->link = 0;
  142. for (p=contabp; p < &contabp[nm]; p++) {
  143. if (p->rq == 0)
  144. continue;
  145. i = MHASH(p->rq);
  146. p->link = mhash[i];
  147. mhash[i] = p;
  148. }
  149. }
  150. void caserm(void)
  151. {
  152. int j;
  153. int k = 0;
  154. lgf++;
  155. g0:
  156. while (!skip() && (j = getrq()) != 0) {
  157. if (dip != d)
  158. for (k = dilev; k; k--)
  159. if (d[k].curd == j) {
  160. ERROR "cannot remove diversion %s during definition",
  161. unpair(j) WARN;
  162. goto g0;
  163. }
  164. clrmn(findmn(j));
  165. }
  166. lgf--;
  167. }
  168. void caseas(void)
  169. {
  170. app++;
  171. caseds();
  172. }
  173. void caseds(void)
  174. {
  175. ds++;
  176. casede();
  177. }
  178. void caseam(void)
  179. {
  180. app++;
  181. casede();
  182. }
  183. void casede(void)
  184. {
  185. int i, req;
  186. Offset savoff;
  187. req = '.';
  188. lgf++;
  189. skip();
  190. if ((i = getrq()) == 0)
  191. goto de1;
  192. if ((offset = finds(i)) == 0)
  193. goto de1;
  194. if (newmn)
  195. savslot = newmn;
  196. else
  197. savslot = findmn(i);
  198. savname = i;
  199. if (ds)
  200. copys();
  201. else
  202. req = copyb();
  203. clrmn(oldmn);
  204. if (newmn) {
  205. if (contabp[newmn].rq)
  206. munhash(&contabp[newmn]);
  207. contabp[newmn].rq = i;
  208. maddhash(&contabp[newmn]);
  209. }
  210. if (apptr) {
  211. savoff = offset;
  212. offset = apptr;
  213. wbf((Tchar) IMP);
  214. offset = savoff;
  215. }
  216. offset = dip->op;
  217. if (req != '.')
  218. control(req, 1);
  219. de1:
  220. ds = app = 0;
  221. }
  222. int findmn(int i)
  223. {
  224. Contab *p;
  225. for (p = mhash[MHASH(i)]; p; p = p->link)
  226. if (i == p->rq)
  227. return(p - contabp);
  228. return(-1);
  229. }
  230. void clrmn(int i)
  231. {
  232. if (i >= 0) {
  233. if (contabp[i].mx)
  234. ffree(contabp[i].mx);
  235. munhash(&contabp[i]);
  236. contabp[i].rq = 0;
  237. contabp[i].mx = 0;
  238. contabp[i].emx = 0;
  239. contabp[i].f = 0;
  240. if (contabp[i].divsiz != NULL) {
  241. free(contabp[i].divsiz);
  242. contabp[i].divsiz = NULL;
  243. }
  244. if (freeslot > i)
  245. freeslot = i;
  246. }
  247. }
  248. void growcontab(void)
  249. {
  250. nm += MDELTA;
  251. contabp = (Contab *) grow((char *) contabp , nm, sizeof(Contab));
  252. if (contabp == NULL) {
  253. ERROR "Too many (%d) string/macro names", nm WARN;
  254. done2(02);
  255. } else {
  256. memset((char *)(contabp) + (nm - MDELTA) * sizeof(Contab),
  257. 0, MDELTA * sizeof(Contab));
  258. mrehash();
  259. }
  260. }
  261. Offset finds(int mn)
  262. {
  263. int i;
  264. Tchar j = IMP;
  265. Offset savip;
  266. oldmn = findmn(mn);
  267. newmn = 0;
  268. apptr = 0;
  269. if (app && oldmn >= 0 && contabp[oldmn].mx) {
  270. savip = ip;
  271. ip = contabp[oldmn].emx;
  272. oldmn = -1;
  273. apptr = ip;
  274. if (!diflg)
  275. ip = incoff(ip);
  276. nextb = ip;
  277. ip = savip;
  278. } else {
  279. for (i = freeslot; i < nm; i++) {
  280. if (contabp[i].rq == 0)
  281. break;
  282. }
  283. if (i == nm)
  284. growcontab();
  285. freeslot = i + 1;
  286. if ((nextb = alloc()) == -1) {
  287. app = 0;
  288. if (macerr++ > 1)
  289. done2(02);
  290. if (nextb == 0)
  291. ERROR "Not enough space for string/macro names" WARN;
  292. edone(04);
  293. return(offset = 0);
  294. }
  295. contabp[i].mx = nextb;
  296. if (!diflg) {
  297. newmn = i;
  298. if (oldmn == -1)
  299. contabp[i].rq = -1;
  300. } else {
  301. contabp[i].rq = mn;
  302. maddhash(&contabp[i]);
  303. }
  304. }
  305. app = 0;
  306. return(offset = nextb);
  307. }
  308. int skip(void)
  309. {
  310. Tchar i;
  311. while (cbits(i = getch()) == ' ' || ismot(i))
  312. ;
  313. ch = i;
  314. return(nlflg);
  315. }
  316. int copyb(void)
  317. {
  318. int i, j, state;
  319. Tchar ii;
  320. int req, k;
  321. Offset savoff;
  322. Uchar *p;
  323. if (skip() || !(j = getrq()))
  324. j = '.';
  325. req = j;
  326. p = unpair(j);
  327. /* was: k = j >> BYTE; j &= BYTEMASK; */
  328. j = p[0];
  329. k = p[1];
  330. copyf++;
  331. flushi();
  332. nlflg = 0;
  333. state = 1;
  334. /* state 0 eat up
  335. * state 1 look for .
  336. * state 2 look for first char of end macro
  337. * state 3 look for second char of end macro
  338. */
  339. while (1) {
  340. i = cbits(ii = getch());
  341. if (state == 3) {
  342. if (i == k)
  343. break;
  344. if (!k) {
  345. ch = ii;
  346. i = getach();
  347. ch = ii;
  348. if (!i)
  349. break;
  350. }
  351. state = 0;
  352. goto c0;
  353. }
  354. if (i == '\n') {
  355. state = 1;
  356. nlflg = 0;
  357. goto c0;
  358. }
  359. if (state == 1 && i == '.') {
  360. state++;
  361. savoff = offset;
  362. goto c0;
  363. }
  364. if (state == 2 && i == j) {
  365. state++;
  366. goto c0;
  367. }
  368. state = 0;
  369. c0:
  370. if (offset)
  371. wbf(ii);
  372. }
  373. if (offset) {
  374. offset = savoff;
  375. wbf((Tchar)0);
  376. }
  377. copyf--;
  378. return(req);
  379. }
  380. void copys(void)
  381. {
  382. Tchar i;
  383. copyf++;
  384. if (skip())
  385. goto c0;
  386. if (cbits(i = getch()) != '"')
  387. wbf(i);
  388. while (cbits(i = getch()) != '\n')
  389. wbf(i);
  390. c0:
  391. wbf((Tchar)0);
  392. copyf--;
  393. }
  394. Offset alloc(void) /* return free Offset in nextb */
  395. {
  396. int i, j;
  397. for (i = bfree; i < nblist; i++)
  398. if (blist[i].nextoff == 0)
  399. break;
  400. if (i == nblist) {
  401. blist = (Blockp *) realloc((char *) blist, 2 * nblist * sizeof(Blockp));
  402. if (blist == NULL) {
  403. ERROR "can't grow blist for string/macro defns" WARN;
  404. done2(2);
  405. }
  406. nblist *= 2;
  407. for (j = i; j < nblist; j++) {
  408. blist[j].nextoff = 0;
  409. blist[j].bp = 0;
  410. }
  411. }
  412. blist[i].nextoff = -1; /* this block is the end */
  413. bfree = i + 1;
  414. if (blist[i].bp == 0)
  415. blist[i].bp = (Tchar *) calloc(BLK, sizeof(Tchar));
  416. if (blist[i].bp == NULL) {
  417. ERROR "can't allocate memory for string/macro definitions" WARN;
  418. done2(2);
  419. }
  420. nextb = (Offset) i * BLK;
  421. return nextb;
  422. }
  423. void ffree(Offset i) /* free list of blocks starting at blist(o) */
  424. { /* (doesn't actually free the blocks, just the pointers) */
  425. int j;
  426. for ( ; blist[j = bindex(i)].nextoff != -1; ) {
  427. if (bfree > j)
  428. bfree = j;
  429. i = blist[j].nextoff;
  430. blist[j].nextoff = 0;
  431. }
  432. blist[j].nextoff = 0;
  433. }
  434. void wbf(Tchar i) /* store i into offset, get ready for next one */
  435. {
  436. int j, off;
  437. if (!offset)
  438. return;
  439. j = bindex(offset);
  440. if (i == 0)
  441. contabp[savslot].emx = offset;
  442. off = boffset(offset);
  443. blist[j].bp[off++] = i;
  444. offset++;
  445. if (pastend(offset)) { /* off the end of this block */
  446. if (blist[j].nextoff == -1) {
  447. if ((nextb = alloc()) == -1) {
  448. ERROR "Out of temp file space" WARN;
  449. done2(01);
  450. }
  451. blist[j].nextoff = nextb;
  452. }
  453. offset = blist[j].nextoff;
  454. }
  455. }
  456. Tchar rbf(void) /* return next char from blist[] block */
  457. {
  458. Tchar i, j;
  459. if (ip == RD_OFFSET) { /* for rdtty */
  460. if (j = rdtty())
  461. return(j);
  462. else
  463. return(popi());
  464. }
  465. i = rbf0(ip);
  466. if (i == 0) {
  467. if (!app)
  468. i = popi();
  469. return(i);
  470. }
  471. ip = incoff(ip);
  472. return(i);
  473. }
  474. Offset xxxincoff(Offset p) /* get next blist[] block */
  475. {
  476. p++;
  477. if (pastend(p)) { /* off the end of this block */
  478. if ((p = blist[bindex(p-1)].nextoff) == -1) { /* and nothing was allocated after it */
  479. ERROR "Bad storage allocation" WARN;
  480. done2(-5);
  481. }
  482. }
  483. return(p);
  484. }
  485. Tchar popi(void)
  486. {
  487. Stack *p;
  488. if (frame == stk)
  489. return(0);
  490. if (strflg)
  491. strflg--;
  492. p = nxf = frame;
  493. p->nargs = 0;
  494. frame = p->pframe;
  495. ip = p->pip;
  496. pendt = p->ppendt;
  497. lastpbp = p->lastpbp;
  498. return(p->pch);
  499. }
  500. /*
  501. * test that the end of the allocation is above a certain location
  502. * in memory
  503. */
  504. #define SPACETEST(base, size) \
  505. if ((char*)base + size >= (char*)stk+STACKSIZE) \
  506. ERROR "Stacksize overflow in n3" WARN
  507. Offset pushi(Offset newip, int mname)
  508. {
  509. Stack *p;
  510. SPACETEST(nxf, sizeof(Stack));
  511. p = nxf;
  512. p->pframe = frame;
  513. p->pip = ip;
  514. p->ppendt = pendt;
  515. p->pch = ch;
  516. p->lastpbp = lastpbp;
  517. p->mname = mname;
  518. lastpbp = pbp;
  519. pendt = ch = 0;
  520. frame = nxf;
  521. if (nxf->nargs == 0)
  522. nxf += 1;
  523. else
  524. nxf = (Stack *)argtop;
  525. return(ip = newip);
  526. }
  527. void *setbrk(int x)
  528. {
  529. char *i;
  530. if ((i = (char *) calloc(x, 1)) == 0) {
  531. ERROR "Core limit reached" WARN;
  532. edone(0100);
  533. }
  534. return(i);
  535. }
  536. int getsn(void)
  537. {
  538. int i;
  539. if ((i = getach()) == 0)
  540. return(0);
  541. if (i == '(')
  542. return(getrq());
  543. else
  544. return(i);
  545. }
  546. Offset setstr(void)
  547. {
  548. int i, j;
  549. lgf++;
  550. if ((i = getsn()) == 0 || (j = findmn(i)) == -1 || !contabp[j].mx) {
  551. lgf--;
  552. return(0);
  553. } else {
  554. SPACETEST(nxf, sizeof(Stack));
  555. nxf->nargs = 0;
  556. strflg++;
  557. lgf--;
  558. return pushi(contabp[j].mx, i);
  559. }
  560. }
  561. void collect(void)
  562. {
  563. int j;
  564. Tchar i, *strp, *lim, **argpp, **argppend;
  565. int quote;
  566. Stack *savnxf;
  567. copyf++;
  568. nxf->nargs = 0;
  569. savnxf = nxf;
  570. if (skip())
  571. goto rtn;
  572. {
  573. char *memp;
  574. memp = (char *)savnxf;
  575. /*
  576. * 1 s structure for the macro descriptor
  577. * APERMAC Tchar *'s for pointers into the strings
  578. * space for the Tchar's themselves
  579. */
  580. memp += sizeof(Stack);
  581. /*
  582. * CPERMAC = the total # of characters for ALL arguments
  583. */
  584. #define CPERMAC 200
  585. #define APERMAC 9
  586. memp += APERMAC * sizeof(Tchar *);
  587. memp += CPERMAC * sizeof(Tchar);
  588. nxf = (Stack *)memp;
  589. }
  590. lim = (Tchar *)nxf;
  591. argpp = (Tchar **)(savnxf + 1);
  592. argppend = &argpp[APERMAC];
  593. SPACETEST(argppend, sizeof(Tchar *));
  594. strp = (Tchar *)argppend;
  595. /*
  596. * Zero out all the string pointers before filling them in.
  597. */
  598. for (j = 0; j < APERMAC; j++)
  599. argpp[j] = 0;
  600. /* ERROR "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x, lim=0x%x",
  601. * savnxf, nxf, argpp, strp, lim WARN;
  602. */
  603. strflg = 0;
  604. while (argpp != argppend && !skip()) {
  605. *argpp++ = strp;
  606. quote = 0;
  607. if (cbits(i = getch()) == '"')
  608. quote++;
  609. else
  610. ch = i;
  611. while (1) {
  612. i = getch();
  613. /* fprintf(stderr, "collect %c %d\n", cbits(i), cbits(i)); */
  614. if (nlflg || (!quote && argpp != argppend && cbits(i) == ' '))
  615. break; /* collects rest into $9 */
  616. if ( quote
  617. && cbits(i) == '"'
  618. && cbits(i = getch()) != '"') {
  619. ch = i;
  620. break;
  621. }
  622. *strp++ = i;
  623. if (strflg && strp >= lim) {
  624. /* ERROR "strp=0x%x, lim = 0x%x", strp, lim WARN; */
  625. ERROR "Macro argument too long" WARN;
  626. copyf--;
  627. edone(004);
  628. }
  629. SPACETEST(strp, 3 * sizeof(Tchar));
  630. }
  631. *strp++ = 0;
  632. }
  633. nxf = savnxf;
  634. nxf->nargs = argpp - (Tchar **)(savnxf + 1);
  635. argtop = strp;
  636. rtn:
  637. copyf--;
  638. }
  639. void seta(void)
  640. {
  641. int i;
  642. i = cbits(getch()) - '0';
  643. if (i > 0 && i <= APERMAC && i <= frame->nargs)
  644. pushback(*(((Tchar **)(frame + 1)) + i - 1));
  645. }
  646. void caseda(void)
  647. {
  648. app++;
  649. casedi();
  650. }
  651. void casegd(void)
  652. {
  653. int i, j;
  654. skip();
  655. if ((i = getrq()) == 0)
  656. return;
  657. if ((j = findmn(i)) >= 0) {
  658. if (contabp[j].divsiz != NULL) {
  659. numtabp[DN].val = contabp[j].divsiz->dix;
  660. numtabp[DL].val = contabp[j].divsiz->diy;
  661. }
  662. }
  663. }
  664. #define FINDDIV(o) if ((o = findmn(dip->curd)) < 0) \
  665. ERROR "lost diversion %s", unpair(dip->curd) WARN
  666. void casedi(void)
  667. {
  668. int i, j, *k;
  669. lgf++;
  670. if (skip() || (i = getrq()) == 0) {
  671. if (dip != d) {
  672. FINDDIV(savslot);
  673. wbf((Tchar)0);
  674. }
  675. if (dilev > 0) {
  676. numtabp[DN].val = dip->dnl;
  677. numtabp[DL].val = dip->maxl;
  678. FINDDIV(j);
  679. if ((contabp[j].divsiz = (Divsiz *) malloc(sizeof(Divsiz))) == NULL) {
  680. ERROR "Cannot alloc diversion size" WARN;
  681. done2(1);
  682. } else {
  683. contabp[j].divsiz->dix = numtabp[DN].val;
  684. contabp[j].divsiz->diy = numtabp[DL].val;
  685. }
  686. dip = &d[--dilev];
  687. offset = dip->op;
  688. }
  689. goto rtn;
  690. }
  691. if (++dilev == NDI) {
  692. --dilev;
  693. ERROR "Diversions nested too deep" WARN;
  694. edone(02);
  695. }
  696. if (dip != d) {
  697. FINDDIV(j);
  698. savslot = j;
  699. wbf((Tchar)0);
  700. }
  701. diflg++;
  702. dip = &d[dilev];
  703. dip->op = finds(i);
  704. dip->curd = i;
  705. clrmn(oldmn);
  706. k = (int *) & dip->dnl;
  707. for (j = 0; j < 10; j++)
  708. k[j] = 0; /*not op and curd*/
  709. rtn:
  710. app = 0;
  711. diflg = 0;
  712. }
  713. void casedt(void)
  714. {
  715. lgf++;
  716. dip->dimac = dip->ditrap = dip->ditf = 0;
  717. skip();
  718. dip->ditrap = vnumb((int *)0);
  719. if (nonumb)
  720. return;
  721. skip();
  722. dip->dimac = getrq();
  723. }
  724. #define LNSIZE 4000
  725. void casetl(void)
  726. {
  727. int j;
  728. int w[3];
  729. Tchar buf[LNSIZE];
  730. Tchar *tp;
  731. Tchar i, delim;
  732. /*
  733. * bug fix
  734. *
  735. * if .tl is the first thing in the file, the p1
  736. * doesn't come out, also the pagenumber will be 0
  737. *
  738. * tends too confuse the device filter (and the user as well)
  739. */
  740. if (dip == d && numtabp[NL].val == -1)
  741. newline(1);
  742. dip->nls = 0;
  743. skip();
  744. if (ismot(delim = getch())) {
  745. ch = delim;
  746. delim = '\'';
  747. } else
  748. delim = cbits(delim);
  749. tp = buf;
  750. numtabp[HP].val = 0;
  751. w[0] = w[1] = w[2] = 0;
  752. j = 0;
  753. while (cbits(i = getch()) != '\n') {
  754. if (cbits(i) == cbits(delim)) {
  755. if (j < 3)
  756. w[j] = numtabp[HP].val;
  757. numtabp[HP].val = 0;
  758. if (w[j] != 0)
  759. *tp++ = WORDSP;
  760. j++;
  761. *tp++ = 0;
  762. } else {
  763. if (cbits(i) == pagech) {
  764. setn1(numtabp[PN].val, numtabp[findr('%')].fmt,
  765. i&SFMASK);
  766. continue;
  767. }
  768. numtabp[HP].val += width(i);
  769. if (tp < &buf[LNSIZE-10]) {
  770. if (cbits(i) == ' ' && *tp != WORDSP)
  771. *tp++ = WORDSP;
  772. *tp++ = i;
  773. } else {
  774. ERROR "Overflow in casetl" WARN;
  775. }
  776. }
  777. }
  778. if (j<3)
  779. w[j] = numtabp[HP].val;
  780. *tp++ = 0;
  781. *tp++ = 0;
  782. *tp = 0;
  783. tp = buf;
  784. if (NROFF)
  785. horiz(po);
  786. while (i = *tp++)
  787. pchar(i);
  788. if (w[1] || w[2])
  789. horiz(j = quant((lt - w[1]) / 2 - w[0], HOR));
  790. while (i = *tp++)
  791. pchar(i);
  792. if (w[2]) {
  793. horiz(lt - w[0] - w[1] - w[2] - j);
  794. while (i = *tp++)
  795. pchar(i);
  796. }
  797. newline(0);
  798. if (dip != d) {
  799. if (dip->dnl > dip->hnl)
  800. dip->hnl = dip->dnl;
  801. } else {
  802. if (numtabp[NL].val > dip->hnl)
  803. dip->hnl = numtabp[NL].val;
  804. }
  805. }
  806. void casepc(void)
  807. {
  808. pagech = chget(IMP);
  809. }
  810. void casepm(void)
  811. {
  812. int i, k;
  813. int xx, cnt, tcnt, kk, tot;
  814. Offset j;
  815. kk = cnt = tcnt = 0;
  816. tot = !skip();
  817. stackdump();
  818. for (i = 0; i < nm; i++) {
  819. if ((xx = contabp[i].rq) == 0 || contabp[i].mx == 0)
  820. continue;
  821. tcnt++;
  822. j = contabp[i].mx;
  823. for (k = 1; (j = blist[bindex(j)].nextoff) != -1; )
  824. k++;
  825. cnt++;
  826. kk += k;
  827. if (!tot)
  828. fprintf(stderr, "%-2.2s %d\n", unpair(xx), k);
  829. }
  830. fprintf(stderr, "pm: total %d, macros %d, space %d\n", tcnt, cnt, kk);
  831. }
  832. void stackdump(void) /* dumps stack of macros in process */
  833. {
  834. Stack *p;
  835. if (frame != stk) {
  836. fprintf(stderr, "stack: ");
  837. for (p = frame; p != stk; p = p->pframe)
  838. fprintf(stderr, "%s ", unpair(p->mname));
  839. fprintf(stderr, "\n");
  840. }
  841. }