bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[v]asnprintf and portability


From: Eric Blake
Subject: [v]asnprintf and portability
Date: Tue, 13 Mar 2007 07:00:38 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.10) Gecko/20070221 Thunderbird/1.5.0.10 Mnenhy/0.7.4.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I'm considering writing a patch that adds [v]asnprintf functionality to
newlib (and thus cygwin).  newlib already has [v]asprintf, even though it
is not standardized; and uses Linux instead of BSD semantics (Linux states
that on failure, the string pointer is unspecified, while BSD makes the
additional guarantee that the string pointer is set to NULL).  But I am
not aware of any other platform that provides a native asnprintf - is it a
gnulib invention?

If it is a gnulib invention, then it almost seems odd to have vasnprintf
vs. vasnprintf-posix modules, since POSIX makes no requirements on it -
why not always support full semantics?  I know, the distinction is whether
you can use the full range of POSIX specifiers, including %a, or whether
you can only defer to underlying platform specifiers.

The newlib list wants to know why it is worth making asnprintf part of the
library.  My argument is as follows:

Without access to the library internals, an implementation of asnprintf
looks like:

char *
asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
  __attribute__ ((__format__ (__printf__, , 4)))
{
  va_list ap;
  size_t len;
  va_start (ap, format);
  len = vsnprintf (NULL, 0, format, ap);
  va_end (ap);
  if ((int) len < 0)
    return NULL; /* errno set by vsnprintf */
  if (!resultbuf || len >= *lengthp)
    resultbuf = malloc (len + 1);
  if (!resultbuf)
    return NULL; /* errno set by malloc */
  va_start (ap, format);
  *lengthp = vsnprintf (resultbuf, len + 1, format, ap);
  va_end (ap);
  return resultbuf;
}

This has two draw-backs.  On 64-bit platforms, it suffers from the
pointless EOVERFLOW on INT_MAX limitation inherited from snprintf (whereas
asnprintf, being non-standardized and using size_t instead of int, need
not be limited in that manner).  The other is that the argument list must
be processed twice, which involves some non-trivial computation time,
particularly on double arguments, in order to compute the length
independently from generating the output.

Both of these drawbacks can be solved by letting asnprintf in on the
internals of the *printf implementation.

Any corrections, or anything else I should add to my arguments?

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFF9qB184KuGfSFAYARAhQEAKC3AjSSTgU8gacAAmLWx0WBbCf+mgCgl1tm
u9jEgW0Tefxt8+wj5KurTRA=
=0GRU
-----END PGP SIGNATURE-----




reply via email to

[Prev in Thread] Current Thread [Next in Thread]