|
|
1.1 root 1: /*
2: * expr.c
3: * Nroff/Troff.
4: * Expression reader.
5: */
6:
7: #include <ctype.h>
8: #include "roff.h"
9:
10: /* Local variables. */
11: static int experr; /* Got an error */
12: static int expmul; /* Default unit multiplier */
13: static int expdiv; /* Default unit divisor */
14: static char *expp; /* Pointer in expression */
15:
16: /*
17: * Return the int value of an expression.
18: * Given:
19: * Name Description Used
20: * str string containing an expression
21: * mul/div default unit multiplier, divisor if no unit given
22: * num initial value if leading sign
23: * hvf horizontal/vertical flag if initial '|'
24: * def default value if no expression
25: * The expression is evaluated from left to right with no priorites
26: * except parentheses.
27: */
28: int
29: number(str, mul, div, num, hvf, def) char *str; long mul, div; int num, hvf, def;
30: {
31: register int n, c;
32:
33: expp = str;
34: expmul = mul;
35: expdiv = div;
36: experr = 0;
37: while (isascii(*expp) && isspace(*expp))
38: expp++;
39: if ((c = *expp) == '\0')
40: return def;
41: if (index("+-|", *expp))
42: ++expp;
43: n = expseq();
44: if (*expp != '\0')
45: experr++;
46: if (experr) {
47: printe("syntax error");
48: return 0;
49: }
50: switch (c) {
51: case '+':
52: n = num + n;
53: break;
54: case '-':
55: n = num - n;
56: break;
57: case '|':
58: n -= hvf ? cdivp->d_rpos : nlinsiz;
59: break;
60: }
61: return n;
62: }
63:
64: /*
65: * Like number(), but fewer args, for efficiency.
66: */
67: int
68: numb(str, mul, div) char *str; long mul, div;
69: {
70: return number(str, mul, div, 0, 0, 0);
71: }
72:
73: /*
74: * Compute an expression sequence.
75: */
76: expseq()
77: {
78: register int n1, n2, c;
79:
80: n1 = expval();
81: if (experr)
82: return 0;
83: for (;;) {
84: while ((c = *expp++)==' ' || c == '\t')
85: ;
86: switch (c) {
87: case '<':
88: if (*expp == '=') {
89: expp++;
90: c = 'l';
91: }
92: break;
93: case '>':
94: if (*expp == '=') {
95: expp++;
96: c = 'g';
97: }
98: break;
99: case '=':
100: if (*expp == '=')
101: expp++;
102: break;
103: default:
104: if ((c != 0) && index("+-/*%&:", c))
105: break;
106: --expp;
107: return n1;
108: }
109: n2 = expval();
110: if (experr)
111: return 0;
112: switch (c) {
113: case '+':
114: n1 += n2;
115: break;
116: case '-':
117: n1 -= n2;
118: break;
119: case '*':
120: n1 *= n2;
121: break;
122: case '/':
123: if (n2 == 0) {
124: printe("attempted zero divide");
125: experr++;
126: return 0;
127: }
128: n1 /= n2;
129: break;
130: case '%':
131: if (n2 == 0) {
132: printe("attempted zero modulus");
133: experr++;
134: return 0;
135: }
136: n1 %= n2;
137: break;
138: case '<':
139: n1 = n1 < n2;
140: break;
141: case '>':
142: n1 = n1 > n2;
143: break;
144: case 'l':
145: n1 = n1 <= n2;
146: break;
147: case 'g':
148: n1 = n1 >= n2;
149: break;
150: case '=':
151: n1 = n1 == n2;
152: break;
153: case '!':
154: n1 = n1 != n2;
155: break;
156: case '&':
157: n1 = n1 && n2;
158: break;
159: case ':':
160: n1 = n1 || n2;
161: break;
162: }
163: }
164: }
165:
166: /*
167: * Get an operand.
168: */
169: expval()
170: {
171: long mul, div, m, d;
172: register int n, c, s;
173:
174: while (isascii(c = *expp++) && isspace(c))
175: ;
176: if (c == '(') {
177: n = expseq();
178: if (*expp++ != ')') {
179: --expp;
180: experr++;
181: n = 0;
182: }
183: return n;
184: }
185: for (s = 1; c == '-'; c = *expp++)
186: s = -s;
187: for (m = 0; isascii(c) && isdigit(c); c = *expp++)
188: m = m * 10 + c - '0';
189: d = 1;
190: if (c == '.') {
191: while (isascii(c = *expp++) && isdigit(c)) {
192: m = m * 10 + c - '0';
193: d *= 10;
194: }
195: }
196: switch (c) {
197: case 'i':
198: mul = SMINCH;
199: div = SDINCH;
200: break;
201: case 'c':
202: mul = SMCENT;
203: div = SDCENT;
204: break;
205: case 'P':
206: mul = SMPICA;
207: div = SDPICA;
208: break;
209: case 'm':
210: mul = SMEMSP;
211: div = SDEMSP;
212: break;
213: case 'n':
214: mul = SMENSP;
215: div = SDENSP;
216: break;
217: case 'p':
218: mul = SMPOIN;
219: div = SDPOIN;
220: break;
221: case 'u':
222: mul = SMUNIT;
223: div = SDUNIT;
224: break;
225: case 'v':
226: mul = SMVLSP;
227: div = SDVLSP;
228: break;
229: default:
230: --expp;
231: mul = expmul;
232: div = expdiv;
233: }
234: while (isascii(c = *expp) && isalpha(c))
235: expp++;
236: return unit(s*m*mul, d*div);
237: }
238:
239: /*
240: * Given a long numerator and denominator, divide the numerator by
241: * the denominator and return an int.
242: */
243: int
244: unit(mul, div) long mul, div;
245: {
246: return ((div == 1) ? ((int) mul) : ((int) (mul/div)));
247: }
248:
249: /* end of expr.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.