<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>The GNU C++ Library</title><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><meta name="description" content="Short Contents Copyright (C) 2008-2025 FSF Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. This is the top level of the libstdc++ documentation set. The documentation is divided into the following three sections. Manual Frequently Asked Questions API and Source Documentation" /><meta name="keywords" content="ISO C++, runtime, library" /><link rel="home" href="index.html" title="The GNU C++ Library" /><link rel="next" href="manual/index.html" title="The GNU C++ Library Manual" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">The GNU C++ Library</th></tr><tr><td width="20%" align="left"> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="manual/index.html">Next</a></td></tr></table><hr /></div><div class="set" lang="en" xml:lang="en"><div class="titlepage"><div><div><h1 class="title"><a id="set-index"></a>The GNU C++ Library</h1></div><div><div class="abstract"><a id="contents"></a><p class="title"><strong>Short Contents</strong></p><p>
- Copyright (C) 2008-2025
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>The GNU C++ Library</title><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><meta name="description" content="Short Contents Copyright (C) 2008-2026 FSF Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. This is the top level of the libstdc++ documentation set. The documentation is divided into the following three sections. Manual Frequently Asked Questions API and Source Documentation" /><meta name="keywords" content="ISO C++, runtime, library" /><link rel="home" href="index.html" title="The GNU C++ Library" /><link rel="next" href="manual/index.html" title="The GNU C++ Library Manual" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">The GNU C++ Library</th></tr><tr><td width="20%" align="left"> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="manual/index.html">Next</a></td></tr></table><hr /></div><div class="set" lang="en" xml:lang="en"><div class="titlepage"><div><div><h1 class="title"><a id="set-index"></a>The GNU C++ Library</h1></div><div><div class="abstract"><a id="contents"></a><p class="title"><strong>Short Contents</strong></p><p>
+ Copyright (C) 2008-2026
<a class="link" href="https://www.fsf.org" target="_top">FSF
</a>
</p><p>
is required for use of experimental C++ library features.
This currently provides support for the C++23 types defined in the
<code class="filename"><stacktrace></code> header,
+ the C++23 functions defined in the
+ <code class="filename"><print></code> header,
the Filesystem library extensions defined in the
<code class="filename"><experimental/filesystem></code>
header,
mode will revert to the non-conforming implementation used prior to the
<a class="link" href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112591" target="_top">PR112591</a>
in GCC-16. Has no impact for C++20 or later modes.
+ </p></dd><dt><span class="term"><code class="code">_GLIBCXX_NO_INLINE_PRINT</code></span></dt><dd><p>
+ Undefined by default. When defined <code class="code">std::print</code> and
+ <code class="code">std::println</code> are not implemented using inline functions.
+ This means that code using those functions will compile faster,
+ but <code class="option">-lstdc++exp</code> must be used when linking.
+ The non-inline definitions are compiled using
+ <code class="option">-fexec-charset=UTF-8</code> so might give incorrect results
+ if called from a source file that uses a non-Unicode encoding,
+ especially for format strings using non-ASCII fill characters.
</p></dd></dl></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="using_headers.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="using.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="using_dual_abi.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Headers </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Dual ABI</td></tr></table></div></body></html>
\ No newline at end of file
is required for use of experimental C++ library features.
This currently provides support for the C++23 types defined in the
<filename class="headerfile"><stacktrace></filename> header,
+ the C++23 functions defined in the
+ <filename class="headerfile"><print></filename> header,
the Filesystem library extensions defined in the
<filename class="headerfile"><experimental/filesystem></filename>
header,
in GCC-16. Has no impact for C++20 or later modes.
</para>
</listitem></varlistentry>
+ <varlistentry><term><code>_GLIBCXX_NO_INLINE_PRINT</code></term>
+ <listitem>
+ <para>
+ Undefined by default. When defined <code>std::print</code> and
+ <code>std::println</code> are not implemented using inline functions.
+ This means that code using those functions will compile faster,
+ but <option>-lstdc++exp</option> must be used when linking.
+ The non-inline definitions are compiled using
+ <option>-fexec-charset=UTF-8</option> so might give incorrect results
+ if called from a source file that uses a non-Unicode encoding,
+ especially for format strings using non-ASCII fill characters.
+ </para>
+ </listitem></varlistentry>
</variablelist>
</section>
${bits_srcdir}/node_handle.h \
${bits_srcdir}/ostream.tcc \
${bits_srcdir}/ostream_insert.h \
+ ${bits_srcdir}/ostream_print.h \
${bits_srcdir}/postypes.h \
+ ${bits_srcdir}/print.h \
${bits_srcdir}/quoted_string.h \
${bits_srcdir}/random.h \
${bits_srcdir}/random.tcc \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/node_handle.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/ostream.tcc \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/ostream_insert.h \
+@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/ostream_print.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/postypes.h \
+@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/print.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/quoted_string.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/random.h \
@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/random.tcc \
--- /dev/null
+// Inline implementation details for std::print functions -*- C++ -*-
+
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/bits/ostream_print.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{ostream}
+ *
+ * This file contains the parts of `<ostream>` which are currently defined
+ * inline, but should be moved into the library eventually.
+ */
+
+#ifndef _GLIBCXX_OSTREAM_PRINT_H
+#define _GLIBCXX_OSTREAM_PRINT_H 1
+
+#ifdef _GLIBCXX_SYSHDR
+#pragma GCC system_header
+#endif
+
+#include <bits/requires_hosted.h> // for std::format
+
+#include <bits/version.h>
+
+#ifdef __glibcxx_print // C++ >= 23
+#include <format>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+#ifdef _GLIBCXX_NO_INLINE_PRINT
+# define _GLIBCXX_PRINT_INLINE_USED [[__gnu__::__used__]]
+#else
+# define _GLIBCXX_PRINT_INLINE_USED
+#endif
+
+ _GLIBCXX_PRINT_INLINE_USED
+ inline void
+ vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args)
+ {
+ ostream::sentry __cerb(__os);
+ if (__cerb)
+ {
+ __format::_Str_sink<char> __buf;
+ std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);
+ auto __out = __buf.view();
+
+ __try
+ {
+ std::__ostream_write(__os, __out.data(), __out.size());
+ }
+ __catch(const __cxxabiv1::__forced_unwind&)
+ {
+ __os._M_setstate(ios_base::badbit);
+ __throw_exception_again;
+ }
+ __catch(...)
+ { __os._M_setstate(ios_base::badbit); }
+ }
+ }
+
+ _GLIBCXX_PRINT_INLINE_USED
+ inline void
+ vprint_unicode(ostream& __os, string_view __fmt, format_args __args)
+ {
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ // For most targets we don't need to do anything special to write
+ // Unicode to a terminal.
+ std::vprint_nonunicode(__os, __fmt, __args);
+#else
+ ostream::sentry __cerb(__os);
+ if (__cerb)
+ {
+ __format::_Str_sink<char> __buf;
+ std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);
+ auto __out = __buf._M_span();
+
+ void* __open_terminal(streambuf*);
+ error_code __write_to_terminal(void*, span<char>);
+ // If stream refers to a terminal, write a Unicode string to it.
+ if (auto __term = __open_terminal(__os.rdbuf()))
+ {
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ // For POSIX, __open_terminal(streambuf*) uses fdopen to open a
+ // new file, so we would need to close it here. This code is not
+ // actually compiled because it's inside an #ifdef _WIN32 group,
+ // but just in case that changes in future ...
+ struct _Guard
+ {
+ _Guard(void* __p) : _M_f((FILE*)__p) { }
+ ~_Guard() { std::fclose(_M_f); }
+ _Guard(_Guard&&) = delete;
+ _Guard& operator=(_Guard&&) = delete;
+ FILE* _M_f;
+ };
+ _Guard __g(__term);
+#endif
+
+ ios_base::iostate __err = ios_base::goodbit;
+ __try
+ {
+ if (__os.rdbuf()->pubsync() == -1)
+ __err = ios::badbit;
+ else if (auto __e = __write_to_terminal(__term, __out))
+ if (__e != std::make_error_code(errc::illegal_byte_sequence))
+ __err = ios::badbit;
+ }
+ __catch(const __cxxabiv1::__forced_unwind&)
+ {
+ __os._M_setstate(ios_base::badbit);
+ __throw_exception_again;
+ }
+ __catch(...)
+ { __os._M_setstate(ios_base::badbit); }
+
+ if (__err)
+ __os.setstate(__err);
+ return;
+ }
+
+ // Otherwise just insert the string as vprint_nonunicode does.
+ __try
+ {
+ std::__ostream_write(__os, __out.data(), __out.size());
+ }
+ __catch(const __cxxabiv1::__forced_unwind&)
+ {
+ __os._M_setstate(ios_base::badbit);
+ __throw_exception_again;
+ }
+ __catch(...)
+ { __os._M_setstate(ios_base::badbit); }
+ }
+#endif // _WIN32
+ }
+#undef _GLIBCXX_PRINT_INLINE_USED
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // __glibcxx_print
+#endif // _GLIBCXX_OSTREAM_PRINT_H
--- /dev/null
+// Inline implementation details for std::print functions -*- C++ -*-
+
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/bits/print.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{print}
+ *
+ * This file contains the parts of `<print>` which are currently defined
+ * inline, but should be moved into the library eventually.
+ */
+
+#ifndef _GLIBCXX_PRINT_H
+#define _GLIBCXX_PRINT_H 1
+
+#ifdef _GLIBCXX_SYSHDR
+#pragma GCC system_header
+#endif
+
+#include <bits/requires_hosted.h> // for std::format
+
+#include <bits/version.h>
+
+#ifdef __glibcxx_print // C++ >= 23
+
+#include <format>
+#include <cstdio> // FILE, EOF, flockfile, etc.
+#include <cerrno> // EACCES, EIO
+#include <bits/functexcept.h> // __throw_system_error
+
+#ifdef _WIN32
+# include <system_error> // system_error
+#endif
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+namespace __format
+{
+#if _GLIBCXX_USE_STDIO_LOCKING && _GLIBCXX_USE_GLIBC_STDIO_EXT
+ // These are defined in <stdio_ext.h> but we don't want to include that.
+ extern "C" int __fwritable(FILE*) noexcept;
+ extern "C" int __flbf(FILE*) noexcept;
+ extern "C" size_t __fbufsize(FILE*) noexcept;
+
+ // A format sink that writes directly to a Glibc FILE.
+ // The file is locked on construction and its buffer is accessed directly.
+ class _File_sink final : _Buf_sink<char>
+ {
+ struct _File
+ {
+ explicit
+ _File(FILE* __f) : _M_file(__f)
+ {
+ ::flockfile(__f);
+ // Ensure stream is in write mode
+ if (!__fwritable(__f))
+ {
+ ::funlockfile(__f);
+ __throw_system_error(EACCES);
+ }
+ // Allocate buffer if needed:
+ if (_M_write_buf().empty())
+ if (::__overflow(__f, EOF) == EOF)
+ {
+ const int __err = errno;
+ ::funlockfile(__f);
+ __throw_system_error(__err);
+ }
+ }
+
+ ~_File() { ::funlockfile(_M_file); }
+
+ _File(_File&&) = delete;
+
+ // A span viewing the unused portion of the stream's output buffer.
+ std::span<char>
+ _M_write_buf() noexcept
+ {
+ return {_M_file->_IO_write_ptr,
+ size_t(_M_file->_IO_buf_end - _M_file->_IO_write_ptr)};
+ }
+
+ // Flush the output buffer to the file so we can write to it again.
+ void
+ _M_flush()
+ {
+ if (::fflush_unlocked(_M_file))
+ __throw_system_error(errno);
+ }
+
+ // Update the current position in the output buffer.
+ void
+ _M_bump(size_t __n) noexcept
+ { _M_file->_IO_write_ptr += __n; }
+
+ bool
+ _M_line_buffered() const noexcept
+ { return __flbf(_M_file); } // Or: _M_file->_flags & 0x200
+
+ bool
+ _M_unbuffered() const noexcept
+ { return __fbufsize(_M_file) == 1; } // Or: _M_file->_flags & 0x2
+
+ FILE* _M_file;
+ } _M_file;
+
+ bool _M_add_newline; // True for std::println, false for std::print.
+
+ // Flush the stream's put area so it can be refilled.
+ void
+ _M_overflow() override
+ {
+ auto __s = this->_M_used();
+ if (__s.data() == this->_M_buf)
+ {
+ // Characters in internal buffer need to be transferred to the FILE.
+ auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(),
+ _M_file._M_file);
+ if (__n != __s.size())
+ __throw_system_error(errno);
+ this->_M_reset(this->_M_buf);
+ }
+ else
+ {
+ // Characters were written directly to the FILE's output buffer.
+ _M_file._M_bump(__s.size());
+ _M_file._M_flush();
+ this->_M_reset(_M_file._M_write_buf());
+ }
+ }
+
+ public:
+ _File_sink(FILE* __f, bool __add_newline)
+ : _M_file(__f), _M_add_newline(__add_newline)
+ {
+ if (!_M_file._M_unbuffered())
+ // Write directly to the FILE's output buffer.
+ this->_M_reset(_M_file._M_write_buf());
+ }
+
+ ~_File_sink() noexcept(false)
+ {
+ auto __s = this->_M_used();
+ if (__s.data() == this->_M_buf) // Unbuffered stream
+ {
+ _File_sink::_M_overflow();
+ if (_M_add_newline)
+ ::putc_unlocked('\n', _M_file._M_file);
+ }
+ else
+ {
+ _M_file._M_bump(__s.size());
+ if (_M_add_newline)
+ ::putc_unlocked('\n', _M_file._M_file);
+ else if (_M_file._M_line_buffered() && __s.size()
+ && (__s.back() == '\n'
+ || __builtin_memchr(__s.data(), '\n', __s.size())))
+ _M_file._M_flush();
+ }
+ }
+
+ using _Sink<char>::out;
+ };
+#elif _GLIBCXX_USE_STDIO_LOCKING
+ // A format sink that buffers output and then copies it to a stdio FILE.
+ // The file is locked on construction and written to using fwrite_unlocked.
+ class _File_sink final : _Buf_sink<char>
+ {
+ FILE* _M_file;
+ bool _M_add_newline;
+
+ // Transfer buffer contents to the FILE, so buffer can be refilled.
+ void
+ _M_overflow() override
+ {
+ auto __s = this->_M_used();
+#if _GLIBCXX_HAVE_FWRITE_UNLOCKED
+ auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(), _M_file);
+ if (__n != __s.size())
+ __throw_system_error(errno);
+#else
+ for (char __c : __s)
+ ::putc_unlocked(__c, _M_file);
+ if (::ferror(_M_file))
+ __throw_system_error(errno);
+#endif
+ this->_M_reset(this->_M_buf);
+ }
+
+ public:
+ _File_sink(FILE* __f, bool __add_newline) noexcept
+ : _Buf_sink<char>(), _M_file(__f), _M_add_newline(__add_newline)
+ { ::flockfile(__f); }
+
+ ~_File_sink() noexcept(false)
+ {
+ _File_sink::_M_overflow();
+ if (_M_add_newline)
+ ::putc_unlocked('\n', _M_file);
+ ::funlockfile(_M_file);
+ }
+
+ using _Sink<char>::out;
+ };
+#else
+ // A wrapper around a format sink that copies the output to a stdio FILE.
+ // This is not actually a _Sink itself, but it creates one to hold the
+ // formatted characters and then copies them to the file when finished.
+ class _File_sink final
+ {
+ FILE* _M_file;
+ _Str_sink<char> _M_sink;
+ bool _M_add_newline;
+
+ public:
+ _File_sink(FILE* __f, bool __add_newline) noexcept
+ : _M_file(__f), _M_add_newline(__add_newline)
+ { }
+
+ ~_File_sink() noexcept(false)
+ {
+ string __s = std::move(_M_sink).get();
+ if (_M_add_newline)
+ __s += '\n';
+ auto __n = std::fwrite(__s.data(), 1, __s.size(), _M_file);
+ if (__n < __s.size())
+ __throw_system_error(EIO);
+ }
+
+ auto out() { return _M_sink.out(); }
+ };
+#endif
+} // namespace __format
+
+#ifdef _GLIBCXX_NO_INLINE_PRINT
+# define _GLIBCXX_PRINT_INLINE_USED [[__gnu__::__used__]]
+#else
+# define _GLIBCXX_PRINT_INLINE_USED
+#endif
+
+ _GLIBCXX_PRINT_INLINE_USED
+ inline void
+ vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args)
+ {
+ std::vformat_to(__format::_File_sink(__stream, false).out(), __fmt, __args);
+ }
+
+ _GLIBCXX_PRINT_INLINE_USED
+ inline void
+ vprint_nonunicode_buffered(FILE* __stream, string_view __fmt,
+ format_args __args)
+ {
+ __format::_Str_sink<char> __buf;
+ std::vformat_to(__buf.out(), __fmt, __args);
+ auto __out = __buf.view();
+ if (std::fwrite(__out.data(), 1, __out.size(), __stream) != __out.size())
+ __throw_system_error(EIO);
+ }
+
+ _GLIBCXX_PRINT_INLINE_USED
+ inline void
+ vprint_unicode(FILE* __stream, string_view __fmt, format_args __args)
+ {
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ // For most targets we don't need to do anything special to write
+ // Unicode to a terminal.
+ std::vprint_nonunicode(__stream, __fmt, __args);
+#else
+ __format::_Str_sink<char> __buf;
+ std::vformat_to(__buf.out(), __fmt, __args);
+ auto __out = __buf._M_span();
+
+ void* __open_terminal(FILE*);
+ error_code __write_to_terminal(void*, span<char>);
+ // If stream refers to a terminal, write a native Unicode string to it.
+ if (auto __term = __open_terminal(__stream))
+ {
+ error_code __e;
+ if (!std::fflush(__stream))
+ {
+ __e = __write_to_terminal(__term, __out);
+ if (!__e)
+ return;
+ if (__e == std::make_error_code(errc::illegal_byte_sequence))
+ return;
+ }
+ else
+ __e = error_code(errno, generic_category());
+ _GLIBCXX_THROW_OR_ABORT(system_error(__e, "std::vprint_unicode"));
+ }
+
+ // Otherwise just write the string to the file.
+ if (std::fwrite(__out.data(), 1, __out.size(), __stream) != __out.size())
+ __throw_system_error(EIO);
+#endif
+ }
+
+ _GLIBCXX_PRINT_INLINE_USED
+ inline void
+ vprint_unicode_buffered(FILE* __stream, string_view __fmt, format_args __args)
+ {
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ // For most targets we don't need to do anything special to write
+ // Unicode to a terminal. Just use the nonunicode function.
+ std::vprint_nonunicode_buffered(__stream, __fmt, __args);
+#else
+ // For Windows the locking function formats everything first anyway,
+ // so no formatting happens while a lock is taken. Just use that.
+ std::vprint_unicode(__stream, __fmt, __args);
+#endif
+ }
+#undef _GLIBCXX_PRINT_INLINE_USED
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // __glibcxx_print
+#endif // _GLIBCXX_PRINT_H
#include <bits/requires_hosted.h> // iostreams
#include <bits/ostream.h>
-#if __cplusplus > 202002L
-# include <format>
+
+#ifdef __glibcxx_print
+# include <format> // format_string, make_format_args
+#endif
+
+#ifndef _GLIBCXX_NO_INLINE_PRINT
+# include <bits/ostream_print.h>
#endif
# define __glibcxx_want_print
-#include <bits/version.h> // __glibcxx_syncbuf
+#include <bits/version.h> // __cpp_lib_print, __glibcxx_syncbuf
namespace std _GLIBCXX_VISIBILITY(default)
{
#endif // __glibcxx_syncbuf
#if __cpp_lib_print // C++ >= 23
- inline void
- vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args)
- {
- ostream::sentry __cerb(__os);
- if (__cerb)
- {
- __format::_Str_sink<char> __buf;
- std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);
- auto __out = __buf.view();
-
- __try
- {
- std::__ostream_write(__os, __out.data(), __out.size());
- }
- __catch(const __cxxabiv1::__forced_unwind&)
- {
- __os._M_setstate(ios_base::badbit);
- __throw_exception_again;
- }
- __catch(...)
- { __os._M_setstate(ios_base::badbit); }
- }
- }
+ void
+ vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args);
- inline void
- vprint_unicode(ostream& __os, string_view __fmt, format_args __args)
- {
-#if !defined(_WIN32) || defined(__CYGWIN__)
- // For most targets we don't need to do anything special to write
- // Unicode to a terminal.
- std::vprint_nonunicode(__os, __fmt, __args);
-#else
- ostream::sentry __cerb(__os);
- if (__cerb)
- {
- __format::_Str_sink<char> __buf;
- std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);
- auto __out = __buf._M_span();
-
- void* __open_terminal(streambuf*);
- error_code __write_to_terminal(void*, span<char>);
- // If stream refers to a terminal, write a Unicode string to it.
- if (auto __term = __open_terminal(__os.rdbuf()))
- {
-#if !defined(_WIN32) || defined(__CYGWIN__)
- // For POSIX, __open_terminal(streambuf*) uses fdopen to open a
- // new file, so we would need to close it here. This code is not
- // actually compiled because it's inside an #ifdef _WIN32 group,
- // but just in case that changes in future ...
- struct _Guard
- {
- _Guard(void* __p) : _M_f((FILE*)__p) { }
- ~_Guard() { std::fclose(_M_f); }
- _Guard(_Guard&&) = delete;
- _Guard& operator=(_Guard&&) = delete;
- FILE* _M_f;
- };
- _Guard __g(__term);
-#endif
-
- ios_base::iostate __err = ios_base::goodbit;
- __try
- {
- if (__os.rdbuf()->pubsync() == -1)
- __err = ios::badbit;
- else if (auto __e = __write_to_terminal(__term, __out))
- if (__e != std::make_error_code(errc::illegal_byte_sequence))
- __err = ios::badbit;
- }
- __catch(const __cxxabiv1::__forced_unwind&)
- {
- __os._M_setstate(ios_base::badbit);
- __throw_exception_again;
- }
- __catch(...)
- { __os._M_setstate(ios_base::badbit); }
-
- if (__err)
- __os.setstate(__err);
- return;
- }
-
- // Otherwise just insert the string as vprint_nonunicode does.
- __try
- {
- std::__ostream_write(__os, __out.data(), __out.size());
- }
- __catch(const __cxxabiv1::__forced_unwind&)
- {
- __os._M_setstate(ios_base::badbit);
- __throw_exception_again;
- }
- __catch(...)
- { __os._M_setstate(ios_base::badbit); }
- }
-#endif // _WIN32
- }
+ void
+ vprint_unicode(ostream& __os, string_view __fmt, format_args __args);
template<typename... _Args>
inline void
#endif
__os.put('\n');
}
-
#endif // __cpp_lib_print
_GLIBCXX_END_NAMESPACE_VERSION
#ifdef __cpp_lib_print // C++ >= 23
-#include <format>
-#include <cstdio>
-#include <cerrno>
-#include <bits/functexcept.h>
+#include <format> // format_args (TODO: move to bits/formatfwd.h?)
+#include <cstdio> // FILE, EOF, putc
+#include <cerrno> // EACCES, EIO
+#include <bits/functexcept.h> // __throw_system_error
#ifdef _WIN32
# include <system_error>
#endif
+#ifndef _GLIBCXX_NO_INLINE_PRINT
+# include <bits/print.h>
+#endif
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
-namespace __format
-{
-#if _GLIBCXX_USE_STDIO_LOCKING && _GLIBCXX_USE_GLIBC_STDIO_EXT
- // These are defined in <stdio_ext.h> but we don't want to include that.
- extern "C" int __fwritable(FILE*) noexcept;
- extern "C" int __flbf(FILE*) noexcept;
- extern "C" size_t __fbufsize(FILE*) noexcept;
-
- // A format sink that writes directly to a Glibc FILE.
- // The file is locked on construction and its buffer is accessed directly.
- class _File_sink final : _Buf_sink<char>
- {
- struct _File
- {
- explicit
- _File(FILE* __f) : _M_file(__f)
- {
- ::flockfile(__f);
- // Ensure stream is in write mode
- if (!__fwritable(__f))
- {
- ::funlockfile(__f);
- __throw_system_error(EACCES);
- }
- // Allocate buffer if needed:
- if (_M_write_buf().empty())
- if (::__overflow(__f, EOF) == EOF)
- {
- const int __err = errno;
- ::funlockfile(__f);
- __throw_system_error(__err);
- }
- }
-
- ~_File() { ::funlockfile(_M_file); }
-
- _File(_File&&) = delete;
-
- // A span viewing the unused portion of the stream's output buffer.
- std::span<char>
- _M_write_buf() noexcept
- {
- return {_M_file->_IO_write_ptr,
- size_t(_M_file->_IO_buf_end - _M_file->_IO_write_ptr)};
- }
-
- // Flush the output buffer to the file so we can write to it again.
- void
- _M_flush()
- {
- if (::fflush_unlocked(_M_file))
- __throw_system_error(errno);
- }
-
- // Update the current position in the output buffer.
- void
- _M_bump(size_t __n) noexcept
- { _M_file->_IO_write_ptr += __n; }
-
- bool
- _M_line_buffered() const noexcept
- { return __flbf(_M_file); } // Or: _M_file->_flags & 0x200
-
- bool
- _M_unbuffered() const noexcept
- { return __fbufsize(_M_file) == 1; } // Or: _M_file->_flags & 0x2
-
- FILE* _M_file;
- } _M_file;
-
- bool _M_add_newline; // True for std::println, false for std::print.
-
- // Flush the stream's put area so it can be refilled.
- void
- _M_overflow() override
- {
- auto __s = this->_M_used();
- if (__s.data() == this->_M_buf)
- {
- // Characters in internal buffer need to be transferred to the FILE.
- auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(),
- _M_file._M_file);
- if (__n != __s.size())
- __throw_system_error(errno);
- this->_M_reset(this->_M_buf);
- }
- else
- {
- // Characters were written directly to the FILE's output buffer.
- _M_file._M_bump(__s.size());
- _M_file._M_flush();
- this->_M_reset(_M_file._M_write_buf());
- }
- }
-
- public:
- _File_sink(FILE* __f, bool __add_newline)
- : _M_file(__f), _M_add_newline(__add_newline)
- {
- if (!_M_file._M_unbuffered())
- // Write directly to the FILE's output buffer.
- this->_M_reset(_M_file._M_write_buf());
- }
-
- ~_File_sink() noexcept(false)
- {
- auto __s = this->_M_used();
- if (__s.data() == this->_M_buf) // Unbuffered stream
- {
- _File_sink::_M_overflow();
- if (_M_add_newline)
- ::putc_unlocked('\n', _M_file._M_file);
- }
- else
- {
- _M_file._M_bump(__s.size());
- if (_M_add_newline)
- ::putc_unlocked('\n', _M_file._M_file);
- else if (_M_file._M_line_buffered() && __s.size()
- && (__s.back() == '\n'
- || __builtin_memchr(__s.data(), '\n', __s.size())))
- _M_file._M_flush();
- }
- }
-
- using _Sink<char>::out;
- };
-#elif _GLIBCXX_USE_STDIO_LOCKING
- // A format sink that buffers output and then copies it to a stdio FILE.
- // The file is locked on construction and written to using fwrite_unlocked.
- class _File_sink final : _Buf_sink<char>
- {
- FILE* _M_file;
- bool _M_add_newline;
-
- // Transfer buffer contents to the FILE, so buffer can be refilled.
- void
- _M_overflow() override
- {
- auto __s = this->_M_used();
-#if _GLIBCXX_HAVE_FWRITE_UNLOCKED
- auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(), _M_file);
- if (__n != __s.size())
- __throw_system_error(errno);
-#else
- for (char __c : __s)
- ::putc_unlocked(__c, _M_file);
- if (::ferror(_M_file))
- __throw_system_error(errno);
-#endif
- this->_M_reset(this->_M_buf);
- }
-
- public:
- _File_sink(FILE* __f, bool __add_newline) noexcept
- : _Buf_sink<char>(), _M_file(__f), _M_add_newline(__add_newline)
- { ::flockfile(__f); }
-
- ~_File_sink() noexcept(false)
- {
- _File_sink::_M_overflow();
- if (_M_add_newline)
- ::putc_unlocked('\n', _M_file);
- ::funlockfile(_M_file);
- }
-
- using _Sink<char>::out;
- };
-#else
- // A wrapper around a format sink that copies the output to a stdio FILE.
- // This is not actually a _Sink itself, but it creates one to hold the
- // formatted characters and then copies them to the file when finished.
- class _File_sink final
- {
- FILE* _M_file;
- _Str_sink<char> _M_sink;
- bool _M_add_newline;
+ void
+ vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args);
- public:
- _File_sink(FILE* __f, bool __add_newline) noexcept
- : _M_file(__f), _M_add_newline(__add_newline)
- { }
+ void
+ vprint_nonunicode_buffered(FILE* __stream, string_view __fmt,
+ format_args __args);
- ~_File_sink() noexcept(false)
- {
- string __s = std::move(_M_sink).get();
- if (_M_add_newline)
- __s += '\n';
- auto __n = std::fwrite(__s.data(), 1, __s.size(), _M_file);
- if (__n < __s.size())
- __throw_system_error(EIO);
- }
+ void
+ vprint_unicode(FILE* __stream, string_view __fmt, format_args __args);
- auto out() { return _M_sink.out(); }
- };
-#endif
-} // namespace __format
+ void
+ vprint_unicode_buffered(FILE* __stream, string_view __fmt,
+ format_args __args);
- inline void
- vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args)
- {
- std::vformat_to(__format::_File_sink(__stream, false).out(), __fmt, __args);
- }
+ void
+ vprint_unicode_buffered(string_view __fmt, format_args __args);
- inline void
- vprint_nonunicode_buffered(FILE* __stream, string_view __fmt,
- format_args __args)
- {
- __format::_Str_sink<char> __buf;
- std::vformat_to(__buf.out(), __fmt, __args);
- auto __out = __buf.view();
- if (std::fwrite(__out.data(), 1, __out.size(), __stream) != __out.size())
- __throw_system_error(EIO);
- }
-
- inline void
- vprint_unicode(FILE* __stream, string_view __fmt, format_args __args)
- {
-#if !defined(_WIN32) || defined(__CYGWIN__)
- // For most targets we don't need to do anything special to write
- // Unicode to a terminal.
- std::vprint_nonunicode(__stream, __fmt, __args);
-#else
- __format::_Str_sink<char> __buf;
- std::vformat_to(__buf.out(), __fmt, __args);
- auto __out = __buf._M_span();
-
- void* __open_terminal(FILE*);
- error_code __write_to_terminal(void*, span<char>);
- // If stream refers to a terminal, write a native Unicode string to it.
- if (auto __term = __open_terminal(__stream))
- {
- error_code __e;
- if (!std::fflush(__stream))
- {
- __e = __write_to_terminal(__term, __out);
- if (!__e)
- return;
- if (__e == std::make_error_code(errc::illegal_byte_sequence))
- return;
- }
- else
- __e = error_code(errno, generic_category());
- _GLIBCXX_THROW_OR_ABORT(system_error(__e, "std::vprint_unicode"));
- }
-
- // Otherwise just write the string to the file.
- if (std::fwrite(__out.data(), 1, __out.size(), __stream) != __out.size())
- __throw_system_error(EIO);
-#endif
- }
-
- inline void
- vprint_unicode_buffered(FILE* __stream, string_view __fmt, format_args __args)
- {
-#if !defined(_WIN32) || defined(__CYGWIN__)
- // For most targets we don't need to do anything special to write
- // Unicode to a terminal. Just use the nonunicode function.
- std::vprint_nonunicode_buffered(__stream, __fmt, __args);
-#else
- // For Windows the locking function formats everything first anyway,
- // so no formatting happens while a lock is taken. Just use that.
- std::vprint_unicode(__stream, __fmt, __args);
-#endif
- }
+ void
+ vprint_nonunicode_buffered(string_view __fmt, format_args __args);
template<typename... _Args>
inline void
// and we know what that would call, so we can call that directly.
auto __fmtargs = std::make_format_args(__args...);
+
#if defined(_WIN32) && !defined(__CYGWIN__)
if constexpr (__unicode::__literal_encoding_is_utf8())
{
else
#endif
+#ifdef _GLIBCXX_NO_INLINE_PRINT
+ {
+ string __fmtn;
+ __fmtn.reserve(__fmt.get().size() + 1);
+ __fmtn = __fmt.get();
+ __fmtn += '\n';
+ std::vprint_nonunicode(__stream, __fmtn, __fmtargs);
+ }
+#else
// For non-Windows and for non-Unicode on Windows, we know that print
// would call vprint_nonunicode or vprint_nonunicode_buffered with a
// newline appended to the format-string. Use a _File_sink that adds
string_view __s(__buf.view());
__format::_File_sink(__stream, true).out() = __s;
}
+#endif
}
template<typename... _Args>
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
+// We want to emit symbols for the inline functions in bits/print.h here.
+#define _GLIBCXX_NO_INLINE_PRINT 1
+#include <ostream>
+#include <bits/ostream_print.h>
+#include <print>
+#include <bits/print.h>
+
#include <span>
#include <string>
#include <streambuf>