From 951eef6af6b0fbcdb764fa92e308d3e396ee3a59 Mon Sep 17 00:00:00 2001 From: bumbread Date: Tue, 19 Jul 2022 09:20:09 +1100 Subject: [PATCH] printf complete --- src/code/fmt/gen_fmt.h | 119 ++++++++++++++++++++++++++++++++++++++--- test/test_printf.c | 10 +++- todo | 1 + 3 files changed, 121 insertions(+), 9 deletions(-) diff --git a/src/code/fmt/gen_fmt.h b/src/code/fmt/gen_fmt.h index 81ce1a7..ff8146b 100644 --- a/src/code/fmt/gen_fmt.h +++ b/src/code/fmt/gen_fmt.h @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include @@ -250,7 +252,7 @@ static int pfx(vprintfcb)( case 'f': case 'F': case 'g': - case 'G': + case 'G': { if(*fmt == 'E' || *fmt == 'F' || *fmt == 'G') flags |= FLAG_UPPER; char conv = tolower(*fmt); ++fmt; @@ -283,7 +285,105 @@ static int pfx(vprintfcb)( } } if(w < 0) return -1; - break; + }break; + case 'c': { + ++fmt; + int ch; + if(flags & FLAG_LONG) { + ch = va_arg(va, wint_t); + } + else { + ch = va_arg(va, int); + } + int pad = width-1; + // Print width left-pad + if(!(flags & FLAG_LEFT) && !(flags & FLAG_ZERO)) while(pad-- > 0) { + out(' '); + } + out(ch); + // Print right-pad + if(flags & FLAG_LEFT) while(pad-- > 0) { + out(' '); + } + } break; + case 's': { + ++fmt; + char *str = NULL; + wchar_t *wstr = NULL; + int len = 0; + if(flags & FLAG_LONG) { + wstr = va_arg(va, wchar_t *); + wchar_t *s = wstr; + while(*s++!=0) ++len; + int pad = width - len; + // Print width left-pad + if(!(flags & FLAG_LEFT) && !(flags & FLAG_ZERO)) while(pad-- > 0) { + out(' '); + } + // Print string + mbstate_t ps = {0}; + for(int i = 0; i < len; ++i) { + if(sizeof(ctype) == 2) { + out(wstr[i]); + } + else { + char utf8[5]; + char *s = utf8; + size_t r = c16rtomb(s, wstr[i], &ps); + if(r == (size_t)(-1)) return -1; + if(r != 0) { + while(*s != 0) { + out(*s++); + } + } + } + } + // Print right-pad + if(flags & FLAG_LEFT) while(pad-- > 0) { + out(' '); + } + } + else { + str = va_arg(va, char *); + char *s = str; + if(flags & FLAG_PREC) { + while(*s++!=0 && len 0) { + out(' '); + } + // Print string + mbstate_t ps = {0}; + for(int i = 0; i < len; ++i) { + out(str[i]); + } + // Print right-pad + if(flags & FLAG_LEFT) while(pad-- > 0) { + out(' '); + } + } + } break; + case 'p': { + ++fmt; + void *ptr = va_arg(va, void *); + unsigned long long iptr = (unsigned long long)(uintptr_t)ptr; + w = pfx(_ntoa)(w, ctx, cb, 0, iptr, 16, 16, 0, FLAG_HASH); + if(w < 0) return -1; + } break; + case 'n': { + ++fmt; + int *p = va_arg(va, int *); + *p = w; + } break; + case '%': { + ++fmt; + out('%'); + } break; } } return w; @@ -345,7 +445,6 @@ static inline int pfx(_ntoa)( if(ndigits > prec) prec = ndigits; int num_len = pref_len + prec; int pad_len = width - num_len; - // Print left-pad due to width (TODO: zero pad should come after prefix?) if(!(flags & FLAG_LEFT)) { ctype pad_ch = ' '; if(flags & FLAG_ZERO) pad_ch = '0'; @@ -353,6 +452,10 @@ static inline int pfx(_ntoa)( out(pad_ch); } } + // Print width left-pad if it's made out of space + if(!(flags & FLAG_LEFT) && !(flags & FLAG_ZERO)) while(pad_len-- > 0) { + out(' '); + } // Print prefix if(flags & FLAG_HASH) { out('0'); @@ -362,6 +465,10 @@ static inline int pfx(_ntoa)( else if(neg) { out('-'); } else if(flags & FLAG_PLUS) { out('+'); } else if(flags & FLAG_SPACE) { out(' '); } + // Print width left-pad if it's made out of zero + if(!(flags & FLAG_LEFT) && (flags & FLAG_ZERO)) while(pad_len-- > 0) { + out('0'); + } // Print zero-pad due to precision for(int i = ndigits; i < prec; ++i) { out('0'); @@ -371,10 +478,8 @@ static inline int pfx(_ntoa)( out(digits[ndigits]); } // Print right-pad - if(flags & FLAG_LEFT) { - while(pad_len-- > 0) { - out(' '); - } + if(flags & FLAG_LEFT) while(pad_len-- > 0) { + out(' '); } return w; } diff --git a/test/test_printf.c b/test/test_printf.c index 39afd6d..b75fbde 100644 --- a/test/test_printf.c +++ b/test/test_printf.c @@ -4,7 +4,13 @@ #include int main() { - printf("%g\n", 1.2345e+10); - printf("%g\n", 123.45); + static char str[] = "XYabcZW"; + printf("|1234567890123|\n"); + printf("|%13s|\n", str); + printf("|%-13.9s|\n", str); + printf("|%13.10s|\n", str); + printf("|%13.11s|\n", str); + printf("|%13.15s|\n", &str[2]); + printf("|%13c|\n", str[5]); return 0; } diff --git a/todo b/todo index 9833d1b..95ff191 100644 --- a/todo +++ b/todo @@ -34,6 +34,7 @@ stdio.h: * Formatted scan * The float printing should include width specifiers * %g should use decimal exponent +* %s precision should specify how much characters to *write* stdlib.h: * Strtod base 16 must be correctly rounded