Dies ist eine alte Version des Dokuments!
// erlaubte Zeichen für Mini-BASIC
static int is_allowed_basic_char(char c) {
if (c == ' ' || c == '.' || c == '"' || c == '=' || c == '+' || c == '-' ||
c == '*' || c == '/' || c == '(' || c == ')' || c == '<' || c == '>' ||
c == ',' ) return 1;
if (c >= 'A' && c <= 'Z') return 1;
if (c >= '0' && c <= '9') return 1;
return 0;
}
// ===================== MINI BASIC (int-only) =====================
#define BASIC_MAX_LINES 64
#define BASIC_LINE_LEN 96
typedef struct {
uint16 line_no;
uint8 used;
char text[BASIC_LINE_LEN];
} BasicLine;
static BasicLine g_prog[BASIC_MAX_LINES];
static int g_vars[26]; // A..Z
static void basic_reset_program(void) {
for (int i = 0; i < BASIC_MAX_LINES; i++) {
g_prog[i].used = 0;
g_prog[i].line_no = 0;
g_prog[i].text[0] = 0;
}
}
static void basic_reset_vars(void) {
for (int i = 0; i < 26; i++) g_vars[i] = 0;
}
static int is_space(char c) { return c == ' ' || c == '\t'; }
static char up(char c) {
if (c >= 'a' && c <= 'z') return (char)(c - 'a' + 'A');
return c;
}
static void skip_spaces(const char **p) {
while (**p && is_space(**p)) (*p)++;
}
static int is_digit(char c) { return (c >= '0' && c <= '9'); }
static int is_alpha(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); }
static int starts_with_kw(const char *s, const char *kw) {
// case-insensitive, kw muss "Wortgrenze" haben (Ende oder Space)
int i = 0;
while (kw[i]) {
if (up(s[i]) != kw[i]) return 0;
i++;
}
char next = s[i];
return (next == 0 || is_space(next));
}
static uint16 parse_u16(const char **p) {
skip_spaces(p);
uint16 v = 0;
while (is_digit(**p)) {
v = (uint16)(v * 10 + (**p - '0'));
(*p)++;
}
return v;
}
static int parse_int(const char **p) {
skip_spaces(p);
int sign = 1;
if (**p == '+') { (*p)++; }
else if (**p == '-') { sign = -1; (*p)++; }
int v = 0;
while (is_digit(**p)) {
v = v * 10 + (**p - '0');
(*p)++;
}
return v * sign;
}
static int find_line_index(uint16 line_no) {
for (int i = 0; i < BASIC_MAX_LINES; i++) {
if (g_prog[i].used && g_prog[i].line_no == line_no) return i;
}
return -1;
}
static int find_free_slot(void) {
for (int i = 0; i < BASIC_MAX_LINES; i++) {
if (!g_prog[i].used) return i;
}
return -1;
}
static int find_next_line_sorted(uint16 last_line, uint16 *out_line, int *out_idx) {
int found = 0;
uint16 best = 0xFFFF;
int best_i = -1;
for (int i = 0; i < BASIC_MAX_LINES; i++) {
if (!g_prog[i].used) continue;
uint16 ln = g_prog[i].line_no;
if (ln > last_line && ln < best) {
best = ln;
best_i = i;
found = 1;
}
}
if (!found) return 0;
*out_line = best;
*out_idx = best_i;
return 1;
}
static void basic_store_line(uint16 line_no, const char *rest) {
// rest: nach der Zeilennummer (inkl. leading spaces)
// Wenn rest leer -> löschen
const char *p = rest;
skip_spaces(&p);
int idx = find_line_index(line_no);
if (*p == 0) {
if (idx >= 0) g_prog[idx].used = 0;
return;
}
if (idx < 0) {
idx = find_free_slot();
if (idx < 0) {
print_new_line();
print_string("BASIC: OUT OF PROGRAM SPACE");
return;
}
g_prog[idx].used = 1;
g_prog[idx].line_no = line_no;
}
// copy text, uppercase keywords funktionieren trotzdem case-insensitive
int j = 0;
while (*p && j < BASIC_LINE_LEN - 1) {
g_prog[idx].text[j++] = *p++;
}
g_prog[idx].text[j] = 0;
}
static void basic_list(void) {
uint16 last = 0;
uint16 ln;
int idx;
while (find_next_line_sorted(last, &ln, &idx)) {
print_new_line();
print_int((int)ln);
print_string(" ");
print_string(g_prog[idx].text);
last = ln;
}
}
static void basic_error(const char *msg) {
print_new_line();
print_string("BASIC ERROR: ");
print_string((char*)msg);
}
// ---------- Expression parser (recursive descent) ----------
static int parse_expr(const char **p); // forward
static int parse_factor(const char **p) {
skip_spaces(p);
// unary
if (**p == '+') { (*p)++; return parse_factor(p); }
if (**p == '-') { (*p)++; return -parse_factor(p); }
if (**p == '(') {
(*p)++;
int v = parse_expr(p);
skip_spaces(p);
if (**p == ')') (*p)++;
else basic_error("MISSING )");
return v;
}
// variable
if (is_alpha(**p)) {
char c = up(**p);
(*p)++;
if (c >= 'A' && c <= 'Z') return g_vars[c - 'A'];
return 0;
}
// number
if (is_digit(**p)) {
return parse_int(p);
}
basic_error("BAD FACTOR");
return 0;
}
static int parse_term(const char **p) {
int v = parse_factor(p);
for (;;) {
skip_spaces(p);
if (**p == '*') { (*p)++; v = v * parse_factor(p); }
else if (**p == '/') {
(*p)++;
int d = parse_factor(p);
if (d == 0) { basic_error("DIV BY ZERO"); return 0; }
v = v / d;
} else break;
}
return v;
}
static int parse_expr(const char **p) {
int v = parse_term(p);
for (;;) {
skip_spaces(p);
if (**p == '+') { (*p)++; v = v + parse_term(p); }
else if (**p == '-') { (*p)++; v = v - parse_term(p); }
else break;
}
return v;
}
static int parse_relop(const char **p, const char **out_op) {
skip_spaces(p);
// supported: =, <, >, <=, >=, <>
if (**p == '=') { *out_op = "="; (*p)++; return 1; }
if (**p == '<') {
(*p)++;
if (**p == '=') { *out_op = "<="; (*p)++; return 1; }
if (**p == '>') { *out_op = "<>"; (*p)++; return 1; }
*out_op = "<"; return 1;
}
if (**p == '>') {
(*p)++;
if (**p == '=') { *out_op = ">="; (*p)++; return 1; }
*out_op = ">"; return 1;
}
return 0;
}
static int eval_relation(int a, int b, const char *op) {
if (op[0] == '=' && op[1] == 0) return a == b;
if (op[0] == '<' && op[1] == 0) return a < b;
if (op[0] == '>' && op[1] == 0) return a > b;
if (op[0] == '<' && op[1] == '=') return a <= b;
if (op[0] == '>' && op[1] == '=') return a >= b;
if (op[0] == '<' && op[1] == '>') return a != b;
return 0;
}
// ---------- Statement execution ----------
static int basic_exec_stmt(const char *line, uint16 *pc_line /*in/out*/, int *stop /*out*/) {
const char *p = line;
skip_spaces(&p);
if (*p == 0) return 1;
// REM
if (starts_with_kw(p, "REM")) return 1;
// END
if (starts_with_kw(p, "END")) { *stop = 1; return 1; }
// PRINT
if (starts_with_kw(p, "PRINT")) {
p += 5;
skip_spaces(&p);
// PRINT "TEXT"
if (*p == '"') {
p++;
print_new_line();
while (*p && *p != '"') {
print_char(*p++);
}
if (*p == '"') p++;
return 1;
}
// PRINT expr
int v = parse_expr(&p);
print_new_line();
print_int(v);
return 1;
}
// LET (optional)
if (starts_with_kw(p, "LET")) {
p += 3;
skip_spaces(&p);
}
// IF expr rel expr THEN line
if (starts_with_kw(p, "IF")) {
p += 2;
int left = parse_expr(&p);
const char *op = 0;
if (!parse_relop(&p, &op)) { basic_error("IF NEEDS RELOP"); return 0; }
int right = parse_expr(&p);
skip_spaces(&p);
if (!starts_with_kw(p, "THEN")) { basic_error("IF NEEDS THEN"); return 0; }
p += 4;
uint16 target = parse_u16(&p);
if (target == 0) { basic_error("BAD THEN LINE"); return 0; }
if (eval_relation(left, right, op)) {
*pc_line = (uint16)(target - 1); // Trick: RUN loop nimmt "next > pc_line"
}
return 1;
}
// GOTO line
if (starts_with_kw(p, "GOTO")) {
p += 4;
uint16 target = parse_u16(&p);
if (target == 0) { basic_error("BAD GOTO LINE"); return 0; }
*pc_line = (uint16)(target - 1);
return 1;
}
// Assignment: A = expr
if (is_alpha(*p)) {
char vname = up(*p++);
if (vname < 'A' || vname > 'Z') { basic_error("BAD VAR"); return 0; }
skip_spaces(&p);
if (*p != '=') { basic_error("EXPECTED ="); return 0; }
p++;
int value = parse_expr(&p);
g_vars[vname - 'A'] = value;
return 1;
}
basic_error("UNKNOWN STATEMENT");
return 0;
}
static void basic_run(void) {
uint16 pc = 0; // last executed line_no (for sorted iteration)
int stop = 0;
// Start at "before" first line:
pc = 0;
while (!stop) {
uint16 ln;
int idx;
if (!find_next_line_sorted(pc, &ln, &idx)) break;
// execute
uint16 pc_before = ln;
uint16 pc_line = ln;
basic_exec_stmt(g_prog[idx].text, &pc_line, &stop);
// pc_line may be changed by GOTO/IF
pc = pc_line;
// normal case: move to next after current
if (pc == pc_before) pc = ln;
}
}
// ---------- REPL line handler ----------
static void basic_repl_line(const char *input) {
const char *p = input;
skip_spaces(&p);
if (*p == 0) return;
// line starts with number? -> program line
if (is_digit(*p)) {
uint16 ln = parse_u16(&p);
basic_store_line(ln, p);
return;
}
// Immediate commands
if (starts_with_kw(p, "LIST")) { basic_list(); return; }
if (starts_with_kw(p, "RUN")) { basic_run(); return; }
if (starts_with_kw(p, "NEW")) { basic_reset_program(); basic_reset_vars(); print_new_line(); print_string("OK"); return; }
// keep your old shell commands too:
if (starts_with_kw(p, "HELP")) {
print_new_line();
print_string("Available commands:");
print_new_line();
print_string(" HELP - Prints this help");
print_new_line();
print_string(" REBOOT - Reboot the system");
print_new_line();
print_string(" NEW - Clear BASIC program + vars");
print_new_line();
print_string(" LIST - List BASIC program");
print_new_line();
print_string(" RUN - Run BASIC program");
print_new_line();
print_string("BASIC examples:");
print_new_line();
print_string(" 10 A=1+2*3");
print_new_line();
print_string(" 20 PRINT A");
print_new_line();
print_string(" 30 IF A=7 THEN 50");
print_new_line();
print_string(" 40 GOTO 20");
print_new_line();
print_string(" 50 END");
return;
}
if (starts_with_kw(p, "REBOOT")) { do_reboot(); return; }
// Otherwise: treat as immediate BASIC statement (PRINT/LET/A=.../IF/GOTO/END)
uint16 dummy = 0;
int stop = 0;
basic_exec_stmt(p, &dummy, &stop);
}
Hallo Besucher! Willkommen in diesem kleinen Wiki rund um IT. Vieles ist noch unvollständig, unstrukturiert oder vielleicht sogar falsch bzw. irreführend.
Du kannst Artikel gerne ergänzen oder verbessern. Gerne mit so vielen Links wie nötig. Bitte keine Werbelinks und nur selbst verfasste oder lizenzfreie Texte! Copyright beachten!
Eine Liste von Seiten die noch erstellt werden müssen.