setvbuf: Add support for configuration of line buffering.

This commit is contained in:
Gregory Nutt
2017-02-08 11:28:24 -06:00
parent 51a14c9b2f
commit 9f859774a1
21 changed files with 120 additions and 149 deletions
+1 -3
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* drivers/syslog/syslog_emergtream.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -109,8 +109,6 @@ static void emergstream_putc(FAR struct lib_outstream_s *this, int ch)
void emergstream(FAR struct lib_outstream_s *stream)
{
stream->put = emergstream_putc;
#ifdef CONFIG_STDIO_LINEBUFFER
stream->flush = lib_noflush;
#endif
stream->nput = 0;
}
-2
View File
@@ -109,8 +109,6 @@ static void syslogstream_putc(FAR struct lib_outstream_s *this, int ch)
void syslogstream(FAR struct lib_outstream_s *stream)
{
stream->put = syslogstream_putc;
#ifdef CONFIG_STDIO_LINEBUFFER
stream->flush = lib_noflush;
#endif
stream->nput = 0;
}
+6
View File
@@ -251,6 +251,12 @@ FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb)
stream->fs_bufpos = stream->fs_bufstart;
stream->fs_bufpos = stream->fs_bufstart;
stream->fs_bufread = stream->fs_bufstart;
/* Setup buffer flags */
#ifdef CONFIG_STDIO_LINEBUFFER
stream->fs_flags |= __FS_FLAG_LBF; /* Line buffering */
#endif
#endif
/* Save the file description and open flags. Setting the
* file descriptor locks this stream.
+2 -1
View File
@@ -65,7 +65,8 @@
#define __FS_FLAG_EOF (1 << 0) /* EOF detected by a read operation */
#define __FS_FLAG_ERROR (1 << 1) /* Error detected by any operation */
#define __FS_FLAG_UBF (1 << 2) /* Buffer allocated by caller of setvbuf */
#define __FS_FLAG_LBF (1 << 2) /* Line buffered */
#define __FS_FLAG_UBF (1 << 3) /* Buffer allocated by caller of setvbuf */
/* Inode i_flag values:
*
+2 -10
View File
@@ -70,9 +70,7 @@ struct lib_instream_s
struct lib_outstream_s
{
lib_putc_t put; /* Put one character to the outstream */
#ifdef CONFIG_STDIO_LINEBUFFER
lib_flush_t flush; /* Flush any buffered characters in the outstream */
#endif
int nput; /* Total number of characters put. Written
* by put method, readable by user */
};
@@ -101,9 +99,7 @@ struct lib_sistream_s
struct lib_sostream_s
{
lib_soputc_t put; /* Put one character to the outstream */
#ifdef CONFIG_STDIO_LINEBUFFER
lib_soflush_t flush; /* Flush any buffered characters in the outstream */
#endif
lib_soseek_t seek; /* Seek a position in the output stream */
int nput; /* Total number of characters put. Written
* by put method, readable by user */
@@ -389,23 +385,21 @@ void emergstream(FAR struct lib_outstream_s *stream);
*
* Description:
* lib_noflush() provides a common, dummy flush method for output streams
* that are not flushable. Only used if CONFIG_STDIO_LINEBUFFER is selected.
* that are not flushable.
*
* Return:
* Always returns OK
*
****************************************************************************/
#ifdef CONFIG_STDIO_LINEBUFFER
int lib_noflush(FAR struct lib_outstream_s *stream);
#endif
/****************************************************************************
* Name: lib_snoflush
*
* Description:
* lib_snoflush() provides a common, dummy flush method for seekable output
* streams that are not flushable. Only used if CONFIG_STDIO_LINEBUFFER
* streams that are not flushable.
* is selected.
*
* Return:
@@ -413,9 +407,7 @@ int lib_noflush(FAR struct lib_outstream_s *stream);
*
****************************************************************************/
#ifdef CONFIG_STDIO_LINEBUFFER
int lib_snoflush(FAR struct lib_sostream_s *this);
#endif
/****************************************************************************
* Name: lib_sprintf and lib_vsprintf
+1 -5
View File
@@ -65,7 +65,7 @@ CSRCS += lib_rdflush.c lib_wrflush.c lib_fputc.c lib_puts.c lib_fputs.c
CSRCS += lib_ungetc.c lib_vprintf.c lib_fprintf.c lib_vfprintf.c
CSRCS += lib_stdinstream.c lib_stdoutstream.c lib_stdsistream.c
CSRCS += lib_stdsostream.c lib_perror.c lib_feof.c lib_ferror.c
CSRCS += lib_clearerr.c lib_setvbuf.c
CSRCS += lib_clearerr.c lib_setvbuf.c lib_libnoflush.c lib_libsnoflush.c
endif
@@ -80,10 +80,6 @@ ifeq ($(CONFIG_LIBC_FLOATINGPOINT),y)
CSRCS += lib_dtoa.c
endif
ifeq ($(CONFIG_STDIO_LINEBUFFER),y)
CSRCS += lib_libnoflush.c lib_libsnoflush.c
endif
# Add the stdio directory to the build
DEPPATH += --dep-path stdio
+3 -4
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* libc/stdio/lib_fputc.c
*
* Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2007, 2008, 2011-2012, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -58,8 +58,7 @@ int fputc(int c, FAR FILE *stream)
{
/* Flush the buffer if a newline is output */
#ifdef CONFIG_STDIO_LINEBUFFER
if (c == '\n')
if (c == '\n' && (stream->fs_flags & __FS_FLAG_LBF) != 0)
{
ret = lib_fflush(stream, true);
if (ret < 0)
@@ -67,7 +66,7 @@ int fputc(int c, FAR FILE *stream)
return EOF;
}
}
#endif
return c;
}
else
+53 -57
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* libc/stdio/lib_fputs.c
*
* Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2007, 2008, 2011-2012, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -90,52 +90,7 @@ int fputs(FAR const char *s, FAR FILE *stream)
/* Flush the buffer if a newline was written to the buffer */
#ifdef CONFIG_STDIO_LINEBUFFER
if (ch == '\n')
{
ret = lib_fflush(stream, true);
if (ret < 0)
{
return EOF;
}
}
#endif
}
return nput;
}
#elif defined(CONFIG_STDIO_LINEBUFFER)
int fputs(FAR const char *s, FAR FILE *stream)
{
int nput;
int ret;
/* Make sure that a string was provided. */
#ifdef CONFIG_DEBUG_FEATURES /* Most parameter checking is disabled if DEBUG is off */
if (!s)
{
set_errno(EINVAL);
return EOF;
}
#endif
/* Write the string. Loop until the null terminator is encountered */
for (nput = 0; *s; nput++, s++)
{
/* Write the next character to the stream buffer */
ret = lib_fwrite(s, 1, stream);
if (ret <= 0)
{
return EOF;
}
/* Flush the buffer if a newline was written to the buffer */
if (*s == '\n')
if (ch == '\n' && (stream->fs_flags & __FS_FLAG_LBF) != 0)
{
ret = lib_fflush(stream, true);
if (ret < 0)
@@ -151,34 +106,75 @@ int fputs(FAR const char *s, FAR FILE *stream)
#else
int fputs(FAR const char *s, FAR FILE *stream)
{
int ntowrite;
int nput;
/* Make sure that a string was provided. */
#ifdef CONFIG_DEBUG_FEATURES /* Most parameter checking is disabled if DEBUG is off */
if (!s)
if (s == NULL || stream == NULL)
{
set_errno(EINVAL);
return EOF;
}
#endif
/* Get the length of the string. */
/* If line buffering is enabled, then we will have to output one character
* at a time, checking for a newline character each time.
*/
ntowrite = strlen(s);
if (ntowrite == 0)
if ((stream->fs_flags & __FS_FLAG_LBF) != 0)
{
return 0;
int ret;
/* Write the string. Loop until the null terminator is encountered */
for (nput = 0; *s; nput++, s++)
{
/* Write the next character to the stream buffer */
ret = lib_fwrite(s, 1, stream);
if (ret <= 0)
{
return EOF;
}
/* Flush the buffer if a newline was written to the buffer */
if (*s == '\n')
{
ret = lib_fflush(stream, true);
if (ret < 0)
{
return EOF;
}
}
}
}
/* Write the string */
/* Without line buffering, we can write the whole string in one operation. */
nput = lib_fwrite(s, ntowrite, stream);
if (nput < 0)
else
{
return EOF;
int ntowrite;
/* Get the length of the string. */
ntowrite = strlen(s);
if (ntowrite == 0)
{
return 0;
}
/* Write the string */
nput = lib_fwrite(s, ntowrite, stream);
if (nput < 0)
{
return EOF;
}
}
return nput;
}
#endif
+2 -7
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* libc/stdio/lib_libnoflush.c
*
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2011-2012, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -49,8 +49,6 @@
#include "libc.h"
#ifdef CONFIG_STDIO_LINEBUFFER
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -60,7 +58,7 @@
*
* Description:
* lib_noflush() provides a common, dummy flush method for output streams
* that are not flushable. Only used if CONFIG_STDIO_LINEBUFFER is selected.
* that are not flushable.
*
* Return:
* Always returns OK
@@ -71,6 +69,3 @@ int lib_noflush(FAR struct lib_outstream_s *this)
{
return OK;
}
#endif /* CONFIG_STDIO_LINEBUFFER */
+2 -8
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* libc/stdio/lib_libsnoflush.c
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -48,8 +48,6 @@
#include "libc.h"
#ifdef CONFIG_STDIO_LINEBUFFER
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -59,8 +57,7 @@
*
* Description:
* lib_snoflush() provides a common, dummy flush method for seekable output
* streams that are not flushable. Only used if CONFIG_STDIO_LINEBUFFER
* is selected.
* streams that are not flushable.
*
* Return:
* Always returns OK
@@ -71,6 +68,3 @@ int lib_snoflush(FAR struct lib_sostream_s *this)
{
return OK;
}
#endif /* CONFIG_STDIO_LINEBUFFER */
+1 -2
View File
@@ -1193,14 +1193,13 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
/* Flush the buffer if a newline is encountered */
#ifdef CONFIG_STDIO_LINEBUFFER
if (FMT_CHAR == '\n')
{
/* Should return an error on a failure to flush */
(void)obj->flush(obj);
}
#endif
/* Process the next character in the format */
continue;
+1 -3
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* libc/stdio/lib_lowoutstream.c
*
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2012, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -88,9 +88,7 @@ static void lowoutstream_putc(FAR struct lib_outstream_s *this, int ch)
void lib_lowoutstream(FAR struct lib_outstream_s *stream)
{
stream->put = lowoutstream_putc;
#ifdef CONFIG_STDIO_LINEBUFFER
stream->flush = lib_noflush;
#endif
stream->nput = 0;
}
+1 -3
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* libc/stdio/lib_memoutstream.c
*
* Copyright (C) 2007-2009, 2011-2012, 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2012, 2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -93,9 +93,7 @@ void lib_memoutstream(FAR struct lib_memoutstream_s *outstream,
FAR char *bufstart, int buflen)
{
outstream->public.put = memoutstream_putc;
#ifdef CONFIG_STDIO_LINEBUFFER
outstream->public.flush = lib_noflush;
#endif
outstream->public.nput = 0; /* Will be buffer index */
outstream->buffer = bufstart; /* Start of buffer */
outstream->buflen = buflen - 1; /* Save space for null terminator */
+1 -3
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* libc/stdio/lib_memsostream.c
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -137,9 +137,7 @@ void lib_memsostream(FAR struct lib_memsostream_s *outstream,
FAR char *bufstart, int buflen)
{
outstream->public.put = memsostream_putc;
#ifdef CONFIG_STDIO_LINEBUFFER
outstream->public.flush = lib_snoflush;
#endif
outstream->public.seek = memsostream_seek;
outstream->public.nput = 0; /* Total number of characters written */
outstream->buffer = bufstart; /* Start of buffer */
+1 -3
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* libc/stdio/lib_nulloutstream.c
*
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2012, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -76,9 +76,7 @@ static void nulloutstream_putc(FAR struct lib_outstream_s *this, int ch)
void lib_nulloutstream(FAR struct lib_outstream_s *nulloutstream)
{
nulloutstream->put = nulloutstream_putc;
#ifdef CONFIG_STDIO_LINEBUFFER
nulloutstream->flush = lib_noflush;
#endif
nulloutstream->nput = 0;
}
+9 -6
View File
@@ -76,15 +76,18 @@ int puts(FAR const char *s)
{
nput = nwritten + 1;
/* Flush the buffer after the newline is output. */
/* Flush the buffer after the newline is output if line buffering
* is enabled.
*/
#ifdef CONFIG_STDIO_LINEBUFFER
ret = lib_fflush(stream, true);
if (ret < 0)
if ((stream->fs_flags & __FS_FLAG_LBF) != 0)
{
nput = EOF;
ret = lib_fflush(stream, true);
if (ret < 0)
{
nput = EOF;
}
}
#endif
}
}
+1 -3
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* libc/stdio/lib_rawsostream.c
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -119,9 +119,7 @@ static off_t rawsostream_seek(FAR struct lib_sostream_s *this, off_t offset,
void lib_rawsostream(FAR struct lib_rawsostream_s *outstream, int fd)
{
outstream->public.put = rawsostream_putc;
#ifdef CONFIG_STDIO_LINEBUFFER
outstream->public.flush = lib_snoflush;
#endif
outstream->public.seek = rawsostream_seek;
outstream->public.nput = 0;
outstream->fd = fd;
-2
View File
@@ -108,9 +108,7 @@ static void rawoutstream_putc(FAR struct lib_outstream_s *this, int ch)
void lib_rawoutstream(FAR struct lib_rawoutstream_s *outstream, int fd)
{
outstream->public.put = rawoutstream_putc;
#ifdef CONFIG_STDIO_LINEBUFFER
outstream->public.flush = lib_noflush;
#endif
outstream->public.nput = 0;
outstream->fd = fd;
}
+30 -20
View File
@@ -76,16 +76,10 @@
* by the setvbuf() function. The contents of the array at any time are
* unspecified.
*
* REVISIT: This initial version of setvbuf has some severe limitations and
* not all features features required by the specification are available.
* These the limitations are the result of hard-coded stream logic based
* the static configuration. This logic cannot support variable behaviors
* without some additional logic. Specifically, we cannot support:
*
* - Any line buffering state that is inconsistent with the configuration
* setting CONFIG_STDIO_LINEBUFFER
* - We cannot support disabling stream buffering if
* CONFIG_STDIO_BUFFER_SIZE > 0
* REVISIT: This initial version of setvbuf has some limitations and not
* all features features required by the specification are available.
* Specifically, this current implementation cannot support sisabling
* stream buffering if CONFIG_STDIO_BUFFER_SIZE > 0
*
* Parmeters:
* stream - the stream to flush
@@ -141,21 +135,17 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size)
goto errout;
}
#if 1 /* REVISIT */
/* Not all features are be available. Without some additional logic,
* we cannot support (1) any line buffering state that is inconsistent
* with CONFIG_STDIO_LINEBUFFER nor can we (2) disable buffering if
* CONFIG_STDIO_BUFFER_SIZE > 0
* we cannot disable buffering if CONFIG_STDIO_BUFFER_SIZE > 0
*/
#ifdef CONFIG_STDIO_LINEBUFFER
if (mode != _IOLBF)
#else
if (mode != _IOFBF)
#endif
if (mode == _IONBF)
{
errcode = ENOSYS;
goto errout;
}
#endif
/* Make sure that we have exclusive access to the stream */
@@ -189,7 +179,11 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size)
* successful.
*/
flags = stream->fs_flags & ~__FS_FLAG_UBF;
#if 1 /* REVISIT: _IONBF not yet supported */
flags = stream->fs_flags & ~(__FS_FLAG_LBF | __FS_FLAG_UBF);
#else
flags = stream->fs_flags & ~(__FS_FLAG_LBF | __FS_FLAG_NBF | __FS_FLAG_UBF);
#endif
/* Allocate a new buffer if one is needed. We have already verified that:
*
@@ -200,7 +194,7 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size)
* That simplifies the following check:
*/
#if 0 /* size should always be > 0 in the currently supported configurations */
#if 0 /* REVISIT: _IONBF not yet supported */
if (size > 0)
#else
DEBUGASSERT(size > 0);
@@ -246,7 +240,23 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size)
stream->fs_bufend = newbuf;
stream->fs_bufpos = newbuf;
stream->fs_bufread = newbuf;
/* Check for line buffering */
if (mode == _IOLBF)
{
flags |= __FS_FLAG_LBF;
}
}
#if 0 /* REVISIT: _IONBF not yet supported */
else
{
/* No buffer needed... We must be performing unbuffered I/O */
DEBUGASSERT(mode == _IONBF);
flags |= __FS_FLAG_NBF;
}
#endif
/* Update the stream flags and return success */
+1 -3
View File
@@ -82,7 +82,7 @@ static void stdoutstream_putc(FAR struct lib_outstream_s *this, int ch)
* Name: stdoutstream_flush
****************************************************************************/
#if defined(CONFIG_STDIO_LINEBUFFER) && CONFIG_STDIO_BUFFER_SIZE > 0
#if CONFIG_STDIO_BUFFER_SIZE > 0
static int stdoutstream_flush(FAR struct lib_outstream_s *this)
{
FAR struct lib_stdoutstream_s *sthis = (FAR struct lib_stdoutstream_s *)this;
@@ -125,7 +125,6 @@ void lib_stdoutstream(FAR struct lib_stdoutstream_s *outstream,
* meaning.
*/
#ifdef CONFIG_STDIO_LINEBUFFER
#if CONFIG_STDIO_BUFFER_SIZE > 0
if ((stream->fs_oflags & O_BINARY) == 0)
{
@@ -136,7 +135,6 @@ void lib_stdoutstream(FAR struct lib_stdoutstream_s *outstream,
{
outstream->public.flush = lib_noflush;
}
#endif
/* Set the number of bytes put to zero and remember the stream */
+2 -4
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* libc/stdio/lib_stdsostream.c
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -82,7 +82,7 @@ static void stdsostream_putc(FAR struct lib_sostream_s *this, int ch)
* Name: stdsostream_flush
****************************************************************************/
#if defined(CONFIG_STDIO_LINEBUFFER) && CONFIG_STDIO_BUFFER_SIZE > 0
#if CONFIG_STDIO_BUFFER_SIZE > 0
static int stdsostream_flush(FAR struct lib_sostream_s *this)
{
FAR struct lib_stdsostream_s *sthis = (FAR struct lib_stdsostream_s *)this;
@@ -138,7 +138,6 @@ void lib_stdsostream(FAR struct lib_stdsostream_s *outstream,
* meaning.
*/
#ifdef CONFIG_STDIO_LINEBUFFER
#if CONFIG_STDIO_BUFFER_SIZE > 0
if ((stream->fs_oflags & O_BINARY) == 0)
{
@@ -149,7 +148,6 @@ void lib_stdsostream(FAR struct lib_stdsostream_s *outstream,
{
outstream->public.flush = lib_snoflush;
}
#endif
/* Select the seek operation */