|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include "ctype.h" ! 3: #include "typedef.h" ! 4: #include "basic.h" ! 5: ! 6: #define GCHDRSIZE (sizeof(struct strarea)) ! 7: #define TYPEMASK 017 ! 8: #define gchdr(p) ((struct strarea *)(p)) ! 9: ! 10: struct strarea { ! 11: unsigned x_len; ! 12: String *x_next; ! 13: }; ! 14: ! 15: static char *typenames[] = { ! 16: "", "integer", "real", "string", "", "function", "for", "gosub", ! 17: "any expression", "integer expression", "real expression", ! 18: "string expression", "", "", "", "" ! 19: }; ! 20: ! 21: double popfloat(); ! 22: Stkptr push(), pop(), nextframe(); ! 23: char *allocstr(); ! 24: ! 25: ! 26: /* ! 27: * push --- push frame pointed to by sp onto stack ! 28: */ ! 29: ! 30: Stkptr push(sp) ! 31: Stkptr sp; ! 32: { ! 33: register Stkptr p; ! 34: register char *s; ! 35: ! 36: p = sp; ! 37: s = stkptr - p->k_len; ! 38: if (s < stkbase) ! 39: err("stack overflow"); ! 40: if (tflg) { ! 41: register int i; ! 42: ! 43: fprintf(stderr, "push: type %d, length %d:", ! 44: p->k_type, p->k_len); ! 45: for (i = 0; i < p->k_len; ++i) ! 46: fprintf(stderr, " %o", ((char *)sp)[i]&0377); ! 47: putc('\n', stderr); ! 48: } ! 49: move(p->k_len, p, s); ! 50: stkptr = (char *)s; ! 51: return ((Stkptr)s); ! 52: } ! 53: ! 54: ! 55: /* ! 56: * clrstk --- reinitialize the stack pointer ! 57: */ ! 58: ! 59: clrstk() ! 60: { ! 61: stkptr = stktop; ! 62: *stkptr-- = 0; /* k_len = 0 */ ! 63: *stkptr = 0; /* k_type = 0 */ ! 64: restore(); ! 65: } ! 66: ! 67: ! 68: /* ! 69: * restore --- reset the DATA pointer to the beginning ! 70: */ ! 71: ! 72: restore() ! 73: { ! 74: ! 75: data.k_un.k_gosub.g_inptr = NULL; ! 76: data.k_un.k_gosub.g_curline = (Linep)lines; ! 77: } ! 78: ! 79: ! 80: /* ! 81: * pop --- pop the top frame off the stack and return a pointer to it; ! 82: * check that the frame is of the specified type ! 83: */ ! 84: ! 85: Stkptr pop(type) ! 86: { ! 87: register Stkptr s; ! 88: register int i; ! 89: ! 90: s = (Stkptr)stkptr; ! 91: if (s->k_type == 0) ! 92: badstk(0); ! 93: if (tflg) { ! 94: fprintf(stderr, "pop: type %d, length %d", ! 95: s->k_type, s->k_len); ! 96: for (i = 0; i < s->k_len; ++i) ! 97: fprintf(stderr, " %o", ((char *)s)[i]&0377); ! 98: putc('\n', stderr); ! 99: } ! 100: if (s->k_type != type && type != ANYTYPE) ! 101: badstk(type); ! 102: stkptr += s->k_len; ! 103: return (s); ! 104: } ! 105: ! 106: ! 107: /* ! 108: * pushstring --- push a string onto the stack ! 109: */ ! 110: ! 111: Stkptr pushstring(ptr, len) ! 112: char *ptr; ! 113: { ! 114: Stkfr s; ! 115: ! 116: s.k_type = STRINGEXPR; ! 117: s.k_len = STRFRLEN; ! 118: s.k_un.k_str.s_ptr = ptr; ! 119: s.k_un.k_str.s_len = len; ! 120: return (push(&s)); ! 121: } ! 122: ! 123: ! 124: /* ! 125: * pushfloat --- push a floating point value onto the stack ! 126: */ ! 127: ! 128: Stkptr pushfloat(f) ! 129: double f; ! 130: { ! 131: register Stkptr s; ! 132: Stkfr fe; ! 133: ! 134: s = (Stkptr)(stkptr - DBLFRLEN); ! 135: if ((char *)s < stkbase) ! 136: badstk(0); ! 137: if (tflg) ! 138: fprintf(stderr, "pushfloat: %f\n", f); ! 139: stkptr = (char *)s; ! 140: s->k_type = FLOATEXPR; ! 141: s->k_len = DBLFRLEN; ! 142: s->k_un.k_dbl = f; ! 143: return (s); ! 144: } ! 145: ! 146: ! 147: /* ! 148: * popfloat --- pop a floating point value off the stack ! 149: */ ! 150: ! 151: double popfloat() ! 152: { ! 153: register Stkptr s; ! 154: ! 155: s = (Stkptr)stkptr; ! 156: if (s->k_type != FLOATEXPR) ! 157: badstk(FLOATEXPR); ! 158: if (tflg) ! 159: fprintf(stderr, "popfloat: %f\n", s->k_un.k_dbl); ! 160: stkptr += s->k_len; ! 161: return (s->k_un.k_dbl); ! 162: } ! 163: ! 164: ! 165: /* ! 166: * badstk --- report a bad stack frame ! 167: */ ! 168: ! 169: badstk(type) ! 170: { ! 171: register int i; ! 172: ! 173: if ((i = ((Stkptr)stkptr)->k_type) == 0) ! 174: err("stack underflow"); ! 175: if (type) ! 176: err("%s value or variable expected; got %s", ! 177: typenames[type & 07], typenames[i & 07]); ! 178: err("bad stack frame"); ! 179: } ! 180: ! 181: ! 182: #ifndef popint ! 183: /* ! 184: * popint --- pop an integer value off the stack ! 185: */ ! 186: ! 187: popint() ! 188: { ! 189: ! 190: return ((int)popfloat()); ! 191: } ! 192: #endif ! 193: ! 194: ! 195: /* ! 196: * popstring --- pop a string off the stack ! 197: */ ! 198: ! 199: popstring(sptr, lptr) ! 200: char **sptr; ! 201: int *lptr; ! 202: { ! 203: register Stkptr s; ! 204: ! 205: s = pop(STRINGEXPR); ! 206: *sptr = s->k_un.k_str.s_ptr; ! 207: *lptr = s->k_un.k_str.s_len; ! 208: } ! 209: ! 210: ! 211: /* ! 212: * allocstr --- allocate and copy string into string space; ! 213: */ ! 214: ! 215: char *allocstr(ptr, len, mlen) ! 216: char *ptr; ! 217: { ! 218: register char *s; ! 219: register int l; ! 220: ! 221: l = len + GCHDRSIZE; ! 222: if (l & 1) ! 223: ++l; /* make it even */ ! 224: if (strptr + l >= endstring) ! 225: collect(); ! 226: s = strptr; ! 227: strptr += l; ! 228: gchdr(s)->x_len = len; ! 229: gchdr(s)->x_next = (String *)NULL; ! 230: s += GCHDRSIZE; ! 231: if (mlen) ! 232: move(mlen, ptr, s); ! 233: return (s); ! 234: } ! 235: ! 236: ! 237: /* ! 238: * collect --- collect garbage in string space ! 239: */ ! 240: ! 241: collect() ! 242: { ! 243: register Symptr s; ! 244: register Stkptr k; ! 245: register char *p, *q; ! 246: register int l, n; ! 247: String *sp, *tsp; ! 248: ! 249: for (s = chains[0][STRING]; s; s = s->v_next) { ! 250: if (tflg) ! 251: fprintf(stderr, "mark var %.2s ", s->v_name); ! 252: mark(&s->v_un.v_str, 1); ! 253: } ! 254: for (s = chains[1][STRING]; s; s = s->v_next) { ! 255: if (tflg) ! 256: fprintf(stderr, "mark vec %.2s ", s->v_name); ! 257: for (n = 1, l = s->v_nsubs; --l >= 0; ) ! 258: n *= s->v_un.v_vec.v_subsc[l]; ! 259: mark(s->v_un.v_vec.v_vecun.v_strvec, n); ! 260: } ! 261: for (k = (Stkptr)stkptr; k->k_type; k = nextframe(k)) ! 262: if (k->k_type == STRINGEXPR) { ! 263: if (tflg) ! 264: fprintf(stderr, "mark stk %X ", k); ! 265: mark(&k->k_un.k_str, 1); /* mark stack frame */ ! 266: } ! 267: for (q = p = strspace; p < strptr; p += l) { ! 268: if ((sp = gchdr(p)->x_next) == (String *)NULL) { ! 269: l = gchdr(p)->x_len + GCHDRSIZE; ! 270: if (l & 1) ! 271: ++l; ! 272: } ! 273: else { ! 274: l = sp->s_len + GCHDRSIZE; ! 275: if (l & 1) ! 276: ++l; ! 277: if (p != q) { ! 278: move(l, p, q); ! 279: if (tflg) ! 280: fprintf(stderr, "move %l %X %X\n", ! 281: l, p, q); ! 282: } ! 283: gchdr(q)->x_len = sp->s_len; ! 284: gchdr(q)->x_next = (String *)NULL; ! 285: for (; sp != (String *)NULL; sp = tsp) { ! 286: tsp = (String *)sp->s_ptr; ! 287: sp->s_ptr = q + GCHDRSIZE; ! 288: if (tflg) ! 289: fprintf(stderr, "reset %X = %X %d\n", ! 290: sp, sp->s_ptr, sp->s_len); ! 291: } ! 292: q += l; ! 293: } ! 294: } ! 295: l = endstring - q; /* amount now free */ ! 296: if (tflg) ! 297: fprintf(stderr, "%d bytes recovered\n", l); ! 298: strptr = q; ! 299: if (l < MAXSTRSPACE / 10) ! 300: err("not enough free space"); ! 301: } ! 302: ! 303: ! 304: /* ! 305: * mark --- mark a string as being used ! 306: * this is accomplished by storing a pointer to the ! 307: * String structure referring to this string in the ! 308: * x_next field of the string header. ! 309: * multiple references to the same string are linked ! 310: * together through the s_ptr field of the String structures. ! 311: */ ! 312: ! 313: mark(ptr, n) ! 314: String *ptr; ! 315: { ! 316: String *s; ! 317: register char *p; ! 318: ! 319: for (s = ptr; --n >= 0; ++s) { ! 320: p = s->s_ptr; ! 321: if (isstring(p)) { ! 322: p -= GCHDRSIZE; /* point to GC header */ ! 323: if (tflg) ! 324: fprintf(stderr, "mark %X %d\n", p, s->s_len); ! 325: if (s->s_len != gchdr(p)->x_len) ! 326: err("bad string list"); ! 327: s->s_ptr = (char *)gchdr(p)->x_next; ! 328: gchdr(p)->x_next = s; ! 329: } ! 330: } ! 331: } ! 332: ! 333: ! 334: /* ! 335: * storestring --- store string at top of stack ! 336: */ ! 337: ! 338: storestring(v) ! 339: String *v; ! 340: { ! 341: /* ! 342: * the old value of the variable is changed last, so that in the ! 343: * case of an error, it is still available, allowing re-execution ! 344: * of the line with the error. ! 345: * if storing a pointer will suffice (a$ = b$) ! 346: * then only store the pointer, otherwise allocate more space ! 347: * and copy the string. ! 348: */ ! 349: register char *ptr; ! 350: register int len; ! 351: register Stkptr s; ! 352: ! 353: s = (Stkptr)stkptr; ! 354: len = s->k_un.k_str.s_len; ! 355: ptr = s->k_un.k_str.s_ptr; ! 356: if (!isstring(ptr) ! 357: || ((unsigned)ptr&1) != 0 ! 358: || gchdr(ptr - GCHDRSIZE)->x_len != len) { ! 359: ptr = allocstr(NULL, len, 0); /* alloc but don't copy */ ! 360: move(len, s->k_un.k_str.s_ptr, ptr); ! 361: } ! 362: v->s_ptr = ptr; ! 363: v->s_len = len; ! 364: pop(STRINGEXPR); ! 365: } ! 366: ! 367: ! 368: /* ! 369: * nextframe --- return ptr to frame after one pointed to by sp ! 370: */ ! 371: ! 372: Stkptr nextframe(sp) ! 373: register Stkptr sp; ! 374: { ! 375: ! 376: return ((Stkptr)((char *)sp + sp->k_len)); ! 377: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.