This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new c30413540c5 libs/libc/stdio: Add <stdio_ext.h>.
c30413540c5 is described below
commit c30413540c58fd5f8db26115dce3e7ceecdeb6b2
Author: Marco Casaroli <[email protected]>
AuthorDate: Thu Oct 8 22:01:13 2026 +0200
libs/libc/stdio: Add <stdio_ext.h>.
glibc and musl provide <stdio_ext.h>, with functions that report or
change the state of a stream: pending output, read-ahead, line
buffering, the error flag, purge. Portable code uses them instead of
looking inside FILE, and fails to build on a C library without them.
Add __fbufsize(), __fpending(), __freading(), __fwriting(),
__freadable(), __fwritable(), __flbf(), __fpurge(), __freadahead(),
__freadptr(), __freadptrinc(), __fseterr(), __fsetlocking() and
_flushlbf(), built on the buffer pointers of struct file_struct. They
are built with CONFIG_FILE_STREAM, like the rest of the stream
functions.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <[email protected]>
---
include/stdio_ext.h | 79 ++++++++++
libs/libc/stdio/CMakeLists.txt | 3 +-
libs/libc/stdio/Make.defs | 2 +-
libs/libc/stdio/lib_stdio_ext.c | 317 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 399 insertions(+), 2 deletions(-)
diff --git a/include/stdio_ext.h b/include/stdio_ext.h
new file mode 100644
index 00000000000..e3c56096f45
--- /dev/null
+++ b/include/stdio_ext.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * include/stdio_ext.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_STDIO_EXT_H
+#define __INCLUDE_STDIO_EXT_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdio.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Values for __fsetlocking() */
+
+#define FSETLOCKING_QUERY 0 /* Only return the current mode */
+#define FSETLOCKING_INTERNAL 1 /* The library locks the stream */
+#define FSETLOCKING_BYCALLER 2 /* The caller locks the stream */
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/* These functions give access to the state of a stream. glibc and musl
+ * provide them, and portable code (gnulib, for example) uses them instead
+ * of looking inside FILE.
+ */
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+size_t __fbufsize(FAR FILE *stream);
+size_t __fpending(FAR FILE *stream);
+int __freading(FAR FILE *stream);
+int __fwriting(FAR FILE *stream);
+int __freadable(FAR FILE *stream);
+int __fwritable(FAR FILE *stream);
+int __flbf(FAR FILE *stream);
+void __fpurge(FAR FILE *stream);
+size_t __freadahead(FAR FILE *stream);
+FAR const char *__freadptr(FAR FILE *stream, FAR size_t *sizep);
+void __freadptrinc(FAR FILE *stream, size_t inc);
+void __fseterr(FAR FILE *stream);
+int __fsetlocking(FAR FILE *stream, int type);
+void _flushlbf(void);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_STDIO_EXT_H */
diff --git a/libs/libc/stdio/CMakeLists.txt b/libs/libc/stdio/CMakeLists.txt
index a41cff00efb..8d2982192aa 100644
--- a/libs/libc/stdio/CMakeLists.txt
+++ b/libs/libc/stdio/CMakeLists.txt
@@ -106,7 +106,8 @@ if(CONFIG_FILE_STREAM)
lib_open_memstream.c
lib_fgetwc.c
lib_getwc.c
- lib_ungetwc.c)
+ lib_ungetwc.c
+ lib_stdio_ext.c)
endif()
target_sources(c PRIVATE ${SRCS})
diff --git a/libs/libc/stdio/Make.defs b/libs/libc/stdio/Make.defs
index 218d494879d..af412a2c915 100644
--- a/libs/libc/stdio/Make.defs
+++ b/libs/libc/stdio/Make.defs
@@ -46,7 +46,7 @@ CSRCS += lib_scanf.c lib_vscanf.c lib_fscanf.c lib_vfscanf.c
lib_tmpfile.c
CSRCS += lib_setbuf.c lib_setvbuf.c lib_libfilelock.c lib_libgetstreams.c
CSRCS += lib_setbuffer.c lib_fputwc.c lib_putwc.c lib_fputws.c
CSRCS += lib_fopencookie.c lib_fmemopen.c lib_open_memstream.c lib_fgetwc.c
-CSRCS += lib_getwc.c lib_ungetwc.c
+CSRCS += lib_getwc.c lib_ungetwc.c lib_stdio_ext.c
endif
# Add the stdio directory to the build
diff --git a/libs/libc/stdio/lib_stdio_ext.c b/libs/libc/stdio/lib_stdio_ext.c
new file mode 100644
index 00000000000..120bd7d0824
--- /dev/null
+++ b/libs/libc/stdio/lib_stdio_ext.c
@@ -0,0 +1,317 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_ext.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/* Does the buffer hold read data? The buffer holds read data between
+ * fs_bufstart and fs_bufread, or write data between fs_bufstart and
+ * fs_bufpos (then fs_bufread == fs_bufstart).
+ */
+
+static bool stdio_ext_reading(FAR FILE *stream)
+{
+#if CONFIG_NUNGET_CHARS > 0
+ if (stream->fs_nungotten > 0)
+ {
+ return true;
+ }
+#endif
+
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+ return stream->fs_bufstart != NULL &&
+ stream->fs_bufread != stream->fs_bufstart;
+#else
+ return false;
+#endif
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: __fbufsize
+ *
+ * Description:
+ * Return the size of the buffer of the stream.
+ *
+ ****************************************************************************/
+
+size_t __fbufsize(FAR FILE *stream)
+{
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+ if (stream->fs_bufstart != NULL)
+ {
+ return stream->fs_bufend - stream->fs_bufstart;
+ }
+#endif
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: __fpending
+ *
+ * Description:
+ * Return the number of bytes in the output buffer of the stream.
+ *
+ ****************************************************************************/
+
+size_t __fpending(FAR FILE *stream)
+{
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+ if (stream->fs_bufstart != NULL &&
+ stream->fs_bufread == stream->fs_bufstart)
+ {
+ return stream->fs_bufpos - stream->fs_bufstart;
+ }
+#endif
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: __freading
+ *
+ * Description:
+ * Return non-zero if the stream is read-only, or if the last operation on
+ * it was a read.
+ *
+ ****************************************************************************/
+
+int __freading(FAR FILE *stream)
+{
+ return (stream->fs_oflags & O_ACCMODE) == O_RDONLY ||
+ stdio_ext_reading(stream);
+}
+
+/****************************************************************************
+ * Name: __fwriting
+ *
+ * Description:
+ * Return non-zero if the stream is write-only, or if the last operation
+ * on it was a write.
+ *
+ ****************************************************************************/
+
+int __fwriting(FAR FILE *stream)
+{
+ return (stream->fs_oflags & O_ACCMODE) == O_WRONLY ||
+ __fpending(stream) > 0;
+}
+
+/****************************************************************************
+ * Name: __freadable
+ *
+ * Description:
+ * Return non-zero if the stream may be read.
+ *
+ ****************************************************************************/
+
+int __freadable(FAR FILE *stream)
+{
+ return (stream->fs_oflags & O_ACCMODE) != O_WRONLY;
+}
+
+/****************************************************************************
+ * Name: __fwritable
+ *
+ * Description:
+ * Return non-zero if the stream may be written.
+ *
+ ****************************************************************************/
+
+int __fwritable(FAR FILE *stream)
+{
+ return (stream->fs_oflags & O_ACCMODE) != O_RDONLY;
+}
+
+/****************************************************************************
+ * Name: __flbf
+ *
+ * Description:
+ * Return non-zero if the stream is line buffered.
+ *
+ ****************************************************************************/
+
+int __flbf(FAR FILE *stream)
+{
+ return (stream->fs_flags & __FS_FLAG_LBF) != 0;
+}
+
+/****************************************************************************
+ * Name: __fpurge
+ *
+ * Description:
+ * Discard the contents of the buffer of the stream: unread input,
+ * pushed-back characters and unwritten output.
+ *
+ ****************************************************************************/
+
+void __fpurge(FAR FILE *stream)
+{
+ flockfile(stream);
+
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+ stream->fs_bufpos = stream->fs_bufstart;
+ stream->fs_bufread = stream->fs_bufstart;
+#endif
+
+#if CONFIG_NUNGET_CHARS > 0
+ stream->fs_nungotten = 0;
+#endif
+
+ funlockfile(stream);
+}
+
+/****************************************************************************
+ * Name: __freadahead
+ *
+ * Description:
+ * Return the number of bytes that have been read into the buffer, or
+ * pushed back, and not yet consumed.
+ *
+ ****************************************************************************/
+
+size_t __freadahead(FAR FILE *stream)
+{
+ size_t n = 0;
+
+ if (!stdio_ext_reading(stream))
+ {
+ return 0;
+ }
+
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+ if (stream->fs_bufstart != NULL)
+ {
+ n = stream->fs_bufread - stream->fs_bufpos;
+ }
+#endif
+
+#if CONFIG_NUNGET_CHARS > 0
+ n += stream->fs_nungotten;
+#endif
+
+ return n;
+}
+
+/****************************************************************************
+ * Name: __freadptr
+ *
+ * Description:
+ * Return a pointer to the bytes in the read buffer that have not been
+ * consumed, and their number in *sizep. Return NULL if there are none,
+ * or if characters have been pushed back.
+ *
+ ****************************************************************************/
+
+FAR const char *__freadptr(FAR FILE *stream, FAR size_t *sizep)
+{
+#if CONFIG_NUNGET_CHARS > 0
+ if (stream->fs_nungotten > 0)
+ {
+ return NULL;
+ }
+#endif
+
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+ if (stdio_ext_reading(stream) && stream->fs_bufread > stream->fs_bufpos)
+ {
+ *sizep = stream->fs_bufread - stream->fs_bufpos;
+ return stream->fs_bufpos;
+ }
+#endif
+
+ return NULL;
+}
+
+/****************************************************************************
+ * Name: __freadptrinc
+ *
+ * Description:
+ * Consume inc bytes of the read buffer (see __freadptr()).
+ *
+ ****************************************************************************/
+
+void __freadptrinc(FAR FILE *stream, size_t inc)
+{
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+ stream->fs_bufpos += inc;
+#endif
+}
+
+/****************************************************************************
+ * Name: __fseterr
+ *
+ * Description:
+ * Set the error indicator of the stream.
+ *
+ ****************************************************************************/
+
+void __fseterr(FAR FILE *stream)
+{
+ stream->fs_flags |= __FS_FLAG_ERROR;
+}
+
+/****************************************************************************
+ * Name: __fsetlocking
+ *
+ * Description:
+ * The library always locks the stream; the type is ignored.
+ *
+ ****************************************************************************/
+
+int __fsetlocking(FAR FILE *stream, int type)
+{
+ UNUSED(stream);
+ UNUSED(type);
+
+ return FSETLOCKING_INTERNAL;
+}
+
+/****************************************************************************
+ * Name: _flushlbf
+ *
+ * Description:
+ * Flush all line-buffered streams. NuttX flushes all streams.
+ *
+ ****************************************************************************/
+
+void _flushlbf(void)
+{
+ fflush(NULL);
+}