|
|
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.