forked from PoliEcho-holding-org/kern
Implemented a proper libc
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
#include <stdio.h>
|
||||
#include <syscall.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
#include <stdio.h>
|
||||
#include <syscall.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
// Warning: returns an 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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <stdint.h>
|
||||
#include <color.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#ifndef MATH_H
|
||||
#define MATH_H
|
||||
|
||||
// Constants
|
||||
#define PI 3.141592653589 // Should be good enough
|
||||
#define E 2.718281828459
|
||||
|
||||
// Macros
|
||||
#define abs(x) ( (x) > 0 ? (x) : -(x) )
|
||||
#define sign(x) ( (x) == 0 ? 0 : ((x) < 0 ? -1 : 1 ) )
|
||||
|
||||
#define floor(x) ( (int)(x) ) // C floors floats when converting to ints
|
||||
#define round(x) ( (int)((x) + 0.5) ) // Normal rounding
|
||||
#define ceil(x) ( (int)((x) + 1) ) // Always rounds up
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef STDARG_H
|
||||
#define STDARG_H
|
||||
|
||||
typedef char* va_list;
|
||||
#define va_start(ap, paramn) (void)((ap) = (char*)(&(paramn) + 1))
|
||||
#define va_end(ap) (void)((ap) = 0)
|
||||
#define va_arg(ap, type) (((type*)((ap) = ((ap) + sizeof(type))))[-1])
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef BOOL_H
|
||||
#define BOOL_H
|
||||
|
||||
#define bool _Bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef STDDEF_H
|
||||
#define STDDEF_H
|
||||
|
||||
#define NULL ((void*)0)
|
||||
|
||||
typedef unsigned int size_t;
|
||||
typedef signed int ssize_t;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef STDINT_H
|
||||
#define STDINT_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
// Signed ints
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef signed long long int64_t;
|
||||
|
||||
// Unsigned ints
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
// TODO: floats
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
#include <stdio.h>
|
||||
#include <syscall.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
FILE* stdin;
|
||||
FILE* stdout;
|
||||
FILE* stderr;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <stdint.h>
|
||||
#include <syscall.h>
|
||||
#include <stdlib.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);
|
||||
}
|
||||
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// 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) { return NULL; } // TODO
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#include <syscall.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define MAX_SYSCALLS 9
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <time.h>
|
||||
#include <syscall.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void sleep(uint32_t ms) {
|
||||
syscall(SYS_SLEEP, ms, 0, 0);
|
||||
}
|
||||
Reference in New Issue
Block a user