xref: /plan9/sys/src/cmd/htmlroff/t1.c (revision 426d2b71458df9b491ba6c167f699b3f1f7b0428)
1*426d2b71SDavid du Colombier #include "a.h"
2*426d2b71SDavid du Colombier 
3*426d2b71SDavid du Colombier /*
4*426d2b71SDavid du Colombier  * Section 1 - General Explanation.
5*426d2b71SDavid du Colombier  */
6*426d2b71SDavid du Colombier 
7*426d2b71SDavid du Colombier /* 1.3 - Numerical parameter input.  */
8*426d2b71SDavid du Colombier char *units = "icPmnpuvx";
9*426d2b71SDavid du Colombier int
scale2units(char c)10*426d2b71SDavid du Colombier scale2units(char c)
11*426d2b71SDavid du Colombier {
12*426d2b71SDavid du Colombier 	int x;
13*426d2b71SDavid du Colombier 
14*426d2b71SDavid du Colombier 	switch(c){
15*426d2b71SDavid du Colombier 	case 'i':	/* inch */
16*426d2b71SDavid du Colombier 		return UPI;
17*426d2b71SDavid du Colombier 	case 'c':	/* centimeter */
18*426d2b71SDavid du Colombier 		return 0.3937008 * UPI;
19*426d2b71SDavid du Colombier 	case 'P':	/* pica = 1/6 inch */
20*426d2b71SDavid du Colombier 		return UPI / 6;
21*426d2b71SDavid du Colombier 	case 'm':	/* em = S points */
22*426d2b71SDavid du Colombier 		return UPI / 72.0 * getnr(L(".s"));
23*426d2b71SDavid du Colombier 	case 'n':	/* en = em/2 */
24*426d2b71SDavid du Colombier 		return UPI / 72.0 * getnr(L(".s")) / 2;
25*426d2b71SDavid du Colombier 	case 'p':	/* point = 1/72 inch */
26*426d2b71SDavid du Colombier 		return UPI / 72;
27*426d2b71SDavid du Colombier 	case 'u':	/* basic unit */
28*426d2b71SDavid du Colombier 		return 1;
29*426d2b71SDavid du Colombier 	case 'v':	/* vertical line space V */
30*426d2b71SDavid du Colombier 		x = getnr(L(".v"));
31*426d2b71SDavid du Colombier 		if(x == 0)
32*426d2b71SDavid du Colombier 			x = 12 * UPI / 72;
33*426d2b71SDavid du Colombier 		return x;
34*426d2b71SDavid du Colombier 	case 'x':	/* pixel (htmlroff addition) */
35*426d2b71SDavid du Colombier 		return UPX;
36*426d2b71SDavid du Colombier 	default:
37*426d2b71SDavid du Colombier 		return 1;
38*426d2b71SDavid du Colombier 	}
39*426d2b71SDavid du Colombier }
40*426d2b71SDavid du Colombier 
41*426d2b71SDavid du Colombier /* 1.4 - Numerical expressions. */
42*426d2b71SDavid du Colombier int eval0(Rune**, int, int);
43*426d2b71SDavid du Colombier int
eval(Rune * s)44*426d2b71SDavid du Colombier eval(Rune *s)
45*426d2b71SDavid du Colombier {
46*426d2b71SDavid du Colombier 	return eval0(&s, 1, 1);
47*426d2b71SDavid du Colombier }
48*426d2b71SDavid du Colombier long
runestrtol(Rune * a,Rune ** p)49*426d2b71SDavid du Colombier runestrtol(Rune *a, Rune **p)
50*426d2b71SDavid du Colombier {
51*426d2b71SDavid du Colombier 	long n;
52*426d2b71SDavid du Colombier 
53*426d2b71SDavid du Colombier 	n = 0;
54*426d2b71SDavid du Colombier 	while('0' <= *a && *a <= '9'){
55*426d2b71SDavid du Colombier 		n = n*10 + *a-'0';
56*426d2b71SDavid du Colombier 		a++;
57*426d2b71SDavid du Colombier 	}
58*426d2b71SDavid du Colombier 	*p = a;
59*426d2b71SDavid du Colombier 	return n;
60*426d2b71SDavid du Colombier }
61*426d2b71SDavid du Colombier 
62*426d2b71SDavid du Colombier int
evalscale(Rune * s,int c)63*426d2b71SDavid du Colombier evalscale(Rune *s, int c)
64*426d2b71SDavid du Colombier {
65*426d2b71SDavid du Colombier 	return eval0(&s, scale2units(c), 1);
66*426d2b71SDavid du Colombier }
67*426d2b71SDavid du Colombier 
68*426d2b71SDavid du Colombier int
eval0(Rune ** pline,int scale,int recur)69*426d2b71SDavid du Colombier eval0(Rune **pline, int scale, int recur)
70*426d2b71SDavid du Colombier {
71*426d2b71SDavid du Colombier 	Rune *p;
72*426d2b71SDavid du Colombier 	int neg;
73*426d2b71SDavid du Colombier 	double f, p10;
74*426d2b71SDavid du Colombier 	int x, y;
75*426d2b71SDavid du Colombier 
76*426d2b71SDavid du Colombier 	neg = 0;
77*426d2b71SDavid du Colombier 	p = *pline;
78*426d2b71SDavid du Colombier 	while(*p == '-'){
79*426d2b71SDavid du Colombier 		neg = 1 - neg;
80*426d2b71SDavid du Colombier 		p++;
81*426d2b71SDavid du Colombier 	}
82*426d2b71SDavid du Colombier 	if(*p == '('){
83*426d2b71SDavid du Colombier 		p++;
84*426d2b71SDavid du Colombier 		x = eval0(&p, scale, 1);
85*426d2b71SDavid du Colombier 		if (*p != ')'){
86*426d2b71SDavid du Colombier 			*pline = p;
87*426d2b71SDavid du Colombier 			return x;
88*426d2b71SDavid du Colombier 		}
89*426d2b71SDavid du Colombier 		p++;
90*426d2b71SDavid du Colombier 	}else{
91*426d2b71SDavid du Colombier 		f = runestrtol(p, &p);
92*426d2b71SDavid du Colombier 		if(*p == '.'){
93*426d2b71SDavid du Colombier 			p10 = 1.0;
94*426d2b71SDavid du Colombier 			p++;
95*426d2b71SDavid du Colombier 			while('0' <= *p && *p <= '9'){
96*426d2b71SDavid du Colombier 				p10 /= 10;
97*426d2b71SDavid du Colombier 				f += p10*(*p++ - '0');
98*426d2b71SDavid du Colombier 			}
99*426d2b71SDavid du Colombier 		}
100*426d2b71SDavid du Colombier 		if(*p && strchr(units, *p)){
101*426d2b71SDavid du Colombier 			if(scale)
102*426d2b71SDavid du Colombier 				f *= scale2units(*p);
103*426d2b71SDavid du Colombier 			p++;
104*426d2b71SDavid du Colombier 		}else if(scale)
105*426d2b71SDavid du Colombier 			f *= scale;
106*426d2b71SDavid du Colombier 		x = f;
107*426d2b71SDavid du Colombier 	}
108*426d2b71SDavid du Colombier 	if(neg)
109*426d2b71SDavid du Colombier 		x = -x;
110*426d2b71SDavid du Colombier 	if(!recur){
111*426d2b71SDavid du Colombier 		*pline = p;
112*426d2b71SDavid du Colombier 		return x;
113*426d2b71SDavid du Colombier 	}
114*426d2b71SDavid du Colombier 
115*426d2b71SDavid du Colombier 	while(*p){
116*426d2b71SDavid du Colombier 		switch(*p++) {
117*426d2b71SDavid du Colombier 		case '+':
118*426d2b71SDavid du Colombier 			x += eval0(&p, scale, 0);
119*426d2b71SDavid du Colombier 			continue;
120*426d2b71SDavid du Colombier 		case '-':
121*426d2b71SDavid du Colombier 			x -= eval0(&p, scale, 0);
122*426d2b71SDavid du Colombier 			continue;
123*426d2b71SDavid du Colombier 		case '*':
124*426d2b71SDavid du Colombier 			x *= eval0(&p, scale, 0);
125*426d2b71SDavid du Colombier 			continue;
126*426d2b71SDavid du Colombier 		case '/':
127*426d2b71SDavid du Colombier 			y = eval0(&p, scale, 0);
128*426d2b71SDavid du Colombier 			if (y == 0) {
129*426d2b71SDavid du Colombier 				fprint(2, "%L: divide by zero %S\n", p);
130*426d2b71SDavid du Colombier 				y = 1;
131*426d2b71SDavid du Colombier 			}
132*426d2b71SDavid du Colombier 			x /= y;
133*426d2b71SDavid du Colombier 			continue;
134*426d2b71SDavid du Colombier 		case '%':
135*426d2b71SDavid du Colombier 			y = eval0(&p, scale, 0);
136*426d2b71SDavid du Colombier 			if (!y) {
137*426d2b71SDavid du Colombier 				fprint(2, "%L: modulo by zero %S\n", p);
138*426d2b71SDavid du Colombier 				y = 1;
139*426d2b71SDavid du Colombier 			}
140*426d2b71SDavid du Colombier 			x %= y;
141*426d2b71SDavid du Colombier 			continue;
142*426d2b71SDavid du Colombier 		case '<':
143*426d2b71SDavid du Colombier 			if (*p == '=') {
144*426d2b71SDavid du Colombier 				p++;
145*426d2b71SDavid du Colombier 				x = x <= eval0(&p, scale, 0);
146*426d2b71SDavid du Colombier 				continue;
147*426d2b71SDavid du Colombier 			}
148*426d2b71SDavid du Colombier 			x = x < eval0(&p, scale, 0);
149*426d2b71SDavid du Colombier 			continue;
150*426d2b71SDavid du Colombier 		case '>':
151*426d2b71SDavid du Colombier 			if (*p == '=') {
152*426d2b71SDavid du Colombier 				p++;
153*426d2b71SDavid du Colombier 				x = x >= eval0(&p, scale, 0);
154*426d2b71SDavid du Colombier 				continue;
155*426d2b71SDavid du Colombier 			}
156*426d2b71SDavid du Colombier 			x = x > eval0(&p, scale, 0);
157*426d2b71SDavid du Colombier 			continue;
158*426d2b71SDavid du Colombier 		case '=':
159*426d2b71SDavid du Colombier 			if (*p == '=')
160*426d2b71SDavid du Colombier 				p++;
161*426d2b71SDavid du Colombier 			x = x == eval0(&p, scale, 0);
162*426d2b71SDavid du Colombier 			continue;
163*426d2b71SDavid du Colombier 		case '&':
164*426d2b71SDavid du Colombier 			x &= eval0(&p, scale, 0);
165*426d2b71SDavid du Colombier 			continue;
166*426d2b71SDavid du Colombier 		case ':':
167*426d2b71SDavid du Colombier 			x |= eval0(&p, scale, 0);
168*426d2b71SDavid du Colombier 			continue;
169*426d2b71SDavid du Colombier 		}
170*426d2b71SDavid du Colombier 	}
171*426d2b71SDavid du Colombier 	*pline = p;
172*426d2b71SDavid du Colombier 	return x;
173*426d2b71SDavid du Colombier }
174*426d2b71SDavid du Colombier 
175*426d2b71SDavid du Colombier void
t1init(void)176*426d2b71SDavid du Colombier t1init(void)
177*426d2b71SDavid du Colombier {
178*426d2b71SDavid du Colombier 	Tm tm;
179*426d2b71SDavid du Colombier 
180*426d2b71SDavid du Colombier 	tm = *localtime(time(0));
181*426d2b71SDavid du Colombier 	nr(L("dw"), tm.wday+1);
182*426d2b71SDavid du Colombier 	nr(L("dy"), tm.mday);
183*426d2b71SDavid du Colombier 	nr(L("mo"), tm.mon);
184*426d2b71SDavid du Colombier 	nr(L("yr"), tm.year%100);
185*426d2b71SDavid du Colombier }
186*426d2b71SDavid du Colombier 
187