n1.c 20 KB

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