Subversion Repositories Krakow BASIC

Rev

Rev 3 | Rev 6 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3 Rev 4
Line 1... Line 1...
1
/* $Id: basic.c 3 2024-09-03 11:21:02Z nishi $ */
1
/* $Id: basic.c 4 2024-09-03 22:40:08Z nishi $ */
2
 
2
 
3
/* Krakow BASIC - Multi-platform simple BASIC */
3
/* Krakow BASIC - Multi-platform simple BASIC */
4
 
4
 
5
#if defined(PLATFORM_SHIROI)
5
#if defined(PLATFORM_SHIROI)
6
 
6
 
Line 12... Line 12...
12
#include "char.h"
12
#include "char.h"
13
#define PLATFORM "Shiroi"
13
#define PLATFORM "Shiroi"
14
#define NEWLINE "\r\n"
14
#define NEWLINE "\r\n"
15
#define BREAKKEY
15
#define BREAKKEY
16
 
16
 
17
#elif defined(PLATFORM_UNIX) || defined(PLATFORM_WINDOWS) || defined(PLATFORM_ARDUINO)
17
#elif defined(PLATFORM_UNIX) || defined(PLATFORM_WINDOWS) || defined(PLATFORM_ARDUINO) || defined(PLATFORM_C64)
18
 
-
 
19
#define mull(x, y) ((x) * (y))
-
 
20
#define divl(x, y) ((x) / (y))
-
 
21
#define killcursor(x)
-
 
22
#define cursor(x)
-
 
23
#define strnum atoi
-
 
24
 
18
 
25
#if defined(PLATFORM_WINDOWS)
19
#if defined(PLATFORM_WINDOWS)
26
#define PLATFORM "Windows"
20
#define PLATFORM "Windows"
27
#elif defined(PLATFORM_UNIX)
21
#elif defined(PLATFORM_UNIX)
28
#define PLATFORM "Unix"
22
#define PLATFORM "Unix"
29
#elif defined(PLATFORM_ARDUINO)
23
#elif defined(PLATFORM_ARDUINO)
30
#define PLATFORM "Arduino"
24
#define PLATFORM "Arduino"
31
#define NEWLINE "\r\n"
25
#define NEWLINE "\r\n"
32
#define BREAKKEY
26
#define BREAKKEY
-
 
27
#elif defined(PLATFORM_C64)
-
 
28
#define PLATFORM "Commodore-64"
-
 
29
#define NEWLINE "\r\n"
-
 
30
#define BREAKKEY
-
 
31
#include <conio.h>
33
#endif
32
#endif
34
 
33
 
-
 
34
#define mull(x, y) ((x) * (y))
-
 
35
#define divl(x, y) ((x) / (y))
-
 
36
#define killcursor(x)
-
 
37
#define cursor(x)
-
 
38
#define strnum atoi
-
 
39
 
35
#ifndef NEWLINE
40
#ifndef NEWLINE
36
#define NEWLINE "\n"
41
#define NEWLINE "\n"
37
#endif
42
#endif
38
 
43
 
39
#include <stdio.h>
44
#include <stdio.h>
Line 55... Line 60...
55
#define LINES (32)
60
#define LINES (32)
56
#undef putchar
61
#undef putchar
57
#define putchar uart_putchar
62
#define putchar uart_putchar
58
#elif defined(PLATFORM_UNIX)
63
#elif defined(PLATFORM_UNIX)
59
#include <termios.h>
64
#include <termios.h>
-
 
65
#elif defined(PLATFORM_C64)
-
 
66
#define BUFFER_SIZE (16 * 1024)
-
 
67
#undef killcursor
-
 
68
#undef cursor
-
 
69
#define killcursor(x) cursor(0)
-
 
70
#define cursor(x) cursor(1)
60
#endif
71
#endif
61
 
72
 
62
#if defined(PLATFORM_ARDUINO)
73
#if defined(PLATFORM_ARDUINO)
63
int uart_putchar(char c) {
74
int uart_putchar(char c) {
64
	while(!(UCSR0A & _BV(UDRE0)))
75
	while(!(UCSR0A & _BV(UDRE0)))
Line 75... Line 86...
75
 
86
 
76
	UCSR0C |= _BV(UCSZ00) | _BV(UCSZ01);
87
	UCSR0C |= _BV(UCSZ00) | _BV(UCSZ01);
77
}
88
}
78
#endif
89
#endif
79
 
