Mail Archives: djgpp-workers/2000/11/17/19:23:58
Hello.
DJ Delorie wrote:
>
> > static __inline__ int __putc_raw(int const x,FILE *const p)
> > {
> > if(p->_cnt>0)
> > {
> > p->_cnt--;
> > return((unsigned char)(*(p->_ptr++)=(unsigned char)x));
> > }
> > else if (p->_flag & _IOSTRG)
>
> This is making this macro pretty complex. Would it be better to move
> the _IOSTRG logic into flsbuf, so that it acts like a "disk full"
> condition when the string buffer is empty?
Yes, that seems like a good idea. Please find below a diff with _flsbuf()
modified instead of __putc_raw(). I've also updated
src/libc/ansi/stdio/file.doc to describe _IOTERM, _IONTERM using the
definitions from include/libc/file.h.
Bye, Rich =]
*** /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 */
***************
*** 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);
***************
*** 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
***************
*** 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/file.doc Fri Nov 14 20:56:16 1997
--- /develop/djgpp.dev/src/libc/ansi/stdio/file.doc Fri Nov 17
23:32:10 2000
***************
*** 31,36 ****
--- 31,38 ----
_IOAPPEND append mode
_IORMONCL remove file on close
_IOUNGETC buffer contents does not correspond to file
+ _IOTERM file's handle hooked by termios
+ _IONTERM file's handle not hooked by termios
int _file;
*** /develop/djgpp/src/libc/ansi/stdio/flsbuf.c Thu Jun 3 18:27:34 1999
--- /develop/djgpp.dev/src/libc/ansi/stdio/flsbuf.c Fri Nov 17
23:36:04 2000
***************
*** 27,32 ****
--- 27,36 ----
if ((f->_flag&_IOWRT)==0)
return EOF;
+ /* No-op for full string buffers */
+ if (f->_flag & _IOSTRG)
+ return c;
+
/* if the buffer is not yet allocated, allocate it */
if ((base = f->_base) == NULL && (f->_flag & _IONBF) == 0)
{
*** /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=../..
***************
*** 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
***************
*** 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
***************
*** 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;
+ }
- Raw text -