summaryrefslogtreecommitdiff
path: root/lib/libc/include
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-07-11 22:48:30 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-07-11 22:48:30 +0800
commit3ad39e9878310e5317ee73c9b353c1e2c1c5c4ee (patch)
tree4bd5a49ef60ad1e371c0984cd46838368c5ef83a /lib/libc/include
parent48ef95c24e9ac3d11200b61af617a01b10b507d1 (diff)
downloadlume-3ad39e9878310e5317ee73c9b353c1e2c1c5c4ee.tar.gz
lume-3ad39e9878310e5317ee73c9b353c1e2c1c5c4ee.tar.xz
lib: establish Zircon libc++ and KTL foundation
Diffstat (limited to 'lib/libc/include')
-rw-r--r--lib/libc/include/assert.h20
-rw-r--r--lib/libc/include/inttypes.h117
-rw-r--r--lib/libc/include/multi-file.h50
-rw-r--r--lib/libc/include/stdint.h278
-rw-r--r--lib/libc/include/stdio.h102
-rw-r--r--lib/libc/include/stdlib.h36
-rw-r--r--lib/libc/include/string-file.h79
-rw-r--r--lib/libc/include/string.h97
8 files changed, 779 insertions, 0 deletions
diff --git a/lib/libc/include/assert.h b/lib/libc/include/assert.h
new file mode 100644
index 0000000..8b6252e
--- /dev/null
+++ b/lib/libc/include/assert.h
@@ -0,0 +1,20 @@
+// Copyright 2020 The Fuchsia Authors
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT
+
+#pragma once
+
+#include <zircon/assert.h>
+
+#ifdef NDEBUG
+#define assert(expr) ((void)0)
+#else
+#define assert(expr) ZX_ASSERT(expr)
+#endif
+
+// make sure static_assert() is defined, even in C
+#if !defined(__cplusplus) && !defined(static_assert)
+#define static_assert(e, msg) _Static_assert(e, msg)
+#endif
diff --git a/lib/libc/include/inttypes.h b/lib/libc/include/inttypes.h
new file mode 100644
index 0000000..b19e0f5
--- /dev/null
+++ b/lib/libc/include/inttypes.h
@@ -0,0 +1,117 @@
+// Copyright 2016 The Fuchsia Authors
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT
+
+#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_INTTYPES_H_
+#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_INTTYPES_H_
+
+// This (or the compiler) defines all the __<type>_FMT<letter>__ macros.
+#include <stdint.h>
+
+#define PRId8 __INT8_FMTd__
+#define PRId16 __INT16_FMTd__
+#define PRId32 __INT32_FMTd__
+#define PRId64 __INT64_FMTd__
+
+#define PRIdLEAST8 __INT_LEAST8_FMTd__
+#define PRIdLEAST16 __INT_LEAST16_FMTd__
+#define PRIdLEAST32 __INT_LEAST32_FMTd__
+#define PRIdLEAST64 __INT_LEAST64_FMTd__
+
+#define PRIdFAST8 __INT_FAST8_FMTd__
+#define PRIdFAST16 __INT_FAST16_FMTd__
+#define PRIdFAST32 __INT_FAST32_FMTd__
+#define PRIdFAST64 __INT_FAST64_FMTd__
+
+#define PRIi8 __INT8_FMTi__
+#define PRIi16 __INT16_FMTi__
+#define PRIi32 __INT32_FMTi__
+#define PRIi64 __INT64_FMTi__
+
+#define PRIiLEAST8 __INT_LEAST8_FMTi__
+#define PRIiLEAST16 __INT_LEAST16_FMTi__
+#define PRIiLEAST32 __INT_LEAST32_FMTi__
+#define PRIiLEAST64 __INT_LEAST64_FMTi__
+
+#define PRIiFAST8 __INT_FAST8_FMTi__
+#define PRIiFAST16 __INT_FAST16_FMTi__
+#define PRIiFAST32 __INT_FAST32_FMTi__
+#define PRIiFAST64 __INT_FAST64_FMTi__
+
+#define PRIo8 __UINT8_FMTo__
+#define PRIo16 __UINT16_FMTo__
+#define PRIo32 __UINT32_FMTo__
+#define PRIo64 __UINT64_FMTo__
+
+#define PRIoLEAST8 __UINT_LEAST8_FMTo__
+#define PRIoLEAST16 __UINT_LEAST16_FMTo__
+#define PRIoLEAST32 __UINT_LEAST32_FMTo__
+#define PRIoLEAST64 __UINT_LEAST64_FMTo__
+
+#define PRIoFAST8 __UINT_FAST8_FMTo__
+#define PRIoFAST16 __UINT_FAST16_FMTo__
+#define PRIoFAST32 __UINT_FAST32_FMTo__
+#define PRIoFAST64 __UINT_FAST64_FMTo__
+
+#define PRIu8 __UINT8_FMTu__
+#define PRIu16 __UINT16_FMTu__
+#define PRIu32 __UINT32_FMTu__
+#define PRIu64 __UINT64_FMTu__
+
+#define PRIuLEAST8 __UINT_LEAST8_FMTu__
+#define PRIuLEAST16 __UINT_LEAST16_FMTu__
+#define PRIuLEAST32 __UINT_LEAST32_FMTu__
+#define PRIuLEAST64 __UINT_LEAST64_FMTu__
+
+#define PRIuFAST8 __UINT_FAST8_FMTu__
+#define PRIuFAST16 __UINT_FAST16_FMTu__
+#define PRIuFAST32 __UINT_FAST32_FMTu__
+#define PRIuFAST64 __UINT_FAST64_FMTu__
+
+#define PRIx8 __UINT8_FMTx__
+#define PRIx16 __UINT16_FMTx__
+#define PRIx32 __UINT32_FMTx__
+#define PRIx64 __UINT64_FMTx__
+
+#define PRIxLEAST8 __UINT_LEAST8_FMTx__
+#define PRIxLEAST16 __UINT_LEAST16_FMTx__
+#define PRIxLEAST32 __UINT_LEAST32_FMTx__
+#define PRIxLEAST64 __UINT_LEAST64_FMTx__
+
+#define PRIxFAST8 __UINT_FAST8_FMTx__
+#define PRIxFAST16 __UINT_FAST16_FMTx__
+#define PRIxFAST32 __UINT_FAST32_FMTx__
+#define PRIxFAST64 __UINT_FAST64_FMTx__
+
+#define PRIX8 __UINT8_FMTX__
+#define PRIX16 __UINT16_FMTX__
+#define PRIX32 __UINT32_FMTX__
+#define PRIX64 __UINT64_FMTX__
+
+#define PRIXLEAST8 __UINT_LEAST8_FMTX__
+#define PRIXLEAST16 __UINT_LEAST16_FMTX__
+#define PRIXLEAST32 __UINT_LEAST32_FMTX__
+#define PRIXLEAST64 __UINT_LEAST64_FMTX__
+
+#define PRIXFAST8 __UINT_FAST8_FMTX__
+#define PRIXFAST16 __UINT_FAST16_FMTX__
+#define PRIXFAST32 __UINT_FAST32_FMTX__
+#define PRIXFAST64 __UINT_FAST64_FMTX__
+
+#define PRIdMAX __INTMAX_FMTd__
+#define PRIiMAX __INTMAX_FMTi__
+#define PRIoMAX __UINTMAX_FMTo__
+#define PRIuMAX __UINTMAX_FMTu__
+#define PRIxMAX __UINTMAX_FMTx__
+#define PRIXMAX __UINTMAX_FMTX__
+
+#define PRIdPTR __INTPTR_FMTd__
+#define PRIiPTR __INTPTR_FMTi__
+#define PRIoPTR __UINTPTR_FMTo__
+#define PRIuPTR __UINTPTR_FMTu__
+#define PRIxPTR __UINTPTR_FMTx__
+#define PRIXPTR __UINTPTR_FMTX__
+
+#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_INTTYPES_H_
diff --git a/lib/libc/include/multi-file.h b/lib/libc/include/multi-file.h
new file mode 100644
index 0000000..a04a031
--- /dev/null
+++ b/lib/libc/include/multi-file.h
@@ -0,0 +1,50 @@
+// Copyright 2022 The Fuchsia Authors
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT
+
+#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_MULTI_FILE_H_
+#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_MULTI_FILE_H_
+
+#include <stdio.h>
+
+#include <ktl/array.h>
+#include <ktl/forward.h>
+#include <ktl/string_view.h>
+#include <ktl/type_traits.h>
+
+// MultiFile broadcasts Write calls across multiple FILE* pointers. Each
+// pointer is ignored if it's null. MultiFile::Write always returns success,
+// ignoring any failures or short writes from the underlying FILE objects.
+template <size_t N>
+class MultiFile : public FILE {
+ public:
+ using FileArray = ktl::array<FILE*, N>;
+
+ constexpr MultiFile() : FILE{this} {}
+
+ constexpr explicit MultiFile(const FileArray& files) : FILE{this}, files_(files) {}
+
+ constexpr MultiFile(const MultiFile& other) : MultiFile(other.files_) {}
+
+ FileArray& files() { return files_; }
+ const FileArray& files() const { return files_; }
+
+ int Write(ktl::string_view str) {
+ for (FILE* file : files_) {
+ if (file) {
+ file->Write(str);
+ }
+ }
+ return static_cast<int>(str.size());
+ }
+
+ private:
+ FileArray files_ = {};
+};
+
+template <size_t N>
+MultiFile(const ktl::array<FILE*, N>&) -> MultiFile<N>;
+
+#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_MULTI_FILE_H_
diff --git a/lib/libc/include/stdint.h b/lib/libc/include/stdint.h
new file mode 100644
index 0000000..3cbdfeb
--- /dev/null
+++ b/lib/libc/include/stdint.h
@@ -0,0 +1,278 @@
+// Copyright 2016 The Fuchsia Authors
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT
+
+#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDINT_H_
+#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDINT_H_
+
+// The compiler predefines macros __<type>_TYPE__, __<type>_MAX__,
+// and __<type>_C for the various types. All we have to do here is
+// define the public names based on those macros.
+
+// Clang predefines macros __<type>_FMT<letter>__ for each type,
+// with <letter> being i and for signed types, and o, u, x, and X
+// for unsigned types. That lets <inttypes.h> do its work without
+// any special knowledge of what the underlying types are.
+// Unfortunately, GCC does not define these macros. To keep all
+// knowledge of the compiler's choices isolated to this file, define
+// them here for GCC so that <inttypes.h> can use them unconditionally.
+#ifndef __INTMAX_FMTd__
+
+#define __INT8_FMT_MODIFIER__ "hh"
+#define __INT16_FMT_MODIFIER__ "h"
+#ifdef _LP64
+#define __INT32_FMT_MODIFIER__ ""
+#else
+#define __INT32_FMT_MODIFIER__ "l"
+#endif
+
+#define __INT_LEAST8_FMT_MODIFIER__ __INT8_FMT_MODIFIER__
+#define __INT_LEAST16_FMT_MODIFIER__ __INT16_FMT_MODIFIER__
+#define __INT_LEAST32_FMT_MODIFIER__ __INT32_FMT_MODIFIER__
+#define __INT_LEAST64_FMT_MODIFIER__ __INT64_FMT_MODIFIER__
+
+// The *-elf and arm-eabi GCC targets use 'int' for the fast{8,16,32}
+// types. On LP64 systems, 'long' is used for the fast64 type, and
+// 'long long' on non-LP64 systems.
+#define __INT_FAST8_FMT_MODIFIER__ ""
+#define __INT_FAST16_FMT_MODIFIER__ ""
+#define __INT_FAST32_FMT_MODIFIER__ ""
+#if _LP64
+#define __INT_FAST64_FMT_MODIFIER__ "l"
+#else
+#define __INT_FAST64_FMT_MODIFIER__ "ll"
+#endif
+
+// On machines where 'long' types are 64 bits, the compiler defines
+// __INT64_TYPE__ et al using 'long', not 'long long', though both are
+// 64-bit types.
+#ifdef _LP64
+#define __INT64_FMT_MODIFIER__ "l"
+#define __INTPTR_FMT_MODIFIER__ "l"
+#else
+#define __INT64_FMT_MODIFIER__ "ll"
+#define __INTPTR_FMT_MODIFIER__ ""
+#endif
+
+#define __INTMAX_FMT_MODIFIER__ __INT64_FMT_MODIFIER__
+
+#define __INTMAX_FMTd__ __INTMAX_FMT_MODIFIER__ "d"
+#define __INTMAX_FMTi__ __INTMAX_FMT_MODIFIER__ "i"
+#define __UINTMAX_FMTo__ __INTMAX_FMT_MODIFIER__ "o"
+#define __UINTMAX_FMTu__ __INTMAX_FMT_MODIFIER__ "u"
+#define __UINTMAX_FMTx__ __INTMAX_FMT_MODIFIER__ "x"
+#define __UINTMAX_FMTX__ __INTMAX_FMT_MODIFIER__ "X"
+#define __INTPTR_FMTd__ __INTPTR_FMT_MODIFIER__ "d"
+#define __INTPTR_FMTi__ __INTPTR_FMT_MODIFIER__ "i"
+#define __UINTPTR_FMTo__ __INTPTR_FMT_MODIFIER__ "o"
+#define __UINTPTR_FMTu__ __INTPTR_FMT_MODIFIER__ "u"
+#define __UINTPTR_FMTx__ __INTPTR_FMT_MODIFIER__ "x"
+#define __UINTPTR_FMTX__ __INTPTR_FMT_MODIFIER__ "X"
+#define __INT8_FMTd__ __INT8_FMT_MODIFIER__ "d"
+#define __INT8_FMTi__ __INT8_FMT_MODIFIER__ "i"
+#define __INT16_FMTd__ __INT16_FMT_MODIFIER__ "d"
+#define __INT16_FMTi__ __INT16_FMT_MODIFIER__ "i"
+#define __INT32_FMTd__ __INT32_FMT_MODIFIER__ "d"
+#define __INT32_FMTi__ __INT32_FMT_MODIFIER__ "i"
+#define __INT64_FMTd__ __INT64_FMT_MODIFIER__ "d"
+#define __INT64_FMTi__ __INT64_FMT_MODIFIER__ "i"
+#define __UINT8_FMTo__ __INT8_FMT_MODIFIER__ "o"
+#define __UINT8_FMTu__ __INT8_FMT_MODIFIER__ "u"
+#define __UINT8_FMTx__ __INT8_FMT_MODIFIER__ "x"
+#define __UINT8_FMTX__ __INT8_FMT_MODIFIER__ "X"
+#define __UINT16_FMTo__ __INT16_FMT_MODIFIER__ "o"
+#define __UINT16_FMTu__ __INT16_FMT_MODIFIER__ "u"
+#define __UINT16_FMTx__ __INT16_FMT_MODIFIER__ "x"
+#define __UINT16_FMTX__ __INT16_FMT_MODIFIER__ "X"
+#define __UINT32_FMTo__ __INT32_FMT_MODIFIER__ "o"
+#define __UINT32_FMTu__ __INT32_FMT_MODIFIER__ "u"
+#define __UINT32_FMTx__ __INT32_FMT_MODIFIER__ "x"
+#define __UINT32_FMTX__ __INT32_FMT_MODIFIER__ "X"
+#define __UINT64_FMTo__ __INT64_FMT_MODIFIER__ "o"
+#define __UINT64_FMTu__ __INT64_FMT_MODIFIER__ "u"
+#define __UINT64_FMTx__ __INT64_FMT_MODIFIER__ "x"
+#define __UINT64_FMTX__ __INT64_FMT_MODIFIER__ "X"
+#define __INT_LEAST8_FMTd__ __INT_LEAST8_FMT_MODIFIER__ "d"
+#define __INT_LEAST8_FMTi__ __INT_LEAST8_FMT_MODIFIER__ "i"
+#define __UINT_LEAST8_FMTo__ __INT_LEAST8_FMT_MODIFIER__ "o"
+#define __UINT_LEAST8_FMTu__ __INT_LEAST8_FMT_MODIFIER__ "u"
+#define __UINT_LEAST8_FMTx__ __INT_LEAST8_FMT_MODIFIER__ "x"
+#define __UINT_LEAST8_FMTX__ __INT_LEAST8_FMT_MODIFIER__ "X"
+#define __INT_LEAST16_FMTd__ __INT_LEAST16_FMT_MODIFIER__ "d"
+#define __INT_LEAST16_FMTi__ __INT_LEAST16_FMT_MODIFIER__ "i"
+#define __UINT_LEAST16_FMTo__ __INT_LEAST16_FMT_MODIFIER__ "o"
+#define __UINT_LEAST16_FMTu__ __INT_LEAST16_FMT_MODIFIER__ "u"
+#define __UINT_LEAST16_FMTx__ __INT_LEAST16_FMT_MODIFIER__ "x"
+#define __UINT_LEAST16_FMTX__ __INT_LEAST16_FMT_MODIFIER__ "X"
+#define __INT_LEAST32_FMTd__ __INT_LEAST32_FMT_MODIFIER__ "d"
+#define __INT_LEAST32_FMTi__ __INT_LEAST32_FMT_MODIFIER__ "i"
+#define __UINT_LEAST32_FMTo__ __INT_LEAST32_FMT_MODIFIER__ "o"
+#define __UINT_LEAST32_FMTu__ __INT_LEAST32_FMT_MODIFIER__ "u"
+#define __UINT_LEAST32_FMTx__ __INT_LEAST32_FMT_MODIFIER__ "x"
+#define __UINT_LEAST32_FMTX__ __INT_LEAST32_FMT_MODIFIER__ "X"
+#define __INT_LEAST64_FMTd__ __INT_LEAST64_FMT_MODIFIER__ "d"
+#define __INT_LEAST64_FMTi__ __INT_LEAST64_FMT_MODIFIER__ "i"
+#define __UINT_LEAST64_FMTo__ __INT_LEAST64_FMT_MODIFIER__ "o"
+#define __UINT_LEAST64_FMTu__ __INT_LEAST64_FMT_MODIFIER__ "u"
+#define __UINT_LEAST64_FMTx__ __INT_LEAST64_FMT_MODIFIER__ "x"
+#define __UINT_LEAST64_FMTX__ __INT_LEAST64_FMT_MODIFIER__ "X"
+#define __INT_FAST8_FMTd__ __INT_FAST8_FMT_MODIFIER__ "d"
+#define __INT_FAST8_FMTi__ __INT_FAST8_FMT_MODIFIER__ "i"
+#define __UINT_FAST8_FMTo__ __INT_FAST8_FMT_MODIFIER__ "o"
+#define __UINT_FAST8_FMTu__ __INT_FAST8_FMT_MODIFIER__ "u"
+#define __UINT_FAST8_FMTx__ __INT_FAST8_FMT_MODIFIER__ "x"
+#define __UINT_FAST8_FMTX__ __INT_FAST8_FMT_MODIFIER__ "X"
+#define __INT_FAST16_FMTd__ __INT_FAST16_FMT_MODIFIER__ "d"
+#define __INT_FAST16_FMTi__ __INT_FAST16_FMT_MODIFIER__ "i"
+#define __UINT_FAST16_FMTo__ __INT_FAST16_FMT_MODIFIER__ "o"
+#define __UINT_FAST16_FMTu__ __INT_FAST16_FMT_MODIFIER__ "u"
+#define __UINT_FAST16_FMTx__ __INT_FAST16_FMT_MODIFIER__ "x"
+#define __UINT_FAST16_FMTX__ __INT_FAST16_FMT_MODIFIER__ "X"
+#define __INT_FAST32_FMTd__ __INT_FAST32_FMT_MODIFIER__ "d"
+#define __INT_FAST32_FMTi__ __INT_FAST32_FMT_MODIFIER__ "i"
+#define __UINT_FAST32_FMTo__ __INT_FAST32_FMT_MODIFIER__ "o"
+#define __UINT_FAST32_FMTu__ __INT_FAST32_FMT_MODIFIER__ "u"
+#define __UINT_FAST32_FMTx__ __INT_FAST32_FMT_MODIFIER__ "x"
+#define __UINT_FAST32_FMTX__ __INT_FAST32_FMT_MODIFIER__ "X"
+#define __INT_FAST64_FMTd__ __INT_FAST64_FMT_MODIFIER__ "d"
+#define __INT_FAST64_FMTi__ __INT_FAST64_FMT_MODIFIER__ "i"
+#define __UINT_FAST64_FMTo__ __INT_FAST64_FMT_MODIFIER__ "o"
+#define __UINT_FAST64_FMTu__ __INT_FAST64_FMT_MODIFIER__ "u"
+#define __UINT_FAST64_FMTx__ __INT_FAST64_FMT_MODIFIER__ "x"
+#define __UINT_FAST64_FMTX__ __INT_FAST64_FMT_MODIFIER__ "X"
+
+#endif
+
+typedef __UINT8_TYPE__ uint8_t;
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
+typedef __UINT64_TYPE__ uint64_t;
+typedef __INT8_TYPE__ int8_t;
+typedef __INT16_TYPE__ int16_t;
+typedef __INT32_TYPE__ int32_t;
+typedef __INT64_TYPE__ int64_t;
+
+#define UINT8_MAX __UINT8_MAX__
+#define UINT16_MAX __UINT16_MAX__
+#define UINT32_MAX __UINT32_MAX__
+#define UINT64_MAX __UINT64_MAX__
+
+#define INT8_MAX __INT8_MAX__
+#define INT16_MAX __INT16_MAX__
+#define INT32_MAX __INT32_MAX__
+#define INT64_MAX __INT64_MAX__
+
+#define INT8_MIN (-INT8_MAX - 1)
+#define INT16_MIN (-INT16_MAX - 1)
+#define INT32_MIN (-INT32_MAX - 1)
+#define INT64_MIN (-INT64_MAX - 1)
+
+typedef __UINT_LEAST8_TYPE__ uint_least8_t;
+typedef __UINT_LEAST16_TYPE__ uint_least16_t;
+typedef __UINT_LEAST32_TYPE__ uint_least32_t;
+typedef __UINT_LEAST64_TYPE__ uint_least64_t;
+typedef __INT_LEAST8_TYPE__ int_least8_t;
+typedef __INT_LEAST16_TYPE__ int_least16_t;
+typedef __INT_LEAST32_TYPE__ int_least32_t;
+typedef __INT_LEAST64_TYPE__ int_least64_t;
+
+#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__
+#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__
+#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__
+#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__
+
+#define INT_LEAST8_MAX __INT_LEAST8_MAX__
+#define INT_LEAST16_MAX __INT_LEAST16_MAX__
+#define INT_LEAST32_MAX __INT_LEAST32_MAX__
+#define INT_LEAST64_MAX __INT_LEAST64_MAX__
+
+#define INT_LEAST8_MIN (-INT_LEAST8_MAX - 1)
+#define INT_LEAST16_MIN (-INT_LEAST16_MAX - 1)
+#define INT_LEAST32_MIN (-INT_LEAST32_MAX - 1)
+#define INT_LEAST64_MIN (-INT_LEAST64_MAX - 1)
+
+typedef __UINT_FAST8_TYPE__ uint_fast8_t;
+typedef __UINT_FAST16_TYPE__ uint_fast16_t;
+typedef __UINT_FAST32_TYPE__ uint_fast32_t;
+typedef __UINT_FAST64_TYPE__ uint_fast64_t;
+typedef __INT_FAST8_TYPE__ int_fast8_t;
+typedef __INT_FAST16_TYPE__ int_fast16_t;
+typedef __INT_FAST32_TYPE__ int_fast32_t;
+typedef __INT_FAST64_TYPE__ int_fast64_t;
+
+#define UINT_FAST8_MAX __UINT_FAST8_MAX__
+#define UINT_FAST16_MAX __UINT_FAST16_MAX__
+#define UINT_FAST32_MAX __UINT_FAST32_MAX__
+#define UINT_FAST64_MAX __UINT_FAST64_MAX__
+
+#define INT_FAST8_MAX __INT_FAST8_MAX__
+#define INT_FAST16_MAX __INT_FAST16_MAX__
+#define INT_FAST32_MAX __INT_FAST32_MAX__
+#define INT_FAST64_MAX __INT_FAST64_MAX__
+
+#define INT_FAST8_MIN (-INT_FAST8_MAX - 1)
+#define INT_FAST16_MIN (-INT_FAST16_MAX - 1)
+#define INT_FAST32_MIN (-INT_FAST32_MAX - 1)
+#define INT_FAST64_MIN (-INT_FAST64_MAX - 1)
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __UINTPTR_TYPE__ uintptr_t;
+
+#define INTPTR_MAX __INTPTR_MAX__
+#define INTPTR_MIN (-INTPTR_MAX - 1)
+#define UINTPTR_MAX __UINTPTR_MAX__
+
+typedef __INTMAX_TYPE__ intmax_t;
+typedef __UINTMAX_TYPE__ uintmax_t;
+
+#define INTMAX_MAX __INTMAX_MAX__
+#define INTMAX_MIN (-INTMAX_MAX - 1)
+#define UINTMAX_MAX __UINTMAX_MAX__
+
+#define SIZE_MAX __SIZE_MAX__
+
+// GCC defines __<type>INT<size>_C macros which append the correct suffix
+// to an (un)signed integer literal, with <size> being one of 8, 16, 32, 64
+// and MAX, and type being U for unsigned types. The standard stdint.h macros
+// with the same names without the leading __ could be implemented in terms of
+// these macros.
+//
+// Clang predefines macros __<type>INT<size>_C_SUFFIX__ which expand to the
+// suffix itself. We define the standard stdint.h macros in terms of the GCC
+// variants and for Clang we define their equivalents.
+#ifndef __INTMAX_C
+
+#define __int_c_join(a, b) a##b
+#define __int_c(v, suffix) __int_c_join(v, suffix)
+
+#define __INT8_C(c) __int_c(c, __INT8_C_SUFFIX__)
+#define __INT16_C(c) __int_c(c, __INT16_C_SUFFIX__)
+#define __INT32_C(c) __int_c(c, __INT32_C_SUFFIX__)
+#define __INT64_C(c) __int_c(c, __INT64_C_SUFFIX__)
+
+#define __UINT8_C(c) __int_c(c, __UINT8_C_SUFFIX__)
+#define __UINT16_C(c) __int_c(c, __UINT16_C_SUFFIX__)
+#define __UINT32_C(c) __int_c(c, __UINT32_C_SUFFIX__)
+#define __UINT64_C(c) __int_c(c, __UINT64_C_SUFFIX__)
+
+#define __INTMAX_C(c) __int_c(c, __INTMAX_C_SUFFIX__)
+#define __UINTMAX_C(c) __int_c(c, __UINTMAX_C_SUFFIX__)
+
+#endif
+
+#define INT8_C(c) __INT8_C(c)
+#define INT16_C(c) __INT16_C(c)
+#define INT32_C(c) __INT32_C(c)
+#define INT64_C(c) __INT64_C(c)
+
+#define UINT8_C(c) __UINT8_C(c)
+#define UINT16_C(c) __UINT16_C(c)
+#define UINT32_C(c) __UINT32_C(c)
+#define UINT64_C(c) __UINT64_C(c)
+
+#define INTMAX_C(c) __INTMAX_C(c)
+#define UINTMAX_C(c) __UINTMAX_C(c)
+
+#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDINT_H_
diff --git a/lib/libc/include/stdio.h b/lib/libc/include/stdio.h
new file mode 100644
index 0000000..ae5a84b
--- /dev/null
+++ b/lib/libc/include/stdio.h
@@ -0,0 +1,102 @@
+// Copyright 2020 The Fuchsia Authors
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT
+
+#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDIO_H_
+#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDIO_H_
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <zircon/compiler.h>
+
+// All anybody really wants from stdio is printf.
+
+#ifdef __cplusplus
+#include <ktl/string_view.h>
+
+class FILE {
+ public:
+ // This is basically equivalent to having a virtual Write function with
+ // subclasses providing their own data members in lieu of ptr. But it's
+ // simpler and avoids a vtable that might need address fixup at load time
+ // (and the double indirection for a single-entry vtable--at the cost of
+ // double indirection for the ptr data in a callback that uses it).
+
+ using Callback = int(void*, ktl::string_view);
+
+ FILE() = default;
+
+ constexpr FILE(Callback* write, void* ptr) : write_(write), ptr_(ptr) {}
+
+ template <typename T>
+ explicit FILE(T* writer)
+ : write_([](void* ptr, ktl::string_view s) { return static_cast<T*>(ptr)->Write(s); }),
+ ptr_(writer) {}
+
+ // This is what fprintf calls to do output.
+ int Write(ktl::string_view s) { return write_(ptr_, s); }
+
+ constexpr explicit operator bool() const { return write_; }
+
+ constexpr bool operator==(const FILE& other) const {
+ return write_ == other.write_ && ptr_ == other.ptr_;
+ }
+
+ constexpr bool operator!=(const FILE& other) const { return !(*this == other); }
+
+ // This is not defined by libc itself. The kernel defines it to point at
+ // the default console output mechanism.
+ static FILE stdout_;
+
+ private:
+ Callback* write_ = nullptr;
+ void* ptr_ = nullptr;
+};
+
+#define stdout (&FILE::stdout_)
+
+inline int fputc(int c, FILE* f) {
+ const unsigned char uc = static_cast<unsigned char>(c);
+ return f->Write({reinterpret_cast<const char*>(&uc), 1}) == 1 ? uc : -1;
+}
+
+inline int putc(int c, FILE* f) { return fputc(c, f); }
+
+inline int putchar(int c) { return fputc(c, stdout); }
+
+inline int fputs(const char* s, FILE* f) {
+ ktl::string_view str(s);
+ return f->Write(str) == static_cast<int>(str.size()) ? 0 : -1;
+}
+
+inline int puts(const char* s) { return fputs(s, stdout) == 0 ? putchar('\n') : -1; }
+
+#else // !__cplusplus
+
+// C users just need the function declarations.
+typedef struct _FILE_is_opaque FILE;
+
+#endif // __cplusplus
+
+__BEGIN_CDECLS
+
+int printf(const char*, ...) __PRINTFLIKE(1, 2);
+int fprintf(FILE*, const char*, ...) __PRINTFLIKE(2, 3);
+int snprintf(char* buf, size_t len, const char*, ...) __PRINTFLIKE(3, 4);
+
+int vprintf(const char*, va_list);
+int vfprintf(FILE*, const char*, va_list);
+int vsnprintf(char* buf, size_t len, const char*, va_list);
+
+__END_CDECLS
+
+#if DISABLE_DEBUG_OUTPUT
+// The declarations stand so these can be used without parens to get
+// the real functions (e.g. &printf or (printf)(...)).
+#define printf(...)
+#define vprintf(fmt, args)
+#endif
+
+#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDIO_H_
diff --git a/lib/libc/include/stdlib.h b/lib/libc/include/stdlib.h
new file mode 100644
index 0000000..45c5a21
--- /dev/null
+++ b/lib/libc/include/stdlib.h
@@ -0,0 +1,36 @@
+// Copyright 2016 The Fuchsia Authors
+// Copyright (c) 2008-2014 Travis Geiselbrecht
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT
+
+#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDLIB_H_
+#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDLIB_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <zircon/compiler.h>
+
+#ifdef _KERNEL
+#include <lib/heap.h> // lib/heap provides malloc/free definitions.
+#endif
+
+__BEGIN_CDECLS
+
+long strtol(const char *nptr, char **endptr, int base);
+unsigned long int strtoul(const char *nptr, char **endptr, int base);
+
+void abort(void) __attribute__((noreturn));
+
+#define RAND_MAX (0x7fffffff)
+
+int rand(void);
+void srand(unsigned int seed);
+
+// Note: POSIX.1 specifies unsigned int, but we use uintptr_t instead.
+int rand_r(uintptr_t *seed);
+
+__END_CDECLS
+
+#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDLIB_H_
diff --git a/lib/libc/include/string-file.h b/lib/libc/include/string-file.h
new file mode 100644
index 0000000..1632933
--- /dev/null
+++ b/lib/libc/include/string-file.h
@@ -0,0 +1,79 @@
+// Copyright 2021 The Fuchsia Authors
+// Copyright (c) 2008 Travis Geiselbrecht
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT
+
+#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_FILE_H_
+#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_FILE_H_
+
+#ifdef __cplusplus
+#include <stdio.h>
+
+#include <ktl/algorithm.h>
+#include <ktl/span.h>
+#include <ktl/string_view.h>
+
+// FILE* wrapper over a string.
+class StringFile : public FILE {
+ public:
+ StringFile() = delete;
+ StringFile(const StringFile &) = delete;
+ StringFile operator=(const StringFile &) = delete;
+
+ explicit StringFile(ktl::span<char> s) : FILE(this), buffer_(s) {}
+
+ ~StringFile() = default;
+
+ // Adds a null character at the end of the current buffer and returns a view
+ // into the written section.
+ ktl::span<char> take() &&;
+
+ // Returns |str.size()| and writes as much of |str| as it would fit in the
+ // buffer [offest_, size - 1) while reserving the last byte for null
+ // character.
+ int Write(ktl::string_view str);
+
+ // Returns a region representing the currently used portion of the buffer.
+ ktl::span<char> used_region() const {
+ return (offset_ > 0) ? ktl::span<char>{buffer_.data(), offset_} : ktl::span<char>{};
+ }
+
+ // Returns a region representing the remaining unused space in the buffer,
+ // _not_ including the space reserved for the final null character.
+ ktl::span<char> available_region() const {
+ const size_t available = ktl::max<size_t>(buffer_.size() - offset_, 1) - 1;
+ return (available > 0) ? ktl::span<char>{buffer_.data() + offset_, available}
+ : ktl::span<char>{};
+ }
+
+ // Skip up to |amt| bytes in the buffer, advancing the write pointer as if we
+ // had written data, but without actually changing the buffer.
+ void Skip(size_t amt) {
+ amt = ktl::min(amt, available_region().size());
+ offset_ += amt;
+ }
+
+ // Provide two ways for users to convert the currently used buffer into a
+ // string_view. Given a string file |S|, users may say either:
+ //
+ // 1) S.as_string_view(); // or
+ // 2) static_cast<ktl::string_view>(S);
+ //
+ // to perform the conversion.
+ //
+ ktl::string_view as_string_view() const {
+ return (offset_ > 0) ? ktl::string_view{buffer_.data(), offset_} : ktl::string_view{};
+ }
+
+ explicit operator ktl::string_view() const { return this->as_string_view(); }
+
+ private:
+ ktl::span<char> buffer_;
+ size_t offset_ = 0;
+};
+
+#endif // __cplusplus
+
+#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_FILE_H_
diff --git a/lib/libc/include/string.h b/lib/libc/include/string.h
new file mode 100644
index 0000000..3b55ccb
--- /dev/null
+++ b/lib/libc/include/string.h
@@ -0,0 +1,97 @@
+// Copyright 2016 The Fuchsia Authors
+// Copyright (c) 2008 Travis Geiselbrecht
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT
+
+#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_H_
+#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_H_
+
+// Other libc++ headers use <cstring> but libc++'s <cstring> complains if it
+// thinks <string.h> is not its own wrapper, which we do not need. We always
+// get the kernel's <string.h> before the libc++ with the way the include paths
+// are set up, which is necessary because of other headers where preempting
+// libc++'s header is unavoidable for the kernel environment. So just we
+// define the macro that <cstring> checks for to keep it happy.
+#define _LIBCPP_STRING_H
+
+#include <stddef.h>
+#include <zircon/compiler.h>
+
+__BEGIN_CDECLS
+
+int memcmp(const void*, const void*, size_t) __PURE;
+void* memcpy(void*, const void*, size_t);
+void* memmove(void*, const void*, size_t);
+void* memset(void*, int, size_t);
+
+char* strcat(char*, const char*);
+int strcmp(const char*, const char*) __PURE;
+char* strcpy(char*, const char*);
+size_t strlen(const char*) __PURE;
+char* strncat(char*, const char*, size_t);
+int strncmp(const char*, const char*, size_t) __PURE;
+char* strncpy(char*, const char*, size_t);
+size_t strspn(const char*, const char*) __PURE;
+size_t strcspn(const char* s, const char*) __PURE;
+char* strtok(char*, const char*);
+int strcoll(const char* s1, const char* s2) __PURE;
+size_t strxfrm(char* dest, const char* src, size_t n) __PURE;
+
+// Not actually defined in the kernel, but <cstring> expects the declaration.
+char* strerror(int);
+
+// Nonstandard.
+size_t strlcat(char*, const char*, size_t);
+size_t strlcpy(char*, const char*, size_t);
+int strncasecmp(const char*, const char*, size_t) __PURE;
+int strnicmp(const char*, const char*, size_t) __PURE;
+size_t strnlen(const char* s, size_t count) __PURE;
+
+// Used by address sanitizer.
+__typeof(memcpy) __unsanitized_memcpy;
+__typeof(memmove) __unsanitized_memmove;
+__typeof(memset) __unsanitized_memset;
+
+__END_CDECLS
+
+// C++ wants overloads for const and non-const versions of some functions.
+#ifdef __cplusplus
+
+const char* strchr(const char*, int) __asm__("strchr") __PURE;
+inline char* strchr(char* s, int c) {
+ return const_cast<char*>(strchr(const_cast<const char*>(s), c));
+}
+
+const char* strpbrk(const char*, const char*) __asm__("strpbrk") __PURE;
+inline char* strpbrk(char* s1, const char* s2) {
+ return const_cast<char*>(strpbrk(const_cast<const char*>(s1), s2));
+}
+
+const char* strrchr(const char*, int) __asm__("strrchr") __PURE;
+inline char* strrchr(char* s, int c) {
+ return const_cast<char*>(strrchr(const_cast<const char*>(s), c));
+}
+
+const void* memchr(const void*, int, size_t) __asm__("memchr") __PURE;
+inline void* memchr(void* s, int c, size_t n) {
+ return const_cast<void*>(memchr(const_cast<const void*>(s), c, n));
+}
+
+const char* strstr(const char*, const char*) __asm__("strstr") __PURE;
+inline char* strstr(char* s1, const char* s2) {
+ return const_cast<char*>(strstr(const_cast<const char*>(s1), s2));
+}
+
+#else
+
+void* memchr(const void*, int, size_t);
+char* strchr(const char*, int) __PURE;
+char* strpbrk(const char*, const char*) __PURE;
+char* strrchr(const char*, int) __PURE;
+char* strstr(const char*, const char*) __PURE;
+
+#endif // __cplusplus
+
+#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_H_