Subversion Repositories Krakow BASIC

Rev

Rev 4 | Rev 7 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 nishi 1
/* $Id: basic.c 6 2024-09-03 22:57:45Z nishi $ */
2
 
3
/* Krakow BASIC - Multi-platform simple BASIC */
4
 
5
#if defined(PLATFORM_SHIROI)
6
 
7
#include "dri/text.h"
8
#include "dri/video.h"
9
#include "dri/math.h"
10
 
11
#include "mem.h"
12
#include "char.h"
13
#define PLATFORM "Shiroi"
14
#define NEWLINE "\r\n"
15
#define BREAKKEY
16
 
6 nishi 17
#elif defined(PLATFORM_UNIX) || defined(PLATFORM_WINDOWS) || defined(PLATFORM_ARDUINO) || defined(PLATFORM_C64) || defined(PLATFORM_A800XL)
2 nishi 18
 
19
#if defined(PLATFORM_WINDOWS)
20
#define PLATFORM "Windows"
21
#elif defined(PLATFORM_UNIX)
22
#define PLATFORM "Unix"
23
#elif defined(PLATFORM_ARDUINO)
24
#define PLATFORM "Arduino"
25
#define NEWLINE "\r\n"
26
#define BREAKKEY
4 nishi 27
#elif defined(PLATFORM_C64)
28
#define PLATFORM "Commodore-64"
29
#define NEWLINE "\r\n"
30
#define BREAKKEY
31
#include <conio.h>
6 nishi 32
#elif defined(PLATFORM_A800XL)
33
#define PLATFORM "Atari-800XL"
34
#define NEWLINE "\n"
35
#define BREAKKEY
36
#include <conio.h>
2 nishi 37
#endif
38
 
4 nishi 39
#define mull(x, y) ((x) * (y))
40
#define divl(x, y) ((x) / (y))
41
#define killcursor(x)
42
#define cursor(x)
43
#define strnum atoi
44
 
2 nishi 45
#ifndef NEWLINE
46
#define NEWLINE "\n"
47
#endif
48
 
49
#include <stdio.h>
50
#include <stdlib.h>
51
#include <string.h>
52
#include <ctype.h>
53
#include <stdbool.h>
54
 
55
#if defined(__MINGW32__)
56
#include <conio.h>
57
#include <windows.h>
58
#elif defined(PLATFORM_ARDUINO)
59
#define BAUD 9600
60
#include <avr/io.h>
61
#include <util/delay.h>
62
#include <util/setbaud.h>
63
#define BUFFER_SIZE (1024)
64
#define LINE_BUFFER_SIZE (128)
65
#define LINES (32)
66
#undef putchar
67
#define putchar uart_putchar
68
#elif defined(PLATFORM_UNIX)
69
#include <termios.h>
4 nishi 70
#elif defined(PLATFORM_C64)
71
#define BUFFER_SIZE (16 * 1024)
72
#undef killcursor
73
#undef cursor
74
#define killcursor(x) cursor(0)
75
#define cursor(x) cursor(1)
6 nishi 76
#elif defined(PLATFORM_A800XL)
77
#define BUFFER_SIZE (16 * 1024)
78
#undef killcursor
79
#undef cursor
80
#define killcursor(x) cursor(0)
81
#define cursor(x) cursor(1)
2 nishi 82
#endif
83
 
84
#if defined(PLATFORM_ARDUINO)
85
int uart_putchar(char c) {
86
	while(!(UCSR0A & _BV(UDRE0)))
87
		;
88
	UDR0 = c;
89
	return 0;
90
}
91
 
92
void uart_init(void) {
93
	UBRR0H = UBRRH_VALUE;
94
	UBRR0L = UBRRL_VALUE;
95
 
96
	UCSR0B |= _BV(TXEN0) | _BV(RXEN0);
97
 
98
	UCSR0C |= _BV(UCSZ00) | _BV(UCSZ01);
99
}
100
#endif
101
 
