code: plan9front

Download patch

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++;