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