补全printf的整型支持

This commit is contained in:
catfood 2023-01-07 10:25:27 +08:00
parent a389dcf93a
commit db97135880
2 changed files with 61 additions and 16 deletions

View File

@ -6,18 +6,20 @@
#include "tty.h" #include "tty.h"
#include "serialport.h" #include "serialport.h"
static void serialputch(int ch, void *cnt) static void serialputch(int ch, int *cnt)
{ {
// write_serial(ch); // write_serial(ch);
char _ch = ch; char _ch = ch;
tty_write(cur_ntty, &_ch, 1); tty_write(cur_ntty, &_ch, 1);
(*cnt)++;
} }
int vkprintf(const char *fmt, va_list ap) int vkprintf(const char *fmt, va_list ap)
{ {
// vprintfmt((void*)kprintfputch, NULL, fmt, ap); // vprintfmt((void*)kprintfputch, NULL, fmt, ap);
vprintfmt((void *)serialputch, NULL, fmt, ap); int cnt = 0;
vprintfmt((void *)serialputch, &cnt, fmt, ap);
return 0; return 0;
} }

View File

@ -24,17 +24,39 @@ printnum(void (*putch)(int, void*), void *putdat,
putch("0123456789abcdef"[num % base], 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, // Get an unsigned int of various possible sizes from a varargs list,
// depending on the lflag parameter. // depending on the lflag parameter.
static unsigned long long static unsigned long long
getuint(va_list *ap, int lflag) getuint(va_list *ap, int lflag)
{ {
if (lflag >= 2) switch (lflag)
{
case 2:
return va_arg(*ap, unsigned long long); return va_arg(*ap, unsigned long long);
else if (lflag) case 1:
return va_arg(*ap, unsigned long); return va_arg(*ap, unsigned long);
else case 0:
return va_arg(*ap, unsigned int); return va_arg(*ap, unsigned int);
default:
return va_arg(*ap, unsigned int);
}
} }
// Same as getuint but signed - can't use getuint // Same as getuint but signed - can't use getuint
@ -42,12 +64,17 @@ getuint(va_list *ap, int lflag)
static long long static long long
getint(va_list *ap, int lflag) getint(va_list *ap, int lflag)
{ {
if (lflag >= 2) switch (lflag)
{
case 2:
return va_arg(*ap, long long); return va_arg(*ap, long long);
else if (lflag) case 1:
return va_arg(*ap, long); return va_arg(*ap, long);
else case 0:
return va_arg(*ap, int); return va_arg(*ap, int);
default:
return va_arg(*ap, int);
}
} }
// Main function to format and print a string. // 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': case 'l':
lflag++; lflag++;
goto reswitch; goto reswitch;
// short flag, though auto promotion will be executed
case 'h':
lflag--;
goto reswitch;
// character // character
case 'c': case 'c':
putch(va_arg(ap, int), putdat); putch(va_arg(ap, int), putdat);
@ -151,7 +181,7 @@ vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap)
break; break;
// (signed) decimal // (signed) decimal
case 'd': case 'd': case 'i':
num = getint(&ap, lflag); num = getint(&ap, lflag);
if ((long long) num < 0) { if ((long long) num < 0) {
putch('-', putdat); putch('-', putdat);
@ -169,11 +199,16 @@ vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap)
// (unsigned) octal // (unsigned) octal
case 'o': case 'o':
// Replace this with your code. // Replace this with your code.
putch('X', putdat); num = getuint(&ap, lflag);
putch('X', putdat); base = 8;
putch('X', putdat); goto number;
break;
// binary, non-standard ext
case 'b':
num = getuint(&ap, lflag);
base = 2;
goto number;
break; break;
// pointer // pointer
case 'p': case 'p':
putch('0', putdat); 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 *); (uintptr_t) va_arg(ap, void *);
base = 16; base = 16;
goto number; goto number;
case 'X':
num = getuint(&ap, lflag);
base = 16;
printnumupper(putch, putdat, num, base, width, padc);
break;
// (unsigned) hexadecimal // (unsigned) hexadecimal
case 'x': case 'x':
num = getuint(&ap, lflag); num = getuint(&ap, lflag);
@ -190,7 +229,11 @@ vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap)
number: number:
printnum(putch, putdat, num, base, width, padc); printnum(putch, putdat, num, base, width, padc);
break; break;
case 'n': {
int * nptr = (int *)va_arg(ap, void *);
*nptr = *(int*)putdat;
break;
}
// escaped '%' character // escaped '%' character
case '%': case '%':
putch(ch, putdat); putch(ch, putdat);