diff options
-rw-r--r-- | kernel/include/lib/kio.h | 17 | ||||
-rw-r--r-- | kernel/include/lib/klib.h | 9 | ||||
-rw-r--r-- | kernel/lib/kprintf.c | 70 | ||||
-rw-r--r-- | kernel/lib/panic.c | 3 | ||||
-rw-r--r-- | user/include/stdio.h | 101 | ||||
-rw-r--r-- | user/lib/printf.c | 122 |
6 files changed, 231 insertions, 91 deletions
diff --git a/kernel/include/lib/kio.h b/kernel/include/lib/kio.h index 652a85b..ef22f95 100644 --- a/kernel/include/lib/kio.h +++ b/kernel/include/lib/kio.h @@ -31,8 +31,9 @@ void kputs(const char *s); * * @param format - the format string * @param ... - variable args for the format + * @returns number of bytes written */ -__attribute__((format(printf, 1, 2))) void kprintf(const char *format, ...); +__attribute__((format(printf, 1, 2))) int kprintf(const char *format, ...); /** * prints out a formatted string to a buffer @@ -42,7 +43,7 @@ __attribute__((format(printf, 1, 2))) void kprintf(const char *format, ...); * @param ... - variable args for the format * @returns number of bytes written */ -__attribute__((format(printf, 2, 3))) size_t ksprintf(char *restrict s, +__attribute__((format(printf, 2, 3))) int ksprintf(char *restrict s, const char *format, ...); /** @@ -53,8 +54,9 @@ __attribute__((format(printf, 2, 3))) size_t ksprintf(char *restrict s, * @param format - the format string * @param ... - variable args for the format * @returns number of bytes written + * @returns number of bytes that would of been written (past maxlen) */ -__attribute__((format(printf, 3, 4))) size_t ksnprintf(char *restrict s, +__attribute__((format(printf, 3, 4))) int ksnprintf(char *restrict s, size_t maxlen, const char *format, ...); @@ -63,8 +65,9 @@ __attribute__((format(printf, 3, 4))) size_t ksnprintf(char *restrict s, * * @param format - the format string * @param args - variable arg list for the format + * @returns number of bytes written */ -void kvprintf(const char *format, va_list args); +int kvprintf(const char *format, va_list args); /** * prints out a formatted string to a buffer @@ -74,7 +77,7 @@ void kvprintf(const char *format, va_list args); * @param args - variable arg list for the format * @returns number of bytes written */ -size_t kvsprintf(char *restrict s, const char *format, va_list args); +int kvsprintf(char *restrict s, const char *format, va_list args); /** * prints out a formatted string to a buffer with a given max length @@ -83,9 +86,9 @@ size_t kvsprintf(char *restrict s, const char *format, va_list args); * @param maxlen - the max len of the buffer * @param format - the format string * @param args - variable arg list for the format - * @returns number of bytes written + * @returns number of bytes that would of been written (past maxlen) */ -size_t kvsnprintf(char *restrict s, size_t maxlen, const char *format, +int kvsnprintf(char *restrict s, size_t maxlen, const char *format, va_list args); #endif /* kio.h */ diff --git a/kernel/include/lib/klib.h b/kernel/include/lib/klib.h index 3afe925..cb1de01 100644 --- a/kernel/include/lib/klib.h +++ b/kernel/include/lib/klib.h @@ -185,13 +185,20 @@ char *btoa(size_t bytes, char *buf); */ unsigned int bound(unsigned int min, unsigned int value, unsigned int max); +#define __PANIC_STR(x) __PANIC_STR2(x) +#define __PANIC_STR2(x) #x + +#define panic(...) __panic(__PANIC_STR(__LINE__), __FILE__, __VA_ARGS__) +#define assert(val, ...) do { if (!(val)) { panic(__VA_ARGS__); } } while (0) + /** * Abort the kernel with a given message. * * @param format - the format string * @param ... - variable args for the format */ -__attribute__((noreturn)) void panic(const char *format, ...); +__attribute__((noreturn, format(printf, 3, 4))) +void __panic(const char *line, const char *file, const char *format, ...); /** * Fill dst with a stack trace consisting of return addresses in order diff --git a/kernel/lib/kprintf.c b/kernel/lib/kprintf.c index 552b923..aabefc4 100644 --- a/kernel/lib/kprintf.c +++ b/kernel/lib/kprintf.c @@ -71,6 +71,7 @@ typedef struct { /* output */ size_t written_len; + size_t possible_written_len; bool sprintf; char *sprintf_buf; @@ -80,6 +81,8 @@ typedef struct { static void printf_putc(context_t *ctx, char c) { + ctx->possible_written_len++; + // bounds check if (ctx->has_max_len) if (ctx->written_len >= ctx->max_len) @@ -348,9 +351,11 @@ static void handle_string_specifier(context_t *ctx, options_t *opts, data_t data) { char *str = data.str; - int str_len = 0; + if (str == NULL) + str = "(null)"; // get length of string + int str_len = 0; if (opts->precision_set) str_len = opts->precision; else @@ -486,6 +491,13 @@ static void do_printf(context_t *ctx, va_list args) case 's': handle_string_specifier(ctx, &opts, data); break; + // very terrible why in the love of FUCKING GOD would you do this + // but its in printf so im adding it for you fucks + case 'n': { + size_t *bad = va_arg(args, size_t *); + *bad = ctx->written_len; + break; + } // unknown default: // print from % to current @@ -494,73 +506,83 @@ static void do_printf(context_t *ctx, va_list args) break; } } + + // add \0 on sprintf + if (ctx->sprintf) { + int len, plen; + len = ctx->written_len; + plen = ctx->possible_written_len; + printf_putc(ctx, '\0'); + ctx->written_len = len; + ctx->possible_written_len = plen; + } } -void kprintf(const char *format, ...) +int kprintf(const char *format, ...) { va_list args; + int len; + va_start(args, format); - kvprintf(format, args); + len = kvprintf(format, args); va_end(args); + return len; } -size_t ksprintf(char *restrict s, const char *format, ...) +int ksprintf(char *restrict s, const char *format, ...) { va_list args; - size_t amt; + int len; + va_start(args, format); - amt = kvsprintf(s, format, args); + len = kvsprintf(s, format, args); va_end(args); - return amt; + return len; } -size_t snprintf(char *restrict s, size_t maxlen, const char *format, ...) +int snprintf(char *restrict s, size_t maxlen, const char *format, ...) { va_list args; - size_t amt; + int len; + va_start(args, format); - amt = kvsnprintf(s, maxlen, format, args); + len = kvsnprintf(s, maxlen, format, args); va_end(args); - return amt; + return len; } -void kvprintf(const char *format, va_list args) +int kvprintf(const char *format, va_list args) { - // create context context_t ctx = { 0 }; ctx.format = format; - // print + do_printf(&ctx, args); + return ctx.written_len; } -size_t kvsprintf(char *restrict s, const char *format, va_list args) +int kvsprintf(char *restrict s, const char *format, va_list args) { - // create context context_t ctx = { 0 }; ctx.format = format; - // sprintf buffer ctx.sprintf_buf = s; ctx.sprintf = 1; - // print + do_printf(&ctx, args); return ctx.written_len; } -size_t kvsnprintf(char *restrict s, size_t maxlen, const char *format, +int kvsnprintf(char *restrict s, size_t maxlen, const char *format, va_list args) { - // create context context_t ctx = { 0 }; ctx.format = format; - // sprintf buffer ctx.sprintf_buf = s; ctx.sprintf = 1; - // sprintf max_len ctx.has_max_len = 1; ctx.max_len = maxlen; - // print + do_printf(&ctx, args); - return ctx.written_len; + return ctx.possible_written_len; } void kputc(char c) diff --git a/kernel/lib/panic.c b/kernel/lib/panic.c index d3db908..486f4b5 100644 --- a/kernel/lib/panic.c +++ b/kernel/lib/panic.c @@ -3,12 +3,13 @@ #include <stdarg.h> #include <comus/asm.h> -__attribute__((noreturn)) void panic(const char *format, ...) +__attribute__((noreturn)) void __panic(const char *line, const char *file, const char *format, ...) { cli(); va_list list; va_start(list, format); kprintf("\n\n!!! PANIC !!!\n"); + kprintf("In file %s at line %s:\n", file, line); kvprintf(format, list); kprintf("\n\n"); log_backtrace(); diff --git a/user/include/stdio.h b/user/include/stdio.h index 9e60f55..0994589 100644 --- a/user/include/stdio.h +++ b/user/include/stdio.h @@ -12,6 +12,12 @@ #include <stdarg.h> #include <stddef.h> +#define EOF (-1) + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + // TODO: implement typedef void FILE; @@ -24,39 +30,53 @@ extern FILE *stdout; * Prints out a char * * @param c - the char + * @returns the character written or EOF on failure */ -extern void putc(char c); +extern int putchar(int c); /** - * Prints out a null terminated string + * Prints out a char to a stream * - * @param s - the string + * @param c - the char + * @param stream - the stream to print to + * @returns the character written or EOF on failure */ -extern void puts(const char *s); +extern int putc(int c, FILE *stream); /** - * Prints out a char + * Prints out a char to a stream * - * @param stream - stream to write to * @param c - the char + * @param stream - stream to write to + * @returns the character written or EOF on failure + */ +extern int fputc(int c, FILE *stream); + +/** + * Prints out a null terminated string with newline + * + * @param str - the string + * @returns nonnegative integer on success, EOF on error */ -extern void fputc(FILE *stream, char c); +extern int puts(const char *str); /** * Prints out a null terminated string * + * @param str - the string * @param stream - stream to write to - * @param s - the string + * @returns nonnegative integer on success, EOF on error */ -extern void fputs(FILE *stream, const char *s); +extern int fputs(const char *str, FILE *stream); /** * prints out a formatted string * * @param format - the format string * @param ... - variable args for the format + * @returns number of bytes written */ -__attribute__((format(printf, 1, 2))) extern void printf(const char *format, +__attribute__((format(printf, 1, 2))) extern int printf(const char *format, ...); /** @@ -67,7 +87,7 @@ __attribute__((format(printf, 1, 2))) extern void printf(const char *format, * @param ... - variable args for the format * @returns number of bytes written */ -__attribute__((format(printf, 2, 3))) extern size_t +__attribute__((format(printf, 2, 3))) extern int sprintf(char *restrict s, const char *format, ...); /** @@ -77,9 +97,9 @@ sprintf(char *restrict s, const char *format, ...); * @param maxlen - the max len of the buffer * @param format - the format string * @param ... - variable args for the format - * @returns number of bytes written + * @returns number of bytes that would of been written (past maxlen) */ -__attribute__((format(printf, 3, 4))) extern size_t +__attribute__((format(printf, 3, 4))) extern int snprintf(char *restrict s, size_t maxlen, const char *format, ...); /** @@ -87,8 +107,9 @@ snprintf(char *restrict s, size_t maxlen, const char *format, ...); * * @param format - the format string * @param args - variable arg list for the format + * @returns number of bytes written */ -extern void vprintf(const char *format, va_list args); +extern int vprintf(const char *format, va_list args); /** * prints out a formatted string to a buffer @@ -98,7 +119,7 @@ extern void vprintf(const char *format, va_list args); * @param args - variable arg list for the format * @returns number of bytes written */ -extern size_t vsprintf(char *restrict s, const char *format, va_list args); +extern int vsprintf(char *restrict s, const char *format, va_list args); /** * prints out a formatted string to a buffer with a given max length @@ -107,9 +128,9 @@ extern size_t vsprintf(char *restrict s, const char *format, va_list args); * @param maxlen - the max len of the buffer * @param format - the format string * @param args - variable arg list for the format - * @returns number of bytes written + * @returns number of bytes that would of been written (past maxlen) */ -extern size_t vsnprintf(char *restrict s, size_t maxlen, const char *format, +extern int vsnprintf(char *restrict s, size_t maxlen, const char *format, va_list args); /** @@ -135,9 +156,20 @@ extern void vfprintf(FILE *stream, const char *format, va_list args); * opens a file with a given file name * * @param filename - the name of the file to open + * @param modes - the modes to open the file in * @returns the file pointer of success, NULL on error */ -extern FILE *fopen(const char *filename); +extern FILE *fopen(const char *restrict filename, const char *restrict modes); + +/** + * opens a file with a given file name, replacing en existing stream with it + * + * @param filename - the name of the file to open + * @param modes - the modes to open the file in + * @param stream - the stream to replace + * @returns the file pointer of success, NULL on error + */ +extern FILE *freopen(const char *restrict filename, const char *restrict modes, FILE *restrict stream); /** * closes a opened file @@ -148,22 +180,49 @@ extern void fclose(FILE *stream); /** * reads data from a file into a pointer + * * @param ptr - the buffer to write into * @param size - the size of the block to read * @param n - the count of blocks to read * @param stream - the file stream to read from * @returns the number of blocks read */ -extern size_t fread(void *ptr, size_t size, size_t n, FILE *stream); +extern size_t fread(void *restrict ptr, size_t size, size_t n, FILE *restrict stream); /** - * writes data from a pointer into a file + * writes data from a pointer into a filename + * * @param ptr - the buffer to read from * @param size - the size of the block to write * @param n - the count of blocks to write * @param stream - the file stream to write into * @returns the number of blocks written */ -extern size_t fwrite(void *ptr, size_t size, size_t n, FILE *stream); +extern size_t fwrite(const void *restrict ptr, size_t size, size_t n, FILE *restrict stream); + +/** + * seek to a certain position on stream + * + * @param stream - the stream to seek + * @param off - the offset from whence + * @param whence - where to seek from (SEEK_SET, SEEK_CUR, SEEK_END) + * @returns 0 on success, -1 on error setting errno + */ +extern int fseek(FILE *stream, long int off, int whence); + +/** + * return the current position of stream + * + * @param stream - the stream to tell + * @return the position on success, -1 on error setting errno + */ +extern long int ftell(FILE *stream); + +/** + * rewing to the begining of a stream + * + * @param stream - the stream to rewind + */ +extern void rewind(FILE *stream); #endif /* stdio.h */ diff --git a/user/lib/printf.c b/user/lib/printf.c index 53f98a6..3b5c65f 100644 --- a/user/lib/printf.c +++ b/user/lib/printf.c @@ -4,6 +4,7 @@ #include <stdbool.h> #include <string.h> #include <stdint.h> +#include <stdarg.h> #define PRINTF_NUMERIC_BUF_LEN 50 @@ -74,6 +75,7 @@ typedef struct { /* output */ size_t written_len; + size_t possible_written_len; bool to_file; union { FILE *file; @@ -86,6 +88,8 @@ typedef struct { static void printf_putc(context_t *ctx, char c) { + ctx->possible_written_len++; + // bounds check if (ctx->has_max_len) if (ctx->written_len >= ctx->max_len) @@ -93,7 +97,7 @@ static void printf_putc(context_t *ctx, char c) // write to correct if (ctx->to_file) - fputc(ctx->out.file, c); + fputc(c, ctx->out.file); else *(ctx->out.buf++) = c; @@ -354,9 +358,11 @@ static void handle_string_specifier(context_t *ctx, options_t *opts, data_t data) { char *str = data.str; - int str_len = 0; + if (str == NULL) + str = "(null)"; // get length of string + int str_len = 0; if (opts->precision_set) str_len = opts->precision; else @@ -492,6 +498,13 @@ static void do_printf(context_t *ctx, va_list args) case 's': handle_string_specifier(ctx, &opts, data); break; + // very terrible why in the love of FUCKING GOD would you do this + // but its in printf so im adding it for you fucks + case 'n': { + size_t *bad = va_arg(args, size_t *); + *bad = ctx->written_len; + break; + } // unknown default: // print from % to current @@ -500,103 +513,138 @@ static void do_printf(context_t *ctx, va_list args) break; } } + + // add \0 on sprintf + if (ctx->to_file == 0) { + int len, plen; + len = ctx->written_len; + plen = ctx->possible_written_len; + printf_putc(ctx, '\0'); + ctx->written_len = len; + ctx->possible_written_len = plen; + } } -void printf(const char *format, ...) +int printf(const char *format, ...) { va_list args; + int len; + va_start(args, format); - vprintf(format, args); + len = vprintf(format, args); va_end(args); + return len; } -size_t sprintf(char *restrict s, const char *format, ...) +int sprintf(char *restrict s, const char *format, ...) { va_list args; - size_t amt; + int len; + va_start(args, format); - amt = vsprintf(s, format, args); + len = vsprintf(s, format, args); va_end(args); - return amt; + return len; } -size_t snprintf(char *restrict s, size_t maxlen, const char *format, ...) +int snprintf(char *restrict s, size_t maxlen, const char *format, ...) { va_list args; - size_t amt; + int len; + va_start(args, format); - amt = vsnprintf(s, maxlen, format, args); + len = vsnprintf(s, maxlen, format, args); va_end(args); - return amt; + return len; } -void vprintf(const char *format, va_list args) +int vprintf(const char *format, va_list args) { - vfprintf(stdout, format, args); + return vfprintf(stdout, format, args); } -size_t vsprintf(char *restrict s, const char *format, va_list args) +int vsprintf(char *restrict s, const char *format, va_list args) { - // create context context_t ctx = { 0 }; ctx.format = format; - // sprintf buffer ctx.out.buf = s; ctx.to_file = 0; - // print + do_printf(&ctx, args); return ctx.written_len; } -size_t vsnprintf(char *restrict s, size_t maxlen, const char *format, +int vsnprintf(char *restrict s, size_t maxlen, const char *format, va_list args) { - // create context context_t ctx = { 0 }; ctx.format = format; - // sprintf buffer ctx.out.buf = s; ctx.to_file = 0; - // sprintf max_len ctx.has_max_len = 1; ctx.max_len = maxlen; - // print + do_printf(&ctx, args); - return ctx.written_len; + return ctx.possible_written_len; } -void fprintf(FILE *stream, const char *format, ...) +int fprintf(FILE *stream, const char *format, ...) { va_list args; + int len; + va_start(args, format); - vfprintf(stream, format, args); + len = vfprintf(stream, format, args); va_end(args); + return len; } -void vfprintf(FILE *stream, const char *format, va_list args) +int vfprintf(FILE *stream, const char *format, va_list args) { - // create context context_t ctx = { 0 }; ctx.format = format; - // fprintf stream ctx.out.file = stream; ctx.to_file = 1; - // print + do_printf(&ctx, args); + return ctx.written_len; } -void putc(char c) +int putchar(int c) { - fputc(stdout, c); + return putc(c, stdout); } -void puts(const char *str) +int putc(int c, FILE *stream) { - fputs(stdout, str); + return fputc(c, stream); } -void fputs(FILE *stream, const char *s) +int fputc(int c, FILE *stream) { - while (*s) - fputc(stream, *s++); + // TODO: a + return c; +} + +int puts(const char *str) +{ + int res; + res = fputs(str, stdout); + if (res == EOF) + return res; + res = fputc('\n', stdout); + if (res == EOF) + return res; + return 0; +} + +int fputs(const char *str, FILE *stream) +{ + int res; + while (*str) { + res = fputc(*str++, stream); + if (res == EOF) + return res; + } + return 0; } |