From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7912 invoked by alias); 8 Jan 2009 10:19:30 -0000 Received: (qmail 7901 invoked by uid 22791); 8 Jan 2009 10:19:28 -0000 X-SWARE-Spam-Status: No, hits=-2.4 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 08 Jan 2009 10:19:21 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id BA4A42A9677; Thu, 8 Jan 2009 05:19:19 -0500 (EST) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id nJRb7lw1zGGQ; Thu, 8 Jan 2009 05:19:19 -0500 (EST) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id 1E2DF2A9675; Thu, 8 Jan 2009 05:19:18 -0500 (EST) Received: by joel.gnat.com (Postfix, from userid 1000) id 1CB0CE7ACD; Thu, 8 Jan 2009 14:19:11 +0400 (RET) Date: Thu, 08 Jan 2009 10:19:00 -0000 From: Joel Brobecker To: Mark Kettenis Cc: gdb-patches@sourceware.org Subject: Re: [RFC] convert a host address to a string Message-ID: <20090108101911.GQ3664@adacore.com> References: <20090107121908.GH1751@adacore.com> <200901071616.n07GGXtu029119@brahms.sibelius.xs4all.nl> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <200901071616.n07GGXtu029119@brahms.sibelius.xs4all.nl> User-Agent: Mutt/1.4.2.2i Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-01/txt/msg00137.txt.bz2 > Probably not, but there's a problem with %p. While it is specified by > C90 and almost certainly implemented in the C library of all systems > we care about, it is implemented how exactly the pointer will be > printed. On OpenBSD and Linux it is something like 0xNNNNNNNN, but > Solaris generates NNNNNNNN (without the initial 0x). That's > undesirable I think. I agree. > An option would be to use the strategy used by phex_nz() to print host > addresses. Or we could use PRINTF_HAS_LONG_LONG, and always use %llx > if it's available. Unfortunately, I don't know how this could be made to work. The problem is that GCC insists that the integer type that we use to cast the host address to must have the same size. At one point, hoping that GCC would kill the wrong branch, I even tried: if (sizeof (void *) == sizeof (long)) printf ("0x%lx", (long) address); else printf ("0x%llx", (long long) address); But this didn't work, because GCC complained about the cast in the "if" branch. Actually, it's only after writing the entire email that I realized that we have another option. See option (3) below. > I'd really like to avoid introducing another macro dealing with > type-size issues if possible. I especially dislike HOST_IS_LLP64 > since I fear its existence encourages people to write unportable code. I can see several solutions: 1. Use %p. To overcome the problem with 0x, we could use two alternatives: a. Import printf from gnulib. I looked at this a while ago, for some other issue, and I immediately stopped, as it looked like it might be a lot of work to do so (printf doesn't come alone, there's a bunch of other routines that printf uses which we probably want). b. Strip the leading "0x" if %p already provides it. In other words: fprintf (buf, "0x%p", address); if (buf[2] == '0' && buf[3] == 'x') buf = buf + 2; return buf; There is no memory management issue in this case, because the buffer we return is more or less static. It's part of a bunch of buffers we cycle through each time we call this routine. The caller never frees the memory we return. 2. Avoid the HOST_IS_LLP64 macro, but still do something similar inside host_address_to_string. Something like: #if defined(WIN64_) fprintf (buf, "0x%llx", (unsigned long long) address); #else fprintf (buf, "0x%lx", (unsigned long) address); #endif This eliminates the likeliness of re-using the HOST_IS_LLP64 macro to write non-portable code. 3. Work through uintptr_t. #ifdef PRINTF_HAS_LONG_LONG fprintf (buf, "0x%llx", (unsigned long long) (uintptr_t) address); #else fprintf (buf, "0x%lx", (unsigned long) (uintptr_t) address); #endif For completeness' sake, I also investigate the use of the PRIxPTR macro, but we still have the problem of casting the address to the right integer type: If PRIxPTR resolves to "lx", then we should cast to "long", otherwise, we should cas to "long long". I kinda like option 1b as being simple and avoiding the need to cast the address to an integer. Option (3) is my next favorite, but I don't like the fact that we end up doing an unnecessary integer promotion on the 32bit targets. Perhaps we could avoid that using an extra "if (sizeof (void *) != sizeof (long))" but then the code becomes increasingly complex. My next favorite would probably be option 2 because I'm lazy, but it's really not elegant. Option 1 looks like a fair amount of work, but would give us access to a predicatable printf. Thoughts? -- Joel