|
|
1.1 ! root 1: static char sccsid[] = "@(#)expr.c 2.12"; ! 2: ! 3: #include "cdb.h" ! 4: #include "macdefs.h" ! 5: ! 6: extern long atol(); ! 7: extern double atof(); ! 8: extern int vrgOffset[]; /* defined in access.c */ ! 9: ! 10: /* the following define the stack mechanism used by the expression parser */ ! 11: ! 12: export int viopMac; /* operator stack pointer */ ! 13: export int vivarMac; /* variable stack pointer */ ! 14: ! 15: #define istkMax 15 ! 16: TYR vrgTy[cTyMax*istkMax]; /* variable stack */ ! 17: ADRT vrgAdr[cTyMax*istkMax]; /* addresses of the variables in vrgTy */ ! 18: TKE vrgTk[istkMax]; /* operator stack */ ! 19: ! 20: #define TOPOP (vrgTk[viopMac-1]) ! 21: #define TOPVAR (vrgTy[vivarMac-1]) ! 22: #define EmptyStack (vivarMac==0) ! 23: #define precParen 99 ! 24: ! 25: /* parser state */ ! 26: #define psFail 0 /* parser tripped */ ! 27: #define psOp 1 /* expression parser last saw an OPERATOR */ ! 28: #define psVar 2 /* expression parser last saw an VARIABLE */ ! 29: typedef int PSE, *pPSE; /* parser state */ ! 30: ! 31: ADRT vadrSb, vadrSbMax; /* where we can stick strings in child */ ! 32: ! 33: /* P U S H O P */ ! 34: ! 35: local void PushOp(tk) ! 36: TKE tk; ! 37: { ! 38: if (viopMac >= istkMax) ! 39: UError("Expression stack overflow"); ! 40: vrgTk[viopMac++] = tk; ! 41: } /* PushOp */ ! 42: ! 43: ! 44: /* P O P O P */ ! 45: ! 46: local TKE PopOp() ! 47: { ! 48: if (viopMac <= 0) ! 49: UError("Operator stack underflow"); ! 50: return(vrgTk[--viopMac]); ! 51: } /* PopOp */ ! 52: ! 53: ! 54: /* P U S H V A R */ ! 55: ! 56: local void PushVar(adrLong, ty) ! 57: long adrLong; ! 58: pTYR ty; ! 59: { ! 60: if (vivarMac >= istkMax) ! 61: UError("Expression stack overflow"); ! 62: CopyTy(vrgTy+vivarMac, ty); ! 63: vrgAdr[vivarMac] = adrLong; ! 64: vivarMac += 2; ! 65: } /* PushVar */ ! 66: ! 67: ! 68: /* F P O P V A R */ ! 69: ! 70: local FLAGT FPopVar(pret, ty) ! 71: long *pret; ! 72: pTYR ty; ! 73: { ! 74: if (vivarMac <= 0) ! 75: return(false); ! 76: vivarMac -= 2; /* point to first one */ ! 77: CopyTy(ty, vrgTy+vivarMac); ! 78: *pret = vrgAdr[vivarMac]; ! 79: return(true); ! 80: } /* FPopVar */ ! 81: ! 82: ! 83: /* A D R F S T O R E */ ! 84: ! 85: export ADRT AdrFStore(sb, cb) ! 86: char *sb; ! 87: int cb; ! 88: { ! 89: ADRT adr; ! 90: TYR ty[cTyMax]; ! 91: ! 92: /* this routine stores data in the CHILD's address space. ! 93: * this is mostly useful for passing strings as arguements to ! 94: * procedure calls from the command line. ! 95: */ ! 96: if (FOdd(cb)) ! 97: cb++; /* force to word boundary */ ! 98: /* will it fit? */ ! 99: if ((vadrSb == 0) OR (vadrSb+cb >= vadrSbMax)) { ! 100: /* no, we will go back and use the buffer over again */ ! 101: vadrSb = AdrFGlobal("__buffer", ty); ! 102: vadrSbMax = AdrFGlobal("_bufMax", ty); ! 103: if (vadrSb+cb >= vadrSbMax) ! 104: UError("I can't put something that big in the child. See 'end.c'"); ! 105: } ! 106: adr = vadrSb; ! 107: vadrSb += cb; /* advance to next free byte */ ! 108: PutBlock(adr, spaceData, sb, cb); ! 109: return(adr); ! 110: } /* AdrFStore */ ! 111: ! 112: ! 113: /* P R E C F T K */ ! 114: ! 115: export int PrecFTk(tk) ! 116: TKE tk; ! 117: { ! 118: /* determine precedence */ ! 119: /* these values are meaningful only in their relationship to one another */ ! 120: switch (tk) { ! 121: default: ! 122: return(0); ! 123: case tkBOE: ! 124: case tkLP: ! 125: return(precParen); ! 126: case tkInside: ! 127: case tkSizeof: ! 128: case tkLSB: ! 129: case tkPtr: ! 130: case tkDot: ! 131: return(96); ! 132: case tkRef: ! 133: case tkUMinus: ! 134: case tkBang: ! 135: case tkTilda: ! 136: case tkDeref: ! 137: return(95); /* unary operator */ ! 138: case tkDiv: ! 139: case tkMul: ! 140: return(80); ! 141: case tkPlus: ! 142: case tkMinus: ! 143: return(70); ! 144: case tkLShift: ! 145: case tkRShift: ! 146: return(60); ! 147: case tkLT: ! 148: case tkLE: ! 149: case tkGT: ! 150: case tkGE: ! 151: return(50); ! 152: case tkEqual: ! 153: case tkNotEqual: ! 154: return(40); ! 155: case tkBitAnd: ! 156: return(32); ! 157: case tkXOR: ! 158: return(31); ! 159: case tkBitOr: ! 160: return(30); ! 161: case tkLAND: ! 162: return(21); ! 163: case tkLOR: ! 164: return(20); ! 165: case tkAssPlus: ! 166: case tkAssMinus: ! 167: case tkAssMult: ! 168: case tkAssDiv: ! 169: case tkAssXOR: ! 170: case tkAssBAND: ! 171: case tkAssBOR: ! 172: case tkAssLeft: ! 173: case tkAssRight: ! 174: case tkAssMod: ! 175: case tkAssign: ! 176: return(3); ! 177: case tkComma: ! 178: case tkEOE: ! 179: case tkRP: ! 180: case tkIndex: ! 181: case tkRSB: ! 182: return(1); ! 183: } /* switch */ ! 184: } /* PrecFTk */ ! 185: ! 186: ! 187: /* V A L F A D R */ ! 188: ! 189: export long ValFAdr(adrLong, ty) ! 190: long adrLong; ! 191: pTYR ty; ! 192: { ! 193: int cb, bt; ! 194: ADRT adrSrc, adrDest; ! 195: STUFFU stuff; ! 196: ! 197: if (ty->td.fConstant) ! 198: return(adrLong); /* it was a constant - ergo, it has no address */ ! 199: ! 200: stuff.lng = 0; ! 201: adrSrc = adrLong; ! 202: cb = CbFTy(ty); ! 203: if (cb > 4) ! 204: cb = 4; /* this routine is not designed for more than a long */ ! 205: ! 206: if (ty->td.st == stReg) { ! 207: #ifndef REGULUS ! 208: if (cb == CBCHAR) { ! 209: stuff.chars.chLoLo = GetReg(adrSrc); ! 210: } ! 211: else if (cb == CBSHORT) { ! 212: stuff.shorts.shortLo = GetReg(adrSrc); ! 213: } ! 214: else { ! 215: #if (CBINT == CBSHORT) ! 216: stuff.shorts.shortHi = GetReg(adrSrc); ! 217: stuff.shorts.shortLo = GetReg(adrSrc+1); ! 218: #else ! 219: stuff.lng = GetReg(adrSrc); ! 220: #endif ! 221: } /* if */ ! 222: #else ! 223: if (trace(ptReadUser, vpid, cb, ! 224: &stuff, v_ar0+vrgOffset[adrSrc]) < 0) ! 225: UError("Bad Access"); ! 226: #endif ! 227: goto extendSign; ! 228: } /* if */ ! 229: ! 230: /* figure address we want this read into */ ! 231: adrDest = (cb == 1) ? (ADRT) &(stuff.chars.chLoLo) : ! 232: (cb == 2) ? (ADRT) &(stuff.shorts.shortLo) : ! 233: (ADRT) &(stuff.lng); ! 234: ! 235: if (ty->td.st == stSpc) { ! 236: /* a `special' variable (lives in debuggers universe) */ ! 237: MoveBytes(adrDest, adrSrc, cb); ! 238: goto extendSign; ! 239: } /* if */ ! 240: ! 241: /* unfortunately, there are some special addresses which look like adrNil! */ ! 242: if (adrSrc == adrNil) ! 243: return(0); ! 244: ! 245: if (cb > 0) { ! 246: GetBlock(adrSrc, spaceData, adrDest, cb); ! 247: return(stuff.lng); ! 248: } ! 249: else { ! 250: /* it must be a bit field spec */ ! 251: /* This is dependent on the order the compiler allocates bits */ ! 252: #ifdef BSD41 ! 253: cb = (ty->valTy + ty->td.width + (SZCHAR-1)) / SZCHAR; ! 254: GetBlock(adrSrc, spaceData, &stuff.lng, cb); ! 255: stuff.lng = Extract(stuff.lng, ty->valTy, ty->td.width); ! 256: return(stuff.lng); ! 257: #else ! 258: Panic("Don't know how to handle bit fields for this machine"); ! 259: #endif ! 260: } /* if */ ! 261: ! 262: extendSign: ! 263: /* following forces sign extension */ ! 264: bt = ty->td.bt; ! 265: if (TqFTy(ty, 1) == tqNil) { /* then it is a base type, not a pointer */ ! 266: if (bt == btChar) ! 267: stuff.lng = stuff.chars.chLoLo; ! 268: else if (bt == btShort) ! 269: stuff.lng = stuff.shorts.shortLo; ! 270: #if (CBINT == CBSHORT) ! 271: else if (bt == btInt) ! 272: stuff.lng = stuff.shorts.shortLo; ! 273: #endif ! 274: } ! 275: return(stuff.lng); ! 276: } /* ValFAdr */ ! 277: ! 278: ! 279: /* P U T V A L */ ! 280: ! 281: export void PutVal(adrLong, ty, val) ! 282: long adrLong; ! 283: pTYR ty; ! 284: long val; ! 285: { ! 286: int cb; ! 287: ADRT adrDest, adrSrc; ! 288: STUFFU stuff; ! 289: ! 290: if (ty->td.fConstant) ! 291: return; /* it was a constant - ergo, it lives no where */ ! 292: ! 293: stuff.lng = val; ! 294: adrDest = adrLong; ! 295: cb = CbFTy(ty); ! 296: if (cb > 4) ! 297: cb = 4; /* this routine is not designed for more than a long */ ! 298: ! 299: /* figure address we want this read from */ ! 300: adrSrc = (cb == 1) ? (ADRT) &(stuff.chars.chLoLo) : ! 301: (cb == 2) ? (ADRT) &(stuff.shorts.shortLo) : ! 302: (ADRT) &(stuff.lng); ! 303: ! 304: if (ty->td.st == stReg) { ! 305: #ifndef REGULUS ! 306: if (cb == CBCHAR) { ! 307: PutReg(adrDest, stuff.chars.chLoLo); ! 308: } ! 309: else if (cb == CBSHORT) { ! 310: PutReg(adrDest, stuff.shorts.shortLo); ! 311: } ! 312: else { ! 313: #if (CBIBT == CBSHORT) ! 314: PutReg(adrDest, stuff.shorts.shortHi); ! 315: PutReg(adrDest+1, stuff.shorts.shortLo); ! 316: #else ! 317: PutReg(adrDest, stuff.lng); ! 318: #endif ! 319: } /* if */ ! 320: #else ! 321: if (trace(ptWriteUser, vpid, cb, ! 322: &stuff, v_ar0+vrgOffset[adrDest]) < 0) ! 323: UError("Bad Access"); ! 324: #endif ! 325: return; ! 326: } /* if */ ! 327: ! 328: if (ty->td.st == stSpc) { ! 329: /* a `local' variable */ ! 330: MoveBytes(adrDest, adrSrc, cb); ! 331: return; ! 332: } /* if */ ! 333: ! 334: if (cb > 0) { ! 335: PutBlock(adrDest, spaceData, adrSrc, cb); ! 336: } ! 337: else { ! 338: /* it must be a bit field */ ! 339: #ifdef BSD41 ! 340: cb = (ty->valTy + ty->td.width + (SZCHAR-1)) / SZCHAR; ! 341: GetBlock(adrDest, spaceData, &stuff.lng, cb); ! 342: SetBits(stuff.lng, ty->td.width, ty->valTy, val); ! 343: PutBlock(adrDest, spaceData, &stuff.lng, cb); ! 344: #else ! 345: Panic("Don't know how to handle bit fields for this machine"); ! 346: #endif ! 347: } /* if */ ! 348: } /* PutVal */ ! 349: ! 350: ! 351: /* P S F D O O P */ ! 352: ! 353: local PSE PsFDoOp() ! 354: { ! 355: /* this is the rotuine that actually does the TOP operator */ ! 356: int cb1, cb2, tq, ipd; ! 357: ushort *rgDim; ! 358: ADRT adr, adrShort; ! 359: FLAGT fDidIt, fDoIntOp; ! 360: TKE tk; ! 361: TYR aty1[cTyMax], aty2[cTyMax], atyMax[cTyMax]; ! 362: pTYR ty, ty1, ty2, tyMax; ! 363: long adr1, adr2, val1, val2; ! 364: STUFFU stuff; ! 365: #define cbAssMax 200 ! 366: char buf[cbAssMax]; ! 367: ! 368: ty1 = aty1; ! 369: ty2 = aty2; ! 370: tyMax = atyMax; ! 371: ! 372: if (viopMac < 0) ! 373: return(psFail); ! 374: ! 375: if (TOPOP == tkLP ! 376: OR TOPOP == tkBOE) ! 377: return(psFail); /* they should be waiting for one of these */ ! 378: tk = PopOp(); ! 379: ! 380: if (!FPopVar(&adr2, ty2)) /* every op needs at least one */ ! 381: return(psFail); ! 382: val2 = ValFAdr(adr2, ty2); ! 383: ! 384: fDidIt = true; ! 385: switch (tk) { ! 386: /* unary operators */ ! 387: default: ! 388: fDidIt = false; ! 389: break; ! 390: case tkUMinus: ! 391: ty2->td.fConstant = true; ! 392: ty2->td.st = stValue; ! 393: PushVar(-val2, ty2); ! 394: break; ! 395: case tkBang: ! 396: PushVar(lengthen(val2==0), vtyCnInt); ! 397: break; ! 398: case tkTilda: ! 399: ty2->td.fConstant = true; ! 400: ty2->td.st = stValue; ! 401: PushVar(~val2, ty2); ! 402: break; ! 403: case tkRef: ! 404: if (ty2->td.fConstant) ! 405: UError("You can't take the address of a constant"); ! 406: if (ty2->td.st == stReg) ! 407: UError("You can't take the address of a register"); ! 408: if (!FAdjTd(ty2, tqPtr)) /* add a pointer level */ ! 409: UError("Type information overflow"); ! 410: ty2->td.fConstant = true; ! 411: ty2->td.st = stValue; ! 412: PushVar(adr2, ty2); ! 413: break; ! 414: case tkDeref: ! 415: tq = TqFTy(ty2, 1); ! 416: if ((tq == tqPtr) OR (tq == tqArray)) ! 417: FAdjTd(ty2, tqNil); /* remove tq */ ! 418: ty2->td.st = stValue; ! 419: if (ty2->td.fConstant) { ! 420: ty2->td.fConstant = false; ! 421: PushVar(adr2, ty2); ! 422: } ! 423: else if (tq == tqArray) { ! 424: PushVar(adr2, ty2); /* array is pointer to itself */ ! 425: } ! 426: else { ! 427: PushVar(val2, ty2); ! 428: } /* if */ ! 429: break; ! 430: case tkInside: ! 431: adrShort = adr2; ! 432: ipd = IpdFAdr(adrShort); ! 433: val2 = (vpc >= vrgPd[ipd].adrStart) ! 434: AND (vpc < vrgPd[ipd+1].adrStart); ! 435: PushVar(val2, vtyCnInt); ! 436: break; ! 437: case tkSizeof: ! 438: val2 = CbFTy(ty2); ! 439: PushVar(val2, vtyCnInt); ! 440: break; ! 441: } /* switch */ ! 442: if (fDidIt) /* we must have done one of them - go back */ ! 443: return(psVar); ! 444: ! 445: /* not unary, so we pop another and try the binaries */ ! 446: if (!FPopVar(&adr1, ty1)) ! 447: return(psFail); ! 448: val1 = ValFAdr(adr1, ty1); ! 449: ! 450: fDidIt = true; ! 451: switch (tk) { ! 452: default: ! 453: fDidIt = false; ! 454: break; ! 455: case tkDot: ! 456: val1 = adr1; /* direct address, then do ptr */ ! 457: case tkPtr: ! 458: val1 = AdrFField(val1, ty1, ty2); ! 459: /* ty1 is struct, ty2 is field */ ! 460: PushVar(val1, ty2); ! 461: break; ! 462: case tkIndex: /* foo[x] */ ! 463: tq = TqFTy(ty1, 1); ! 464: if (tq == tqArray) ! 465: val1 = adr1; /* array value IS the address */ ! 466: FAdjTd(ty1, tqNil);/* remove ptr or array level */ ! 467: adr1 = val1 + (val2 * CbFTy(ty1)); ! 468: PushVar(adr1, ty1); ! 469: break; ! 470: ! 471: } /* switch */ ! 472: if (fDidIt) ! 473: return(psVar); ! 474: ! 475: /* MaxFTyTy may try to do too much. It first determines if the types ! 476: * are such that integer operators may be applied to them (and returns ! 477: * a true/false on this) If so, it copies into tyMax the ty of the ! 478: * larger of the two operands. ! 479: */ ! 480: fDoIntOp = MaxFTyTy(tyMax, ty1, ty2); ! 481: if ( (!fDoIntOp) ! 482: AND (tk != tkPtr) ! 483: AND (tk != tkDot) ! 484: AND (tk != tkAssign) ) { ! 485: /* they are trying something stupid, like adding structures together */ ! 486: UError("Cannot allow that combination of operand(s) and operator"); ! 487: } /* if */ ! 488: ! 489: tyMax->td.fConstant = true; /* any op that DOESN'T want this turns it off */ ! 490: tyMax->td.st = stValue; ! 491: /* binary operators */ ! 492: fDidIt = true; ! 493: switch (tk) { ! 494: default: ! 495: fDidIt = false; ! 496: break; ! 497: case tkDiv: ! 498: val1 = val1 / val2; ! 499: break; ! 500: case tkMul: ! 501: val1 = val1 * val2; ! 502: break; ! 503: case tkPlus: ! 504: val1 = val1 + val2; ! 505: break; ! 506: case tkMinus: ! 507: val1 = val1 - val2; ! 508: break; ! 509: case tkBitAnd: ! 510: val1 = val1 & val2; ! 511: break; ! 512: case tkXOR: ! 513: val1 = val1 ^ val2; ! 514: break; ! 515: case tkBitOr: ! 516: val1 = val1 | val2; ! 517: break; ! 518: } /* switch */ ! 519: if (fDidIt) { ! 520: PushVar(val1, tyMax); ! 521: return(psVar); ! 522: } /* if */ ! 523: ! 524: fDidIt = true; ! 525: ty = vtyCnInt; ! 526: switch (tk) { ! 527: default: ! 528: fDidIt = false; ! 529: break; ! 530: case tkLT: ! 531: val1 = val1 < val2; ! 532: break; ! 533: case tkLE: ! 534: val1 = val1 <= val2; ! 535: break; ! 536: case tkGT: ! 537: val1 = val1 > val2; ! 538: break; ! 539: case tkGE: ! 540: val1 = val1 >= val2; ! 541: break; ! 542: case tkEqual: ! 543: val1 = val1 == val2; ! 544: break; ! 545: case tkNotEqual: ! 546: val1 = val1 != val2; ! 547: break; ! 548: case tkLAND: ! 549: val1 = val1 && val2; ! 550: break; ! 551: case tkLOR: ! 552: val1 = val1 || val2; ! 553: break; ! 554: case tkLShift: ! 555: if (ty1->td.bt == btShort) { ! 556: /* we do this to crop it to 16 bits */ ! 557: stuff.lng = val1; ! 558: val1 = stuff.shorts.shortLo << val2; ! 559: } ! 560: else { ! 561: val1 = val1 << val2; ! 562: ty = vtyCnLong; ! 563: } /* if */ ! 564: break; ! 565: case tkRShift: ! 566: if (ty1->td.bt == btShort) { ! 567: /* we do this to crop it to 16 bits */ ! 568: stuff.lng = val1; ! 569: val1 = stuff.shorts.shortLo >> val2; ! 570: } ! 571: else { ! 572: val1 = val1 >> val2; ! 573: ty = vtyCnLong; ! 574: } /* if */ ! 575: break; ! 576: } /* switch */ ! 577: if (fDidIt) { ! 578: PushVar(val1, ty); ! 579: return(psVar); ! 580: } /* if */ ! 581: ! 582: if (tk != tkAssign) ! 583: UError("Unknown operator"); ! 584: ! 585: cb1 = CbFTy(ty1); ! 586: if (cb1 <= CBLONG) { ! 587: PutVal(adr1, ty1, val2); ! 588: } ! 589: else { ! 590: cb2 = CbFTy(ty2); ! 591: if (cb1 >= cbAssMax) ! 592: Panic("Too many bytes (> %d) moved in assignment", cbAssMax); ! 593: /* we transfer cb1 bytes, just to be safe */ ! 594: adrShort = adr2; ! 595: GetBlock(adrShort, spaceData, (ADRT)buf, cb1); ! 596: adrShort = adr1; ! 597: PutBlock(adrShort, spaceData, (ADRT)buf, cb1); ! 598: if (cb1 != cb2) { ! 599: printf("WARNING: X=Y: X is %d bytes and Y is %d bytes\n", ! 600: cb1, cb2); ! 601: printf(" Moving %d bytes\n", cb1); ! 602: } /* if */ ! 603: } /* if */ ! 604: PushVar(adr1, ty1); /* leave dest on stack, too */ ! 605: return(psVar); ! 606: } /* PsFDoOp */ ! 607: ! 608: ! 609: /* P S F O P E R A T O R */ ! 610: ! 611: local PSE PsFOperator(tk, ps) ! 612: TKE tk; ! 613: PSE ps; ! 614: { ! 615: /* this routine implements the precedence rules */ ! 616: int prec; ! 617: TKE tkStop, tkNew; ! 618: long adr; ! 619: TYR rgTy[cTyMax]; ! 620: ! 621: prec = PrecFTk(tk); ! 622: if (prec == 0) ! 623: Panic("Bad token in PsFOperator - [%d]", tk); ! 624: ! 625: if (ps == psOp) { ! 626: /* this had better be a unary operator */ ! 627: switch (tk) { ! 628: case tkSizeof: ! 629: case tkInside: ! 630: case tkBang: ! 631: case tkTilda: ! 632: case tkBOE: ! 633: case tkLP: ! 634: PushOp(tk); ! 635: break; ! 636: /* these next ones map to something else */ ! 637: case tkAmper: ! 638: PushOp(tkRef); ! 639: break; ! 640: case tkStar: ! 641: PushOp(tkDeref); ! 642: break; ! 643: case tkMinus: ! 644: PushOp(tkUMinus); ! 645: break; ! 646: case tkPlus: /* ignore it */ ! 647: break; ! 648: default: ! 649: UError("Two operators in a row??"); ! 650: } /* switch */ ! 651: return(psOp); ! 652: } /* if */ ! 653: ! 654: tkStop = tkNil; ! 655: switch (tk) { /* set our stop token for [], (), and (x,y,z) */ ! 656: case tkEOE: ! 657: tkStop = tkBOE; ! 658: break; ! 659: case tkRSB: ! 660: tkStop = tkLSB; ! 661: break; ! 662: case tkComma: ! 663: case tkRP: ! 664: tkStop = tkLP; ! 665: break; ! 666: } /* switch */ ! 667: ! 668: /* first process all higher precedence operators */ ! 669: while (prec <= PrecFTk(TOPOP)) { ! 670: if (TOPOP == tkStop) { ! 671: PopOp(); /* eat top op */ ! 672: return(psVar); /* by definition, "(x+y)" is a var */ ! 673: } ! 674: else if (PrecFTk(TOPOP) == precParen) { ! 675: break; /* we pretend it is higher precedence than the paren */ ! 676: } /* if */ ! 677: if (PsFDoOp() == psFail) { ! 678: switch (tk) { ! 679: case tkRSB: ! 680: UError("Missing '['"); ! 681: case tkRP: ! 682: UError("Missing '('"); ! 683: case tkComma: ! 684: UError("Bad procedure call"); ! 685: default: ! 686: UError("Badly formed expression"); ! 687: } /* switch */ ! 688: } /* if */ ! 689: } /* while */ ! 690: ! 691: tkNew = tkNil; ! 692: switch (tk) { ! 693: case tkAssPlus: ! 694: tkNew = tkPlus; ! 695: break; ! 696: case tkAssMinus: ! 697: tkNew = tkMinus; ! 698: break; ! 699: case tkAssMult: ! 700: tkNew = tkMul; ! 701: break; ! 702: case tkAssDiv: ! 703: tkNew = tkDiv; ! 704: break; ! 705: case tkAssXOR: ! 706: tkNew = tkXOR; ! 707: break; ! 708: case tkAssBAND: ! 709: tkNew = tkBitAnd; ! 710: break; ! 711: case tkAssBOR: ! 712: tkNew = tkBitOr; ! 713: break; ! 714: case tkAssLeft: ! 715: tkNew = tkLShift; ! 716: break; ! 717: case tkAssRight: ! 718: tkNew = tkRShift; ! 719: break; ! 720: case tkAssMod: ! 721: tkNew = tkModulo; ! 722: break; ! 723: } /* switch */ ! 724: if (tkNew != tkNil) { ! 725: /* this is an 'assign with function' op e.g. *= or += */ ! 726: /* replicate the top of the variable stack */ ! 727: if (!FPopVar(&adr, rgTy)) ! 728: UError("Bad Syntax"); ! 729: PushVar(adr, rgTy); ! 730: PushVar(adr, rgTy); ! 731: PushOp(tkAssign); ! 732: tk = tkNew; ! 733: } /* if */ ! 734: ! 735: PushOp(tk); ! 736: if (tk == tkLSB) ! 737: PushOp(tkIndex); /* we push the tkLSB and then the tkIndex */ ! 738: return(psOp); ! 739: } /* PsFOperator */ ! 740: ! 741: ! 742: /* T K F O P E R A N D */ ! 743: ! 744: export TKE TkFOperand() ! 745: { ! 746: int iln, ifd, ipd, cnt; ! 747: short valShort; ! 748: char sbFloat[30]; ! 749: long val; ! 750: TKE tk; ! 751: ADRT adr, fp, ap; ! 752: TYR ty[cTyMax]; ! 753: STUFFU stuff; ! 754: ! 755: /* look at the current token and figure out what the hell it is */ ! 756: /* successful cases fall out bottom and return tkAdr */ ! 757: switch (vtk) { ! 758: default: ! 759: return(tkNil); /* nothing of interest */ ! 760: case tkDot: ! 761: PushVar(vdot, vtyDot); ! 762: break; ! 763: case tkColon: /* they want us to search ONLY global space */ ! 764: tk = TkNext(); ! 765: if (tk != tkStr) ! 766: UError("Misformed global name"); ! 767: if ((adr = AdrFGlobal(vsbTok, ty)) == adrNil) ! 768: UError("Unknown global - %s", vsbTok); ! 769: PushVar(lengthen(adr), ty); ! 770: break; ! 771: case tkCharConstant: ! 772: CopyTy(ty, vtyCnChar); ! 773: val = vsbTok[0]; ! 774: PushVar(val, ty); ! 775: break; ! 776: case tkStrConstant: ! 777: adr = AdrFStore(vsbTok, vcbTok+1); ! 778: CopyTy(ty, vtyCnChar); /* it is a constant */ ! 779: FAdjTd(ty, tqPtr); /* this makes it a 'char *' */ ! 780: PushVar(lengthen(adr), ty); ! 781: break; ! 782: case tkNumber: ! 783: if (vsbTok[0] == '0') { ! 784: if (vsbTok[1] == 'x') ! 785: sscanf((vsbTok+2), "%X", &val); ! 786: else sscanf(vsbTok, "%O", &val); ! 787: } ! 788: else { ! 789: tk = TkPeek(); ! 790: if (tk == tkDot) { ! 791: /* looks like a float constant */ ! 792: strcpy(sbFloat, vsbTok); ! 793: TkNext(); /* eat the dot */ ! 794: strcat(sbFloat, "."); ! 795: /* we allow them to say "10." instead of "10.0" */ ! 796: if (tkNumber == TkPeek()) { ! 797: TkNext(); /* actually get the number */ ! 798: strcat(sbFloat, vsbTok); /* get fractional part */ ! 799: } /* if */ ! 800: stuff.fl = atof(sbFloat); ! 801: PushVar(stuff.lng, vtyCnFloat); /* sorta kludgey */ ! 802: return(tkNumber); ! 803: } ! 804: else { ! 805: val = atol(vsbTok); ! 806: } /* if */ ! 807: } /* if */ ! 808: ! 809: TkPeek(); ! 810: /* did they specify long? */ ! 811: if ((vcbPeek == 1) ! 812: AND (vsbTokPeek[0] == 'L' OR vsbTokPeek[0] == 'l')) { ! 813: TkNext(); /* actually eat the L or l */ ! 814: PushVar(val, vtyCnLong); ! 815: } ! 816: else { ! 817: valShort = val & 0x0000ffff; ! 818: PushVar(val, (val==valShort) ? vtyCnInt : vtyCnLong); ! 819: } ! 820: return(tkNumber); ! 821: /* NOTREACHED */ ! 822: break; ! 823: case tkStr: ! 824: if ((TOPOP == tkDot) OR (TOPOP == tkPtr)) { ! 825: /* we don't do anything until we PROCESS the field. ! 826: * so we jam the name in a record. ! 827: */ ! 828: ty[0] = *vtyZeros; ! 829: ty[1] = *vtyZeros; ! 830: #ifdef BSD41 ! 831: ty[0].sbVar = SbSafe(vsbTok); ! 832: #else ! 833: strncpy(ty[0].sbVar, vsbTok, cbVarMax); ! 834: #endif ! 835: ty[0].td.fConstant = true; ! 836: ty[0].td.st = stStruct; ! 837: PushVar(0L, ty); ! 838: return(psVar); ! 839: } /* if */ ! 840: ! 841: /* is it a register or Special variable? */ ! 842: if (vsbTok[0] == '$') { ! 843: if (FAdrFSpecial(vsbTok, ty, &adr)) { ! 844: PushVar(lengthen(adr), ty); ! 845: break; ! 846: } /* if */ ! 847: UError("Unknown special variable `%s'", vsbTok); ! 848: } /* if */ ! 849: ! 850: /* is it a local? */ ! 851: if ((vipd != ipdNil) ! 852: AND ((adr=AdrFLocal(vipd, -1, vsbTok, ty)) != adrNil)) { ! 853: PushVar(lengthen(adr), ty); ! 854: break; ! 855: } /* if */ ! 856: ! 857: /* is it a global? */ ! 858: if ((adr = AdrFGlobal(vsbTok, ty)) != adrNil) { ! 859: PushVar(lengthen(adr), ty); ! 860: break; ! 861: } /* if */ ! 862: ! 863: /* is it a procedure name? */ ! 864: if ((ipd = IpdFName(vsbTok)) != ipdNil) { ! 865: /* it is a procedure name! is there anymore to the name? */ ! 866: tk = TkPeek(); ! 867: if (tk == tkDot) { ! 868: /* so far we know `procname.' */ ! 869: TkNext(); /* eat dot */ ! 870: /* we want full name of a local */ ! 871: FpApFIpd(&fp, &ap, ipd, -1); ! 872: if (fp == 0) ! 873: UError("procedure %s not active",vrgPd[ipd].sbProc); ! 874: tk = TkNext(); ! 875: cnt = -1; /* default - take first instance */ ! 876: if (tk == tkNumber) { ! 877: /* we have `proc.3' (or something like that). ! 878: * they want a SPECIFIC instance of this proc ! 879: * at backtrace location #. ! 880: * This is useful for recursive procedures... ! 881: */ ! 882: cnt = atoi(vsbTok); ! 883: if (TkNext() != tkDot) ! 884: UError("Need a `.' after the number"); ! 885: ; ! 886: tk = TkNext(); ! 887: } /* if */ ! 888: if (tk != tkStr) { ! 889: /* procname.???? */ ! 890: UError("Syntax error - bad local name '%s'",vsbTok); ! 891: } /* if */ ! 892: if ((adr = AdrFLocal(ipd,cnt,vsbTok,ty)) ! 893: != adrNil) { ! 894: PushVar(lengthen(adr), ty); ! 895: return(tkAdr); ! 896: } ! 897: else { ! 898: UError("No such local - %s.%s", ! 899: vrgPd[ipd].sbProc, vsbTok); ! 900: } /* if */ ! 901: } ! 902: else if (tk == tkLP) { ! 903: /* we have `procname(' - must be a procedure call */ ! 904: TkNext(); /* eat ( */ ! 905: val = DoProc(ipd, ty, adrNil); ! 906: PushVar(val, ty); ! 907: break; ! 908: } ! 909: else if (tk == tkHash) { ! 910: TkNext(); /* eat the # */ ! 911: tk = TkNext(); ! 912: if (tk != tkNumber) ! 913: UError("'#' should be followed by a decimal line number."); ! 914: iln = atoi(vsbTok); ! 915: ifd = IfdFIpd(ipd); ! 916: adr = AdrFIfdLn(ifd, iln); /* get adr of this line */ ! 917: PushVar(lengthen(adr), vtyCnInt); ! 918: } ! 919: else { ! 920: /* proc name followed by ???, give proc adr and type */ ! 921: TyFLocal(ty, vrgPd[ipd].sbProc, vrgPd[ipd].isym); ! 922: PushVar(lengthen(vrgPd[ipd].adrStart), ty); ! 923: } /* if */ ! 924: } ! 925: else if ((adr=AdrFLabel(vsbTok)) != adrNil) { ! 926: /* it is a label */ ! 927: TkPeek(); ! 928: if (vtkPeek == tkLP) { ! 929: /* we have `label(' - must be a procedure call */ ! 930: TkNext(); /* eat ( */ ! 931: val = DoProc(ipdNil, ty, adr); ! 932: PushVar(val, ty); ! 933: } ! 934: else { ! 935: PushVar(lengthen(adr), vtyCnInt); ! 936: } ! 937: } ! 938: else { ! 939: /* don't what it is, it is NOT something we can handle! */ ! 940: return(tkNil); ! 941: } /* if */ ! 942: break; ! 943: } /* switch */ ! 944: return(tkAdr); ! 945: } /* TkFOperand */ ! 946: ! 947: ! 948: /* T K F E X P R */ ! 949: ! 950: export TKE TkFExpr(pret, ty) ! 951: long *pret; ! 952: pTYR ty; ! 953: { ! 954: int cbTemp; ! 955: PSE ps; ! 956: TKE tk, tkRet, tkTemp; ! 957: char *sbCmdTemp, sbTokTemp[50]; ! 958: ! 959: if (vtk == tkNil) { ! 960: *pret = 0; ! 961: return(tkNil); ! 962: } /* if */ ! 963: ! 964: /* save the token state in case we think it is garbage */ ! 965: cbTemp = vcbTok; ! 966: sbCmdTemp = vsbCmd; ! 967: tk = tkTemp = vtk; ! 968: ps = psOp; ! 969: strcpy(sbTokTemp, vsbTok); ! 970: ! 971: PushOp(tkBOE); /* push a {ning-of-expression onto the stack */ ! 972: ! 973: /* we do a little dance here to see if we have a pure number */ ! 974: tkRet = TkFOperand(); ! 975: if (tkRet != tkNil) { ! 976: ps = psVar; ! 977: tk = TkNext(); ! 978: if ((tkRet == tkNumber) AND (PrecFTk(tk)==0)) { ! 979: tk = PopOp(); /* eat the BOE */ ! 980: FPopVar(pret, ty); ! 981: return(tkNumber); ! 982: } /* if */ ! 983: } ! 984: else if (PrecFTk(tk) == 0) { ! 985: /* it is neither an operator nor an operand */ ! 986: goto bombout; ! 987: } /* if */ ! 988: ! 989: if (tk == tkComma) { ! 990: PushOp(tkLP); /* makes procedure call code easier */ ! 991: tk = TkNext(); ! 992: } /* if */ ! 993: ! 994: while (tk != tkNil) { ! 995: if ( (PrecFTk(tk) != 0) ! 996: AND ((tk != tkDot) OR (ps == psVar)) ) { ! 997: /* it is an operator */ ! 998: ps = PsFOperator(tk, ps); ! 999: if (ps == psFail) ! 1000: goto bombout; ! 1001: if (tk == tkComma) ! 1002: break; ! 1003: } ! 1004: else { ! 1005: /* it's not an operator, is it an OPERAND?? */ ! 1006: tk = TkFOperand(); ! 1007: if (tk == tkNil) { ! 1008: ps = psFail; ! 1009: break; /* not operand - fall out of loop and see what happens */ ! 1010: } /* if */ ! 1011: ps = psVar; /* yup, it was an operand - and it's on the stack */ ! 1012: } /* if */ ! 1013: tk = TkNext(); ! 1014: } /* while */ ! 1015: ! 1016: /* one way or the other, someone thinks we might be done, try it and see */ ! 1017: if (psFail != PsFOperator(tkEOE, ps)) { ! 1018: FPopVar(pret, ty); /* put final stuff in return variables */ ! 1019: return(tkAdr); ! 1020: } /* if */ ! 1021: ! 1022: bombout: ! 1023: /* something ain't right - reset the universe */ ! 1024: vcbTok = cbTemp; ! 1025: vsbCmd = sbCmdTemp; ! 1026: vtk = tkTemp; ! 1027: strcpy(vsbTok, sbTokTemp); ! 1028: vivarMac = 0; /* stack pointer cleanup */ ! 1029: viopMac = 0; ! 1030: return(tkNil); ! 1031: } /* TkFExpr */ ! 1032: ! 1033: ! 1034: /* G E T E X P R */ ! 1035: ! 1036: export long GetExpr(pty, tk) ! 1037: pTYR *pty; ! 1038: TKE tk; ! 1039: { ! 1040: long adrLong, i; ! 1041: static TYR ty[cTyMax]; ! 1042: /* ty is used for callers to GetExp who don't want to be bothered ! 1043: * with allocating an ty. ! 1044: * NOTE(!): if they want this info for more than a statement or two, ! 1045: * they MUST copy it someplace else!!! ! 1046: */ ! 1047: ! 1048: if (tk == tkNil) ! 1049: TkNext(); ! 1050: if (TkFExpr(&adrLong, ty) != tkNil) { ! 1051: i = ValFAdr(adrLong, ty); ! 1052: *pty = ty; ! 1053: } ! 1054: else { ! 1055: *pty = tyNil; ! 1056: } /* if */ ! 1057: return(i); ! 1058: } /* GetExpr */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.