ref: bc1cc79225f0b006dd66d4fd81030d06f83bfca2
parent: 1ce6f0f2ab1896e35869f0e9e5079fc20dd981fc
author: kvik <kvik@a-b.xyz>
date: Fri Feb 19 18:04:09 EST 2021
libstdio: sync bits of vfprintf from APE * Add the %ll length modifier, * Convert nil to "<nil>" 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.
--- a/sys/man/2/fprintf
+++ b/sys/man/2/fprintf
@@ -200,6 +200,22 @@
.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 @@
.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 @@
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 @@
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 @@
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
--- 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 @@
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 @@
}
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 @@
}
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<width; i++) putc(' ', f);
@@ -226,6 +234,8 @@
char *s;
s = va_arg(*args, char *);
+ if(!s)
+ s = "<nil>";
if(!(flags&LEFT)){
if(precision >= 0)
for(i=0; i!=precision && s[i]; i++);
@@ -257,15 +267,14 @@
}
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 @@
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 @@
}
} 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 @@
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 @@
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 @@
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++;