Subversion Repositories Shiroi

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8 nishi 1
/* $Id: basic.c 35 2024-09-01 15:14:41Z nishi $ */
2
 
18 nishi 3
#include "dri/text.h"
32 nishi 4
#include "dri/video.h"
5
#include "dri/math.h"
8 nishi 6
 
32 nishi 7
#include "mem.h"
29 nishi 8
#include "char.h"
8 nishi 9
 
35 nishi 10
#define VERSION "0.0"
32 nishi 11
#define LINE_BUFFER_SIZE 512
12
#define BUFFER_SIZE (1024 * 24)
29 nishi 13
 
14
unsigned char basicbuffer[BUFFER_SIZE];
32 nishi 15
char linebuf[LINE_BUFFER_SIZE];
29 nishi 16
 
32 nishi 17
int pexpr(char* expr, char* buffer, int* number){
18
	char ownbuf[128];
19
	int i;
20
	for(i = 0; expr[i] != 0; i++) ownbuf[i] = expr[i];
21
	ownbuf[i] = 0;
22
	int start = 0;
23
	int br = 0;
24
	int result = 0;
25
	int stack[128];
26
	int sp = 0;
27
	char put = 0;
28
	for(i = 0; i < 128; i++) stack[i] = 0;
29
	for(i = 0;; i++){
30
		if(ownbuf[i] == 0){
31
			break;
32
		}else if('0' <= ownbuf[i] && ownbuf[i] <= '9'){
33
			stack[sp] *= 10;
34
			stack[sp] += ownbuf[i] - '0';
35
			put = 1;
36
		}else if(ownbuf[i] == '+' || ownbuf[i] == '-' || ownbuf[i] == '*' || ownbuf[i] == '/'){
37
			put = 0;
38
			if(sp < 2){
39
				return -1;
40
			}else{
41
				int top = stack[--sp];
42
				int bottom = stack[--sp];
43
				int value = 0;
44
				if(ownbuf[i] == '+'){
45
					value = top + bottom;
46
				}else if(ownbuf[i] == '-'){
47
					value = bottom + top;
48
				}else if(ownbuf[i] == '*'){
49
					value = mull(top, bottom);
50
				}else if(ownbuf[i] == '/'){
51
					value = divl(bottom, top);
52
				}
53
				stack[sp++] = value;
54
			}
55
			stack[sp] = 0;
56
		}else if(ownbuf[i] == ' ' && put == 1){
57
			stack[++sp] = 0;
58
		}
59
	}
60
	result = stack[0];
61
	*number = result;
62
	return 1;
63
}
64
 
33 nishi 65
/* arr gets sorted, arr2 index gets replaced */
66
void sort(int* arr, int* arr2, int size){
67
	int i;
68
redo:
69
	for(i = 1; i < size; i++){
70
		if(arr[i - 1] > arr[i]){
71
			int tmp = arr[i];
72
			arr[i] = arr[i - 1];
73
			arr[i - 1] = tmp;
74
			tmp = arr2[i];
75
			arr2[i] = arr2[i - 1];
76
			arr2[i - 1] = tmp;
77
		}
78
	}
79
	for(i = 1; i < size; i++){
80
		if(arr[i - 1] > arr[i]){
81
			goto redo;
82
		}
83
	}
84
}
85
 
