Subversion Repositories planix.SVN

Rev

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

#include "e.h"

#define MAXLINE 3600    /* maximum input line */

char *version = "version Oct 24, 1991";

char    in[MAXLINE+1];  /* input buffer */
int     noeqn;
char    *cmdname;

int     yyparse(void);
void    settype(char *);
int     getdata(void);
int     getline(char *);
void    inlineeq(void);
void    init(void);
void    init_tbl(void);

void
main(int argc, char *argv[])
{
        char *p, buf[20];

        cmdname = argv[0];
        if (p = getenv("TYPESETTER"))
                typesetter = p;
        while (argc > 1 && argv[1][0] == '-') {
                switch (argv[1][1]) {

                case 'd':
                        if (argv[1][2] == '\0') {
                                dbg++;
                                printf("...\teqn %s\n", version);
                        } else {
                                lefteq = argv[1][2];
                                righteq = argv[1][3];
                        }
                        break;
                case 's': szstack[0] = gsize = atoi(&argv[1][2]); break;
                case 'p': deltaps = atoi(&argv[1][2]); dps_set = 1; break;
                case 'm': minsize = atoi(&argv[1][2]); break;
                case 'f': strcpy(ftstack[0].name,&argv[1][2]); break;
                case 'e': noeqn++; break;
                case 'T': typesetter = &argv[1][2]; break;
                default:
                        fprintf(stderr, "%s: unknown option %s\n", cmdname, argv[1]);
                        break;
                }
                argc--;
                argv++;
        }
        settype(typesetter);
        sprintf(buf, "\"%s\"", typesetter);
        install(deftbl, strsave(typesetter), strsave(buf), 0);
        init_tbl();     /* install other keywords in tables */
        curfile = infile;
        pushsrc(File, curfile->fname);
        if (argc <= 1) {
                curfile->fin = stdin;
                curfile->fname = strsave("-");
                getdata();
        } else
                while (argc-- > 1) {
                        if (strcmp(*++argv, "-") == 0)
                                curfile->fin = stdin;
                        else if ((curfile->fin = fopen(*argv, "r")) == NULL)
                                ERROR "can't open file %s", *argv FATAL;
                        curfile->fname = strsave(*argv);
                        getdata();
                        if (curfile->fin != stdin)
                                fclose(curfile->fin);
                }
        exit(0);
}

void settype(char *s)   /* initialize data for particular typesetter */
                        /* the minsize could profitably come from the */
{                       /* troff description file /usr/lib/font/dev.../DESC.out */
        if (strcmp(s, "202") == 0)
                { minsize = 5; ttype = DEV202; }
        else if (strcmp(s, "aps") == 0)
                { minsize = 5; ttype = DEVAPS; }
        else if (strcmp(s, "cat") == 0)
                { minsize = 6; ttype = DEVCAT; }
        else if (strcmp(s, "post") == 0)
                { minsize = 4; ttype = DEVPOST; }
        else
                { minsize = 5; ttype = DEV202; }
}

getdata(void)
{
        int i, type, ln;
        char fname[100];
        extern int errno;

        errno = 0;
        curfile->lineno = 0;
        printf(".lf 1 %s\n", curfile->fname);
        while ((type = getline(in)) != EOF) {
                if (in[0] == '.' && in[1] == 'E' && in[2] == 'Q') {
                        for (i = 11; i < 100; i++)
                                used[i] = 0;
                        printf("%s", in);
                        if (markline) { /* turn off from last time */
                                printf(".nr MK 0\n");
                                markline = 0;
                        }
                        display = 1;
                        init();
                        yyparse();
                        if (eqnreg > 0) {
                                if (markline)
                                        printf(".nr MK %d\n", markline); /* for -ms macros */
                                printf(".if %gm>\\n(.v .ne %gm\n", eqnht, eqnht);
                                printf(".rn %d 10\n", eqnreg);
                                if (!noeqn)
                                        printf("\\&\\*(10\n");
                        }
                        printf(".EN");
                        while (putchar(input()) != '\n')
                                ;
                        printf(".lf %d\n", curfile->lineno+1);
                }
                else if (type == lefteq)
                        inlineeq();
                else if (in[0] == '.' && in[1] == 'l' && in[2] == 'f') {
                        if (sscanf(in+3, "%d %s", &ln, fname) == 2) {
                                free(curfile->fname);
                                printf(".lf %d %s\n", curfile->lineno = ln, curfile->fname = strsave(fname));
                        } else
                                printf(".lf %d\n", curfile->lineno = ln);
                } else
                        printf("%s", in);
        }
        return(0);
}

getline(char *s)
{
        register c;

        while ((c=input()) != '\n' && c != EOF && c != lefteq) {
                if (s >= in+MAXLINE) {
                        ERROR "input line too long: %.20s\n", in WARNING;
                        in[MAXLINE] = '\0';
                        break;
                }
                *s++ = c;
        }
        if (c != lefteq)
                *s++ = c;
        *s = '\0';
        return(c);
}

