You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1047 lines
24 KiB
1047 lines
24 KiB
void **variables;
|
|
void *statement_list;
|
|
|
|
int ERR_VAL;
|
|
int INT_VAL;
|
|
int STR_VAL;
|
|
int do_end;
|
|
int do_if;
|
|
int do_while;
|
|
int do_skip_if;
|
|
int do_skip_while;
|
|
int do_gosub;
|
|
int do_goto;
|
|
int do_return;
|
|
|
|
int goto_label;
|
|
|
|
int gosubs[32];
|
|
int current_gosub;
|
|
|
|
void *create_value(int type, void *value){
|
|
void **output;
|
|
|
|
output = kmalloc(POINTER_SIZE*2);
|
|
output[0] = (void *) type;
|
|
output[1] = value;
|
|
|
|
return output;
|
|
}
|
|
|
|
void *create_statement_entry(void *statement, int line_number){
|
|
void **output;
|
|
|
|
output = kmalloc(POINTER_SIZE*2);
|
|
output[0] = statement;
|
|
output[1] = (void *) line_number;
|
|
|
|
return output;
|
|
}
|
|
|
|
void free_statement_entry(void *statement_entry){
|
|
free_statement(((void **) statement_entry)[0]);
|
|
kfree(statement_entry);
|
|
}
|
|
|
|
void free_value(void **value){
|
|
if((int) value[0] == STR_VAL)
|
|
kfree(value[1]);
|
|
kfree(value);
|
|
}
|
|
|
|
int strlen(char *str){
|
|
int output;
|
|
|
|
output = 0;
|
|
while(*str){
|
|
output = output + 1;
|
|
str = str + 1;
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
void strcpy(char *a, char *b){
|
|
while(*b){
|
|
*a = *b;
|
|
a = a + 1;
|
|
b = b + 1;
|
|
}
|
|
*a = 0;
|
|
}
|
|
|
|
void strncpy(char *str1, char *str2, int max){
|
|
while(max && *str2){
|
|
*str1 = *str2;
|
|
str1 = str1 + 1;
|
|
str2 = str2 + 1;
|
|
max = max - 1;
|
|
}
|
|
|
|
*str1 = 0;
|
|
}
|
|
|
|
char *duplicate_str(char *str){
|
|
int str_len;
|
|
int i;
|
|
char *output;
|
|
|
|
str_len = strlen(str);
|
|
output = kmalloc(CHAR_SIZE*(str_len + 1));
|
|
for(i = 0; i < str_len; i = i + 1)
|
|
output[i] = str[i];
|
|
|
|
output[str_len] = 0;
|
|
|
|
return output;
|
|
}
|
|
|
|
char *concat(char *str_a, char *str_b){
|
|
int i;
|
|
int len_a;
|
|
int len_b;
|
|
char *output;
|
|
|
|
len_a = strlen(str_a);
|
|
len_b = strlen(str_b);
|
|
output = kmalloc(CHAR_SIZE*(len_a + len_b + 1));
|
|
|
|
for(i = 0; i < len_a; i = i + 1){
|
|
output[i] = str_a[i];
|
|
}
|
|
|
|
for(i = len_a; i < len_a + len_b; i = i + 1){
|
|
output[i] = str_b[i - len_a];
|
|
}
|
|
|
|
output[i] = 0;
|
|
|
|
return output;
|
|
}
|
|
|
|
void *add_values(void **value0, void **value1){
|
|
char *new_str;
|
|
|
|
if((int) value0[0] == INT_VAL && (int) value1[0] == INT_VAL){
|
|
value0[1] = (void *) ((int) value0[1] + (int) value1[1]);
|
|
free_value(value1);
|
|
return value0;
|
|
} else if((int) value0[0] == STR_VAL && (int) value1[0] == STR_VAL){
|
|
new_str = concat((char *) value0[1], (char *) value1[1]);
|
|
kfree(value0[1]);
|
|
kfree(value1[1]);
|
|
value0[1] = new_str;
|
|
return value0;
|
|
} else {
|
|
free_value(value0);
|
|
free_value(value1);
|
|
value0 = create_value(ERR_VAL, (void *) 0);
|
|
return value0;
|
|
}
|
|
}
|
|
|
|
void *subtract_values(void **value0, void **value1){
|
|
char *new_str;
|
|
|
|
if((int) value0[0] == INT_VAL && (int) value1[0] == INT_VAL){
|
|
value0[1] = (void *) ((int) value0[1] - (int) value1[1]);
|
|
free_value(value1);
|
|
return value0;
|
|
} else {
|
|
free_value(value0);
|
|
free_value(value1);
|
|
value0 = create_value(ERR_VAL, (void *) 0);
|
|
return value0;
|
|
}
|
|
}
|
|
|
|
void *multiply_values(void **value0, void **value1){
|
|
char *new_str;
|
|
|
|
if((int) value0[0] == INT_VAL && (int) value1[0] == INT_VAL){
|
|
value0[1] = (void *) ((int) value0[1]*(int) value1[1]);
|
|
free_value(value1);
|
|
return value0;
|
|
} else {
|
|
free_value(value0);
|
|
free_value(value1);
|
|
value0 = create_value(ERR_VAL, (void *) 0);
|
|
return value0;
|
|
}
|
|
}
|
|
|
|
void *divide_values(void **value0, void **value1){
|
|
char *new_str;
|
|
|
|
if((int) value0[0] == INT_VAL && (int) value1[0] == INT_VAL){
|
|
value0[1] = (void *) ((int) value0[1]/(int) value1[1]);
|
|
free_value(value1);
|
|
return value0;
|
|
} else {
|
|
free_value(value0);
|
|
free_value(value1);
|
|
value0 = create_value(ERR_VAL, (void *) 0);
|
|
return value0;
|
|
}
|
|
}
|
|
|
|
void *equals_values(void **value0, void **value1){
|
|
int result;
|
|
|
|
if((int) value0[0] == INT_VAL && (int) value1[0] == INT_VAL){
|
|
result = (value0[1] == value1[1]);
|
|
value0[1] = (void *) result;
|
|
free_value(value1);
|
|
return value0;
|
|
} else if((int) value0[0] == STR_VAL && (int) value1[0] == STR_VAL){
|
|
result = !strcmp(value0[1], value1[1]);
|
|
kfree(value0[1]);
|
|
value0[0] = (void *) INT_VAL;
|
|
value0[1] = (void *) result;
|
|
free_value(value1);
|
|
return value0;
|
|
} else if((int) value0[0] != ERR_VAL && (int) value1[0] != ERR_VAL){
|
|
free_value(value0);
|
|
free_value(value1);
|
|
return create_value(INT_VAL, (void *) 0);
|
|
} else {
|
|
free_value(value0);
|
|
free_value(value1);
|
|
return create_value(ERR_VAL, (void *) 0);
|
|
}
|
|
}
|
|
|
|
void *not_equals_values(void **value0, void **value1){
|
|
int result;
|
|
|
|
if((int) value0[0] == INT_VAL && (int) value1[0] == INT_VAL){
|
|
result = (value0[1] != value1[1]);
|
|
value0[1] = (void *) result;
|
|
free_value(value1);
|
|
return value0;
|
|
} else if((int) value0[0] == STR_VAL && (int) value1[0] == STR_VAL){
|
|
result = !!strcmp(value0[1], value1[1]);
|
|
kfree(value0[1]);
|
|
value0[0] = (void *) INT_VAL;
|
|
value0[1] = (void *) result;
|
|
free_value(value1);
|
|
return value0;
|
|
} else if((int) value0[0] != ERR_VAL && (int) value1[0] != ERR_VAL){
|
|
free_value(value0);
|
|
free_value(value1);
|
|
return create_value(INT_VAL, (void *) 1);
|
|
} else {
|
|
free_value(value0);
|
|
free_value(value1);
|
|
return create_value(ERR_VAL, (void *) 0);
|
|
}
|
|
}
|
|
|
|
void *greater_than_values(void **value0, void **value1){
|
|
if((int) value0[0] == INT_VAL && (int) value1[0] == INT_VAL){
|
|
value0[1] = (void *) ((int) value0[1] > (int) value1[1]);
|
|
free_value(value1);
|
|
return value0;
|
|
} else {
|
|
free_value(value0);
|
|
free_value(value1);
|
|
return create_value(ERR_VAL, (void *) 0);
|
|
}
|
|
}
|
|
|
|
void *less_than_values(void **value0, void **value1){
|
|
if((int) value0[0] == INT_VAL && (int) value1[0] == INT_VAL){
|
|
value0[1] = (void *) ((int) value0[1] < (int) value1[1]);
|
|
free_value(value1);
|
|
return value0;
|
|
} else {
|
|
free_value(value0);
|
|
free_value(value1);
|
|
return create_value(ERR_VAL, (void *) 0);
|
|
}
|
|
}
|
|
|
|
void *and_values(void **value0, void **value1){
|
|
if((int) value0[0] == INT_VAL && (int) value1[0] == INT_VAL){
|
|
value0[1] = (void *) ((int) value0[1] && (int) value1[1]);
|
|
free_value(value1);
|
|
return value0;
|
|
} else {
|
|
free_value(value0);
|
|
free_value(value1);
|
|
return create_value(ERR_VAL, (void *) 0);
|
|
}
|
|
}
|
|
|
|
void *or_values(void **value0, void **value1){
|
|
if((int) value0[0] == INT_VAL && (int) value1[0] == INT_VAL){
|
|
value0[1] = (void *) ((int) value0[1] || (int) value1[1]);
|
|
free_value(value1);
|
|
return value0;
|
|
} else {
|
|
free_value(value0);
|
|
free_value(value1);
|
|
return create_value(ERR_VAL, (void *) 0);
|
|
}
|
|
}
|
|
|
|
void *strfunc(void **value1){
|
|
int int_arg;
|
|
int is_neg;
|
|
char *new_str;
|
|
char *str_pos;
|
|
char buffer[16];
|
|
char c;
|
|
|
|
is_neg = 0;
|
|
|
|
if((int) value1[0] == INT_VAL){
|
|
int_arg = (int) value1[1];
|
|
buffer[15] = 0;
|
|
str_pos = buffer + 14;
|
|
if(int_arg < 0){
|
|
int_arg = -int_arg;
|
|
is_neg = 1;
|
|
}
|
|
if(!int_arg){
|
|
*str_pos = '0';
|
|
str_pos = str_pos - 1;
|
|
} else {
|
|
while(int_arg){
|
|
c = int_arg%10 + '0';
|
|
*str_pos = c;
|
|
str_pos = str_pos - 1;
|
|
int_arg = int_arg/10;
|
|
}
|
|
}
|
|
if(is_neg){
|
|
*str_pos = '-';
|
|
str_pos = str_pos - 1;
|
|
}
|
|
new_str = kmalloc(CHAR_SIZE*(buffer - str_pos + 16));
|
|
strcpy(new_str, str_pos + 1);
|
|
free_value(value1);
|
|
return create_value(STR_VAL, new_str);
|
|
} else if((int) value1[0] == STR_VAL){
|
|
return value1;
|
|
} else {
|
|
free_value(value1);
|
|
return create_value(ERR_VAL, (void *) 0);
|
|
}
|
|
}
|
|
|
|
void *substring(void **value1, void **value2, void **value3){
|
|
int char0;
|
|
int char1;
|
|
int str_len;
|
|
char *str;
|
|
char *new_str;
|
|
|
|
if((int) value1[0] == STR_VAL && (int) value2[0] == INT_VAL && (int) value3[0] == INT_VAL){
|
|
str = value1[1];
|
|
str_len = strlen(str);
|
|
char0 = (int) value2[1];
|
|
char1 = (int) value3[1];
|
|
if(char0 < 0)
|
|
char0 = 0;
|
|
if(char0 >= str_len)
|
|
char0 = str_len - 1;
|
|
if(char1 < 0)
|
|
char1 = 0;
|
|
if(char1 >= str_len)
|
|
char1 = str_len - 1;
|
|
if(char0 > char1){
|
|
free_value(value1);
|
|
free_value(value2);
|
|
free_value(value3);
|
|
str = kmalloc(CHAR_SIZE);
|
|
*str = 0;
|
|
return create_value(STR_VAL, str);
|
|
} else {
|
|
new_str = kmalloc(CHAR_SIZE*(char1 - char0 + 2));
|
|
strncpy(new_str, str + char0, char1 - char0 + 1);
|
|
free_value(value1);
|
|
free_value(value2);
|
|
free_value(value3);
|
|
return create_value(STR_VAL, new_str);
|
|
}
|
|
} else {
|
|
free_value(value1);
|
|
free_value(value2);
|
|
free_value(value3);
|
|
return create_value(ERR_VAL, (void *) 0);
|
|
}
|
|
}
|
|
|
|
void *evaluate(void *expression){
|
|
void **var;
|
|
void *index_expr;
|
|
int index;
|
|
int length;
|
|
void **index_value;
|
|
void **var_value;
|
|
|
|
if(((int *) expression)[0] == INT_TOKEN){
|
|
return create_value(INT_VAL, ((void **) expression)[1]);
|
|
} else if(((int *) expression)[0] == STR_TOKEN){
|
|
return create_value(STR_VAL, duplicate_str(((void **) expression)[1]));
|
|
} else if(((int *) expression)[0] == PLUS){
|
|
return add_values(evaluate(((void **) expression)[1]), evaluate(((void **) expression)[2]));
|
|
} else if(((int *) expression)[0] == MINUS){
|
|
return subtract_values(evaluate(((void **) expression)[1]), evaluate(((void **) expression)[2]));
|
|
} else if(((int *) expression)[0] == MULTIPLY){
|
|
return multiply_values(evaluate(((void **) expression)[1]), evaluate(((void **) expression)[2]));
|
|
} else if(((int *) expression)[0] == DIVIDE){
|
|
return divide_values(evaluate(((void **) expression)[1]), evaluate(((void **) expression)[2]));
|
|
} else if(((int *) expression)[0] == EQUALS){
|
|
return equals_values(evaluate(((void **) expression)[1]), evaluate(((void **) expression)[2]));
|
|
} else if(((int *) expression)[0] == NOT_EQUALS){
|
|
return not_equals_values(evaluate(((void **) expression)[1]), evaluate(((void **) expression)[2]));
|
|
} else if(((int *) expression)[0] == GREATER_THAN){
|
|
return greater_than_values(evaluate(((void **) expression)[1]), evaluate(((void **) expression)[2]));
|
|
} else if(((int *) expression)[0] == LESS_THAN){
|
|
return less_than_values(evaluate(((void **) expression)[1]), evaluate(((void **) expression)[2]));
|
|
} else if(((int *) expression)[0] == OR){
|
|
return or_values(evaluate(((void **) expression)[1]), evaluate(((void **) expression)[2]));
|
|
} else if(((int *) expression)[0] == AND){
|
|
return and_values(evaluate(((void **) expression)[1]), evaluate(((void **) expression)[2]));
|
|
} else if(((int *) expression)[0] == VAR_TOKEN){
|
|
var = read_dictionary(variables, ((void **) expression)[1], 0);
|
|
if(!(int) var){
|
|
return create_value(INT_VAL, (void *) 0);
|
|
}
|
|
|
|
index_expr = ((void **) expression)[2];
|
|
if((int) index_expr){
|
|
index_value = evaluate(index_expr);
|
|
if(((int *) index_value)[0] == INT_VAL){
|
|
index = (int) index_value[1];
|
|
} else {
|
|
free_value(index_value);
|
|
return create_value(ERR_VAL, (void *) 0);
|
|
}
|
|
free_value(index_value);
|
|
length = ((int *) var)[2];
|
|
if(index >= length || index < 0)
|
|
return create_value(ERR_VAL, (void *) 0);
|
|
} else {
|
|
index = 0;
|
|
}
|
|
|
|
var_value = ((void ***) var)[1][index];
|
|
if(((int *) var_value)[0] == STR_VAL)
|
|
return create_value(((int *) var_value)[0], duplicate_str(((char **) var_value)[1]));
|
|
else
|
|
return create_value(((int *) var_value)[0], ((void **) var_value)[1]);
|
|
} else if(((int *) expression)[0] == SUBSTRING){
|
|
void *arg1;
|
|
void *arg2;
|
|
void *arg3;
|
|
void *value1;
|
|
void *value2;
|
|
void *value3;
|
|
|
|
arg1 = ((void **) expression)[1];
|
|
arg2 = ((void **) expression)[2];
|
|
arg3 = ((void **) expression)[3];
|
|
|
|
value1 = evaluate(arg1);
|
|
value2 = evaluate(arg2);
|
|
value3 = evaluate(arg3);
|
|
|
|
return substring(value1, value2, value3);
|
|
} else if(((int *) expression)[0] == STRFUNC){
|
|
void *arg1;
|
|
void *value1;
|
|
|
|
arg1 = ((void **) expression)[1];
|
|
|
|
value1 = evaluate(arg1);
|
|
|
|
return strfunc(value1);
|
|
} else {
|
|
return create_value(ERR_VAL, (void *) 0);
|
|
}
|
|
}
|
|
|
|
void print_value(void **value){
|
|
if((int) value[0] == INT_VAL){
|
|
printd((int) value[1]);
|
|
} else if((int) value[0] == STR_VAL){
|
|
prints(value[1]);
|
|
}
|
|
}
|
|
|
|
int run_print(void **statement){
|
|
void **expr_value;
|
|
|
|
expr_value = evaluate(statement[1]);
|
|
print_value(expr_value);
|
|
if((int) expr_value[0] == ERR_VAL){
|
|
free_value(expr_value);
|
|
return 1;
|
|
} else {
|
|
prints("\n");
|
|
free_value(expr_value);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int run_if(void **statement){
|
|
void **expr_value;
|
|
|
|
expr_value = evaluate(statement[1]);
|
|
if((int) expr_value[0] == ERR_VAL){
|
|
free_value(expr_value);
|
|
return 1;
|
|
} else if((int) expr_value[0] != INT_VAL || ((int) expr_value[0] == INT_VAL && (int) expr_value[1])){
|
|
free_value(expr_value);
|
|
return 0;
|
|
} else {
|
|
do_skip_if = 1;
|
|
free_value(expr_value);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int run_goto(void **statement){
|
|
void **expr_value;
|
|
|
|
expr_value = evaluate(statement[1]);
|
|
if((int) expr_value[0] != INT_VAL){
|
|
free_value(expr_value);
|
|
return 1;
|
|
}
|
|
goto_label = (int) expr_value[1];
|
|
free_value(expr_value);
|
|
do_goto = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int run_gosub(void **statement){
|
|
void **expr_value;
|
|
|
|
expr_value = evaluate(statement[1]);
|
|
if((int) expr_value[0] != INT_VAL){
|
|
free_value(expr_value);
|
|
return 1;
|
|
}
|
|
goto_label = (int) expr_value[1];
|
|
free_value(expr_value);
|
|
do_gosub = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int run_return(void **statement){
|
|
do_return = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int run_while(void **statement){
|
|
void **expr_value;
|
|
|
|
expr_value = evaluate(statement[1]);
|
|
if((int) expr_value[0] == ERR_VAL){
|
|
free_value(expr_value);
|
|
return 1;
|
|
} else if((int) expr_value[0] != INT_VAL || ((int) expr_value[0] == INT_VAL && (int) expr_value[1])){
|
|
free_value(expr_value);
|
|
return 0;
|
|
} else {
|
|
do_skip_while = 1;
|
|
free_value(expr_value);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int set_var(void **var_token, void **value){
|
|
void *var;
|
|
void **index_expr;
|
|
void **index_value;
|
|
void **var_values;
|
|
void **value_before;
|
|
int index;
|
|
int length;
|
|
|
|
var = read_dictionary(variables, var_token[1], 0);
|
|
if(!(int) var){
|
|
index_expr = var_token[2];
|
|
if((int) index_expr){
|
|
index_value = evaluate(index_expr);
|
|
if(((int *) index_value)[0] == INT_VAL){
|
|
index = (int) index_value[1];
|
|
} else {
|
|
free_value(index_value);
|
|
return 1;
|
|
}
|
|
free_value(index_value);
|
|
} else {
|
|
index = 0;
|
|
}
|
|
if(index != 0)
|
|
return 1;
|
|
var_values = kmalloc(POINTER_SIZE);
|
|
var_values[0] = value;
|
|
write_dictionary(variables, var_token[1], create_variable(INTVAR, var_values, 1), 0);
|
|
} else {
|
|
index_expr = var_token[2];
|
|
if((int) index_expr){
|
|
index_value = evaluate(index_expr);
|
|
if(((int *) index_value)[0] == INT_VAL){
|
|
index = (int) index_value[1];
|
|
} else {
|
|
free_value(index_value);
|
|
return 1;
|
|
}
|
|
free_value(index_value);
|
|
} else {
|
|
index = 0;
|
|
}
|
|
length = ((int *) var)[2];
|
|
if(index >= length || index < 0)
|
|
return 1;
|
|
value_before = ((void ***) var)[1][index];
|
|
free_value(value_before);
|
|
((void ***) var)[1][index] = value;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void del_var(void **var_token){
|
|
void *var;
|
|
void **values;
|
|
int i;
|
|
int size;
|
|
|
|
var = read_dictionary(variables, var_token[1], 0);
|
|
if(!var)
|
|
return;
|
|
values = ((void **) var)[1];
|
|
size = ((int *) var)[2];
|
|
for(i = 0; i < size; i = i + 1)
|
|
free_value(values[i]);
|
|
kfree(values);
|
|
kfree(var);
|
|
write_dictionary(variables, var_token[1], (void *) 0, 0);
|
|
}
|
|
|
|
int run_dim(void **statement){
|
|
void **var_token;
|
|
void *expr;
|
|
void **value;
|
|
void **values;
|
|
void *var;
|
|
int size;
|
|
int i;
|
|
|
|
var_token = statement[1];
|
|
expr = statement[2];
|
|
value = evaluate(expr);
|
|
if((int) value[0] != INT_VAL || (int) value[1] < 1){
|
|
free_value(value);
|
|
return 1;
|
|
}
|
|
del_var(var_token);
|
|
size = (int) value[1];
|
|
free_value(value);
|
|
values = kmalloc(POINTER_SIZE*size);
|
|
for(i = 0; i < size; i = i + 1)
|
|
values[i] = create_value(INT_VAL, (void *) 0);
|
|
var = create_variable(INTVAR, values, size);
|
|
write_dictionary(variables, var_token[1], var, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int run_input(void **statement){
|
|
int inp;
|
|
void **var_token;
|
|
void **value;
|
|
|
|
inp = inputd();
|
|
|
|
var_token = statement[1];
|
|
value = create_value(INT_VAL, (void *) inp);
|
|
if(set_var(var_token, value)){
|
|
free_value(value);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int run_inputstr(void **statement){
|
|
char inp_buffer[256];
|
|
int inp_length;
|
|
char *new_str;
|
|
void **var_token;
|
|
void **value;
|
|
|
|
inputs(inp_buffer, 256);
|
|
inp_length = strlen(inp_buffer);
|
|
if(inp_length){
|
|
inp_buffer[inp_length - 1] = 0;
|
|
inp_length = inp_length - 1;
|
|
}
|
|
new_str = kmalloc(CHAR_SIZE*(inp_length + 1));
|
|
strcpy(new_str, inp_buffer);
|
|
|
|
var_token = statement[1];
|
|
value = create_value(STR_VAL, new_str);
|
|
if(set_var(var_token, value)){
|
|
free_value(value);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int run_let(void **statement){
|
|
void **var_token;
|
|
void **expr;
|
|
void **value;
|
|
|
|
var_token = statement[1];
|
|
value = evaluate(statement[2]);
|
|
if(((int *) value)[0] == ERR_VAL){
|
|
free_value(value);
|
|
return 1;
|
|
}
|
|
if(set_var(var_token, value)){
|
|
free_value(value);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int run_end(void **statement){
|
|
int mode;
|
|
|
|
mode = ((int *) statement)[1];
|
|
if(!mode)
|
|
do_end = 1;
|
|
else if(mode == WHILE){
|
|
do_while = 1;
|
|
} else if(mode != IF){
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void *skip_to_end(void *current_statement_list, int mode){
|
|
int counter;
|
|
void *list_value;
|
|
void *next;
|
|
|
|
counter = 1;
|
|
next = next_list(current_statement_list);
|
|
if((int) next)
|
|
current_statement_list = next;
|
|
while((int) (next = next_list(current_statement_list))){
|
|
list_value = get_list_value(current_statement_list);
|
|
if(list_value){
|
|
if(((int **) list_value)[0][0] == mode)
|
|
counter = counter + 1;
|
|
else if(((int **) list_value)[0][0] == END && ((int **) list_value)[0][1] == mode)
|
|
counter = counter - 1;
|
|
if(!counter)
|
|
return current_statement_list;
|
|
}
|
|
current_statement_list = next;
|
|
}
|
|
|
|
return current_statement_list;
|
|
}
|
|
|
|
void *seek(void *current_statement_list, int mode){
|
|
int counter;
|
|
void *list_value;
|
|
void *prev;
|
|
|
|
counter = 1;
|
|
current_statement_list = previous_list(current_statement_list);
|
|
while((int) (prev = previous_list(current_statement_list)) && counter){
|
|
list_value = get_list_value(current_statement_list);
|
|
if(((int **) list_value)[0][0] == END && ((int **) list_value)[0][1] == mode)
|
|
counter = counter + 1;
|
|
else if(((int **) list_value)[0][0] == mode)
|
|
counter = counter - 1;
|
|
if(!counter)
|
|
return previous_list(current_statement_list);
|
|
current_statement_list = prev;
|
|
}
|
|
|
|
return (void *) 0;
|
|
}
|
|
|
|
void *seek_goto(int line){
|
|
void *current_statement_list;
|
|
void **list_value;
|
|
|
|
current_statement_list = next_list(statement_list);
|
|
while((int) current_statement_list){
|
|
list_value = get_list_value(current_statement_list);
|
|
if(((int *) list_value)[1] == line)
|
|
return current_statement_list;
|
|
current_statement_list = next_list(current_statement_list);
|
|
}
|
|
|
|
return (void *) 0;
|
|
}
|
|
|
|
int run_statement(void **statement);
|
|
|
|
int run_program(void *current_statement_list){
|
|
void *current_statement_entry;
|
|
|
|
while((int) current_statement_list){
|
|
current_statement_entry = get_list_value(current_statement_list);
|
|
if(run_statement(((void **) current_statement_entry)[0]))
|
|
return 1;
|
|
if(do_end){
|
|
do_end = 0;
|
|
return 0;
|
|
} else if(do_skip_if){
|
|
current_statement_list = skip_to_end(current_statement_list, IF);
|
|
do_skip_if = 0;
|
|
if(!(int) next_list(current_statement_list))
|
|
return 1;
|
|
} else if(do_skip_while){
|
|
current_statement_list = skip_to_end(current_statement_list, WHILE);
|
|
do_skip_while = 0;
|
|
if(!(int) next_list(current_statement_list))
|
|
return 1;
|
|
} else if(do_while){
|
|
current_statement_list = seek(current_statement_list, WHILE);
|
|
do_while = 0;
|
|
if(!(int) current_statement_list)
|
|
return 1;
|
|
} else if(do_goto){
|
|
current_statement_list = previous_list(seek_goto(goto_label));
|
|
do_goto = 0;
|
|
if(!(int) current_statement_list)
|
|
return 1;
|
|
} else if(do_gosub){
|
|
if(current_gosub < 32){
|
|
gosubs[current_gosub] = ((int *) current_statement_entry)[1];
|
|
current_gosub = current_gosub + 1;
|
|
current_statement_list = previous_list(seek_goto(goto_label));
|
|
do_gosub = 0;
|
|
if(!(int) current_statement_list)
|
|
return 1;
|
|
} else {
|
|
return 1;
|
|
}
|
|
} else if(do_return){
|
|
if(current_gosub){
|
|
current_gosub = current_gosub - 1;
|
|
current_statement_list = seek_goto(gosubs[current_gosub]);
|
|
do_return = 0;
|
|
if(!(int) current_statement_list)
|
|
return 1;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
current_statement_list = next_list(current_statement_list);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int run_list(void **statement);
|
|
|
|
int run_statement(void **statement){
|
|
if((int) statement[0] == PRINT)
|
|
return run_print(statement);
|
|
else if((int) statement[0] == INPUT)
|
|
return run_input(statement);
|
|
else if((int) statement[0] == INPUTSTR)
|
|
return run_inputstr(statement);
|
|
else if((int) statement[0] == RUN)
|
|
return run_program(next_list(statement_list));
|
|
else if((int) statement[0] == END)
|
|
return run_end(statement);
|
|
else if((int) statement[0] == IF)
|
|
return run_if(statement);
|
|
else if((int) statement[0] == WHILE)
|
|
return run_while(statement);
|
|
else if((int) statement[0] == LET)
|
|
return run_let(statement);
|
|
else if((int) statement[0] == DIM)
|
|
return run_dim(statement);
|
|
else if((int) statement[0] == GOTO)
|
|
return run_goto(statement);
|
|
else if((int) statement[0] == GOSUB)
|
|
return run_gosub(statement);
|
|
else if((int) statement[0] == RETURN)
|
|
return run_return(statement);
|
|
else if((int) statement[0] == LIST)
|
|
return run_list(statement);
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
void list_statement(void **statement){
|
|
if((int) statement[0] == PRINT)
|
|
list_print(statement);
|
|
else if((int) statement[0] == INPUT)
|
|
list_input(statement);
|
|
else if((int) statement[0] == INPUTSTR)
|
|
list_inputstr(statement);
|
|
else if((int) statement[0] == RUN)
|
|
list_run(next_list(statement_list));
|
|
else if((int) statement[0] == END)
|
|
list_end(statement);
|
|
else if((int) statement[0] == IF)
|
|
list_if(statement);
|
|
else if((int) statement[0] == WHILE)
|
|
list_while(statement);
|
|
else if((int) statement[0] == LET)
|
|
list_let(statement);
|
|
else if((int) statement[0] == DIM)
|
|
list_dim(statement);
|
|
else if((int) statement[0] == GOTO)
|
|
list_goto(statement);
|
|
else if((int) statement[0] == GOSUB)
|
|
list_gosub(statement);
|
|
else if((int) statement[0] == RETURN)
|
|
list_return(statement);
|
|
else if((int) statement[0] == LIST)
|
|
list_list(statement);
|
|
}
|
|
|
|
void remove_line(int line_number){
|
|
void *current_statement_list;
|
|
void *current_statement;
|
|
|
|
current_statement_list = next_list(statement_list);
|
|
while((int) current_statement_list){
|
|
current_statement = get_list_value(current_statement_list);
|
|
if(((int *) current_statement)[1] == line_number){
|
|
free_statement(((void **) current_statement)[0]);
|
|
remove_value(current_statement_list, kfree);
|
|
return;
|
|
}
|
|
current_statement_list = next_list(current_statement_list);
|
|
}
|
|
}
|
|
|
|
int run_list(void **statement){
|
|
void *current_statement_list;
|
|
void *current_statement;
|
|
int line;
|
|
|
|
current_statement_list = next_list(statement_list);
|
|
while(current_statement_list){
|
|
current_statement = get_list_value(current_statement_list);
|
|
line = ((int *) current_statement)[1];
|
|
printd(line);
|
|
prints(" ");
|
|
list_statement(((void **) current_statement)[0]);
|
|
prints("\n");
|
|
current_statement_list = next_list(current_statement_list);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void insert_statement(void *statement, int line_number){
|
|
void *statement_entry;
|
|
void *current_statement_list;
|
|
void *current_statement_entry;
|
|
void *new_statement_entry;
|
|
void *previous_statement_list;
|
|
int current_line_number;
|
|
|
|
new_statement_entry = create_statement_entry(statement, line_number);
|
|
previous_statement_list = statement_list;
|
|
current_statement_list = next_list(previous_statement_list);
|
|
while((int) current_statement_list){
|
|
current_statement_entry = get_list_value(current_statement_list);
|
|
current_line_number = ((int *) current_statement_entry)[1];
|
|
if(current_line_number > line_number){
|
|
add_value(previous_statement_list, new_statement_entry);
|
|
return;
|
|
} else if(current_line_number == line_number){
|
|
remove_value(current_statement_list, free_statement_entry);
|
|
add_value(previous_statement_list, new_statement_entry);
|
|
return;
|
|
}
|
|
previous_statement_list = current_statement_list;
|
|
current_statement_list = next_list(current_statement_list);
|
|
}
|
|
|
|
add_value(previous_statement_list, new_statement_entry);
|
|
}
|
|
|
|
void add_statement(char **c){
|
|
int line_number;
|
|
void *statement;
|
|
|
|
line_number = get_int(c);
|
|
skip_whitespace(c);
|
|
if(!**c){
|
|
remove_line(line_number);
|
|
return;
|
|
}
|
|
|
|
statement = get_statement(c);
|
|
if((int) statement)
|
|
insert_statement(statement, line_number);
|
|
else
|
|
prints("SYNTAX ERROR");
|
|
}
|
|
|
|
void entry(){
|
|
char buffer[256];
|
|
char *c;
|
|
void *statement;
|
|
|
|
ERR_VAL = 0;
|
|
INT_VAL = 1;
|
|
STR_VAL = 2;
|
|
kmalloc_init(malloc(32000), 32000);
|
|
|
|
variables = create_dictionary((void *) 0);
|
|
statement_list = create_linked_list(&ERR_VAL);
|
|
init_tokens();
|
|
|
|
do_end = 0;
|
|
do_if = 0;
|
|
do_while = 0;
|
|
do_skip_if = 0;
|
|
do_skip_while = 0;
|
|
do_goto = 0;
|
|
do_gosub = 0;
|
|
do_return = 0;
|
|
|
|
current_gosub = 0;
|
|
|
|
while(1){
|
|
prints("\n>: ");
|
|
inputs(buffer, 256);
|
|
c = buffer;
|
|
skip_whitespace(&c);
|
|
if(digit(*c)){
|
|
add_statement(&c);
|
|
} else {
|
|
statement = get_statement(&c);
|
|
if(!(int) statement){
|
|
prints("SYNTAX ERROR");
|
|
} else {
|
|
if(run_statement(statement))
|
|
prints("RUNTIME ERROR");
|
|
free_statement(statement);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|