X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=bootcensus;a=blobdiff_plain;f=src%2Flibc%2Fstdio.c;h=1f12fd696ba64aa17f623a72f03274bdecfd7b25;hp=449a5aa610317d5e9f5412a9d947cfddd0cbdd8c;hb=81c11bdd80190ec319a82b0402173cfb65fcbf72;hpb=97356e29f73e12f0856fde92a48e86c73bef387c diff --git a/src/libc/stdio.c b/src/libc/stdio.c index 449a5aa..1f12fd6 100644 --- a/src/libc/stdio.c +++ b/src/libc/stdio.c @@ -1,6 +1,6 @@ /* pcboot - bootable PC demo/game kernel -Copyright (C) 2018 John Tsiombikas +Copyright (C) 2018-2019 John Tsiombikas This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,12 +18,24 @@ along with this program. If not, see . #include #include #include +#include #include "contty.h" +#include "serial.h" +#include "panic.h" + +enum { + OUT_DEF, + OUT_BUF, + OUT_SCR, + OUT_SER +}; extern void pcboot_putchar(int c); -static void bwrite(char *buf, size_t buf_sz, char *str, int sz); -static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap); +static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap); +static int intern_scanf(const char *instr, FILE *infile, const char *fmt, va_list ap); +static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz); +/*static int readchar(const char *str, FILE *fp);*/ int putchar(int c) { @@ -42,24 +54,20 @@ int puts(const char *s) /* -- printf and friends -- */ -static char *convc = "dioxXucsfeEgGpn%"; - -#define IS_CONV(c) strchr(convc, c) - int printf(const char *fmt, ...) { int res; va_list ap; va_start(ap, fmt); - res = intern_printf(0, 0, fmt, ap); + res = intern_printf(OUT_DEF, 0, 0, fmt, ap); va_end(ap); return res; } int vprintf(const char *fmt, va_list ap) { - return intern_printf(0, 0, fmt, ap); + return intern_printf(OUT_DEF, 0, 0, fmt, ap); } int sprintf(char *buf, const char *fmt, ...) @@ -68,14 +76,14 @@ int sprintf(char *buf, const char *fmt, ...) va_list ap; va_start(ap, fmt); - res = intern_printf(buf, 0, fmt, ap); + res = intern_printf(OUT_BUF, buf, 0, fmt, ap); va_end(ap); return res; } int vsprintf(char *buf, const char *fmt, va_list ap) { - return intern_printf(buf, 0, fmt, ap); + return intern_printf(OUT_BUF, buf, 0, fmt, ap); } int snprintf(char *buf, size_t sz, const char *fmt, ...) @@ -84,16 +92,57 @@ int snprintf(char *buf, size_t sz, const char *fmt, ...) va_list ap; va_start(ap, fmt); - res = intern_printf(buf, sz, fmt, ap); + res = intern_printf(OUT_BUF, buf, sz, fmt, ap); va_end(ap); return res; } int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap) { - return intern_printf(buf, sz, fmt, ap); + return intern_printf(OUT_BUF, buf, sz, fmt, ap); +} + +int fprintf(FILE *fp, const char *fmt, ...) +{ + int res; + va_list ap; + + va_start(ap, fmt); + res = vfprintf(fp, fmt, ap); + va_end(ap); + return res; +} + +int vfprintf(FILE *fp, const char *fmt, va_list ap) +{ + if(fp == stdout || fp == stderr) { + return vprintf(fmt, ap); + } + + panic("*fprintf for anything other than stdout/stderr, not implemented yet\n"); + return 0; } +int ser_printf(const char *fmt, ...) +{ + int res; + va_list ap; + + va_start(ap, fmt); + res = intern_printf(OUT_SER, 0, 0, fmt, ap); + va_end(ap); + return res; +} + +int ser_vprintf(const char *fmt, va_list ap) +{ + return intern_printf(OUT_SER, 0, 0, fmt, ap); +} + +void perror(const char *s) +{ + printf("%s: %s\n", s, strerror(errno)); +} /* intern_printf provides all the functionality needed by all the printf * variants. @@ -104,11 +153,14 @@ int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap) * by the (v)snprintf variants to avoid buffer overflows. * The rest are obvious, format string and variable argument list. */ +static char *convc = "dioxXucsfeEgGpn%"; + +#define IS_CONV(c) strchr(convc, c) #define BUF(x) ((x) ? (x) + cnum : (x)) #define SZ(x) ((x) ? (x) - cnum : (x)) -static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap) +static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap) { char conv_buf[32]; char *str; @@ -122,9 +174,10 @@ static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap) int fwidth = 0; int padc = ' '; int sign = 0; - int left_align = 0; /* not implemented yet */ + int left_align = 0; int hex_caps = 0; int unsig = 0; + int num, unum; while(*fmt) { if(*fmt == '%') { @@ -143,7 +196,8 @@ static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap) base = 16; if(alt) { - bwrite(BUF(buf), SZ(sz), "0x", 2); + bwrite(out, BUF(buf), SZ(sz), "0x", 2); + cnum += 2; } case 'u': @@ -154,16 +208,19 @@ static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap) base = 8; if(alt) { - bwrite(BUF(buf), SZ(sz), "0", 1); + bwrite(out, BUF(buf), SZ(sz), "0", 1); + cnum++; } } case 'd': case 'i': if(unsig) { - utoa(va_arg(ap, unsigned int), conv_buf, base); + unum = va_arg(ap, unsigned int); + utoa(unum, conv_buf, base); } else { - itoa(va_arg(ap, int), conv_buf, base); + num = va_arg(ap, int); + itoa(num, conv_buf, base); } if(hex_caps) { for(i=0; conv_buf[i]; i++) { @@ -172,19 +229,34 @@ static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap) } slen = strlen(conv_buf); + + if(left_align) { + if(!unsig && sign && num >= 0) { + bwrite(out, BUF(buf), SZ(sz), "+", 1); + cnum++; + } + bwrite(out, BUF(buf), SZ(sz), conv_buf, slen); + cnum += slen; + padc = ' '; + } for(i=slen; i= 0) { + bwrite(out, BUF(buf), SZ(sz), "+", 1); + cnum++; + } + bwrite(out, BUF(buf), SZ(sz), conv_buf, slen); + cnum += slen; + } break; case 'c': { char c = va_arg(ap, int); - bwrite(BUF(buf), SZ(sz), &c, 1); + bwrite(out, BUF(buf), SZ(sz), &c, 1); cnum++; } break; @@ -193,12 +265,19 @@ static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap) str = va_arg(ap, char*); slen = strlen(str); + if(left_align) { + bwrite(out, BUF(buf), SZ(sz), str, slen); + cnum += slen; + padc = ' '; + } for(i=slen; i