www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2000/11/15/17:59:43

Sender: richdawe AT bigfoot DOT com
Message-ID: <3A132065.9FA6E06B@bigfoot.com>
Date: Wed, 15 Nov 2000 23:46:45 +0000
From: Richard Dawe <richdawe AT bigfoot DOT com>
X-Mailer: Mozilla 4.51 [en] (X11; I; Linux 2.2.17 i586)
X-Accept-Language: de,fr
MIME-Version: 1.0
To: DJGPP workers <djgpp-workers AT delorie DOT com>
Subject: snprintf() diff, take 2
Reply-To: djgpp-workers AT delorie DOT com

This is a cryptographically signed message in MIME format.

--------------ms1424A44FEF052BAD90FA7479
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hello.

Here is a second diff for the snprintf() code. This supercedes the
previous one. Changes from the previous version:

* __putc_raw() now returns the character that would have been stuffed into
the buffer, if had there been space. Previously it returned 0. The change
restores the semantics of __putc_raw() the full string buffer case.

* I added a note on the maximum value of 'n' for snprintf(), vsnprintf().
The value of errno is not documented, since errno is only set for the case
where n is too big. This seems to be OK according to the C spec - we can
set errno to whatever we like, since snprintf() does not have a defined
effect on errno.

* Fixed a couple of format warnings in the test.

Bye, Rich

*** /develop/djgpp/include/libc/file.h  Sun Jun 27 17:27:44 1999
--- /develop/djgpp.dev/include/libc/file.h      Wed Nov 15 22:38:38 2000
***************
*** 1,3 ****
--- 1,4 ----
+ /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
*************** static __inline__ int __putc_raw(int con
*** 52,57 ****
--- 53,63 ----
     {
        p->_cnt--;
        return((unsigned char)(*(p->_ptr++)=(unsigned char)x));
+    }
+    else if (p->_flag & _IOSTRG)
+    {
+       /* noop for full string buffers */
+       return((unsigned char)x);
     }
     return(_flsbuf((unsigned char)x,p));
  }
*** /develop/djgpp/include/stdio.h      Sun Nov 15 13:37:28 1998
--- /develop/djgpp.dev/include/stdio.h  Sun Nov 12 21:18:46 2000
***************
*** 1,3 ****
--- 1,4 ----
+ /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  
*************** void    rewind(FILE *_stream);
*** 94,99 ****
--- 95,101 ----
  int   scanf(const char *_format, ...);
  void  setbuf(FILE *_stream, char *_buf);
  int   setvbuf(FILE *_stream, char *_buf, int _mode, size_t _size);
+ int   snprintf(char *str, size_t n, const char *fmt, ...);
  int   sprintf(char *_s, const char *_format, ...);
  int   sscanf(const char *_s, const char *_format, ...);
  FILE *        tmpfile(void);
*************** char *  tmpnam(char *_s);
*** 101,106 ****
--- 103,109 ----
  int   ungetc(int _c, FILE *_stream);
  int   vfprintf(FILE *_stream, const char *_format, va_list _ap);
  int   vprintf(const char *_format, va_list _ap);
+ int   vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
  int   vsprintf(char *_s, const char *_format, va_list _ap);
  
  #ifndef __STRICT_ANSI__
*** /develop/djgpp/src/docs/kb/wc204.txi        Fri Oct  6 23:53:22 2000
--- /develop/djgpp.dev/src/docs/kb/wc204.txi    Sun Nov 12 21:34:42 2000
*************** pollute the name space with the symbols 
*** 131,133 ****
--- 131,136 ----
  @code{end}.  The profiling code was also changed to not pollute the name
  space with @code{etext}.
  
+ @findex snprintf
+ @findex vsnprintf
+ New functions @code{snprintf} and @code{vsnprintf} added.
*** /develop/djgpp/src/libc/ansi/stdio/makefile Sun Jun 28 18:44:16 1998
--- /develop/djgpp.dev/src/libc/ansi/stdio/makefile     Sun Nov 12
21:57:50 2000
***************
*** 1,3 ****
--- 1,4 ----
+ # Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details
  # Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details
  # Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details
  TOP=../..
*************** SRC += ungetc.c
*** 61,65 ****
--- 62,68 ----
  SRC += vfprintf.c
  SRC += vprintf.c
  SRC += vsprintf.c
+ SRC += snprintf.c
+ SRC += vsnprntf.c
  
  include $(TOP)/../makefile.inc
