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);
			}
		}
	}
}