This commit is contained in:
retoor 2025-11-22 23:15:15 +01:00
parent e6d75958c8
commit bd8d9d819e
13 changed files with 417 additions and 42 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -7,16 +7,25 @@
#include "parser.h" #include "parser.h"
void error(char *msg) { void error(char *msg) {
if (pc >= 0 && pc < MAX_TOK && pc < tk_idx) {
printf("Error at token %d ('%c'): %s\n", pc, tokens[pc].type, msg); printf("Error at token %d ('%c'): %s\n", pc, tokens[pc].type, msg);
} else {
printf("Error at token %d: %s\n", pc, msg);
}
exit(1); exit(1);
} }
void match(int type) { void match(int type) {
if (pc >= MAX_TOK || pc >= tk_idx) {
error("Token index out of bounds in match");
}
if (tokens[pc].type == type) pc++; if (tokens[pc].type == type) pc++;
else error("Unexpected token"); else error("Unexpected token");
} }
int find_local(char *name, int len) { int find_local(char *name, int len) {
if (!name || len < 0 || len >= 32) return -1;
if (loc_cnt > VAR_MAX) loc_cnt = VAR_MAX;
for (int i = loc_cnt - 1; i >= 0; i--) { for (int i = loc_cnt - 1; i >= 0; i--) {
if (!strncmp(locals[i].name, name, len) && locals[i].name[len] == 0) if (!strncmp(locals[i].name, name, len) && locals[i].name[len] == 0)
return i; return i;
@ -25,6 +34,8 @@ int find_local(char *name, int len) {
} }
int find_func(char *name, int len) { int find_func(char *name, int len) {
if (!name || len < 0 || len >= 32) return -1;
if (func_cnt > 100) func_cnt = 100;
for (int i = 0; i < func_cnt; i++) { for (int i = 0; i < func_cnt; i++) {
if (!strncmp(funcs[i].name, name, len) && funcs[i].name[len] == 0) if (!strncmp(funcs[i].name, name, len) && funcs[i].name[len] == 0)
return i; return i;
@ -33,6 +44,8 @@ int find_func(char *name, int len) {
} }
int find_native_func(char *name, int len) { int find_native_func(char *name, int len) {
if (!name || len < 0 || len >= 32) return -1;
if (native_func_cnt > 100) native_func_cnt = 100;
for (int i = 0; i < native_func_cnt; i++) { for (int i = 0; i < native_func_cnt; i++) {
if (!strncmp(native_funcs[i].name, name, len) && native_funcs[i].name[len] == 0) if (!strncmp(native_funcs[i].name, name, len) && native_funcs[i].name[len] == 0)
return i; return i;
@ -43,16 +56,22 @@ int find_native_func(char *name, int len) {
void skip_block() { void skip_block() {
int brace = 0; int brace = 0;
do { do {
if (pc >= MAX_TOK || pc >= tk_idx) {
error("Token index out of bounds in skip_block");
}
if (tokens[pc].type == '{') brace++; if (tokens[pc].type == '{') brace++;
if (tokens[pc].type == '}') brace--; if (tokens[pc].type == '}') brace--;
pc++; pc++;
} while (brace > 0 && tokens[pc].type != 0); } while (brace > 0 && pc < MAX_TOK && pc < tk_idx && tokens[pc].type != 0);
} }
void statement() { void statement() {
if (pc >= MAX_TOK || pc >= tk_idx) {
error("Token index out of bounds in statement");
}
if (tokens[pc].type == '{') { if (tokens[pc].type == '{') {
pc++; pc++;
while (tokens[pc].type != '}' && tokens[pc].type != 0) { while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != '}' && tokens[pc].type != 0) {
statement(); statement();
if (ax == -999) break; if (ax == -999) break;
} }
@ -60,32 +79,46 @@ void statement() {
} }
else if (tokens[pc].type == Int || tokens[pc].type == Char) { else if (tokens[pc].type == Int || tokens[pc].type == Char) {
pc++; pc++;
while (tokens[pc].type != ';') { while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') {
while (tokens[pc].type == '*') pc++; while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '*') pc++;
if (pc >= MAX_TOK || pc >= tk_idx) break;
Token *t = &tokens[pc]; Token *t = &tokens[pc];
match(Id); match(Id);
if (loc_cnt >= VAR_MAX) {
error("Too many local variables");
}
if (sp >= MEM_SIZE) {
error("Stack overflow");
}
int addr = sp; int addr = sp;
Symbol *s = &locals[loc_cnt++]; Symbol *s = &locals[loc_cnt++];
strncpy(s->name, t->text, t->val); s->name[t->val] = 0; strncpy(s->name, t->text, t->val); s->name[t->val] = 0;
s->addr = addr; s->addr = addr;
s->is_array = 0; s->is_array = 0;
if (tokens[pc].type == '[') { if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '[') {
pc++; pc++;
int size = (int)expression(); int size = (int)expression();
match(']'); match(']');
s->is_array = 1; s->is_array = 1;
if (sp + size >= MEM_SIZE) {
error("Stack overflow during array allocation");
}
sp += size; sp += size;
} else { } else {
sp++; sp++;
} }
if (tokens[pc].type == '=') { if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '=') {
pc++; pc++;
if (addr >= 0 && addr < MEM_SIZE) {
memory[addr] = expression(); memory[addr] = expression();
} else {
error("Memory access out of bounds");
} }
if (tokens[pc].type == ',') pc++; }
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == ',') pc++;
} }
match(';'); match(';');
} }
@ -97,10 +130,10 @@ void statement() {
if (cond) { if (cond) {
statement(); statement();
if (ax == -999) return; if (ax == -999) return;
if (tokens[pc].type == Else) { pc++; skip_block(); } if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) { pc++; skip_block(); }
} else { } else {
skip_block(); skip_block();
if (tokens[pc].type == Else) { if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) {
pc++; pc++;
statement(); statement();
if (ax == -999) return; if (ax == -999) return;
@ -116,10 +149,17 @@ void statement() {
if (!cond) { if (!cond) {
skip_block(); skip_block();
} else { } else {
int iteration_count = 0;
while (1) { while (1) {
if (++iteration_count > 1000000) {
error("Potential infinite loop detected");
}
statement(); statement();
if (ax == -999) return; if (ax == -999) return;
int save_pc = pc; int save_pc = pc;
if (loop_start >= MAX_TOK || loop_start >= tk_idx) {
error("Loop start out of bounds");
}
pc = loop_start; pc = loop_start;
match('('); match('(');
cond = expression(); cond = expression();
@ -130,7 +170,7 @@ void statement() {
} }
else if (tokens[pc].type == Return) { else if (tokens[pc].type == Return) {
pc++; pc++;
if (tokens[pc].type != ';') ax = expression(); if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') ax = expression();
else ax = 0; else ax = 0;
match(';'); match(';');
ax = -999; ax = -999;
@ -138,7 +178,11 @@ void statement() {
else if (tokens[pc].type == Printf) { else if (tokens[pc].type == Printf) {
pc++; pc++;
match('('); match('(');
if (pc >= MAX_TOK || pc >= tk_idx) {
error("Token index out of bounds in printf");
}
char *fmt = tokens[pc].text; char *fmt = tokens[pc].text;
if (!fmt) fmt = "";
match(Str); match(Str);
char *p = fmt; char *p = fmt;
@ -148,7 +192,10 @@ void statement() {
match(','); match(',');
long val = expression(); long val = expression();
if (*p == 'd') printf("%ld", val); if (*p == 'd') printf("%ld", val);
else if (*p == 's') printf("%s", (char*)val); else if (*p == 's') {
char *str = (char*)val;
if (str) printf("%s", str);
}
p++; p++;
} else { } else {
putchar(*p++); putchar(*p++);
@ -165,34 +212,41 @@ void statement() {
void scan_functions() { void scan_functions() {
int i = 0; int i = 0;
while (tokens[i].type != 0) { while (i < MAX_TOK && i < tk_idx && tokens[i].type != 0) {
if ((tokens[i].type == Int || tokens[i].type == Char) && if (i + 2 < MAX_TOK && i + 2 < tk_idx &&
(tokens[i].type == Int || tokens[i].type == Char) &&
tokens[i+1].type == Id && tokens[i+2].type == '(') { tokens[i+1].type == Id && tokens[i+2].type == '(') {
if (func_cnt >= 100) {
error("Too many functions defined");
}
Func *f = &funcs[func_cnt++]; Func *f = &funcs[func_cnt++];
Token *name = &tokens[i+1]; Token *name = &tokens[i+1];
strncpy(f->name, name->text, name->val); f->name[name->val] = 0; strncpy(f->name, name->text, name->val); f->name[name->val] = 0;
i += 3; i += 3;
int params = 0; int params = 0;
while(tokens[i].type != ')') { while(i < MAX_TOK && i < tk_idx && tokens[i].type != ')') {
if (tokens[i].type == Int || tokens[i].type == Char) { if (tokens[i].type == Int || tokens[i].type == Char) {
params++; params++;
i++; i++;
while (tokens[i].type == '*') i++; while (i < MAX_TOK && i < tk_idx && tokens[i].type == '*') i++;
if (tokens[i].type == Id) i++; if (i < MAX_TOK && i < tk_idx && tokens[i].type == Id) i++;
} else i++; } else i++;
} }
f->param_count = params; f->param_count = params;
i++; if (i < MAX_TOK && i < tk_idx) i++;
f->entry_point = i; f->entry_point = i;
int brace = 0; int brace = 0;
do { do {
if (i >= MAX_TOK || i >= tk_idx) {
error("Token index out of bounds in scan_functions");
}
if (tokens[i].type == '{') brace++; if (tokens[i].type == '{') brace++;
if (tokens[i].type == '}') brace--; if (tokens[i].type == '}') brace--;
i++; i++;
} while (brace > 0 && tokens[i].type != 0); } while (brace > 0 && i < MAX_TOK && i < tk_idx && tokens[i].type != 0);
} else { } else {
i++; i++;
} }

View File

@ -17,8 +17,15 @@ int main(int argc, char **argv) {
return 1; return 1;
} }
src_code = malloc(MAX_SRC); src_code = malloc(MAX_SRC + 1);
if (!src_code) {
printf("Memory allocation failed.\n");
fclose(f);
return 1;
}
size_t n = fread(src_code, 1, MAX_SRC, f); size_t n = fread(src_code, 1, MAX_SRC, f);
if (n >= MAX_SRC) n = MAX_SRC - 1;
src_code[n] = 0; src_code[n] = 0;
fclose(f); fclose(f);
@ -28,17 +35,23 @@ int main(int argc, char **argv) {
scan_functions(); scan_functions();
int main_idx = find_func("main", 4); int main_idx = find_func("main", 4);
if (main_idx == -1) { if (main_idx == -1 || main_idx >= func_cnt) {
printf("No main function found.\n"); printf("No main function found.\n");
return 1; return 1;
} }
pc = funcs[main_idx].entry_point; pc = funcs[main_idx].entry_point;
if (sp + 2 >= MEM_SIZE) {
printf("Stack overflow during initialization.\n");
return 1;
}
memory[sp++] = 0; memory[sp++] = 0;
memory[sp++] = 0; memory[sp++] = 0;
ax = 0; ax = 0;
statement(); statement();
free(src_code);
return 0; return 0;
} }

View File

@ -12,6 +12,9 @@
#include "interpreter.h" #include "interpreter.h"
void register_native_func(char *name, NativeFunc func) { void register_native_func(char *name, NativeFunc func) {
if (!name || !func || native_func_cnt >= 100) {
return;
}
NativeFuncDef *nf = &native_funcs[native_func_cnt++]; NativeFuncDef *nf = &native_funcs[native_func_cnt++];
strncpy(nf->name, name, 31); strncpy(nf->name, name, 31);
nf->name[31] = 0; nf->name[31] = 0;
@ -19,6 +22,9 @@ void register_native_func(char *name, NativeFunc func) {
} }
long native_socket(long *args, int argc) { long native_socket(long *args, int argc) {
if (!args || argc < 3) {
return -1;
}
int domain = (int)args[0]; int domain = (int)args[0];
int type = (int)args[1]; int type = (int)args[1];
int protocol = (int)args[2]; int protocol = (int)args[2];
@ -26,6 +32,9 @@ long native_socket(long *args, int argc) {
} }
long native_bind(long *args, int argc) { long native_bind(long *args, int argc) {
if (!args || argc < 2) {
return -1;
}
int sockfd = (int)args[0]; int sockfd = (int)args[0];
int port = (int)args[1]; int port = (int)args[1];
@ -39,28 +48,46 @@ long native_bind(long *args, int argc) {
} }
long native_listen(long *args, int argc) { long native_listen(long *args, int argc) {
if (!args || argc < 2) {
return -1;
}
int sockfd = (int)args[0]; int sockfd = (int)args[0];
int backlog = (int)args[1]; int backlog = (int)args[1];
return listen(sockfd, backlog); return listen(sockfd, backlog);
} }
long native_accept(long *args, int argc) { long native_accept(long *args, int argc) {
if (!args || argc < 1) {
return -1;
}
int sockfd = (int)args[0]; int sockfd = (int)args[0];
return accept(sockfd, NULL, NULL); return accept(sockfd, NULL, NULL);
} }
long native_recv(long *args, int argc) { long native_recv(long *args, int argc) {
if (!args || argc < 4) {
return -1;
}
int sockfd = (int)args[0]; int sockfd = (int)args[0];
int addr = (int)args[1]; int addr = (int)args[1];
int len = (int)args[2]; int len = (int)args[2];
int flags = (int)args[3]; int flags = (int)args[3];
if (addr < 0 || addr >= MEM_SIZE) {
return -1;
}
char temp_buf[8192]; char temp_buf[8192];
if (len > 8192) len = 8192; if (len > 8192) len = 8192;
if (len < 0) len = 0;
if (addr + len > MEM_SIZE) {
len = MEM_SIZE - addr;
}
int result = recv(sockfd, temp_buf, len, flags); int result = recv(sockfd, temp_buf, len, flags);
if (result > 0) { if (result > 0) {
for (int i = 0; i < result; i++) { for (int i = 0; i < result && addr + i < MEM_SIZE; i++) {
memory[addr + i] = temp_buf[i]; memory[addr + i] = temp_buf[i];
} }
} }
@ -68,19 +95,34 @@ long native_recv(long *args, int argc) {
} }
long native_send(long *args, int argc) { long native_send(long *args, int argc) {
if (!args || argc < 4) {
return -1;
}
int sockfd = (int)args[0]; int sockfd = (int)args[0];
long buf_arg = args[1]; long buf_arg = args[1];
int len = (int)args[2]; int len = (int)args[2];
int flags = (int)args[3]; int flags = (int)args[3];
if (len < 0) {
return -1;
}
if (buf_arg > MEM_SIZE * 8 || buf_arg < 0) { if (buf_arg > MEM_SIZE * 8 || buf_arg < 0) {
return send(sockfd, (char*)buf_arg, len, flags); return send(sockfd, (char*)buf_arg, len, flags);
} }
if (buf_arg >= MEM_SIZE) {
return -1;
}
char temp_buf[8192]; char temp_buf[8192];
if (len > 8192) len = 8192; if (len > 8192) len = 8192;
for (int i = 0; i < len; i++) { if (buf_arg + len > MEM_SIZE) {
len = MEM_SIZE - buf_arg;
}
for (int i = 0; i < len && buf_arg + i < MEM_SIZE; i++) {
temp_buf[i] = (char)memory[buf_arg + i]; temp_buf[i] = (char)memory[buf_arg + i];
} }
@ -88,12 +130,21 @@ long native_send(long *args, int argc) {
} }
long native_close(long *args, int argc) { long native_close(long *args, int argc) {
if (!args || argc < 1) {
return -1;
}
int fd = (int)args[0]; int fd = (int)args[0];
return close(fd); return close(fd);
} }
long native_strlen(long *args, int argc) { long native_strlen(long *args, int argc) {
if (!args || argc < 1) {
return 0;
}
char *str = (char*)args[0]; char *str = (char*)args[0];
if (!str) {
return 0;
}
return strlen(str); return strlen(str);
} }
@ -106,40 +157,70 @@ long native_SOCK_STREAM(long *args, int argc) {
} }
long native_sqrt(long *args, int argc) { long native_sqrt(long *args, int argc) {
if (!args || argc < 1) {
return 0;
}
return (long)sqrt((double)args[0]); return (long)sqrt((double)args[0]);
} }
long native_pow(long *args, int argc) { long native_pow(long *args, int argc) {
if (!args || argc < 2) {
return 0;
}
return (long)pow((double)args[0], (double)args[1]); return (long)pow((double)args[0], (double)args[1]);
} }
long native_sin(long *args, int argc) { long native_sin(long *args, int argc) {
if (!args || argc < 1) {
return 0;
}
return (long)(sin((double)args[0]) * 1000000); return (long)(sin((double)args[0]) * 1000000);
} }
long native_cos(long *args, int argc) { long native_cos(long *args, int argc) {
if (!args || argc < 1) {
return 0;
}
return (long)(cos((double)args[0]) * 1000000); return (long)(cos((double)args[0]) * 1000000);
} }
long native_tan(long *args, int argc) { long native_tan(long *args, int argc) {
if (!args || argc < 1) {
return 0;
}
return (long)(tan((double)args[0]) * 1000000); return (long)(tan((double)args[0]) * 1000000);
} }
long native_abs(long *args, int argc) { long native_abs(long *args, int argc) {
if (!args || argc < 1) {
return 0;
}
return (long)abs((int)args[0]); return (long)abs((int)args[0]);
} }
long native_floor(long *args, int argc) { long native_floor(long *args, int argc) {
if (!args || argc < 1) {
return 0;
}
return (long)floor((double)args[0]); return (long)floor((double)args[0]);
} }
long native_ceil(long *args, int argc) { long native_ceil(long *args, int argc) {
if (!args || argc < 1) {
return 0;
}
return (long)ceil((double)args[0]); return (long)ceil((double)args[0]);
} }
long native_strpos(long *args, int argc) { long native_strpos(long *args, int argc) {
if (!args || argc < 2) {
return -1;
}
char *haystack = (char*)args[0]; char *haystack = (char*)args[0];
char *needle = (char*)args[1]; char *needle = (char*)args[1];
if (!haystack || !needle) {
return -1;
}
char *pos = strstr(haystack, needle); char *pos = strstr(haystack, needle);
if (pos) { if (pos) {
return pos - haystack; return pos - haystack;
@ -148,20 +229,33 @@ long native_strpos(long *args, int argc) {
} }
long native_substr(long *args, int argc) { long native_substr(long *args, int argc) {
static char empty_str[] = "";
if (!args || argc < 3) {
return (long)empty_str;
}
char *str = (char*)args[0]; char *str = (char*)args[0];
if (!str) {
return (long)empty_str;
}
int start = (int)args[1]; int start = (int)args[1];
int length = (int)args[2]; int length = (int)args[2];
if (str_pool_idx >= STR_POOL_SIZE) {
error("String pool overflow");
return (long)empty_str;
}
char *result = &str_pool[str_pool_idx]; char *result = &str_pool[str_pool_idx];
int str_len = strlen(str); int str_len = strlen(str);
if (start < 0) start = 0; if (start < 0) start = 0;
if (start >= str_len) return (long)""; if (start >= str_len) return (long)empty_str;
if (start + length > str_len) length = str_len - start; if (start + length > str_len) length = str_len - start;
if (length < 0) return (long)""; if (length < 0) return (long)empty_str;
if (str_pool_idx + length + 1 >= STR_POOL_SIZE) { if (str_pool_idx + length + 1 >= STR_POOL_SIZE) {
error("String pool overflow"); error("String pool overflow");
return (long)empty_str;
} }
strncpy(result, str + start, length); strncpy(result, str + start, length);
@ -172,12 +266,26 @@ long native_substr(long *args, int argc) {
} }
long native_upper(long *args, int argc) { long native_upper(long *args, int argc) {
static char empty_str[] = "";
if (!args || argc < 1) {
return (long)empty_str;
}
char *str = (char*)args[0]; char *str = (char*)args[0];
if (!str) {
return (long)empty_str;
}
if (str_pool_idx >= STR_POOL_SIZE) {
error("String pool overflow");
return (long)empty_str;
}
char *result = &str_pool[str_pool_idx]; char *result = &str_pool[str_pool_idx];
int len = strlen(str); int len = strlen(str);
if (str_pool_idx + len + 1 >= STR_POOL_SIZE) { if (str_pool_idx + len + 1 >= STR_POOL_SIZE) {
error("String pool overflow"); error("String pool overflow");
return (long)empty_str;
} }
for (int i = 0; i <= len; i++) { for (int i = 0; i <= len; i++) {
@ -189,12 +297,26 @@ long native_upper(long *args, int argc) {
} }
long native_lower(long *args, int argc) { long native_lower(long *args, int argc) {
static char empty_str[] = "";
if (!args || argc < 1) {
return (long)empty_str;
}
char *str = (char*)args[0]; char *str = (char*)args[0];
if (!str) {
return (long)empty_str;
}
if (str_pool_idx >= STR_POOL_SIZE) {
error("String pool overflow");
return (long)empty_str;
}
char *result = &str_pool[str_pool_idx]; char *result = &str_pool[str_pool_idx];
int len = strlen(str); int len = strlen(str);
if (str_pool_idx + len + 1 >= STR_POOL_SIZE) { if (str_pool_idx + len + 1 >= STR_POOL_SIZE) {
error("String pool overflow"); error("String pool overflow");
return (long)empty_str;
} }
for (int i = 0; i <= len; i++) { for (int i = 0; i <= len; i++) {
@ -206,7 +328,20 @@ long native_lower(long *args, int argc) {
} }
long native_strip(long *args, int argc) { long native_strip(long *args, int argc) {
static char empty_str[] = "";
if (!args || argc < 1) {
return (long)empty_str;
}
char *str = (char*)args[0]; char *str = (char*)args[0];
if (!str) {
return (long)empty_str;
}
if (str_pool_idx >= STR_POOL_SIZE) {
error("String pool overflow");
return (long)empty_str;
}
char *result = &str_pool[str_pool_idx]; char *result = &str_pool[str_pool_idx];
while (*str && isspace(*str)) str++; while (*str && isspace(*str)) str++;
@ -216,6 +351,7 @@ long native_strip(long *args, int argc) {
if (str_pool_idx + len + 1 >= STR_POOL_SIZE) { if (str_pool_idx + len + 1 >= STR_POOL_SIZE) {
error("String pool overflow"); error("String pool overflow");
return (long)empty_str;
} }
strncpy(result, str, len); strncpy(result, str, len);
@ -226,9 +362,21 @@ long native_strip(long *args, int argc) {
} }
long native_replace(long *args, int argc) { long native_replace(long *args, int argc) {
static char empty_str[] = "";
if (!args || argc < 3) {
return (long)empty_str;
}
char *str = (char*)args[0]; char *str = (char*)args[0];
char *old_str = (char*)args[1]; char *old_str = (char*)args[1];
char *new_str = (char*)args[2]; char *new_str = (char*)args[2];
if (!str || !old_str || !new_str) {
return (long)empty_str;
}
if (str_pool_idx >= STR_POOL_SIZE) {
error("String pool overflow");
return (long)empty_str;
}
char *result = &str_pool[str_pool_idx]; char *result = &str_pool[str_pool_idx];
char *src = str; char *src = str;
@ -236,10 +384,26 @@ long native_replace(long *args, int argc) {
int old_len = strlen(old_str); int old_len = strlen(old_str);
int new_len = strlen(new_str); int new_len = strlen(new_str);
if (old_len == 0) {
int str_len = strlen(str);
if (str_pool_idx + str_len + 1 >= STR_POOL_SIZE) {
error("String pool overflow");
return (long)empty_str;
}
strcpy(result, str);
str_pool_idx += str_len + 1;
return (long)result;
}
while (*src) { while (*src) {
if (strncmp(src, old_str, old_len) == 0) { if (strncmp(src, old_str, old_len) == 0) {
if (str_pool_idx + (dst - result) + new_len + strlen(src + old_len) + 1 >= STR_POOL_SIZE) { int remaining = strlen(src + old_len);
int current_pos = dst - result;
if (str_pool_idx + current_pos + new_len + remaining + 1 >= STR_POOL_SIZE) {
error("String pool overflow"); error("String pool overflow");
*dst = 0;
str_pool_idx += current_pos + 1;
return (long)result;
} }
strcpy(dst, new_str); strcpy(dst, new_str);
dst += new_len; dst += new_len;
@ -256,15 +420,27 @@ long native_replace(long *args, int argc) {
} }
long native_startswith(long *args, int argc) { long native_startswith(long *args, int argc) {
if (!args || argc < 2) {
return 0;
}
char *str = (char*)args[0]; char *str = (char*)args[0];
char *prefix = (char*)args[1]; char *prefix = (char*)args[1];
if (!str || !prefix) {
return 0;
}
int prefix_len = strlen(prefix); int prefix_len = strlen(prefix);
return strncmp(str, prefix, prefix_len) == 0; return strncmp(str, prefix, prefix_len) == 0;
} }
long native_endswith(long *args, int argc) { long native_endswith(long *args, int argc) {
if (!args || argc < 2) {
return 0;
}
char *str = (char*)args[0]; char *str = (char*)args[0];
char *suffix = (char*)args[1]; char *suffix = (char*)args[1];
if (!str || !suffix) {
return 0;
}
int str_len = strlen(str); int str_len = strlen(str);
int suffix_len = strlen(suffix); int suffix_len = strlen(suffix);

View File

@ -27,6 +27,7 @@ extern int find_native_func(char *name, int len);
extern void statement(); extern void statement();
long factor() { long factor() {
if (pc >= MAX_TOK) return 0;
Token *t = &tokens[pc]; Token *t = &tokens[pc];
long val = 0; long val = 0;
@ -45,17 +46,22 @@ long factor() {
return val; return val;
} }
else if (t->type == Id) { else if (t->type == Id) {
if (pc + 1 >= MAX_TOK) return 0;
if (tokens[pc + 1].type == '(') { if (tokens[pc + 1].type == '(') {
int nf_idx = find_native_func(t->text, t->val); int nf_idx = find_native_func(t->text, t->val);
if (nf_idx != -1) { if (nf_idx != -1) {
if (nf_idx < 0 || nf_idx >= native_func_cnt) return 0;
pc += 2; pc += 2;
long args[10]; long args[10];
int argc = 0; int argc = 0;
if (pc >= MAX_TOK) return 0;
if (tokens[pc].type != ')') { if (tokens[pc].type != ')') {
do { do {
if (argc >= 10) break;
args[argc++] = expression(); args[argc++] = expression();
if (pc >= MAX_TOK) return 0;
} while (tokens[pc].type == ',' && pc++); } while (tokens[pc].type == ',' && pc++);
} }
match(')'); match(')');
@ -65,30 +71,42 @@ long factor() {
int f_idx = find_func(t->text, t->val); int f_idx = find_func(t->text, t->val);
if (f_idx == -1) error("Unknown function"); if (f_idx == -1) error("Unknown function");
if (f_idx < 0 || f_idx >= func_cnt) return 0;
pc += 2; pc += 2;
int old_bp = bp; int old_bp = bp;
long args[10]; long args[10];
int argc = 0; int argc = 0;
if (pc >= MAX_TOK) return 0;
if (tokens[pc].type != ')') { if (tokens[pc].type != ')') {
do { do {
if (argc >= 10) break;
args[argc++] = expression(); args[argc++] = expression();
if (pc >= MAX_TOK) return 0;
} while (tokens[pc].type == ',' && pc++); } while (tokens[pc].type == ',' && pc++);
} }
match(')'); match(')');
int ret_pc = pc; int ret_pc = pc;
if (sp >= MEM_SIZE) return 0;
if (bp < 0 || bp >= MEM_SIZE) return 0;
memory[sp] = bp; bp = sp++; memory[sp] = bp; bp = sp++;
if (sp >= MEM_SIZE) return 0;
memory[sp++] = ret_pc; memory[sp++] = ret_pc;
for(int i=0; i<argc; i++) memory[sp++] = args[i]; for(int i=0; i<argc; i++) {
if (sp >= MEM_SIZE) break;
memory[sp++] = args[i];
}
pc = funcs[f_idx].entry_point; pc = funcs[f_idx].entry_point;
statement(); statement();
val = ax; val = ax;
if (bp < 0 || bp >= MEM_SIZE) return 0;
sp = bp; sp = bp;
if (sp < 0 || sp >= MEM_SIZE) return 0;
bp = memory[sp]; bp = memory[sp];
pc = ret_pc; pc = ret_pc;
return val; return val;
@ -96,19 +114,23 @@ long factor() {
else { else {
int idx = find_local(t->text, t->val); int idx = find_local(t->text, t->val);
if (idx == -1) error("Undefined variable"); if (idx == -1) error("Undefined variable");
if (idx < 0 || idx >= loc_cnt) return 0;
pc++; pc++;
Symbol *sym = &locals[idx]; Symbol *sym = &locals[idx];
if (pc >= MAX_TOK) return 0;
if (tokens[pc].type == '[') { if (tokens[pc].type == '[') {
pc++; pc++;
long start_or_index = expression(); long start_or_index = expression();
if (pc >= MAX_TOK) return 0;
if (tokens[pc].type == ':') { if (tokens[pc].type == ':') {
pc++; pc++;
long end = expression(); long end = expression();
match(']'); match(']');
if (sym->addr < 0 || sym->addr >= MEM_SIZE) return 0;
long val = memory[sym->addr]; long val = memory[sym->addr];
if (is_string_ptr(val)) { if (is_string_ptr(val)) {
return slice_string(val, start_or_index, end); return slice_string(val, start_or_index, end);
@ -117,7 +139,9 @@ long factor() {
} }
} else { } else {
match(']'); match(']');
return memory[sym->addr + start_or_index]; long addr = sym->addr + start_or_index;
if (addr < 0 || addr >= MEM_SIZE) return 0;
return memory[addr];
} }
} }
@ -125,6 +149,7 @@ long factor() {
return sym->addr; return sym->addr;
} }
if (sym->addr < 0 || sym->addr >= MEM_SIZE) return 0;
return memory[sym->addr]; return memory[sym->addr];
} }
} }
@ -132,20 +157,24 @@ long factor() {
} }
long unary() { long unary() {
if (pc >= MAX_TOK) return 0;
if (tokens[pc].type == '*') { if (tokens[pc].type == '*') {
pc++; pc++;
int addr = unary(); int addr = unary();
if (addr > MEM_SIZE * 8 || addr < 0) { if (addr > MEM_SIZE * 8 || addr < 0) {
return *(char*)addr; return *(char*)addr;
} }
if (addr < 0 || addr >= MEM_SIZE) return 0;
return memory[addr]; return memory[addr];
} }
else if (tokens[pc].type == '&') { else if (tokens[pc].type == '&') {
pc++; pc++;
if (pc >= MAX_TOK) return 0;
Token *t = &tokens[pc]; Token *t = &tokens[pc];
if (t->type != Id) error("Expected identifier after &"); if (t->type != Id) error("Expected identifier after &");
int idx = find_local(t->text, t->val); int idx = find_local(t->text, t->val);
if (idx == -1) error("Undefined variable"); if (idx == -1) error("Undefined variable");
if (idx < 0 || idx >= loc_cnt) return 0;
pc++; pc++;
return locals[idx].addr; return locals[idx].addr;
} }
@ -158,18 +187,21 @@ long unary() {
long term() { long term() {
long val = unary(); long val = unary();
while (tokens[pc].type == '*' || tokens[pc].type == '/') { while (pc < MAX_TOK && (tokens[pc].type == '*' || tokens[pc].type == '/')) {
int op = tokens[pc++].type; int op = tokens[pc++].type;
long val2 = unary(); long val2 = unary();
if (op == '*') val = val * val2; if (op == '*') val = val * val2;
else val = val / val2; else {
if (val2 != 0) val = val / val2;
else val = 0;
}
} }
return val; return val;
} }
long add() { long add() {
long val = term(); long val = term();
while (tokens[pc].type == '+' || tokens[pc].type == '-') { while (pc < MAX_TOK && (tokens[pc].type == '+' || tokens[pc].type == '-')) {
int op = tokens[pc++].type; int op = tokens[pc++].type;
long val2 = term(); long val2 = term();
if (op == '+') { if (op == '+') {
@ -187,7 +219,7 @@ long add() {
long relational() { long relational() {
long val = add(); long val = add();
while (tokens[pc].type >= Eq && tokens[pc].type <= Ge) { while (pc < MAX_TOK && tokens[pc].type >= Eq && tokens[pc].type <= Ge) {
int op = tokens[pc++].type; int op = tokens[pc++].type;
long val2 = add(); long val2 = add();
if (op == Eq) val = val == val2; if (op == Eq) val = val == val2;
@ -199,9 +231,11 @@ long relational() {
} }
long expression() { long expression() {
if (pc >= MAX_TOK) return 0;
if (tokens[pc].type == '*') { if (tokens[pc].type == '*') {
int save_pc = pc; int save_pc = pc;
unary(); unary();
if (pc >= MAX_TOK) return 0;
if (tokens[pc].type == '=') { if (tokens[pc].type == '=') {
pc = save_pc; pc = save_pc;
pc++; pc++;
@ -214,18 +248,23 @@ long expression() {
pc = save_pc; pc = save_pc;
} }
if (pc >= MAX_TOK) return 0;
if (tokens[pc].type == Id) { if (tokens[pc].type == Id) {
if (pc + 1 >= MAX_TOK) return 0;
if (tokens[pc+1].type == '[') { if (tokens[pc+1].type == '[') {
int idx = find_local(tokens[pc].text, tokens[pc].val); int idx = find_local(tokens[pc].text, tokens[pc].val);
if (idx == -1) error("Assign to unknown var"); if (idx == -1) error("Assign to unknown var");
if (idx < 0 || idx >= loc_cnt) return 0;
pc += 2; pc += 2;
long start_or_index = expression(); long start_or_index = expression();
if (pc >= MAX_TOK) return 0;
if (tokens[pc].type == ':') { if (tokens[pc].type == ':') {
pc++; pc++;
long end = expression(); long end = expression();
match(']'); match(']');
if (locals[idx].addr < 0 || locals[idx].addr >= MEM_SIZE) return 0;
long val = memory[locals[idx].addr]; long val = memory[locals[idx].addr];
if (is_string_ptr(val)) { if (is_string_ptr(val)) {
return slice_string(val, start_or_index, end); return slice_string(val, start_or_index, end);
@ -236,19 +275,28 @@ long expression() {
match(']'); match(']');
int addr = locals[idx].addr; int addr = locals[idx].addr;
if (pc >= MAX_TOK) return 0;
if (tokens[pc].type == '=') { if (tokens[pc].type == '=') {
pc++; pc++;
long val = expression(); long val = expression();
memory[addr + start_or_index] = val; long target_addr = addr + start_or_index;
if (target_addr >= 0 && target_addr < MEM_SIZE) {
memory[target_addr] = val;
}
return val; return val;
} }
return memory[addr + start_or_index]; long read_addr = addr + start_or_index;
if (read_addr < 0 || read_addr >= MEM_SIZE) return 0;
return memory[read_addr];
} else if (tokens[pc+1].type == '=') { } else if (tokens[pc+1].type == '=') {
int idx = find_local(tokens[pc].text, tokens[pc].val); int idx = find_local(tokens[pc].text, tokens[pc].val);
if (idx == -1) error("Assign to unknown var"); if (idx == -1) error("Assign to unknown var");
if (idx < 0 || idx >= loc_cnt) return 0;
pc += 2; pc += 2;
long val = expression(); long val = expression();
if (locals[idx].addr >= 0 && locals[idx].addr < MEM_SIZE) {
memory[locals[idx].addr] = val; memory[locals[idx].addr] = val;
}
return val; return val;
} }
} }

View File

@ -4,12 +4,29 @@
#include "interpreter.h" #include "interpreter.h"
int is_string_ptr(long val) { int is_string_ptr(long val) {
return val > MEM_SIZE * 8; if (val < 0) {
return 0;
}
if (val > MEM_SIZE * 8) {
return 1;
}
return 0;
} }
long concat_strings(long ptr1, long ptr2) { long concat_strings(long ptr1, long ptr2) {
static char empty_str[] = "";
char *s1 = (char*)ptr1; char *s1 = (char*)ptr1;
char *s2 = (char*)ptr2; char *s2 = (char*)ptr2;
if (!s1 || !s2) {
return (long)empty_str;
}
if (str_pool_idx >= STR_POOL_SIZE) {
error("String pool overflow");
return (long)empty_str;
}
char *result = &str_pool[str_pool_idx]; char *result = &str_pool[str_pool_idx];
int len1 = strlen(s1); int len1 = strlen(s1);
@ -17,6 +34,7 @@ long concat_strings(long ptr1, long ptr2) {
if (str_pool_idx + len1 + len2 + 1 >= STR_POOL_SIZE) { if (str_pool_idx + len1 + len2 + 1 >= STR_POOL_SIZE) {
error("String pool overflow"); error("String pool overflow");
return (long)empty_str;
} }
strcpy(result, s1); strcpy(result, s1);
@ -28,7 +46,18 @@ long concat_strings(long ptr1, long ptr2) {
} }
long slice_string(long str_ptr, int start, int end) { long slice_string(long str_ptr, int start, int end) {
static char empty_str[] = "";
char *str = (char*)str_ptr; char *str = (char*)str_ptr;
if (!str) {
return (long)empty_str;
}
if (str_pool_idx >= STR_POOL_SIZE) {
error("String pool overflow");
return (long)empty_str;
}
char *result = &str_pool[str_pool_idx]; char *result = &str_pool[str_pool_idx];
int str_len = strlen(str); int str_len = strlen(str);
@ -36,14 +65,19 @@ long slice_string(long str_ptr, int start, int end) {
if (end < 0) end = str_len; if (end < 0) end = str_len;
if (end > str_len) end = str_len; if (end > str_len) end = str_len;
if (start > end) start = end; if (start > end) start = end;
if (start > str_len) start = str_len;
int length = end - start; int length = end - start;
if (length < 0) length = 0;
if (str_pool_idx + length + 1 >= STR_POOL_SIZE) { if (str_pool_idx + length + 1 >= STR_POOL_SIZE) {
error("String pool overflow"); error("String pool overflow");
return (long)empty_str;
} }
if (length > 0 && start < str_len) {
strncpy(result, str + start, length); strncpy(result, str + start, length);
}
result[length] = 0; result[length] = 0;
str_pool_idx += length + 1; str_pool_idx += length + 1;

View File

@ -6,13 +6,19 @@
void tokenize(char *src) { void tokenize(char *src) {
char *s = src; char *s = src;
if (!src) return;
while (*s) { while (*s) {
if (isspace(*s)) { s++; continue; } if (isspace(*s)) { s++; continue; }
if (tk_idx >= MAX_TOK - 1) {
return;
}
Token *t = &tokens[tk_idx++]; Token *t = &tokens[tk_idx++];
t->text = s; t->text = s;
if (*s == '/' && *(s+1) == '/') { if (*s == '/' && s[1] && s[1] == '/') {
while (*s && *s != '\n') s++; while (*s && *s != '\n') s++;
tk_idx--; tk_idx--;
continue; continue;
@ -20,9 +26,10 @@ void tokenize(char *src) {
if (isalpha(*s)) { if (isalpha(*s)) {
int len = 0; int len = 0;
while (isalnum(s[len]) || s[len] == '_') len++; while (s[len] && (isalnum(s[len]) || s[len] == '_') && len < 31) len++;
char buf[32]; char buf[32];
if (len > 31) len = 31;
strncpy(buf, s, len); buf[len] = 0; strncpy(buf, s, len); buf[len] = 0;
if (!strcmp(buf, "int")) t->type = Int; if (!strcmp(buf, "int")) t->type = Int;
@ -52,7 +59,7 @@ void tokenize(char *src) {
char *d = s; char *d = s;
while (*s && *s != '"') { while (*s && *s != '"') {
if (*s == '\\' && *(s+1) == 'n') { if (*s == '\\' && s[1] && s[1] == 'n') {
*d++ = '\n'; s+=2; *d++ = '\n'; s+=2;
} else { } else {
*d++ = *s++; *d++ = *s++;
@ -76,5 +83,7 @@ void tokenize(char *src) {
t->type = *s++; t->type = *s++;
} }
if (tk_idx < MAX_TOK) {
tokens[tk_idx].type = 0; tokens[tk_idx].type = 0;
} }
}

41
tests/edge_cases.rc Normal file
View File

@ -0,0 +1,41 @@
int main() {
printf("Testing Edge Cases:\n\n");
printf("1. Empty string operations:\n");
char *empty = "";
char *result1 = upper(empty);
printf("upper('') = '%s'\n", result1);
printf("\n2. String slicing edge cases:\n");
char *text = "Hello";
char *slice1 = text[0:0];
printf("'Hello'[0:0] = '%s'\n", slice1);
char *slice2 = text[10:20];
printf("'Hello'[10:20] = '%s'\n", slice2);
char *slice3 = text[3:3];
printf("'Hello'[3:3] = '%s'\n", slice3);
printf("\n3. Math with edge cases:\n");
int zero = 0;
printf("abs(0) = %d\n", abs(zero));
printf("sqrt(0) = %d\n", sqrt(zero));
printf("\n4. String concatenation:\n");
char *str1 = "A";
char *str2 = "B";
char *concat = str1 + str2;
printf("'A' + 'B' = '%s'\n", concat);
printf("\n5. String search edge cases:\n");
int pos1 = strpos("test", "xyz");
printf("strpos('test', 'xyz') = %d\n", pos1);
int pos2 = strpos("test", "test");
printf("strpos('test', 'test') = %d\n", pos2);
printf("\n6. Nested operations:\n");
char *nested = upper(lower(upper("TeSt")));
printf("upper(lower(upper('TeSt'))) = '%s'\n", nested);
printf("\nAll edge cases handled safely!\n");
return 0;
}