4 nishi 102
#define agetch(x) oggetch(0)
103
char oggetch(char wait) {
104
	int c;
2 nishi 105
#if defined(PLATFORM_WINDOWS)
106
rescan:
107
	c = _getch();
108
	if(c == '\r') return '\n';
109
	if(c == '\n') goto rescan;
110
#elif defined(PLATFORM_UNIX)
4 nishi 111
	c = getchar();
2 nishi 112
	if(c == EOF) return -1;
113
	if(c == '\r') return '\n';
114
#elif defined(PLATFORM_ARDUINO)
115
rescan:
4 nishi 116
	if(wait){
117
		if(!(UCSR0A & _BV(RXC0))) return 0;
118
	}else{
119
		while(!(UCSR0A & _BV(RXC0)));
120
	}
2 nishi 121
	c = UDR0;
122
	if(c == '\r') return '\n';
123
	if(c == '\n') goto rescan;
124
	if(c == 3) return 1;
4 nishi 125
#elif defined(PLATFORM_C64)
126
	if(!wait){
127
		if(!kbhit()) return 0;
128
	}
129
	c = cgetc();
130
	if(c == EOF) return -1;
131
	if(c == '\r') return '\n';
132
	if(c == 20) return 8;
133
	if(c == 3) return 1;
6 nishi 134
#elif defined(PLATFORM_A800XL)
135
	if(!wait){
136
		if(!kbhit()) return 0;
137
	}
138
	c = cgetc();
139
	if(c == EOF) return -1;
140
	if(c == '\r') return '\n';
141
	if(c == 126) return 8;
142
	if(c == 3) return 1;
2 nishi 143
#endif
144
	return c;
145
}
146
 
147
bool strcaseequ(const char* a, const char* b) { return strcasecmp(a, b) == 0; }
148
 
149
#if defined(PLATFORM_ARDUINO)
150
void putstr(const char* n) {
151
	int i;
152
	for(i = 0; n[i] != 0; i++) {
153
		uart_putchar(n[i]);
154
	}
155
}
156
 
157
void putnum(int n) {
158
	char buf[64];
159
	int incr = 63;
160
	buf[incr--] = 0;
161
	while(1) {
162
		buf[incr--] = (n % 10) + '0';
163
		n /= 10;
164
		if(n == 0) break;
165
	}
166
	putstr(buf + incr + 1);
167
}
168
#else
169
void putnum(int n) {
170
	printf("%d", n);
171
	fflush(stdout);
172
}
173
 
174
void putstr(const char* n) {
175
	printf("%s", n);
176
	fflush(stdout);
177
}
178
#endif
179
 
180
void change_color(int a) {
4 nishi 181
#if defined(PLATFORM_ARDUINO) || defined(PLATFORM_UNIX)
2 nishi 182
	int fg = (a >> 4) & 0xf;
183
	int bg = (a & 0xf);
4 nishi 184
	char color[2];
2 nishi 185
	if(!(0 <= fg && fg <= 15)) return;
186
	if(!(0 <= bg && bg <= 15)) return;
187
	color[1] = 0;
3 nishi 188
	if(bg < 8) {
2 nishi 189
		color[0] = bg + '0';
190
		putstr("\x1b[4");
3 nishi 191
	} else {
2 nishi 192
		color[0] = (bg - 8) + '0';
193
		putstr("\x1b[10");
194
	}
195
	putstr(color);
196
	putstr("m");
3 nishi 197
	if(fg < 8) {
2 nishi 198
		color[0] = fg + '0';
199
		putstr("\x1b[3");
3 nishi 200
	} else {
2 nishi 201
		color[0] = (fg - 8) + '0';
202
		putstr("\x1b[9");
203
	}
204
	putstr(color);
205
	putstr("m");
206
	putstr("\x1b[2J\x1b[1;1H");
6 nishi 207
#elif defined(PLATFORM_C64) || defined(PLATFORM_A800XL)
4 nishi 208
	int fg = (a >> 4) & 0xf;
209
	int bg = (a & 0xf);
210
	bgcolor(bg);
211
	textcolor(fg);
212
#endif
2 nishi 213
}
214
 
