mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 02:16:58 +00:00
CLI apps transfer to Userspace
This commit is contained in:
@@ -5,29 +5,36 @@ LD = x86_64-elf-ld
|
||||
CFLAGS = -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc
|
||||
LDFLAGS = -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start
|
||||
|
||||
BIN_DIR = bin
|
||||
|
||||
LIBC_SOURCES = $(wildcard libc/*.c)
|
||||
LIBC_OBJS = $(LIBC_SOURCES:.c=.o) crt0.o
|
||||
LIBC_OBJS = $(patsubst libc/%.c, $(BIN_DIR)/%.o, $(LIBC_SOURCES)) $(BIN_DIR)/crt0.o
|
||||
|
||||
APP_SOURCES = $(filter-out nanojpeg.c, $(wildcard *.c))
|
||||
APP_OBJS = $(APP_SOURCES:.c=.o)
|
||||
APP_ELFS = $(APP_SOURCES:.c=.elf)
|
||||
APP_ELFS = $(patsubst %.c, $(BIN_DIR)/%.elf, $(APP_SOURCES))
|
||||
|
||||
all: $(APP_ELFS)
|
||||
all: $(BIN_DIR) $(APP_ELFS)
|
||||
|
||||
crt0.o: crt0.asm
|
||||
$(BIN_DIR):
|
||||
mkdir -p $(BIN_DIR)
|
||||
|
||||
$(BIN_DIR)/crt0.o: crt0.asm
|
||||
$(AS) -f elf64 $< -o $@
|
||||
|
||||
libc/%.o: libc/%.c
|
||||
$(BIN_DIR)/%.o: libc/%.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
%.o: %.c
|
||||
$(BIN_DIR)/nanojpeg.o: nanojpeg.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
viewer.elf: $(LIBC_OBJS) viewer.o nanojpeg.o
|
||||
$(BIN_DIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BIN_DIR)/viewer.elf: $(LIBC_OBJS) $(BIN_DIR)/viewer.o $(BIN_DIR)/nanojpeg.o
|
||||
$(LD) $(LDFLAGS) $^ -o $@
|
||||
|
||||
%.elf: $(LIBC_OBJS) %.o
|
||||
$(BIN_DIR)/%.elf: $(LIBC_OBJS) $(BIN_DIR)/%.o
|
||||
$(LD) $(LDFLAGS) $^ -o $@
|
||||
|
||||
clean:
|
||||
rm -f *.o libc/*.o *.elf
|
||||
rm -rf $(BIN_DIR)
|
||||
|
||||
9
src/kernel/userland/beep.c
Normal file
9
src/kernel/userland/beep.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
printf("BEEP!\n");
|
||||
sys_system(14, 1000, 100, 0, 0); // SYSTEM_CMD_BEEP (freq, ms)
|
||||
return 0;
|
||||
}
|
||||
9
src/kernel/userland/boredver.c
Normal file
9
src/kernel/userland/boredver.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
printf("BoredOS v1.64\n");
|
||||
printf("BoredOS Kernel V3.0.0\n");
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
24
src/kernel/userland/cat.c
Normal file
24
src/kernel/userland/cat.c
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: cat <filename>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fd = sys_open(argv[1], "r");
|
||||
if (fd < 0) {
|
||||
printf("Error: Cannot open %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buffer[4096];
|
||||
int bytes;
|
||||
while ((bytes = sys_read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
sys_write(1, buffer, bytes);
|
||||
}
|
||||
|
||||
sys_close(fd);
|
||||
return 0;
|
||||
}
|
||||
519
src/kernel/userland/cc.c
Normal file
519
src/kernel/userland/cc.c
Normal file
@@ -0,0 +1,519 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
#include "../vm.h"
|
||||
|
||||
// --- Compiler Limits ---
|
||||
#define MAX_SOURCE 65536
|
||||
#define MAX_TOKENS 16384
|
||||
#define MAX_VARS 512
|
||||
#define CODE_SIZE 32768
|
||||
#define STR_POOL_SIZE 16384
|
||||
|
||||
static int compile_error = 0;
|
||||
|
||||
// --- Lexer ---
|
||||
typedef enum {
|
||||
TOK_EOF,
|
||||
TOK_INT, // 123, 0xFF
|
||||
TOK_STRING, // "hello"
|
||||
TOK_ID, // abc
|
||||
TOK_PLUS, // +
|
||||
TOK_MINUS, // -
|
||||
TOK_MUL, // *
|
||||
TOK_DIV, // /
|
||||
TOK_ASSIGN, // =
|
||||
TOK_LPAREN, // (
|
||||
TOK_RPAREN, // )
|
||||
TOK_LBRACKET, // [
|
||||
TOK_RBRACKET, // ]
|
||||
TOK_LBRACE, // {
|
||||
TOK_RBRACE, // }
|
||||
TOK_SEMI, // ;
|
||||
TOK_COMMA, // ,
|
||||
TOK_EQ, // ==
|
||||
TOK_NEQ, // !=
|
||||
TOK_LT, // <
|
||||
TOK_GT, // >
|
||||
TOK_LE, // <=
|
||||
TOK_GE, // >=
|
||||
TOK_IF, // if
|
||||
TOK_ELSE, // else
|
||||
TOK_WHILE, // while
|
||||
TOK_INT_TYPE, // int
|
||||
TOK_CHAR_TYPE,// char
|
||||
TOK_VOID_TYPE,// void
|
||||
TOK_MAIN // main
|
||||
} TokenType;
|
||||
|
||||
typedef struct {
|
||||
TokenType type;
|
||||
int int_val;
|
||||
char str_val[64]; // Identifier or String Content
|
||||
} Token;
|
||||
|
||||
static char *source_ptr;
|
||||
static Token tokens[MAX_TOKENS];
|
||||
static int token_count = 0;
|
||||
|
||||
static void lex_error(const char *msg) {
|
||||
printf("Compiler Error: %s\n", msg);
|
||||
compile_error = 1;
|
||||
}
|
||||
|
||||
static void lexer(const char *source) {
|
||||
source_ptr = (char*)source;
|
||||
token_count = 0;
|
||||
compile_error = 0;
|
||||
|
||||
while (*source_ptr) {
|
||||
while (*source_ptr == ' ' || *source_ptr == '\n' || *source_ptr == '\t' || *source_ptr == '\r') source_ptr++;
|
||||
if (!*source_ptr) break;
|
||||
|
||||
if (*source_ptr == '/' && *(source_ptr+1) == '/') {
|
||||
while (*source_ptr && *source_ptr != '\n') source_ptr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Token *t = &tokens[token_count++];
|
||||
|
||||
if (*source_ptr == '0' && (*(source_ptr+1) == 'x' || *(source_ptr+1) == 'X')) {
|
||||
source_ptr += 2;
|
||||
t->type = TOK_INT;
|
||||
t->int_val = 0;
|
||||
int has_digits = 0;
|
||||
while ((*source_ptr >= '0' && *source_ptr <= '9') ||
|
||||
(*source_ptr >= 'a' && *source_ptr <= 'f') ||
|
||||
(*source_ptr >= 'A' && *source_ptr <= 'F')) {
|
||||
int digit = 0;
|
||||
if (*source_ptr >= '0' && *source_ptr <= '9') digit = *source_ptr - '0';
|
||||
else if (*source_ptr >= 'a' && *source_ptr <= 'f') digit = *source_ptr - 'a' + 10;
|
||||
else if (*source_ptr >= 'A' && *source_ptr <= 'F') digit = *source_ptr - 'A' + 10;
|
||||
t->int_val = (t->int_val << 4) | digit;
|
||||
source_ptr++;
|
||||
has_digits = 1;
|
||||
}
|
||||
if (!has_digits) { lex_error("Invalid hex literal"); return; }
|
||||
} else if (*source_ptr >= '0' && *source_ptr <= '9') {
|
||||
t->type = TOK_INT;
|
||||
t->int_val = 0;
|
||||
while (*source_ptr >= '0' && *source_ptr <= '9') {
|
||||
t->int_val = t->int_val * 10 + (*source_ptr - '0');
|
||||
source_ptr++;
|
||||
}
|
||||
} else if (*source_ptr == '"') {
|
||||
t->type = TOK_STRING;
|
||||
source_ptr++;
|
||||
int len = 0;
|
||||
while (*source_ptr && *source_ptr != '"') {
|
||||
if (*source_ptr == '\\' && *(source_ptr+1) == 'n') {
|
||||
if (len < 63) t->str_val[len++] = '\n';
|
||||
source_ptr += 2;
|
||||
} else {
|
||||
if (len < 63) t->str_val[len++] = *source_ptr;
|
||||
source_ptr++;
|
||||
}
|
||||
}
|
||||
t->str_val[len] = 0;
|
||||
if (*source_ptr == '"') source_ptr++;
|
||||
} else if (*source_ptr == '\'') {
|
||||
t->type = TOK_INT;
|
||||
source_ptr++;
|
||||
char c = 0;
|
||||
if (*source_ptr == '\\') {
|
||||
source_ptr++;
|
||||
if (*source_ptr == 'n') c = '\n';
|
||||
else if (*source_ptr == 't') c = '\t';
|
||||
else if (*source_ptr == '0') c = '\0';
|
||||
else if (*source_ptr == '\\') c = '\\';
|
||||
else if (*source_ptr == '\'') c = '\'';
|
||||
else c = *source_ptr;
|
||||
source_ptr++;
|
||||
} else {
|
||||
c = *source_ptr;
|
||||
source_ptr++;
|
||||
}
|
||||
if (*source_ptr == '\'') source_ptr++;
|
||||
else { lex_error("Expected closing '"); return; }
|
||||
t->int_val = (int)c;
|
||||
} else if ((*source_ptr >= 'a' && *source_ptr <= 'z') || (*source_ptr >= 'A' && *source_ptr <= 'Z') || *source_ptr == '_') {
|
||||
int len = 0;
|
||||
while ((*source_ptr >= 'a' && *source_ptr <= 'z') || (*source_ptr >= 'A' && *source_ptr <= 'Z') || (*source_ptr >= '0' && *source_ptr <= '9') || *source_ptr == '_') {
|
||||
if (len < 63) t->str_val[len++] = *source_ptr;
|
||||
source_ptr++;
|
||||
}
|
||||
t->str_val[len] = 0;
|
||||
if (strcmp(t->str_val, "if") == 0) t->type = TOK_IF;
|
||||
else if (strcmp(t->str_val, "else") == 0) t->type = TOK_ELSE;
|
||||
else if (strcmp(t->str_val, "while") == 0) t->type = TOK_WHILE;
|
||||
else if (strcmp(t->str_val, "int") == 0) t->type = TOK_INT_TYPE;
|
||||
else if (strcmp(t->str_val, "char") == 0) t->type = TOK_CHAR_TYPE;
|
||||
else if (strcmp(t->str_val, "void") == 0) t->type = TOK_VOID_TYPE;
|
||||
else if (strcmp(t->str_val, "main") == 0) t->type = TOK_MAIN;
|
||||
else t->type = TOK_ID;
|
||||
} else {
|
||||
switch (*source_ptr) {
|
||||
case '+': t->type = TOK_PLUS; break;
|
||||
case '-': t->type = TOK_MINUS; break;
|
||||
case '*': t->type = TOK_MUL; break;
|
||||
case '/': t->type = TOK_DIV; break;
|
||||
case '(': t->type = TOK_LPAREN; break;
|
||||
case ')': t->type = TOK_RPAREN; break;
|
||||
case '[': t->type = TOK_LBRACKET; break;
|
||||
case ']': t->type = TOK_RBRACKET; break;
|
||||
case '{': t->type = TOK_LBRACE; break;
|
||||
case '}': t->type = TOK_RBRACE; break;
|
||||
case ';': t->type = TOK_SEMI; break;
|
||||
case ',': t->type = TOK_COMMA; break;
|
||||
case '=':
|
||||
if (*(source_ptr+1) == '=') { t->type = TOK_EQ; source_ptr++; }
|
||||
else t->type = TOK_ASSIGN;
|
||||
break;
|
||||
case '!':
|
||||
if (*(source_ptr+1) == '=') { t->type = TOK_NEQ; source_ptr++; }
|
||||
else { lex_error("Unexpected !"); return; }
|
||||
break;
|
||||
case '<':
|
||||
if (*(source_ptr+1) == '=') { t->type = TOK_LE; source_ptr++; }
|
||||
else t->type = TOK_LT;
|
||||
break;
|
||||
case '>':
|
||||
if (*(source_ptr+1) == '=') { t->type = TOK_GE; source_ptr++; }
|
||||
else t->type = TOK_GT;
|
||||
break;
|
||||
default: lex_error("Unknown char"); return;
|
||||
}
|
||||
source_ptr++;
|
||||
}
|
||||
}
|
||||
tokens[token_count].type = TOK_EOF;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int syscall_id;
|
||||
} Builtin;
|
||||
|
||||
static const Builtin builtins[] = {
|
||||
{"exit", VM_SYS_EXIT},
|
||||
{"print_int", VM_SYS_PRINT_INT},
|
||||
{"print_char", VM_SYS_PRINT_CHAR},
|
||||
{"print_str", VM_SYS_PRINT_STR},
|
||||
{"print", VM_SYS_PRINT_INT},
|
||||
{"pritc", VM_SYS_PRINT_CHAR},
|
||||
{"puts", VM_SYS_PRINT_STR},
|
||||
{"nl", VM_SYS_NL},
|
||||
{"cls", VM_SYS_CLS},
|
||||
{"getchar", VM_SYS_GETCHAR},
|
||||
{"strlen", VM_SYS_STRLEN},
|
||||
{"strcmp", VM_SYS_STRCMP},
|
||||
{"strcpy", VM_SYS_STRCPY},
|
||||
{"strcat", VM_SYS_STRCAT},
|
||||
{"memset", VM_SYS_MEMSET},
|
||||
{"memcpy", VM_SYS_MEMCPY},
|
||||
{"malloc", VM_SYS_MALLOC},
|
||||
{"free", VM_SYS_FREE},
|
||||
{"rand", VM_SYS_RAND},
|
||||
{"srand", VM_SYS_SRAND},
|
||||
{"abs", VM_SYS_ABS},
|
||||
{"min", VM_SYS_MIN},
|
||||
{"max", VM_SYS_MAX},
|
||||
{"pow", VM_SYS_POW},
|
||||
{"sqrt", VM_SYS_SQRT},
|
||||
{"sleep", VM_SYS_SLEEP},
|
||||
{"fopen", VM_SYS_FOPEN},
|
||||
{"fclose", VM_SYS_FCLOSE},
|
||||
{"fread", VM_SYS_FREAD},
|
||||
{"fwrite", VM_SYS_FWRITE},
|
||||
{"fseek", VM_SYS_FSEEK},
|
||||
{"remove", VM_SYS_REMOVE},
|
||||
{"draw_pixel", VM_SYS_DRAW_PIXEL},
|
||||
{"draw_rect", VM_SYS_DRAW_RECT},
|
||||
{"draw_line", VM_SYS_DRAW_LINE},
|
||||
{"draw_text", VM_SYS_DRAW_TEXT},
|
||||
{"get_width", VM_SYS_GET_WIDTH},
|
||||
{"get_height", VM_SYS_GET_HEIGHT},
|
||||
{"get_time", VM_SYS_GET_TIME},
|
||||
{"kb_hit", VM_SYS_KB_HIT},
|
||||
{"mouse_x", VM_SYS_MOUSE_X},
|
||||
{"mouse_y", VM_SYS_MOUSE_Y},
|
||||
{"mouse_state", VM_SYS_MOUSE_STATE},
|
||||
{"play_sound", VM_SYS_PLAY_SOUND},
|
||||
{"atoi", VM_SYS_ATOI},
|
||||
{"itoa", VM_SYS_ITOA},
|
||||
{"peek", VM_SYS_PEEK},
|
||||
{"poke", VM_SYS_POKE},
|
||||
{"exec", VM_SYS_EXEC},
|
||||
{"system", VM_SYS_SYSTEM},
|
||||
{"strchr", VM_SYS_STRCHR},
|
||||
{"memcmp", VM_SYS_MEMCMP},
|
||||
{"isalnum", VM_SYS_ISALNUM},
|
||||
{"isalpha", VM_SYS_ISALPHA},
|
||||
{"isdigit", VM_SYS_ISDIGIT},
|
||||
{"tolower", VM_SYS_TOLOWER},
|
||||
{"toupper", VM_SYS_TOUPPER},
|
||||
{"strncpy", VM_SYS_STRNCPY},
|
||||
{"strncat", VM_SYS_STRNCAT},
|
||||
{"strncmp", VM_SYS_STRNCMP},
|
||||
{"strstr", VM_SYS_STRSTR},
|
||||
{"strrchr", VM_SYS_STRRCHR},
|
||||
{"memmove", VM_SYS_MEMMOVE},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
static int find_builtin(const char *name) {
|
||||
for (int i = 0; builtins[i].name != NULL; i++) {
|
||||
if (strcmp(builtins[i].name, name) == 0) return builtins[i].syscall_id;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint8_t code[CODE_SIZE];
|
||||
static int code_pos = 0;
|
||||
static int cur_token = 0;
|
||||
static uint8_t str_pool[STR_POOL_SIZE];
|
||||
static int str_pool_pos = 0;
|
||||
|
||||
typedef struct {
|
||||
char name[32];
|
||||
int addr;
|
||||
} Symbol;
|
||||
|
||||
static Symbol symbols[MAX_VARS];
|
||||
static int symbol_count = 0;
|
||||
static int next_var_addr = 32768;
|
||||
|
||||
static int find_symbol(const char *name) {
|
||||
for (int i = 0; i < symbol_count; i++) {
|
||||
if (strcmp(symbols[i].name, name) == 0) return symbols[i].addr;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int add_symbol(const char *name) {
|
||||
int existing = find_symbol(name);
|
||||
if (existing != -1) return existing;
|
||||
if (symbol_count >= MAX_VARS) return -1;
|
||||
strcpy(symbols[symbol_count].name, name);
|
||||
symbols[symbol_count].addr = next_var_addr;
|
||||
next_var_addr += 4;
|
||||
return symbol_count++;
|
||||
}
|
||||
|
||||
static void emit(uint8_t b) {
|
||||
if (code_pos < CODE_SIZE) code[code_pos++] = b;
|
||||
else { printf("Error: Code buffer overflow\n"); compile_error = 1; }
|
||||
}
|
||||
|
||||
static void emit32(int v) {
|
||||
emit(v & 0xFF); emit((v >> 8) & 0xFF); emit((v >> 16) & 0xFF); emit((v >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
static int add_string(const char *str) {
|
||||
int start = str_pool_pos;
|
||||
int len = strlen(str);
|
||||
if (str_pool_pos + len + 1 >= STR_POOL_SIZE) { printf("Error: String pool overflow\n"); compile_error = 1; return 0; }
|
||||
for(int i=0; i<len; i++) str_pool[str_pool_pos++] = str[i];
|
||||
str_pool[str_pool_pos++] = 0;
|
||||
return start;
|
||||
}
|
||||
|
||||
static void match(TokenType t) {
|
||||
if (compile_error) return;
|
||||
if (tokens[cur_token].type == t) cur_token++;
|
||||
else { printf("Syntax Error: Expected token %d got %d\n", t, tokens[cur_token].type); compile_error = 1; }
|
||||
}
|
||||
|
||||
static void expression();
|
||||
static void statement();
|
||||
static void block();
|
||||
|
||||
static void function_call(int syscall_id) {
|
||||
if (compile_error) return;
|
||||
cur_token++;
|
||||
match(TOK_LPAREN);
|
||||
if (tokens[cur_token].type != TOK_RPAREN) {
|
||||
expression();
|
||||
while (tokens[cur_token].type == TOK_COMMA) { cur_token++; expression(); }
|
||||
}
|
||||
match(TOK_RPAREN);
|
||||
emit(OP_SYSCALL);
|
||||
emit32(syscall_id);
|
||||
}
|
||||
|
||||
static void factor() {
|
||||
if (compile_error) return;
|
||||
if (tokens[cur_token].type == TOK_INT) { emit(OP_IMM); emit32(tokens[cur_token].int_val); cur_token++; }
|
||||
else if (tokens[cur_token].type == TOK_STRING) { int offset = add_string(tokens[cur_token].str_val); emit(OP_PUSH_PTR); emit32(offset); cur_token++; }
|
||||
else if (tokens[cur_token].type == TOK_ID) {
|
||||
int syscall = find_builtin(tokens[cur_token].str_val);
|
||||
if (syscall != -1 && tokens[cur_token+1].type == TOK_LPAREN) function_call(syscall);
|
||||
else {
|
||||
int addr = find_symbol(tokens[cur_token].str_val);
|
||||
if (addr == -1) { printf("Error: Undefined variable: %s\n", tokens[cur_token].str_val); compile_error = 1; }
|
||||
emit(OP_LOAD); emit32(addr); cur_token++;
|
||||
}
|
||||
} else if (tokens[cur_token].type == TOK_LPAREN) { cur_token++; expression(); match(TOK_RPAREN); }
|
||||
else { printf("Syntax Error: Unexpected token in factor\n"); compile_error = 1; }
|
||||
}
|
||||
|
||||
static void term() {
|
||||
if (compile_error) return;
|
||||
factor();
|
||||
while (tokens[cur_token].type == TOK_MUL || tokens[cur_token].type == TOK_DIV) {
|
||||
TokenType op = tokens[cur_token].type; cur_token++; factor();
|
||||
if (op == TOK_MUL) emit(OP_MUL); else emit(OP_DIV);
|
||||
}
|
||||
}
|
||||
|
||||
static void additive() {
|
||||
if (compile_error) return;
|
||||
term();
|
||||
while (tokens[cur_token].type == TOK_PLUS || tokens[cur_token].type == TOK_MINUS) {
|
||||
TokenType op = tokens[cur_token].type; cur_token++; term();
|
||||
if (op == TOK_PLUS) emit(OP_ADD); else emit(OP_SUB);
|
||||
}
|
||||
}
|
||||
|
||||
static void relation() {
|
||||
if (compile_error) return;
|
||||
additive();
|
||||
if (tokens[cur_token].type >= TOK_EQ && tokens[cur_token].type <= TOK_GE) {
|
||||
TokenType op = tokens[cur_token].type; cur_token++; additive();
|
||||
switch (op) {
|
||||
case TOK_EQ: emit(OP_EQ); break;
|
||||
case TOK_NEQ: emit(OP_NEQ); break;
|
||||
case TOK_LT: emit(OP_LT); break;
|
||||
case TOK_GT: emit(OP_GT); break;
|
||||
case TOK_LE: emit(OP_LE); break;
|
||||
case TOK_GE: emit(OP_GE); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void expression() { if (compile_error) return; relation(); }
|
||||
|
||||
static void statement() {
|
||||
if (compile_error) return;
|
||||
if (tokens[cur_token].type == TOK_INT_TYPE || tokens[cur_token].type == TOK_CHAR_TYPE) {
|
||||
cur_token++;
|
||||
while (tokens[cur_token].type == TOK_MUL) cur_token++;
|
||||
if (tokens[cur_token].type == TOK_ID) {
|
||||
add_symbol(tokens[cur_token].str_val);
|
||||
cur_token++;
|
||||
if (tokens[cur_token].type == TOK_LBRACKET) {
|
||||
cur_token++; if (tokens[cur_token].type == TOK_INT) cur_token++;
|
||||
if (tokens[cur_token].type == TOK_RBRACKET) cur_token++;
|
||||
else printf("Error: Expected ]\n");
|
||||
}
|
||||
if (tokens[cur_token].type == TOK_ASSIGN) {
|
||||
int addr = find_symbol(tokens[cur_token-1].str_val);
|
||||
cur_token++; expression(); emit(OP_STORE); emit32(addr);
|
||||
}
|
||||
match(TOK_SEMI);
|
||||
} else { printf("Syntax Error: Expected identifier\n"); compile_error = 1; }
|
||||
} else if (tokens[cur_token].type == TOK_ID) {
|
||||
int syscall = find_builtin(tokens[cur_token].str_val);
|
||||
if (syscall != -1 && tokens[cur_token+1].type == TOK_LPAREN) {
|
||||
function_call(syscall); match(TOK_SEMI); emit(OP_POP);
|
||||
} else {
|
||||
int addr = find_symbol(tokens[cur_token].str_val);
|
||||
if (addr == -1) { printf("Error: Undefined variable assignment: %s\n", tokens[cur_token].str_val); compile_error = 1; return; }
|
||||
cur_token++; match(TOK_ASSIGN); expression(); match(TOK_SEMI); emit(OP_STORE); emit32(addr);
|
||||
}
|
||||
} else if (tokens[cur_token].type == TOK_IF) {
|
||||
cur_token++; match(TOK_LPAREN); expression(); match(TOK_RPAREN);
|
||||
emit(OP_JZ); int jz_addr_pos = code_pos; emit32(0); block();
|
||||
if (tokens[cur_token].type == TOK_ELSE) {
|
||||
emit(OP_JMP); int jmp_addr_pos = code_pos; emit32(0);
|
||||
int else_start = code_pos;
|
||||
code[jz_addr_pos] = else_start & 0xFF; code[jz_addr_pos+1] = (else_start >> 8) & 0xFF; code[jz_addr_pos+2] = (else_start >> 16) & 0xFF; code[jz_addr_pos+3] = (else_start >> 24) & 0xFF;
|
||||
cur_token++; block();
|
||||
int end_addr = code_pos;
|
||||
code[jmp_addr_pos] = end_addr & 0xFF; code[jmp_addr_pos+1] = (end_addr >> 8) & 0xFF; code[jmp_addr_pos+2] = (end_addr >> 16) & 0xFF; code[jmp_addr_pos+3] = (end_addr >> 24) & 0xFF;
|
||||
} else {
|
||||
int end_addr = code_pos;
|
||||
code[jz_addr_pos] = end_addr & 0xFF; code[jz_addr_pos+1] = (end_addr >> 8) & 0xFF; code[jz_addr_pos+2] = (end_addr >> 16) & 0xFF; code[jz_addr_pos+3] = (end_addr >> 24) & 0xFF;
|
||||
}
|
||||
} else if (tokens[cur_token].type == TOK_WHILE) {
|
||||
int start_addr = code_pos; cur_token++; match(TOK_LPAREN); expression(); match(TOK_RPAREN);
|
||||
emit(OP_JZ); int jz_addr_pos = code_pos; emit32(0); block();
|
||||
emit(OP_JMP); emit32(start_addr);
|
||||
int end_addr = code_pos;
|
||||
code[jz_addr_pos] = end_addr & 0xFF; code[jz_addr_pos+1] = (end_addr >> 8) & 0xFF; code[jz_addr_pos+2] = (end_addr >> 16) & 0xFF; code[jz_addr_pos+3] = (end_addr >> 24) & 0xFF;
|
||||
} else cur_token++;
|
||||
}
|
||||
|
||||
static void block() {
|
||||
if (compile_error) return;
|
||||
match(TOK_LBRACE);
|
||||
while (tokens[cur_token].type != TOK_RBRACE && tokens[cur_token].type != TOK_EOF && !compile_error) statement();
|
||||
match(TOK_RBRACE);
|
||||
}
|
||||
|
||||
static void program() {
|
||||
if (tokens[cur_token].type == TOK_INT_TYPE || tokens[cur_token].type == TOK_VOID_TYPE) cur_token++;
|
||||
if (tokens[cur_token].type == TOK_MAIN) cur_token++;
|
||||
match(TOK_LPAREN); match(TOK_RPAREN); block(); emit(OP_HALT);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) { printf("Usage: cc <filename.c>\n"); return 1; }
|
||||
|
||||
int fh = sys_open(argv[1], "r");
|
||||
if (fh < 0) { printf("Error: Cannot open source file.\n"); return 1; }
|
||||
|
||||
char *source = (char*)malloc(MAX_SOURCE);
|
||||
if (!source) { printf("Error: Out of memory for source buffer.\n"); sys_close(fh); return 1; }
|
||||
|
||||
int len = sys_read(fh, source, MAX_SOURCE - 1);
|
||||
source[len] = 0;
|
||||
sys_close(fh);
|
||||
|
||||
lexer(source);
|
||||
free(source);
|
||||
|
||||
if (compile_error) return 1;
|
||||
|
||||
code_pos = 0; symbol_count = 0; cur_token = 0; str_pool_pos = 0; next_var_addr = 32768;
|
||||
|
||||
const char* magic = VM_MAGIC;
|
||||
for(int i=0; i<7; i++) emit(magic[i]);
|
||||
emit(1);
|
||||
program();
|
||||
|
||||
if (compile_error) { printf("Compilation Failed.\n"); return 1; }
|
||||
|
||||
int pool_start_addr = code_pos;
|
||||
for(int i=0; i<str_pool_pos; i++) emit(str_pool[i]);
|
||||
|
||||
int pc = 8;
|
||||
while (pc < pool_start_addr) {
|
||||
uint8_t op = code[pc++];
|
||||
switch (op) {
|
||||
case OP_HALT: break; case OP_IMM: case OP_LOAD: case OP_STORE: case OP_LOAD8: case OP_STORE8: case OP_JMP: case OP_JZ: case OP_SYSCALL: pc += 4; break;
|
||||
case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_PRINT: case OP_PRITC: case OP_EQ: case OP_NEQ: case OP_LT: case OP_GT: case OP_LE: case OP_GE: case OP_POP: break;
|
||||
case OP_PUSH_PTR: {
|
||||
int offset = 0;
|
||||
offset |= code[pc]; offset |= code[pc+1] << 8; offset |= code[pc+2] << 16; offset |= code[pc+3] << 24;
|
||||
int abs_addr = pool_start_addr + offset;
|
||||
code[pc] = abs_addr & 0xFF; code[pc+1] = (abs_addr >> 8) & 0xFF; code[pc+2] = (abs_addr >> 16) & 0xFF; code[pc+3] = (abs_addr >> 24) & 0xFF;
|
||||
pc += 4; code[pc-5] = OP_IMM; break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
char out_name[64]; int i = 0;
|
||||
while(argv[1][i] && argv[1][i] != '.') { out_name[i] = argv[1][i]; i++; }
|
||||
out_name[i] = 0;
|
||||
|
||||
int out_fh = sys_open(out_name, "w");
|
||||
if (out_fh >= 0) {
|
||||
sys_write_fs(out_fh, code, code_pos);
|
||||
sys_close(out_fh);
|
||||
printf("Compilation successful. Output: %s\n", out_name);
|
||||
} else { printf("Error: Cannot write output file.\n"); }
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
src/kernel/userland/clear.c
Normal file
8
src/kernel/userland/clear.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
sys_system(10, 0, 0, 0, 0); // SYSTEM_CMD_CLEAR_SCREEN
|
||||
return 0;
|
||||
}
|
||||
26
src/kernel/userland/cowsay.c
Normal file
26
src/kernel/userland/cowsay.c
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *msg = (char*)"Bored!";
|
||||
if (argc > 1) {
|
||||
// Simple concatenation of args for now
|
||||
// For simplicity in this demo, just use the first arg
|
||||
msg = argv[1];
|
||||
}
|
||||
|
||||
size_t len = strlen(msg);
|
||||
|
||||
printf(" ");
|
||||
for(size_t i=0; i<len+2; i++) printf("_");
|
||||
printf("\n< %s >\n ", msg);
|
||||
for(size_t i=0; i<len+2; i++) printf("-");
|
||||
printf("\n");
|
||||
printf(" \\ ^__^\n");
|
||||
printf(" \\ (oo)\\_______\n");
|
||||
printf(" (__)\\ )\\/\\\n");
|
||||
printf(" ||----w |\n");
|
||||
printf(" || ||\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
33
src/kernel/userland/cp.c
Normal file
33
src/kernel/userland/cp.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 3) {
|
||||
printf("Usage: cp <source> <dest>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fd_in = sys_open(argv[1], "r");
|
||||
if (fd_in < 0) {
|
||||
printf("Error: Cannot open source %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fd_out = sys_open(argv[2], "w");
|
||||
if (fd_out < 0) {
|
||||
printf("Error: Cannot create destination %s\n", argv[2]);
|
||||
sys_close(fd_in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buffer[4096];
|
||||
int bytes;
|
||||
while ((bytes = sys_read(fd_in, buffer, sizeof(buffer))) > 0) {
|
||||
sys_write_fs(fd_out, buffer, bytes);
|
||||
}
|
||||
|
||||
sys_close(fd_in);
|
||||
sys_close(fd_out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
13
src/kernel/userland/date.c
Normal file
13
src/kernel/userland/date.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
int dt[6];
|
||||
if (sys_system(11, (uint64_t)dt, 0, 0, 0) == 0) {
|
||||
printf("Current Date: %d-%d-%d %d:%d:%d\n", dt[0], dt[1], dt[2], dt[3], dt[4], dt[5]);
|
||||
} else {
|
||||
printf("Error: Could not retrieve date.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
10
src/kernel/userland/echo.c
Normal file
10
src/kernel/userland/echo.c
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
printf("%s%s", argv[i], (i == argc - 1) ? "" : " ");
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,41 +1,13 @@
|
||||
#include "syscall.h"
|
||||
|
||||
int strlen(const char* str) {
|
||||
int len = 0;
|
||||
while(str[len]) len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
void print_int(int n) {
|
||||
char buf[16];
|
||||
if (n == 0) {
|
||||
sys_write(1, "0", 1);
|
||||
return;
|
||||
}
|
||||
int i = 0;
|
||||
while(n > 0) {
|
||||
buf[i++] = (n % 10) + '0';
|
||||
n /= 10;
|
||||
}
|
||||
for(int j = i - 1; j >= 0; j--) {
|
||||
sys_write(1, &buf[j], 1);
|
||||
}
|
||||
}
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
const char* msg = "Hello from Userland ELF!\n";
|
||||
sys_write(1, msg, 25);
|
||||
printf("Hello from Userland ELF!\n");
|
||||
|
||||
sys_write(1, "argc: ", 6);
|
||||
print_int(argc);
|
||||
sys_write(1, "\n", 1);
|
||||
printf("argc: %d\n", argc);
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
sys_write(1, "argv[", 5);
|
||||
print_int(i);
|
||||
sys_write(1, "]: ", 3);
|
||||
sys_write(1, argv[i], strlen(argv[i]));
|
||||
sys_write(1, "\n", 1);
|
||||
printf("argv[%d]: %s\n", i, argv[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
32
src/kernel/userland/help.c
Normal file
32
src/kernel/userland/help.c
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
printf("BoredOS CLI Help (Userspace)\n");
|
||||
printf("---------------------------\n");
|
||||
printf("ls [path] - List directory contents\n");
|
||||
printf("cd <path> - Change current directory (built-in)\n");
|
||||
printf("pwd - Print current directory\n");
|
||||
printf("mkdir <dir> - Create directory\n");
|
||||
printf("rm <path> - Remove file or directory\n");
|
||||
printf("cat <file> - Print file contents\n");
|
||||
printf("echo [text] - Print text\n");
|
||||
printf("touch <file> - Create empty file\n");
|
||||
printf("cp <src> <dst> - Copy file\n");
|
||||
printf("mv <src> <dst> - Move file\n");
|
||||
printf("date - Print current date and time\n");
|
||||
printf("uptime - Print system uptime\n");
|
||||
printf("meminfo - Print memory information\n");
|
||||
printf("cowsay [msg] - Fun cow says something\n");
|
||||
printf("beep - Make a beep sound\n");
|
||||
printf("reboot - Reboot the system\n");
|
||||
printf("shutdown - Shutdown the system\n");
|
||||
printf("boredver - Show BoredOS version\n");
|
||||
printf("cc <file.c> - C Compiler\n");
|
||||
printf("man <cmd> - Show manual page\n");
|
||||
printf("clear - Clear the screen\n");
|
||||
printf("exit - Exit the terminal\n");
|
||||
printf("\nHint: Use Ctrl+C to force quit any running .elf app.\n");
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
@@ -123,14 +123,142 @@ void *realloc(void *ptr, size_t size) {
|
||||
}
|
||||
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
unsigned char *p = s;
|
||||
unsigned char *p = (unsigned char *)s;
|
||||
while (n--) *p++ = (unsigned char)c;
|
||||
return s;
|
||||
}
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n) {
|
||||
unsigned char *d = dest;
|
||||
const unsigned char *s = src;
|
||||
unsigned char *d = (unsigned char *)dest;
|
||||
const unsigned char *s = (const unsigned char *)src;
|
||||
while (n--) *d++ = *s++;
|
||||
return dest;
|
||||
}
|
||||
|
||||
// String functions
|
||||
size_t strlen(const char *s) {
|
||||
size_t len = 0;
|
||||
while (s[len]) len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
int strcmp(const char *s1, const char *s2) {
|
||||
while (*s1 && (*s1 == *s2)) {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return *(const unsigned char*)s1 - *(const unsigned char*)s2;
|
||||
}
|
||||
|
||||
char* strcpy(char *dest, const char *src) {
|
||||
char *ret = dest;
|
||||
while (*src) *dest++ = *src++;
|
||||
*dest = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
char* strcat(char *dest, const char *src) {
|
||||
char *ret = dest;
|
||||
while (*dest) dest++;
|
||||
while (*src) *dest++ = *src++;
|
||||
*dest = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int atoi(const char *nptr) {
|
||||
int res = 0;
|
||||
int sign = 1;
|
||||
if (*nptr == '-') {
|
||||
sign = -1;
|
||||
nptr++;
|
||||
}
|
||||
while (*nptr >= '0' && *nptr <= '9') {
|
||||
res = res * 10 + (*nptr - '0');
|
||||
nptr++;
|
||||
}
|
||||
return sign * res;
|
||||
}
|
||||
|
||||
void itoa(int n, char *buf) {
|
||||
if (n == 0) {
|
||||
buf[0] = '0'; buf[1] = 0; return;
|
||||
}
|
||||
int i = 0;
|
||||
int sign = n < 0;
|
||||
if (sign) n = -n;
|
||||
while (n > 0) {
|
||||
buf[i++] = (n % 10) + '0';
|
||||
n /= 10;
|
||||
}
|
||||
if (sign) buf[i++] = '-';
|
||||
buf[i] = 0;
|
||||
// Reverse
|
||||
for (int j = 0; j < i / 2; j++) {
|
||||
char t = buf[j];
|
||||
buf[j] = buf[i - 1 - j];
|
||||
buf[i - 1 - j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
// IO functions
|
||||
void puts(const char *s) {
|
||||
sys_write(1, s, strlen(s));
|
||||
sys_write(1, "\n", 1);
|
||||
}
|
||||
|
||||
void printf(const char *fmt, ...) {
|
||||
// Simple printf implementation
|
||||
__builtin_va_list args;
|
||||
__builtin_va_start(args, fmt);
|
||||
char buf[1024];
|
||||
int buf_idx = 0;
|
||||
|
||||
while (*fmt) {
|
||||
if (*fmt == '%') {
|
||||
fmt++;
|
||||
if (*fmt == 's') {
|
||||
char *s = __builtin_va_arg(args, char *);
|
||||
while (*s) buf[buf_idx++] = *s++;
|
||||
} else if (*fmt == 'd') {
|
||||
int d = __builtin_va_arg(args, int);
|
||||
char ibuf[32];
|
||||
itoa(d, ibuf);
|
||||
char *s = ibuf;
|
||||
while (*s) buf[buf_idx++] = *s++;
|
||||
} else if (*fmt == 'c') {
|
||||
char c = (char)__builtin_va_arg(args, int);
|
||||
buf[buf_idx++] = c;
|
||||
} else if (*fmt == '%') {
|
||||
buf[buf_idx++] = '%';
|
||||
}
|
||||
} else {
|
||||
buf[buf_idx++] = *fmt;
|
||||
}
|
||||
fmt++;
|
||||
if (buf_idx >= 1022) break; // Simple overflow protection
|
||||
}
|
||||
buf[buf_idx] = 0;
|
||||
sys_write(1, buf, buf_idx);
|
||||
__builtin_va_end(args);
|
||||
}
|
||||
|
||||
// System/Process functions
|
||||
int chdir(const char *path) {
|
||||
return sys_chdir(path);
|
||||
}
|
||||
|
||||
char* getcwd(char *buf, int size) {
|
||||
if (sys_getcwd(buf, size) == 0) return buf;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void sleep(int ms) {
|
||||
// We don't have a sleep syscall yet, so we'll just busy wait for now or skip
|
||||
// Actually, BoredOS doesn't seem to have a sleep syscall.
|
||||
// I'll add one if needed, but for now I'll just skip.
|
||||
(void)ms;
|
||||
}
|
||||
|
||||
void exit(int status) {
|
||||
sys_exit(status);
|
||||
}
|
||||
|
||||
@@ -11,4 +11,22 @@ void* realloc(void* ptr, size_t size);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
|
||||
// String functions
|
||||
size_t strlen(const char *s);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
char* strcpy(char *dest, const char *src);
|
||||
char* strcat(char *dest, const char *src);
|
||||
int atoi(const char *nptr);
|
||||
void itoa(int n, char *buf);
|
||||
|
||||
// IO functions
|
||||
void puts(const char *s);
|
||||
void printf(const char *fmt, ...);
|
||||
|
||||
// System/Process functions
|
||||
int chdir(const char *path);
|
||||
char* getcwd(char *buf, int size);
|
||||
void sleep(int ms);
|
||||
void exit(int status);
|
||||
|
||||
#endif
|
||||
|
||||
Binary file not shown.
@@ -121,3 +121,15 @@ int sys_exists(const char *path) {
|
||||
return (int)syscall2(SYS_FS, FS_CMD_EXISTS, (uint64_t)path);
|
||||
}
|
||||
|
||||
int sys_getcwd(char *buf, int size) {
|
||||
return (int)syscall3(SYS_FS, FS_CMD_GETCWD, (uint64_t)buf, (uint64_t)size);
|
||||
}
|
||||
|
||||
int sys_chdir(const char *path) {
|
||||
return (int)syscall2(SYS_FS, FS_CMD_CHDIR, (uint64_t)path);
|
||||
}
|
||||
|
||||
void sys_kill(int pid) {
|
||||
syscall1(SYS_KILL, (uint64_t)pid);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#define SYS_GUI 3
|
||||
#define SYS_FS 4
|
||||
#define SYS_SYSTEM 5
|
||||
#define SYS_KILL 10
|
||||
#define SYS_SBRK 9
|
||||
|
||||
// FS Commands
|
||||
@@ -23,6 +24,8 @@
|
||||
#define FS_CMD_SIZE 9
|
||||
#define FS_CMD_MKDIR 10
|
||||
#define FS_CMD_EXISTS 11
|
||||
#define FS_CMD_GETCWD 12
|
||||
#define FS_CMD_CHDIR 13
|
||||
|
||||
// Internal assembly entry into Ring 0
|
||||
extern uint64_t syscall0(uint64_t sys_num);
|
||||
@@ -36,6 +39,7 @@ extern uint64_t syscall5(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_
|
||||
void sys_exit(int status);
|
||||
int sys_write(int fd, const char *buf, int len);
|
||||
void *sys_sbrk(int incr);
|
||||
void sys_kill(int pid);
|
||||
int sys_system(int cmd, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4);
|
||||
|
||||
// FS API
|
||||
@@ -49,8 +53,18 @@ uint32_t sys_size(int fd);
|
||||
int sys_delete(const char *path);
|
||||
int sys_mkdir(const char *path);
|
||||
int sys_exists(const char *path);
|
||||
int sys_getcwd(char *buf, int size);
|
||||
int sys_chdir(const char *path);
|
||||
|
||||
struct FAT32_FileInfo;
|
||||
int sys_list(const char *path, struct FAT32_FileInfo *entries, int max_entries);
|
||||
typedef struct {
|
||||
char name[256];
|
||||
uint32_t size;
|
||||
uint8_t is_directory;
|
||||
uint32_t start_cluster;
|
||||
uint16_t write_date;
|
||||
uint16_t write_time;
|
||||
} FAT32_FileInfo;
|
||||
|
||||
int sys_list(const char *path, FAT32_FileInfo *entries, int max_entries);
|
||||
|
||||
#endif
|
||||
|
||||
Binary file not shown.
32
src/kernel/userland/ls.c
Normal file
32
src/kernel/userland/ls.c
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char path[256];
|
||||
if (argc > 1) {
|
||||
strcpy(path, argv[1]);
|
||||
} else {
|
||||
if (!getcwd(path, sizeof(path))) {
|
||||
strcpy(path, ".");
|
||||
}
|
||||
}
|
||||
|
||||
FAT32_FileInfo entries[128];
|
||||
int count = sys_list(path, entries, 128);
|
||||
|
||||
if (count < 0) {
|
||||
printf("Error: Cannot list directory %s\n", path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (entries[i].is_directory) {
|
||||
printf("[DIR] %s\n", entries[i].name);
|
||||
} else {
|
||||
printf("[FILE] %s (%d bytes)\n", entries[i].name, entries[i].size);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nTotal: %d items\n", count);
|
||||
return 0;
|
||||
}
|
||||
33
src/kernel/userland/man.c
Normal file
33
src/kernel/userland/man.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
printf("What manual page do you want?\nExample: man ls\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char path[128];
|
||||
printf("Manual for: %s\n", argv[1]);
|
||||
printf("---------------------------\n");
|
||||
|
||||
strcpy(path, "A:/Library/man/");
|
||||
strcat(path, argv[1]);
|
||||
strcat(path, ".txt");
|
||||
|
||||
int fd = sys_open(path, "r");
|
||||
if (fd < 0) {
|
||||
printf("No manual entry for %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buffer[4096];
|
||||
int bytes;
|
||||
while ((bytes = sys_read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
sys_write(1, buffer, bytes);
|
||||
}
|
||||
|
||||
sys_close(fd);
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
27
src/kernel/userland/math.c
Normal file
27
src/kernel/userland/math.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 4) {
|
||||
printf("Usage: math <num1> <op> <num2>\n");
|
||||
printf("Ops: + - * /\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n1 = atoi(argv[1]);
|
||||
int n2 = atoi(argv[3]);
|
||||
char op = argv[2][0];
|
||||
int res = 0;
|
||||
|
||||
if (op == '+') res = n1 + n2;
|
||||
else if (op == '-') res = n1 - n2;
|
||||
else if (op == '*') res = n1 * n2;
|
||||
else if (op == '/') {
|
||||
if (n2 == 0) { printf("Error: Div by zero\n"); return 1; }
|
||||
res = n1 / n2;
|
||||
}
|
||||
else { printf("Error: Unknown op %c\n", op); return 1; }
|
||||
|
||||
printf("%d %c %d = %d\n", n1, op, n2, res);
|
||||
return 0;
|
||||
}
|
||||
16
src/kernel/userland/meminfo.c
Normal file
16
src/kernel/userland/meminfo.c
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
uint64_t mem[2];
|
||||
if (sys_system(15, (uint64_t)mem, 0, 0, 0) == 0) {
|
||||
printf("Memory Info:\n");
|
||||
printf("Total: %d MB\n", (int)(mem[0] / 1024 / 1024));
|
||||
printf("Used: %d MB\n", (int)(mem[1] / 1024 / 1024));
|
||||
printf("Free: %d MB\n", (int)((mem[0] - mem[1]) / 1024 / 1024));
|
||||
} else {
|
||||
printf("Error: Could not retrieve memory info.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
17
src/kernel/userland/mkdir.c
Normal file
17
src/kernel/userland/mkdir.c
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: mkdir <dirname>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sys_mkdir(argv[1]) == 0) {
|
||||
printf("Created directory: %s\n", argv[1]);
|
||||
} else {
|
||||
printf("Error: Cannot create directory %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
38
src/kernel/userland/mv.c
Normal file
38
src/kernel/userland/mv.c
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 3) {
|
||||
printf("Usage: mv <source> <dest>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Simplification: use cp then rm
|
||||
int fd_in = sys_open(argv[1], "r");
|
||||
if (fd_in < 0) {
|
||||
printf("Error: Cannot open source %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fd_out = sys_open(argv[2], "w");
|
||||
if (fd_out < 0) {
|
||||
printf("Error: Cannot create destination %s\n", argv[2]);
|
||||
sys_close(fd_in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buffer[4096];
|
||||
int bytes;
|
||||
while ((bytes = sys_read(fd_in, buffer, sizeof(buffer))) > 0) {
|
||||
sys_write_fs(fd_out, buffer, bytes);
|
||||
}
|
||||
|
||||
sys_close(fd_in);
|
||||
sys_close(fd_out);
|
||||
|
||||
if (sys_delete(argv[1]) != 0) {
|
||||
printf("Warning: Failed to delete source %s after copy\n", argv[1]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
30
src/kernel/userland/pci_list.c
Normal file
30
src/kernel/userland/pci_list.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
typedef struct {
|
||||
uint16_t vendor;
|
||||
uint16_t device;
|
||||
uint8_t class_code;
|
||||
uint8_t subclass;
|
||||
} pci_info_t;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
int count = sys_system(17, 0, 0, 0, 0); // Get count
|
||||
if (count < 0) {
|
||||
printf("Error: Could not retrieve PCI device count.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PCI Devices (%d found):\n", count);
|
||||
printf("---------------------------\n");
|
||||
for (int i = 0; i < count; i++) {
|
||||
pci_info_t info;
|
||||
if (sys_system(17, (uint64_t)&info, i, 0, 0) == 0) {
|
||||
printf("[%d] Vendor:%04x Device:%04x Class:%02x Sub:%02x\n",
|
||||
i, info.vendor, info.device, info.class_code, info.subclass);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
14
src/kernel/userland/pwd.c
Normal file
14
src/kernel/userland/pwd.c
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
char path[256];
|
||||
if (getcwd(path, sizeof(path))) {
|
||||
printf("%s\n", path);
|
||||
} else {
|
||||
printf("Error: Could not get current directory\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
9
src/kernel/userland/reboot.c
Normal file
9
src/kernel/userland/reboot.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
printf("Rebooting...\n");
|
||||
sys_system(12, 0, 0, 0, 0); // SYSTEM_CMD_REBOOT
|
||||
return 0;
|
||||
}
|
||||
18
src/kernel/userland/rm.c
Normal file
18
src/kernel/userland/rm.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: rm <path>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Simple rm (no recursive support yet for simplicity, but can be added)
|
||||
if (sys_delete(argv[1]) == 0) {
|
||||
printf("Deleted: %s\n", argv[1]);
|
||||
} else {
|
||||
printf("Error: Cannot delete %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
9
src/kernel/userland/shutdown.c
Normal file
9
src/kernel/userland/shutdown.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
printf("Shutting down...\n");
|
||||
sys_system(13, 0, 0, 0, 0); // SYSTEM_CMD_SHUTDOWN
|
||||
return 0;
|
||||
}
|
||||
30
src/kernel/userland/sweden.c
Normal file
30
src/kernel/userland/sweden.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
static void beep(int freq, int ms) {
|
||||
sys_system(14, freq, ms, 0, 0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
printf("Playing Sweden - C418 (Minecraft)...\n");
|
||||
|
||||
// Main melody (simplified pattern)
|
||||
beep(392, 400); // G4
|
||||
beep(440, 400); // A4
|
||||
beep(493, 800); // B4
|
||||
|
||||
beep(440, 400); // A4
|
||||
beep(392, 800); // G4
|
||||
beep(329, 800); // E4
|
||||
|
||||
beep(392, 400); // G4
|
||||
beep(440, 400); // A4
|
||||
beep(493, 800); // B4
|
||||
|
||||
beep(440, 400); // A4
|
||||
beep(392, 1200); // G4
|
||||
|
||||
printf("Done.\n");
|
||||
return 0;
|
||||
}
|
||||
24
src/kernel/userland/touch.c
Normal file
24
src/kernel/userland/touch.c
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: touch <filename>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Check if file already exists
|
||||
if (sys_exists(argv[1])) {
|
||||
// Just return success if it exists (simplification)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fd = sys_open(argv[1], "w");
|
||||
if (fd < 0) {
|
||||
printf("Error: Cannot create %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sys_close(fd);
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
16
src/kernel/userland/uptime.c
Normal file
16
src/kernel/userland/uptime.c
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
uint64_t ticks = sys_system(16, 0, 0, 0, 0); // SYSTEM_CMD_UPTIME
|
||||
uint64_t seconds = ticks / 100; // 100Hz timer assumed
|
||||
uint64_t minutes = seconds / 60;
|
||||
uint64_t hours = minutes / 60;
|
||||
uint64_t days = hours / 24;
|
||||
|
||||
printf("Uptime: %d days, %d hours, %d minutes, %d seconds\n",
|
||||
(int)days, (int)(hours % 24), (int)(minutes % 60), (int)(seconds % 60));
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user