| /* |
| * n2.c |
| * |
| * output, cleanup |
| */ |
| |
| #define _BSD_SOURCE 1 /* popen */ |
| #define _DEFAULT_SOURCE 1 |
| #include "tdef.h" |
| #include "fns.h" |
| #include "ext.h" |
| #include <setjmp.h> |
| |
| #ifdef STRICT |
| /* not in ANSI or POSIX */ |
| FILE* popen(char*, char*); |
| #endif |
| |
| |
| extern jmp_buf sjbuf; |
| int toolate; |
| int error; |
| |
| char obuf[2*BUFSIZ]; |
| char *obufp = obuf; |
| |
| /* pipe command structure; allows redicously long commends for .pi */ |
| struct Pipe { |
| char *buf; |
| int tick; |
| int cnt; |
| } Pipe; |
| |
| |
| int xon = 0; /* records if in middle of \X */ |
| |
| int pchar(Tchar i) |
| { |
| int j; |
| static int hx = 0; /* records if have seen HX */ |
| |
| if (hx) { |
| hx = 0; |
| j = absmot(i); |
| if (isnmot(i)) { |
| if (j > dip->blss) |
| dip->blss = j; |
| } else { |
| if (j > dip->alss) |
| dip->alss = j; |
| ralss = dip->alss; |
| } |
| return 0; |
| } |
| if (ismot(i)) { |
| pchar1(i); |
| return 0; |
| } |
| switch (j = cbits(i)) { |
| case 0: |
| case IMP: |
| case RIGHT: |
| case LEFT: |
| return 0; |
| case HX: |
| hx = 1; |
| return 0; |
| case XON: |
| xon++; |
| break; |
| case XOFF: |
| xon--; |
| break; |
| case PRESC: |
| if (!xon && !tflg && dip == &d[0]) |
| j = eschar; /* fall through */ |
| default: |
| setcbits(i, trtab[j]); |
| } |
| if (NROFF & xon) /* rob fix for man2html */ |
| return 0; |
| pchar1(i); |
| return 0; |
| } |
| |
| |
| void pchar1(Tchar i) |
| { |
| int j; |
| |
| j = cbits(i); |
| if (dip != &d[0]) { |
| wbf(i); |
| dip->op = offset; |
| return; |
| } |
| if (!tflg && !print) { |
| if (j == '\n') |
| dip->alss = dip->blss = 0; |
| return; |
| } |
| if (j == FILLER && !xon) |
| return; |
| if (tflg) { /* transparent mode, undiverted */ |
| if (print) /* assumes that it's ok to print */ |
| /* OUT "%c", j PUT; /* i.e., is ascii */ |
| outascii(i); |
| return; |
| } |
| if (TROFF && ascii) |
| outascii(i); |
| else |
| ptout(i); |
| } |
| |
| |
| void outweird(int k) /* like ptchname() but ascii */ |
| { |
| char *chn = chname(k); |
| |
| switch (chn[0]) { |
| case MBchar: |
| OUT "%s", chn+1 PUT; /* \n not needed? */ |
| break; |
| case Number: |
| OUT "\\N'%s'", chn+1 PUT; |
| break; |
| case Troffchar: |
| if (strlen(chn+1) == 2) |
| OUT "\\(%s", chn+1 PUT; |
| else |
| OUT "\\C'%s'", chn+1 PUT; |
| break; |
| default: |
| OUT " %s? ", chn PUT; |
| break; |
| } |
| } |
| |
| void outascii(Tchar i) /* print i in best-guess ascii */ |
| { |
| int j = cbits(i); |
| |
| /* is this ever called with NROFF set? probably doesn't work at all. */ |
| |
| if (ismot(i)) |
| oput(' '); |
| else if (j < ALPHABET && j >= ' ' || j == '\n' || j == '\t') |
| oput(j); |
| else if (j == DRAWFCN) |
| oputs("\\D"); |
| else if (j == HYPHEN) |
| oput('-'); |
| else if (j == MINUS) /* special pleading for strange encodings */ |
| oputs("\\-"); |
| else if (j == PRESC) |
| oputs("\\e"); |
| else if (j == FILLER) |
| oputs("\\&"); |
| else if (j == UNPAD) |
| oputs("\\ "); |
| else if (j == OHC) /* this will never occur; stripped out earlier */ |
| oputs("\\%"); |
| else if (j == XON) |
| oputs("\\X"); |
| else if (j == XOFF) |
| oputs(" "); |
| else if (j == LIG_FI) |
| oputs("fi"); |
| else if (j == LIG_FL) |
| oputs("fl"); |
| else if (j == LIG_FF) |
| oputs("ff"); |
| else if (j == LIG_FFI) |
| oputs("ffi"); |
| else if (j == LIG_FFL) |
| oputs("ffl"); |
| else if (j == WORDSP) { /* nothing at all */ |
| if (xon) /* except in \X */ |
| oput(' '); |
| |
| } else |
| outweird(j); |
| } |
| |
| int flusho(void) |
| { |
| if (NROFF && !toolate && t.twinit) |
| fwrite(t.twinit, strlen(t.twinit), 1, ptid); |
| |
| if (obufp > obuf) { |
| if (pipeflg && !toolate) { |
| /* fprintf(stderr, "Pipe to <%s>\n", Pipe.buf); */ |
| if (!Pipe.buf[0] || (ptid = popen(Pipe.buf, "w")) == NULL) |
| ERROR "pipe %s not created.", Pipe.buf WARN; |
| if (Pipe.buf) |
| free(Pipe.buf); |
| } |
| if (!toolate) |
| toolate++; |
| *obufp = 0; |
| fputs(obuf, ptid); |
| fflush(ptid); |
| obufp = obuf; |
| } |
| return 1; |
| } |
| |
| |
| void caseex(void) |
| { |
| done(0); |
| } |
| |
| |
| void done(int x) |
| { |
| int i; |
| |
| error |= x; |
| app = ds = lgf = 0; |
| if (i = em) { |
| donef = -1; |
| eschar = '\\'; |
| em = 0; |
| if (control(i, 0)) |
| longjmp(sjbuf, 1); |
| } |
| if (!nfo) |
| done3(0); |
| mflg = 0; |
| dip = &d[0]; |
| if (woff) /* BUG!!! This isn't set anywhere */ |
| wbf((Tchar)0); |
| if (pendw) |
| getword(1); |
| pendnf = 0; |
| if (donef == 1) |
| done1(0); |
| donef = 1; |
| ip = 0; |
| frame = stk; |
| nxf = frame + 1; |
| if (!ejf) |
| tbreak(); |
| nflush++; |
| eject((Stack *)0); |
| longjmp(sjbuf, 1); |
| } |
| |
| |
| void done1(int x) |
| { |
| error |= x; |
| if (numtabp[NL].val) { |
| trap = 0; |
| eject((Stack *)0); |
| longjmp(sjbuf, 1); |
| } |
| if (!ascii) |
| pttrailer(); |
| done2(0); |
| } |
| |
| |
| void done2(int x) |
| { |
| ptlead(); |
| if (TROFF && !ascii) |
| ptstop(); |
| flusho(); |
| done3(x); |
| } |
| |
| void done3(int x) |
| { |
| error |= x; |
| flusho(); |
| if (NROFF) |
| twdone(); |
| if (pipeflg) |
| pclose(ptid); |
| exit(error); |
| } |
| |
| |
| void edone(int x) |
| { |
| frame = stk; |
| nxf = frame + 1; |
| ip = 0; |
| done(x); |
| } |
| |
| |
| void casepi(void) |
| { |
| int j; |
| char buf[NTM]; |
| |
| if (Pipe.buf == NULL) { |
| if ((Pipe.buf = (char *)calloc(NTM, sizeof(char))) == NULL) { |
| ERROR "No buf space for pipe cmd" WARN; |
| return; |
| } |
| Pipe.tick = 1; |
| } else |
| Pipe.buf[Pipe.cnt++] = '|'; |
| |
| getline(buf, NTM); |
| j = strlen(buf); |
| if (toolate) { |
| ERROR "Cannot create pipe to %s", buf WARN; |
| return; |
| } |
| Pipe.cnt += j; |
| if (j >= NTM +1) { |
| Pipe.tick++; |
| if ((Pipe.buf = (char *)realloc(Pipe.buf, Pipe.tick * NTM * sizeof(char))) == NULL) { |
| ERROR "No more buf space for pipe cmd" WARN; |
| return; |
| } |
| } |
| strcat(Pipe.buf, buf); |
| pipeflg++; |
| } |