215
void clear(void) {
216
#if defined(PLATFORM_WINDOWS)
217
	system("cls");
218
#elif defined(PLATFORM_UNIX) || defined(PLATFORM_ARDUINO)
219
	putstr("\x1b[0m\x1b[2J\x1b[1;1H");
4 nishi 220
#elif defined(PLATFORM_C64)
221
	clrscr();
2 nishi 222
#endif
223
}
224
 
225
void basic(void);
226
 
227
int main() {
228
#if defined(PLATFORM_WINDOWS)
229
	HANDLE winstdout = GetStdHandle(STD_OUTPUT_HANDLE);
230
	DWORD mode = 0;
231
	GetConsoleMode(winstdout, &mode);
232
	const DWORD origmode = mode;
233
	mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
234
	SetConsoleMode(winstdout, mode);
235
#elif defined(PLATFORM_UNIX)
236
	struct termios old, new;
237
	tcgetattr(0, &old);
238
	new = old;
239
	new.c_lflag &= ~(ECHO | ICANON);
240
	tcsetattr(0, TCSANOW, &new);
241
#elif defined(PLATFORM_ARDUINO)
242
	uart_init();
243
	DDRB |= _BV(DDB5);
244
	PORTB |= _BV(PORT5);
245
#endif
6 nishi 246
#if defined(PLATFORM_C64) || defined(PLATFORM_A800XL)
4 nishi 247
	change_color((1 << 4) | 0);
248
#endif
2 nishi 249
	basic();
250
#if defined(PLATFORM_WINDOWS)
251
	SetConsoleMode(winstdout, origmode);
252
#elif defined(PLATFORM_UNIX)
253
	tcsetattr(0, TCSANOW, &old);
254
#endif
255
}
256
 
257
#else
258
#error "Define PLATFORM_*"
259
#endif
260
 
261
#define VERSION "0.0"
262
 
263
#ifndef LINE_BUFFER_SIZE
264
#define LINE_BUFFER_SIZE (512)
265
#endif
266
 
267
#ifndef BUFFER_SIZE
268
#define BUFFER_SIZE (1024 * 24)
269
#endif
270
 
271
#ifndef LINES
272
#define LINES (1024)
273
#endif
274
 
275
unsigned char basicbuffer[BUFFER_SIZE];
276
char linebuf[LINE_BUFFER_SIZE];
277
 
278
int pexpr(char* expr, char* buffer, int* number) {
279
	char ownbuf[128];
280
	int i;
281
	int start = 0;
282
	int br = 0;
283
	int result = 0;
284
	int stack[32];
285
	int sp = 0;
286
	char put = 0;
4 nishi 287
	for(i = 0; expr[i] != 0; i++) ownbuf[i] = expr[i];
288
	ownbuf[i] = 0;
2 nishi 289
	for(i = 0; i < 32; i++) stack[i] = 0;
290
	for(i = 0;; i++) {
291
		if(ownbuf[i] == 0) {
292
			break;
293
		} else if('0' <= ownbuf[i] && ownbuf[i] <= '9') {
294
			stack[sp] *= 10;
295
			stack[sp] += ownbuf[i] - '0';
296
			put = 1;
297
		} else if(ownbuf[i] == '+' || ownbuf[i] == '-' || ownbuf[i] == '*' || ownbuf[i] == '/') {
298
			put = 0;
299
			if(sp < 2) {
300
				return -1;
301
			} else {
302
				int top = stack[--sp];
303
				int bottom = stack[--sp];
304
				int value = 0;
305
				if(ownbuf[i] == '+') {
306
					value = top + bottom;
307
				} else if(ownbuf[i] == '-') {
308
					value = bottom + top;
309
				} else if(ownbuf[i] == '*') {
310
					value = mull(top, bottom);
311
				} else if(ownbuf[i] == '/') {
312
					value = divl(bottom, top);
313
				}
314
				stack[sp++] = value;
315
			}
316
			stack[sp] = 0;
317
		} else if(ownbuf[i] == ' ' && put == 1) {
318
			stack[++sp] = 0;
319
		}
320
	}
321
	result = stack[0];
322
	*number = result;
323
	return 1;
324
}
325
 
