n1.c 20 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130
  1. /*
  2. * n1.c
  3. *
  4. * consume options, initialization, main loop,
  5. * input routines, escape function calling
  6. */
  7. #include "tdef.h"
  8. #include "fns.h"
  9. #include "ext.h"
  10. #include "dwbinit.h"
  11. #include <setjmp.h>
  12. #include <time.h>
  13. char *Version = "March 11, 1994";
  14. #ifndef DWBVERSION
  15. #define DWBVERSION "???"
  16. #endif
  17. char *DWBfontdir = FONTDIR;
  18. char *DWBntermdir = NTERMDIR;
  19. char *DWBalthyphens = ALTHYPHENS;
  20. char *DWBhomedir = "";
  21. dwbinit dwbpaths[] = {
  22. &DWBfontdir, NULL, 0,
  23. &DWBntermdir, NULL, 0,
  24. &DWBalthyphens, NULL, 0,
  25. &DWBhomedir, NULL, 0,
  26. NULL, nextf, NS,
  27. NULL, NULL, 0
  28. };
  29. int TROFF = 1; /* assume we started in troff... */
  30. jmp_buf sjbuf;
  31. Offset ipl[NSO];
  32. static FILE *ifile = stdin;
  33. static FILE *ifl[NSO]; /* open input file pointers */
  34. char cfname[NSO+1][NS] = { "stdin" }; /* file name stack */
  35. int cfline[NSO]; /* input line count stack */
  36. char *progname; /* program name (troff or nroff) */
  37. int trace = 0; /* tracing mode: default off */
  38. int trace1 = 0;
  39. main(int argc, char *argv[])
  40. {
  41. char *p;
  42. int j;
  43. Tchar i;
  44. char buf[100];
  45. buf[0] = '\0'; /* make sure it's empty (silly 3b2) */
  46. progname = argv[0];
  47. if ((p = strrchr(progname, '/')) == NULL)
  48. p = progname;
  49. else
  50. p++;
  51. DWBinit(progname, dwbpaths);
  52. if (strcmp(p, "nroff") == 0)
  53. TROFF = 0;
  54. #ifdef UNICODE
  55. alphabet = 128; /* unicode for plan 9 */
  56. #endif /*UNICODE*/
  57. mnspace();
  58. nnspace();
  59. mrehash();
  60. nrehash();
  61. numtabp[NL].val = -1;
  62. while (--argc > 0 && (++argv)[0][0] == '-')
  63. switch (argv[0][1]) {
  64. case 'N': /* ought to be used first... */
  65. TROFF = 0;
  66. break;
  67. case 'd':
  68. fprintf(stderr, "troff/nroff version %s\n", Version);
  69. break;
  70. case 'F': /* switch font tables from default */
  71. if (argv[0][2] != '\0') {
  72. strcpy(termtab, &argv[0][2]);
  73. strcpy(fontdir, &argv[0][2]);
  74. } else {
  75. argv++; argc--;
  76. strcpy(termtab, argv[0]);
  77. strcpy(fontdir, argv[0]);
  78. }
  79. break;
  80. case 0:
  81. goto start;
  82. case 'i':
  83. stdi++;
  84. break;
  85. case 'n':
  86. npn = atoi(&argv[0][2]);
  87. break;
  88. case 'u': /* set emboldening amount */
  89. bdtab[3] = atoi(&argv[0][2]);
  90. if (bdtab[3] < 0 || bdtab[3] > 50)
  91. bdtab[3] = 0;
  92. break;
  93. case 's':
  94. if (!(stop = atoi(&argv[0][2])))
  95. stop++;
  96. break;
  97. case 'r':
  98. sprintf(buf + strlen(buf), ".nr %c %s\n",
  99. argv[0][2], &argv[0][3]);
  100. /* not yet cpushback(buf);*/
  101. /* dotnr(&argv[0][2], &argv[0][3]); */
  102. break;
  103. case 'm':
  104. if (mflg++ >= NMF) {
  105. ERROR "Too many macro packages: %s", argv[0] WARN;
  106. break;
  107. }
  108. strcpy(mfiles[nmfi], nextf);
  109. strcat(mfiles[nmfi++], &argv[0][2]);
  110. break;
  111. case 'o':
  112. getpn(&argv[0][2]);
  113. break;
  114. case 'T':
  115. strcpy(devname, &argv[0][2]);
  116. dotT++;
  117. break;
  118. case 'a':
  119. ascii = 1;
  120. break;
  121. case 'h':
  122. hflg++;
  123. break;
  124. case 'e':
  125. eqflg++;
  126. break;
  127. case 'q':
  128. quiet++;
  129. save_tty();
  130. break;
  131. case 'V':
  132. fprintf(stdout, "%croff: DWB %s\n",
  133. TROFF ? 't' : 'n', DWBVERSION);
  134. exit(0);
  135. case 't':
  136. if (argv[0][2] != '\0')
  137. trace = trace1 = argv[0][2];
  138. break; /* for the sake of compatibility */
  139. default:
  140. ERROR "unknown option %s", argv[0] WARN;
  141. done(02);
  142. }
  143. start:
  144. /*
  145. * cpushback maintains a LIFO, so push pack the -r arguments
  146. * in reverse order to maintain a FIFO in case someone did -rC1 -rC3
  147. */
  148. if (buf[0]) {
  149. char *p = buf;
  150. while(*p++)
  151. ;
  152. while(p > buf) {
  153. while(strncmp(p, ".nr", 3) != 0)
  154. p--;
  155. cpushback(p);
  156. *p-- = '\0';
  157. }
  158. }
  159. argp = argv;
  160. rargc = argc;
  161. nmfi = 0;
  162. init2();
  163. setjmp(sjbuf);
  164. loop:
  165. copyf = lgf = nb = nflush = nlflg = 0;
  166. if (ip && rbf0(ip) == 0 && ejf && frame->pframe <= ejl && dip == d) {
  167. nflush++;
  168. trap = 0;
  169. eject((Stack *)0);
  170. goto loop;
  171. }
  172. i = getch();
  173. if (pendt)
  174. goto Lt;
  175. if ((j = cbits(i)) == XPAR) {
  176. copyf++;
  177. tflg++;
  178. while (cbits(i) != '\n')
  179. pchar(i = getch());
  180. tflg = 0;
  181. copyf--;
  182. goto loop;
  183. }
  184. if (j == cc || j == c2) {
  185. if (j == c2)
  186. nb++;
  187. copyf++;
  188. while ((j = cbits(i = getch())) == ' ' || j == '\t')
  189. ;
  190. ch = i;
  191. copyf--;
  192. control(getrq(), 1);
  193. flushi();
  194. goto loop;
  195. }
  196. Lt:
  197. ch = i;
  198. text();
  199. if (nlflg)
  200. numtabp[HP].val = 0;
  201. goto loop;
  202. }
  203. void init2(void)
  204. {
  205. int i;
  206. char buf[100];
  207. for (i = NTRTAB; --i; )
  208. trtab[i] = i;
  209. trtab[UNPAD] = ' ';
  210. iflg = 0;
  211. obufp = obuf;
  212. if (TROFF)
  213. t_ptinit();
  214. else
  215. n_ptinit();
  216. mchbits();
  217. cvtime();
  218. numtabp[PID].val = getpid();
  219. numtabp[HP].val = init = 0;
  220. numtabp[NL].val = -1;
  221. nfo = 0;
  222. copyf = raw = 0;
  223. sprintf(buf, ".ds .T %s\n", devname);
  224. cpushback(buf);
  225. sprintf(buf, ".ds .P %s\n", DWBhomedir);
  226. cpushback(buf);
  227. numtabp[CD].val = -1; /* compensation */
  228. nx = mflg;
  229. frame = stk = (Stack *)setbrk(STACKSIZE);
  230. dip = &d[0];
  231. nxf = frame + 1;
  232. for (i = 1; i < NEV; i++) /* propagate the environment */
  233. envcopy(&env[i], &env[0]);
  234. for (i = 0; i < NEV; i++) {
  235. if ((env[i]._word._bufp = (Tchar *)calloc(WDSIZE, sizeof(Tchar))) == NULL) {
  236. ERROR "not enough room for word buffers" WARN;
  237. done2(1);
  238. }
  239. env[i]._word._size = WDSIZE;
  240. if ((env[i]._line._bufp = (Tchar *)calloc(LNSIZE, sizeof(Tchar))) == NULL) {
  241. ERROR "not enough room for line buffers" WARN;
  242. done2(1);
  243. }
  244. env[i]._line._size = LNSIZE;
  245. }
  246. if ((oline = (Tchar *)calloc(OLNSIZE, sizeof(Tchar))) == NULL) {
  247. ERROR "not enough room for line buffers" WARN;
  248. done2(1);
  249. }
  250. olinep = oline;
  251. olnsize = OLNSIZE;
  252. blockinit();
  253. }
  254. void cvtime(void)
  255. {
  256. long tt;
  257. struct tm *ltime;
  258. time(&tt);
  259. ltime = localtime(&tt);
  260. numtabp[YR].val = ltime->tm_year % 100;
  261. numtabp[YR].fmt = 2;
  262. numtabp[MO].val = ltime->tm_mon + 1; /* troff uses 1..12 */
  263. numtabp[DY].val = ltime->tm_mday;
  264. numtabp[DW].val = ltime->tm_wday + 1; /* troff uses 1..7 */
  265. }
  266. char errbuf[200];
  267. void errprint(void) /* error message printer */
  268. {
  269. int savecd = numtabp[CD].val;
  270. if (!nlflg)
  271. numtabp[CD].val++;
  272. fprintf(stderr, "%s: ", progname);
  273. fputs(errbuf, stderr);
  274. if (cfname[ifi][0])
  275. fprintf(stderr, "; %s:%d", cfname[ifi], numtabp[CD].val);
  276. fputs("\n", stderr);
  277. if (cfname[ifi][0])
  278. stackdump();
  279. numtabp[CD].val = savecd;
  280. }
  281. int control(int a, int b)
  282. {
  283. int j, k;
  284. extern Contab *contabp;
  285. numerr.type = RQERR;
  286. numerr.req = a;
  287. if (a == 0 || (j = findmn(a)) == -1)
  288. return(0);
  289. if (contabp[j].f == 0) {
  290. if (trace & TRMAC)
  291. fprintf(stderr, "invoke macro %s\n", unpair(a));
  292. if (dip != d)
  293. for (k = dilev; k; k--)
  294. if (d[k].curd == a) {
  295. ERROR "diversion %s invokes itself during diversion",
  296. unpair(a) WARN;
  297. edone(0100);
  298. }
  299. nxf->nargs = 0;
  300. if (b)
  301. collect();
  302. flushi();
  303. return pushi(contabp[j].mx, a); /* BUG??? all that matters is 0/!0 */
  304. }
  305. if (b) {
  306. if (trace & TRREQ)
  307. fprintf(stderr, "invoke request %s\n", unpair(a));
  308. (*contabp[j].f)();
  309. }
  310. return(0);
  311. }
  312. void casept(void)
  313. {
  314. int i;
  315. noscale++;
  316. if (skip())
  317. i = trace1;
  318. else {
  319. i = max(inumb(&trace), 0);
  320. if (nonumb)
  321. i = trace1;
  322. }
  323. trace1 = trace;
  324. trace = i;
  325. noscale = 0;
  326. }
  327. int getrq(void)
  328. {
  329. int i, j;
  330. if ((i = getach()) == 0 || (j = getach()) == 0)
  331. goto rtn;
  332. i = PAIR(i, j);
  333. rtn:
  334. return(i);
  335. }
  336. /*
  337. * table encodes some special characters, to speed up tests
  338. * in getch, viz FLSS, RPT, f, \b, \n, fc, tabch, ldrch
  339. */
  340. char gchtab[NCHARS] = {
  341. 000,004,000,000,010,000,000,000, /* fc, ldr */
  342. 001,002,001,000,001,000,000,000, /* \b, tab, nl, RPT */
  343. 000,000,000,000,000,000,000,000,
  344. 000,001,000,001,000,000,000,000, /* FLSS, ESC */
  345. 000,000,000,000,000,000,000,000,
  346. 000,000,000,000,000,000,000,000,
  347. 000,000,000,000,000,000,000,000,
  348. 000,000,000,000,000,000,000,000,
  349. 000,000,000,000,000,000,000,000,
  350. 000,000,000,000,000,000,000,000,
  351. 000,000,000,000,000,000,000,000,
  352. 000,000,000,000,000,000,000,000,
  353. 000,000,000,000,000,000,001,000, /* f */
  354. 000,000,000,000,000,000,000,000,
  355. 000,000,000,000,000,000,000,000,
  356. 000,000,000,000,000,000,000,000,
  357. };
  358. int realcbits(Tchar c) /* return character bits, or MOTCH if motion */
  359. {
  360. if (ismot(c))
  361. return MOTCH;
  362. else
  363. return c & 0xFFFF;
  364. }
  365. Tchar getch(void)
  366. {
  367. int k;
  368. Tchar i, j;
  369. g0:
  370. if (ch) {
  371. i = ch;
  372. if (cbits(i) == '\n')
  373. nlflg++;
  374. ch = 0;
  375. return(i);
  376. }
  377. if (nlflg)
  378. return('\n');
  379. i = getch0();
  380. if (ismot(i))
  381. return(i);
  382. k = cbits(i);
  383. if (k >= sizeof(gchtab)/sizeof(gchtab[0]) || gchtab[k] == 0) /* nothing special */
  384. return(i);
  385. if (k != ESC) {
  386. if (k == '\n') {
  387. nlflg++;
  388. if (ip == 0)
  389. numtabp[CD].val++; /* line number */
  390. return(k);
  391. }
  392. if (k == FLSS) {
  393. copyf++;
  394. raw++;
  395. i = getch0();
  396. if (!fi)
  397. flss = i;
  398. copyf--;
  399. raw--;
  400. goto g0;
  401. }
  402. if (k == RPT) {
  403. setrpt();
  404. goto g0;
  405. }
  406. if (!copyf) {
  407. if (k == 'f' && lg && !lgf) {
  408. i = getlg(i);
  409. return(i);
  410. }
  411. if (k == fc || k == tabch || k == ldrch) {
  412. if ((i = setfield(k)) == 0)
  413. goto g0;
  414. else
  415. return(i);
  416. }
  417. if (k == '\b') {
  418. i = makem(-width(' ' | chbits));
  419. return(i);
  420. }
  421. }
  422. return(i);
  423. }
  424. k = cbits(j = getch0());
  425. if (ismot(j))
  426. return(j);
  427. switch (k) {
  428. case 'n': /* number register */
  429. setn();
  430. goto g0;
  431. case '$': /* argument indicator */
  432. seta();
  433. goto g0;
  434. case '*': /* string indicator */
  435. setstr();
  436. goto g0;
  437. case '{': /* LEFT */
  438. i = LEFT;
  439. goto gx;
  440. case '}': /* RIGHT */
  441. i = RIGHT;
  442. goto gx;
  443. case '"': /* comment */
  444. while (cbits(i = getch0()) != '\n')
  445. ;
  446. if (ip == 0)
  447. numtabp[CD].val++; /* line number */
  448. nlflg++;
  449. return(i);
  450. /* experiment: put it here instead of copy mode */
  451. case '(': /* special char name \(xx */
  452. case 'C': /* \C'...' */
  453. if ((i = setch(k)) == 0)
  454. goto g0;
  455. goto gx;
  456. case ESC: /* double backslash */
  457. i = eschar;
  458. goto gx;
  459. case 'e': /* printable version of current eschar */
  460. i = PRESC;
  461. goto gx;
  462. case '\n': /* concealed newline */
  463. numtabp[CD].val++;
  464. goto g0;
  465. case ' ': /* unpaddable space */
  466. i = UNPAD;
  467. goto gx;
  468. case '\'': /* \(aa */
  469. i = ACUTE;
  470. goto gx;
  471. case '`': /* \(ga */
  472. i = GRAVE;
  473. goto gx;
  474. case '_': /* \(ul */
  475. i = UNDERLINE;
  476. goto gx;
  477. case '-': /* current font minus */
  478. i = MINUS;
  479. goto gx;
  480. case '&': /* filler */
  481. i = FILLER;
  482. goto gx;
  483. case 'c': /* to be continued */
  484. i = CONT;
  485. goto gx;
  486. case '!': /* transparent indicator */
  487. i = XPAR;
  488. goto gx;
  489. case 't': /* tab */
  490. i = '\t';
  491. return(i);
  492. case 'a': /* leader (SOH) */
  493. /* old: *pbp++ = LEADER; goto g0; */
  494. i = LEADER;
  495. return i;
  496. case '%': /* ohc */
  497. i = OHC;
  498. return(i);
  499. case 'g': /* return format of a number register */
  500. setaf(); /* should this really be in copy mode??? */
  501. goto g0;
  502. case '.': /* . */
  503. i = '.';
  504. gx:
  505. setsfbits(i, sfbits(j));
  506. return(i);
  507. }
  508. if (copyf) {
  509. *pbp++ = j;
  510. return(eschar);
  511. }
  512. switch (k) {
  513. case 'f': /* font indicator */
  514. setfont(0);
  515. goto g0;
  516. case 's': /* size indicator */
  517. setps();
  518. goto g0;
  519. case 'v': /* vert mot */
  520. numerr.type = numerr.escarg = 0; numerr.esc = k;
  521. if (i = vmot()) {
  522. return(i);
  523. }
  524. goto g0;
  525. case 'h': /* horiz mot */
  526. numerr.type = numerr.escarg = 0; numerr.esc = k;
  527. if (i = hmot())
  528. return(i);
  529. goto g0;
  530. case '|': /* narrow space */
  531. if (NROFF)
  532. goto g0;
  533. return(makem((int)(EM)/6));
  534. case '^': /* half narrow space */
  535. if (NROFF)
  536. goto g0;
  537. return(makem((int)(EM)/12));
  538. case 'w': /* width function */
  539. setwd();
  540. goto g0;
  541. case 'p': /* spread */
  542. spread++;
  543. goto g0;
  544. case 'N': /* absolute character number */
  545. numerr.type = numerr.escarg = 0; numerr.esc = k;
  546. if ((i = setabs()) == 0)
  547. goto g0;
  548. return i;
  549. case 'H': /* character height */
  550. numerr.type = numerr.escarg = 0; numerr.esc = k;
  551. return(setht());
  552. case 'S': /* slant */
  553. numerr.type = numerr.escarg = 0; numerr.esc = k;
  554. return(setslant());
  555. case 'z': /* zero with char */
  556. return(setz());
  557. case 'l': /* hor line */
  558. numerr.type = numerr.escarg = 0; numerr.esc = k;
  559. setline();
  560. goto g0;
  561. case 'L': /* vert line */
  562. numerr.type = numerr.escarg = 0; numerr.esc = k;
  563. setvline();
  564. goto g0;
  565. case 'D': /* drawing function */
  566. numerr.type = numerr.escarg = 0; numerr.esc = k;
  567. setdraw();
  568. goto g0;
  569. case 'X': /* \X'...' for copy through */
  570. setxon();
  571. goto g0;
  572. case 'b': /* bracket */
  573. setbra();
  574. goto g0;
  575. case 'o': /* overstrike */
  576. setov();
  577. goto g0;
  578. case 'k': /* mark hor place */
  579. if ((k = findr(getsn())) != -1) {
  580. numtabp[k].val = numtabp[HP].val;
  581. }
  582. goto g0;
  583. case '0': /* number space */
  584. return(makem(width('0' | chbits)));
  585. case 'x': /* extra line space */
  586. numerr.type = numerr.escarg = 0; numerr.esc = k;
  587. if (i = xlss())
  588. return(i);
  589. goto g0;
  590. case 'u': /* half em up */
  591. case 'r': /* full em up */
  592. case 'd': /* half em down */
  593. return(sethl(k));
  594. default:
  595. return(j);
  596. }
  597. /* NOTREACHED */
  598. }
  599. void setxon(void) /* \X'...' for copy through */
  600. {
  601. Tchar xbuf[NC];
  602. Tchar *i;
  603. Tchar c;
  604. int delim, k;
  605. if (ismot(c = getch()))
  606. return;
  607. delim = cbits(c);
  608. i = xbuf;
  609. *i++ = XON | chbits;
  610. while ((k = cbits(c = getch())) != delim && k != '\n' && i < xbuf+NC-1) {
  611. if (k == ' ')
  612. setcbits(c, WORDSP);
  613. *i++ = c | ZBIT;
  614. }
  615. *i++ = XOFF | chbits;
  616. *i = 0;
  617. pushback(xbuf);
  618. }
  619. char ifilt[32] = { 0, 001, 002, 003, 0, 005, 006, 007, 010, 011, 012 };
  620. Tchar getch0(void)
  621. {
  622. int j;
  623. Tchar i;
  624. again:
  625. if (pbp > lastpbp)
  626. i = *--pbp;
  627. else if (ip) {
  628. /* i = rbf(); */
  629. i = rbf0(ip);
  630. if (i == 0)
  631. i = rbf();
  632. else {
  633. ++ip;
  634. if (pastend(ip)) {
  635. --ip;
  636. rbf();
  637. }
  638. }
  639. } else {
  640. if (donef || ndone)
  641. done(0);
  642. if (nx || 1) { /* BUG: was ibufp >= eibuf, so EOF test is wrong */
  643. if (nfo < 0)
  644. ERROR "in getch0, nfo = %d", nfo WARN;
  645. if (nfo == 0) {
  646. g0:
  647. if (nextfile()) {
  648. if (ip)
  649. goto again;
  650. }
  651. }
  652. nx = 0;
  653. #ifdef UNICODE
  654. if (MB_CUR_MAX > 1)
  655. i = get1ch(ifile);
  656. else
  657. #endif /*UNICODE*/
  658. i = getc(ifile);
  659. if (i == EOF)
  660. goto g0;
  661. if (ip)
  662. goto again;
  663. }
  664. g2:
  665. if (i >= 040) /* zapped: && i < 0177 */
  666. goto g4;
  667. i = ifilt[i];
  668. }
  669. if (cbits(i) == IMP && !raw)
  670. goto again;
  671. if (i == 0 && !init && !raw) { /* zapped: || i == 0177 */
  672. goto again;
  673. }
  674. g4:
  675. if (ismot(i))
  676. return i;
  677. if (copyf == 0 && sfbits(i) == 0)
  678. i |= chbits;
  679. if (cbits(i) == eschar && !raw)
  680. setcbits(i, ESC);
  681. return(i);
  682. }
  683. #ifdef UNICODE
  684. Tchar get1ch(FILE *fp) /* get one "character" from input, figure out what alphabet */
  685. {
  686. wchar_t wc;
  687. char buf[100], *p;
  688. int i, n, c;
  689. for (i = 0, p = buf; i < MB_CUR_MAX; i++) {
  690. if ((c = getc(fp)) == EOF)
  691. return c;
  692. *p++ = c;
  693. if ((n = mbtowc(&wc, buf, p-buf)) >= 0)
  694. break;
  695. }
  696. if (n == 1) /* real ascii, presumably */
  697. return wc;
  698. if (n == 0)
  699. return p[-1]; /* illegal, but what else to do? */
  700. if (c == EOF)
  701. return EOF;
  702. *p = 0;
  703. return chadd(buf, MBchar, Install); /* add name even if haven't seen it */
  704. }
  705. #endif /*UNICODE*/
  706. void pushback(Tchar *b)
  707. {
  708. Tchar *ob = b;
  709. while (*b++)
  710. ;
  711. b--;
  712. while (b > ob && pbp < &pbbuf[NC-3])
  713. *pbp++ = *--b;
  714. if (pbp >= &pbbuf[NC-3]) {
  715. ERROR "pushback overflow" WARN;
  716. done(2);
  717. }
  718. }
  719. void cpushback(char *b)
  720. {
  721. char *ob = b;
  722. while (*b++)
  723. ;
  724. b--;
  725. while (b > ob && pbp < &pbbuf[NC-3])
  726. *pbp++ = *--b;
  727. if (pbp >= &pbbuf[NC-3]) {
  728. ERROR "cpushback overflow" WARN;
  729. done(2);
  730. }
  731. }
  732. int nextfile(void)
  733. {
  734. char *p;
  735. n0:
  736. if (ifile != stdin)
  737. fclose(ifile);
  738. if (ifi > 0 && !nx) {
  739. if (popf())
  740. goto n0; /* popf error */
  741. return(1); /* popf ok */
  742. }
  743. if (nx || nmfi < mflg) {
  744. p = mfiles[nmfi++];
  745. if (*p != 0)
  746. goto n1;
  747. }
  748. if (rargc-- <= 0) {
  749. if ((nfo -= mflg) && !stdi) {
  750. done(0);
  751. }
  752. nfo++;
  753. numtabp[CD].val = stdi = mflg = 0;
  754. ifile = stdin;
  755. strcpy(cfname[ifi], "stdin");
  756. return(0);
  757. }
  758. p = (argp++)[0];
  759. if (rargc >= 0)
  760. cfname[ifi][0] = 0;
  761. n1:
  762. numtabp[CD].val = 0;
  763. if (p[0] == '-' && p[1] == 0) {
  764. ifile = stdin;
  765. strcpy(cfname[ifi], "stdin");
  766. } else if ((ifile = fopen(p, "r")) == NULL) {
  767. ERROR "cannot open file %s", p WARN;
  768. nfo -= mflg;
  769. done(02);
  770. } else
  771. strcpy(cfname[ifi],p);
  772. nfo++;
  773. return(0);
  774. }
  775. popf(void)
  776. {
  777. --ifi;
  778. if (ifi < 0) {
  779. ERROR "popf went negative" WARN;
  780. return 1;
  781. }
  782. numtabp[CD].val = cfline[ifi]; /* restore line counter */
  783. ip = ipl[ifi]; /* input pointer */
  784. ifile = ifl[ifi]; /* input FILE * */
  785. return(0);
  786. }
  787. void flushi(void)
  788. {
  789. if (nflush)
  790. return;
  791. ch = 0;
  792. copyf++;
  793. while (!nlflg) {
  794. if (donef && frame == stk)
  795. break;
  796. getch();
  797. }
  798. copyf--;
  799. }
  800. /*
  801. * return 16-bit, ascii/alphabetic character, ignore chars with more bits,
  802. * (internal names), spaces and special cookies (below 040).
  803. * Leave STX ETX ENQ ACK and BELL in to maintain compatibility with v7 troff.
  804. */
  805. getach(void)
  806. {
  807. Tchar i;
  808. int j;
  809. lgf++;
  810. j = cbits(i = getch());
  811. if (ismot(i)
  812. || j > SHORTMASK
  813. || (j <= 040 && j != 002 /*STX*/
  814. && j != 003 /*ETX*/
  815. && j != 005 /*ENQ*/
  816. && j != 006 /*ACK*/
  817. && j != 007)) { /*BELL*/
  818. ch = i;
  819. j = 0;
  820. }
  821. lgf--;
  822. return j;
  823. }
  824. void casenx(void)
  825. {
  826. lgf++;
  827. skip();
  828. getname();
  829. nx++;
  830. if (nmfi > 0)
  831. nmfi--;
  832. strcpy(mfiles[nmfi], nextf);
  833. nextfile();
  834. nlflg++;
  835. ip = 0;
  836. pendt = 0;
  837. frame = stk;
  838. nxf = frame + 1;
  839. }
  840. getname(void)
  841. {
  842. int j, k;
  843. Tchar i;
  844. lgf++;
  845. for (k = 0; k < NS - 1; k++) {
  846. j = getach();
  847. if (!j)
  848. break;
  849. nextf[k] = j;
  850. }
  851. nextf[k] = 0;
  852. lgf--;
  853. return(nextf[0]);
  854. }
  855. void caseso(void)
  856. {
  857. FILE *fp;
  858. char *p, *q;
  859. lgf++;
  860. nextf[0] = 0;
  861. if (skip() || !getname() || (fp = fopen(nextf, "r")) == NULL || ifi >= NSO) {
  862. ERROR "can't open file %s", nextf WARN;
  863. done(02);
  864. }
  865. strcpy(cfname[ifi+1], nextf);
  866. cfline[ifi] = numtabp[CD].val; /*hold line counter*/
  867. numtabp[CD].val = 0;
  868. flushi();
  869. ifl[ifi] = ifile;
  870. ifile = fp;
  871. ipl[ifi] = ip;
  872. ip = 0;
  873. nx++;
  874. nflush++;
  875. ifi++;
  876. }
  877. void caself(void) /* set line number and file */
  878. {
  879. int n;
  880. if (skip())
  881. return;
  882. n = atoi0();
  883. if (!nonumb)
  884. cfline[ifi] = numtabp[CD].val = n - 1;
  885. if (!skip())
  886. if (getname()) { /* eats '\n' ? */
  887. strcpy(cfname[ifi], nextf);
  888. if (!nonumb)
  889. numtabp[CD].val--;
  890. }
  891. }
  892. void cpout(FILE *fin, char *token)
  893. {
  894. int n;
  895. char buf[1024];
  896. if (token) { /* BUG: There should be no NULL bytes in input */
  897. char *newl = buf;
  898. while ((fgets(buf, sizeof buf, fin)) != NULL) {
  899. if (newl) {
  900. numtabp[CD].val++; /* line number */
  901. if (strcmp(token, buf) == 0)
  902. return;
  903. }
  904. newl = strchr(buf, '\n');
  905. fputs(buf, ptid);
  906. }
  907. } else {
  908. while ((n = fread(buf, sizeof *buf, sizeof buf, fin)) > 0)
  909. fwrite(buf, n, 1, ptid);
  910. fclose(fin);
  911. }
  912. }
  913. void casecf(void)
  914. { /* copy file without change */
  915. FILE *fd;
  916. char *eof, *p;
  917. extern int hpos, esc, po;
  918. /* this may not make much sense in nroff... */
  919. lgf++;
  920. nextf[0] = 0;
  921. if (!skip() && getname()) {
  922. if (strncmp("<<", nextf, 2) != 0) {
  923. if ((fd = fopen(nextf, "r")) == NULL) {
  924. ERROR "can't open file %s", nextf WARN;
  925. done(02);
  926. }
  927. eof = (char *) NULL;
  928. } else { /* current file */
  929. if (pbp > lastpbp || ip) {
  930. ERROR "casecf: not reading from file" WARN;
  931. done(02);
  932. }
  933. eof = &nextf[2];
  934. if (!*eof) {
  935. ERROR "casecf: missing end of input token" WARN;
  936. done(02);
  937. }
  938. p = eof;
  939. while(*++p)
  940. ;
  941. *p++ = '\n';
  942. *p = 0;
  943. fd = ifile;
  944. }
  945. } else {
  946. ERROR "casecf: no argument" WARN;
  947. lgf--;
  948. return;
  949. }
  950. lgf--;
  951. /* make it into a clean state, be sure that everything is out */
  952. tbreak();
  953. hpos = po;
  954. esc = 0;
  955. ptesc(); /* to left margin */
  956. esc = un;
  957. ptesc();
  958. ptlead();
  959. ptps();
  960. ptfont();
  961. flusho();
  962. cpout(fd, eof);
  963. ptps();
  964. ptfont();
  965. }
  966. void getline(char *s, int n) /* get rest of input line into s */
  967. {
  968. int i;
  969. lgf++;
  970. copyf++;
  971. skip();
  972. for (i = 0; i < n-1; i++)
  973. if ((s[i] = cbits(getch())) == '\n' || s[i] == RIGHT)
  974. break;
  975. s[i] = 0;
  976. copyf--;
  977. lgf--;
  978. }
  979. void casesy(void) /* call system */
  980. {
  981. char sybuf[NTM];
  982. getline(sybuf, NTM);
  983. system(sybuf);
  984. }
  985. void getpn(char *a)
  986. {
  987. int n, neg;
  988. if (*a == 0)
  989. return;
  990. neg = 0;
  991. for ( ; *a; a++)
  992. switch (*a) {
  993. case '+':
  994. case ',':
  995. continue;
  996. case '-':
  997. neg = 1;
  998. continue;
  999. default:
  1000. n = 0;
  1001. if (isdigit(*a)) {
  1002. do
  1003. n = 10 * n + *a++ - '0';
  1004. while (isdigit(*a));
  1005. a--;
  1006. } else
  1007. n = 9999;
  1008. *pnp++ = neg ? -n : n;
  1009. neg = 0;
  1010. if (pnp >= &pnlist[NPN-2]) {
  1011. ERROR "too many page numbers" WARN;
  1012. done3(-3);
  1013. }
  1014. }
  1015. if (neg)
  1016. *pnp++ = -9999;
  1017. *pnp = -INT_MAX;
  1018. print = 0;
  1019. pnp = pnlist;
  1020. if (*pnp != -INT_MAX)
  1021. chkpn();
  1022. }
  1023. void setrpt(void)
  1024. {
  1025. Tchar i, j;
  1026. copyf++;
  1027. raw++;
  1028. i = getch0();
  1029. copyf--;
  1030. raw--;
  1031. if ((long) i < 0 || cbits(j = getch0()) == RPT)
  1032. return;
  1033. while (i > 0 && pbp < &pbbuf[NC-3]) {
  1034. i--;
  1035. *pbp++ = j;
  1036. }
  1037. }