diff --git a/libc/src/stdio/printf_files/converter.h b/libc/src/stdio/printf_files/converter.h new file mode 100644 --- /dev/null +++ b/libc/src/stdio/printf_files/converter.h @@ -0,0 +1,34 @@ +//===-- Format specifier converter for printf -------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_STDIO_PRINTF_FILES_CONVERTER_H +#define LLVM_LIBC_SRC_STDIO_PRINTF_FILES_CONVERTER_H + +#include "src/stdio/printf_files/core_structs.h" +#include "src/stdio/printf_files/writer.h" + +#include + +namespace __llvm_libc { +namespace internal { +namespace printf_core { + +class Converter { + Writer *writer; + +public: + Converter(Writer *writer); + + void convert(format_section to_conv); +}; + +} // namespace printf_core +} // namespace internal +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDIO_PRINTF_FILES_CONVERTER_H diff --git a/libc/src/stdio/printf_files/core_structs.h b/libc/src/stdio/printf_files/core_structs.h new file mode 100644 --- /dev/null +++ b/libc/src/stdio/printf_files/core_structs.h @@ -0,0 +1,74 @@ +//===-- Core Structures for printf ------------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_STDIO_PRINTF_FILES_CORE_STRUCTS_H +#define LLVM_LIBC_SRC_STDIO_PRINTF_FILES_CORE_STRUCTS_H + +#include +#include + +namespace __llvm_libc { +namespace internal { +namespace printf_core { + +enum class LengthModifier { hh, h, l, ll, j, z, t, L, none }; +enum VariableType : uint8_t { + // Types + + Void = 0x00, + Char = 0x01, + // WChar = 0x02, + // WInt = 0x03, + Short = 0x04, + Int = 0x05, + Long = 0x06, + LLong = 0x07, + Intmax = 0x08, + Size = 0x09, + Ptrdiff = 0x0a, + Double = 0x0b, + LDouble = 0x0c, + + // Modifiers + + Signed = 0x40, + Pointer = 0x80, + + // Masks + + Type_Mask = 0x3f, + Modifier_Mask = 0xc, +}; + +struct format_section { + bool has_conv; + + const char *__restrict raw_string; + size_t raw_len; + + // Format Specifier Values + bool left_justified; + bool force_sign; + bool space_prefix; + bool alt_form; + bool leading_zeroes; + LengthModifier length_modifier; + int min_width; + int precision; + + __uint128_t conv_val_raw; // Needs to be large enough to hold a long double. + void *conv_val_ptr; + + char conv_name; +}; + +} // namespace printf_core +} // namespace internal +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDIO_PRINTF_FILES_CORE_STRUCTS_H diff --git a/libc/src/stdio/printf_files/parser.h b/libc/src/stdio/printf_files/parser.h new file mode 100644 --- /dev/null +++ b/libc/src/stdio/printf_files/parser.h @@ -0,0 +1,51 @@ +//===-- Format string parser for printf -------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_STDIO_PRINTF_FILES_PARSER_H +#define LLVM_LIBC_SRC_STDIO_PRINTF_FILES_PARSER_H + +#include "src/stdio/printf_files/core_structs.h" + +#include +#include + +namespace __llvm_libc { +namespace internal { +namespace printf_core { + +// TODO: Make this a compile option. +constexpr size_t TYPE_ARR_SIZE = 32; + +class Parser { + const char *__restrict str; + + size_t cur_pos = 0; + + va_list *vlist_start; + va_list *vlist_cur; + size_t vlist_index; + + // TODO: Make this an optional piece. + VariableType type_arr[TYPE_ARR_SIZE]; + + // TODO: Look into object stores for optimization. + +public: + Parser(const char *__restrict str, va_list *vlist); + + format_section get_next_section(); + +private: + template T get_arg_value(size_t index); +}; + +} // namespace printf_core +} // namespace internal +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDIO_PRINTF_FILES_PARSER_H diff --git a/libc/src/stdio/printf_files/printf_main.h b/libc/src/stdio/printf_files/printf_main.h new file mode 100644 --- /dev/null +++ b/libc/src/stdio/printf_files/printf_main.h @@ -0,0 +1,42 @@ +//===-- Starting point for printf -------------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_STDIO_PRINTF_FILES_PRINTF_MAIN_H +#define LLVM_LIBC_SRC_STDIO_PRINTF_FILES_PRINTF_MAIN_H + +#include "src/stdio/printf_files/converter.h" +#include "src/stdio/printf_files/core_structs.h" +#include "src/stdio/printf_files/parser.h" +#include "src/stdio/printf_files/writer.h" + +#include +#include + +namespace __llvm_libc { +namespace internal { + +int printf_main(printf_core::Writer *writer, const char *__restrict str, + va_list vlist) { + printf_core::Parser parser(str, &vlist); + printf_core::Converter converter(writer); + + for (printf_core::format_section cur_section = parser.get_next_section(); + cur_section.raw_len > 0; cur_section = parser.get_next_section()) { + if (cur_section.has_conv) + converter.convert(cur_section); + else + writer->write(cur_section.raw_string, cur_section.raw_len); + } + + return writer->get_chars_written(); +} + +} // namespace internal +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDIO_PRINTF_FILES_PRINTF_MAIN_H diff --git a/libc/src/stdio/printf_files/writer.h b/libc/src/stdio/printf_files/writer.h new file mode 100644 --- /dev/null +++ b/libc/src/stdio/printf_files/writer.h @@ -0,0 +1,40 @@ +//===-- String writer for printf --------------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_STDIO_PRINTF_FILES_WRITER_H +#define LLVM_LIBC_SRC_STDIO_PRINTF_FILES_WRITER_H + +#include + +namespace __llvm_libc { +namespace internal { +namespace printf_core { + +using WriteFunc = void (*)(void *, const char *__restrict, size_t); + +class Writer { + void *output; + WriteFunc raw_write; + + size_t max_length; + size_t chars_written; + +public: + Writer(void *output, WriteFunc raw_write, size_t max_length); + + void write(const char *new_string, size_t length); + void write_chars(char new_char, size_t length); + + size_t get_chars_written(); +}; + +} // namespace printf_core +} // namespace internal +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDIO_PRINTF_FILES_WRITER_H