326
/* arr gets sorted, arr2 index gets replaced */
327
void sort(int* arr, int* arr2, int size) {
328
	int i;
329
redo:
330
	for(i = 1; i < size; i++) {
331
		if(arr[i - 1] > arr[i]) {
332
			int tmp = arr[i];
333
			arr[i] = arr[i - 1];
334
			arr[i - 1] = tmp;
335
			tmp = arr2[i];
336
			arr2[i] = arr2[i - 1];
337
			arr2[i - 1] = tmp;
338
		}
339
	}
340
	for(i = 1; i < size; i++) {
341
		if(arr[i - 1] > arr[i]) {
342
			goto redo;
343
		}
344
	}
345
}
346
 
347
int run(char* cmd, int linenum, char num, int* lgoto) {
4 nishi 348
	char line[LINE_BUFFER_SIZE];
349
	char rcmd[32];
350
	int i;
351
	char* arg;
352
	int incr = 0;
2 nishi 353
#ifdef BREAKKEY
354
	if(agetch() == 1) return -1;
355
#endif
356
	if(lgoto != 0) *lgoto = 0;
357
	for(i = 0; cmd[i] != 0; i++) line[i] = cmd[i];
358
	line[i] = 0;
359
	rcmd[0] = 0;
360
	for(i = 0;; i++) {
361
		if(line[i] == ' ' || line[i] == '\t' || line[i] == 0 || line[i] == '"') {
362
			break;
363
		} else {
364
			rcmd[incr++] = line[i];
365
			if(incr == 32) {
366
				putstr("! Command too long");
367
				if(linenum != -1) {
368
					putstr(" in line ");
369
					putnum(linenum);
370
				}
371
				putstr(NEWLINE);
372
				return 1;
373
			}
374
			rcmd[incr] = 0;
375
		}
376
	}
4 nishi 377
	arg = line + 1 + strlen(rcmd);
2 nishi 378
	if(strcaseequ(rcmd, "COLOR")) {
379
		int argc = 0;
380
		char* farg = 0;
381
		char* sarg = 0;
4 nishi 382
		int fgcolor, bgcolor, ret0, ret1;
2 nishi 383
		if(arg[0] != 0) argc++;
384
		for(i = 0; arg[i] != 0; i++) {
385
			if(arg[i] == ',') {
386
				arg[i] = 0;
387
				farg = arg;
388
				sarg = arg + i + 1;
389
				for(; *sarg != 0 && (*sarg == '\t' || *sarg == ' '); sarg++)
390
					;
391
				argc++;
392
			}
393
		}
394
		if(argc != 2) {
395
			putstr("! Invalid argument");
396
			if(linenum != -1) {
397
				putstr(" in line ");
398
				putnum(linenum);
399
			}
400
			putstr(NEWLINE);
401
			return 1;
402
		}
4 nishi 403
		bgcolor = 0;
404
		fgcolor = 0;
405
		ret0 = pexpr(farg, 0, &bgcolor);
406
		ret1 = pexpr(sarg, 0, &fgcolor);
2 nishi 407
		if(ret0 == 0) {
408
			putstr("! Invalid argument");
409
			if(linenum != -1) {
410
				putstr(" in line ");
411
				putnum(linenum);
412
			}
413
			putstr(NEWLINE);
414
			return 1;
415
		} else if(ret0 == -1) {
416
			putstr("! Syntax error");
417
			if(linenum != -1) {
418
				putstr(" in line ");
419
				putnum(linenum);
420
			}
421
			putstr(NEWLINE);
422
			return 1;
423
		}
424
		if(ret1 == 1) {
425
			change_color((fgcolor << 4) | bgcolor);
426
		} else if(ret1 == 0) {
427
			putstr("! Invalid argument");
428
			if(linenum != -1) {
429
				putstr(" in line ");
430
				putnum(linenum);
431
			}
432
			putstr(NEWLINE);
433
			return 1;
434
		} else if(ret1 == -1) {
435
			putstr("! Syntax error");
436
			if(linenum != -1) {
437
				putstr(" in line ");
438
				putnum(linenum);
439
			}
440
			putstr(NEWLINE);
441
			return 1;
442
		}
443
	} else if(num == 0 && strcaseequ(rcmd, "LIST")) {
444
		int addr = BUFFER_SIZE - 1;
445
		int saddr = 0;
446
		int lbuf[LINES];
447
		int shift[LINES];
448
		int cnt = 0;
4 nishi 449
		int i;
2 nishi 450
		while(1) {
451
			unsigned long ln = 0;
452
			for(i = 0; i < 4; i++) {
453
				ln >>= 8;
454
				ln |= (unsigned long)basicbuffer[addr--] << 24;
455
			}
456
			if(ln == 0) break;
457
			lbuf[cnt] = ln;
458
			shift[cnt++] = saddr;
459
			saddr += strlen(basicbuffer + saddr) + 1;
460
		}
461
		sort(lbuf, shift, cnt);
462
		for(i = 0; i < cnt; i++) {
463
			putnum(lbuf[i]);
464
			putstr(" ");
465
			putstr(basicbuffer + shift[i]);
466
			putstr(NEWLINE);
467
		}
468
	} else if(num == 1 && strcaseequ(rcmd, "GOTO")) {
469
		int ret = pexpr(arg, 0, lgoto);
470
		if(ret == 0) {
471
			putstr("! Invalid argument");
472
			if(linenum != -1) {
473
				putstr(" in line ");
474
				putnum(linenum);
475
			}
476
			putstr(NEWLINE);
477
			return 1;
478
		} else if(ret == -1) {
479
			putstr("! Syntax error");
480
			if(linenum != -1) {
481
				putstr(" in line ");
482
				putnum(linenum);
483
			}
484
			putstr(NEWLINE);
485
			return 1;
486
		}
487
	} else if(num == 0 && strcaseequ(rcmd, "RUN")) {
488
		int addr = BUFFER_SIZE - 1;
489
		int saddr = 0;
490
		int lbuf[LINES];
491
		int shift[LINES];
492
		int cnt = 0;
4 nishi 493
		int gt, i;
2 nishi 494
		while(1) {
495
			unsigned long ln = 0;
496
			for(i = 0; i < 4; i++) {
497
				ln >>= 8;
498
				ln |= (unsigned long)basicbuffer[addr--] << 24;
499
			}
500
			if(ln == 0) break;
501
			lbuf[cnt] = ln;
502
			shift[cnt++] = saddr;
503
			saddr += strlen(basicbuffer + saddr) + 1;
504
		}
505
		sort(lbuf, shift, cnt);
506
		for(i = 0; i < cnt; i++) {
507
			int ret = run(basicbuffer + shift[i], lbuf[i], 1, &gt);
508
			if(ret != 0) return ret;
509
			if(gt != 0) {
4 nishi 510
				char found;
2 nishi 511
				for(i = 0; i < cnt; i++) {
512
					if(lbuf[i] == gt) {
513
						found = 1;
514
						break;
515
					}
516
				}
517
				if(found) {
518
					i--;
519
				} else {
520
					putstr("! GOTO no such line");
521
					if(linenum != -1) {
522
						putstr(" in line ");
523
						putnum(linenum);
524
					}
525
					putstr(NEWLINE);
526
					return 1;
527
				}
528
			}
529
		}
530
	} else {
531
		putstr("! Unknown command");
532
		if(linenum != -1) {
533
			putstr(" in line ");
534
			putnum(linenum);
535
		}
536
		putstr(NEWLINE);
537
		return 1;
538
	}
539
	return 0;
540
}
541
 
