补全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 "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;
}

View File

@ -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);