From db97135880d7c39618fbc7b41804d065c073305c Mon Sep 17 00:00:00 2001 From: catfood Date: Sat, 7 Jan 2023 10:25:27 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=A8printf=E7=9A=84=E6=95=B4?= =?UTF-8?q?=E5=9E=8B=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/kprintf.c | 6 +++-- lib/printfmt.c | 71 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/lib/kprintf.c b/lib/kprintf.c index d9efc57..6ac9651 100644 --- a/lib/kprintf.c +++ b/lib/kprintf.c @@ -6,18 +6,20 @@ #include "tty.h" #include "serialport.h" -static void serialputch(int ch, void *cnt) +static void serialputch(int ch, int *cnt) { // write_serial(ch); char _ch = ch; tty_write(cur_ntty, &_ch, 1); + (*cnt)++; } int vkprintf(const char *fmt, va_list ap) { // vprintfmt((void*)kprintfputch, NULL, fmt, ap); - vprintfmt((void *)serialputch, NULL, fmt, ap); + int cnt = 0; + vprintfmt((void *)serialputch, &cnt, fmt, ap); return 0; } diff --git a/lib/printfmt.c b/lib/printfmt.c index aa39cd0..6b45178 100644 --- a/lib/printfmt.c +++ b/lib/printfmt.c @@ -24,17 +24,39 @@ printnum(void (*putch)(int, void*), void *putdat, putch("0123456789abcdef"[num % base], putdat); } +static void +printnumupper(void (*putch)(int, void*), void *putdat, + unsigned long num, unsigned base, int width, int padc) +{ + // first recursively print all preceding (more significant) digits + if (num >= base) { + printnumupper(putch, putdat, num / base, base, width - 1, padc); + } else { + // print any needed pad characters before first digit + while (--width > 0) + putch(padc, putdat); + } + + // then print this (the least significant) digit + putch("0123456789ABCDEF"[num % base], putdat); +} + // Get an unsigned int of various possible sizes from a varargs list, // depending on the lflag parameter. static unsigned long long getuint(va_list *ap, int lflag) { - if (lflag >= 2) + switch (lflag) + { + case 2: return va_arg(*ap, unsigned long long); - else if (lflag) + case 1: return va_arg(*ap, unsigned long); - else + case 0: return va_arg(*ap, unsigned int); + default: + return va_arg(*ap, unsigned int); + } } // Same as getuint but signed - can't use getuint @@ -42,12 +64,17 @@ getuint(va_list *ap, int lflag) static long long getint(va_list *ap, int lflag) { - if (lflag >= 2) + switch (lflag) + { + case 2: return va_arg(*ap, long long); - else if (lflag) + case 1: return va_arg(*ap, long); - else + case 0: return va_arg(*ap, int); + default: + return va_arg(*ap, int); + } } // Main function to format and print a string. @@ -128,7 +155,10 @@ vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap) case 'l': lflag++; goto reswitch; - + // short flag, though auto promotion will be executed + case 'h': + lflag--; + goto reswitch; // character case 'c': putch(va_arg(ap, int), putdat); @@ -151,7 +181,7 @@ vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap) break; // (signed) decimal - case 'd': + case 'd': case 'i': num = getint(&ap, lflag); if ((long long) num < 0) { putch('-', putdat); @@ -169,11 +199,16 @@ vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap) // (unsigned) octal case 'o': // Replace this with your code. - putch('X', putdat); - putch('X', putdat); - putch('X', putdat); + num = getuint(&ap, lflag); + base = 8; + goto number; + break; + // binary, non-standard ext + case 'b': + num = getuint(&ap, lflag); + base = 2; + goto number; break; - // pointer case 'p': putch('0', putdat); @@ -182,7 +217,11 @@ vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap) (uintptr_t) va_arg(ap, void *); base = 16; goto number; - + case 'X': + num = getuint(&ap, lflag); + base = 16; + printnumupper(putch, putdat, num, base, width, padc); + break; // (unsigned) hexadecimal case 'x': num = getuint(&ap, lflag); @@ -190,7 +229,11 @@ vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap) number: printnum(putch, putdat, num, base, width, padc); break; - + case 'n': { + int * nptr = (int *)va_arg(ap, void *); + *nptr = *(int*)putdat; + break; + } // escaped '%' character case '%': putch(ch, putdat);