[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