90
 
80
char agetch(void) {
91
#define agetch(x) oggetch(0)
81
#if defined(PLATFORM_WINDOWS)
92
char oggetch(char wait) {
82
	int c;
93
	int c;
-
 
94
#if defined(PLATFORM_WINDOWS)
83
rescan:
95
rescan:
84
	c = _getch();
96
	c = _getch();
85
	if(c == '\r') return '\n';
97
	if(c == '\r') return '\n';
86
	if(c == '\n') goto rescan;
98
	if(c == '\n') goto rescan;
87
	return c;
-
 
88
#elif defined(PLATFORM_UNIX)
99
#elif defined(PLATFORM_UNIX)
89
	int c = getchar();
100
	c = getchar();
90
	if(c == EOF) return -1;
101
	if(c == EOF) return -1;
91
	if(c == '\r') return '\n';
102
	if(c == '\r') return '\n';
92
#elif defined(PLATFORM_ARDUINO)
103
#elif defined(PLATFORM_ARDUINO)
93
	int c;
-
 
94
rescan:
104
rescan:
-
 
105
	if(wait){
95
	if(!(UCSR0A & _BV(RXC0))) return 0;
106
		if(!(UCSR0A & _BV(RXC0))) return 0;
-
 
107
	}else{
-
 
108
		while(!(UCSR0A & _BV(RXC0)));
-
 
109
	}
96
	c = UDR0;
110
	c = UDR0;
97
	if(c == '\r') return '\n';
111
	if(c == '\r') return '\n';
98
	if(c == '\n') goto rescan;
112
	if(c == '\n') goto rescan;
99
	if(c == 3) return 1;
113
	if(c == 3) return 1;
-
 
114
#elif defined(PLATFORM_C64)
-
 
115
	if(!wait){
-
 
116
		if(!kbhit()) return 0;
-
 
117
	}
-
 
118
	c = cgetc();
-
 
119
	if(c == EOF) return -1;
-
 
120
	if(c == '\r') return '\n';
-
 
121
	if(c == 20) return 8;
100
	return c;
122
	if(c == 3) return 1;
101
#endif
123
#endif
102
	return c;
124
	return c;
103
}
125
}
104
 
126
 
105
bool strcaseequ(const char* a, const char* b) { return strcasecmp(a, b) == 0; }
127
bool strcaseequ(const char* a, const char* b) { return strcasecmp(a, b) == 0; }
Line 134... Line 156...
134
	fflush(stdout);
156
	fflush(stdout);
135
}
157
}
136
#endif
158
#endif
137
 
159
 
138
void change_color(int a) {
160
void change_color(int a) {
-
 
161
#if defined(PLATFORM_ARDUINO) || defined(PLATFORM_UNIX)
139
	int fg = (a >> 4) & 0xf;
162
	int fg = (a >> 4) & 0xf;
140
	int bg = (a & 0xf);
163
	int bg = (a & 0xf);
-
 
164
	char color[2];
141
	if(!(0 <= fg && fg <= 15)) return;
165
	if(!(0 <= fg && fg <= 15)) return;
142
	if(!(0 <= bg && bg <= 15)) return;
166
	if(!(0 <= bg && bg <= 15)) return;
143
	char color[2];
-
 
144
	color[1] = 0;
167
	color[1] = 0;
145
	if(bg < 8) {
168
	if(bg < 8) {
146
		color[0] = bg + '0';
169
		color[0] = bg + '0';
147
		putstr("\x1b[4");
170
		putstr("\x1b[4");
148
	} else {
171
	} else {
Line 159... Line 182...
159
		putstr("\x1b[9");
182
		putstr("\x1b[9");
160
	}
183
	}
161
	putstr(color);
184
	putstr(color);
162
	putstr("m");
185
	putstr("m");
163
	putstr("\x1b[2J\x1b[1;1H");
186
	putstr("\x1b[2J\x1b[1;1H");
-
 
187
#elif defined(PLATFORM_C64)
-
 
188
	int fg = (a >> 4) & 0xf;
-
 
189
	int bg = (a & 0xf);
-
 
190
	bgcolor(bg);
-
 
191
	textcolor(fg);
-
 
192
#endif
164
}
193
}
165
 
