|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include "ctype.h" ! 3: #include "typedef.h" ! 4: #include "basic.h" ! 5: #include "tokens.h" ! 6: ! 7: static int listlevel, /* listing indentation level */ ! 8: rflg; /* automatic run flag */ ! 9: ! 10: char lnrdelims[] = {MINUS, COMMA, '-', ',', 0}; ! 11: ! 12: char *endstr(); ! 13: Linep findline(); ! 14: Lnr cvtlnr(); ! 15: Stkptr pop(); ! 16: void old(), dorun(), doline(); ! 17: FILE *file; ! 18: char *frstwd, *using; ! 19: ! 20: ! 21: /* ! 22: * main --- main program for basic ! 23: */ ! 24: ! 25: main(argc, argv) ! 26: int argc; ! 27: char **argv; ! 28: { ! 29: register char *argp; ! 30: ! 31: --argc; ! 32: ++argv; ! 33: ! 34: while (argc > 0 && *(argp = *argv) == '-') { ! 35: ++argv; ! 36: --argc; ! 37: while (*++argp) ! 38: switch (*argp) { ! 39: case 'r': ! 40: ++rflg; ! 41: break; ! 42: case 's': ! 43: typelens[FLOAT] = sizeof(float); ! 44: break; ! 45: case 't': ! 46: ++tflg; ! 47: break; ! 48: case 'p': ! 49: pltini(*argv++); ! 50: --argc; ! 51: break; ! 52: default: ! 53: fprintf(stderr, "I don't know about -%c\n", ! 54: *argp); ! 55: exit(1); ! 56: } ! 57: } ! 58: ! 59: initsys(); ! 60: init(); ! 61: if (argc > 0) { ! 62: argcnt = argc; ! 63: argvec = argv; ! 64: argc = 0; ! 65: enter(old, *argv); ! 66: } ! 67: if (rflg) { ! 68: enter(dorun, NULL); ! 69: exit(0); ! 70: } ! 71: for (;;) ! 72: enter(doline, NULL); ! 73: } ! 74: ! 75: ! 76: /* ! 77: * doline --- read and process one line ! 78: */ ! 79: ! 80: void doline() ! 81: { ! 82: ! 83: if (tty) ! 84: fputs(prompt, stderr); ! 85: if (readline(line, infile) < 0) { ! 86: if (attnflg) ! 87: err("attn!!"); ! 88: exit(0); ! 89: } ! 90: inptr = line; ! 91: if (line[0] == 0) ! 92: ; ! 93: else if (!moncmd()) ! 94: compile(); ! 95: } ! 96: ! 97: ! 98: /* ! 99: * compile --- tokenize a line; store numbered ones, execute others ! 100: */ ! 101: ! 102: compile() ! 103: { ! 104: register Lnr lnr; ! 105: register int l; ! 106: register Linep p; ! 107: ! 108: inptr = line; ! 109: tokenize(line, line); ! 110: if (tflg) ! 111: listline(&immed, stderr); ! 112: inptr = line; ! 113: if (isdigit(line[0])) { ! 114: lnr = cvtlnr(); ! 115: if (*inptr) { ! 116: l = strlen(inptr) + 1; ! 117: move(l, inptr, immed.l_line); ! 118: if (l & 1) ! 119: ++l; ! 120: l += LINESIZE; ! 121: immed.l_len = l; ! 122: immed.l_lnr = lnr; ! 123: storeline(&immed); ! 124: } ! 125: else { ! 126: p = findline(lnr, NEXTLNR); ! 127: if (p->l_lnr == lnr) ! 128: delline(p); ! 129: } ! 130: } ! 131: else { ! 132: curline = (Linep)NULL; ! 133: immed.l_len = 0; ! 134: execute(&immed); ! 135: } ! 136: return(YES); ! 137: } ! 138: ! 139: ! 140: /* ! 141: * findline --- search for the specified line; return pointer to it ! 142: * if line is not found and flag==NEXTLNR, return pointer ! 143: * to next higher-numbered line ! 144: */ ! 145: ! 146: Linep findline(lnr, flag) ! 147: Lnr lnr; ! 148: int flag; ! 149: { ! 150: register Linep p; ! 151: ! 152: for ALL_LINES(p) ! 153: if (lnr <= p->l_lnr) ! 154: break; ! 155: if (p->l_lnr != lnr && flag != NEXTLNR) ! 156: err("line not found"); ! 157: return(p); ! 158: } ! 159: ! 160: ! 161: /* ! 162: * list --- list the specified range of lines ! 163: */ ! 164: ! 165: list(line1, line2, file) ! 166: Lnr line1, line2; ! 167: FILE *file; ! 168: { ! 169: register Linep p; ! 170: ! 171: listlevel = 0; ! 172: for ALL_LINES(p) { ! 173: if (attnflg) ! 174: err("attn!"); ! 175: if (p->l_lnr >= line1) ! 176: if (p->l_lnr <= line2) ! 177: listline(p, file); ! 178: else ! 179: break; ! 180: } ! 181: } ! 182: ! 183: ! 184: /* ! 185: * listline --- list a single line ! 186: */ ! 187: ! 188: listline(linep, file) ! 189: Linep linep; ! 190: FILE *file; ! 191: { ! 192: register char *p; ! 193: register Linep l; ! 194: register int c; ! 195: int i, wastoken = YES; ! 196: ! 197: l = linep; ! 198: fprintf(file, "%5u\t", l->l_lnr); ! 199: for (i = 0; i < listlevel; ++i) ! 200: putc('\t', file); ! 201: ! 202: for (p = l->l_line; *p; ++p) ! 203: if (istoken(*p)) { ! 204: if (!wastoken) ! 205: putc(' ', file); ! 206: wastoken = YES; ! 207: switch (c = *p) { ! 208: case QUOTE: ! 209: case PRIME: ! 210: c = tokens[UNTOKEN(c)][0]; ! 211: putc(c, file); ! 212: while (*++p && !istoken(*p)) { ! 213: if (*p == c) ! 214: putc(c, file); ! 215: putc(*p, file); ! 216: } ! 217: putc(c, file); ! 218: putc(' ', file); ! 219: break; ! 220: case REM: ! 221: case PRFORM: ! 222: case DATA: ! 223: fputs(tokens[UNTOKEN(c)], file); ! 224: break; ! 225: case FOR: ! 226: if (p[1] != INPUT && p[1] != OUTPUT && p[1] != APPEND) ! 227: listlevel++; ! 228: goto normal; ! 229: case NEXT: ! 230: listlevel--; ! 231: default: ! 232: normal: ! 233: fputs(tokens[UNTOKEN(c)], file); ! 234: putc(' ', file); ! 235: } ! 236: } ! 237: else { ! 238: putc(*p, file); ! 239: wastoken = NO; ! 240: } ! 241: ! 242: putc('\n', file); ! 243: } ! 244: ! 245: ! 246: /* ! 247: * getlnrs2 --- parse up to two line numbers from current line ! 248: * but don't check for end of line in case there ! 249: * are more arguments on line (for example, ! 250: * renumber 1000, 10, 300-400 ! 251: */ ! 252: ! 253: getlnrs2(lp1, lp2, type) ! 254: Lnr *lp1, *lp2; ! 255: int type; ! 256: { ! 257: register Lnr line1, line2; ! 258: ! 259: if (type == LISTLNRS) { ! 260: line1 = MINLNR; ! 261: line2 = MAXLNR; ! 262: } ! 263: else { ! 264: line1 = *lp1; ! 265: line2 = *lp2; ! 266: } ! 267: if (*inptr) { ! 268: skipbl(); ! 269: optional(lnrdelims); ! 270: skipbl(); ! 271: line1 = cvtlnr(); ! 272: if (type == LISTLNRS) ! 273: line2 = line1; ! 274: skipbl(); ! 275: optional(lnrdelims); ! 276: skipbl(); ! 277: if (*inptr) ! 278: line2 = cvtlnr(); ! 279: } ! 280: *lp1 = line1; ! 281: *lp2 = line2; ! 282: ! 283: } ! 284: /* ! 285: * getlnrs --- parse up to two line numbers from current line ! 286: */ ! 287: ! 288: getlnrs(lp1, lp2, type) ! 289: Lnr *lp1, *lp2; ! 290: int type; ! 291: { ! 292: register Lnr line1, line2; ! 293: ! 294: if (type == LISTLNRS) { ! 295: line1 = MINLNR; ! 296: line2 = MAXLNR; ! 297: } ! 298: else { ! 299: line1 = *lp1; ! 300: line2 = *lp2; ! 301: } ! 302: if (*inptr) { ! 303: skipbl(); ! 304: optional(lnrdelims); ! 305: skipbl(); ! 306: line1 = cvtlnr(); ! 307: if (type == LISTLNRS) ! 308: line2 = line1; ! 309: skipbl(); ! 310: optional(lnrdelims); ! 311: skipbl(); ! 312: if (*inptr) ! 313: line2 = cvtlnr(); ! 314: } ! 315: endchk(); ! 316: *lp1 = line1; ! 317: *lp2 = line2; ! 318: } ! 319: ! 320: ! 321: /* ! 322: * delete --- delete the specified range of lines ! 323: */ ! 324: ! 325: delete(line1, line2) ! 326: Lnr line1, line2; ! 327: { ! 328: register Linep p; ! 329: ! 330: for (p = findline(line1, NEXTLNR); ! 331: isline(p) && p->l_lnr <= line2; delline(p)) ! 332: ; ! 333: } ! 334: ! 335: ! 336: /* ! 337: * delline --- delete the line pointed to by linep ! 338: */ ! 339: ! 340: delline(linep) ! 341: register Linep linep; ! 342: { ! 343: register char *p, *q; ! 344: register int l; ! 345: ! 346: p = (char *)linep; ! 347: l = linep->l_len; ! 348: q = p + l; ! 349: smartmove(lastline - q, q, p); ! 350: lastline -= l; ! 351: --linecnt; ! 352: } ! 353: ! 354: ! 355: /* ! 356: * storeline --- save the line pointed to by linep ! 357: */ ! 358: ! 359: storeline(linep) ! 360: Linep linep; ! 361: { ! 362: register Linep l; ! 363: register char *p, *q; ! 364: int overlap; ! 365: ! 366: l = linep; ! 367: p = (char *)findline(l->l_lnr, NEXTLNR); ! 368: if (l->l_lnr != ((Linep)p)->l_lnr) ! 369: q = p; ! 370: else ! 371: q = p + ((Linep)p)->l_len; ! 372: overlap = q - p; ! 373: if (overlap >= l->l_len && overlap - l->l_len <= LEN_FUZZ) ! 374: l->l_len = overlap; ! 375: else { ! 376: while (lastline + l->l_len - overlap > endlines) ! 377: if (!morelines()) ! 378: err("out of room"); ! 379: smartmove(lastline - q, q, p + l->l_len); ! 380: } ! 381: move(l->l_len, (char *)l, p); ! 382: lastline += l->l_len - overlap; ! 383: if (!overlap) ! 384: ++linecnt; ! 385: } ! 386: ! 387: ! 388: /* ! 389: * cvtlnr --- parse one line number from the current input line ! 390: */ ! 391: ! 392: Lnr cvtlnr() ! 393: { ! 394: register Lnr l, lastl; ! 395: register int c; ! 396: ! 397: lastl = l = 0; ! 398: while ((c = *inptr) && isdigit(c)) { ! 399: l = 10 * l + (c - '0'); ! 400: if (l > MAXLNR || l < lastl) ! 401: err("bad line number"); ! 402: lastl = l; ! 403: ++inptr; ! 404: } ! 405: return(l); ! 406: } ! 407: ! 408: ! 409: /* ! 410: * optional --- accept any single character in str if present ! 411: */ ! 412: ! 413: optional(str) ! 414: char *str; ! 415: { ! 416: register char *s; ! 417: ! 418: if (*inptr) ! 419: for (s = str; *s; ++s) ! 420: if (*s == *inptr) { ! 421: inptr++; ! 422: return(YES); ! 423: } ! 424: return(NO); ! 425: } ! 426: ! 427: ! 428: /* ! 429: * tokenize --- convert input line into a string of tokens ! 430: */ ! 431: ! 432: tokenize(inp, outp) ! 433: char *inp, *outp; ! 434: { ! 435: register char *t, *p; ! 436: register int c; ! 437: int i; ! 438: ! 439: while ((c = *inp++)) { ! 440: if (c == ' ' || c == '\t') ! 441: continue; ! 442: for (i = -1; (t = tokens[UNTOKEN(i)]); --i) { ! 443: for (p = inp - 1;; ) { ! 444: if (*p++ != *t++) { ! 445: if (p[-1] == ' ' || p[-1] == '\t') { ! 446: --t; ! 447: continue; ! 448: } ! 449: else if (isupper(p[-1]) ! 450: && p[-1] == toupper(t[-1])) ! 451: ; ! 452: else ! 453: break; ! 454: } ! 455: if (*t == 0) { ! 456: if (tflg) ! 457: fprintf(stderr, "token %d ", i); ! 458: inp = p; ! 459: c = i; ! 460: switch (i) { ! 461: case REM: ! 462: case PRFORM: ! 463: case DATA: ! 464: *outp++ = c; ! 465: while ((*outp++ = *inp++)) ! 466: ; ! 467: return; ! 468: case PRIME: ! 469: case QUOTE: ! 470: --t; ! 471: *outp++ = c; ! 472: while (*inp) { ! 473: if (*inp == *t && *++inp != *t) ! 474: break; ! 475: *outp++ = *inp++; ! 476: } ! 477: if (*inp == 0) { ! 478: *outp++ = c; ! 479: *outp = 0; ! 480: return; ! 481: } ! 482: break; ! 483: } ! 484: goto loop; ! 485: } ! 486: } ! 487: } ! 488: if (isupper(c)) ! 489: c = tolower(c); ! 490: loop: ! 491: *outp++ = c; ! 492: } ! 493: *outp = c; ! 494: } ! 495: ! 496: ! 497: /* ! 498: * execute --- interpret the line pointed to by linep ! 499: */ ! 500: ! 501: execute(linep) ! 502: Linep linep; ! 503: { ! 504: register Lnr line1; ! 505: register int c; ! 506: register Stkptr s; ! 507: Linep fmlnep; ! 508: char *p; ! 509: ! 510: curline = linep; ! 511: if (curline != &immed && !isline(curline)) ! 512: return; ! 513: loop: ! 514: inptr = curline->l_line; ! 515: if (trace && curline != &immed) ! 516: fprintf(stderr, "#%u\n", curline->l_lnr); ! 517: do { ! 518: if (attnflg) ! 519: err("attn"); ! 520: next: ! 521: c = *inptr; ! 522: if (istoken(c)) { ! 523: ++inptr; ! 524: switch (c) { ! 525: case END: ! 526: return; ! 527: case TRACE: ! 528: trace = YES; ! 529: break; ! 530: case NOTRACE: ! 531: trace = NO; ! 532: break; ! 533: case PRINT: ! 534: if (*inptr == ' ') ! 535: inptr++; ! 536: if (*inptr != USING) ! 537: prtstmt(); ! 538: else { ! 539: inptr++; ! 540: line1 = cvtlnr(); ! 541: fmlnep = findline(line1, EXACTLNR); ! 542: p = fmlnep->l_line; ! 543: if (*p++ != PRFORM) ! 544: err("image-line not found"); ! 545: else ! 546: prtusing(p); ! 547: } ! 548: break; ! 549: case INPUT: ! 550: case ASK: ! 551: ask(); ! 552: break; ! 553: case READ: ! 554: readdata(); ! 555: break; ! 556: case RESTORE: ! 557: if (data.k_un.k_gosub.g_inptr != NULL) ! 558: restore(); ! 559: break; ! 560: case DIM: ! 561: dim(); ! 562: break; ! 563: case FOR: ! 564: forstmt(); ! 565: break; ! 566: case NEXT: ! 567: nextstmt(); ! 568: break; ! 569: case REM: ! 570: case MORE: ! 571: case ELSE: ! 572: case QUOTE: ! 573: case PRIME: ! 574: case PRFORM: ! 575: case DATA: ! 576: while (*inptr) ! 577: ++inptr; ! 578: break; ! 579: case RETURN: ! 580: while (((Stkptr)stkptr)->k_type == STK_FOR) ! 581: (void)pop(ANYTYPE); ! 582: s = pop(STK_GOSUB); ! 583: curline = s->k_un.k_gosub.g_curline; ! 584: inptr = s->k_un.k_gosub.g_inptr; ! 585: break; ! 586: case GOSUB: ! 587: line1 = cvtlnr(); ! 588: endchk(); ! 589: gosub.k_un.k_gosub.g_curline = curline; ! 590: gosub.k_un.k_gosub.g_inptr = inptr; ! 591: gosub.k_type = STK_GOSUB; ! 592: gosub.k_len = GOSUBFRLEN; ! 593: push(&gosub); ! 594: curline = findline(line1, EXACTLNR); ! 595: inptr = NULL; ! 596: break; ! 597: case GOTO: ! 598: line1 = cvtlnr(); ! 599: endchk(); ! 600: curline = findline(line1, EXACTLNR); ! 601: inptr = NULL; ! 602: break; ! 603: case DEF: ! 604: def(); ! 605: break; ! 606: case LET: ! 607: let(); ! 608: break; ! 609: case IF: ! 610: ifstmt(); ! 611: goto nochk; ! 612: case STOP: ! 613: endchk(); ! 614: err("stop"); ! 615: break; ! 616: case COLON: ! 617: goto next; ! 618: case ON: ! 619: ongoto(); ! 620: break; ! 621: case CHAIN: ! 622: chain(); ! 623: break; ! 624: case HPLOT: ! 625: hplot(); ! 626: break; ! 627: case HGR: ! 628: hgr(); ! 629: break; ! 630: case OPEN: ! 631: openstmt(); ! 632: break; ! 633: case CLOSE: ! 634: clsstmt(); ! 635: break; ! 636: case FLUSH: ! 637: flsstmt(); ! 638: break; ! 639: case USING: ! 640: err("print must precede using"); ! 641: break; ! 642: default: ! 643: badsyn(); ! 644: } ! 645: } ! 646: else ! 647: let(); ! 648: if (inptr) ! 649: endchk(); ! 650: nochk: ! 651: ; ! 652: } while (inptr && *inptr); ! 653: ! 654: if (inptr == NULL) { ! 655: if (curline && isline(curline)) ! 656: goto loop; ! 657: return; ! 658: } ! 659: else if (curline != &immed) { ! 660: curline = nextline(curline); ! 661: if (isline(curline)) ! 662: goto loop; ! 663: } ! 664: } ! 665: ! 666: ! 667: /* ! 668: * run --- handle the RUN command ! 669: */ ! 670: ! 671: run() ! 672: { ! 673: register Lnr line1; ! 674: ! 675: line1 = cvtlnr(); ! 676: endchk(); ! 677: dorun(line1); ! 678: } ! 679: ! 680: ! 681: /* ! 682: * dorun --- begin execution at the specified line ! 683: */ ! 684: ! 685: void dorun(line1) ! 686: Lnr line1; ! 687: { ! 688: ! 689: clrsym(); ! 690: clrstk(); ! 691: clrio(); ! 692: curline = findline(line1, NEXTLNR); ! 693: inptr = NULL; ! 694: execute(curline); ! 695: } ! 696: ! 697: ! 698: /* ! 699: * autonumber --- handle the AUTO command ! 700: */ ! 701: ! 702: autonumber(line1, line2) ! 703: register Lnr line1, line2; ! 704: { ! 705: register Linep p; ! 706: register char *q; ! 707: ! 708: curline = (Linep)NULL; ! 709: for (;; line1 += line2) { ! 710: if ((p = findline(line1, NEXTLNR)) && p->l_lnr == line1) ! 711: err("line %u already exists", line1); ! 712: sprintf(line, "%5u ", line1); ! 713: fputs(line, stderr); ! 714: /* fflush(stderr); */ ! 715: q = endstr(line); ! 716: if (readline(q, infile) < 0 || *q == 0) { ! 717: if (attnflg) ! 718: err("attn!!"); ! 719: break; ! 720: } ! 721: inptr = line; ! 722: compile(); ! 723: } ! 724: } ! 725: ! 726: ! 727: /* ! 728: * badsyn --- report bad syntax ! 729: */ ! 730: ! 731: badsyn() ! 732: { ! 733: ! 734: err("bad syntax"); ! 735: } ! 736: ! 737: ! 738: /* ! 739: * init --- perform startup initialization ! 740: */ ! 741: ! 742: init() ! 743: { ! 744: ! 745: initprio(); ! 746: clrsym(); ! 747: clrstk(); ! 748: clrprog(); ! 749: } ! 750: ! 751: ! 752: /* ! 753: * clrprog --- reinitialize the line storage space ! 754: */ ! 755: ! 756: clrprog() ! 757: { ! 758: register Linep l; ! 759: ! 760: l = (Linep)lines; ! 761: l->l_len = 0; ! 762: l->l_lnr = MAXLNR; ! 763: lastline = lines + LINESIZE; ! 764: linecnt = 0; ! 765: } ! 766: ! 767: ! 768: /* ! 769: * nextline --- return ptr to line following one pointed to by lp ! 770: */ ! 771: ! 772: Linep nextline(lp) ! 773: register Linep lp; ! 774: { ! 775: ! 776: return((Linep)((char *)lp + lp->l_len)); ! 777: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.