Started Implementing a BASIC interpriter

This commit is contained in:
OusmBlueNinja 2024-12-30 15:52:32 -06:00
parent e82fb49c04
commit 3eee0f8269
73 changed files with 984 additions and 644 deletions

22
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,22 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${default}",
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"windowsSdkVersion": "10.0.22621.0",
"compilerPath": "C:/msys64/mingw64/bin/gcc.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}

Binary file not shown.

Binary file not shown.

BIN
build/x86_64/basic.o Normal file

Binary file not shown.

BIN
build/x86_64/strings.o Normal file

Binary file not shown.

BIN
dist/x86_64/kernel.bin vendored Normal file

Binary file not shown.

View File

@ -10,9 +10,7 @@
#include "window.h" #include "window.h"
#include "fs.h" #include "fs.h"
#include "fat12.h" #include "fat12.h"
#include "basic.h"
#define COMMAND_BUFFER_SIZE 256 // Increase buffer size to handle longer commands #define COMMAND_BUFFER_SIZE 256 // Increase buffer size to handle longer commands
#define BACKSPACE_KEY 8 #define BACKSPACE_KEY 8
@ -22,9 +20,9 @@
extern void kpanic(int error_code); extern void kpanic(int error_code);
void shutdown_system()
void shutdown_system() { {
__asm__ ( __asm__(
"movl $1, %eax\n" // syscall number for sys_reboot (1 in this case) "movl $1, %eax\n" // syscall number for sys_reboot (1 in this case)
"movl $0, %ebx\n" // reboot flags "movl $0, %ebx\n" // reboot flags
"movl $0, %ecx\n" // no additional arguments "movl $0, %ecx\n" // no additional arguments
@ -33,18 +31,20 @@ void shutdown_system() {
); );
} }
char commandHistory[HISTORY_SIZE][COMMAND_BUFFER_SIZE]; char commandHistory[HISTORY_SIZE][COMMAND_BUFFER_SIZE];
int currentHistoryIndex = 0; int currentHistoryIndex = 0;
int historyCount = 0; int historyCount = 0;
void add_to_history(const char* command) { void add_to_history(const char *command)
if (historyCount < HISTORY_SIZE) { {
if (historyCount < HISTORY_SIZE)
{
historyCount++; historyCount++;
} else { }
for (int i = 1; i < HISTORY_SIZE; i++) { else
{
for (int i = 1; i < HISTORY_SIZE; i++)
{
strcpy(commandHistory[i - 1], commandHistory[i]); strcpy(commandHistory[i - 1], commandHistory[i]);
} }
} }
@ -52,23 +52,26 @@ void add_to_history(const char* command) {
currentHistoryIndex = historyCount; currentHistoryIndex = historyCount;
} }
const char* get_previous_command() { const char *get_previous_command()
if (currentHistoryIndex > 0) { {
if (currentHistoryIndex > 0)
{
currentHistoryIndex--; currentHistoryIndex--;
return commandHistory[currentHistoryIndex]; return commandHistory[currentHistoryIndex];
} }
return NULL; return NULL;
} }
const char* get_next_command() { const char *get_next_command()
if (currentHistoryIndex < historyCount - 1) { {
if (currentHistoryIndex < historyCount - 1)
{
currentHistoryIndex++; currentHistoryIndex++;
return commandHistory[currentHistoryIndex]; return commandHistory[currentHistoryIndex];
} }
return NULL; return NULL;
} }
const void clear() const void clear()
{ {
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set text color print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set text color
@ -79,27 +82,35 @@ const void clear()
print_setup_prompt(); print_setup_prompt();
} }
void halt()
{
void halt(){
print_str("[ WARN ] HALT\n"); print_str("[ WARN ] HALT\n");
while (1) {} while (1)
{
}
} }
void commandHandler(char* command) { void commandHandler(char *command)
{
printf("\n"); printf("\n");
if (strcmp(command, "cls") == 0) { if (strcmp(command, "cls") == 0)
{
clear(); clear();
} else if (strcmp(command, "knp") == 0) { }
else if (strcmp(command, "knp") == 0)
{
kpanic(1); kpanic(1);
} else if (int_strncmp(command, "echo ", 5) == 0) { }
char* message = command + 5; // Skip the "echo " part else if (int_strncmp(command, "echo ", 5) == 0)
{
char *message = command + 5; // Skip the "echo " part
print_str("\n"); print_str("\n");
print_str(message); print_str(message);
print_str("\n"); print_str("\n");
} else if (int_strncmp(command, "cwin", 4) == 0) { }
else if (int_strncmp(command, "cwin", 4) == 0)
{
// Define window properties // Define window properties
Window myWindow; Window myWindow;
int x = 8; // X position of the window int x = 8; // X position of the window
@ -117,75 +128,81 @@ void commandHandler(char* command) {
print_text_in_window(&myWindow, 2, 2, "Window Manager is a "); print_text_in_window(&myWindow, 2, 2, "Window Manager is a ");
print_text_in_window(&myWindow, 2, 3, "Work in progress, Sorry :("); // Print text inside the window print_text_in_window(&myWindow, 2, 3, "Work in progress, Sorry :("); // Print text inside the window
print_text_in_window(&myWindow, 2, 4, "do [ cls ] to clear"); // Print text inside the window print_text_in_window(&myWindow, 2, 4, "do [ cls ] to clear"); // Print text inside the window
}
else if (int_strncmp(command, "exit", 4) == 0)
{
} else if (int_strncmp(command, "exit", 4) == 0) {
printf("Driver Call [ shutdown_system(); ] \n"); printf("Driver Call [ shutdown_system(); ] \n");
shutdown_system(); shutdown_system();
}
else if (int_strncmp(command, "panic_test", 10) == 0)
} else if (int_strncmp(command, "panic_test", 10) == 0) { {
int _y = 1/0; int _y = 1 / 0;
printf("Output %d\n", _y); printf("Output %d\n", _y);
}
} else if (int_strncmp(command, "test", 4) == 0) { else if (int_strncmp(command, "test", 4) == 0)
{
//// Test custom malloc and free //// Test custom malloc and free
//void* block1 = malloc(32); // void* block1 = malloc(32);
//void* block2 = malloc(64); // void* block2 = malloc(64);
//void* block3 = malloc(128); // void* block3 = malloc(128);
// //
//// List used blocks //// List used blocks
//list_used_blocks(); // list_used_blocks();
// //
//// Free a block and check again //// Free a block and check again
//free(block2); // free(block2);
//printf("\nAfter freeing block2:\n"); // printf("\nAfter freeing block2:\n");
//list_used_blocks(); // list_used_blocks();
// //
//void* block4 = malloc(64); // void* block4 = malloc(64);
// //
//list_used_blocks(); // list_used_blocks();
create_game(); create_game();
}
} else if (int_strncmp(command, "split", 5) == 0) { else if (int_strncmp(command, "split", 5) == 0)
{
printf("Kernel Call [ split_string(); ]\n"); printf("Kernel Call [ split_string(); ]\n");
// Check the length of the command string and use it properly // Check the length of the command string and use it properly
char** new_command = split_string(command, ",", strlen(command)); char **new_command = split_string(command, ",", strlen(command));
//char** new_command = {{NULL, NULL, NULL, NULL}}; // char** new_command = {{NULL, NULL, NULL, NULL}};
if (new_command) { if (new_command)
{
// Add a loop to print all the elements in the new_command array for debugging // Add a loop to print all the elements in the new_command array for debugging
for (int i = 0; new_command[i] != NULL; i++) { for (int i = 0; new_command[i] != NULL; i++)
{
printf("new_command[%d]: %s\n", i, new_command[i]); printf("new_command[%d]: %s\n", i, new_command[i]);
} }
//halt(); // Debug halt // halt(); // Debug halt
// Ensure that new_command[1] exists before accessing it // Ensure that new_command[1] exists before accessing it
if (new_command[1] != NULL) { if (new_command[1] != NULL)
{
printf("%s\n", new_command[1]); printf("%s\n", new_command[1]);
} else { }
else
{
printf("Error: new_command[1] is NULL\n"); printf("Error: new_command[1] is NULL\n");
} }
} else { }
else
{
printf("Error: split_string returned NULL\n"); printf("Error: split_string returned NULL\n");
} }
}
else
} else { {
printf("Unknown command: %s\n", command); printf("Unknown command: %s\n", command);
} }
} }
void print_setup_prompt()
{
void print_setup_prompt() {
move_cursor(0, 0); move_cursor(0, 0);
print_set_color(PRINT_COLOR_LIGHT_RED, PRINT_COLOR_BLACK); print_set_color(PRINT_COLOR_LIGHT_RED, PRINT_COLOR_BLACK);
print_str("-------------------- "); print_str("-------------------- ");
@ -197,35 +214,59 @@ void print_setup_prompt() {
print_str("V 1.5.01\n"); print_str("V 1.5.01\n");
} }
int test_basic()
{
InterpreterState state;
init_state(&state);
const char *program[] = {
"LET A = 10",
"LET B = 20",
"PRINT A + B",
"LET A = \"Hello\"",
"LET B = \" World\"",
"PRINT A + B",
"END",
void kernel_main() { };
for (size_t i = 0; i < sizeof(program) / sizeof(program[0]); i++)
{
execute_line(&state, program[i]);
if (!state.running)
break;
}
return 0;
}
void kernel_main()
{
init_keyboard_driver(); init_keyboard_driver();
idt_install(); idt_install();
print_str("[ WARN ] Skipping File System Initialization...\n[ INFO ] Do [ fsinit ] to initalize the filesystem\n"); print_str("[ WARN ] Skipping File System Initialization...\n[ INFO ] Do [ fsinit ] to initalize the filesystem\n");
if (fat12_init() == 0) { if (fat12_init() == 0)
{
printf("Filesystem mounted\n"); printf("Filesystem mounted\n");
fat12_read_root_directory(); fat12_read_root_directory();
fat12_dir_entry_t entry; fat12_dir_entry_t entry;
if (fat12_find_file("HELLOTXT", &entry)) { if (fat12_find_file("HELLOTXT", &entry))
{
printf("File found: HELLO.TXT\n"); printf("File found: HELLO.TXT\n");
} }
} }
clear();
test_basic();
print_setup_prompt(); print_setup_prompt();
print_str(" > "); print_str(" > ");
// Main loop // Main loop
@ -234,40 +275,46 @@ void kernel_main() {
char commandBuffer[COMMAND_BUFFER_SIZE]; char commandBuffer[COMMAND_BUFFER_SIZE];
size_t commandLength = 0; // To track the length of the current command size_t commandLength = 0; // To track the length of the current command
while (1)
while (1) { {
key = read_key(); key = read_key();
if (key != 0) { if (key != 0)
if (!keydown) { {
if (!keydown)
{
CursorPosition pos = get_print_cursor_pos(); CursorPosition pos = get_print_cursor_pos();
move_cursor(pos.x,pos.y); move_cursor(pos.x, pos.y);
if (key == 10) { // Enter key if (key == 10)
{ // Enter key
commandBuffer[commandLength] = '\0'; // Null-terminate the command commandBuffer[commandLength] = '\0'; // Null-terminate the command
commandHandler(commandBuffer); commandHandler(commandBuffer);
// Reset command buffer for the next input // Reset command buffer for the next input
commandLength = 0; commandLength = 0;
print_str(" > "); print_str(" > ");
}
} else if (key == BACKSPACE_KEY) { // Backspace key else if (key == BACKSPACE_KEY)
if (commandLength > 0) { { // Backspace key
if (commandLength > 0)
{
// Remove the last character from the buffer // Remove the last character from the buffer
commandLength--; commandLength--;
commandBuffer[commandLength] = '0'; // Null-terminate after removal commandBuffer[commandLength] = '0'; // Null-terminate after removal
// Clear the character from the screen (overwrite with space) // Clear the character from the screen (overwrite with space)
// Move cursor back one position // Move cursor back one position
offset_print_cursor(-1,0); offset_print_cursor(-1, 0);
print_char(' '); // Overwrite the character print_char(' '); // Overwrite the character
offset_print_cursor(-1,0); // Move cursor back one position(because its moved left one by the rpintf) offset_print_cursor(-1, 0); // Move cursor back one position(because its moved left one by the rpintf)
} }
}
} else { else
if (key >= 32 && key <= 126) { // Check if the key is a printable character {
if (commandLength < COMMAND_BUFFER_SIZE - 1) { if (key >= 32 && key <= 126)
{ // Check if the key is a printable character
if (commandLength < COMMAND_BUFFER_SIZE - 1)
{
commandBuffer[commandLength++] = key; // Append character to buffer commandBuffer[commandLength++] = key; // Append character to buffer
commandBuffer[commandLength] = '\0'; // Null-terminate the buffer commandBuffer[commandLength] = '\0'; // Null-terminate the buffer
print_char(key); // Print key to the screen print_char(key); // Print key to the screen
@ -276,7 +323,9 @@ void kernel_main() {
} }
keydown = true; keydown = true;
} }
} else { }
else
{
keydown = false; keydown = false;
} }
@ -284,5 +333,4 @@ void kernel_main() {
} }
kpanic(2); kpanic(2);
} }

184
src/impl/x86_64/basic.c Normal file
View File

@ -0,0 +1,184 @@
#include "memory.h"
#include "print.h"
#include "strings.h"
#include "stdint.h"
#include "stddef.h"
#include "basic.h"
// Utility: Find or create a variable by name
Variable* get_variable(InterpreterState* state, const char* name) {
for (size_t i = 0; i < state->variable_count; i++) {
if (strcmp(state->variables[i].name, name) == 0) {
return &state->variables[i];
}
}
if (state->variable_count < MAX_VARIABLES) {
Variable* var = &state->variables[state->variable_count++];
strncpy(var->name, name, sizeof(var->name) - 1);
var->name[sizeof(var->name) - 1] = '\0';
var->value = 0;
var->str_value = NULL;
return var;
}
return NULL; // No space for more variables
}
// Parse an integer from a string, skipping leading whitespace
int parse_int(const char* str) {
while (*str == ' ') str++; // Skip leading spaces
int result = 0;
int sign = 1;
if (*str == '-') {
sign = -1;
str++;
}
while (*str >= '0' && *str <= '9') {
result = result * 10 + (*str - '0');
str++;
}
return result * sign;
}
const char* evaluate_expression(InterpreterState* state, const char* expr) {
char buffer[64];
strncpy(buffer, expr, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
char* plus = strrchr(buffer, '+');
if (plus) {
*plus = '\0';
// Evaluate the left and right sides only once
const char* left = evaluate_expression(state, buffer);
const char* right = evaluate_expression(state, plus + 1);
// Debug output
printf("DEBUG: Left operand: %s\n", left);
printf("DEBUG: Right operand: %s\n", right);
// Check if both sides are numeric
int left_is_number = (left[0] >= '0' && left[0] <= '9') || (left[0] == '-' && left[1] >= '0' && left[1] <= '9');
int right_is_number = (right[0] >= '0' && right[0] <= '9') || (right[0] == '-' && right[1] >= '0' && right[1] <= '9');
static char result[128];
if (left_is_number && right_is_number) {
// Parse the left and right operands
int left_value = parse_int(left);
int right_value = parse_int(right);
// Correct addition logic
int sum = left_value + right_value;
// Debug addition
printf("DEBUG: Adding %d + %d = %d\n", left_value, right_value, sum);
// Format the result as a string
snprintf(result, sizeof(result), "%d", sum);
} else {
// Concatenate strings
snprintf(result, sizeof(result), "%s%s", left, right);
// Debug string concatenation
printf("DEBUG: Concatenating strings: %s + %s = %s\n", left, right, result);
}
return result;
}
// Trim leading and trailing spaces
const char* start = buffer;
while (*start == ' ') start++;
char* end = buffer + strlen(buffer) - 1;
while (end > start && *end == ' ') *end-- = '\0';
if (start[0] >= 'A' && start[0] <= 'Z') {
Variable* var = get_variable(state, start);
if (var) {
static char var_result[64];
if (var->str_value) {
strncpy(var_result, var->str_value, sizeof(var_result) - 1);
var_result[sizeof(var_result) - 1] = '\0';
return var_result;
} else {
snprintf(var_result, sizeof(var_result), "%d", var->value);
return var_result;
}
}
}
if (start[0] == '"') {
// String literal
size_t len = strlen(start);
if (start[len - 1] == '"') {
static char str_result[64];
strncpy(str_result, start + 1, len - 2);
str_result[len - 2] = '\0';
return str_result;
}
}
static char int_result[16];
snprintf(int_result, sizeof(int_result), "%d", parse_int(start));
return int_result;
}
// Interpret a single line of code
void interpret_line(InterpreterState* state, const char* line) {
if (strncmp(line, "LET", 3) == 0) {
const char* rest = line + 3;
while (*rest == ' ') rest++;
const char* equals = strchr(rest, '=');
if (!equals) return;
char var_name[16];
strncpy(var_name, rest, equals - rest);
var_name[equals - rest] = '\0';
// Trim trailing spaces from var_name
size_t len = strlen(var_name);
while (len > 0 && var_name[len - 1] == ' ') {
var_name[--len] = '\0';
}
Variable* var = get_variable(state, var_name);
if (var) {
const char* value = evaluate_expression(state, equals + 1);
if (value[0] >= '0' && value[0] <= '9') {
var->value = parse_int(value);
var->str_value = NULL;
} else {
var->str_value = malloc(strlen(value) + 1);
strcpy(var->str_value, value);
}
}
} else if (strncmp(line, "PRINT", 5) == 0) {
const char* rest = line + 5;
while (*rest == ' ') rest++;
const char* value = evaluate_expression(state, rest);
printf("%s\n", value);
} else if (strncmp(line, "END", 3) == 0) {
printf("Program terminated.\n");
state->running = 0;
}
}
// Initialize interpreter state
void init_state(InterpreterState* state) {
state->variable_count = 0;
state->running = 1;
}
// Execute a single line in the context of a state
void execute_line(InterpreterState* state, const char* line) {
printf("Executing line: %s\n", line); // Debugging
interpret_line(state, line);
}

View File

@ -334,6 +334,48 @@ int my_sscanf(const char *input, const char *format, char *output) {
return match_count; return match_count;
} }
snprintf(char* buffer, size_t size, const char* format, ...) {
va_list args;
va_start(args, format);
const char* traverse = format;
size_t written = 0;
while (*traverse && written < size - 1) {
if (*traverse == '%' && *(traverse + 1)) {
traverse++;
if (*traverse == 's') {
const char* str = va_arg(args, const char*);
while (*str && written < size - 1) {
buffer[written++] = *str++;
}
} else if (*traverse == 'd') {
int num = va_arg(args, int);
char num_buffer[16];
int num_len = 0;
if (num < 0) {
if (written < size - 1) buffer[written++] = '-';
num = -num;
}
do {
num_buffer[num_len++] = '0' + (num % 10);
num /= 10;
} while (num > 0);
while (num_len > 0 && written < size - 1) {
buffer[written++] = num_buffer[--num_len];
}
}
} else {
buffer[written++] = *traverse;
}
traverse++;
}
buffer[written] = '\0';
va_end(args);
return written;
}
void printf(const char* format, ...) { void printf(const char* format, ...) {
va_list args; va_list args;

View File

@ -90,3 +90,13 @@ int strncmp(const char *s1, const char *s2, size_t n) {
return (*(unsigned char *)s1 - *(unsigned char *)s2); return (*(unsigned char *)s1 - *(unsigned char *)s2);
} }
} }
char* strchr(const char* str, int ch) {
while (*str) {
if (*str == (char)ch) {
return (char*)str;
}
str++;
}
return NULL;
}

32
src/intf/basic.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef BASIC_INTERPRETER_H
#define BASIC_INTERPRETER_H
#include "stdint.h"
#include "stddef.h"
#define MAX_LINE_LENGTH 128
#define MAX_VARIABLES 32
typedef struct {
char name[16];
int value;
char* str_value;
} Variable;
typedef struct {
Variable variables[MAX_VARIABLES];
size_t variable_count;
int running;
} InterpreterState;
// Initialize the interpreter state
void init_state(InterpreterState* state);
// Execute a single line of code in the context of a state
void execute_line(InterpreterState* state, const char* line);
// Utility to evaluate an expression (exposed for potential reuse)
const char* evaluate_expression(InterpreterState* state, const char* expr);
#endif // BASIC_INTERPRETER_H

View File

@ -29,6 +29,7 @@ enum {
}; };
void sscanf(const char *str, const char *format, char *filename, char *content); void sscanf(const char *str, const char *format, char *filename, char *content);
snprintf(char* buffer, size_t size, const char* format, ...);
int my_sscanf(const char *input, const char *format, char *output); int my_sscanf(const char *input, const char *format, char *output);
void print_clear(); void print_clear();
void print_char(char character); void print_char(char character);

View File

@ -5,8 +5,9 @@
int strcmp(const char *str1, const char *str2); int strcmp(const char *str1, const char *str2);
size_t strlen(const char *str); size_t strlen(const char *str);
char *strncpy(char *dest, const char *src, size_t n); char *strncpy(char *dest, const char *src, size_t n);
int int_strncmp(const char* s1, const char* s2, size_t n); int int_strncmp(const char *s1, const char *s2, size_t n);
void strcpy(char *dest, const char *src); void strcpy(char *dest, const char *src);
char* strrchr(const char* str, char ch); char *strrchr(const char *str, char ch);
int strncmp(const char *s1, const char *s2, size_t n); int strncmp(const char *s1, const char *s2, size_t n);
char *strchr(const char *str, int ch);

Binary file not shown.