Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * n2.c
 *
 * output, cleanup
 */

#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++;
}