194
 
166
void clear(void) {
195
void clear(void) {
167
#if defined(PLATFORM_WINDOWS)
196
#if defined(PLATFORM_WINDOWS)
168
	system("cls");
197
	system("cls");
169
#elif defined(PLATFORM_UNIX) || defined(PLATFORM_ARDUINO)
198
#elif defined(PLATFORM_UNIX) || defined(PLATFORM_ARDUINO)
170
	putstr("\x1b[0m\x1b[2J\x1b[1;1H");
199
	putstr("\x1b[0m\x1b[2J\x1b[1;1H");
-
 
200
#elif defined(PLATFORM_C64)
-
 
201
	clrscr();
171
#endif
202
#endif
172
}
203
}
173
 
204
 
174
void basic(void);
205
void basic(void);
175
 
206
 
Line 190... Line 221...
190
#elif defined(PLATFORM_ARDUINO)
221
#elif defined(PLATFORM_ARDUINO)
191
	uart_init();
222
	uart_init();
192
	DDRB |= _BV(DDB5);
223
	DDRB |= _BV(DDB5);
193
	PORTB |= _BV(PORT5);
224
	PORTB |= _BV(PORT5);
194
#endif
225
#endif
-
 
226
#if defined(PLATFORM_C64)
-
 
227
	change_color((1 << 4) | 0);
-
 
228
#endif
195
	basic();
229
	basic();
196
#if defined(PLATFORM_WINDOWS)
230
#if defined(PLATFORM_WINDOWS)
197
	SetConsoleMode(winstdout, origmode);
231
	SetConsoleMode(winstdout, origmode);
198
#elif defined(PLATFORM_UNIX)
232
#elif defined(PLATFORM_UNIX)
199
	tcsetattr(0, TCSANOW, &old);
233
	tcsetattr(0, TCSANOW, &old);
Line 222... Line 256...
222
char linebuf[LINE_BUFFER_SIZE];
256
char linebuf[LINE_BUFFER_SIZE];
223
 
257
 
224
int pexpr(char* expr, char* buffer, int* number) {
258
int pexpr(char* expr, char* buffer, int* number) {
225
	char ownbuf[128];
259
	char ownbuf[128];
226
	int i;
260
	int i;
227
	for(i = 0; expr[i] != 0; i++) ownbuf[i] = expr[i];
-
 
228
	ownbuf[i] = 0;
-
 
229
	int start = 0;
261
	int start = 0;
230
	int br = 0;
262
	int br = 0;
231
	int result = 0;
263
	int result = 0;
232
	int stack[32];
264
	int stack[32];
233
	int sp = 0;
265
	int sp = 0;
234
	char put = 0;
266
	char put = 0;
-
 
267
	for(i = 0; expr[i] != 0; i++) ownbuf[i] = expr[i];
-
 
268
	ownbuf[i] = 0;
235
	for(i = 0; i < 32; i++) stack[i] = 0;
269
	for(i = 0; i < 32; i++) stack[i] = 0;
236
	for(i = 0;; i++) {
270
	for(i = 0;; i++) {
237
		if(ownbuf[i] == 0) {
271
		if(ownbuf[i] == 0) {
238
			break;
272
			break;
239
		} else if('0' <= ownbuf[i] && ownbuf[i] <= '9') {
273
		} else if('0' <= ownbuf[i] && ownbuf[i] <= '9') {
Line 289... Line 323...
289
		}
323
		}
290
	}
324
	}
291
}
325
}
292
 
326
 
