|
|
1.1 ! root 1: #include "expr.pri" ! 2: #include "gram.h" ! 3: #include "symbol.h" ! 4: #include "format.pub" ! 5: #include "frame.pri" ! 6: #include "phrase.pub" ! 7: #include "symtab.pub" ! 8: #include "core.pub" ! 9: #include <CC/signal.h> /* floating point exceptions */ ! 10: SRCFILE("expr.c") ! 11: ! 12: #ifdef V9 ! 13: #define SIG_TYP SIG_ARG_TYP ! 14: #endif ! 15: ! 16: char *OpName(Op op) ! 17: { ! 18: switch(op){ ! 19: case O_DEREF: return "*"; ! 20: case O_REF: return "&"; ! 21: case O_INDEX: return "[]"; ! 22: case O_DOT: return "."; ! 23: case O_ARROW: return "->"; ! 24: case O_PLUS: return "+"; ! 25: case O_MINUS: return "-"; ! 26: case O_MULT: return "*"; ! 27: case O_DIV: return "/"; ! 28: case O_CALL: return "()"; ! 29: case O_MOD: return "%"; ! 30: case O_ASSIGN: return "="; ! 31: case O_COMMA: return ","; ! 32: case O_SIZEOF: return "sizeof"; ! 33: case O_TYPEOF: return "typeof"; ! 34: case O_QINDEX: return "[?]"; ! 35: case O_CAST: return "(cast)"; ! 36: case O_QCAST: return " ?"; ! 37: case O_QSTRUCT: return "struct ?"; ! 38: case O_QENUM: return "enum ?"; ! 39: case O_EQ: return "=="; ! 40: case O_NE: return "!="; ! 41: case O_LT: return "<"; ! 42: case O_GT: return ">"; ! 43: case O_LE: return "<="; ! 44: case O_GE: return ">="; ! 45: case O_LOGAND: return "&&"; ! 46: case O_LOGOR: return "||"; ! 47: case O_LOGNOT: return "!"; ! 48: case O_BITAND: return "&"; ! 49: case O_BITOR: return "|"; ! 50: case O_BITXOR: return "^"; ! 51: case O_1SCOMP: return "~"; ! 52: case O_FABS: return "fabs"; ! 53: case O_ENV: return "{}"; ! 54: case O_RANGE: return ".."; ! 55: case O_SPECIAL: return "special"; ! 56: case O_LSHIFT: return "<<"; ! 57: case O_RSHIFT: return ">>"; ! 58: default: return Name( "Op=%d", op ); ! 59: } ! 60: } ! 61: ! 62: int Prec( Op op ) /* for Expr::text() - not gram.y */ ! 63: { ! 64: switch(op){ ! 65: case O_ENV: return 1; ! 66: case O_CALL: ! 67: case O_INDEX: ! 68: case O_DOT: ! 69: case O_ARROW: return 2; ! 70: case O_MULT: ! 71: case O_DIV: ! 72: case O_MOD: return 3; ! 73: case O_PLUS: ! 74: case O_MINUS: return 4; ! 75: case O_LSHIFT: ! 76: case O_RSHIFT: return 5; ! 77: case O_LT: ! 78: case O_GT: ! 79: case O_LE: ! 80: case O_GE: return 6; ! 81: case O_EQ: ! 82: case O_NE: return 7; ! 83: case O_BITAND: return 8; ! 84: case O_BITXOR: return 9; ! 85: case O_BITOR: return 10; ! 86: case O_LOGAND: return 11; ! 87: case O_LOGOR: return 12; ! 88: case O_ASSIGN: return 13; ! 89: case O_COMMA: return 14; ! 90: case O_RANGE: return 15; ! 91: default: return 16; ! 92: } ! 93: } ! 94: ! 95: Expr *E_Id(char *id ) { return new Expr(E_ID,0,0,0,0,id,0,0); } ! 96: ! 97: Expr *E_Sym(Symbol *s ) { return new Expr(E_SYMNODE,0,0,0,0,0,0,s); } ! 98: ! 99: Expr *E_Unary(Op unary, Expr *sub) { return new Expr(E_UNARY,unary,sub,0,0,0,0,0); } ! 100: ! 101: Expr *E_Binary(Expr*l,Op binary,Expr*r) ! 102: { return new Expr(E_BINARY,binary,l,r,0,0,0,0); } ! 103: ! 104: Expr *E_IConst(long i) { return new Expr(E_LCONST,0,0,0,i,Token,LONG,0); } ! 105: ! 106: Expr *E_DConst(double d) { return new Expr(E_DCONST,0,0,0,d,Token,DOUBLE,0); } ! 107: ! 108: char *Expr::floaterror() ! 109: { ! 110: return val.floaterror(); ! 111: } ! 112: ! 113: char *Expr::under(Expr *e) ! 114: { ! 115: if( e->edisc != E_BINARY || Prec(e->op) < Prec(op) ) return e->text(); ! 116: return sf( "(%s)", e->text() ); ! 117: } ! 118: ! 119: Expr::Expr() {} ! 120: ! 121: Expr::Expr( EDisc d, Op o, Expr* s1, Expr* s2, Cslfd c, char* s, int t, Symbol *v) ! 122: { ! 123: type.pcc = t; ! 124: edisc = d; ! 125: op = o; ! 126: sub1 = s1; ! 127: sub2 = s2; ! 128: val = c; ! 129: id = s ? sf("%s",s) : ""; ! 130: sym = v; ! 131: evalerr = 0; ! 132: spy = 0; ! 133: addr = 0; ! 134: bitaddr = 0; ! 135: trace( "Expr(edisc=%d,op=%s,sub1=%d,sub2=%d,val.lng=%d,id=%s,symbol=%d", ! 136: edisc, OpName(op), sub1, sub2, val.lng, id?id:"", v); ! 137: } ! 138: ! 139: char *Expr::left(Expr *e) ! 140: { ! 141: switch( e->edisc ){ ! 142: case E_BINARY: switch( e->op ){ ! 143: case O_INDEX: ! 144: case O_DOT: ! 145: case O_ARROW: return e->text(); ! 146: } ! 147: case E_UNARY: return sf( "(%s)", e->text() ); ! 148: default: return e->text(); ! 149: } ! 150: } ! 151: ! 152: char *Expr::textunary() ! 153: { ! 154: trace( "%d.textunary()", this ); OK("textunary"); ! 155: switch( op ){ ! 156: case O_QCAST: ! 157: case O_QSTRUCT: ! 158: case O_QENUM: ! 159: return sf("(%0.*s%s )%s",val.lng,"*******",OpName(op),sub1->text()); ! 160: case O_CAST: ! 161: return sf("(%s)%s",type.text(),sub1->text()); ! 162: case O_QINDEX: ! 163: return sf( "%s[ ? ]", left(sub1) ); ! 164: case O_SIZEOF: ! 165: case O_TYPEOF: ! 166: case O_FABS: ! 167: case O_SPECIAL: ! 168: return sf( "%s(%s)", OpName(op), sub1->text() ); ! 169: } ! 170: if( sub1->edisc==E_BINARY && Prec(sub1->op)>=Prec(O_MULT) ) ! 171: return sf( "%s(%s)", OpName(op), sub1->text() ); ! 172: return sf( "%s%s", OpName(op), sub1->text() ); ! 173: } ! 174: ! 175: char *Expr::textbinary() ! 176: { ! 177: trace( "%d.textbinary()", this ); OK("textbinary"); ! 178: switch( op ){ ! 179: case O_ENV: ! 180: return sf( "{%s}%s", sub1->text(), sub2->text() ); ! 181: case O_COMMA: /* ??? */ ! 182: return sf( "%s,%s", sub1->text(), sub2->text() ); ! 183: case O_CALL: ! 184: return sf( "%s(%s)", sub1->text(), sub2?sub2->text():"" ); ! 185: case O_ASSIGN: ! 186: return sf("(%s:=%s)", left(sub1), sub2->text() ); ! 187: case O_INDEX: ! 188: return sf("%s[%s]", left(sub1), sub2->text() ); ! 189: case O_DOT: ! 190: case O_ARROW: ! 191: return sf("%s%s%s", left(sub1), OpName(op), sub2->text()); ! 192: } ! 193: if( sub1->edisc==E_BINARY && Prec(sub1->op) == Prec(op) ) ! 194: return sf("%s%s%s", sub1->text(), OpName(op), under(sub2)); ! 195: return sf("%s%s%s", under(sub1), OpName(op), under(sub2)); ! 196: } ! 197: ! 198: char *Expr::text() ! 199: { ! 200: trace( "%d.text()", this ); OK("text"); ! 201: switch( edisc ){ ! 202: case E_DCONST: if( !id || !*id ) return sf( "%g", val.dbl ); ! 203: case E_LCONST: if( !id || !*id ) return sf( "%d", val.lng ); ! 204: case E_ID: return id; ! 205: case E_UNARY: return textunary(); ! 206: case E_BINARY: return textbinary(); ! 207: case E_SYMNODE: ! 208: if( !sym || !sym->_text ) return "<symbol>"; ! 209: return sym->_text; ! 210: } ! 211: return "<expr>"; ! 212: } ! 213: ! 214: int Expr::format() ! 215: { ! 216: trace( "%d.format() %s %s", this, text(), type.text() ); OK(F_HEX); ! 217: return type.format(); ! 218: } ! 219: ! 220: void Expr::reformat(int over, int stars) ! 221: { ! 222: trace("%d.reformat(0x%X,%d) %s %s",this,over,stars,text(),type.text()); VOK; ! 223: switch( edisc ){ ! 224: case E_ID: break; // shut up cfront ! 225: case E_LCONST: ! 226: case E_DCONST: ! 227: type.reformat(over); ! 228: return; ! 229: case E_SYMNODE: ! 230: IF_LIVE(!sym) return; ! 231: ((Var*)sym)->type.reformat(over,stars); ! 232: return; ! 233: case E_UNARY: ! 234: switch( op ){ ! 235: case O_REF: ! 236: case O_SIZEOF: ! 237: case O_CAST: ! 238: type.reformat(over,stars); ! 239: return; ! 240: case O_DEREF: ! 241: sub1->reformat(over,stars+1); ! 242: return; ! 243: case O_MINUS: ! 244: case O_1SCOMP: ! 245: case O_LOGNOT: ! 246: sub1->reformat(over,stars); ! 247: return; ! 248: } ! 249: case E_BINARY: ! 250: switch( op ){ ! 251: case O_DIV: ! 252: case O_MULT: ! 253: case O_MOD: ! 254: case O_PLUS: ! 255: case O_MINUS: ! 256: case O_BITAND: ! 257: case O_BITOR: ! 258: case O_BITXOR: ! 259: sub1->reformat(over,stars); /* fall thru */ ! 260: case O_ARROW: ! 261: case O_DOT: ! 262: case O_COMMA: ! 263: sub2->reformat(over,stars); ! 264: return; ! 265: case O_ASSIGN: ! 266: case O_ENV: ! 267: case O_LSHIFT: ! 268: case O_RSHIFT: ! 269: sub1->reformat(over,stars); ! 270: return; ! 271: case O_INDEX: ! 272: sub1->reformat(over,stars+1); ! 273: return; ! 274: case O_CALL: ! 275: Func *func = (Func*) sub1->sym; ! 276: if( func->ok() ) ! 277: func->type.decref()->reformat(over,stars); ! 278: return; ! 279: } ! 280: } ! 281: } ! 282: ! 283: char *Expr::ascii(Frame *frame, int limit ) ! 284: { ! 285: static char buf[256]; ! 286: char *raw, *fail = "fail"; // fail is unique ! 287: Bls esc( "\"" ); ! 288: int i; ! 289: ! 290: trace("%d.ascii(%d)", this, frame); OK("ascii"); ! 291: if( !val.lng ) return "0"; ! 292: raw = frame->peekstring(val.lng, fail); ! 293: if( raw == fail ) return "<string error>"; ! 294: for( i = 0; raw[i] && i<limit; ++i ) ! 295: esc.af( "%s", FmtByte(raw[i]) ); ! 296: if( raw[i] ) esc.af("..."); ! 297: sprintf(buf, "%s\"", esc.text); ! 298: return buf; ! 299: } ! 300: ! 301: char *Expr::enumformat() ! 302: { ! 303: Var *m; ! 304: ! 305: trace( "%d.enumformat()", this ); OK("enumformat"); ! 306: TypMems tm(type.utype()); ! 307: while( m = tm.gen() ) ! 308: if( m->range.lo == val.lng ) ! 309: return m->text(); ! 310: return sf( "(enum %s)%d", type.utype()?type.utype()->text():"?", val.lng ); ! 311: } ! 312: ! 313: char *Expr::utypeformat(Frame *frame, Bls &build) ! 314: { ! 315: Var *m, g(0,0,0,0,"$pi.Expr::utypeformat"); ! 316: int i = 0; ! 317: Expr e; /* use constructor to guarantee zeros? */ ! 318: ! 319: trace("%d.utypeformat(%d,%d)", this, frame, &build); OK("utypeformat"); ! 320: build.af("{"); ! 321: TypMems tm(type.utype()); ! 322: while( m = tm.gen() ) if( m->showorhide==SHOW ){ ! 323: Bls local; ! 324: g = *m; ! 325: g._disc = U_GLB; ! 326: DType t = g.type; ! 327: e.bitaddr = 0; ! 328: if( t.pcc==BITS || t.pcc==UBITS ){ ! 329: e.bitaddr = g.range.lo; ! 330: g.range.lo = 0; ! 331: } ! 332: g.range.lo += addr; ! 333: e.edisc = E_SYMNODE; ! 334: e.sym = &g; ! 335: e.spy = 0; ! 336: e.op = 0; ! 337: build.af( "%s%s", i++?",":"", e.evaltext(frame,local) ); ! 338: } ! 339: build.af( "}" ); ! 340: return build.text; ! 341: } ! 342: ! 343: char *Expr::evaltextcomma(Frame *frame, Bls &build) ! 344: { ! 345: trace("%d.evaltextcomma(%d,%d)",this,frame,&build);OK("evaltextcomma"); ! 346: sub1->evaltext(frame,build); ! 347: if( evalerr = sub1->evalerr ) return build.text; ! 348: build.af(", "); ! 349: sub2->evaltext(frame,build); ! 350: evalerr = sub2->evalerr; ! 351: type = sub2->type; ! 352: val = sub2->val; ! 353: return build.text; ! 354: } ! 355: ! 356: char *Expr::evaltext(Frame *frame, Bls &build) ! 357: { ! 358: trace( "%d.evaltext(%d,%d)", this, frame, &build ); OK("evaltext"); ! 359: evalerr = 0; ! 360: doevaltext(frame, build); ! 361: if( evalerr ) setspy(0); ! 362: if( spy ) spy->b = build.text; ! 363: return build.text; ! 364: } ! 365: ! 366: char *Expr::doevaltext(Frame *frame, Bls &build) ! 367: { ! 368: char *error, *t; ! 369: Format form(0, frame->core->symtab()); ! 370: ! 371: trace( "%d.doevaltext(%d,%d)", this, frame, &build ); OK("doevaltext"); ! 372: switch( op ){ ! 373: case O_QINDEX: ! 374: case O_QCAST: ! 375: case O_QENUM: ! 376: case O_QSTRUCT: ! 377: build.af( "%s", text() ); ! 378: return build.text; ! 379: } ! 380: if( op == O_COMMA ) return evaltextcomma(frame,build); ! 381: if( error = eval(frame) ){ ! 382: build.af( "%s: %s", text(), error ); ! 383: evalerr = 1; ! 384: return build.text; ! 385: } ! 386: if( spy ) build.af(">>> "); ! 387: build.af( "%s", text() ); ! 388: if( type.pcc == VOID ){ ! 389: build.af( "=void" ); ! 390: return build.text; ! 391: } ! 392: form.format = format(); ! 393: if( form.format&(F_DOUBLE|F_FLOAT) && val.floaterror() ){ ! 394: build.af( "=<%s>", val.floaterror() ); ! 395: form.format &= ~(F_DOUBLE|F_FLOAT); ! 396: form.format |= F_NONE; ! 397: } ! 398: if( form.format&F_ARY ) val.lng = addr; ! 399: if( *(t = form.f(val.lng,val.dbl)) ) ! 400: build.af( "=%s", t ); ! 401: if( form.format&F_UTYPE ){ ! 402: build.af( "="); ! 403: utypeformat(frame,build); ! 404: } ! 405: if( form.format&F_ENUM ) ! 406: build.af( "=%s", enumformat() ); ! 407: if( form.format&F_STRING ) ! 408: build.af( "=%s", ascii(frame, form.format&F_LONGSTRING?200:20) ); ! 409: return build.text; ! 410: } ! 411: ! 412: char *Expr::getval( Frame *frame ) /* addr already fixed */ ! 413: { ! 414: trace( "%d.getval(%d)", this, frame ); OK("getval"); ! 415: if( sym ){ ! 416: switch( sym->disc() ){ ! 417: case U_FUNC: ! 418: type = ((Func*)sym)->type; ! 419: break; ! 420: default: ! 421: type = ((Var*)sym)->type; ! 422: ((Var*)sym)->show(SHOW); ! 423: } ! 424: } ! 425: if( !addr ) return "addressing error: 0"; ! 426: addr += (bitaddr>>5)*4; ! 427: if( type.isscalar() ){ ! 428: Cslfd *m = frame->peek(addr,0); ! 429: if( !m ) return sf( "addressing error: 0x%X", addr ); ! 430: val = *m; ! 431: } ! 432: if( type.isscalar() ) switch( type.pcc ){ ! 433: case BITS: ! 434: case UBITS: val.lng = (val.lng>>(bitaddr&31)); ! 435: int power = 1<<type.dim; ! 436: val.lng &= power-1; ! 437: if( type.pcc==BITS && val.lng&(power>>1) ) ! 438: val.lng |= ~(power-1); ! 439: addr = 0; break; ! 440: case CHAR: val.lng = (char) val.chr; break; ! 441: case UCHAR: val.lng = (unsigned char) val.chr; break; ! 442: case SHORT: val.lng = (short) val.sht; break; ! 443: case USHORT: val.lng = (unsigned short) val.sht; break; ! 444: case FLOAT: val.dbl = val.flt; break; ! 445: } ! 446: trace( "%s %d %d %s", sym?sym->_text:"", addr, val.lng, type.text() ); ! 447: return 0; ! 448: } ! 449: ! 450: char *Expr::invalidoperands(char *more) ! 451: { ! 452: trace( "%d.invalidoperands()", this ); OK("invalidoperands"); ! 453: char *colon = more ? ": " : ""; ! 454: if( !more ) more = ""; ! 455: return sf( "invalid operand(s) of %s%s%s", OpName(op), colon, more ); ! 456: } ! 457: ! 458: char *Expr::eval(Frame *frame) ! 459: { ! 460: trace( "%d.eval(%d)", this, frame ); OK("eval"); ! 461: switch(op){ ! 462: case O_QINDEX: ! 463: case O_QCAST: ! 464: case O_QSTRUCT: ! 465: case O_QENUM: ! 466: return "? stops evaluation"; ! 467: } ! 468: switch( edisc ){ ! 469: case E_DCONST: ! 470: case E_LCONST: ! 471: return 0; /* should all be there! */ ! 472: case E_UNARY: ! 473: return evalunary(frame); ! 474: case E_BINARY: ! 475: return evalbinary(frame); ! 476: case E_ID: ! 477: if( !(sym = frame->idtosym(id)) ) ! 478: return enumid(frame); ! 479: edisc = E_SYMNODE; /* fall thru */ ! 480: case E_SYMNODE: ! 481: if( !sym ) return "symbol table error"; ! 482: addr = frame->locate((Var*)sym); ! 483: return getval(frame); ! 484: default: ! 485: return "not an expression"; ! 486: } ! 487: } ! 488: ! 489: char *Expr::enumid(Frame *frame) ! 490: { ! 491: trace("%d.enumid(%s)", this, id); OK("enumid"); ! 492: UType *u; Var *v; ! 493: for( u = frame->symtab()->utypelist(); u; u = (UType*) u->rsib ){ ! 494: if( u->type.pcc != ENUMTY ) continue; ! 495: TypMems tm(u); ! 496: while( v = tm.gen() ) if( !strcmp(id, v->_text) ){ ! 497: edisc = E_LCONST; ! 498: val.lng = v->range.lo; ! 499: addr = 0; ! 500: type.pcc = LONG; ! 501: return 0; ! 502: } ! 503: } ! 504: return sf("not found: %s", id); ! 505: } ! 506: ! 507: char *Expr::evalindex(Frame *frame, Expr *ap, long i) ! 508: { ! 509: long size = 0; ! 510: ! 511: trace( "%d.index(%d,%d,%d)", this, frame, ap, i); OK("evalindex"); ! 512: if( ap && ap->type.decref() ){ ! 513: type = *ap->type.decref(); ! 514: size = type.size_of(); ! 515: } ! 516: if( !size ) return "cannot determine size for []"; ! 517: addr = ap->type.isptr() ? ap->val.lng : ap->addr; ! 518: if( !addr ) return "zero pointer for []"; ! 519: addr += size * i; ! 520: return getval(frame); ! 521: } ! 522: ! 523: char *Expr::evaldotarrow(Frame *frame) ! 524: { ! 525: DType t; ! 526: ! 527: trace( "%d.evaldotarrow(%d)", this, frame ); OK("evaldotarrow"); ! 528: addr = 0; ! 529: t = sub1->type; ! 530: if( op == O_DOT ) ! 531: addr = sub1->addr; ! 532: else { ! 533: if( !t.isptr() ) return invalidoperands("not a pointer"); ! 534: t = *t.decref(); ! 535: addr = sub1->val.lng; ! 536: } ! 537: if( !t.isstrun() ) return invalidoperands("not a struct/union"); ! 538: if( !addr ) return invalidoperands("zero address"); ! 539: if( sub2->edisc == E_ID && t.utype() ){ ! 540: TypMems tm(t.utype()); ! 541: while( sub2->sym = tm.gen() ) ! 542: if( !strcmp(sub2->sym->text(), sub2->id) ) break; ! 543: if( !sub2->sym ) return sf("not found: %s", sub2->id); ! 544: sub2->edisc = E_SYMNODE; ! 545: } ! 546: if( sub2->edisc != E_SYMNODE ) return invalidoperands(); ! 547: sym = sub2->sym; ! 548: t = ((Var*)sym)->type; ! 549: if( t.pcc==BITS || t.pcc==UBITS ) ! 550: bitaddr = sym->range.lo; ! 551: else ! 552: addr += sym->range.lo; ! 553: return getval(frame); ! 554: } ! 555: ! 556: Expr *Expr::actual(int a) ! 557: { ! 558: int m; ! 559: trace( "%d.actual(%d)", this, a ); ! 560: if( !this ) return 0; ! 561: if( op != O_COMMA ) return a == 1 ? this : 0; ! 562: for( m = 0; sub1->actual(m+1); ++m ) {} ! 563: return a<=m ? sub1->actual(a) : sub2->actual(a-m); ! 564: } ! 565: ! 566: char *Expr::evalcall(Frame *frame) ! 567: { ! 568: char *error = 0; ! 569: long i, nargs = 1, argwords = 0, regloc; ! 570: Var *formal; ! 571: Func *func; ! 572: Frame *called = 0; ! 573: ! 574: trace( "%d.evalcall(%d)", this, frame ); OK("evalcall"); ! 575: if( !sub1 )return "<fcn call>"; ! 576: switch( sub1->edisc ){ ! 577: default: return "<fcn call>"; ! 578: case E_ID: ! 579: sub1->sym = frame->symtab()->idtosym( U_FUNC, sub1->id ); ! 580: case E_SYMNODE: ! 581: func = (Func*) sub1->sym; ! 582: } ! 583: if( !func ) return sf( "not a function: %s", sub1->id ); ! 584: while( sub2->actual(nargs) ) ! 585: if( !(formal = func->argument(nargs)) ) ! 586: return "too many args in function call"; ! 587: else { ! 588: argwords += (formal->type.size_of()+3)/4; /* vax & 32 */ ! 589: ++nargs; ! 590: } ! 591: if( func->argument(nargs) ) ! 592: return "too few args in function call"; ! 593: --nargs; ! 594: Core *core = frame->core; ! 595: if( !core->online() ) ! 596: return "cannot call function in dump"; ! 597: Context *cc = core->newContext(); ! 598: if( cc->error ){ ! 599: delete cc; ! 600: return cc->error; ! 601: } ! 602: called = new Frame(core); ! 603: called->ap = core->apforcall(argwords*4); ! 604: if( !called->ap ) ! 605: { error = "function calling is broken"; goto Restore; } ! 606: for( i = 1; i <= nargs; ++i ){ ! 607: Expr *e; ! 608: e = E_Binary(E_Sym(func->argument(i)), O_ASSIGN, sub2->actual(i)); ! 609: if( error = e->sub1->eval(called) ) ! 610: { error = sf("formal arg: %s", error); goto Restore; } ! 611: if( error = e->sub2->eval(frame) ) ! 612: { error = sf("actual arg: %s", error); goto Restore; } ! 613: if( error = e->evalassign(called) ) ! 614: { error = sf("arg assign: %s", error); goto Restore; } ! 615: } ! 616: if( error = core->docall(func->range.lo, argwords) ) ! 617: goto Restore; ! 618: type = *func->type.decref(); ! 619: regloc = core->returnregloc(); ! 620: if( !regloc) ! 621: { error = "function return error"; goto Restore; } ! 622: if( type.isstrun() ) ! 623: switch( type.size_of() ){ ! 624: case 1: ! 625: case 2: ! 626: case 4: addr = regloc; ! 627: break; ! 628: default: ! 629: addr = core->peek(regloc)->lng; ! 630: } ! 631: else ! 632: val = *core->peek(regloc); /* doubles? */ ! 633: Restore: ! 634: if( called ) delete called; ! 635: cc->restore(); ! 636: if( cc->error && !error ) ! 637: error = cc->error; ! 638: delete cc; ! 639: return error; ! 640: } ! 641: ! 642: char *Expr::evalenv(Frame *frame) ! 643: { ! 644: Frame *env = frame ? frame->caller() : 0; ! 645: char *error; ! 646: ! 647: trace( "%d.evalenv(%d)", this, frame ); OK("evalenv"); ! 648: for( ; env; env = env->caller() ) ! 649: if( !strcmp(env->func->_text,sub2->text()) ) ! 650: break; ! 651: if( !env ){ ! 652: Frame sta(frame->core); ! 653: sta.func = (Func*) sta.core->symtab()->idtosym(U_FUNC,sub2->text()); ! 654: if( sta.func ) env = &sta; ! 655: } ! 656: if( !env ) return sf( "not found: %s()", sub2->text() ); ! 657: if( error = sub1->eval(env) ) return error; ! 658: type = sub1->type; ! 659: val = sub1->val; ! 660: addr = sub1->addr; ! 661: return 0; ! 662: } ! 663: ! 664: char *Expr::evalrange() ! 665: { ! 666: const int range = 32; ! 667: trace( "%d.evalrange()", this ); OK("evalrange"); ! 668: if( !sub1->type.isintegral() ! 669: || !sub2->type.isintegral() ! 670: || sub2->val.lng < sub1->val.lng ) ! 671: return invalidoperands(); ! 672: if( sub2->val.lng > sub1->val.lng+range ) ! 673: return sf( "range may not exceed %d", range ); ! 674: return 0; ! 675: } ! 676: ! 677: void Expr::catchfpe() /* VAX: put down operands that must succeed */ ! 678: { /* and restart the instruction */ ! 679: *fp1 = *fp2 = 1.0; ! 680: fpe = "floating point exception"; ! 681: } ! 682: ! 683: char *Expr::evalflop() /* VAX host */ ! 684: { ! 685: char *error; ! 686: trace( "%d.evalflop()", this ); OK("evalflop"); ! 687: if( !sub1->type.isreal() || !sub2->type.isreal() ) ! 688: return invalidoperands(); ! 689: if( (error = sub1->floaterror()) ! 690: || (error = sub2->floaterror()) ) ! 691: return invalidoperands(error); ! 692: type.pcc = DOUBLE; ! 693: double l = sub1->val.dbl; double r = sub2->val.dbl; ! 694: fp1 = &l; ! 695: fp2 = &r; ! 696: fpe = 0; ! 697: signal(SIGFPE, (SIG_TYP)&Expr::catchfpe); ! 698: switch( op ){ ! 699: case O_MULT: val.dbl = l*r; break; ! 700: case O_DIV: val.dbl = l/r; break; ! 701: case O_PLUS: val.dbl = l+r; break; ! 702: case O_MINUS: val.dbl = l-r; break; ! 703: } ! 704: signal(SIGFPE, (SIG_TYP)SIG_DFL); ! 705: return fpe; ! 706: } ! 707: ! 708: char *Expr::evalbinary(Frame *frame) ! 709: { ! 710: char *error; ! 711: long size; ! 712: ! 713: trace( "%d.evalbinary(%d)", this, frame ); OK("evalbinary"); ! 714: IF_LIVE( edisc!=E_BINARY ) return "<binary expr>"; ! 715: switch( op ){ ! 716: case O_CALL: return evalcall(frame); ! 717: case O_ENV: return evalenv(frame); ! 718: } ! 719: if( error = sub1->eval(frame) ) return error; ! 720: type.pcc = LONG; ! 721: type.over = sub1->type.over; ! 722: if( op==O_DOT || op==O_ARROW ) return evaldotarrow(frame); ! 723: if( (sub1->type.isintegral() && op==O_LOGAND && !sub1->val.lng) ! 724: || (sub1->type.isintegral() && op==O_LOGOR && sub1->val.lng) ){ ! 725: val = sub1->val.lng != 0; ! 726: return 0; ! 727: } ! 728: if( error = sub2->eval(frame) ) return error; ! 729: type.over |= sub2->type.over; ! 730: switch( op ){ ! 731: case O_RANGE: ! 732: return evalrange(); ! 733: case O_COMMA: ! 734: type = sub2->type; ! 735: val = sub2->val; ! 736: return 0; ! 737: case O_ASSIGN: ! 738: return evalassign(frame); ! 739: case O_MULT: ! 740: case O_DIV: ! 741: if( sub1->type.isreal() || sub2->type.isreal() ) ! 742: return evalflop(); ! 743: case O_MOD: ! 744: if( sub1->type.isintegral() && sub2->type.isintegral() ){ ! 745: long l = sub1->val.lng, r = sub2->val.lng; ! 746: if( op==O_MULT ){ ! 747: val.lng = l * r; ! 748: return 0; ! 749: } ! 750: if( r == 0 ) return "zero divide"; ! 751: if( op == O_MOD ) val.lng = l % r; ! 752: if( op == O_DIV ) val.lng = l / r; ! 753: return 0; ! 754: } ! 755: return invalidoperands(); ! 756: case O_LOGAND: ! 757: case O_LOGOR: ! 758: case O_BITAND: ! 759: case O_BITOR: ! 760: case O_BITXOR: ! 761: case O_LSHIFT: ! 762: case O_RSHIFT: ! 763: if( sub1->type.isscalar() && sub2->type.isscalar() ){ ! 764: long l = sub1->val.lng, r = sub2->val.lng; ! 765: switch( op ){ ! 766: case O_LOGAND: val.lng = l && r; return 0; ! 767: case O_LOGOR: val.lng = l || r; return 0; ! 768: case O_BITAND: val.lng = l & r; return 0; ! 769: case O_BITOR: val.lng = l | r; return 0; ! 770: case O_BITXOR: val.lng = l ^ r; return 0; ! 771: case O_LSHIFT: val.lng = l << r; return 0; ! 772: case O_RSHIFT: val.lng = l >> r; return 0; ! 773: } ! 774: return "internal error: && || & | ^ >> <<"; ! 775: } ! 776: return invalidoperands(); ! 777: case O_EQ: ! 778: case O_NE: ! 779: case O_LT: ! 780: case O_GT: ! 781: case O_LE: ! 782: case O_GE: ! 783: type.pcc = LONG; ! 784: if( sub1->type.isreal() || sub2->type.isreal() ){ ! 785: if( !sub1->type.isreal() || sub1->floaterror() ! 786: || !sub2->type.isreal() || sub2->floaterror() ) ! 787: return invalidoperands(); ! 788: double l = sub1->val.dbl; double r = sub2->val.dbl; /*C++*/ ! 789: switch( op ){ ! 790: case O_EQ: val.lng = l == r; return 0; ! 791: case O_NE: val.lng = l != r; return 0; ! 792: case O_LT: val.lng = l < r; return 0; ! 793: case O_GT: val.lng = l > r; return 0; ! 794: case O_LE: val.lng = l <= r; return 0; ! 795: case O_GE: val.lng = l >= r; return 0; ! 796: } ! 797: return "internal floating relation error"; ! 798: } ! 799: if( sub1->type.isscalar() && sub2->type.isscalar() ){ ! 800: long l = sub1->val.lng, r = sub2->val.lng; ! 801: switch( op ){ ! 802: case O_EQ: val.lng = l == r; return 0; ! 803: case O_NE: val.lng = l != r; return 0; ! 804: case O_LT: val.lng = l < r; return 0; ! 805: case O_GT: val.lng = l > r; return 0; ! 806: case O_LE: val.lng = l <= r; return 0; ! 807: case O_GE: val.lng = l >= r; return 0; ! 808: } ! 809: return "internal fixed point relation error"; ! 810: } ! 811: return invalidoperands(); ! 812: case O_PLUS: ! 813: case O_MINUS: ! 814: if( sub1->type.isreal() || sub2->type.isreal() ) ! 815: return evalflop(); ! 816: if( sub1->type.isary() ){ ! 817: sub1->val.lng = sub1->addr; ! 818: sub1->type = sub1->type.decref()->incref(); ! 819: } ! 820: if( sub2->type.isary() ){ ! 821: sub2->val.lng = sub2->addr; ! 822: sub2->type = sub2->type.decref()->incref(); ! 823: } ! 824: if( sub1->type.isptr() && sub2->type.isintegral() ){ ! 825: size = sub1->type.decref()->size_of(); ! 826: if( !size ) return "pointer arithmetic error"; ! 827: if( op == O_MINUS ) size = -size; ! 828: val.lng = sub1->val.lng + size*sub2->val.lng; ! 829: type = sub1->type; ! 830: return 0; ! 831: } ! 832: if( sub1->type.isintegral() && sub2->type.isintegral() ){ ! 833: if( op==O_PLUS ) val.lng = sub1->val.lng+sub2->val.lng; ! 834: if( op==O_MINUS) val.lng = sub1->val.lng-sub2->val.lng; ! 835: return 0; ! 836: } ! 837: if( op == O_PLUS && sub2->type.isptr() && sub1->type.isintegral() ){ ! 838: size = sub2->type.decref()->size_of(); ! 839: if( !size ) return "pointer arithmetic error"; ! 840: val.lng = sub2->val.lng + size*sub1->val.lng; ! 841: type = sub2->type; ! 842: return 0; ! 843: } ! 844: if( op == O_MINUS && sub1->type.isptr() && sub2->type.isptr() ){ ! 845: size = sub1->type.decref()->size_of(); ! 846: if( !size || size!=sub2->type.decref()->size_of() ) ! 847: return "pointer-pointer size error"; ! 848: val.lng = (sub1->val.lng - sub2->val.lng)/size; ! 849: type.over |= sub2->type.over; ! 850: return 0; ! 851: } ! 852: return invalidoperands(); ! 853: case O_INDEX: ! 854: trace( "%s %s", sub1->type.text(), sub2->type.text() ); ! 855: if( sub1->type.isaryorptr() && sub2->type.isintegral() ) ! 856: return evalindex(frame,sub1,sub2->val.lng); ! 857: if( sub2->type.isaryorptr() && sub1->type.isintegral() ) ! 858: return evalindex(frame,sub2,sub1->val.lng); ! 859: return invalidoperands(); ! 860: default: ! 861: return "binary operator not implemented"; ! 862: } ! 863: } ! 864: ! 865: char *Expr::evalcast() ! 866: { ! 867: trace( "%d.evalcast()", this, ); OK("<cast>"); ! 868: IF_LIVE( !type.isscalar() || !sub1->type.isscalar() ) return "cast error"; ! 869: if( type.isptr() ){ ! 870: if( sub1->type.isreal() ) return "can't cast float to ptr"; ! 871: val.lng = sub1->val.lng; ! 872: return 0; ! 873: } ! 874: if( type.isreal() ){ ! 875: if( sub1->floaterror() ) return sub1->floaterror(); ! 876: val.dbl = sub1->val.dbl; ! 877: if( !sub1->type.isreal() ) val.dbl = sub1->val.lng; ! 878: return 0; ! 879: } ! 880: val.lng = sub1->val.lng; ! 881: switch( sub1->type.pcc ){ ! 882: case CHAR: val.lng = sub1->val.chr; break; ! 883: case SHORT: val.lng = sub1->val.sht; break; ! 884: } ! 885: addr = sub1->addr; ! 886: if( sub1->type.isreal() ){ ! 887: if( sub1->floaterror() ) return sub1->floaterror(); ! 888: val.lng = (long) sub1->val.dbl; ! 889: } ! 890: return 0; ! 891: } ! 892: ! 893: char *Expr::evalunary(Frame *frame) ! 894: { ! 895: char *error; ! 896: ! 897: trace( "%d.evalunary(%d)", this, frame ); OK("<unary expr>"); ! 898: IF_LIVE( edisc!=E_UNARY ) return "<unary expr>"; ! 899: if( error = sub1->eval(frame) ) return error; ! 900: switch( op ){ ! 901: case O_SPECIAL: ! 902: type = sub1->type; ! 903: addr = sub1->addr; ! 904: val = sub1->val; ! 905: if( type.isptr() ){ ! 906: type = *type.decref(); ! 907: addr = val.lng; ! 908: } ! 909: if( !type.pcc == STRTY || !type.utype() || !addr ) ! 910: return invalidoperands(); ! 911: error = frame->special( type.utype()->text(), addr ); ! 912: { // cfront bug ! 913: DType nulltype; ! 914: type = nulltype; ! 915: } // cfront bug ! 916: type.pcc = VOID; ! 917: addr = 0; ! 918: return error; ! 919: case O_1SCOMP: ! 920: case O_LOGNOT: ! 921: if( !sub1->type.isscalar() || sub1->type.isreal() ) ! 922: return invalidoperands(); ! 923: type.pcc = LONG; ! 924: if( op == O_1SCOMP ) val.lng = ~sub1->val.lng; ! 925: if( op == O_LOGNOT ) val.lng = !sub1->val.lng; ! 926: return 0; ! 927: case O_FABS: ! 928: { // cfront bug ! 929: double fabs(double); ! 930: if( !sub1->type.isreal() || sub1->floaterror() ) ! 931: return invalidoperands(); ! 932: type.pcc = DOUBLE; ! 933: val.dbl = fabs(sub1->val.dbl); /* cannot fail? */ ! 934: return 0; ! 935: } // cfront bug ! 936: case O_MINUS: ! 937: if( sub1->type.isintegral() ){ ! 938: type.pcc = LONG; ! 939: val.lng = -sub1->val.lng; ! 940: return 0; ! 941: } ! 942: if( sub1->type.isreal() && !sub1->floaterror() ){ ! 943: type.pcc = DOUBLE; ! 944: val.dbl = -sub1->val.dbl; ! 945: return 0; ! 946: } ! 947: return invalidoperands(); ! 948: case O_CAST: ! 949: return evalcast(); ! 950: case O_SIZEOF: ! 951: addr = 0; ! 952: if( !(val.lng = sub1->type.size_of())) return "sizeof error"; ! 953: type.pcc = UNSIGNED; ! 954: return 0; ! 955: case O_TYPEOF: ! 956: return sub1->type.text(); ! 957: case O_DEREF: ! 958: if( !sub1->type.isptr() ) return "unary * applied to non-pointer"; ! 959: addr = sub1->val.lng; ! 960: type = *sub1->type.decref(); ! 961: return getval(frame); ! 962: case O_REF: ! 963: if( !sub1->addr ) return "unary & applied to non-lvalue"; ! 964: addr = 0; ! 965: int o = type.over; ! 966: type = sub1->type.incref(); ! 967: type.over = o; ! 968: val.lng = sub1->addr; ! 969: return 0; ! 970: default: ! 971: return "unary operator not implemented"; ! 972: } ! 973: } ! 974: ! 975: Index Expr::castcarte() ! 976: { ! 977: static Index *ix; ! 978: static short bt[] = { DOUBLE, FLOAT, LONG, SHORT, CHAR, 0 }; ! 979: Menu m; ! 980: DType *base, *ptr; ! 981: ! 982: trace( "%d.castcarte()", this ); OK(ZIndex); ! 983: if (!ix) ! 984: ix = new Index(0,0); ! 985: if( !ix->null() ) return *ix; ! 986: Action a = (Action)&Phrase::applycast; ! 987: int t; ! 988: for( t = 0; bt[t]; ++t ){ ! 989: base = new DType(); ! 990: base->pcc = bt[t]; ! 991: ptr = new DType; ! 992: *ptr = base->incref(); ! 993: m.first( sf( "%s\240", ptr->text() ), a, (long) ptr ); ! 994: m.first( sf( " %s\240", base->text()), a, (long) base ); ! 995: } ! 996: Action i = (Action)&Phrase::increfcast; ! 997: Action e = (Action)&Phrase::enumcast; ! 998: Action s = (Action)&Phrase::strcast; ! 999: m.last( " * ? ", i, 1 ); ! 1000: m.last( " enum ? ", e, 0 ); ! 1001: m.last( " *struct ? ", s, 1 ); ! 1002: return *ix = m.index("cast $"); ! 1003: } ! 1004: ! 1005: Index Expr::carte(Frame *f) ! 1006: { ! 1007: Menu m; ! 1008: ! 1009: trace( "%d.carte()", this ); OK(ZIndex); ! 1010: m.last( "eval $", (Action)&Phrase::evaluate ); ! 1011: if( evalerr || op==O_TYPEOF ) ! 1012: return m.index(); ! 1013: switch( op ){ ! 1014: case O_QCAST: ! 1015: return castcarte(); ! 1016: case O_QSTRUCT: ! 1017: return f ? f->symtab()->utypecarte(STRTY) : ZIndex; ! 1018: case O_QENUM: ! 1019: return f ? f->symtab()->utypecarte(ENUMTY) : ZIndex; ! 1020: case O_QINDEX: ! 1021: return NumericRange( -2, 20 ); ! 1022: } ! 1023: if( !spy ) ! 1024: m.first( "spy on $", (Action) &Phrase::setspy, 1 ); ! 1025: else ! 1026: m.first( "unspy $", (Action) &Phrase::setspy, 0 ); ! 1027: if( addr ) m.last( "& $", (Action)&Phrase::applyunary, (long)O_REF ); ! 1028: if( val.lng ) ! 1029: m.last( "mem .=$ ", (Action)&Phrase::memory ); ! 1030: if( type.isscalar() ) m.last(castcarte()); ! 1031: m.last(type.carte()); ! 1032: return m.index(); ! 1033: } ! 1034: ! 1035: void Expr::setspy(long s) ! 1036: { ! 1037: trace( "%d.setspy(%d)", this, s ); VOK; ! 1038: if( !s && spy ){ ! 1039: delete spy; ! 1040: spy = 0; ! 1041: } else if( s ) ! 1042: spy = new Spy; ! 1043: } ! 1044: ! 1045: char *Expr::evalassign(Frame *frame) ! 1046: { ! 1047: char *error; ! 1048: ! 1049: trace( "%d.evalassign(%d)", this, frame ); OK("evalassign"); ! 1050: if( !sub1->addr ) return "lhs of = does not yield an lvalue"; ! 1051: if( sub2->type.isary() && sub2->addr ){ ! 1052: sub2->type.pcc = PTR; ! 1053: sub2->val.lng = sub2->addr; ! 1054: } ! 1055: if( sub1->type.isscalar() && sub2->type.isscalar() ){ ! 1056: DType type1 = sub1->type, type2 = sub2->type; ! 1057: long addr1 = sub1->addr, size1 = type1.size_of(); ! 1058: Cslfd *val2 = &sub2->val; ! 1059: if( type1.isreal() || type1.isreal() ){ ! 1060: if( !type1.isreal() || !type2.isreal() ) ! 1061: return invalidoperands("mixed mode"); ! 1062: error = frame->pokedbl(addr1, val2->dbl, type1.size_of()); ! 1063: } else ! 1064: error = frame->poke(addr1, val2->lng, type1.size_of()); ! 1065: if( error ) ! 1066: return sf( "%s: 0x%X", error, sub1->addr ); ! 1067: if( error = sub1->eval(frame) ) ! 1068: return error; ! 1069: type = sub1->type; ! 1070: val = sub1->val; ! 1071: addr = 0; ! 1072: return 0; ! 1073: } ! 1074: if( sub1->type.isstrun() && sub2->type.isstrun() ){ ! 1075: UType *u1 = sub1->type.utype(), *u2 = sub2->type.utype(); ! 1076: if( !u1 ! 1077: || !u2 ! 1078: || u1->type.pcc != u2->type.pcc ! 1079: || strcmp(u1->type.text(), u2->type.text()) ) ! 1080: return "incompatible struct/union ="; ! 1081: if( !sub2->addr ) ! 1082: return "rhs of struct/union = does not yield an lvalue"; ! 1083: error = frame->blockmove(sub2->addr,sub1->addr,u1->type.size_of()); ! 1084: type = sub1->type; ! 1085: val = 0; ! 1086: addr = sub1->addr; ! 1087: return error; ! 1088: } ! 1089: return "invalid asssignment"; ! 1090: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.