1: # include <ingres.h> 2: # include <aux.h> 3: # include <symbol.h> 4: # include <tree.h> 5: # include <access.h> 6: # include "../decomp/globs.h" 7: # include <sccs.h> 8: # include <errors.h> 9: 10: SCCSID(@(#)interp.c 8.4 2/8/85) 11: 12: 13: 14: /* 15: ** 16: ** INTERPRET 17: ** 18: ** Processes the retrieved tuple from the De.ov_source relation 19: ** according to the symbols in the list. Recognition 20: ** of characteristic delimiters and separators initiates 21: ** action appropriate to a target list or qualification list 22: ** as the case may be. 23: ** 24: ** Between delimiters, the symbol list is expected to be in 25: ** Polish postfix form. A qualification list is further 26: ** expected to be in conjunctive normal form, with Boolean 27: ** operators infixed. 28: ** 29: */ 30: 31: 32: double pow(); 33: double sqrt(); 34: double log(); 35: double exp(); 36: double sin(); 37: double cos(); 38: double atan(); 39: 40: # define SPUSH(v) (++((struct stacksym *) v)) 41: # define SPOP(v) (((struct stacksym *) v)--) 42: 43: SYMBOL * 44: interpret(istlist,list) 45: int istlist; /* signals a target list: used for string substitution */ 46: SYMBOL **list; /* ptr to list of sym pointers */ 47: { 48: register SYMBOL *tos; 49: SYMBOL *op1,*op2; /*operands popped off stack*/ 50: register ANYTYPE *val1,*val2; /*ptrs to values of operands*/ 51: int opval, optype, l1; 52: char *s1; 53: int byflag; 54: long hitid; 55: extern char *Usercode; 56: extern ov_err(); 57: int cb_mark; 58: extern char *ov_ovqpbuf; 59: extern char *locv(); 60: int i; 61: 62: # ifdef xOTR1 63: if (tTf(72, 0)) 64: { 65: printf("INTERP: list=%x\n",list); 66: printf(" istlist = %d\n", istlist); 67: } 68: # endif 69: 70: 71: byflag = (list == De.ov_bylist); /* set byflag if aggregate function */ 72: tos = (SYMBOL *)(De.ov_stack-1); 73: /* reset the concat and ascii operator buffer */ 74: seterr(De.ov_ovqpbuf, CBUFULL, ov_err); 75: cb_mark = markbuf(De.ov_ovqpbuf); 76: 77: loop: 78: # ifdef xOTR1 79: if (tTf(72, 1) && tos >= (SYMBOL *) De.ov_stack) 80: { 81: printf("\ttops of stack="); 82: prstack(tos); /* print top of stack element */ 83: } 84: # endif 85: /* check for stack overflow */ 86: l1 = getsymbol(SPUSH(tos), &list); /* getsymbol changes the value of list */ 87: 88: if (l1) 89: { 90: 91: freebuf(De.ov_ovqpbuf, cb_mark); 92: return (tos); 93: } 94: optype = tos->type; 95: opval = tos->value.sym_data.i2type; 96: op1 = tos; 97: SPOP(tos); /* assume that stack will be popped */ 98: 99: switch(optype) 100: { 101: case CHAR: 102: /* do any chars have to be inserted? */ 103: if (istlist && (Patnum || Globnum)) 104: { 105: insert_chars(op1); 106: } 107: case INT: 108: case FLOAT: 109: SPUSH(tos); /* just leave symbol on stack */ 110: goto loop; 111: 112: case COP: 113: SPUSH(tos); /* new symbol goes on stack */ 114: tos->type = CHAR; 115: switch (opval) 116: { 117: 118: case opDBA: 119: tos->value.sym_data.cptype = Admin.adhdr.adowner; 120: tos->len = 2; 121: goto loop; 122: 123: case opUSERCODE: 124: tos->value.sym_data.cptype = Usercode; 125: tos->len = 2; 126: goto loop; 127: } 128: 129: case AND: /* if top value false return immediately */ 130: if (!tos->value.sym_data.i2type) 131: { 132: freebuf(De.ov_ovqpbuf, cb_mark); 133: return(tos); 134: } 135: else 136: SPOP(tos); 137: freebuf(De.ov_ovqpbuf, cb_mark); 138: goto loop; 139: 140: case OR: /* if top value is true then skip to 141: ** end of disjunction. */ 142: if (tos->value.sym_data.i2type) 143: { 144: SPUSH(tos); 145: do 146: { 147: getsymbol(tos, &list); /* getsymbol changes the value of list */ 148: } while (tos->type != AND); 149: optype = AND; 150: SPOP(tos); 151: } 152: SPOP(tos); 153: goto loop; 154: 155: case RESDOM: 156: freebuf(De.ov_ovqpbuf, cb_mark); /* init the concat and ascii buffer */ 157: if (De.ov_result) 158: { 159: if (opval) /* if gt zero then opval represents a real domain */ 160: { 161: if (byflag) 162: opval++; /* skip over count field for ag functs */ 163: rcvt(tos, De.ov_result->relfrmt[opval], De.ov_result->relfrml[opval]); 164: tout(tos, De.ov_outtup+De.ov_result->reloff[opval], De.ov_result->relfrml[opval]); 165: } 166: else /* opval refers to the tid and this is an update */ 167: { 168: De.ov_uptid = tos->value.sym_data.i4type; /* copy tid */ 169: if (De.de_qmode == mdREPL || (De.ov_diffrel && De.de_qmode == mdDEL && De.ov_result->reldum.relindxd > 0 )) 170: { 171: /* De.ov_origtup must be left with the orig 172: ** unaltered tuple, and De.ov_outtup must 173: ** be initialized with the orig tuple. 174: ** 175: ** De.ov_outtup only matters with REPL. 176: ** Scan() sets up De.ov_origtup so when 177: ** De.ov_source == De.ov_result, origtup is already 178: ** correct. 179: */ 180: 181: if (De.ov_diffrel) 182: { 183: if (l1 = get(De.ov_result, &De.ov_uptid, &hitid, De.ov_origtup, CURTUP)) 184: syserr("interp:get on resdom %s, %d", locv(De.ov_uptid), l1); 185: bmove(De.ov_origtup, De.ov_outtup, De.ov_result->reldum.relwid); 186: } 187: else 188: { 189: bmove(De.ov_intup, De.ov_outtup, De.ov_result->reldum.relwid); 190: } 191: } 192: } 193: } 194: else 195: { 196: /* 197: ** This is really here for the 68k machines, 198: ** this works on the VAX, but nowhere else... 199: */ 200: if ( tos->type == INT && tos->len == 1) 201: tos->value.sym_data.i1type = tos->value.sym_data.i2type; 202: if (Equel) 203: equelatt(tos); /* send attribute to equel */ 204: else 205: { 206: if (tos->type == CHAR) 207: s1 = tos->value.sym_data.cptype; 208: else 209: s1 = tos->value.sym_data.c0type; 210: printatt(tos->type, tos->len & I1MASK, s1); /* print attribute */ 211: } 212: } 213: SPOP(tos); 214: goto loop; 215: 216: 217: case BOP: 218: op2 = (SYMBOL *)SPOP(tos); 219: op1 = (SYMBOL *)tos; 220: typecheck(op1, op2, opval); 221: val1 = &op1->value.sym_data; 222: val2 = &op2->value.sym_data; 223: 224: switch (tos->type) 225: { 226: case INT: 227: switch (tos->len) 228: { 229: case 1: 230: case 2: 231: switch (opval) 232: { 233: case opADD: 234: val1->i2type += val2->i2type; 235: goto loop; 236: 237: case opSUB: 238: val1->i2type -= val2->i2type; 239: goto loop; 240: 241: case opMUL: 242: val1->i2type *= val2->i2type; 243: goto loop; 244: 245: case opDIV: 246: val1->i2type /= val2->i2type; 247: goto loop; 248: 249: case opMOD: 250: val1->i2type %= val2->i2type; 251: goto loop; 252: 253: case opPOW: 254: itof(op1); 255: itof(op2); 256: val1->f8type = pow(val1->f8type, val2->f8type); 257: goto loop; 258: 259: /* relational operator */ 260: default: 261: l1 = val1->i2type - val2->i2type; 262: val1->i2type = relop_interp(opval, l1); 263: goto loop; 264: } 265: 266: case 4: 267: switch(opval) 268: { 269: case opADD: 270: val1->i4type += val2->i4type; 271: goto loop; 272: 273: case opSUB: 274: val1->i4type -= val2->i4type; 275: goto loop; 276: 277: case opMUL: 278: val1->i4type *= val2->i4type; 279: goto loop; 280: 281: case opDIV: 282: val1->i4type /= val2->i4type; 283: goto loop; 284: 285: case opMOD: 286: val1->i4type %= val2->i4type; 287: goto loop; 288: 289: case opPOW: 290: itof(op1); 291: itof(op2); 292: val1->f8type = pow(val1->f8type, val2->f8type); 293: goto loop; 294: 295: /* relational operator */ 296: default: 297: tos->len = 2; 298: if (val1->i4type > val2->i4type) 299: l1 = 1; 300: else 301: if (val1->i4type == val2->i4type) 302: l1 = 0; 303: else 304: l1 = -1; 305: 306: val1->i2type = relop_interp(opval, l1); 307: goto loop; 308: 309: } 310: } 311: 312: case FLOAT: 313: switch (opval) 314: { 315: case opADD: 316: val1->f8type += val2->f8type; 317: goto loop; 318: 319: case opSUB: 320: val1->f8type -= val2->f8type; 321: goto loop; 322: 323: case opMUL: 324: val1->f8type *= val2->f8type; 325: goto loop; 326: 327: case opDIV: 328: val1->f8type /= val2->f8type; 329: goto loop; 330: 331: case opPOW: 332: val1->f8type = pow(val1->f8type, val2->f8type); 333: goto loop; 334: 335: default: 336: tos->type = INT; 337: tos->len = 2; 338: if (val1->f8type > val2->f8type) 339: l1 = 1; 340: else 341: if (val1->f8type == val2->f8type) 342: l1 = 0; 343: else 344: l1 = -1; 345: val1->i2type = relop_interp(opval, l1); 346: goto loop; 347: } 348: 349: case CHAR: 350: switch (opval) 351: { 352: case opSUB: 353: newstring(op1, op2); 354: goto loop; 355: case opADD: 356: case opCONCAT: 357: concatsym(op1, op2); /* concatenate the two symbols */ 358: goto loop; 359: default: 360: l1 = lexcomp(val1->cptype, size(op1), val2->cptype, op2->len & I1MASK,0); 361: tos->type = INT; 362: tos->len = 2; 363: val1->i2type = relop_interp(opval, l1); 364: goto loop; 365: } 366: } /* end of BOP */ 367: 368: case UOP: 369: val1 = &tos->value.sym_data; 370: switch (opval) 371: { 372: case opMINUS: 373: case opABS: 374: if (tos->type == CHAR) 375: ov_err(BADUOPC); 376: l1 = opval == opMINUS; 377: switch (tos->type) 378: { 379: case INT: 380: switch (tos->len) 381: { 382: case 1: 383: case 2: 384: if (l1 || val1->i2type < 0) 385: val1->i2type = -val1->i2type; 386: goto loop; 387: 388: case 4: 389: if (l1 || val1->i4type < 0) 390: val1->i4type = -val1->i4type; 391: goto loop; 392: } 393: 394: case FLOAT: 395: if (l1 || val1->f8type < 0.0) 396: val1->f8type = -val1->f8type; 397: goto loop; 398: } 399: 400: case opNOT: 401: val1->i2type = !val1->i2type; 402: case opPLUS: 403: if (tos->type == CHAR) 404: ov_err(BADUOPC); 405: goto loop; 406: 407: case opASCII: 408: ascii(tos); 409: goto loop; 410: 411: case opINT1: 412: typecoerce(tos, INT, 1); 413: goto loop; 414: 415: case opINT2: 416: typecoerce(tos, INT, 2); 417: goto loop; 418: 419: case opINT4: 420: typecoerce(tos, INT, 4); 421: goto loop; 422: 423: case opFLOAT4: 424: typecoerce(tos, FLOAT, 4); 425: goto loop; 426: 427: case opFLOAT8: 428: typecoerce(tos, FLOAT, 8); 429: goto loop; 430: 431: default: 432: if (tos->type == CHAR) 433: ov_err(BADUOPC); 434: if (tos->type == INT) 435: itof(tos); 436: switch (opval) 437: { 438: case opATAN: 439: val1->f8type = atan(val1->f8type); 440: goto loop; 441: 442: case opLOG: 443: val1->f8type = log(val1->f8type); 444: goto loop; 445: 446: case opSIN: 447: val1->f8type = sin(val1->f8type); 448: goto loop; 449: 450: case opCOS: 451: val1->f8type = cos(val1->f8type); 452: goto loop; 453: 454: case opSQRT: 455: val1->f8type = sqrt(val1->f8type); 456: goto loop; 457: 458: case opEXP: 459: val1->f8type = exp(val1->f8type); 460: goto loop; 461: 462: default: 463: syserr("interp:bad uop %d",opval); 464: } 465: } 466: 467: 468: case AOP: 469: aop_interp(opval, tos); 470: SPOP(tos); /* pop this symbol */ 471: goto loop; 472: 473: } 474: syserr("interp: fell out"); 475: /*NOTREACHED*/ 476: } 477: /* 478: ** relop_interp interprets the relational operators 479: ** (ie. EQ, NE etc.) and returns true or false 480: ** by evaluating l1. 481: ** 482: ** l1 should be greater than, equal or less than zero. 483: */ 484: 485: relop_interp(opval, l1) 486: int opval; 487: int l1; 488: { 489: register int i; 490: 491: i = l1; 492: 493: switch (opval) 494: { 495: 496: case opEQ: 497: return (i == 0); 498: 499: case opNE: 500: return (i != 0); 501: 502: case opLT: 503: return (i < 0); 504: 505: case opLE: 506: return (i <= 0); 507: 508: case opGT: 509: return (i > 0); 510: 511: case opGE: 512: return (i >= 0); 513: 514: default: 515: syserr("relop:bad relop or bop %d", opval); 516: } 517: /*NOTREACHED*/ 518: } 519: /* 520: ** Aggregate values are stored in De.ov_outtup. De.ov_tend points 521: ** to the spot for the next aggregate. Aop_interp() 522: ** computes the value for the aggregate and leaves 523: ** the result in the position pointed to by De.ov_tend. 524: */ 525: 526: aop_interp(opval, tos) 527: int opval; 528: register SYMBOL *tos; 529: { 530: register int i; 531: int l1; 532: ANYTYPE numb; /* used for type conversion */ 533: 534: bmove(De.ov_tend, (char *) &numb, 8); /* note: this assumes that there are always 8 bytes which can be moved. 535: ** if it moves beyond De.ov_tend, it's ok */ 536: switch (opval) 537: { 538: 539: case opSUMU: 540: case opSUM: 541: if (*De.ov_counter <= 1) 542: goto puta; 543: switch (tos->type) 544: { 545: case INT: 546: switch(tos->len) 547: { 548: case 1: 549: tos->value.sym_data.i2type += numb.i1type; 550: goto puta; 551: 552: case 2: 553: tos->value.sym_data.i2type += numb.i2type; 554: goto puta; 555: 556: case 4: 557: tos->value.sym_data.i4type += numb.i4type; 558: goto puta; 559: } 560: 561: case FLOAT: 562: if (tos->len == 4) 563: numb.f8type = numb.f4type; 564: tos->value.sym_data.f8type += numb.f8type; 565: goto puta; 566: 567: default: 568: ov_err(BADSUMC); /* cant sum char fields */ 569: } 570: 571: case opCOUNTU: 572: case opCOUNT: 573: tos->type = CNTTYPE; 574: tos->len = CNTLEN; 575: tos->value.sym_data.i4type = *De.ov_counter; 576: goto puta; 577: 578: case opANY: 579: tos->type = OANYTYPE; 580: tos->len = OANYLEN; 581: if (*De.ov_counter) 582: { 583: tos->value.sym_data.i2type = 1; 584: if (!De.ov_bylist && (De.ov_agcount == 1)) 585: De.ov_targvc = 0; /* if simple agg. stop scan */ 586: } 587: else 588: tos->value.sym_data.i2type = 0; 589: goto puta; 590: 591: case opMIN: 592: case opMAX: 593: if (*De.ov_counter<=1) 594: goto puta; 595: switch (tos->type) 596: { 597: case INT: 598: switch (tos->len) 599: { 600: case 1: 601: i = (tos->value.sym_data.i1type < numb.i1type); 602: break; 603: 604: case 2: 605: i = (tos->value.sym_data.i2type < numb.i2type); 606: break; 607: 608: case 4: 609: i = (tos->value.sym_data.i4type < numb.i4type); 610: break; 611: } 612: break; 613: 614: case FLOAT: 615: if (tos->len == 4) 616: numb.f8type = numb.f4type; 617: i = (tos->value.sym_data.f8type < numb.f8type); 618: break; 619: 620: case CHAR: 621: l1 = size(tos); 622: i = (lexcomp(tos->value.sym_data.cptype, l1, De.ov_tend, l1,0) < 0); 623: break; 624: 625: default: 626: syserr("interp:bad op type for opMIN/MAX %d", tos->type); 627: } 628: 629: /* check result of comparison */ 630: if (opval == opMAX) 631: i = !i; /* complement test for opMAX */ 632: if (i) 633: goto puta; /* condition true. new value */ 634: 635: /* condition false. Keep old value */ 636: goto done; 637: 638: 639: case opAVGU: 640: case opAVG: 641: if (tos->type == INT) 642: itof(tos); 643: else 644: if (tos->type == CHAR) 645: ov_err(BADAVG); 646: if (*De.ov_counter > 1) 647: { 648: tos->value.sym_data.f8type = numb.f8type + (tos->value.sym_data.f8type - numb.f8type) / *De.ov_counter; 649: } 650: tos->len = 8; 651: goto puta; 652: 653: default: 654: syserr("interp:bad agg op %d", tos->type); 655: } 656: 657: puta: 658: tout(tos, De.ov_tend, tos->len); 659: done: 660: De.ov_tend += tos->len & I1MASK; 661: }