293
int run(char* cmd, int linenum, char num, int* lgoto) {
327
int run(char* cmd, int linenum, char num, int* lgoto) {
294
#ifdef BREAKKEY
-
 
295
	if(agetch() == 1) return -1;
-
 
296
#endif
-
 
297
	char line[LINE_BUFFER_SIZE];
328
	char line[LINE_BUFFER_SIZE];
298
	char rcmd[32];
329
	char rcmd[32];
299
	int i;
330
	int i;
-
 
331
	char* arg;
-
 
332
	int incr = 0;
-
 
333
#ifdef BREAKKEY
-
 
334
	if(agetch() == 1) return -1;
-
 
335
#endif
300
	if(lgoto != 0) *lgoto = 0;
336
	if(lgoto != 0) *lgoto = 0;
301
	for(i = 0; cmd[i] != 0; i++) line[i] = cmd[i];
337
	for(i = 0; cmd[i] != 0; i++) line[i] = cmd[i];
302
	line[i] = 0;
338
	line[i] = 0;
303
	rcmd[0] = 0;
339
	rcmd[0] = 0;
304
	int incr = 0;
-
 
305
	for(i = 0;; i++) {
340
	for(i = 0;; i++) {
306
		if(line[i] == ' ' || line[i] == '\t' || line[i] == 0 || line[i] == '"') {
341
		if(line[i] == ' ' || line[i] == '\t' || line[i] == 0 || line[i] == '"') {
307
			break;
342
			break;
308
		} else {
343
		} else {
309
			rcmd[incr++] = line[i];
344
			rcmd[incr++] = line[i];
Line 317... Line 352...
317
				return 1;
352
				return 1;
318
			}
353
			}
319
			rcmd[incr] = 0;
354
			rcmd[incr] = 0;
320
		}
355
		}
321
	}
356
	}
322
	char* arg = line + 1 + strlen(rcmd);
357
	arg = line + 1 + strlen(rcmd);