542
int execute(int linenum, char* cmd, char num) {
543
	int i;
544
	char line[LINE_BUFFER_SIZE];
545
	int incr = 0;
546
	char dq = 0;
547
	for(i = 0; cmd[i] != 0; i++) {
548
		if(cmd[i] == ' ' || cmd[i] == '\t') {
549
			if(!dq) {
550
				for(; cmd[i] != 0 && (cmd[i] == ' ' || cmd[i] == '\t'); i++)
551
					;
552
				i--;
553
			}
554
			line[incr++] = cmd[i];
555
		} else if(cmd[i] == '"') {
556
			line[incr++] = '"';
557
			dq = dq == 0 ? 1 : 0;
558
		} else {
559
			line[incr++] = dq == 0 ? toupper(cmd[i]) : cmd[i];
560
		}
561
	}
562
	line[incr] = 0;
563
	if(num == 0) {
564
		int ret = run(line, -1, 0, 0);
6 nishi 565
		putstr("Ready");
566
		putstr(NEWLINE);
2 nishi 567
		return ret;
568
	} else {
569
		int addr = BUFFER_SIZE - 1;
570
		int i;
571
		int shf = 0;
572
		int cnt = 0;
4 nishi 573
		int len;
2 nishi 574
		while(1) {
575
			unsigned long ln = 0;
576
			for(i = 0; i < 4; i++) {
577
				ln >>= 8;
578
				ln |= (unsigned long)basicbuffer[addr--] << 24;
579
			}
580
			cnt++;
581
			if(ln == linenum) shf = cnt;
582
			if(shf != 0) {
583
				addr += 4;
584
				for(i = 0; i < 4; i++) {
585
					basicbuffer[addr] = basicbuffer[addr - 4 * shf];
586
					addr--;
587
				}
588
				addr += 4;
589
				ln = 0;
590
				for(i = 0; i < 4; i++) {
591
					ln >>= 8;
592
					ln |= (unsigned long)basicbuffer[addr--] << 24;
593
				}
594
			}
595
			if(ln == 0) break;
596
		}
597
		if(line[0] != 0) {
598
			addr += 4;
599
			for(i = 0; i < 4; i++) {
600
				basicbuffer[addr--] = linenum & 0xff;
601
				linenum >>= 8;
602
			}
603
		}
4 nishi 604
		len = 0;
2 nishi 605
		cnt = 0;
606
		while(1) {
607
			int slen = strlen(basicbuffer + len);
608
			if(slen == 0) break;
609
			len += slen + 1;
610
			cnt++;
611
		}
612
		if(line[0] != 0) {
613
			for(i = 0; line[i] != 0; i++) {
614
				basicbuffer[len + i] = line[i];
615
			}
616
			basicbuffer[len + i] = 0;
617
			basicbuffer[len + i + 1] = 0;
618
		}
619
		if(shf != 0) {
620
			cnt = 0;
621
			len = 0;
622
			while(1) {
623
				int slen = strlen(basicbuffer + len);
624
				if(slen == 0) break;
625
 
626
				len += slen + 1;
627
				cnt++;
628
 
629
				if(cnt == shf) {
630
					int i;
631
					int nc = 0;
4 nishi 632
					len -= slen + 1;
2 nishi 633
					for(i = len;; i++) {
634
						basicbuffer[i] = basicbuffer[i + slen + 1];
635
						if(basicbuffer[i] == 0) {
636
							nc++;
637
							if(nc == 2) break;
638
						} else {
639
							nc = 0;
640
						}
641
					}
642
					break;
643
				}
644
			}
645
		}
646
		return 0;
647
	}
648
}
649
 
