[libc-commits] [libc] [libc] Add getc, ungetc, fflush to enable libc++ iostream on baremetal (PR #175530)

Petr Hosek via libc-commits libc-commits at lists.llvm.org
Wed Feb 11 01:02:03 PST 2026


================
@@ -0,0 +1,61 @@
+//===--- Helpers for file I/O on baremetal ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/baremetal/file_internal.h"
+#include "src/__support/CPP/optional.h"
+
+#include "hdr/stdio_macros.h" // for EOF
+
+namespace LIBC_NAMESPACE_DECL {
+
+// Out of standard streams only stdin supports ungetc,
+// because stdin is readable - ungetc on stdout/stderr is undefined.
+// Only one value is required by the C standard to be stored by ungetc.
+// This minimal implementation only handles stdin and returns error on all
+// other streams.
+// TODO: Shall we have an embedding API for ungetc?
+extern "C" ::FILE *stdin;
+
+static cpp::optional<unsigned char> ungetc_state_stdin;
+
+bool pop_ungetc_value(::FILE *stream, unsigned char &out) {
+  if (stream != stdin)
+    return false;
+
+  if (!ungetc_state_stdin)
+    return false;
+
+  out = *ungetc_state_stdin;
+  ungetc_state_stdin.reset();
+  return true;
+}
+
+int push_ungetc_value(::FILE *stream, int c) {
+  if (c == EOF || stream == nullptr)
+    return EOF;
+
+  if (stream != stdin)
+    return EOF;
+
+  if (ungetc_state_stdin)
+    return EOF;
+
+  ungetc_state_stdin =
+      cpp::optional<unsigned char>{static_cast<unsigned char>(c)};
+  return c;
+}
+
+namespace internal {
+
+int ungetc_internal(int c, ::FILE *stream) {
+  return push_ungetc_value(stream, c);
+}
----------------
petrhosek wrote:

Could this be inlined into the header?

https://github.com/llvm/llvm-project/pull/175530


More information about the libc-commits mailing list