n4.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. /*
  2. * troff4.c
  3. *
  4. * number registers, conversion, arithmetic
  5. */
  6. #include "tdef.h"
  7. #include "fns.h"
  8. #include "ext.h"
  9. int regcnt = NNAMES;
  10. int falsef = 0; /* on if inside false branch of if */
  11. #define NHASHSIZE 128 /* must be 2**n */
  12. #define NHASH(i) ((i>>6)^i) & (NHASHSIZE-1)
  13. Numtab *nhash[NHASHSIZE];
  14. Numtab *numtabp = NULL;
  15. #define NDELTA 400
  16. int ncnt = 0;
  17. void setn(void)
  18. {
  19. int i, j, f;
  20. Tchar ii;
  21. Uchar *p;
  22. char buf[NTM]; /* for \n(.S */
  23. f = nform = 0;
  24. if ((i = cbits(ii = getach())) == '+')
  25. f = 1;
  26. else if (i == '-')
  27. f = -1;
  28. else if (ii) /* don't put it back if it's already back (thanks to jaap) */
  29. ch = ii;
  30. if (falsef)
  31. f = 0;
  32. if ((i = getsn()) == 0)
  33. return;
  34. p = unpair(i);
  35. if (p[0] == '.')
  36. switch (p[1]) {
  37. case 's':
  38. i = pts;
  39. break;
  40. case 'v':
  41. i = lss;
  42. break;
  43. case 'f':
  44. i = font;
  45. break;
  46. case 'p':
  47. i = pl;
  48. break;
  49. case 't':
  50. i = findt1();
  51. break;
  52. case 'o':
  53. i = po;
  54. break;
  55. case 'l':
  56. i = ll;
  57. break;
  58. case 'i':
  59. i = in;
  60. break;
  61. case '$':
  62. i = frame->nargs;
  63. break;
  64. case 'A':
  65. i = ascii;
  66. break;
  67. case 'c':
  68. i = numtabp[CD].val;
  69. break;
  70. case 'n':
  71. i = lastl;
  72. break;
  73. case 'a':
  74. i = ralss;
  75. break;
  76. case 'h':
  77. i = dip->hnl;
  78. break;
  79. case 'd':
  80. if (dip != d)
  81. i = dip->dnl;
  82. else
  83. i = numtabp[NL].val;
  84. break;
  85. case 'u':
  86. i = fi;
  87. break;
  88. case 'j':
  89. i = ad + 2 * admod;
  90. break;
  91. case 'w':
  92. i = widthp;
  93. break;
  94. case 'x':
  95. i = nel;
  96. break;
  97. case 'y':
  98. i = un;
  99. break;
  100. case 'T':
  101. i = dotT;
  102. break; /* -Tterm used in nroff */
  103. case 'V':
  104. i = VERT;
  105. break;
  106. case 'H':
  107. i = HOR;
  108. break;
  109. case 'k':
  110. i = ne;
  111. break;
  112. case 'P':
  113. i = print;
  114. break;
  115. case 'L':
  116. i = ls;
  117. break;
  118. case 'R': /* maximal # of regs that can be addressed */
  119. i = 255*256 - regcnt;
  120. break;
  121. case 'z':
  122. p = unpair(dip->curd);
  123. *pbp++ = p[1]; /* watch order */
  124. *pbp++ = p[0];
  125. return;
  126. case 'b':
  127. i = bdtab[font];
  128. break;
  129. case 'F':
  130. cpushback(cfname[ifi]);
  131. return;
  132. case 'S':
  133. buf[0] = j = 0;
  134. for( i = 0; tabtab[i] != 0 && i < NTAB; i++) {
  135. if (i > 0)
  136. buf[j++] = ' ';
  137. sprintf(&buf[j], "%d", tabtab[i] & TABMASK);
  138. j = strlen(buf);
  139. if ( tabtab[i] & RTAB)
  140. sprintf(&buf[j], "uR");
  141. else if (tabtab[i] & CTAB)
  142. sprintf(&buf[j], "uC");
  143. else
  144. sprintf(&buf[j], "uL");
  145. j += 2;
  146. }
  147. cpushback(buf);
  148. return;
  149. default:
  150. goto s0;
  151. }
  152. else {
  153. s0:
  154. if ((j = findr(i)) == -1)
  155. i = 0;
  156. else {
  157. i = numtabp[j].val = numtabp[j].val + numtabp[j].inc * f;
  158. nform = numtabp[j].fmt;
  159. }
  160. }
  161. setn1(i, nform, (Tchar) 0);
  162. }
  163. Tchar numbuf[25];
  164. Tchar *numbufp;
  165. int wrc(Tchar i)
  166. {
  167. if (numbufp >= &numbuf[24])
  168. return(0);
  169. *numbufp++ = i;
  170. return(1);
  171. }
  172. /* insert into input number i, in format form, with size-font bits bits */
  173. void setn1(int i, int form, Tchar bits)
  174. {
  175. numbufp = numbuf;
  176. nrbits = bits;
  177. nform = form;
  178. fnumb(i, wrc);
  179. *numbufp = 0;
  180. pushback(numbuf);
  181. }
  182. void prnumtab(Numtab *p)
  183. {
  184. int i;
  185. for (i = 0; i < ncnt; i++)
  186. if (p)
  187. if (p[i].r != 0)
  188. fprintf(stderr, "slot %d, %s, val %d\n", i, unpair(p[i].r), p[i].val);
  189. else
  190. fprintf(stderr, "slot %d empty\n", i);
  191. else
  192. fprintf(stderr, "slot %d empty\n", i);
  193. }
  194. void nnspace(void)
  195. {
  196. ncnt = sizeof(numtab)/sizeof(Numtab) + NDELTA;
  197. numtabp = (Numtab *) grow((char *)numtabp, ncnt, sizeof(Numtab));
  198. if (numtabp == NULL) {
  199. ERROR "not enough memory for registers (%d)", ncnt WARN;
  200. exit(1);
  201. }
  202. numtabp = (Numtab *) memcpy((char *)numtabp, (char *)numtab,
  203. sizeof(numtab));
  204. if (numtabp == NULL) {
  205. ERROR "Cannot initialize registers" WARN;
  206. exit(1);
  207. }
  208. }
  209. void grownumtab(void)
  210. {
  211. ncnt += NDELTA;
  212. numtabp = (Numtab *) grow((char *) numtabp, ncnt, sizeof(Numtab));
  213. if (numtabp == NULL) {
  214. ERROR "Too many number registers (%d)", ncnt WARN;
  215. done2(04);
  216. } else {
  217. memset((char *)(numtabp) + (ncnt - NDELTA) * sizeof(Numtab),
  218. 0, NDELTA * sizeof(Numtab));
  219. nrehash();
  220. }
  221. }
  222. void nrehash(void)
  223. {
  224. Numtab *p;
  225. int i;
  226. for (i=0; i<NHASHSIZE; i++)
  227. nhash[i] = 0;
  228. for (p=numtabp; p < &numtabp[ncnt]; p++)
  229. p->link = 0;
  230. for (p=numtabp; p < &numtabp[ncnt]; p++) {
  231. if (p->r == 0)
  232. continue;
  233. i = NHASH(p->r);
  234. p->link = nhash[i];
  235. nhash[i] = p;
  236. }
  237. }
  238. void nunhash(Numtab *rp)
  239. {
  240. Numtab *p;
  241. Numtab **lp;
  242. if (rp->r == 0)
  243. return;
  244. lp = &nhash[NHASH(rp->r)];
  245. p = *lp;
  246. while (p) {
  247. if (p == rp) {
  248. *lp = p->link;
  249. p->link = 0;
  250. return;
  251. }
  252. lp = &p->link;
  253. p = p->link;
  254. }
  255. }
  256. int findr(int i)
  257. {
  258. Numtab *p;
  259. int h = NHASH(i);
  260. if (i == 0)
  261. return(-1);
  262. a0:
  263. for (p = nhash[h]; p; p = p->link)
  264. if (i == p->r)
  265. return(p - numtabp);
  266. for (p = numtabp; p < &numtabp[ncnt]; p++) {
  267. if (p->r == 0) {
  268. p->r = i;
  269. p->link = nhash[h];
  270. nhash[h] = p;
  271. regcnt++;
  272. return(p - numtabp);
  273. }
  274. }
  275. grownumtab();
  276. goto a0;
  277. }
  278. int usedr(int i) /* returns -1 if nr i has never been used */
  279. {
  280. Numtab *p;
  281. if (i == 0)
  282. return(-1);
  283. for (p = nhash[NHASH(i)]; p; p = p->link)
  284. if (i == p->r)
  285. return(p - numtabp);
  286. return -1;
  287. }
  288. int fnumb(int i, int (*f)(Tchar))
  289. {
  290. int j;
  291. j = 0;
  292. if (i < 0) {
  293. j = (*f)('-' | nrbits);
  294. i = -i;
  295. }
  296. switch (nform) {
  297. default:
  298. case '1':
  299. case 0:
  300. return decml(i, f) + j;
  301. case 'i':
  302. case 'I':
  303. return roman(i, f) + j;
  304. case 'a':
  305. case 'A':
  306. return abc(i, f) + j;
  307. }
  308. }
  309. int decml(int i, int (*f)(Tchar))
  310. {
  311. int j, k;
  312. k = 0;
  313. nform--;
  314. if ((j = i / 10) || (nform > 0))
  315. k = decml(j, f);
  316. return(k + (*f)((i % 10 + '0') | nrbits));
  317. }
  318. int roman(int i, int (*f)(Tchar))
  319. {
  320. if (!i)
  321. return((*f)('0' | nrbits));
  322. if (nform == 'i')
  323. return(roman0(i, f, "ixcmz", "vldw"));
  324. else
  325. return(roman0(i, f, "IXCMZ", "VLDW"));
  326. }
  327. int roman0(int i, int (*f)(Tchar), char *onesp, char *fivesp)
  328. {
  329. int q, rem, k;
  330. if (!i)
  331. return(0);
  332. k = roman0(i / 10, f, onesp + 1, fivesp + 1);
  333. q = (i = i % 10) / 5;
  334. rem = i % 5;
  335. if (rem == 4) {
  336. k += (*f)(*onesp | nrbits);
  337. if (q)
  338. i = *(onesp + 1);
  339. else
  340. i = *fivesp;
  341. return(k += (*f)(i | nrbits));
  342. }
  343. if (q)
  344. k += (*f)(*fivesp | nrbits);
  345. while (--rem >= 0)
  346. k += (*f)(*onesp | nrbits);
  347. return(k);
  348. }
  349. int abc(int i, int (*f)(Tchar))
  350. {
  351. if (!i)
  352. return((*f)('0' | nrbits));
  353. else
  354. return(abc0(i - 1, f));
  355. }
  356. int abc0(int i, int (*f)(Tchar))
  357. {
  358. int j, k;
  359. k = 0;
  360. if (j = i / 26)
  361. k = abc0(j - 1, f);
  362. return(k + (*f)((i % 26 + nform) | nrbits));
  363. }
  364. long atoi0(void)
  365. {
  366. int c, k, cnt;
  367. Tchar ii;
  368. long i, acc;
  369. acc = 0;
  370. nonumb = 0;
  371. cnt = -1;
  372. a0:
  373. cnt++;
  374. ii = getch();
  375. c = cbits(ii);
  376. switch (c) {
  377. default:
  378. ch = ii;
  379. if (cnt)
  380. break;
  381. case '+':
  382. i = ckph();
  383. if (nonumb)
  384. break;
  385. acc += i;
  386. goto a0;
  387. case '-':
  388. i = ckph();
  389. if (nonumb)
  390. break;
  391. acc -= i;
  392. goto a0;
  393. case '*':
  394. i = ckph();
  395. if (nonumb)
  396. break;
  397. acc *= i;
  398. goto a0;
  399. case '/':
  400. i = ckph();
  401. if (nonumb)
  402. break;
  403. if (i == 0) {
  404. flusho();
  405. ERROR "divide by zero." WARN;
  406. acc = 0;
  407. } else
  408. acc /= i;
  409. goto a0;
  410. case '%':
  411. i = ckph();
  412. if (nonumb)
  413. break;
  414. acc %= i;
  415. goto a0;
  416. case '&': /*and*/
  417. i = ckph();
  418. if (nonumb)
  419. break;
  420. if ((acc > 0) && (i > 0))
  421. acc = 1;
  422. else
  423. acc = 0;
  424. goto a0;
  425. case ':': /*or*/
  426. i = ckph();
  427. if (nonumb)
  428. break;
  429. if ((acc > 0) || (i > 0))
  430. acc = 1;
  431. else
  432. acc = 0;
  433. goto a0;
  434. case '=':
  435. if (cbits(ii = getch()) != '=')
  436. ch = ii;
  437. i = ckph();
  438. if (nonumb) {
  439. acc = 0;
  440. break;
  441. }
  442. if (i == acc)
  443. acc = 1;
  444. else
  445. acc = 0;
  446. goto a0;
  447. case '>':
  448. k = 0;
  449. if (cbits(ii = getch()) == '=')
  450. k++;
  451. else
  452. ch = ii;
  453. i = ckph();
  454. if (nonumb) {
  455. acc = 0;
  456. break;
  457. }
  458. if (acc > (i - k))
  459. acc = 1;
  460. else
  461. acc = 0;
  462. goto a0;
  463. case '<':
  464. k = 0;
  465. if (cbits(ii = getch()) == '=')
  466. k++;
  467. else
  468. ch = ii;
  469. i = ckph();
  470. if (nonumb) {
  471. acc = 0;
  472. break;
  473. }
  474. if (acc < (i + k))
  475. acc = 1;
  476. else
  477. acc = 0;
  478. goto a0;
  479. case ')':
  480. break;
  481. case '(':
  482. acc = atoi0();
  483. goto a0;
  484. }
  485. return(acc);
  486. }
  487. long ckph(void)
  488. {
  489. Tchar i;
  490. long j;
  491. if (cbits(i = getch()) == '(')
  492. j = atoi0();
  493. else {
  494. j = atoi1(i);
  495. }
  496. return(j);
  497. }
  498. /*
  499. * print error about illegal numeric argument;
  500. */
  501. void prnumerr(void)
  502. {
  503. char err_buf[40];
  504. static char warn[] = "Numeric argument expected";
  505. int savcd = numtabp[CD].val;
  506. if (numerr.type == RQERR)
  507. sprintf(err_buf, "%c%s: %s", nb ? cbits(c2) : cbits(cc),
  508. unpair(numerr.req), warn);
  509. else
  510. sprintf(err_buf, "\\%c'%s': %s", numerr.esc, &numerr.escarg,
  511. warn);
  512. if (frame != stk) /* uncertainty correction */
  513. numtabp[CD].val--;
  514. ERROR err_buf WARN;
  515. numtabp[CD].val = savcd;
  516. }
  517. long atoi1(Tchar ii)
  518. {
  519. int i, j, digits;
  520. double acc; /* this is the only double in troff! */
  521. int neg, abs, field, decpnt;
  522. extern int ifnum;
  523. neg = abs = field = decpnt = digits = 0;
  524. acc = 0;
  525. for (;;) {
  526. i = cbits(ii);
  527. switch (i) {
  528. default:
  529. break;
  530. case '+':
  531. ii = getch();
  532. continue;
  533. case '-':
  534. neg = 1;
  535. ii = getch();
  536. continue;
  537. case '|':
  538. abs = 1 + neg;
  539. neg = 0;
  540. ii = getch();
  541. continue;
  542. }
  543. break;
  544. }
  545. a1:
  546. while (i >= '0' && i <= '9') {
  547. field++;
  548. digits++;
  549. acc = 10 * acc + i - '0';
  550. ii = getch();
  551. i = cbits(ii);
  552. }
  553. if (i == '.' && !decpnt++) {
  554. field++;
  555. digits = 0;
  556. ii = getch();
  557. i = cbits(ii);
  558. goto a1;
  559. }
  560. if (!field) {
  561. ch = ii;
  562. goto a2;
  563. }
  564. switch (i) {
  565. case 'u':
  566. i = j = 1; /* should this be related to HOR?? */
  567. break;
  568. case 'v': /*VSs - vert spacing*/
  569. j = lss;
  570. i = 1;
  571. break;
  572. case 'm': /*Ems*/
  573. j = EM;
  574. i = 1;
  575. break;
  576. case 'n': /*Ens*/
  577. j = EM;
  578. if (TROFF)
  579. i = 2;
  580. else
  581. i = 1; /*Same as Ems in NROFF*/
  582. break;
  583. case 'p': /*Points*/
  584. j = INCH;
  585. i = 72;
  586. break;
  587. case 'i': /*Inches*/
  588. j = INCH;
  589. i = 1;
  590. break;
  591. case 'c': /*Centimeters*/
  592. /* if INCH is too big, this will overflow */
  593. j = INCH * 50;
  594. i = 127;
  595. break;
  596. case 'P': /*Picas*/
  597. j = INCH;
  598. i = 6;
  599. break;
  600. default:
  601. j = dfact;
  602. ch = ii;
  603. i = dfactd;
  604. }
  605. if (neg)
  606. acc = -acc;
  607. if (!noscale) {
  608. acc = (acc * j) / i;
  609. }
  610. if (field != digits && digits > 0)
  611. while (digits--)
  612. acc /= 10;
  613. if (abs) {
  614. if (dip != d)
  615. j = dip->dnl;
  616. else
  617. j = numtabp[NL].val;
  618. if (!vflag) {
  619. j = numtabp[HP].val;
  620. }
  621. if (abs == 2)
  622. j = -j;
  623. acc -= j;
  624. }
  625. a2:
  626. nonumb = (!field || field == decpnt);
  627. if (nonumb && (trace & TRNARGS) && !ismot(ii) && !nlflg && !ifnum) {
  628. if (cbits(ii) != RIGHT ) /* Too painful to do right */
  629. prnumerr();
  630. }
  631. return(acc);
  632. }
  633. void caserr(void)
  634. {
  635. int i, j;
  636. Numtab *p;
  637. lgf++;
  638. while (!skip() && (i = getrq()) ) {
  639. j = usedr(i);
  640. if (j < 0)
  641. continue;
  642. p = &numtabp[j];
  643. nunhash(p);
  644. p->r = p->val = p->inc = p->fmt = 0;
  645. regcnt--;
  646. }
  647. }
  648. /*
  649. * .nr request; if tracing, don't check optional
  650. * 2nd argument because tbl generates .in 1.5n
  651. */
  652. void casenr(void)
  653. {
  654. int i, j;
  655. int savtr = trace;
  656. lgf++;
  657. skip();
  658. if ((i = findr(getrq())) == -1)
  659. goto rtn;
  660. skip();
  661. j = inumb(&numtabp[i].val);
  662. if (nonumb)
  663. goto rtn;
  664. numtabp[i].val = j;
  665. skip();
  666. trace = 0;
  667. j = atoi0(); /* BUG??? */
  668. trace = savtr;
  669. if (nonumb)
  670. goto rtn;
  671. numtabp[i].inc = j;
  672. rtn:
  673. return;
  674. }
  675. void caseaf(void)
  676. {
  677. int i, k;
  678. Tchar j;
  679. lgf++;
  680. if (skip() || !(i = getrq()) || skip())
  681. return;
  682. k = 0;
  683. j = getch();
  684. if (!isalpha(cbits(j))) {
  685. ch = j;
  686. while ((j = cbits(getch())) >= '0' && j <= '9')
  687. k++;
  688. }
  689. if (!k)
  690. k = j;
  691. numtabp[findr(i)].fmt = k; /* was k & BYTEMASK */
  692. }
  693. void setaf(void) /* return format of number register */
  694. {
  695. int i, j;
  696. i = usedr(getsn());
  697. if (i == -1)
  698. return;
  699. if (numtabp[i].fmt > 20) /* it was probably a, A, i or I */
  700. *pbp++ = numtabp[i].fmt;
  701. else
  702. for (j = (numtabp[i].fmt ? numtabp[i].fmt : 1); j; j--)
  703. *pbp++ = '0';
  704. }
  705. int vnumb(int *i)
  706. {
  707. vflag++;
  708. dfact = lss;
  709. res = VERT;
  710. return(inumb(i));
  711. }
  712. int hnumb(int *i)
  713. {
  714. dfact = EM;
  715. res = HOR;
  716. return(inumb(i));
  717. }
  718. int inumb(int *n)
  719. {
  720. int i, j, f;
  721. Tchar ii;
  722. f = 0;
  723. if (n) {
  724. if ((j = cbits(ii = getch())) == '+')
  725. f = 1;
  726. else if (j == '-')
  727. f = -1;
  728. else
  729. ch = ii;
  730. }
  731. i = atoi0();
  732. if (n && f)
  733. i = *n + f * i;
  734. i = quant(i, res);
  735. vflag = 0;
  736. res = dfactd = dfact = 1;
  737. if (nonumb)
  738. i = 0;
  739. return(i);
  740. }
  741. int quant(int n, int m)
  742. {
  743. int i, neg;
  744. neg = 0;
  745. if (n < 0) {
  746. neg++;
  747. n = -n;
  748. }
  749. /* better as i = ((n + m/2)/m)*m */
  750. i = n / m;
  751. if (n - m * i > m / 2)
  752. i += 1;
  753. i *= m;
  754. if (neg)
  755. i = -i;
  756. return(i);
  757. }