Thread: *printf and zero size

*printf and zero size

From
Bruce Momjian
Date:
Tom, did you implement this functionality in *printf?
The size may be given as zero to find out how many characters areneeded; in this case, the str argument is ignored.
Sprintf()andvsprintf() effectively assume an infinite size.
 

Looking at the code it doesn't seem supported.  Should it be added to
the limitations comment section?

--  Bruce Momjian                        |  http://candle.pha.pa.us pgman@candle.pha.pa.us               |  (610)
359-1001+  If your life is a hard drive,     |  13 Roberts Road +  Christ can be your backup.        |  Newtown Square,
Pennsylvania19073
 


Re: *printf and zero size

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> Tom, did you implement this functionality in *printf?
>     The size may be given as zero to find out how many characters are
>     needed; in this case, the str argument is ignored. Sprintf() and
>     vsprintf() effectively assume an infinite size.

Where do you read that?  The SUS says the opposite:
If the value of n is zero on a call to snprintf(), an unspecifiedvalue less than 1 is returned. 

and that's what our code implements.
        regards, tom lane


Re: *printf and zero size

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > Tom, did you implement this functionality in *printf?
> >     The size may be given as zero to find out how many characters are
> >     needed; in this case, the str argument is ignored. Sprintf() and
> >     vsprintf() effectively assume an infinite size.
> 
> Where do you read that?  The SUS says the opposite:
> 
>     If the value of n is zero on a call to snprintf(), an unspecified
>     value less than 1 is returned. 
> 
> and that's what our code implements.

I got it from the BSD/OS manual page, and in the NetBSD manual page I
see:
If size is zero, nothing is written and str may be a NULL pointer.

and:
Upon successful completion snprintf() and vsnprintf() return the numberof characters that would have been written to a
sufficientlysized str,excluding the terminating NUL character.
 

but it seems this is some BSD'ism that we don't need to support if the
standard doesn't say so.

--  Bruce Momjian                        |  http://candle.pha.pa.us pgman@candle.pha.pa.us               |  (610)
359-1001+  If your life is a hard drive,     |  13 Roberts Road +  Christ can be your backup.        |  Newtown Square,
Pennsylvania19073
 


Re: *printf and zero size

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
>     Upon successful completion snprintf() and vsnprintf() return the number
>     of characters that would have been written to a sufficiently sized str,
>     excluding the terminating NUL character.

> but it seems this is some BSD'ism that we don't need to support if the
> standard doesn't say so.

Yeah, that is a BSD-ism.  You have a point though, we ought to document
which return convention the code follows.  I'll add something.
        regards, tom lane


Re: *printf and zero size

From
Tom Lane
Date:
Kurt Roeckx <kurt@roeckx.be> writes:
>      Concerning  the return value of snprintf(), the SUSv2 and the C99 stan-
>      dard contradict each other:

Is that where the problem comes from?

Anyway, I've added some text to snprintf.c explaining what we do.  Since
the calling code has to be prepared to handle either result convention,
I see no need to do anything except what's easiest to implement, which
in this case is the SUS behavior.  (There's also a consistency issue,
which is that fprintf is supposed to return the number of bytes actually
transmitted, not the number it would have sent in the absence of error.)
        regards, tom lane

  * 5. Space and '#' flags are not implemented.
+  *
+  *
+  * The result values of these functions are not the same across different
+  * platforms.  This implementation is compatible with the Single Unix Spec:
+  *
+  * 1. -1 is returned only if processing is abandoned due to an invalid
+  * parameter, such as incorrect format string.  (Although not required by
+  * the spec, this happens only when no characters have yet been transmitted
+  * to the destination.)
+  *
+  * 2. For snprintf and sprintf, 0 is returned if str == NULL or count == 0;
+  * no data has been stored.
+  *
+  * 3. Otherwise, the number of bytes actually transmitted to the destination
+  * is returned (excluding the trailing '\0' for snprintf and sprintf).
+  *
+  * For snprintf with nonzero count, the result cannot be more than count-1
+  * (a trailing '\0' is always stored); it is not possible to distinguish
+  * buffer overrun from exact fit.  This is unlike some implementations that
+  * return the number of bytes that would have been needed for the complete
+  * result string.  */


Re: *printf and zero size

From
Kurt Roeckx
Date:
On Mon, Dec 05, 2005 at 04:35:31PM -0500, Bruce Momjian wrote:
> 
> but it seems this is some BSD'ism that we don't need to support if the
> standard doesn't say so.

I think the Linux manpage is more informative about this:
      The functions snprintf and vsnprintf do not write more  than      size  bytes (including the trailing '\0').  If
theoutput was truncated      due to this limit then the return value is  the  number  of  characters      (not
includingthe trailing '\0') which would have been written to the      final string if enough space had been available.
Thus,a  return  value      of  size  or  more means that the output was truncated. (See also below      under NOTES.)
Ifan output error is encountered, a negative  value  is      returned.
 

[...]

NOTES      The  glibc  implementation  of the functions snprintf() and vsnprintf()      conforms to the C99 standard,
i.e.,behaves as described  above,  since      glibc version 2.1. Until glibc 2.0.6 they would return -1 when the out-
  put was truncated.
 

[...]
      Concerning  the return value of snprintf(), the SUSv2 and the C99 stan-      dard contradict each other: when
snprintf()is called with size=0  then      SUSv2  stipulates  an  unspecified  return value less than 1, while C99
allowsstr to be NULL in this case, and  gives  the  return  value  (as      always)  as  the  number  of characters
thatwould have been written in      case the output string has been large enough.
 


Kurt