|
|
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.