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