323
	if(strcaseequ(rcmd, "COLOR")) {
358
	if(strcaseequ(rcmd, "COLOR")) {
324
		int argc = 0;
359
		int argc = 0;
325
		char* farg = 0;
360
		char* farg = 0;
326
		char* sarg = 0;
361
		char* sarg = 0;
-
 
362
		int fgcolor, bgcolor, ret0, ret1;
327
		if(arg[0] != 0) argc++;
363
		if(arg[0] != 0) argc++;
328
		for(i = 0; arg[i] != 0; i++) {
364
		for(i = 0; arg[i] != 0; i++) {
329
			if(arg[i] == ',') {
365
			if(arg[i] == ',') {
330
				arg[i] = 0;
366
				arg[i] = 0;
331
				farg = arg;
367
				farg = arg;
Line 342... Line 378...
342
				putnum(linenum);
378
				putnum(linenum);
343
			}
379
			}
344
			putstr(NEWLINE);
380
			putstr(NEWLINE);
345
			return 1;
381
			return 1;
346
		}
382
		}
347
		int bgcolor = 0;
383
		bgcolor = 0;
348
		int fgcolor = 0;
384
		fgcolor = 0;
349
		int ret0 = pexpr(farg, 0, &bgcolor);
385
		ret0 = pexpr(farg, 0, &bgcolor);
350
		int ret1 = pexpr(sarg, 0, &fgcolor);
386
		ret1 = pexpr(sarg, 0, &fgcolor);
351
		if(ret0 == 0) {
387
		if(ret0 == 0) {
352
			putstr("! Invalid argument");
388
			putstr("! Invalid argument");
353
			if(linenum != -1) {
389
			if(linenum != -1) {
354
				putstr(" in line ");
390
				putstr(" in line ");
355
				putnum(linenum);
391
				putnum(linenum);
Line 388... Line 424...
388
		int addr = BUFFER_SIZE - 1;
424
		int addr = BUFFER_SIZE - 1;
389
		int saddr = 0;
425
		int saddr = 0;
390
		int lbuf[LINES];
426
		int lbuf[LINES];
391
		int shift[LINES];
427
		int shift[LINES];
392
		int cnt = 0;
428
		int cnt = 0;
-
 
429
		int i;
393
		while(1) {
430
		while(1) {
394
			unsigned long ln = 0;
431
			unsigned long ln = 0;
395
			for(i = 0; i < 4; i++) {
432
			for(i = 0; i < 4; i++) {
396
				ln >>= 8;
433
				ln >>= 8;
397
				ln |= (unsigned long)basicbuffer[addr--] << 24;
434
				ln |= (unsigned long)basicbuffer[addr--] << 24;
Line 400... Line 437...
400
			lbuf[cnt] = ln;
437
			lbuf[cnt] = ln;
401
			shift[cnt++] = saddr;
438
			shift[cnt++] = saddr;
402
			saddr += strlen(basicbuffer + saddr) + 1;
439
			saddr += strlen(basicbuffer + saddr) + 1;
403
		}
440
		}
404
		sort(lbuf, shift, cnt);
441
		sort(lbuf, shift, cnt);
405
		int i;
-
 
406
		for(i = 0; i < cnt; i++) {
442
		for(i = 0; i < cnt; i++) {
407
			putnum(lbuf[i]);
443
			putnum(lbuf[i]);
408
			putstr(" ");
444
			putstr(" ");
409
			putstr(basicbuffer + shift[i]);
445
			putstr(basicbuffer + shift[i]);
410
			putstr(NEWLINE);
446
			putstr(NEWLINE);
Line 432... Line 468...
432
		int addr = BUFFER_SIZE - 1;
468
		int addr = BUFFER_SIZE - 1;
433
		int saddr = 0;
469
		int saddr = 0;
434
		int lbuf[LINES];
470
		int lbuf[LINES];
435
		int shift[LINES];
471
		int shift[LINES];
436
		int cnt = 0;
472
		int cnt = 0;
437
		int gt;
473
		int gt, i;
438
		while(1) {
474
		while(1) {
439
			unsigned long ln = 0;
475
			unsigned long ln = 0;
440
			for(i = 0; i < 4; i++) {
476
			for(i = 0; i < 4; i++) {
441
				ln >>= 8;
477
				ln >>= 8;
442
				ln |= (unsigned long)basicbuffer[addr--] << 24;
478
				ln |= (unsigned long)basicbuffer[addr--] << 24;
Line 445... Line 481...
445
			lbuf[cnt] = ln;
481
			lbuf[cnt] = ln;
446
			shift[cnt++] = saddr;
482
			shift[cnt++] = saddr;
447
			saddr += strlen(basicbuffer + saddr) + 1;
483
			saddr += strlen(basicbuffer + saddr) + 1;
448
		}
484
		}
449
		sort(lbuf, shift, cnt);
485
		sort(lbuf, shift, cnt);
450
		int i;
-
 
451
		for(i = 0; i < cnt; i++) {
486
		for(i = 0; i < cnt; i++) {
452
			int ret = run(basicbuffer + shift[i], lbuf[i], 1, &gt);
487
			int ret = run(basicbuffer + shift[i], lbuf[i], 1, &gt);
453
			if(ret != 0) return ret;
488
			if(ret != 0) return ret;
454
			if(gt != 0) {
489
			if(gt != 0) {
455
				char found = 0;
490
				char found;
456
				for(i = 0; i < cnt; i++) {
491
				for(i = 0; i < cnt; i++) {
457
					if(lbuf[i] == gt) {
492
					if(lbuf[i] == gt) {
458
						found = 1;
493
						found = 1;
459
						break;
494
						break;
460
					}
495
					}
Line 512... Line 547...
512
	} else {
547
	} else {
513
		int addr = BUFFER_SIZE - 1;
548
		int addr = BUFFER_SIZE - 1;
514
		int i;
549
		int i;
515
		int shf = 0;
550
		int shf = 0;
516
		int cnt = 0;
551
		int cnt = 0;
-
 
552
		int len;
517
		while(1) {
553
		while(1) {
518
			unsigned long ln = 0;
554
			unsigned long ln = 0;
519
			for(i = 0; i < 4; i++) {
555
			for(i = 0; i < 4; i++) {
520
				ln >>= 8;
556
				ln >>= 8;
521
				ln |= (unsigned long)basicbuffer[addr--] << 24;
557
				ln |= (unsigned long)basicbuffer[addr--] << 24;
Line 542... Line 578...
542
			for(i = 0; i < 4; i++) {
578
			for(i = 0; i < 4; i++) {
543
				basicbuffer[addr--] = linenum & 0xff;
579
				basicbuffer[addr--] = linenum & 0xff;
544
				linenum >>= 8;
580
				linenum >>= 8;
545
			}
581
			}
546
		}
582
		}
547
		int len = 0;
583
		len = 0;
548
		cnt = 0;
584
		cnt = 0;
549
		while(1) {
585
		while(1) {
550
			int slen = strlen(basicbuffer + len);
586
			int slen = strlen(basicbuffer + len);
551
			if(slen == 0) break;
587
			if(slen == 0) break;
552
			len += slen + 1;
588
			len += slen + 1;
Line 568... Line 604...
568
 
604
 
569
				len += slen + 1;
605
				len += slen + 1;
570
				cnt++;
606
				cnt++;
571
 
607
 
572
				if(cnt == shf) {
608
				if(cnt == shf) {
573
					len -= slen + 1;
-
 
574
					int i;
609
					int i;
575
					int nc = 0;
610
					int nc = 0;
-
 
611
					len -= slen + 1;
576
					for(i = len;; i++) {
612
					for(i = len;; i++) {
577
						basicbuffer[i] = basicbuffer[i + slen + 1];
613
						basicbuffer[i] = basicbuffer[i + slen + 1];
578
						if(basicbuffer[i] == 0) {
614
						if(basicbuffer[i] == 0) {
579
							nc++;
615
							nc++;
580
							if(nc == 2) break;
616
							if(nc == 2) break;
Line 590... Line 626...
590
	}
626
	}
591
}
627
}
592
 
628
 
593
void basic(void) {
629
void basic(void) {
594
	int i;
630
	int i;
-
 
631
	int lineind;
595
	clear();
632
	clear();
596
 
633
 
597
#ifdef SMALL
634
#ifdef SMALL
598
	putstr("Krakow BASIC  Ver. ");
635
	putstr("Krakow BASIC  Ver. ");
599
	putstr(VERSION);
636
	putstr(VERSION);
Line 629... Line 666...
629
	putstr("Ready");
666
	putstr("Ready");
630
	putstr(NEWLINE);
667
	putstr(NEWLINE);
631
 
668
 
632
	cursor();
669
	cursor();
633
	linebuf[0] = 0;
670
	linebuf[0] = 0;
634
	int lineind = 0;
671
	lineind = 0;
635
	while(1) {
672
	while(1) {
-
 
673
		char c;
-
 
674
#if defined(PLATFORM_C64)
-
 
675
		c = oggetch(1);
-
 
676
#else
636
		char c = agetch();
677
		c = agetch();
-
 
678
#endif
637
		if(c != 0) killcursor();
679
		if(c != 0) killcursor();
638
		if(c == 1) {
680
		if(c == 1) {
639
			putstr("Break");
681
			putstr("Break");
640
			putstr(NEWLINE);
682
			putstr(NEWLINE);
641
			lineind = 0;
683
			lineind = 0;
642
		} else if(c == '\n') {
684
		} else if(c == '\n') {
643
			linebuf[lineind] = 0;
-
 
644
			putstr(NEWLINE);
-
 
645
			if(lineind == 0) goto skip;
-
 
646
 
-
 
647
			int i;
685
			int i;
648
			char num = 1;
686
			char num = 1;
649
 
-
 
650
			char* cmd = linebuf;
687
			char* cmd = linebuf;
651
 
688
 
-
 
689
			linebuf[lineind] = 0;
-
 
690
			putstr(NEWLINE);
-
 
691
			if(lineind == 0) goto skip;
-
 
692
 
652
			for(i = 0; linebuf[i] != 0; i++) {
693
			for(i = 0; linebuf[i] != 0; i++) {
653
				if(linebuf[i] == ' ') {
694
				if(linebuf[i] == ' ') {
654
					linebuf[i] = 0;
695
					linebuf[i] = 0;
655
					cmd = linebuf + i + 1;
696
					cmd = linebuf + i + 1;
656
					break;
697
					break;