86
int run(char* cmd, int linenum, char num, int* lgoto){
87
	if(agetch() == 1) return -1;
32 nishi 88
	char line[LINE_BUFFER_SIZE];
89
	char rcmd[32];
90
	int i;
33 nishi 91
	if(lgoto != 0) *lgoto = 0;
32 nishi 92
	for(i = 0; cmd[i] != 0; i++) line[i] = cmd[i];
93
	line[i] = 0;
94
	rcmd[0] = 0;
95
	int incr = 0;
96
	for(i = 0;; i++){
97
		if(line[i] == ' ' || line[i] == '\t' || line[i] == 0 || line[i] == '"'){
98
			break;
99
		}else{
100
			rcmd[incr++] = line[i];
101
			if(incr == 32){
102
				putstr("! Command too long");
103
				if(linenum != -1){
104
					putstr(" in line ");
105
					putnum(linenum);
106
				}
107
				putstr("\r\n");
108
				return 1;
109
			}
110
			rcmd[incr] = 0;
111
		}
112
	}
113
	char* arg = line + 1 + strlen(rcmd);
114
	if(strcaseequ(rcmd, "COLOR")){
115
		int argc = 0;
116
		char* farg = 0;
117
		char* sarg = 0;
118
		if(arg[0] != 0) argc++;
119
		for(i = 0; arg[i] != 0; i++){
120
			if(arg[i] == ','){
121
				arg[i] = 0;
122
				farg = arg;
123
				sarg = arg + i + 1;
124
				for(; *sarg != 0 && (*sarg == '\t' || *sarg == ' '); sarg++);
125
				argc++;
126
			}
127
		}
128
		if(argc != 2){
129
			putstr("! Invalid argument");
130
			if(linenum != -1){
131
				putstr(" in line ");
132
				putnum(linenum);
133
			}
134
			putstr("\r\n");
135
			return 1;
136
		}
137
		int bgcolor = 0;
138
		int fgcolor = 0;
139
		int ret0 = pexpr(farg, 0, &bgcolor);
140
		int ret1 = pexpr(sarg, 0, &fgcolor);
141
		if(ret0 == 0){
142
			putstr("! Invalid argument");
143
			if(linenum != -1){
144
				putstr(" in line ");
145
				putnum(linenum);
146
			}
147
			putstr("\r\n");
148
			return 1;
149
		}else if(ret0 == -1){
150
			putstr("! Syntax error");
151
			if(linenum != -1){
152
				putstr(" in line ");
153
				putnum(linenum);
154
			}
155
			putstr("\r\n");
156
			return 1;
157
		}
158
		if(ret1 == 1){
159
			change_color((fgcolor << 4) | bgcolor);
160
		}else if(ret1 == 0){
161
			putstr("! Invalid argument");
162
			if(linenum != -1){
163
				putstr(" in line ");
164
				putnum(linenum);
165
			}
166
			putstr("\r\n");
167
			return 1;
168
		}else if(ret1 == -1){
169
			putstr("! Syntax error");
170
			if(linenum != -1){
171
				putstr(" in line ");
172
				putnum(linenum);
173
			}
174
			putstr("\r\n");
175
			return 1;
176
		}
33 nishi 177
	}else if(num == 0 && strcaseequ(rcmd, "LIST")){
178
		int addr = BUFFER_SIZE - 1;
179
		int saddr = 0;
180
		int lbuf[1024];
181
		int shift[1024];
182
		int cnt = 0;
183
		while(1){
184
			unsigned long ln = 0;
185
			for(i = 0; i < 4; i++){
186
				ln >>= 8;
187
				ln |= (unsigned long)basicbuffer[addr--] << 24;
188
			}
189
			if(ln == 0) break;
190
			lbuf[cnt] = ln;
191
			shift[cnt++] = saddr;
192
			saddr += strlen(basicbuffer + saddr) + 1;
193
		}
194
		sort(lbuf, shift, cnt);
195
		int i;
196
		for(i = 0; i < cnt; i++){
197
			putnum(lbuf[i]);
198
			putstr(" ");
199
			putstr(basicbuffer + shift[i]);
200
			putstr("\r\n");
201
		}
202
	}else if(num == 1 && strcaseequ(rcmd, "GOTO")){
203
		int ret = pexpr(arg, 0, lgoto);
204
		if(ret == 0){
205
			putstr("! Invalid argument");
206
			if(linenum != -1){
207
				putstr(" in line ");
208
				putnum(linenum);
209
			}
210
			putstr("\r\n");
211
			return 1;
212
		}else if(ret == -1){
213
			putstr("! Syntax error");
214
			if(linenum != -1){
215
				putstr(" in line ");
216
				putnum(linenum);
217
			}
218
			putstr("\r\n");
219
			return 1;
220
		}
221
	}else if(num == 0 && strcaseequ(rcmd, "RUN")){
222
		int addr = BUFFER_SIZE - 1;
223
		int saddr = 0;
224
		int lbuf[1024];
225
		int shift[1024];
226
		int cnt = 0;
227
		int gt;
228
		while(1){
229
			unsigned long ln = 0;
230
			for(i = 0; i < 4; i++){
231
				ln >>= 8;
232
				ln |= (unsigned long)basicbuffer[addr--] << 24;
233
			}
234
			if(ln == 0) break;
235
			lbuf[cnt] = ln;
236
			shift[cnt++] = saddr;
237
			saddr += strlen(basicbuffer + saddr) + 1;
238
		}
239
		sort(lbuf, shift, cnt);
240
		int i;
241
		for(i = 0; i < cnt; i++){
242
			int ret = run(basicbuffer + shift[i], lbuf[i], 1, &gt);
243
			if(ret != 0) return ret;
244
			if(gt != 0){
245
				char found = 0;
246
				for(i = 0; i < cnt; i++){
247
					if(lbuf[i] == gt){
248
						found = 1;
249
						break;
250
					}
251
				}
252
				if(found){
253
					i--;
254
				}else{
255
					putstr("! GOTO no such line");
256
					if(linenum != -1){
257
						putstr(" in line ");
258
						putnum(linenum);
259
					}
260
					putstr("\r\n");
261
					return 1;
262
				}
263
			}
264
		}
32 nishi 265
	}else{
266
		putstr("! Unknown command");
267
		if(linenum != -1){
268
			putstr(" in line ");
269
			putnum(linenum);
270
		}
271
		putstr("\r\n");
272
		return 1;
273
	}
274
	return 0;
275
}
276
 
