Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include "a.h"
 
/*
 * Section 1 - General Explanation.
 */

/* 1.3 - Numerical parameter input.  */
char *units = "icPmnpuvx";
int
scale2units(char c)
{
        int x;
        
        switch(c){
        case 'i':       /* inch */
                return UPI;
        case 'c':       /* centimeter */
                return 0.3937008 * UPI;
        case 'P':       /* pica = 1/6 inch */
                return UPI / 6;
        case 'm':       /* em = S points */
                return UPI / 72.0 * getnr(L(".s"));
        case 'n':       /* en = em/2 */
                return UPI / 72.0 * getnr(L(".s")) / 2;
        case 'p':       /* point = 1/72 inch */
                return UPI / 72;
        case 'u':       /* basic unit */
                return 1;
        case 'v':       /* vertical line space V */
                x = getnr(L(".v"));
                if(x == 0)
                        x = 12 * UPI / 72;
                return x;
        case 'x':       /* pixel (htmlroff addition) */
                return UPX;
        default:
                return 1;
        }
}

/* 1.4 - Numerical expressions. */
int eval0(Rune**, int, int);
int
eval(Rune *s)
{
        return eval0(&s, 1, 1);
}
long
runestrtol(Rune *a, Rune **p)
{
        long n;
        
        n = 0;
        while('0' <= *a && *a <= '9'){
                n = n*10 + *a-'0';
                a++;
        }
        *p = a;
        return n;
}

int
evalscale(Rune *s, int c)
{
        return eval0(&s, scale2units(c), 1);
}

int
eval0(Rune **pline, int scale, int recur)
{
        Rune *p;
        int neg;
        double f, p10;
        int x, y;

        neg = 0;
        p = *pline;
        while(*p == '-'){
                neg = 1 - neg;
                p++;
        }
        if(*p == '('){
                p++;
                x = eval0(&p, scale, 1);
                if (*p != ')'){
                        *pline = p;
                        return x;
                }
                p++;
        }else{
                f = runestrtol(p, &p);
                if(*p == '.'){
                        p10 = 1.0;
                        p++;
                        while('0' <= *p && *p <= '9'){
                                p10 /= 10;
                                f += p10*(*p++ - '0');
                        }
                }
                if(*p && strchr(units, *p)){
                        if(scale)
                                f *= scale2units(*p);
                        p++;
                }else if(scale)
                        f *= scale;
                x = f;
        }
        if(neg)
                x = -x;
        if(!recur){
                *pline = p;
                return x;
        }
        
        while(*p){
                switch(*p++) {
                case '+':
                        x += eval0(&p, scale, 0);
                        continue;
                case '-':
                        x -= eval0(&p, scale, 0);
                        continue;
                case '*':
                        x *= eval0(&p, scale, 0);
                        continue;
                case '/':
                        y = eval0(&p, scale, 0);
                        if (y == 0) {
                                fprint(2, "%L: divide by zero %S\n", p);
                                y = 1;
                        }
                        x /= y;
                        continue;
                case '%':
                        y = eval0(&p, scale, 0);
                        if (!y) {
                                fprint(2, "%L: modulo by zero %S\n", p);
                                y = 1;
                        }
                        x %= y;
                        continue;
                case '<':
                        if (*p == '=') {
                                p++;
                                x = x <= eval0(&p, scale, 0);
                                continue;
                        }
                        x = x < eval0(&p, scale, 0);
                        continue;
                case '>':
                        if (*p == '=') {
                                p++;
                                x = x >= eval0(&p, scale, 0);
                                continue;
                        }
                        x = x > eval0(&p, scale, 0);
                        continue;
                case '=':
                        if (*p == '=')
                                p++;
                        x = x == eval0(&p, scale, 0);
                        continue;
                case '&':
                        x &= eval0(&p, scale, 0);
                        continue;
                case ':':
                        x |= eval0(&p, scale, 0);
                        continue;
                }
        }
        *pline = p;
        return x;
}

void
t1init(void)
{
        Tm tm;
        
        tm = *localtime(time(0));
        nr(L("dw"), tm.wday+1);
        nr(L("dy"), tm.mday);
        nr(L("mo"), tm.mon);
        nr(L("yr"), tm.year%100);
}