void inlineeq(void)
{
        int ds, n, sz1 = 0;

        n = curfile->lineno;
        if (szstack[0] != 0)
                printf(".nr %d \\n(.s\n", sz1 = salloc());
        ds = salloc();
        printf(".rm %d \n", ds);
        display = 0;
        do {
                if (*in)
                        printf(".as %d \"%s\n", ds, in);
                init();
                yyparse();
                if (eqnreg > 0) {
                        printf(".as %d \\*(%d\n", ds, eqnreg);
                        sfree(eqnreg);
                        printf(".lf %d\n", curfile->lineno+1);
                }
        } while (getline(in) == lefteq);
        if (*in)
                printf(".as %d \"%s", ds, in);
        if (sz1)
                printf("\\s\\n(%d", sz1);
        printf("\\*(%d\n", ds);
        printf(".lf %d\n", curfile->lineno+1);
        if (curfile->lineno > n+3)
                fprintf(stderr, "eqn warning: multi-line %c...%c, file %s:%d,%d\n",
                        lefteq, righteq, curfile->fname, n, curfile->lineno); 
        sfree(ds);
        if (sz1) sfree(sz1);
}

void putout(int p1)
{
        double before, after;
        extern double BeforeSub, AfterSub;

        dprintf(".\tanswer <- S%d, h=%g,b=%g\n",p1, eht[p1], ebase[p1]);
        eqnht = eht[p1];
        before = eht[p1] - ebase[p1] - BeforeSub;       /* leave room for sub or superscript */
        after = ebase[p1] - AfterSub;
        if (spaceval || before > 0.01 || after > 0.01) {
                printf(".ds %d ", p1);  /* used to be \\x'0' here:  why? */
                if (spaceval != NULL)
                        printf("\\x'0-%s'", spaceval);
                else if (before > 0.01)
                        printf("\\x'0-%gm'", before);
                printf("\\*(%d", p1);
                if (spaceval == NULL && after > 0.01)
                        printf("\\x'%gm'", after);
                putchar('\n');
        }
        if (szstack[0] != 0)
                printf(".ds %d %s\\*(%d\\s\\n(99\n", p1, DPS(gsize,gsize), p1);
        eqnreg = p1;
        if (spaceval != NULL) {
                free(spaceval);
                spaceval = NULL;
        }
}

void init(void)
{
        synerr = 0;
        ct = 0;
        ps = gsize;
        ftp = ftstack;
        ft = ftp->ft;
        nszstack = 0;
        if (szstack[0] != 0)    /* absolute gsize in effect */
                printf(".nr 99 \\n(.s\n");
}

salloc(void)
{
        int i;

        for (i = 11; i < 100; i++)
                if (used[i] == 0) {
                        used[i]++;
                        return(i);
                }
        ERROR "no eqn strings left (%d)", i FATAL;
        return(0);
}

void sfree(int n)
{
        used[n] = 0;
}

void nrwid(int n1, int p, int n2)
{
        printf(".nr %d 0\\w'%s\\*(%d'\n", n1, DPS(gsize,p), n2);        /* 0 defends against - width */
}

char *ABSPS(int dn)     /* absolute size dn in printable form \sd or \s(dd (dd >= 40) */
{
        static char buf[100], *lb = buf;
        char *p;

        if (lb > buf + sizeof(buf) - 10)
                lb = buf;
        p = lb;
        *lb++ = '\\';
        *lb++ = 's';
        if (dn >= 10) {         /* \s(dd only works in new troff */
                if (dn >= 40)
                        *lb++ = '(';
                *lb++ = dn/10 + '0';
                *lb++ = dn%10 + '0';
        } else {
                *lb++ = dn + '0';
        }
        *lb++ = '\0';   
        return p;
}

char *DPS(int f, int t) /* delta ps (t-f) in printable form \s+d or \s-d or \s+-(dd */
{
        static char buf[100], *lb = buf;
        char *p;
        int dn;

        if (lb > buf + sizeof(buf) - 10)
                lb = buf;
        p = lb;
        *lb++ = '\\';
        *lb++ = 's';
        dn = EFFPS(t) - EFFPS(f);
        if (szstack[nszstack] != 0)     /* absolute */
                dn = EFFPS(t);          /* should do proper \s(dd */
        else if (dn >= 0)
                *lb++ = '+';
        else {
                *lb++ = '-';
                dn = -dn;
        }
        if (dn >= 10) {         /* \s+(dd only works in new troff */
                *lb++ = '(';
                *lb++ = dn/10 + '0';
                *lb++ = dn%10 + '0';
        } else {
                *lb++ = dn + '0';
        }
        *lb++ = '\0';   
        return p;
}

EFFPS(int n)    /* effective value of n */
{
        if (n >= minsize)
                return n;
        else
                return minsize;
}

double EM(double m, int ps)     /* convert m to ems in gsize */
{
        m *= (double) EFFPS(ps) / gsize;
        if (m <= 0.001 && m >= -0.001)
                return 0;
        else
                return m;
}

double REL(double m, int ps)    /* convert m to ems in ps */
{
        m *= (double) gsize / EFFPS(ps);
        if (m <= 0.001 && m >= -0.001)
                return 0;
        else
                return m;
}