n2.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * n2.c
  3. *
  4. * output, cleanup
  5. */
  6. #include "tdef.h"
  7. #include "fns.h"
  8. #include "ext.h"
  9. #include <setjmp.h>
  10. #ifdef STRICT
  11. /* not in ANSI or POSIX */
  12. FILE* popen(char*, char*);
  13. #endif
  14. extern jmp_buf sjbuf;
  15. int toolate;
  16. int error;
  17. char obuf[2*BUFSIZ];
  18. char *obufp = obuf;
  19. /* pipe command structure; allows redicously long commends for .pi */
  20. struct Pipe {
  21. char *buf;
  22. int tick;
  23. int cnt;
  24. } Pipe;
  25. int xon = 0; /* records if in middle of \X */
  26. int pchar(Tchar i)
  27. {
  28. int j;
  29. static int hx = 0; /* records if have seen HX */
  30. if (hx) {
  31. hx = 0;
  32. j = absmot(i);
  33. if (isnmot(i)) {
  34. if (j > dip->blss)
  35. dip->blss = j;
  36. } else {
  37. if (j > dip->alss)
  38. dip->alss = j;
  39. ralss = dip->alss;
  40. }
  41. return 0;
  42. }
  43. if (ismot(i)) {
  44. pchar1(i);
  45. return 0;
  46. }
  47. switch (j = cbits(i)) {
  48. case 0:
  49. case IMP:
  50. case RIGHT:
  51. case LEFT:
  52. return 0;
  53. case HX:
  54. hx = 1;
  55. return 0;
  56. case XON:
  57. xon++;
  58. break;
  59. case XOFF:
  60. xon--;
  61. break;
  62. case PRESC:
  63. if (!xon && !tflg && dip == &d[0])
  64. j = eschar; /* fall through */
  65. default:
  66. setcbits(i, trtab[j]);
  67. }
  68. if (NROFF & xon) /* rob fix for man2html */
  69. return 0;
  70. pchar1(i);
  71. return 0;
  72. }
  73. void pchar1(Tchar i)
  74. {
  75. int j;
  76. j = cbits(i);
  77. if (dip != &d[0]) {
  78. wbf(i);
  79. dip->op = offset;
  80. return;
  81. }
  82. if (!tflg && !print) {
  83. if (j == '\n')
  84. dip->alss = dip->blss = 0;
  85. return;
  86. }
  87. if (j == FILLER && !xon)
  88. return;
  89. if (tflg) { /* transparent mode, undiverted */
  90. if (print) /* assumes that it's ok to print */
  91. /* OUT "%c", j PUT; /* i.e., is ascii */
  92. outascii(i);
  93. return;
  94. }
  95. if (TROFF && ascii)
  96. outascii(i);
  97. else
  98. ptout(i);
  99. }
  100. void outweird(int k) /* like ptchname() but ascii */
  101. {
  102. char *chn = chname(k);
  103. switch (chn[0]) {
  104. case MBchar:
  105. OUT "%s", chn+1 PUT; /* \n not needed? */
  106. break;
  107. case Number:
  108. OUT "\\N'%s'", chn+1 PUT;
  109. break;
  110. case Troffchar:
  111. if (strlen(chn+1) == 2)
  112. OUT "\\(%s", chn+1 PUT;
  113. else
  114. OUT "\\C'%s'", chn+1 PUT;
  115. break;
  116. default:
  117. OUT " %s? ", chn PUT;
  118. break;
  119. }
  120. }
  121. void outascii(Tchar i) /* print i in best-guess ascii */
  122. {
  123. char *p;
  124. int j = cbits(i);
  125. /* is this ever called with NROFF set? probably doesn't work at all. */
  126. if (ismot(i))
  127. oput(' ');
  128. else if (j < ALPHABET && j >= ' ' || j == '\n' || j == '\t')
  129. oput(j);
  130. else if (j == DRAWFCN)
  131. oputs("\\D");
  132. else if (j == HYPHEN)
  133. oput('-');
  134. else if (j == MINUS) /* special pleading for strange encodings */
  135. oputs("\\-");
  136. else if (j == PRESC)
  137. oputs("\\e");
  138. else if (j == FILLER)
  139. oputs("\\&");
  140. else if (j == UNPAD)
  141. oputs("\\ ");
  142. else if (j == OHC) /* this will never occur; stripped out earlier */
  143. oputs("\\%");
  144. else if (j == XON)
  145. oputs("\\X");
  146. else if (j == XOFF)
  147. oputs(" ");
  148. else if (j == LIG_FI)
  149. oputs("fi");
  150. else if (j == LIG_FL)
  151. oputs("fl");
  152. else if (j == LIG_FF)
  153. oputs("ff");
  154. else if (j == LIG_FFI)
  155. oputs("ffi");
  156. else if (j == LIG_FFL)
  157. oputs("ffl");
  158. else if (j == WORDSP) { /* nothing at all */
  159. if (xon) /* except in \X */
  160. oput(' ');
  161. } else
  162. outweird(j);
  163. }
  164. int flusho(void)
  165. {
  166. if (NROFF && !toolate && t.twinit)
  167. fwrite(t.twinit, strlen(t.twinit), 1, ptid);
  168. if (obufp > obuf) {
  169. if (pipeflg && !toolate) {
  170. /* fprintf(stderr, "Pipe to <%s>\n", Pipe.buf); */
  171. if (!Pipe.buf[0] || (ptid = popen(Pipe.buf, "w")) == NULL)
  172. ERROR "pipe %s not created.", Pipe.buf WARN;
  173. if (Pipe.buf)
  174. free(Pipe.buf);
  175. }
  176. if (!toolate)
  177. toolate++;
  178. *obufp = 0;
  179. fputs(obuf, ptid);
  180. fflush(ptid);
  181. obufp = obuf;
  182. }
  183. return 1;
  184. }
  185. void caseex(void)
  186. {
  187. done(0);
  188. }
  189. void done(int x)
  190. {
  191. int i;
  192. error |= x;
  193. app = ds = lgf = 0;
  194. if (i = em) {
  195. donef = -1;
  196. eschar = '\\';
  197. em = 0;
  198. if (control(i, 0))
  199. longjmp(sjbuf, 1);
  200. }
  201. if (!nfo)
  202. done3(0);
  203. mflg = 0;
  204. dip = &d[0];
  205. if (woff) /* BUG!!! This isn't set anywhere */
  206. wbf((Tchar)0);
  207. if (pendw)
  208. getword(1);
  209. pendnf = 0;
  210. if (donef == 1)
  211. done1(0);
  212. donef = 1;
  213. ip = 0;
  214. frame = stk;
  215. nxf = frame + 1;
  216. if (!ejf)
  217. tbreak();
  218. nflush++;
  219. eject((Stack *)0);
  220. longjmp(sjbuf, 1);
  221. }
  222. void done1(int x)
  223. {
  224. error |= x;
  225. if (numtabp[NL].val) {
  226. trap = 0;
  227. eject((Stack *)0);
  228. longjmp(sjbuf, 1);
  229. }
  230. if (!ascii)
  231. pttrailer();
  232. done2(0);
  233. }
  234. void done2(int x)
  235. {
  236. ptlead();
  237. if (TROFF && !ascii)
  238. ptstop();
  239. flusho();
  240. done3(x);
  241. }
  242. void done3(int x)
  243. {
  244. error |= x;
  245. flusho();
  246. if (NROFF)
  247. twdone();
  248. if (pipeflg)
  249. pclose(ptid);
  250. exit(error);
  251. }
  252. void edone(int x)
  253. {
  254. frame = stk;
  255. nxf = frame + 1;
  256. ip = 0;
  257. done(x);
  258. }
  259. void casepi(void)
  260. {
  261. int j;
  262. char buf[NTM];
  263. if (Pipe.buf == NULL) {
  264. if ((Pipe.buf = (char *)calloc(NTM, sizeof(char))) == NULL) {
  265. ERROR "No buf space for pipe cmd" WARN;
  266. return;
  267. }
  268. Pipe.tick = 1;
  269. } else
  270. Pipe.buf[Pipe.cnt++] = '|';
  271. getline(buf, NTM);
  272. j = strlen(buf);
  273. if (toolate) {
  274. ERROR "Cannot create pipe to %s", buf WARN;
  275. return;
  276. }
  277. Pipe.cnt += j;
  278. if (j >= NTM +1) {
  279. Pipe.tick++;
  280. if ((Pipe.buf = (char *)realloc(Pipe.buf, Pipe.tick * NTM * sizeof(char))) == NULL) {
  281. ERROR "No more buf space for pipe cmd" WARN;
  282. return;
  283. }
  284. }
  285. strcat(Pipe.buf, buf);
  286. pipeflg++;
  287. }