Implemented a proper libc

This commit is contained in:
2024-10-05 13:34:24 +02:00
parent a6445ebcb6
commit 5a5ea4ea59
28 changed files with 258 additions and 123 deletions
-83
View File
@@ -1,83 +0,0 @@
#ifndef _FILEIO_H
#define _FILEIO_H
#include <syscall.h>
#include <stdlib.h>
#include <stddef.h>
// Nobody should have to interface with the internals of this structure
typedef struct _iobuf { // 24B
unsigned char* _ptr; // File buffer base
unsigned int _size; // Size of buffer
int _offset; // Offset into file
unsigned short _flag; // Open flags
int _file; // File descriptor
char __reserved[6];
} FILE;
FILE* stdin;
FILE* stdout;
FILE* stderr;
FILE* fopen(const char* filename, const char* mode) {
int oflag = O_RDWR | O_CREAT | O_BIN; // TODO!
int fd = open(filename, oflag);
if (fd < 0) {
printf(""); // TODO: i'd prefer if i didn't need this
return NULL;
}
// TODO: Somehow get the open file table
FILE* fp = malloc(sizeof(FILE));
fp->_file = fd;
return fp;
}
int fclose(FILE* stream) {
int res = close(stream->_file);
return res;
}
size_t fread(void* ptr, size_t size, size_t count, FILE* stream) {
unsigned int offset = 0;
size_t readEl = 0;
int fd = stream->_file;
while (readEl != count) {
if (read(fd, (void*)(ptr + offset), size) != size) break;
offset += size;
readEl++;
}
return readEl;
}
size_t fwrite(const void* ptr, size_t size, size_t count, FILE* stream) {
unsigned int offset = 0;
size_t writtenEl = 0;
int fd = stream->_file;
while (writtenEl != count) {
if (write(fd, (void*)(ptr + offset), size) != size) break;
offset += size;
writtenEl++;
}
return writtenEl;
}
int fseek(FILE* stream, long int origin, int offset) {
// TODO
return -1;
}
long int ftell(FILE* stream) {
// TODO
return -1;
}
#endif
-130
View File
@@ -1,130 +0,0 @@
#ifndef _PRINTF_H
#define _PRINTF_H
#include <syscall.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <_fileio.h>
// Warning: returns a allocated buffer, must be freed!
char* _format(const char* fmt, va_list args) {
static char* buffer;
size_t len = 0;
size_t max = 256;
buffer = malloc(max);
size_t i = 0;
while (fmt[i] != '\0') {
if (len > max) {
max *= 2;
// Reallocate a larger buffer
char* temp = malloc(max);
strcpy(temp, buffer);
free(buffer);
buffer = temp;
}
// Formatting magic...
if (fmt[i] == '%') { i++;
/* TODO:
%p - pointer (0x########)
%n - ""
*/
int pad = -1;
char padc = ' ';
if (fmt[i] == '0') { i++; padc = '0'; }
if (fmt[i] >= '0' && fmt[i] <= '9') {
pad = atoi(fmt + i);
while (fmt[i] >= '0' && fmt[i] <= '9') { i++; }
}
while (pad > 0) { buffer[len++] = padc; pad--; }
char c = fmt[i++];
if (c == 'd' || c == 'x' || c == 'o') {
int base = 10;
if (c == 'x') base = 16;
else if (c == 'o') base = 8;
char* s = itoa(va_arg(args, int), base);
if (pad == 0) len -= strlen(s);
while ((buffer[len++] = *s++) != '\0');
len--;
} else if (c == 'c') {
if (pad == 0) len--;
buffer[len++] = va_arg(args, char);
} else if (c == 's') {
char* s = va_arg(args, char*);
if (pad == 0) len -= strlen(s);
while ((buffer[len++] = *s++) != '\0');
len--;
} else if (c == '%') {
buffer[len++] = '%';
} else {
buffer[len++] = '%';
if (padc == '0') { buffer[len++] = '0'; }
if (pad > 0) { buffer[len++] = '#'; } // TODO
buffer[len++] = c;
}
} else { buffer[len++] = fmt[i++]; }
}
buffer[len] = '\0';
return buffer;
}
int sprintf(char* str, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
char* buffer = _format(fmt, args);
strcpy(str, buffer);
free(buffer);
va_end(args);
return strlen(str);
}
int snprintf(char* str, size_t n, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
char* buffer = _format(fmt, args);
strncpy(str, buffer, n);
free(buffer);
va_end(args);
return strlen(str);
}
int fprintf(FILE* stream, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
char* buffer = _format(fmt, args);
size_t len = strlen(buffer);
write(stream->_file, buffer, len); // TODO: use fwrite()
free(buffer);
va_end(args);
return len;
}
int printf(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
char* buffer = _format(fmt, args);
size_t len = strlen(buffer);
write(stdout->_file, buffer, len); // TODO: use fwrite()
free(buffer);
va_end(args);
return len;
}
#endif
-27
View File
@@ -1,27 +0,0 @@
#ifndef COLOR_H
#define COLOR_H
#define BLACK 0x00000000 // 0
#define RED 0x00ff0000 // 1
#define GREEN 0x0000ff00 // 2
#define YELLOW 0x00ffff00 // 3
#define BLUE 0x000000ff // 4
#define MAGENTA 0x00ff00ff // 5
#define CYAN 0x0000ffff // 6
#define WHITE 0x00ffffff // 7
uint32_t codeToColor(uint8_t code) {
switch (code) {
case 0: return BLACK;
case 1: return RED;
case 2: return GREEN;
case 3: return YELLOW;
case 4: return BLUE;
case 5: return MAGENTA;
case 6: return CYAN;
case 7: return WHITE;
default: return BLACK;
}
}
#endif
-62
View File
@@ -1,62 +0,0 @@
#ifndef STDIO_H
#define STDIO_H
#include <syscall.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
/* Declarations */
void putc(char);
char getc();
int printf(const char*, ...);
/* STDIO Include */
#include <_fileio.h>
#include <_printf.h>
void putc(char c) {
// write(stdout, &c, 1); TODO: This doesn't work and we need to use a static variable
static char _c;
_c = c;
write(1, &_c, 1);
}
char getc() {
char* c = (char*)0x2100;
*c= '\0';
while (*c == '\0') { __asm__ volatile ("hlt"); }
return *c;
}
void print(const char* s) {
write(1, s, strlen(s));
}
void clear() {
print("\x1b[J");
}
// Reads until a newline
// TODO: Use Read() Syscall
void reads(char* buffer) {
char c;
int len = 0;
while ((c = getc()) != '\n') {
if (c == '\b') {
if (len < 1) continue; // Can we backspace?
len--;
putc(c);
} else {
buffer[len++] = c;
putc(c);
}
}
putc(c); // Print the newline
buffer[len] = '\0'; // Null terminate
}
#endif
-15
View File
@@ -1,15 +0,0 @@
#ifndef STDLIB_H
#define STDLIB_H
#include <stdint.h>
#include <syscall.h>
void* malloc(const uint32_t size) {
return (void*)syscall(SYS_MALLOC, size, 0, 0);
}
void free(const void* ptr) {
syscall(SYS_FREE, (int)ptr, 0, 0);
}
#endif
-143
View File
@@ -1,143 +0,0 @@
#ifndef STRING_H
#define STRING_H
#include <stdint.h>
void* memcpy(void* src, void* dst, uint32_t length);
void* memcpy32(void* src, void* dst, uint32_t length);
void* memset(void* dst, uint8_t value, uint32_t length);
// Source: http://www.strudel.org.uk/itoa/
char* itoa(uint32_t val, uint8_t base) {
static char buf[32] = { 0 };
if (base == 0 || base > 16) { return NULL; }
if (val == 0) {
buf[0] = '0';
return buf;
}
int i;
for (i = 30; val && i; i--, val /= base) {
buf[i] = "0123456789abcdef"[val % base];
}
return &buf[i + 1];
}
uint32_t atoi(const char* str) {
uint32_t res = 0;
// TODO: Add error checking
while (*str >= '0' && *str <= '9') {
res = res * 10 + (*str++ - '0');
}
return res;
}
int isSpace(char c) {
if (c == ' ' || c == '\t' || c == '\n') return 1;
else return 0;
}
// Some implementations taken from https://en.wikibooks.org/wiki/C_Programming/String_manipulation
char* strcpy(char* str1, const char* str2) {
char* dst = str1;
const char* src = str2;
while ((*dst++ = *src++) != '\0');
return str1;
}
char* strncpy(char* str1, const char* str2, size_t n) {
char* dst = str1;
const char* src = str2;
while (n > 0) {
n--;
if ((*dst++ = *src++) == '\0') {
memset(dst, '\0', n);
break;
}
}
return str1;
}
char* strcat(char* str1, const char* str2) {
char* s = str1;
while (*s != '\0') { s++; }
strcpy(s, str2);
return str1;
}
char* strncat(char* str1, const char* str2, size_t n) {
char* s = str1;
while (*s != '\0') { s++; }
strncpy(s, str2, n);
return str1;
}
char* strchr(const char* str, char c) {
const char* s = str;
while (*s != '\0' && *s != c) { s++; }
return (*s == c) ? (char*)s : NULL;
}
// char* strrchr(const char* str, char c);
int strcmp(const char* str1, const char* str2) {
while (*str1 != '\0' && *str1 == *str2) {
str1++;
str2++;
}
uint8_t c1 = (*(uint8_t*)str1);
uint8_t c2 = (*(uint8_t*)str2);
return ((c1 < c2) ? -1 : (c1 > c2));
}
int strncmp(const char* str1, const char* str2, size_t n) {
if (n == 0) { return 0; }
while (n-- > 0 && *str1 == *str2) {
if (n == 0 || *str1 == '\0') { return 0; }
str1++;
str2++;
}
uint8_t c1 = (*(uint8_t*)str1);
uint8_t c2 = (*(uint8_t*)str2);
return ((c1 < c2) ? -1 : (c1 > c2));
}
uint32_t strlen(const char* str) {
const char* p = str;
while (*++p != '\0');
return (uint32_t)(p - str);
}
// Memory functions
void* memcpy(void* src, void* dst, uint32_t length) {
for (uint32_t i = 0; i < length; i++) {
*((uint8_t*)dst + i) = *((uint8_t*)src + i);
}
return dst;
}
void* memcpy32(void* src, void* dst, uint32_t length) {
for (uint32_t i = 0; i * 4 < length; i++) {
*((uint32_t*)dst + i) = *((uint32_t*)src + i);
}
return dst;
}
void* memset(void* dst, uint8_t value, uint32_t length) {
for (uint32_t i = 0; i < length; i++) {
*(uint8_t*)(dst + i) = value;
}
return dst;
}
#endif
-11
View File
@@ -1,11 +0,0 @@
#ifndef TIME_H
#define TIME_H
#include <syscall.h>
#include <stdint.h>
void sleep(uint32_t ms) {
syscall(SYS_SLEEP, ms, 0, 0);
}
#endif
+15
View File
@@ -0,0 +1,15 @@
#ifndef COLOR_H
#define COLOR_H
#define BLACK 0x00000000 // 0
#define RED 0x00ff0000 // 1
#define GREEN 0x0000ff00 // 2
#define YELLOW 0x00ffff00 // 3
#define BLUE 0x000000ff // 4
#define MAGENTA 0x00ff00ff // 5
#define CYAN 0x0000ffff // 6
#define WHITE 0x00ffffff // 7
uint32_t codeToColor(uint8_t code);
#endif
+41
View File
@@ -0,0 +1,41 @@
#ifndef STDIO_H
#define STDIO_H
#include <stddef.h>
// Nobody should have to interface with the internals of this structure
typedef struct _iobuf { // 24B
unsigned char* _ptr; // File buffer base
unsigned int _size; // Size of buffer
int _offset; // Offset into file
unsigned short _flag; // Open flags
int _file; // File descriptor
char __reserved[6];
} FILE;
// Standard file pointers
extern FILE* stdin;
extern FILE* stdout;
extern FILE* stderr;
/* File IO */
FILE* fopen(const char* filename, const char* mode);
int fclose(FILE* stream);
size_t fread(void* ptr, size_t size, size_t count, FILE* stream);
size_t fwrite(const void* ptr, size_t size, size_t count, FILE* stream);
int fseek(FILE* stream, long int origin, int offset);
long int ftell(FILE* stream);
/* Terminal IO */
int printf(const char* fmt, ...);
int sprintf(char* str, const char* fmt, ...);
int snprintf(char* str, size_t n, const char* fmt, ...);
int fprintf(FILE* stream, const char* fmt, ...);
void putc(char c);
char getc();
void print(const char* str);
void clear();
void reads(char* str);
#endif
+10
View File
@@ -0,0 +1,10 @@
#ifndef STDLIB_H
#define STDLIB_H
#include <stdint.h>
#include <syscall.h>
void* malloc(const uint32_t size);
void free(const void* ptr);
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifndef STRING_H
#define STRING_H
#include <stdint.h>
void* memcpy(void* src, void* dst, uint32_t length);
void* memcpy32(void* src, void* dst, uint32_t length);
void* memset(void* dst, uint8_t value, uint32_t length);
char* itoa(uint32_t val, uint8_t base);
uint32_t atoi(const char* str);
int isSpace(char c);
char* strcpy(char* str1, const char* str2);
char* strncpy(char* str1, const char* str2, size_t n);
char* strcat(char* str1, const char* str2);
char* strncat(char* str1, const char* str2, size_t n);
char* strchr(const char* str, char c);
char* strrchr(const char* str, char c);
int strcmp(const char* str1, const char* str2);
int strncmp(const char* str1, const char* str2, size_t n);
uint32_t strlen(const char* str);
#endif
+5 -24
View File
@@ -27,31 +27,12 @@ typedef enum {
O_BIN = 0x40, // Read bytes, not text
} OFLAGS;
int syscall(int nr, int arg0, int arg1, int arg2) {
int ret = 0;
__asm__ volatile ("int $0x80" : "=a"(ret) : "a"(nr), "b"(arg0), "c"(arg1), "d"(arg2));
return ret;
}
int syscall(int nr, int arg0, int arg1, int arg2);
/* Syscall wrappers */
int read(int fd, void* ptr, size_t count) {
// Returns: int fd
return syscall(SYS_READ, fd, (int)ptr, count);
}
int write(int fd, const void* ptr, size_t count) {
// Returns: int count
return syscall(SYS_WRITE, fd, (int)ptr, count);
}
int open(const char* path, int oflag) {
// Returns: int fd
return syscall(SYS_OPEN, (int)path, oflag, 0);
}
int close(int fd) {
// Returns: int status
return syscall(SYS_CLOSE, fd, 0, 0);
}
int read(int fd, void* ptr, size_t count);
int write(int fd, const void* ptr, size_t count);
int open(const char* path, int oflag);
int close(int fd);
#endif
+8
View File
@@ -0,0 +1,8 @@
#ifndef TIME_H
#define TIME_H
#include <stdint.h>
void sleep(uint32_t ms);
#endif