650
void basic(void) {
651
	int i;
4 nishi 652
	int lineind;
2 nishi 653
	clear();
654
 
655
#ifdef SMALL
656
	putstr("Krakow BASIC  Ver. ");
657
	putstr(VERSION);
658
	putstr(NEWLINE);
659
	putstr(NEWLINE);
660
#else
661
	putstr(PLATFORM);
662
	putstr("   Krakow BASIC V");
663
	putstr(VERSION);
6 nishi 664
	putstr(NEWLINE);
665
	putstr("Copyright 2024 by: Nishi.");
666
	putstr(NEWLINE);
2 nishi 667
	putstr("                   penguin2233.");
668
	putstr(NEWLINE);
669
	putstr(NEWLINE);
670
	putstr(" Max ");
671
	putnum(LINE_BUFFER_SIZE);
672
	putstr(" characters per line");
673
	putstr(NEWLINE);
674
	putstr(" Max ");
675
	putnum(LINES);
676
	putstr(" lines");
677
	putstr(NEWLINE);
678
	putstr(" ");
679
#endif
680
	putnum(BUFFER_SIZE);
681
	putstr(" bytes free");
682
	putstr(NEWLINE);
683
	putstr(NEWLINE);
684
 
685
	for(i = 0; i < BUFFER_SIZE; i++) {
686
		basicbuffer[i] = 0;
687
	}
688
	putstr("Ready");
689
	putstr(NEWLINE);
690
 
691
	cursor();
692
	linebuf[0] = 0;
4 nishi 693
	lineind = 0;
2 nishi 694
	while(1) {
4 nishi 695
		char c;
6 nishi 696
#if defined(PLATFORM_C64) || defined(PLATFORM_A800XL)
4 nishi 697
		c = oggetch(1);
698
#else
699
		c = agetch();
700
#endif
2 nishi 701
		if(c != 0) killcursor();
702
		if(c == 1) {
703
			putstr("Break");
704
			putstr(NEWLINE);
705
			lineind = 0;
706
		} else if(c == '\n') {
4 nishi 707
			int i;
708
			char num = 1;
709
			char* cmd = linebuf;
710
 
2 nishi 711
			linebuf[lineind] = 0;
712
			putstr(NEWLINE);
713
			if(lineind == 0) goto skip;
714
 
715
			for(i = 0; linebuf[i] != 0; i++) {
716
				if(linebuf[i] == ' ') {
717
					linebuf[i] = 0;
718
					cmd = linebuf + i + 1;
719
					break;
720
				} else if(!('0' <= linebuf[i] && linebuf[i] <= '9')) {
721
					num = 0;
722
					break;
723
				}
724
			}
725
 
726
			if(num == 1 && strnum(linebuf) == 0) {
727
				putstr("! Line number 0 is illegal");
728
				putstr(NEWLINE);
729
			} else {
730
				int ret = execute(num == 1 ? strnum(linebuf) : -1, (num == 1 && cmd == linebuf) ? "" : cmd, num);
731
				if(ret == -1) {
732
					putstr("! Break");
733
					putstr(NEWLINE);
734
				}
735
			}
736
 
737
		skip:
738
			lineind = 0;
739
		} else if(c == 0x8 || c == 0x7f) {
740
			if(lineind > 0) {
6 nishi 741
#if defined(PLATFORM_A800XL)
742
				putstr("\x7e \x7e");
743
#else
2 nishi 744
				putstr("\x08 \x08");
6 nishi 745
#endif
2 nishi 746
				linebuf[--lineind] = 0;
747
			}
748
		} else if(c == -1) {
749
			break;
750
		} else if(c != 0) {
751
			putchar(c);
752
			linebuf[lineind++] = c;
753
		}
754
		cursor();
755
	}
756
}