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.
This commit is contained in:
parent
1ce6f0f2ab
commit
bc1cc79225
2 changed files with 56 additions and 16 deletions
|
@ -200,6 +200,22 @@ or
|
||||||
.B long
|
.B long
|
||||||
argument;
|
argument;
|
||||||
an optional
|
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
|
.B l
|
||||||
specifying that a following
|
specifying that a following
|
||||||
.B n
|
.B n
|
||||||
|
@ -207,6 +223,14 @@ conversion specifier applies to a pointer to a
|
||||||
.B long
|
.B long
|
||||||
.B int
|
.B int
|
||||||
argument;
|
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
|
or an optional
|
||||||
.B L
|
.B L
|
||||||
specifying that a following
|
specifying that a following
|
||||||
|
@ -222,6 +246,7 @@ argument.
|
||||||
If an
|
If an
|
||||||
.BR h ,
|
.BR h ,
|
||||||
.BR l ,
|
.BR l ,
|
||||||
|
.BR ll ,
|
||||||
or
|
or
|
||||||
.B L
|
.B L
|
||||||
appears with any other conversion specifier, the behavior is undefined.
|
appears with any other conversion specifier, the behavior is undefined.
|
||||||
|
@ -459,7 +484,7 @@ zero
|
||||||
value for
|
value for
|
||||||
the argument yields undefined results.
|
the argument yields undefined results.
|
||||||
.TP
|
.TP
|
||||||
.B P
|
.B p
|
||||||
The
|
The
|
||||||
.B void*
|
.B void*
|
||||||
argument is printed in an implementation-defined way (for Plan 9:
|
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
|
conversion, or a pointer cast to be a pointer to
|
||||||
.B void
|
.B void
|
||||||
using
|
using
|
||||||
.B %P
|
.B %p
|
||||||
conversion), the behavior is undefined.
|
conversion), the behavior is undefined.
|
||||||
.PP
|
.PP
|
||||||
In no case does a nonexistent or small field width cause truncation
|
In no case does a nonexistent or small field width cause truncation
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#define LONG 64 /* 'l' convert a long integer */
|
#define LONG 64 /* 'l' convert a long integer */
|
||||||
#define LDBL 128 /* 'L' convert a long double */
|
#define LDBL 128 /* 'L' convert a long double */
|
||||||
#define PTR 256 /* convert a void * (%p) */
|
#define PTR 256 /* convert a void * (%p) */
|
||||||
|
#define VLONG 512 /* 'll' convert a long long integer */
|
||||||
|
|
||||||
static int lflag[] = { /* leading flags */
|
static int lflag[] = { /* leading flags */
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, /* ^@ ^A ^B ^C ^D ^E ^F ^G */
|
0, 0, 0, 0, 0, 0, 0, 0, /* ^@ ^A ^B ^C ^D ^E ^F ^G */
|
||||||
|
@ -148,7 +149,7 @@ QLock _stdiolk;
|
||||||
int
|
int
|
||||||
vfprintf(FILE *f, const char *s, va_list args)
|
vfprintf(FILE *f, const char *s, va_list args)
|
||||||
{
|
{
|
||||||
int flags, width, precision;
|
int tfl, flags, width, precision;
|
||||||
|
|
||||||
qlock(&_stdiolk);
|
qlock(&_stdiolk);
|
||||||
|
|
||||||
|
@ -187,7 +188,15 @@ vfprintf(FILE *f, const char *s, va_list args)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
precision = -1;
|
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);
|
if(ocvt[*s]) nprint += (*ocvt[*s++])(f, &args, flags, width, precision);
|
||||||
else if(*s){
|
else if(*s){
|
||||||
putc(*s++, f);
|
putc(*s++, f);
|
||||||
|
@ -208,9 +217,8 @@ vfprintf(FILE *f, const char *s, va_list args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
int i;
|
||||||
|
|
||||||
if(!(flags&LEFT)) for(i=1; i<width; i++) putc(' ', f);
|
if(!(flags&LEFT)) for(i=1; i<width; i++) putc(' ', f);
|
||||||
|
@ -226,6 +234,8 @@ ocvt_s(FILE *f, va_list *args, int flags, int width, int precision)
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
s = va_arg(*args, char *);
|
s = va_arg(*args, char *);
|
||||||
|
if(!s)
|
||||||
|
s = "<nil>";
|
||||||
if(!(flags&LEFT)){
|
if(!(flags&LEFT)){
|
||||||
if(precision >= 0)
|
if(precision >= 0)
|
||||||
for(i=0; i!=precision && s[i]; i++);
|
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
|
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)
|
if(flags&SHORT)
|
||||||
*va_arg(*args, short *) = nprint;
|
*va_arg(*args, short *) = nprint;
|
||||||
else if(flags&LONG)
|
else if(flags&LONG)
|
||||||
*va_arg(*args, long *) = nprint;
|
*va_arg(*args, long *) = nprint;
|
||||||
|
else if(flags&VLONG)
|
||||||
|
*va_arg(*args, long long*) = nprint;
|
||||||
else
|
else
|
||||||
*va_arg(*args, int *) = nprint;
|
*va_arg(*args, int *) = nprint;
|
||||||
return 0;
|
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 digits[128]; /* no reasonable machine will ever overflow this */
|
||||||
char *sign;
|
char *sign;
|
||||||
char *dp;
|
char *dp;
|
||||||
long snum;
|
long long snum;
|
||||||
unsigned long num;
|
unsigned long long num;
|
||||||
int nout, npad, nlzero;
|
int nout, npad, nlzero;
|
||||||
|
|
||||||
if(sgned){
|
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&SHORT) snum = va_arg(*args, short);
|
||||||
else if(flags&LONG) snum = va_arg(*args, long);
|
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);
|
else snum = va_arg(*args, int);
|
||||||
if(snum < 0){
|
if(snum < 0){
|
||||||
sign = "-";
|
sign = "-";
|
||||||
|
@ -308,9 +318,10 @@ ocvt_fixed(FILE *f, va_list *args, int flags, int width, int precision,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sign = "";
|
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&SHORT) num = va_arg(*args, unsigned short);
|
||||||
else if(flags&LONG) num = va_arg(*args, unsigned long);
|
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);
|
else num = va_arg(*args, unsigned int);
|
||||||
}
|
}
|
||||||
if(num == 0) prefix = "";
|
if(num == 0) prefix = "";
|
||||||
|
@ -391,7 +402,7 @@ static int
|
||||||
ocvt_p(FILE *f, va_list *args, int flags, int width, int precision)
|
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,
|
return ocvt_fixed(f, args, flags|PTR|ALT, width, precision, 16, 0,
|
||||||
"0123456789ABCDEF", "0X");
|
"0123456789ABCDEF", "0x");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -495,6 +506,10 @@ ocvt_flt(FILE *f, va_list *args, int flags, int width, int precision, char afmt)
|
||||||
fmt = 'f';
|
fmt = 'f';
|
||||||
}
|
}
|
||||||
ndig = edigits-digits;
|
ndig = edigits-digits;
|
||||||
|
if(ndig == 0) {
|
||||||
|
ndig = 1;
|
||||||
|
digits = "0";
|
||||||
|
}
|
||||||
if((afmt=='g' || afmt=='G') && !(flags&ALT)){ /* knock off trailing zeros */
|
if((afmt=='g' || afmt=='G') && !(flags&ALT)){ /* knock off trailing zeros */
|
||||||
if(fmt == 'f'){
|
if(fmt == 'f'){
|
||||||
if(precision+exponent > ndig) {
|
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);
|
if(sign) putc('-', f);
|
||||||
else if(flags&SIGN) putc('+', f);
|
else if(flags&SIGN) putc('+', f);
|
||||||
else if(flags&SPACE) putc(' ', f);
|
else if(flags&SPACE) putc(' ', f);
|
||||||
if(flags&ZPAD)
|
if((flags&ZPAD) && !(flags&LEFT))
|
||||||
while(nout < width){
|
while(nout < width){
|
||||||
putc('0', f);
|
putc('0', f);
|
||||||
nout++;
|
nout++;
|
||||||
|
|
Loading…
Reference in a new issue