|
|
1.1 root 1: /*
2: * db/db5.c
3: * A debugger.
4: * Expression evaluator.
5: */
6:
7: #include "db.h"
8:
9: #define VALUE (-2) /* must be distinct from chars */
10: #define VILLEGAL (-3) /* ditto */
11: #define PRCFULL (0<<8) /* precedence wall for full expression */
12: #define PRECADD (1<<8) /* precedence of additive ops */
13: #define PRECMUL (2<<8) /* precedence of multiplicative ops */
14: #define PRIMARY (4<<8) /* precedence of primary expression */
15: #define tk_preced(op) ((op)&(~0<<8))
16: #define tk_char(op) ((op)&0377)
17:
18: /*
19: * Recursive expression reader;
20: * returns -1 for error, 0 for null expr, 1 for good expr.
21: */
22: int
23: expr(left, wall) register VAL *left; int wall;
24: {
25: VAL v;
26: register VAL *right;
27: int token, result;
28: WORD_T word;
29:
30: right = &v;
31: token = lextoken(left);
32: if (token==VALUE)
33: ;
34: else if (token==VILLEGAL)
35: return -1;
36: else switch (tk_char(token)) {
37: case '~':
38: if (expr(left, PRIMARY)<=0)
39: return -1;
40: left->v_nval = ~left->v_nval;
41: break;
42: case '-':
43: if (expr(left, PRIMARY)<=0)
44: return -1;
45: left->v_nval = -left->v_nval;
46: break;
47: case '*':
48: /* Indirection. */
49: if (expr(left, PRIMARY)<=0)
50: return -1;
51: add = left->v_nval;
52: /* Fetch what the left points to. */
53: getb(val_segn(left), (char *)&word, sizeof word);
54: left->v_nval = (long)word;
55: left->v_flag = 0;
56: break;
57: case '(':
58: if (expr(left, PRCFULL)<=0)
59: return -1;
60: if ((token = lextoken((VAL *)NULL))==')')
61: break;
62: else {
63: unlex(token);
64: printe("Missing ')'");
65: return -1;
66: }
67: default:
68: unlex(token);
69: left->v_flag = VNULL;
70: return 0;
71: }
72: for (;;) {
73: token = lextoken((VAL *)NULL);
74: if (tk_preced(token) <= wall) {
75: unlex(token);
76: return 1;
77: } else switch (tk_char(token)) {
78: case '*':
79: if ((result=expr(right, PRECMUL))<=0)
80: break;
81: left->v_nval *= right->v_nval;
82: continue;
83: case '/':
84: if ((result=expr(right, PRECMUL))<=0)
85: break;
86: left->v_nval /= right->v_nval;
87: continue;
88: case '+':
89: if ((result=expr(right, PRECADD))<=0)
90: break;
91: left->v_nval += right->v_nval;
92: continue;
93: case '-':
94: if ((result=expr(right, PRECADD))<=0)
95: break;
96: left->v_nval -= right->v_nval;
97: continue;
98: default:
99: unlex(token);
100: printe("Unimplemented operator");
101: return -1;
102: }
103: if (result==0)
104: printe("Missing operand");
105: return -1;
106: }
107: }
108:
109: /*
110: * Evaluate an expression list.
111: */
112: int
113: expr_list(vlist) VAL vlist[VALSIZE];
114: {
115: register VAL *vp;
116: register int c, n;
117:
118: vp = vlist;
119: n = VALSIZE;
120: do {
121: if (expr(vp, PRCFULL)<0)
122: return 0;
123: vp++;
124: --n;
125: } while ((c=getn()) == ',');
126: ungetn(c);
127: while (n--)
128: vp++->v_flag = VNULL;
129: return 1;
130: }
131:
132: /*
133: * Lex a token. If value, store in given val ptr.
134: */
135: int
136: lextoken(vp) VAL *vp;
137: {
138: register int c;
139:
140: for (;;) switch (c=getn()) {
141: case ' ':
142: case '\t':
143: continue;
144: case '.':
145: if (vp == (VAL *)NULL) {
146: printe("Missing operand before '.'");
147: ungetn(c);
148: return VILLEGAL;
149: }
150: vp->v_flag = VSEGN;
151: vp->v_segn = cseg;
152: vp->v_nval = dot;
153: return VALUE;
154: /*
155: * Only binary ops need be mentioned explicitly
156: * so precedences can be added.
157: */
158: case '*':
159: case '/':
160: return c|PRECMUL;
161: case '+':
162: case '-':
163: return c|PRECADD;
164: default:
165: if ('0'<=c && c<='9')
166: return readval(vp, c);
167: else if ('a'<=c && c<='z' || 'A'<=c && c<='Z' || c=='_' || c=='%')
168: return readvar(vp, c);
169: else
170: return c;
171: }
172: }
173:
174: /*
175: * Evaluate a value as an lvalue and return it.
176: * If the value is VNULL, return 'v'.
177: */
178: ADDR_T
179: lvalue(vp, v) register VAL *vp; ADDR_T v;
180: {
181: return (vp->v_flag & VNULL) ? v : (ADDR_T)vp->v_nval;
182: }
183:
184: #if 0 /* Covered by macro in db.h */
185: /*
186: * If the given value is null, return 1, else 0.
187: */
188: int
189: nvalue(vp) VAL *vp;
190: {
191: return vp->v_flag & VNULL;
192: }
193: #endif
194:
195: /*
196: * Read a number.
197: */
198: int
199: readval(vp, c) VAL *vp; register int c;
200: {
201: long l;
202: register int i, base;
203:
204: if (vp == (VAL *)NULL) {
205: printe("Missing operand before number");
206: ungetn(c);
207: return VILLEGAL;
208: }
209: base = 10;
210: if (c=='0') {
211: base = 8;
212: if ((c = getn())=='x') {
213: base = 16;
214: } else {
215: ungetn(c);
216: }
217: c = '0';
218: }
219: if (c == '#')
220: base = 16;
221: else
222: l = '0' - c;
223: for (;;) {
224: if ((10 <= (i=(c = getn())-('a'-10))
225: || 10 <= (i=c-('A'-10))
226: || 0 <= (i=c-'0') && i <= 9)
227: && i < base)
228: l = l*base - i;
229: else
230: break;
231: }
232: ungetn(c);
233: vp->v_flag = 0;
234: vp->v_nval = -l;
235: return VALUE;
236: }
237:
238: /*
239: * Read symbol and place value in given val struct.
240: */
241: int
242: readvar(vp, c) VAL *vp; int c;
243: {
244: ungetn(c);
245: if (vp == (VAL *)NULL) {
246: printe("Missing operand before symbol");
247: return VILLEGAL;
248: }
249: return (symval(vp)) ? VALUE : VILLEGAL;
250: }
251:
252: /*
253: * Evaluate a value as an rvalue and return it.
254: * If the value is null, return 'v'.
255: */
256: long
257: rvalue(vp, v) register VAL *vp; long v;
258: {
259: return (vp->v_flag&VNULL) ? v : vp->v_nval;
260: }
261:
262: /*
263: * Push token back on input stream.
264: */
265: void
266: unlex(c) int c;
267: {
268: if (c != VILLEGAL && c != VALUE)
269: ungetn(tk_char(c));
270: }
271:
272: /*
273: * Return the segment associated with a value.
274: * If there is no segment associated with it,
275: * look at the segmentation map to see if it is found.
276: * If the value is null or not found, return the current segment.
277: */
278: int
279: val_segn(vp) register VAL *vp;
280: {
281: register int s;
282:
283: if (vp->v_flag & VNULL)
284: return cseg;
285: if (vp->v_flag & VSEGN)
286: return vp->v_segn; /* in known segment */
287: else if ((s = find_seg((ADDR_T)vp->v_nval)) != SEG_NONE)
288: return s; /* in existing segment */
289: else
290: return cseg; /* take a guess... */
291: }
292:
293: /* end of db/db5.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.