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
|
||||
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
|
||||
|
|
|
@ -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<width; i++) putc(' ', f);
|
||||
|
@ -226,6 +234,8 @@ ocvt_s(FILE *f, va_list *args, int flags, int width, int precision)
|
|||
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 @@ 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++;
|
||||
|
|
Loading…
Reference in a new issue