*** /develop/djgpp/src/libc/ansi/stdio/snprintf.c       Sun Nov 12
21:57:18 2000
--- /develop/djgpp.dev/src/libc/ansi/stdio/snprintf.c   Sun Nov 12
21:58:06 2000
***************
*** 1 ****
--- 1,28 ----
+ /* Copyright (C) 2000 DJ Delorie see COPYING.DJ for details */
+ #include <stdio.h>
+ #include <limits.h>
+ #include <errno.h>
+ #include <libc/file.h>
  
+ int
+ snprintf(char *str, size_t n, const char *fmt, ...)
+ {
+   FILE _strbuf;
+   int len;
+ 
+   /* _cnt is an int in the FILE structure. To prevent wrap-around, we
limit
+    * n to between 0 and INT_MAX inclusively. */
+   if (n > INT_MAX)
+   {
+     errno = EFBIG;
+     return -1;
+   }
+ 
+   _strbuf._flag = _IOWRT | _IOSTRG | _IONTERM;
+   _strbuf._ptr = str;
+   _strbuf._cnt = n - 1;
+   len = _doprnt(fmt, &(fmt)+1, &_strbuf);
+   if (n != 0)
+     *_strbuf._ptr = 0;
+   return len;
+ }
*** /develop/djgpp/src/libc/ansi/stdio/snprintf.txh     Sun Nov 12
21:57:18 2000
--- /develop/djgpp.dev/src/libc/ansi/stdio/snprintf.txh Wed Nov 15
22:36:34 2000
***************
*** 1 ****
--- 1,27 ----
+ @node snprintf, stdio
+ @subheading Syntax
  
