|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include <assert.h> ! 3: #include "bc.h" ! 4: ! 5: ! 6: /* ! 7: * Gerror is used by the various grammar actions when a ! 8: * semantic error is discoverd. It simply prints out a ! 9: * message and sets allok to FALSE. ! 10: * It is also called by yyerror to report syntax errors. ! 11: * It is also called by lexerror to report lexical errors. ! 12: * Allok, errors, and any partially defined function or statement ! 13: * will be cleared at the end of the line, except for the ! 14: * too much code error which clears at the end of the function ! 15: * or statement which has grown too large. ! 16: */ ! 17: ! 18: gerror(str) ! 19: char *str; ! 20: { ! 21: if (allok == TRUE) { ! 22: if (infnam != NULL) ! 23: fprintf(stderr, "%s: ", infnam); ! 24: if (inline != 0) ! 25: fprintf(stderr, "%d: ", inline); ! 26: fprintf(stderr, "%r\n", &str); ! 27: allok = FALSE; ! 28: } ! 29: } ! 30: ! 31: /* ! 32: * Chktype verifies that the type of `var' will work in sload, aeload, ! 33: * or arload. Otherwise it emits an error and returns zero so the ! 34: * grammar action can abort the parse. ! 35: */ ! 36: chktype(var, type) ! 37: register dicent *var; ! 38: register int type; ! 39: { ! 40: if (var->localt == type) ! 41: return 1; ! 42: else if (var->localt == UNDEFINED) ! 43: if (var->globalt == type || var->globalt == UNDEFINED) ! 44: return 1; ! 45: else ! 46: gerror("'%s' is wrong global type", var->word); ! 47: else ! 48: gerror("'%s' is wrong local type", var->word); ! 49: return 0; ! 50: } ! 51: ! 52: /* ! 53: * Sload emits the code to load the scalar with dictionary entry ! 54: * var. ! 55: */ ! 56: ! 57: sload(var) ! 58: register dicent *var; ! 59: { ! 60: switch (var->localt) { ! 61: case SCALAR: ! 62: emitop(PLOSC); ! 63: emitcnt(var->localv); ! 64: break; ! 65: case UNDEFINED: ! 66: switch (var->globalt) { ! 67: case UNDEFINED: ! 68: var->globalt = SCALAR; ! 69: newscalar(&var->globalv.rvalue); ! 70: /* fall thru */ ! 71: case SCALAR: ! 72: emitop(PGLSC); ! 73: emitnum(&var->globalv.rvalue); ! 74: break; ! 75: } ! 76: } ! 77: } ! 78: ! 79: ! 80: /* ! 81: * Aeload emits the code to load the array element with dictionary ! 82: * entry var. ! 83: */ ! 84: ! 85: aeload(var) ! 86: register dicent *var; ! 87: { ! 88: switch (var->localt) { ! 89: case ARRAY: ! 90: emitop(PLOAE); ! 91: emitcnt(var->localv); ! 92: break; ! 93: case UNDEFINED: ! 94: switch (var->globalt) { ! 95: case UNDEFINED: ! 96: var->globalt = ARRAY; ! 97: newarray(&var->globalv.arvalue); ! 98: /* fall thru */ ! 99: case ARRAY: ! 100: emitop(PGLAE); ! 101: emitarry(&var->globalv.arvalue); ! 102: break; ! 103: } ! 104: } ! 105: } ! 106: ! 107: ! 108: /* ! 109: * Arload emits the code to load the whole array with dictionary ! 110: * entry var. ! 111: */ ! 112: ! 113: arload(var) ! 114: register dicent *var; ! 115: { ! 116: switch (var->localt) { ! 117: case ARRAY: ! 118: emitop(PLOAR); ! 119: emitcnt(var->localv); ! 120: break; ! 121: case UNDEFINED: ! 122: switch (var->globalt) { ! 123: case UNDEFINED: ! 124: var->globalt = ARRAY; ! 125: newarray(&var->globalv.arvalue); ! 126: /* fall thru */ ! 127: case ARRAY: ! 128: emitop(PGLAR); ! 129: emitarry(&var->globalv.arvalue); ! 130: break; ! 131: } ! 132: } ! 133: } ! 134: ! 135: ! 136: /* ! 137: * If there is room for another code item, incloc advances loc ! 138: * and returns the old loc. If not then incloc calls gerror. ! 139: * Note that both the value returned by incloc and loc itself ! 140: * always point to a location in cstream. ! 141: */ ! 142: ! 143: code * ! 144: incloc() ! 145: { ! 146: register code *res; ! 147: ! 148: res = loc++; ! 149: if (res >= &cstream[MAXCODE - 1]) { ! 150: loc = res; ! 151: gerror("Too much code"); ! 152: } ! 153: return (res); ! 154: } ! 155: ! 156: ! 157: /* ! 158: * Negate returns the opcode which branches on the opposite ! 159: * condition of when `op' branches. ! 160: */ ! 161: ! 162: opcode ! 163: negate(op) ! 164: opcode op; ! 165: { ! 166: switch (op) { ! 167: case BRALW: ! 168: return (BRNEV); ! 169: case BRNEV: ! 170: return (BRALW); ! 171: case BRLT: ! 172: return (BRGE); ! 173: case BRLE: ! 174: return (BRGT); ! 175: case BREQ: ! 176: return (BRNE); ! 177: case BRGE: ! 178: return (BRLT); ! 179: case BRGT: ! 180: return (BRLE); ! 181: case BRNE: ! 182: return (BREQ); ! 183: } ! 184: assert(FALSE); ! 185: } ! 186: ! 187: ! 188: /* ! 189: * Locaddr sets the local addresses (ie frame pointer offsets) for ! 190: * all local variables and parameters. `vec' is an array of `len' ! 191: * pointers to dictionary entries and `base' is the frame offset ! 192: * of the first entry. ! 193: * Note that locaddr assumes that it is never called with len zero. ! 194: */ ! 195: ! 196: locaddr(vec, len, base) ! 197: register dicent *vec[]; ! 198: register int len, ! 199: base; ! 200: { ! 201: do { ! 202: (*vec++)->localv = base++; ! 203: } while (--len > 0); ! 204: } ! 205: ! 206: ! 207: /* ! 208: * Chkfunc checks to make sure that the identifier with dictionary ! 209: * entry pointed to by `dicp' can be used as a function. If it ! 210: * is not already a function, then the body and types fields of the ! 211: * func value are set to NULL. ! 212: */ ! 213: ! 214: chkfunc(dicp) ! 215: register dicent *dicp; ! 216: { ! 217: if (dicp->globalt == FUNCTION) ! 218: return 1; ! 219: if (dicp->globalt == UNDEFINED) { ! 220: dicp->globalt = FUNCTION; ! 221: dicp->globalv.fvalue.fcsize = 0; ! 222: dicp->globalv.fvalue.body = dicp->globalv.fvalue.types = NULL; ! 223: return 1; ! 224: } ! 225: gerror("'%s' is not a function", dicp->word); ! 226: return 0; ! 227: } ! 228: ! 229: /* ! 230: * Install installs the definition of the function `fnc'. ! 231: * `pvec' and `lpvec' (`avec' and `lavec') are the vector ! 232: * of formal parameters (respectively automatic variables) ! 233: * and its length. ! 234: */ ! 235: ! 236: install(fnc, pvec, lpvec, avec, lavec) ! 237: register func *fnc; ! 238: dicent **pvec, ! 239: **avec; ! 240: int lpvec, ! 241: lavec; ! 242: { ! 243: int csize; ! 244: ! 245: litfree(fnc->body, fnc->body+fnc->fcsize); ! 246: mpfree(fnc->body); ! 247: mpfree(fnc->types); ! 248: fnc->nparams = lpvec; ! 249: fnc->nautos = lavec; ! 250: if (lpvec + lavec == 0) ! 251: fnc->types = NULL; ! 252: else { ! 253: fnc->types = (type *)mpalc((lpvec + lavec) * sizeof (type)); ! 254: copylty(pvec, fnc->types, lpvec); ! 255: copylty(avec, &fnc->types[lpvec], lavec); ! 256: } ! 257: fnc->fcsize = loc - cstream; ! 258: csize = fnc->fcsize * sizeof (code); ! 259: fnc->body = (code *)mpalc(csize); ! 260: copy((char *)cstream, (char *)fnc->body, csize); ! 261: remloc(pvec, lpvec); ! 262: remloc(avec, lavec); ! 263: } ! 264: ! 265: /* ! 266: * Copylty copyies the local types from the dictionary vector ! 267: * `dvec' to the type vector `tvec'. `len' is the number of ! 268: * entries to copy. ! 269: */ ! 270: ! 271: copylty(dvec, tvec, len) ! 272: register dicent *dvec[]; ! 273: register type tvec[]; ! 274: register int len; ! 275: { ! 276: while (--len >= 0) ! 277: *tvec++ = (*dvec++)->localt; ! 278: } ! 279: ! 280: ! 281: /* ! 282: * Copy copyies the block of bytes at `from' to that at `to'. ! 283: * `len' is the number of bytes to copy. Note that these ! 284: * blocks should not overlap. ! 285: */ ! 286: ! 287: copy(from, to, len) ! 288: register char *from, ! 289: *to; ! 290: register int len; ! 291: { ! 292: while (--len >= 0) ! 293: *to++ = *from++; ! 294: } ! 295: ! 296: /* ! 297: * Remloc is used to remove the local types from the dictionary ! 298: * vector `dvec'. `len' is the length of the vector. ! 299: */ ! 300: ! 301: remloc(dvec, len) ! 302: register dicent **dvec; ! 303: register int len; ! 304: { ! 305: while (--len >= 0) ! 306: (*dvec++)->localt = UNDEFINED; ! 307: } ! 308: ! 309: /* ! 310: * Litfree recovers literal and string storage from bp to ep. ! 311: * Called after interp() on cstream to loc, ! 312: * after function definition abort on cstream to loc, ! 313: * during function redefinition on the old body. ! 314: */ ! 315: litfree(pc, end) register code *pc, *end; ! 316: { ! 317: register int op; ! 318: while (pc < end) { ! 319: op = pc++->opcode; ! 320: if (pc >= end) ! 321: break; ! 322: switch (op) { ! 323: case BRNEV: /* Why by two? */ ! 324: printf("BRNEV in litfree\n"); ! 325: case CALL: ! 326: ++pc; ! 327: case PGLSC: ! 328: case PLOSC: ! 329: case PGLAE: ! 330: case PLOAE: ! 331: case PGLAR: ! 332: case PLOAR: ! 333: case RETURN: ! 334: case BRALW: ! 335: case BRLT: ! 336: case BRLE: ! 337: case BREQ: ! 338: case BRGE: ! 339: case BRGT: ! 340: case BRNE: ! 341: ++pc; ! 342: case LOAD: ! 343: case LIBASE: ! 344: case LOBASE: ! 345: case LSCALE: ! 346: case STORE: ! 347: case SIBASE: ! 348: case SOBASE: ! 349: case SSCALE: ! 350: case POP: ! 351: case PRVAL: ! 352: case STOP: ! 353: case INC: ! 354: case DEC: ! 355: case PRNUM: ! 356: case PRNL: ! 357: case LENGTH: ! 358: case SCALE: ! 359: case SQRT: ! 360: case ADD: ! 361: case SUB: ! 362: case MUL: ! 363: case DIV: ! 364: case REM: ! 365: case EXP: ! 366: case NEG: ! 367: case EXIT: ! 368: break; ! 369: case PLISC: ! 370: mvfree(&pc->lvalue->mantissa); ! 371: mpfree(pc++->lvalue); ! 372: break; ! 373: case PRSTR: ! 374: mpfree(pc++->svalue); ! 375: break; ! 376: default: ! 377: fprintf(stderr, "Mixup in litfree\n"); ! 378: exit(1); ! 379: } ! 380: } ! 381: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.