From bc1cc79225f0b006dd66d4fd81030d06f83bfca2 Mon Sep 17 00:00:00 2001 From: kvik Date: Fri, 19 Feb 2021 23:04:09 +0100 Subject: [PATCH] libstdio: sync bits of vfprintf from APE * Add the %ll length modifier, * Convert nil to "" under %s (not in APE), * Cast void* to uintptr under %p, * Use "0x" hex prefix under %p, * Fix manual page mentions of %P to %p, * Fix empty result for fp conversions, * Fix zero padding of left-aligned fp conversions, * Remove deprecated #pragma ref uses. Most of these were introduced in APE prior to 9front. I've omitted the %z conversion specifier since Plan 9 code rarely uses the usize type. This may need to be added later for the benefit of native ports of alien code. --- sys/man/2/fprintf | 29 +++++++++++++++++++++++-- sys/src/libstdio/vfprintf.c | 43 +++++++++++++++++++++++++------------ 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/sys/man/2/fprintf b/sys/man/2/fprintf index b7f616c33..abd7687f4 100644 --- a/sys/man/2/fprintf +++ b/sys/man/2/fprintf @@ -200,6 +200,22 @@ or .B long argument; an optional +.B ll +specifying that a following +.BR d , +.BR i , +.BR o , +.BR u , +.BR x , +or +.B X +conversion character applies to a +.B long long +or +.B unsigned +.B long long +argument; +an optional .B l specifying that a following .B n @@ -207,6 +223,14 @@ conversion specifier applies to a pointer to a .B long .B int argument; +an optional +.B ll +specifying that a following +.B n +conversion specifier applies to a pointer to a +.B long long +.B int +argument; or an optional .B L specifying that a following @@ -222,6 +246,7 @@ argument. If an .BR h , .BR l , +.BR ll , or .B L appears with any other conversion specifier, the behavior is undefined. @@ -459,7 +484,7 @@ zero value for the argument yields undefined results. .TP -.B P +.B p The .B void* argument is printed in an implementation-defined way (for Plan 9: @@ -487,7 +512,7 @@ If any argument is, or points to, a union or an aggregate conversion, or a pointer cast to be a pointer to .B void using -.B %P +.B %p conversion), the behavior is undefined. .PP In no case does a nonexistent or small field width cause truncation diff --git a/sys/src/libstdio/vfprintf.c b/sys/src/libstdio/vfprintf.c index 4600caff6..66069d8c0 100644 --- a/sys/src/libstdio/vfprintf.c +++ b/sys/src/libstdio/vfprintf.c @@ -17,6 +17,7 @@ #define LONG 64 /* 'l' convert a long integer */ #define LDBL 128 /* 'L' convert a long double */ #define PTR 256 /* convert a void * (%p) */ +#define VLONG 512 /* 'll' convert a long long integer */ static int lflag[] = { /* leading flags */ 0, 0, 0, 0, 0, 0, 0, 0, /* ^@ ^A ^B ^C ^D ^E ^F ^G */ @@ -148,7 +149,7 @@ QLock _stdiolk; int vfprintf(FILE *f, const char *s, va_list args) { - int flags, width, precision; + int tfl, flags, width, precision; qlock(&_stdiolk); @@ -187,7 +188,15 @@ vfprintf(FILE *f, const char *s, va_list args) } else precision = -1; - while(tflag[*s&_IO_CHMASK]) flags |= tflag[*s++&_IO_CHMASK]; + + while(tfl = tflag[*s&_IO_CHMASK]){ + if(tfl == LONG && (flags & LONG)){ + flags &= ~LONG; + tfl = VLONG; + } + flags |= tfl; + s++; + } if(ocvt[*s]) nprint += (*ocvt[*s++])(f, &args, flags, width, precision); else if(*s){ putc(*s++, f); @@ -208,9 +217,8 @@ vfprintf(FILE *f, const char *s, va_list args) } static int -ocvt_c(FILE *f, va_list *args, int flags, int width, int precision) +ocvt_c(FILE *f, va_list *args, int flags, int width, int) { -#pragma ref precision int i; if(!(flags&LEFT)) for(i=1; i= 0) for(i=0; i!=precision && s[i]; i++); @@ -257,15 +267,14 @@ ocvt_s(FILE *f, va_list *args, int flags, int width, int precision) } static int -ocvt_n(FILE *f, va_list *args, int flags, int width, int precision) +ocvt_n(FILE *, va_list *args, int flags, int, int) { -#pragma ref f -#pragma ref width -#pragma ref precision if(flags&SHORT) *va_arg(*args, short *) = nprint; else if(flags&LONG) *va_arg(*args, long *) = nprint; + else if(flags&VLONG) + *va_arg(*args, long long*) = nprint; else *va_arg(*args, int *) = nprint; return 0; @@ -288,14 +297,15 @@ ocvt_fixed(FILE *f, va_list *args, int flags, int width, int precision, char digits[128]; /* no reasonable machine will ever overflow this */ char *sign; char *dp; - long snum; - unsigned long num; + long long snum; + unsigned long long num; int nout, npad, nlzero; if(sgned){ - if(flags&PTR) snum = (long)va_arg(*args, void *); + if(flags&PTR) snum = (uintptr)va_arg(*args, void *); else if(flags&SHORT) snum = va_arg(*args, short); else if(flags&LONG) snum = va_arg(*args, long); + else if(flags&VLONG) snum = va_arg(*args, long long); else snum = va_arg(*args, int); if(snum < 0){ sign = "-"; @@ -308,9 +318,10 @@ ocvt_fixed(FILE *f, va_list *args, int flags, int width, int precision, } } else { sign = ""; - if(flags&PTR) num = (long)va_arg(*args, void *); + if(flags&PTR) num = (uintptr)va_arg(*args, void *); else if(flags&SHORT) num = va_arg(*args, unsigned short); else if(flags&LONG) num = va_arg(*args, unsigned long); + else if(flags&VLONG) num = va_arg(*args, unsigned long long); else num = va_arg(*args, unsigned int); } if(num == 0) prefix = ""; @@ -391,7 +402,7 @@ static int ocvt_p(FILE *f, va_list *args, int flags, int width, int precision) { return ocvt_fixed(f, args, flags|PTR|ALT, width, precision, 16, 0, - "0123456789ABCDEF", "0X"); + "0123456789ABCDEF", "0x"); } static int @@ -495,6 +506,10 @@ ocvt_flt(FILE *f, va_list *args, int flags, int width, int precision, char afmt) fmt = 'f'; } ndig = edigits-digits; + if(ndig == 0) { + ndig = 1; + digits = "0"; + } if((afmt=='g' || afmt=='G') && !(flags&ALT)){ /* knock off trailing zeros */ if(fmt == 'f'){ if(precision+exponent > ndig) { @@ -527,7 +542,7 @@ ocvt_flt(FILE *f, va_list *args, int flags, int width, int precision, char afmt) if(sign) putc('-', f); else if(flags&SIGN) putc('+', f); else if(flags&SPACE) putc(' ', f); - if(flags&ZPAD) + if((flags&ZPAD) && !(flags&LEFT)) while(nout < width){ putc('0', f); nout++;