n5.c 14 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * troff5.c
  11. *
  12. * misc processing requests
  13. */
  14. #include "tdef.h"
  15. #include "fns.h"
  16. #include "ext.h"
  17. int iflist[NIF];
  18. int ifx;
  19. int ifnum = 0; /* trying numeric expression for .if or .ie condition */
  20. void casead(void)
  21. {
  22. int i;
  23. ad = 1;
  24. /* leave admod alone */
  25. if (skip())
  26. return;
  27. switch (i = cbits(getch())) {
  28. case 'r': /* right adj, left ragged */
  29. admod = 2;
  30. break;
  31. case 'l': /* left adj, right ragged */
  32. admod = ad = 0; /* same as casena */
  33. break;
  34. case 'c': /*centered adj*/
  35. admod = 1;
  36. break;
  37. case 'b':
  38. case 'n':
  39. admod = 0;
  40. break;
  41. case '0':
  42. case '2':
  43. case '4':
  44. ad = 0;
  45. case '1':
  46. case '3':
  47. case '5':
  48. admod = (i - '0') / 2;
  49. }
  50. }
  51. void casena(void)
  52. {
  53. ad = 0;
  54. }
  55. void casefi(void)
  56. {
  57. tbreak();
  58. fi = 1;
  59. pendnf = 0;
  60. }
  61. void casenf(void)
  62. {
  63. tbreak();
  64. fi = 0;
  65. }
  66. void casers(void)
  67. {
  68. dip->nls = 0;
  69. }
  70. void casens(void)
  71. {
  72. dip->nls++;
  73. }
  74. chget(int c)
  75. {
  76. Tchar i;
  77. i = 0;
  78. if (skip() || ismot(i = getch()) || cbits(i) == ' ' || cbits(i) == '\n') {
  79. ch = i;
  80. return(c);
  81. } else
  82. return cbits(i); /* was (i & BYTEMASK) */
  83. }
  84. void casecc(void)
  85. {
  86. cc = chget('.');
  87. }
  88. void casec2(void)
  89. {
  90. c2 = chget('\'');
  91. }
  92. void casehc(void)
  93. {
  94. ohc = chget(OHC);
  95. }
  96. void casetc(void)
  97. {
  98. tabc = chget(0);
  99. }
  100. void caselc(void)
  101. {
  102. dotc = chget(0);
  103. }
  104. void casehy(void)
  105. {
  106. int i;
  107. hyf = 1;
  108. if (skip())
  109. return;
  110. noscale++;
  111. i = atoi0();
  112. noscale = 0;
  113. if (nonumb)
  114. return;
  115. hyf = max(i, 0);
  116. }
  117. void casenh(void)
  118. {
  119. hyf = 0;
  120. }
  121. max(int aa, int bb)
  122. {
  123. if (aa > bb)
  124. return(aa);
  125. else
  126. return(bb);
  127. }
  128. void casece(void)
  129. {
  130. int i;
  131. noscale++;
  132. skip();
  133. i = max(atoi0(), 0);
  134. if (nonumb)
  135. i = 1;
  136. tbreak();
  137. ce = i;
  138. noscale = 0;
  139. }
  140. void casein(void)
  141. {
  142. int i;
  143. if (skip())
  144. i = in1;
  145. else {
  146. i = max(hnumb(&in), 0);
  147. if (nonumb)
  148. i = in1;
  149. }
  150. tbreak();
  151. in1 = in;
  152. in = i;
  153. if (!nc) {
  154. un = in;
  155. setnel();
  156. }
  157. }
  158. void casell(void)
  159. {
  160. int i;
  161. if (skip())
  162. i = ll1;
  163. else {
  164. i = max(hnumb(&ll), INCH / 10);
  165. if (nonumb)
  166. i = ll1;
  167. }
  168. ll1 = ll;
  169. ll = i;
  170. setnel();
  171. }
  172. void caselt(void)
  173. {
  174. int i;
  175. if (skip())
  176. i = lt1;
  177. else {
  178. i = max(hnumb(&lt), 0);
  179. if (nonumb)
  180. i = lt1;
  181. }
  182. lt1 = lt;
  183. lt = i;
  184. }
  185. void caseti(void)
  186. {
  187. int i;
  188. if (skip())
  189. return;
  190. i = max(hnumb(&in), 0);
  191. tbreak();
  192. un1 = i;
  193. setnel();
  194. }
  195. void casels(void)
  196. {
  197. int i;
  198. noscale++;
  199. if (skip())
  200. i = ls1;
  201. else {
  202. i = max(inumb(&ls), 1);
  203. if (nonumb)
  204. i = ls1;
  205. }
  206. ls1 = ls;
  207. ls = i;
  208. noscale = 0;
  209. }
  210. void casepo(void)
  211. {
  212. int i;
  213. if (skip())
  214. i = po1;
  215. else {
  216. i = max(hnumb(&po), 0);
  217. if (nonumb)
  218. i = po1;
  219. }
  220. po1 = po;
  221. po = i;
  222. if (TROFF & !ascii)
  223. esc += po - po1;
  224. }
  225. void casepl(void)
  226. {
  227. int i;
  228. skip();
  229. if ((i = vnumb(&pl)) == 0)
  230. pl = 11 * INCH; /*11in*/
  231. else
  232. pl = i;
  233. if (numtabp[NL].val > pl)
  234. numtabp[NL].val = pl;
  235. }
  236. void casewh(void)
  237. {
  238. int i, j, k;
  239. lgf++;
  240. skip();
  241. i = vnumb((int *)0);
  242. if (nonumb)
  243. return;
  244. skip();
  245. j = getrq();
  246. if ((k = findn(i)) != NTRAP) {
  247. mlist[k] = j;
  248. return;
  249. }
  250. for (k = 0; k < NTRAP; k++)
  251. if (mlist[k] == 0)
  252. break;
  253. if (k == NTRAP) {
  254. flusho();
  255. ERROR "cannot plant trap." WARN;
  256. return;
  257. }
  258. mlist[k] = j;
  259. nlist[k] = i;
  260. }
  261. void casech(void)
  262. {
  263. int i, j, k;
  264. lgf++;
  265. skip();
  266. if (!(j = getrq()))
  267. return;
  268. else
  269. for (k = 0; k < NTRAP; k++)
  270. if (mlist[k] == j)
  271. break;
  272. if (k == NTRAP)
  273. return;
  274. skip();
  275. i = vnumb((int *)0);
  276. if (nonumb)
  277. mlist[k] = 0;
  278. nlist[k] = i;
  279. }
  280. findn(int i)
  281. {
  282. int k;
  283. for (k = 0; k < NTRAP; k++)
  284. if ((nlist[k] == i) && (mlist[k] != 0))
  285. break;
  286. return(k);
  287. }
  288. void casepn(void)
  289. {
  290. int i;
  291. skip();
  292. noscale++;
  293. i = max(inumb(&numtabp[PN].val), 0);
  294. noscale = 0;
  295. if (!nonumb) {
  296. npn = i;
  297. npnflg++;
  298. }
  299. }
  300. void casebp(void)
  301. {
  302. int i;
  303. Stack *savframe;
  304. if (dip != d)
  305. return;
  306. savframe = frame;
  307. skip();
  308. if ((i = inumb(&numtabp[PN].val)) < 0)
  309. i = 0;
  310. tbreak();
  311. if (!nonumb) {
  312. npn = i;
  313. npnflg++;
  314. } else if (dip->nls)
  315. return;
  316. eject(savframe);
  317. }
  318. void casetm(void)
  319. {
  320. casetm1(0, stderr);
  321. }
  322. void casefm(void)
  323. {
  324. static struct fcache {
  325. char *name;
  326. FILE *fp;
  327. } fcache[15];
  328. int i;
  329. if ( skip() || !getname()) {
  330. ERROR "fm: missing filename" WARN;
  331. return;
  332. }
  333. for (i = 0; i < 15 && fcache[i].fp != NULL; i++) {
  334. if (strcmp(nextf, fcache[i].name) == 0)
  335. break;
  336. }
  337. if (i >= 15) {
  338. ERROR "fm: too many streams" WARN;
  339. return;
  340. }
  341. if (fcache[i].fp == NULL) {
  342. if( (fcache[i].fp = fopen(nextf, "w")) == NULL) {
  343. ERROR "fm: cannot open %s", nextf WARN;
  344. return;
  345. }
  346. fcache[i].name = strdupl(nextf);
  347. }
  348. casetm1(0, fcache[i].fp);
  349. }
  350. void casetm1(int ab, FILE *out)
  351. {
  352. int i, j, c;
  353. char *p;
  354. char tmbuf[NTM];
  355. lgf++;
  356. copyf++;
  357. if (ab) {
  358. if (skip())
  359. ERROR "User Abort" WARN;
  360. else {
  361. extern int error;
  362. int savtrac = trace;
  363. trace = 0;
  364. noscale++;
  365. i = inumb(&trace);
  366. noscale--;
  367. if (i) {
  368. error = i;
  369. if (nlflg || skip())
  370. ERROR "User Abort, exit code %d", i WARN;
  371. }
  372. trace = savtrac;
  373. }
  374. } else
  375. skip();
  376. for (i = 0; i < NTM - 2; ) {
  377. if ((c = cbits(getch())) == '\n' || c == RIGHT)
  378. break;
  379. else if (c == MINUS) { /* special pleading for strange encodings */
  380. tmbuf[i++] = '\\';
  381. tmbuf[i++] = '-';
  382. } else if (c == PRESC) {
  383. tmbuf[i++] = '\\';
  384. tmbuf[i++] = 'e';
  385. } else if (c == FILLER) {
  386. tmbuf[i++] = '\\';
  387. tmbuf[i++] = '&';
  388. } else if (c == UNPAD) {
  389. tmbuf[i++] = '\\';
  390. tmbuf[i++] = ' ';
  391. } else if (c == OHC) {
  392. tmbuf[i++] = '\\';
  393. tmbuf[i++] = '%';
  394. } else if (c >= ALPHABET) {
  395. p = chname(c);
  396. switch (*p) {
  397. case MBchar:
  398. sprintf(&tmbuf[i], p+1);
  399. break;
  400. case Number:
  401. sprintf(&tmbuf[i], "\\N'%s'", p+1);
  402. break;
  403. case Troffchar:
  404. if (strlen(p+1) == 2)
  405. sprintf(&tmbuf[i], "\\(%s", p+1);
  406. else
  407. sprintf(&tmbuf[i], "\\C'%s'", p+1);
  408. break;
  409. default:
  410. sprintf(&tmbuf[i]," %s? ", p);
  411. break;
  412. }
  413. j = strlen(&tmbuf[i]);
  414. i += j;
  415. } else
  416. tmbuf[i++] = c;
  417. }
  418. tmbuf[i] = 0;
  419. if (ab) /* truncate output */
  420. obufp = obuf; /* should be a function in n2.c */
  421. flusho();
  422. if (i)
  423. fprintf(out, "%s\n", tmbuf);
  424. fflush(out);
  425. copyf--;
  426. lgf--;
  427. }
  428. void casesp(void)
  429. {
  430. casesp1(0);
  431. }
  432. void casesp1(int a)
  433. {
  434. int i, j, savlss;
  435. tbreak();
  436. if (dip->nls || trap)
  437. return;
  438. i = findt1();
  439. if (!a) {
  440. skip();
  441. j = vnumb((int *)0);
  442. if (nonumb)
  443. j = lss;
  444. } else
  445. j = a;
  446. if (j == 0)
  447. return;
  448. if (i < j)
  449. j = i;
  450. savlss = lss;
  451. if (dip != d)
  452. i = dip->dnl;
  453. else
  454. i = numtabp[NL].val;
  455. if ((i + j) < 0)
  456. j = -i;
  457. lss = j;
  458. newline(0);
  459. lss = savlss;
  460. }
  461. void casert(void)
  462. {
  463. int a, *p;
  464. skip();
  465. if (dip != d)
  466. p = &dip->dnl;
  467. else
  468. p = &numtabp[NL].val;
  469. a = vnumb(p);
  470. if (nonumb)
  471. a = dip->mkline;
  472. if ((a < 0) || (a >= *p))
  473. return;
  474. nb++;
  475. casesp1(a - *p);
  476. }
  477. void caseem(void)
  478. {
  479. lgf++;
  480. skip();
  481. em = getrq();
  482. }
  483. void casefl(void)
  484. {
  485. tbreak();
  486. if (!ascii)
  487. ptflush();
  488. flusho();
  489. }
  490. void caseev(void)
  491. {
  492. int nxev;
  493. if (skip()) {
  494. e0:
  495. if (evi == 0)
  496. return;
  497. nxev = evlist[--evi];
  498. goto e1;
  499. }
  500. noscale++;
  501. nxev = atoi0();
  502. noscale = 0;
  503. if (nonumb)
  504. goto e0;
  505. flushi();
  506. if (nxev >= NEV || nxev < 0 || evi >= EVLSZ) {
  507. flusho();
  508. ERROR "cannot do .ev %d", nxev WARN;
  509. if (error)
  510. done2(040);
  511. else
  512. edone(040);
  513. return;
  514. }
  515. evlist[evi++] = ev;
  516. e1:
  517. if (ev == nxev)
  518. return;
  519. ev = nxev;
  520. envp = &env[ev];
  521. }
  522. void envcopy(Env *e1, Env *e2) /* copy env e2 to e1 */
  523. {
  524. *e1 = *e2; /* rumor hath that this fails on some machines */
  525. }
  526. void caseel(void)
  527. {
  528. if (--ifx < 0) {
  529. ifx = 0;
  530. iflist[0] = 0;
  531. }
  532. caseif1(2);
  533. }
  534. void caseie(void)
  535. {
  536. if (ifx >= NIF) {
  537. ERROR "if-else overflow." WARN;
  538. ifx = 0;
  539. edone(040);
  540. }
  541. caseif1(1);
  542. ifx++;
  543. }
  544. void caseif(void)
  545. {
  546. caseif1(0);
  547. }
  548. void caseif1(int x)
  549. {
  550. extern int falsef;
  551. int notflag, true;
  552. Tchar i;
  553. if (x == 2) {
  554. notflag = 0;
  555. true = iflist[ifx];
  556. goto i1;
  557. }
  558. true = 0;
  559. skip();
  560. if ((cbits(i = getch())) == '!') {
  561. notflag = 1;
  562. } else {
  563. notflag = 0;
  564. ch = i;
  565. }
  566. ifnum++;
  567. i = atoi0();
  568. ifnum = 0;
  569. if (!nonumb) {
  570. if (i > 0)
  571. true++;
  572. goto i1;
  573. }
  574. i = getch();
  575. switch (cbits(i)) {
  576. case 'e':
  577. if (!(numtabp[PN].val & 01))
  578. true++;
  579. break;
  580. case 'o':
  581. if (numtabp[PN].val & 01)
  582. true++;
  583. break;
  584. case 'n':
  585. if (NROFF)
  586. true++;
  587. break;
  588. case 't':
  589. if (TROFF)
  590. true++;
  591. break;
  592. case ' ':
  593. break;
  594. default:
  595. true = cmpstr(i);
  596. }
  597. i1:
  598. true ^= notflag;
  599. if (x == 1)
  600. iflist[ifx] = !true;
  601. if (true) {
  602. i2:
  603. while ((cbits(i = getch())) == ' ')
  604. ;
  605. if (cbits(i) == LEFT)
  606. goto i2;
  607. ch = i;
  608. nflush++;
  609. } else {
  610. if (!nlflg) {
  611. copyf++;
  612. falsef++;
  613. eatblk(0);
  614. copyf--;
  615. falsef--;
  616. }
  617. }
  618. }
  619. void eatblk(int inblk)
  620. {
  621. int cnt, i;
  622. cnt = 0;
  623. do {
  624. if (ch) {
  625. i = cbits(ch);
  626. ch = 0;
  627. } else
  628. i = cbits(getch0());
  629. if (i == ESC)
  630. cnt++;
  631. else {
  632. if (cnt == 1)
  633. switch (i) {
  634. case '{': i = LEFT; break;
  635. case '}': i = RIGHT; break;
  636. case '\n': i = 'x'; break;
  637. }
  638. cnt = 0;
  639. }
  640. if (i == LEFT) eatblk(1);
  641. } while ((!inblk && (i != '\n')) || (inblk && (i != RIGHT)));
  642. if (i == '\n') {
  643. nlflg++;
  644. if (ip == 0)
  645. numtabp[CD].val++;
  646. }
  647. }
  648. cmpstr(Tchar c)
  649. {
  650. int j, delim;
  651. Tchar i;
  652. int val;
  653. int savapts, savapts1, savfont, savfont1, savpts, savpts1;
  654. Tchar string[1280];
  655. Tchar *sp;
  656. if (ismot(c))
  657. return(0);
  658. delim = cbits(c);
  659. savapts = apts;
  660. savapts1 = apts1;
  661. savfont = font;
  662. savfont1 = font1;
  663. savpts = pts;
  664. savpts1 = pts1;
  665. sp = string;
  666. while ((j = cbits(i = getch()))!=delim && j!='\n' && sp<&string[1280-1])
  667. *sp++ = i;
  668. if (sp >= string + 1280) {
  669. ERROR "too-long string compare." WARN;
  670. edone(0100);
  671. }
  672. if (nlflg) {
  673. val = sp==string;
  674. goto rtn;
  675. }
  676. *sp = 0;
  677. apts = savapts;
  678. apts1 = savapts1;
  679. font = savfont;
  680. font1 = savfont1;
  681. pts = savpts;
  682. pts1 = savpts1;
  683. mchbits();
  684. val = 1;
  685. sp = string;
  686. while ((j = cbits(i = getch())) != delim && j != '\n') {
  687. if (*sp != i) {
  688. eat(delim);
  689. val = 0;
  690. goto rtn;
  691. }
  692. sp++;
  693. }
  694. if (*sp)
  695. val = 0;
  696. rtn:
  697. apts = savapts;
  698. apts1 = savapts1;
  699. font = savfont;
  700. font1 = savfont1;
  701. pts = savpts;
  702. pts1 = savpts1;
  703. mchbits();
  704. return(val);
  705. }
  706. void caserd(void)
  707. {
  708. lgf++;
  709. skip();
  710. getname();
  711. if (!iflg) {
  712. if (quiet) {
  713. if (NROFF) {
  714. echo_off();
  715. flusho();
  716. }
  717. fprintf(stderr, "\007"); /*bell*/
  718. } else {
  719. if (nextf[0]) {
  720. fprintf(stderr, "%s:", nextf);
  721. } else {
  722. fprintf(stderr, "\007"); /*bell*/
  723. }
  724. }
  725. }
  726. collect();
  727. tty++;
  728. pushi(RD_OFFSET, PAIR('r','d'));
  729. }
  730. rdtty(void)
  731. {
  732. char onechar;
  733. onechar = 0;
  734. if (read(0, &onechar, 1) == 1) {
  735. if (onechar == '\n')
  736. tty++;
  737. else
  738. tty = 1;
  739. if (tty != 3)
  740. return(onechar);
  741. }
  742. tty = 0;
  743. if (NROFF && quiet)
  744. echo_on();
  745. return(0);
  746. }
  747. void caseec(void)
  748. {
  749. eschar = chget('\\');
  750. }
  751. void caseeo(void)
  752. {
  753. eschar = 0;
  754. }
  755. void caseta(void)
  756. {
  757. int i, j, k;
  758. tabtab[0] = nonumb = 0;
  759. for (i = 0; ((i < (NTAB - 1)) && !nonumb); i++) {
  760. if (skip())
  761. break;
  762. k = tabtab[max(i-1, 0)] & TABMASK;
  763. if ((j = max(hnumb(&k), 0)) > TABMASK) {
  764. ERROR "Tab too far away" WARN;
  765. j = TABMASK;
  766. }
  767. tabtab[i] = j & TABMASK;
  768. if (!nonumb)
  769. switch (cbits(ch)) {
  770. case 'C':
  771. tabtab[i] |= CTAB;
  772. break;
  773. case 'R':
  774. tabtab[i] |= RTAB;
  775. break;
  776. default: /*includes L*/
  777. break;
  778. }
  779. nonumb = ch = 0;
  780. }
  781. if (!skip())
  782. ERROR "Too many tab stops" WARN;
  783. tabtab[i] = 0;
  784. }
  785. void casene(void)
  786. {
  787. int i, j;
  788. skip();
  789. i = vnumb((int *)0);
  790. if (nonumb)
  791. i = lss;
  792. if (dip == d && numtabp[NL].val == -1) {
  793. newline(1);
  794. return;
  795. }
  796. if (i > (j = findt1())) {
  797. i = lss;
  798. lss = j;
  799. dip->nls = 0;
  800. newline(0);
  801. lss = i;
  802. }
  803. }
  804. void casetr(void)
  805. {
  806. int i, j;
  807. Tchar k;
  808. lgf++;
  809. skip();
  810. while ((i = cbits(k=getch())) != '\n') {
  811. if (ismot(k))
  812. return;
  813. if (ismot(k = getch()))
  814. return;
  815. if ((j = cbits(k)) == '\n')
  816. j = ' ';
  817. trtab[i] = j;
  818. }
  819. }
  820. void casecu(void)
  821. {
  822. cu++;
  823. caseul();
  824. }
  825. void caseul(void)
  826. {
  827. int i;
  828. noscale++;
  829. skip();
  830. i = max(atoi0(), 0);
  831. if (nonumb)
  832. i = 1;
  833. if (ul && (i == 0)) {
  834. font = sfont;
  835. ul = cu = 0;
  836. }
  837. if (i) {
  838. if (!ul) {
  839. sfont = font;
  840. font = ulfont;
  841. }
  842. ul = i;
  843. }
  844. noscale = 0;
  845. mchbits();
  846. }
  847. void caseuf(void)
  848. {
  849. int i, j;
  850. if (skip() || !(i = getrq()) || i == 'S' || (j = findft(i)) == -1)
  851. ulfont = ULFONT; /*default underline position*/
  852. else
  853. ulfont = j;
  854. if (NROFF && ulfont == FT)
  855. ulfont = ULFONT;
  856. }
  857. void caseit(void)
  858. {
  859. int i;
  860. lgf++;
  861. it = itmac = 0;
  862. noscale++;
  863. skip();
  864. i = atoi0();
  865. skip();
  866. if (!nonumb && (itmac = getrq()))
  867. it = i;
  868. noscale = 0;
  869. }
  870. void casemc(void)
  871. {
  872. int i;
  873. if (icf > 1)
  874. ic = 0;
  875. icf = 0;
  876. if (skip())
  877. return;
  878. ic = getch();
  879. icf = 1;
  880. skip();
  881. i = max(hnumb((int *)0), 0);
  882. if (!nonumb)
  883. ics = i;
  884. }
  885. void casemk(void)
  886. {
  887. int i, j;
  888. if (dip != d)
  889. j = dip->dnl;
  890. else
  891. j = numtabp[NL].val;
  892. if (skip()) {
  893. dip->mkline = j;
  894. return;
  895. }
  896. if ((i = getrq()) == 0)
  897. return;
  898. numtabp[findr(i)].val = j;
  899. }
  900. void casesv(void)
  901. {
  902. int i;
  903. skip();
  904. if ((i = vnumb((int *)0)) < 0)
  905. return;
  906. if (nonumb)
  907. i = 1;
  908. sv += i;
  909. caseos();
  910. }
  911. void caseos(void)
  912. {
  913. int savlss;
  914. if (sv <= findt1()) {
  915. savlss = lss;
  916. lss = sv;
  917. newline(0);
  918. lss = savlss;
  919. sv = 0;
  920. }
  921. }
  922. void casenm(void)
  923. {
  924. int i;
  925. lnmod = nn = 0;
  926. if (skip())
  927. return;
  928. lnmod++;
  929. noscale++;
  930. i = inumb(&numtabp[LN].val);
  931. if (!nonumb)
  932. numtabp[LN].val = max(i, 0);
  933. getnm(&ndf, 1);
  934. getnm(&nms, 0);
  935. getnm(&ni, 0);
  936. getnm(&nmwid, 3); /* really kludgy! */
  937. noscale = 0;
  938. nmbits = chbits;
  939. }
  940. /*
  941. * .nm relies on the fact that illegal args are skipped; don't warn
  942. * for illegality of these
  943. */
  944. void getnm(int *p, int min)
  945. {
  946. int i;
  947. int savtr = trace;
  948. eat(' ');
  949. if (skip())
  950. return;
  951. trace = 0;
  952. i = atoi0();
  953. if (nonumb)
  954. return;
  955. *p = max(i, min);
  956. trace = savtr;
  957. }
  958. void casenn(void)
  959. {
  960. noscale++;
  961. skip();
  962. nn = max(atoi0(), 1);
  963. noscale = 0;
  964. }
  965. void caseab(void)
  966. {
  967. casetm1(1, stderr);
  968. done3(0);
  969. }
  970. /* nroff terminal handling has been pretty well excised */
  971. /* as part of the merge with troff. these are ghostly remnants, */
  972. /* called, but doing nothing. restore them at your peril. */
  973. void save_tty(void) /*save any tty settings that may be changed*/
  974. {
  975. }
  976. void restore_tty(void) /*restore tty settings from beginning*/
  977. {
  978. }
  979. void set_tty(void)
  980. {
  981. }
  982. void echo_off(void) /*turn off ECHO for .rd in "-q" mode*/
  983. {
  984. }
  985. void echo_on(void) /*restore ECHO after .rd in "-q" mode*/
  986. {
  987. }