|
|
1.1 root 1: /*
2: * Korn expression evaluation
3: */
4:
5: static char *RCSid = "$Header: expr.c,v 3.1 88/11/03 09:15:55 egisin Exp $";
6:
7: #include <stddef.h>
8: #include <errno.h>
9: #include <setjmp.h>
10: #include "sh.h"
11: #include "table.h"
12:
13: #define ef else if /* fashion statement */
14:
15: #define VAR 0x01
16: #define LIT 0x02
17: #define LEQ 0x03
18: #define LNE 0x04
19: #define LLE 0x05
20: #define LGE 0x06
21:
22: static void token(); /* read next token */
23: static Const char *expression; /* expression being evaluated */
24: static Const char *tokp; /* lexical position */
25: static int tok; /* token from token() */
26: static struct tbl *val; /* value from token() */
27:
28: static struct tbl *tempvar(), *intvar();
29: static struct tbl *asn(), *e6(), *e5(), *e3(), *e2(), *e0();
30:
31: /*
32: * parse and evalute expression
33: */
34: void
35: evalerr(err)
36: char *err;
37: {
38: errorf("%s: %s\n", expression, err);
39: }
40:
41: long
42: evaluate(expr)
43: Const char *expr;
44: {
45: struct tbl *v;
46:
47: expression = tokp = expr;
48: token();
49: v = intvar(asn());
50: if (!(tok == 0))
51: evalerr("bad expression");
52: return v->val.i;
53: }
54:
55: static struct tbl *
56: asn()
57: {
58: register struct tbl *vl, *vr;
59:
60: vr = vl = e6();
61: if ((tok == '=')) {
62: Area * olastarea = lastarea;
63: token();
64: if ((vl->flag&RDONLY)) /* assign to rvalue */
65: evalerr("bad assignment");
66: vr = intvar(asn());
67: lastarea = olastarea;
68: setint(vl, vr->val.i);
69: if ((vl->flag&INTEGER) && vl->type == 0) /* default base? */
70: vl->type = vr->type;
71: }
72: return vr;
73: }
74:
75: static struct tbl *
76: e6()
77: {
78: register struct tbl *vl, *vr;
79:
80: vl = e5();
81: while ((tok == LEQ) || (tok == LNE)) {
82: int op = tok;
83: token();
84: vl = intvar(vl);
85: vr = intvar(e5());
86: vl->val.i = vl->val.i == vr->val.i;
87: if (op == LNE)
88: vl->val.i = ! vl->val.i;
89: }
90: return vl;
91: }
92:
93: static struct tbl *
94: e5()
95: {
96: register struct tbl *vl, *vr;
97:
98: vl = e3();
99: while ((tok == LLE) || (tok == '<') || (tok == '>') || (tok == LGE)) {
100: int op = tok;
101: token();
102: vl = intvar(vl);
103: vr = intvar(e3());
104: if (op == LLE)
105: vl->val.i = vl->val.i <= vr->val.i;
106: ef (op == '<')
107: vl->val.i = vl->val.i < vr->val.i;
108: ef (op == LGE)
109: vl->val.i = vl->val.i >= vr->val.i;
110: ef (op == '>')
111: vl->val.i = vl->val.i > vr->val.i;
112: }
113: return vl;
114: }
115:
116: static struct tbl *
117: e3()
118: {
119: register struct tbl *vl, *vr;
120:
121: vl = e2();
122: while ((tok == '+') || (tok == '-')) {
123: int op = tok;
124: token();
125: vl = intvar(vl);
126: vr = intvar(e2());
127: if (op == '+')
128: vl->val.i += vr->val.i;
129: ef (op == '-')
130: vl->val.i -= vr->val.i;
131: }
132: return vl;
133: }
134:
135: static struct tbl *
136: e2()
137: {
138: register struct tbl *vl, *vr;
139:
140: vl = e0();
141: while ((tok == '*') || (tok == '/') || (tok == '%')) {
142: int op = tok;
143: token();
144: vl = intvar(vl);
145: vr = intvar(e0());
146: if (op != '*' && vr->val.i == 0)
147: evalerr("zero divisor");
148: if (op == '*')
149: vl->val.i *= vr->val.i;
150: ef (op == '/')
151: vl->val.i /= vr->val.i;
152: ef (op == '%')
153: vl->val.i %= vr->val.i;
154: }
155: return vl;
156: }
157:
158: static struct tbl *
159: e0()
160: {
161: register struct tbl *v;
162:
163: if ((tok == '!') || (tok == '-')) {
164: int op = tok;
165: token();
166: v = intvar(e0());
167: if (op == '!')
168: v->val.i = !v->val.i;
169: ef (op == '-')
170: v->val.i = -v->val.i;
171: } else
172: if ((tok == '(')) {
173: token();
174: v = asn();
175: if (!(tok == ')'))
176: evalerr("missing )");
177: token();
178: } else
179: if ((tok == VAR) || (tok == LIT)) {
180: v = val;
181: token();
182: } else
183: evalerr("bad expression");
184: return v;
185: }
186:
187: static void
188: token()
189: {
190: register char *cp = (char *) tokp;
191: register int c, c2;
192:
193: /* skip white space */
194: do c = *cp++; while (c != '\0' && (c == ' ' || c == '\t'));
195: tokp = cp-1;
196:
197: if (letter(c)) {
198: for (; letnum(c); c = *cp++)
199: ;
200: c = *--cp;
201: *cp = 0;
202: val = global(tokp);
203: *cp = c;
204: tok = VAR;
205: } else
206: if (digit(c)) {
207: for (; letnum(c) || c == '#'; c = *cp++)
208: ;
209: c = *--cp;
210: *cp = 0;
211: val = tempvar();
212: setstr(val, tokp);
213: val->flag |= RDONLY;
214: *cp = c;
215: tok = LIT;
216: } else {
217: c2 = *cp++;
218: if (c == '=' && c2 == '=')
219: c = LEQ;
220: ef (c == '!' && c2 == '=')
221: c = LNE;
222: ef (c == '<' && c2 == '=')
223: c = LLE;
224: ef (c == '>' && c2 == '=')
225: c = LGE;
226: else
227: cp--;
228: tok = c;
229: }
230: tokp = cp;
231: }
232:
233: static struct tbl *
234: tempvar()
235: {
236: register struct tbl *vp;
237:
238: vp = alloc(sizeof(struct tbl), ATEMP);
239: lastarea = ATEMP;
240: vp->flag = ISSET|INTEGER;
241: vp->type = 0;
242: vp->name[0] = '\0';
243: return vp;
244: }
245:
246: /* cast (string) variable to temporary integer variable */
247: static struct tbl *
248: intvar(vp)
249: register struct tbl *vp;
250: {
251: register struct tbl *vq;
252:
253: vq = tempvar();
254: vq->type = 10;
255: return strint(vq, vp);
256: }
257:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.