This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Libiberty's snprintf for v3?


 > From: Paolo Carlini <pcarlini at unitus dot it>
 > 
 > Hi Kaveh, hi everyone,
 > 
 > now that snprintf is available in libiberty we can consider actually 
 > using it in v3.
 > 
 > I briefly recall (for Kaveh and the accidental readers) that currently 
 > we use either snprintf or the unsafe sprintf depending on 
 > _GLIBCPP_USE_C99 (see config/locale/gnu/c_locale.h).
 > 
 > Having snprintf unconditionally available would simplify and made safer 
 > a few functions in include/bits/locale_facets.tcc
 > 
 > Do we really want that? In case, I volunteer to do the needed work 
 > (provided you guys help me a little bit ;).
 > Paolo.


Hi Paolo,

I'd like to see this happen, but there's a license snag.  I think I
mentioned this last time snprintf came up, but in case not:

While the new files I added for [v]snprintf use GPL plus special
exception, the implementation I wrote relies on libiberty's
vasprintf.c or a working system vasprintf.  I think vasprintf is more
rare than [v]snprintf since I believe vasprintf didn't make it into
c99.  So if we just suck [v]snprintf.c into libstdc++, it probably
won't be very useful since any system which needs it probably also
needs vasprintf.c.

The vasprintf.c file in libiberty uses LGPL which has different terms
than the special exception clause used in libstdc++ and [v]snprintf.c.

I see two remedies.

1.  Someone (not me, probably Paolo :-) ) needs to write to
    assign at gnu dot org, explain the situation and ask them to change the
    license on vasprintf.c to GPL + special exception.  This isn't so
    bad, I've found them to be reasonable and responsive.  Then you
    can suck in that file too.

Or:

2.  Someone (probably me) needs to rewrite [v]snprintf.c to avoid
    using vasprintf.  E.g. we can use vfprintf to /dev/null to get the
    length of the resulting string.  I imagine something like this for
    vsnprintf.c:

    (Assume `s' is the buffer, `n' is the max length, and `msg' is the
    format and `ap' is the va_list.)

    len = vfprintf (dev_null_stream, msg, ap)
    if (len < n)
      vsprintf (s, msg, ap)
    else
      {
        buf = alloca (len+1)
	vsprintf (buf, msg, ap)
	memcpy (s, buf, n);
      }

    (It's probably more complicated in reality, but you get the idea.)
    

The downsides to this approach are:

A.  We assume /dev/null exists.

B.  We either open and close the stream every time (very slow) or
    cache the open /dev/null stream (close it with atexit) and waste
    one open file descriptor and one atexit slot for the entire run of
    any program which uses libiberty's [v]snprintf.c.

C.  I'm not sure if it's legal (portable) to traverse the va_list
    twice inside vsnprintf.c, once with vfprintf and once is vsprintf.

But, on the upside we won't need vasprintf.c, and the resulting code
will probably be faster than the current implementation if we cache
the fd.

If this doesn't work, perhaps someone can come up with another
approach?  Comments?

		--Kaveh
--
Kaveh R. Ghazi			ghazi at caip dot rutgers dot edu


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]