diff --git a/iso/boot/kernel.elf b/iso/boot/kernel.elf index 8f6b396..7b70d9e 100755 Binary files a/iso/boot/kernel.elf and b/iso/boot/kernel.elf differ diff --git a/src/kernel/kmain.c b/src/kernel/kmain.c index 6028000..2483599 100644 --- a/src/kernel/kmain.c +++ b/src/kernel/kmain.c @@ -39,7 +39,6 @@ int kmain(int retvalue) timer_install(); keyboard_install(); - shell_install(); return retvalue; diff --git a/src/kernel/shell.c b/src/kernel/shell.c index 34831cb..6e1872e 100644 --- a/src/kernel/shell.c +++ b/src/kernel/shell.c @@ -21,7 +21,7 @@ void shell_install() } else if (strcmp(input_buffer, "help") == 0) { - printf("help\tpanic\twords\tprimes\trainbow\tclear\n"); + printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\n"); } else if (strcmp(input_buffer, "panic") == 0) { @@ -43,6 +43,10 @@ void shell_install() { program_clear(); } + else if (strcmp(input_buffer, "math") == 0) + { + program_math(); + } else { printf("Unknown command %s\n", input_buffer); } diff --git a/src/libc/ctype.c b/src/libc/ctype.c new file mode 100644 index 0000000..49e4545 --- /dev/null +++ b/src/libc/ctype.c @@ -0,0 +1,13 @@ + +#include "stdint.h" + +bool isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + + +bool isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} diff --git a/src/libc/ctype.h b/src/libc/ctype.h new file mode 100644 index 0000000..10ace98 --- /dev/null +++ b/src/libc/ctype.h @@ -0,0 +1,9 @@ +#ifndef CTYPE_H +#define CTYPE_H + +#include "stdint.h" + +bool isdigit(char c); +bool isspace(char c); + +#endif diff --git a/src/libc/stdio.c b/src/libc/stdio.c index c356875..70a8555 100644 --- a/src/libc/stdio.c +++ b/src/libc/stdio.c @@ -176,6 +176,50 @@ void colorputs(const char* str, unsigned int color) } } +// double to string for printf +void dtostrf(double val, char *buffer, int precision) +{ + int whole_part = (int)val; + double fractional_part = val - whole_part; + if (fractional_part < 0) fractional_part = -fractional_part; + + char *start = buffer; + if (whole_part == 0) + { + *buffer++ = '0'; + } + else + { + if (whole_part < 0) + { + *buffer++ = '-'; + whole_part = -whole_part; + } + char temp[32]; + int pos = 0; + + while (whole_part > 0) + { + temp[pos++] = '0' + (whole_part % 10); + whole_part /= 10; + } + while (pos > 0) + { + *buffer++ = temp[--pos]; + } + } + + *buffer++ = '.'; + for (int i = 0; i < precision; i++) + { + fractional_part *= 10; + int digit = (int)fractional_part; + *buffer++ = '0' + digit; + fractional_part -= digit; + } + *buffer = '\0'; +} + void printf(const char* fmt, ...) { int* argp = (int*) &fmt; @@ -188,52 +232,52 @@ void printf(const char* fmt, ...) while (*fmt) { switch(state) { - case PRINTF_STATE_START: - if (*fmt == '%') - { - state = PRINTF_STATE_LENGTH; - } - else { - putc(*fmt); - } - break; - case PRINTF_STATE_LENGTH: - if (*fmt == 'h') - { - length = PRINTF_LENGTH_SHORT; - state = PRINTF_STATE_SHORT; - } - else if (*fmt == 'l') - { - length = PRINTF_LENGTH_LONG; - state = PRINTF_STATE_LONG; - } - else { - goto PRINTF_STATE_SPEC_; - } - break; - case PRINTF_STATE_SHORT: - if (*fmt == 'h') - { - length = PRINTF_LENGTH_SHORT_SHORT; - state = PRINTF_STATE_SPEC; - } - else { - goto PRINTF_STATE_SPEC_; - } - break; - case PRINTF_STATE_LONG: - if (*fmt == 'l') - { - length = PRINTF_LENGTH_LONG_LONG; - state = PRINTF_STATE_SPEC; - } - else { - goto PRINTF_STATE_SPEC_; - } - break; - case PRINTF_STATE_SPEC: - PRINTF_STATE_SPEC_: + case PRINTF_STATE_START: + if (*fmt == '%') + { + state = PRINTF_STATE_LENGTH; + } + else { + putc(*fmt); + } + break; + case PRINTF_STATE_LENGTH: + if (*fmt == 'h') + { + length = PRINTF_LENGTH_SHORT; + state = PRINTF_STATE_SHORT; + } + else if (*fmt == 'l') + { + length = PRINTF_LENGTH_LONG; + state = PRINTF_STATE_LONG; + } + else { + goto PRINTF_STATE_SPEC_; + } + break; + case PRINTF_STATE_SHORT: + if (*fmt == 'h') + { + length = PRINTF_LENGTH_SHORT_SHORT; + state = PRINTF_STATE_SPEC; + } + else { + goto PRINTF_STATE_SPEC_; + } + break; + case PRINTF_STATE_LONG: + if (*fmt == 'l') + { + length = PRINTF_LENGTH_LONG_LONG; + state = PRINTF_STATE_SPEC; + } + else { + goto PRINTF_STATE_SPEC_; + } + break; + case PRINTF_STATE_SPEC: + PRINTF_STATE_SPEC_: switch(*fmt) { case 'c': @@ -270,14 +314,24 @@ void printf(const char* fmt, ...) sign = false; argp = printf_number(argp, length, sign, radix); break; + case 'f': { + // Handle floating-point numbers + double* dargp = (double*)argp; + double d = *(double*)dargp; + char buffer[64]; + dtostrf(d, buffer, 6); // Default precision: 6 + puts(buffer); + argp += 2; // Incrementing by 2 to move past the double argument + break; + } default: break; } - state = PRINTF_STATE_START; - length = PRINTF_LENGTH_START; - radix = 10; - sign = false; - break; + state = PRINTF_STATE_START; + length = PRINTF_LENGTH_START; + radix = 10; + sign = false; + break; } fmt++; } diff --git a/src/programs/math.c b/src/programs/math.c new file mode 100644 index 0000000..70d20c1 --- /dev/null +++ b/src/programs/math.c @@ -0,0 +1,260 @@ +// Math expression lexer and parser + +#include "../libc/stdint.h" +#include "../kernel/system.h" +#include "../libc/stdio.h" +#include "../libc/ctype.h" + +#define BUFFER_SIZE 256 + +typedef enum +{ + TOKEN_NUMBER, + TOKEN_PLUS, + TOKEN_MINUS, + TOKEN_MULTIPLY, + TOKEN_DIVIDE, + TOKEN_LPAREN, + TOKEN_RPAREN, + TOKEN_END +} TokenType; + +typedef struct +{ + TokenType type; + double value; +} Token; + +typedef struct +{ + const char *text; + size_t pos; + Token current_token; +} Lexer; + +void lexer_init(Lexer *lexer, const char *text) +{ + lexer->text = text; + lexer->pos = 0; + lexer->current_token.type = TOKEN_END; + lexer->current_token.value = 0; +} + +void lexer_advance(Lexer *lexer) +{ + lexer->pos++; +} + +char lexer_peek(const Lexer *lexer) +{ + return lexer->text[lexer->pos]; +} + +bool lexer_is_at_end(const Lexer *lexer) +{ + return lexer->text[lexer->pos] == '\0'; +} + +Token lexer_get_next_token(Lexer *lexer) +{ + while (!lexer_is_at_end(lexer)) + { + char current_char = lexer_peek(lexer); + + if (isspace(current_char)) { + lexer_advance(lexer); + continue; + } + + if (isdigit(current_char)) { + double value = 0; + while (isdigit(current_char)) + { + value = value * 10 + (current_char - '0'); + lexer_advance(lexer); + current_char = lexer_peek(lexer); + } + if (current_char == '.') + { + lexer_advance(lexer); + double decimal_place = 0.1; + while (isdigit(lexer_peek(lexer))) + { + value += decimal_place * (lexer_peek(lexer)-'0'); + decimal_place *= 0.1; + lexer_advance(lexer); + } + } + lexer->current_token.type = TOKEN_NUMBER; + lexer->current_token.value = value; + //printf("NUMBER %f\n", value); + return lexer->current_token; + } + + if (current_char == '+') + { + lexer_advance(lexer); + lexer->current_token.type = TOKEN_PLUS; + printf("PLUS\n"); + return lexer->current_token; + } + + if (current_char == '-') + { + lexer_advance(lexer); + lexer->current_token.type = TOKEN_MINUS; + printf("MINUS\n"); + return lexer->current_token; + } + + if (current_char == '*') + { + lexer_advance(lexer); + lexer->current_token.type = TOKEN_MULTIPLY; + printf("MULTIPLY\n"); + return lexer->current_token; + } + + if (current_char == '/') + { + lexer_advance(lexer); + lexer->current_token.type = TOKEN_DIVIDE; + printf("DIVIDE\n"); + return lexer->current_token; + } + + if (current_char == '(') + { + lexer_advance(lexer); + lexer->current_token.type = TOKEN_LPAREN; + printf("LPAREN\n"); + return lexer->current_token; + } + + if (current_char == ')') + { + lexer_advance(lexer); + lexer->current_token.type = TOKEN_RPAREN; + printf("RPAREN\n"); + return lexer->current_token; + } + + printf("Unknown character %c\n", current_char); + //shell_install(); + } + + lexer->current_token.type = TOKEN_END; + printf("END\n"); + return lexer->current_token; +} + +typedef struct +{ + Lexer lexer; + Token current_token; +} Parser; + +void parser_init(Parser *parser, const char *text) +{ + lexer_init(&parser->lexer, text); + parser->current_token = lexer_get_next_token(&parser->lexer); +} + +void parser_eat(Parser *parser, TokenType type) +{ + if (parser->current_token.type == type) + { + parser->current_token = lexer_get_next_token(&parser->lexer); + } else { + printf("Unexpected token %d\n", parser->current_token.type); + //shell_install(); + } +} + +double parser_factor(Parser *parser); +double parser_term(Parser *parser); +double parser_expression(Parser *parser); + +double parser_factor(Parser *parser) +{ + Token token = parser->current_token; + if (token.type == TOKEN_NUMBER) + { + parser_eat(parser, TOKEN_NUMBER); + //printf("Factor: %f\n", token.value); + return token.value; + } else if (token.type == TOKEN_LPAREN) { + parser_eat(parser, TOKEN_LPAREN); + double result = parser_expression(parser); + parser_eat(parser, TOKEN_RPAREN); + //printf("Factor (expression): %f\n", result); + return result; + } else { + printf("Unexpected token in factor %d\n", token.type); + //shell_install(); + } + return -1; +} + +double parser_term(Parser *parser) +{ + double result = parser_factor(parser); + //printf("Initial term: %f\n", result); + + while (parser->current_token.type == TOKEN_MULTIPLY || parser->current_token.type == TOKEN_DIVIDE) + { + Token token = parser->current_token; + if (token.type == TOKEN_MULTIPLY) + { + parser_eat(parser, TOKEN_MULTIPLY); + result *= parser_factor(parser); + //printf("Term after multiply: %f\n", result); + } else if (token.type == TOKEN_DIVIDE) { + parser_eat(parser, TOKEN_DIVIDE); + result /= parser_factor(parser); + //printf("Term after divide: %f\n", result); + } + } + return result; +} + +double parser_expression(Parser *parser) +{ + double result = parser_term(parser); + //printf("Initial expression: %f\n", result); + + while (parser->current_token.type == TOKEN_PLUS || parser->current_token.type == TOKEN_MINUS) + { + Token token = parser->current_token; + if (token.type == TOKEN_PLUS) + { + parser_eat(parser, TOKEN_PLUS); + result += parser_term(parser); + //printf("Expression after plus: %f\n", result); + } else if (token.type == TOKEN_MINUS) { + parser_eat(parser, TOKEN_MINUS); + result -= parser_term(parser); + //printf("Expression after minus: %f\n", result); + } + } + return result; +} + +double parse(const char* text) +{ + Parser parser; + parser_init(&parser, text); + double result = parser_expression(&parser); + //printf("Final result: %f\n", result); + return result; +} + +void program_math() +{ + char input_buffer[BUFFER_SIZE]; + puts("Expression? "); + get_input(input_buffer, BUFFER_SIZE); + printf("Input: %s\n", input_buffer); + double result = parse(input_buffer); + printf("\n%f\n", result); +} diff --git a/src/programs/programs.h b/src/programs/programs.h index 8f8ca31..0c57177 100644 --- a/src/programs/programs.h +++ b/src/programs/programs.h @@ -3,6 +3,7 @@ void program_words(); void program_primes(); +void program_math(); // Misc void program_rainbow();