33 nishi 277
int execute(int linenum, char* cmd, char num){
32 nishi 278
	int i;
279
	char line[LINE_BUFFER_SIZE];
280
	int incr = 0;
281
	char dq = 0;
282
	for(i = 0; cmd[i] != 0; i++){
283
		if(cmd[i] == ' ' || cmd[i] == '\t'){
284
			if(!dq){
285
				for(; cmd[i] != 0 && (cmd[i] == ' ' || cmd[i] == '\t'); i++);
286
				i--;
287
			}
288
			line[incr++] = cmd[i];
289
		}else if(cmd[i] == '"'){
290
			line[incr++] = '"';
291
			dq = dq == 0 ? 1 : 0;
292
		}else{
293
			line[incr++] = dq == 0 ? toupper(cmd[i]) : cmd[i];
294
		}
295
	}
296
	line[incr] = 0;
297
	if(num == 0){
33 nishi 298
		int ret = run(line, -1, 0, 0);
32 nishi 299
		putstr("Ready\r\n");
33 nishi 300
		return ret;
32 nishi 301
	}else{
302
		int addr = BUFFER_SIZE - 1;
303
		int i;
304
		int shf = 0;
305
		int cnt = 0;
306
		while(1){
307
			unsigned long ln = 0;
308
			for(i = 0; i < 4; i++){
309
				ln >>= 8;
310
				ln |= (unsigned long)basicbuffer[addr--] << 24;
311
			}
312
			cnt++;
313
			if(ln == linenum) shf = cnt;
314
			if(shf != 0){
315
				addr += 4;
316
				for(i = 0; i < 4; i++){
317
					basicbuffer[addr] = basicbuffer[addr - 4 * shf];
318
					addr--;
319
				}
320
				addr += 4;
321
				ln = 0;
322
				for(i = 0; i < 4; i++){
323
					ln >>= 8;
324
					ln |= (unsigned long)basicbuffer[addr--] << 24;
325
				}
326
			}
327
			if(ln == 0) break;
328
		}
329
		if(line[0] != 0){
330
			addr += 4;
331
			for(i = 0; i < 4; i++){
332
				basicbuffer[addr--] = linenum & 0xff;
333
				linenum >>= 8;
334
			}
335
		}
336
		int len = 0;
337
		cnt = 0;
338
		while(1){
339
			int slen = strlen(basicbuffer + len);
340
			if(slen == 0) break;
341
			len += slen + 1;
342
			cnt++;
343
		}
344
		if(line[0] != 0){
345
			for(i = 0; line[i] != 0; i++){
346
				basicbuffer[len + i] = line[i];
347
			}
348
			basicbuffer[len + i] = 0;
349
			basicbuffer[len + i + 1] = 0;
350
		}
351
		if(shf != 0){
352
			cnt = 0;
353
			len = 0;
354
			while(1){
355
				int slen = strlen(basicbuffer + len);
356
				if(slen == 0) break;
357
 
358
				len += slen + 1;
359
				cnt++;
360
 
361
				if(cnt == shf){
362
					len -= slen + 1;
363
					int i;
364
					int nc = 0;
365
					for(i = len;; i++){
366
						basicbuffer[i] = basicbuffer[i + slen + 1];
367
						if(basicbuffer[i] == 0){
368
							nc++;
369
							if(nc == 2) break;
370
						}else{
371
							nc = 0;
372
						}
373
					}
374
					break;
375
				}
376
			}
377
		}
33 nishi 378
		return 0;
32 nishi 379
	}
380
}
381
 
