[PATCH] fix printf "%p" output on 64-bit platform
Roman Kononov
roman at xtremedatainc.com
Fri Jan 26 18:29:47 UTC 2007
In reference to http://www.uclibc.org/lists/uclibc/2006-November/016736.html
I confirm that the current printf("%p") (revision 17475) is broken for x86_64.
The patch in the above link fixes it.
Nevertheless, I made another patch, which looks more portable in (contrived?)
cases when sizeof(long)!=sizeof(void*).
I used this test cases on x86_64:
int main()
{
printf("%zu, %zu\n",sizeof(void*),sizeof(long long));
void* p1=(void*)1ull;
void* p2=(void*)(1ull<<31);
void* p3=(void*)(1ull<<32);
void* p4=(void*)(1ull<<63);
printf("%p, %p, %p, %p\n",p1,p2,p3,p4);
printf("%0p, %0p, %0p, %0p\n",p1,p2,p3,p4);
printf("%+p, %+p, %+p, %+p\n",p1,p2,p3,p4);
printf("%lp, %lp, %lp, %lp\n",p1,p2,p3,p4);
printf("%Lp, %Lp, %Lp, %Lp\n",p1,p2,p3,p4);
void* p=(void*)(1ull<<32);
int i=~0;
short s=~0;
signed char c=~0;
long l=~0;
long long L=~0;
long t=~0;
printf("&i=%p, &s=%p, &c=%p, &l=%p, &L=%p, &t=%p\n",&i,&s,&c,&l,&L,&t);
printf("%p |%n %hn %hhn %ln %lln %tn\n",p,&i,&s,&c,&l,&L,&t);
printf("i=%i, s=%hi, c=%hhi, l=%li, L=%lli, t=%ti\n",i,s,c,l,L,t);
return 0;
}
In the patch,
if (sizeof(void*)!=sizeof(int) && (desttype&PA_FLAG_PTR))
should be optimized by the complier to reduce the code size.
Regards, Roman
-----------------------------
Index: libc/stdio/_load_inttype.c
===================================================================
--- libc/stdio/_load_inttype.c (revision 17475)
+++ libc/stdio/_load_inttype.c (working copy)
@@ -11,6 +11,12 @@
uintmax_t _load_inttype(int desttype, register const void *src, int uflag) attribute_hidden;
uintmax_t _load_inttype(int desttype, register const void *src, int uflag)
{
+ if (sizeof(void*)!=sizeof(int) && (desttype&PA_FLAG_PTR)) {
+ /* if this test fails you are in trouble */
+ typedef char test_t[sizeof(void*)<sizeof(uintmax_t)?-1:1];
+ return (uintmax_t)*(void**)src;
+ }
+
if (uflag >= 0) { /* unsigned */
#if LONG_MAX != INT_MAX
if (desttype & (PA_FLAG_LONG|PA_FLAG_LONG_LONG)) {
Index: libc/stdio/_vfprintf.c
===================================================================
--- libc/stdio/_vfprintf.c (revision 17475)
+++ libc/stdio/_vfprintf.c (working copy)
@@ -269,7 +269,7 @@ enum {
#define SPEC_OR_MASK { \
/* n */ (PA_FLAG_PTR|PA_INT), \
- /* p */ PA_POINTER, \
+ /* p */ PA_POINTER | PA_FLAG_PTR, \
/* oxXudi */ PA_INT, \
/* fFeEgGaA */ PA_DOUBLE, \
/* C */ PA_WCHAR, \
@@ -280,7 +280,7 @@ enum {
#define SPEC_AND_MASK { \
/* n */ (PA_FLAG_PTR|__PA_INTMASK), \
- /* p */ PA_POINTER, \
+ /* p */ PA_POINTER | PA_FLAG_PTR, \
/* oxXudi */ (__PA_INTMASK), \
/* fFeEgGaA */ (PA_FLAG_LONG_DOUBLE|PA_DOUBLE), \
/* C */ (PA_WCHAR), \
@@ -1566,7 +1566,7 @@ static int _do_one_spec(FILE * __restric
#endif /* __UCLIBC_MJN3_ONLY__ */
s = _uintmaxtostr(buf + sizeof(buf) - 1,
(uintmax_t)
- _load_inttype(*argtype & __PA_INTMASK,
+ _load_inttype(*argtype & (__PA_INTMASK | PA_FLAG_PTR),
*argptr, base), base, alphacase);
if (ppfs->conv_num > CONV_u) { /* signed int */
if (*s == '-') {
More information about the uClibc
mailing list