forked from PoliEcho-holding-org/kern
Fully implemented stdio.h!
This commit is contained in:
@@ -1,6 +1,11 @@
|
|||||||
#ifndef _FCNTL_H
|
#ifndef _FCNTL_H
|
||||||
#define _FCNTL_H
|
#define _FCNTL_H
|
||||||
|
|
||||||
|
/* Standard file decriptors */
|
||||||
|
#define STDIN_FILENO 0
|
||||||
|
#define STDOUT_FILENO 1
|
||||||
|
#define STDERR_FILENO 2
|
||||||
|
|
||||||
/* File access modes */
|
/* File access modes */
|
||||||
#define O_CREAT 0x0001 // Create if does not exist
|
#define O_CREAT 0x0001 // Create if does not exist
|
||||||
#define O_RDONLY 0x0002 // Read only
|
#define O_RDONLY 0x0002 // Read only
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ int ungetc(int c, FILE* stream);
|
|||||||
/* Line I/O */
|
/* Line I/O */
|
||||||
char* fgets(char* str, int n, FILE* stream);
|
char* fgets(char* str, int n, FILE* stream);
|
||||||
int fputs(const char* str, FILE* stream);
|
int fputs(const char* str, FILE* stream);
|
||||||
|
char* gets(char* str, int n);
|
||||||
int puts(const char* str);
|
int puts(const char* str);
|
||||||
|
|
||||||
/* TODO: Error handling
|
/* TODO: Error handling
|
||||||
|
|||||||
@@ -35,14 +35,14 @@ inline int syscall(int nr, int a0, int a1, int a2, int a3, int a4) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Syscall wrappers */
|
/* Syscall wrappers */
|
||||||
inline int _exit(int status) { return syscall(SYS_EXIT, status, 0, 0, 0, 0); }
|
static inline int _exit(int status) { return syscall(SYS_EXIT, status, 0, 0, 0, 0); }
|
||||||
inline int read(int fd, void* ptr, size_t count) { return syscall(SYS_READ, fd, (int)ptr, (int)count, 0, 0); }
|
static inline int read(int fd, void* ptr, size_t count) { return syscall(SYS_READ, fd, (int)ptr, (int)count, 0, 0); }
|
||||||
inline int write(int fd, const void* ptr, size_t count) { return syscall(SYS_WRITE, fd, (int)ptr, (int)count, 0, 0); }
|
static inline int write(int fd, const void* ptr, size_t count) { return syscall(SYS_WRITE, fd, (int)ptr, (int)count, 0, 0); }
|
||||||
inline int open(const char* path, int oflag) { return syscall(SYS_OPEN, (int)path, oflag, 0, 0, 0); }
|
static inline int open(const char* path, int oflag) { return syscall(SYS_OPEN, (int)path, oflag, 0, 0, 0); }
|
||||||
inline int close(int fd) { return syscall(SYS_CLOSE, fd, 0, 0, 0, 0); }
|
static inline int close(int fd) { return syscall(SYS_CLOSE, fd, 0, 0, 0, 0); }
|
||||||
inline int seek(int fd, size_t offset, int whence) { return syscall(SYS_SEEK, fd, offset, whence, 0, 0); }
|
static inline int seek(int fd, size_t offset, int whence) { return syscall(SYS_SEEK, fd, offset, whence, 0, 0); }
|
||||||
inline int _malloc(int size) { return syscall(SYS_MALLOC, size, 0, 0, 0, 0); }
|
static inline int _malloc(int size) { return syscall(SYS_MALLOC, size, 0, 0, 0, 0); }
|
||||||
inline int _free(void* ptr) { return syscall(SYS_FREE, (int)ptr, 0, 0, 0, 0); }
|
static inline int _free(void* ptr) { return syscall(SYS_FREE, (int)ptr, 0, 0, 0, 0); }
|
||||||
inline int _sleep(int t) { return syscall(SYS_SLEEP, t, 0, 0, 0, 0); }
|
static inline int _sleep(int t) { return syscall(SYS_SLEEP, t, 0, 0, 0, 0); }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ int putchar(int c) { return putc(c, stdout); }
|
|||||||
int getc(FILE* stream) {
|
int getc(FILE* stream) {
|
||||||
if (!stream) { return EOF; }
|
if (!stream) { return EOF; }
|
||||||
|
|
||||||
unsigned char ch;
|
unsigned char ch = '\0';
|
||||||
ssize_t res = read(stream->_file, &ch, 1);
|
ssize_t res = read(stream->_file, &ch, 1);
|
||||||
if (res <= 0) { return EOF; }
|
if (res <= 0) { return EOF; }
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
FILE* stdin;
|
||||||
|
FILE* stdout;
|
||||||
|
FILE* stderr;
|
||||||
|
|
||||||
FILE* fopen(const char* path, const char* mode) {
|
FILE* fopen(const char* path, const char* mode) {
|
||||||
FILE* fp = (FILE*)malloc(sizeof(FILE));
|
FILE* fp = (FILE*)malloc(sizeof(FILE));
|
||||||
if (!fp) { return NULL; }
|
if (!fp) { return NULL; }
|
||||||
|
|||||||
+113
-2
@@ -2,6 +2,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
/* Internal definitions */
|
/* Internal definitions */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -11,6 +12,57 @@ typedef struct {
|
|||||||
} printfEnv_t;
|
} printfEnv_t;
|
||||||
|
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
|
// Digit to character
|
||||||
|
static char _dtoc(int digit) { return digit < 10 ? '0' + digit : 'a' + (digit - 10); }
|
||||||
|
static double _fabs(double x) { return (x < 0.0) ? -x : x; }
|
||||||
|
static void _fmtInt(void (*outfn)(char c, void* arg), void* arg, int n, int base, int width, char padc) {
|
||||||
|
char buf[32];
|
||||||
|
int negative = 0;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (n < 0 && base == 10) {
|
||||||
|
negative = 1;
|
||||||
|
n = -n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert number, this will be done in reverse
|
||||||
|
do {
|
||||||
|
buf[i++] = _dtoc(n % base);
|
||||||
|
n /= base;
|
||||||
|
} while (n > 0);
|
||||||
|
|
||||||
|
// Padding
|
||||||
|
while (i < width) { buf[i++] = padc; }
|
||||||
|
// Add negative sign
|
||||||
|
if (negative) { buf[i++] = '-'; }
|
||||||
|
|
||||||
|
// Funny arrow
|
||||||
|
while (i --> 0) { outfn(buf[i], arg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _fmtFloat(void (*outfn)(char c, void* arg), void* arg, double f) {
|
||||||
|
int whole = (int)f;
|
||||||
|
double frac = _fabs(f - whole);
|
||||||
|
int decPlaces = 6;
|
||||||
|
|
||||||
|
// Add negative sign
|
||||||
|
if (f < 0) { outfn('-', arg); }
|
||||||
|
|
||||||
|
// Print whole part
|
||||||
|
_fmtInt(outfn, arg, whole, 10, 0, ' ');
|
||||||
|
|
||||||
|
// Print decimal point
|
||||||
|
outfn('.', arg);
|
||||||
|
|
||||||
|
// Format fractional part
|
||||||
|
for (int i = 0; i < decPlaces; i++) {
|
||||||
|
frac *= 10;
|
||||||
|
int digit = (int)frac;
|
||||||
|
outfn('0' + digit, arg);
|
||||||
|
frac -= digit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void _dynamicPutc(char c, void* arg) {
|
static void _dynamicPutc(char c, void* arg) {
|
||||||
printfEnv_t* env = (printfEnv_t*)arg;
|
printfEnv_t* env = (printfEnv_t*)arg;
|
||||||
if (!env->buf) { return; }
|
if (!env->buf) { return; }
|
||||||
@@ -40,8 +92,67 @@ static void _staticPutc(char c, void* arg) {
|
|||||||
|
|
||||||
/* Impementation */
|
/* Impementation */
|
||||||
int vpprintf(void (*outfn)(char c, void* arg), void* arg, const char* fmt, va_list va) {
|
int vpprintf(void (*outfn)(char c, void* arg), void* arg, const char* fmt, va_list va) {
|
||||||
// TODO
|
int i = 0;
|
||||||
return -1;
|
|
||||||
|
while (fmt[i] != '\0') {
|
||||||
|
if (fmt[i] != '%') { // Just print the character
|
||||||
|
outfn(fmt[i++], arg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++; // Consume the %
|
||||||
|
if (fmt[i] == '\0') { // End of string
|
||||||
|
outfn('%', arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parse fmt string
|
||||||
|
int width = 0;
|
||||||
|
char pad = ' ';
|
||||||
|
|
||||||
|
// Check for zero pad and parse width
|
||||||
|
if (isdigit(fmt[i])) {
|
||||||
|
if (fmt[i] == '0') { pad = '0'; i++; }
|
||||||
|
|
||||||
|
while (isdigit(fmt[i])) { // Parse width
|
||||||
|
width *= 10;
|
||||||
|
width += fmt[i++] - '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse specifier
|
||||||
|
switch (fmt[i]) {
|
||||||
|
case 'c': { // Character
|
||||||
|
char c = va_arg(va, char);
|
||||||
|
outfn(c, arg);
|
||||||
|
break;
|
||||||
|
} case 's': { // String
|
||||||
|
char* s = va_arg(va, char*);
|
||||||
|
while (*s) { outfn(*s++, arg); }
|
||||||
|
break;
|
||||||
|
} case 'd': { // Decimal number
|
||||||
|
int d = va_arg(va, int);
|
||||||
|
_fmtInt(outfn, arg, d, 10, width, pad);
|
||||||
|
break;
|
||||||
|
} case 'x': { // Hex number
|
||||||
|
int x = va_arg(va, int);
|
||||||
|
_fmtInt(outfn, arg, x, 16, width, pad);
|
||||||
|
break;
|
||||||
|
} case 'f': { // Float
|
||||||
|
double f = va_arg(va, double);
|
||||||
|
_fmtFloat(outfn, arg, f);
|
||||||
|
break;
|
||||||
|
} default: {
|
||||||
|
outfn(fmt[i], arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vsnprintf(char* str, size_t size, const char* fmt, va_list va) {
|
int vsnprintf(char* str, size_t size, const char* fmt, va_list va) {
|
||||||
|
|||||||
Reference in New Issue
Block a user