8 nishi 382
void basic(void){
35 nishi 383
	int i;
8 nishi 384
	clear();
385
 
35 nishi 386
	putstr(PLATFORM);
387
	putstr("   Krakow BASIC V");
388
	putstr(VERSION);
389
	putstr("\r\n");
390
	putstr("Copyright 2024 by: Nishi.\r\n");
391
	putstr("                   penguin2233.\r\n\r\n ");
29 nishi 392
	putnum(BUFFER_SIZE);
393
	putstr(" bytes free\r\n");
35 nishi 394
	putstr("\r\n");
32 nishi 395
 
396
	for(i = 0; i < BUFFER_SIZE; i++){
397
		basicbuffer[i] = 0;
398
	}
399
	putstr("Ready\r\n");
400
 
8 nishi 401
	cursor();
29 nishi 402
	linebuf[0] = 0;
28 nishi 403
	int lineind = 0;
8 nishi 404
	while(1){
12 nishi 405
		char c = agetch();
20 nishi 406
		if(c != 0) killcursor();
407
		if(c == 1){
408
			putstr("Break\r\n");
28 nishi 409
			lineind = 0;
20 nishi 410
		}else if(c == '\n'){
29 nishi 411
			linebuf[lineind] = 0;
8 nishi 412
			putstr("\r\n");
32 nishi 413
			if(lineind == 0) goto skip;
414
 
415
			int i;
416
			char num = 1;
417
 
418
			char* cmd = linebuf;
419
 
420
			for(i = 0; linebuf[i] != 0; i++){
421
				if(linebuf[i] == ' '){
422
					linebuf[i] = 0;
423
					cmd = linebuf + i + 1;
424
					break;
425
				}else if(!('0' <= linebuf[i] && linebuf[i] <= '9')){
426
					num = 0;
427
					break;
428
				}
429
			}
430
 
431
			if(num == 1 && strnum(linebuf) == 0){
432
				putstr("! Line number 0 is illegal\r\n");
433
			}else{
33 nishi 434
				int ret = execute(num == 1 ? strnum(linebuf) : -1, (num == 1 && cmd == linebuf) ? "" : cmd, num);
435
				if(ret == -1){
436
					putstr("! Break\r\n");
437
				}
32 nishi 438
			}
439
 
440
skip:
28 nishi 441
			lineind = 0;
442
		}else if(c == 0x8){
443
			if(lineind > 0){
444
				putstr("\x08 \x08");
445
				lineind--;
446
			}
12 nishi 447
		}else if(c != 0){
8 nishi 448
			putchar(c);
29 nishi 449
			linebuf[lineind++] = c;
8 nishi 450
		}
451
		cursor();
452
	}
453
}