+ @example
+ #include <stdio.h>
+ 
+ int snprintf (char *@var{buffer}, size_t @var{n}, const char
*@var{format},
+               @dots{});
+ @end example
+ 
+ @subheading Description
+ 
+ This function works similarly to @xref{sprintf}, but the size @var{n} of
+ the @var{buffer} is also taken into account. This function will write
+ @var{n} - 1 characters. The @var{n}th character is used for the
terminating
+ nul.  If @var{n} is zero, @var{buffer} is not touched.
+ 
+ @subheading Return Value
+ 
+ The number of characters that would have been written (excluding the
trailing
+ nul) is returned; otherwise -1 is returned to flag encoding errors.
+ 
+ @subheading Portability
+ 
+ @port-note ansi For DJGPP, the maximum accepted value of @var{n} is
INT_MAX. An error is returned if @var{n} is greater than this limit.
+ 
+ @portability ansi
\ No newline at end of file
*** /develop/djgpp/src/libc/ansi/stdio/sprintf.txh      Sun Sep 27
16:20:50 1998
--- /develop/djgpp.dev/src/libc/ansi/stdio/sprintf.txh  Sun Nov 12
21:37:08 2000
*************** int sprintf(char *buffer, const char *fo
*** 12,17 ****
--- 12,20 ----
  Sends formatted output from the arguments (@dots{}) to the @var{buffer}.
  @xref{printf}.
  
+ To avoid buffer overruns, it is safer to use @code{snprintf()}
+ (@pxref{snprintf}).
+ 
  @subheading Return Value
  
  The number of characters written.
*** /develop/djgpp/src/libc/ansi/stdio/vsnprntf.c       Sun Nov 12
21:57:18 2000
--- /develop/djgpp.dev/src/libc/ansi/stdio/vsnprntf.c   Sun Nov 12
21:58:16 2000
***************
*** 1 ****
--- 1,29 ----
+ /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */
+ #include <stdio.h>
+ #include <stdarg.h>
+ #include <limits.h>
+ #include <errno.h>
+ #include <libc/file.h>
  
+ int
+ vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
+ {
+   FILE _strbuf;
+   int len;
+ 
+   /* _cnt is an int in the FILE structure. To prevent wrap-around, we
limit
+    * n to between 0 and INT_MAX inclusively. */
+   if (n > INT_MAX)
+   {
+     errno = EFBIG;
+     return -1;
+   }
+ 
+   _strbuf._flag = _IOWRT | _IOSTRG | _IONTERM;
+   _strbuf._ptr = str;
+   _strbuf._cnt = n - 1;
+   len = _doprnt(fmt, ap, &_strbuf);
+   if (n != 0)
+     *_strbuf._ptr = 0;
+   return len;
+ }
*** /develop/djgpp/src/libc/ansi/stdio/vsnprntf.txh     Sun Nov 12
21:57:18 2000
--- /develop/djgpp.dev/src/libc/ansi/stdio/vsnprntf.txh Wed Nov 15
22:36:54 2000
***************
*** 1 ****
--- 1,28 ----
+ @node vsnprintf, stdio
+ @subheading Syntax
  
+ @example
+ #include <stdio.h>
+ #include <stdarg.h>
+ 
+ int vsnprintf (char *@var{buffer}, size_t @var{n}, const char
*@var{format},
+                va_list @var{ap});
+ @end example
+ 
+ @subheading Description
+ 
+ This function works similarly to @xref{vsprintf}, but the size @var{n}
of
+ the @var{buffer} is also taken into account. This function will write
+ @var{n} - 1 characters. The @var{n}th character is used for the
terminating
+ nul.  If @var{n} is zero, @var{buffer} is not touched.
+ 
+ @subheading Return Value
+ 
+ The number of characters that would have been written (excluding the
trailing
+ nul) is returned; otherwise -1 is returned to flag encoding errors.
+ 
+ @subheading Portability
+ 
+ @port-note ansi For DJGPP, the maximum accepted value of @var{n} is
INT_MAX. An error is returned if @var{n} is greater than this limit.
+ 
+ @portability ansi
*** /develop/djgpp/src/libc/ansi/stdio/vsprintf.txh     Sun Sep 27
16:20:50 1998
--- /develop/djgpp.dev/src/libc/ansi/stdio/vsprintf.txh Sun Nov 12
21:37:00 2000
*************** int vsprintf(char *buffer, const char *f
*** 13,18 ****
--- 13,21 ----
  Sends formatted output from the @var{arguments} to the @var{buffer}.
  @xref{printf}. @xref{vfprintf}.
  
+ To avoid buffer overruns, it is safer to use @code{vsnprintf()}
+ (@pxref{vsnprintf}).
+ 
  @subheading Return Value
  
  The number of characters written.
*** /develop/djgpp/tests/libc/ansi/stdio/snprintf.c     Sun Nov 12
21:57:18 2000
--- /develop/djgpp.dev/tests/libc/ansi/stdio/snprintf.c Wed Nov 15
22:41:26 2000
***************
*** 1 ****
--- 1,58 ----
+ #include <stdio.h>
  
+ int main ()
+ {
+   char holder[24];
+   unsigned i, j;
+ 
+ #define BIG "Hello this is a too big string for the buffer"
+   i = snprintf (holder, sizeof (holder), "%s\n", BIG);
+   printf ("%s\n", BIG);
+   printf ("%s\n", holder);
+   /*
+    * We are expecting :
+    *   i == strlen (BIG) + 1
+    * meaning the number that would have been written if the buffer was
+    * large enough (see C9X).
+    */
+   if (i != strlen (BIG) + 1/* NL */)
+     {
+       fprintf (stderr, "FAILED snprintf\n");
+       fprintf (stderr,
+              "sizeof (%ld), snprintf(%d), strlen(%ld)\n",
+              sizeof (holder), i, strlen (BIG)) ;
+       exit (1);
+     }
+ 
+   /* We may have broken sscanf since it is also a string stream
+    * Lets do a basic test.
+    */
+   {
+     static char *line = "25 December 2000\n";
+     int day, year;
+     char month[24];
+ 
+     /* we are expectinc to read 3 variables */
+     if ((i = sscanf (line, "%d %s %d\n", &day, month, &year)) == 3)
+       {
+       i = snprintf (holder, sizeof(holder), "%d %s %d\n", day, month,
year);
+       printf (line);
+       j = printf (holder);
+       if (i != j)
+         {
+           fprintf (stderr, "FAILED snprintf\n");
+           fprintf (stderr, "snprintf (%d) != printf (%d)\n", i, j);
+           exit (1);
+         }
+       }
+     else
+       {
+           printf ("sscanf (%d)\n", i);
+           printf ("FAILED sscanf\n");
+           exit (1);
+       }
+   }
+   /* signal success */
+   printf ("SUCCESS\n");
+   return 0;
+ }
--------------ms1424A44FEF052BAD90FA7479
Content-Type: application/x-pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"
Content-Description: S/MIME Cryptographic Signature

MIIHFQYJKoZIhvcNAQcCoIIHBjCCBwICAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC
BY0wggLMMIICNaADAgECAhB2D2twnX9wqhegGKLtJkJmMA0GCSqGSIb3DQEBBAUAMFgxJzAl
BgNVBAoTHkJyaXRpc2ggVGVsZWNvbW11bmljYXRpb25zIHBsYzEtMCsGA1UECxMkQlQgVHJ1
c3R3aXNlIC0gQ2xhc3MgMSBJbmRpdmlkdWFsIENBMB4XDTAwMTAxNTAwMDAwMFoXDTAxMTAx
NTIzNTk1OVowggERMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMx
LTArBgNVBAsTJEJUIFRydXN0d2lzZSAtIENsYXNzIDEgSW5kaXZpZHVhbCBDQTFGMEQGA1UE
CxM9d3d3LnRydXN0d2lzZS5jb20vcmVwb3NpdG9yeS9SUCBJbmNvcnAuIGJ5IFJlZi4sTElB
Qi5MVEQoYyk5ODEzMDEGA1UECxMqRGlnaXRhbCBJRCBDbGFzcyAxIC0gTmV0c2NhcGUgRnVs
bCBTZXJ2aWNlMRUwEwYDVQQDEwxSaWNoYXJkIERhd2UxIzAhBgkqhkiG9w0BCQEWFHJpY2hk
YXdlQGJpZ2Zvb3QuY29tMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMJ3LQ1fxlYpzsChuJ16
J9dwyZIkhexC8uW2RGyxJVOG6643weIDoATk515qu8G91CS85rLDRFIB0u2N4ezCUCkCAwEA
AaMgMB4wCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCB4AwDQYJKoZIhvcNAQEEBQADgYEA
llCoL5Afa66m9bxGh/gMgwUCCCOb6DdKHmJw9Q5h0xoEHuHOcEEjNPqQug5ZQaKioEIJM7DS
gsuSPrEy5Z521OzNWxN8nRv9YAlV3fVHQxcNlsjaAZru6zJxZ0+0uAKKFKOjJLTdfXFUqdcH
kcY2syIZo6DRSIap9pCqC+HYOoIwggK5MIICIqADAgECAhEA0zBJnvKZLVDb03kHStQNPTAN
BgkqhkiG9w0BAQIFADBfMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4x
NzA1BgNVBAsTLkNsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
dHkwHhcNOTgwMjEyMDAwMDAwWhcNMDMwMjEyMjM1OTU5WjBYMScwJQYDVQQKEx5Ccml0aXNo
IFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxLTArBgNVBAsTJEJUIFRydXN0d2lzZSAtIENsYXNz
IDEgSW5kaXZpZHVhbCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0QG30oEW28L0
Z/5fC03tfZ+a2ahBQYehZ6hrcb1PW6ZIXuqm5y8KpzYJ9rLhRkMA3BzH8eACTVhkn/qAJmqC
m2GTDa7eueV8q6A/0I/p9KwahkjEgG4exysZ9svlo21+HWn0yFtrHAraKuNoZOPpFnNP5dOp
AuObV5lKytU5AlkCAwEAAaN8MHowEQYJYIZIAYb4QgEBBAQDAgEGMEcGA1UdIARAMD4wPAYL
YIZIAYb4RQEHAQEwLTArBggrBgEFBQcCARYfd3d3LnZlcmlzaWduLmNvbS9yZXBvc2l0b3J5
L1JQQTAPBgNVHRMECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQIFAAOBgQBS
Acma9vqkvYS4miXj6t5jPDVao9pIjdxWTjRoiRPRRi7wz0On9jUzqVK8sVcrPIpwxmvnlOyv
jM8KpZaJVXECrgclfNlGR58eSiyTSHyBO0XUK4XLJkwkBXyBmiHc+32l5gvC+QXuGccUEdg8
WZ/OOeoRMbCdGuw1+LeE55h4JzGCAVAwggFMAgEBMGwwWDEnMCUGA1UEChMeQnJpdGlzaCBU
ZWxlY29tbXVuaWNhdGlvbnMgcGxjMS0wKwYDVQQLEyRCVCBUcnVzdHdpc2UgLSBDbGFzcyAx
IEluZGl2aWR1YWwgQ0ECEHYPa3Cdf3CqF6AYou0mQmYwCQYFKw4DAhoFAKB9MBgGCSqGSIb3
DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTAwMTExNTIzNDY0NVowHgYJKoZI
hvcNAQkPMREwDzANBggqhkiG9w0DAgIBKDAjBgkqhkiG9w0BCQQxFgQUoyWMqqTC2OlJiyyj
v12V09/mA7YwDQYJKoZIhvcNAQEBBQAEQHPEs80Lh5fXowzEVbF3y9htir/6sv5i0GL/jCxW
Z+OiNEC6UAGT/kPptnOTtREuVKNcsJLt0MNtyRrxiN0U6XU=
--------------ms1424A44FEF052BAD90FA7479--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019