From b881c0ec9ea6936a87b8032375b3f11e21087b05 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sat, 17 Jun 2023 10:13:50 -0700 Subject: [PATCH] Remove printf() linking hack --- Makefile | 2 +- README.md | 4 +- ape/ape.lds | 30 +- build/definitions.mk | 2 +- examples/hello.c | 5 +- examples/hello3.c | 4 +- libc/dns/getnameinfo.c | 9 +- libc/fmt/conv.h | 8 + libc/fmt/fmt.c | 431 ------ libc/fmt/fmt.h | 14 - libc/fmt/fmt.internal.h | 33 - libc/fmt/internal.h | 16 - libc/fmt/itoa.c | 30 - libc/fmt/ntoa.c | 196 --- libc/fmt/pad.c | 26 - libc/fmt/pflink.h | 71 - libc/fmt/stoa.c | 219 --- libc/isystem/stdio.h | 2 +- libc/isystem/stdlib.h | 3 +- libc/log/logerrno.c | 2 +- libc/log/meminfo.c | 2 +- libc/log/memsummary.c | 2 +- libc/log/vflogf.c | 2 +- libc/mem/fmt.h | 6 - libc/nexgen32e/cescapec.c | 56 - libc/sock/syslog.c | 2 +- libc/{mem => stdio}/asprintf.c | 0 libc/{calls => stdio}/dprintf.c | 2 +- libc/{calls => stdio}/dprintf.h | 6 - libc/stdio/dtoa.c | 567 ------- libc/stdio/fmt.c | 1375 +++++++++++++++++ libc/{fmt => stdio}/snprintf.c | 0 libc/{fmt => stdio}/sprintf.c | 0 libc/{fmt => stdio}/sscanf.c | 0 libc/stdio/stdio.h | 20 - libc/{fmt => stdio}/swprintf.c | 0 libc/{mem => stdio}/vasprintf.c | 0 libc/{fmt => stdio}/vcscanf.c | 0 libc/{calls => stdio}/vdprintf.c | 0 libc/{fmt => stdio}/vsnprintf.c | 0 libc/{fmt => stdio}/vsprintf.c | 0 libc/{fmt => stdio}/vsscanf.c | 0 libc/str/str.h | 1 - libc/time/time.mk | 3 +- libc/x/xasprintf.h | 6 - net/finger/describesyn.c | 2 +- test/libc/calls/symlinkat_test.c | 2 +- .../printf_uppercase_e_static_yoink_test.c | 42 - .../printf_uppercase_f_static_yoink_test.c | 41 - .../printf_uppercase_g_static_yoink_test.c | 41 - test/libc/nexgen32e/cescapec_test.c | 286 ---- test/libc/{fmt => stdio}/fmt_test.c | 1 - test/libc/{fmt => stdio}/fprintf_test.c | 0 test/libc/{fmt => stdio}/palandprintf_test.c | 2 - test/libc/{fmt => stdio}/snprintf_test.c | 0 test/libc/{fmt => stdio}/sprintf_s.inc | 0 test/libc/{fmt => stdio}/sprintf_s_test.c | 6 +- test/libc/{fmt => stdio}/sscanf_test.c | 1 - test/libc/tinymath/strtod_test.c | 2 +- test/net/http/parseurl_test.c | 1 - third_party/awk/lib.c | 2 +- third_party/ctags/args.h | 2 +- third_party/ctags/eiffel.c | 2 +- third_party/ctags/entry.h | 2 +- third_party/ctags/flex.c | 2 +- third_party/ctags/jscript.c | 2 +- third_party/ctags/main.h | 2 +- third_party/ctags/options.c | 4 +- third_party/ctags/read.h | 2 +- third_party/ctags/sort.c | 4 +- third_party/ctags/sql.c | 2 +- third_party/ctags/tex.c | 2 +- third_party/ctags/vim.c | 2 +- third_party/ctags/vstring.h | 2 +- third_party/gdtoa/atof.c | 1 + third_party/gdtoa/gdtoa.h | 56 +- third_party/gdtoa/strtod.c | 3 + third_party/gdtoa/strtod_l.c | 24 - third_party/gdtoa/strtof.c | 3 + third_party/gdtoa/strtof_l.c | 24 - third_party/gdtoa/strtold.c | 3 + third_party/gdtoa/strtold_l.c | 40 - third_party/gdtoa/wcstold.c | 2 + third_party/gdtoa/wcstold_l.c | 25 - third_party/hiredis/alloc.c | 2 +- third_party/hiredis/async.c | 2 +- third_party/hiredis/dict.c | 2 +- third_party/hiredis/hiredis.c | 2 +- third_party/hiredis/net.c | 4 +- third_party/hiredis/read.c | 2 +- third_party/hiredis/read.h | 2 +- third_party/hiredis/sds.c | 6 +- third_party/lua/luaconf.h | 2 +- third_party/quickjs/atof.c | 2 +- third_party/quickjs/qjs.c | 2 +- third_party/quickjs/qjsc.c | 2 +- third_party/regex/regex.mk | 2 +- third_party/sqlite3/geopoly.inc | 2 +- third_party/sqlite3/json.c | 3 +- third_party/zip/tailor.h | 4 +- third_party/zip/zip.c | 2 +- third_party/zip/zipcloak.c | 2 +- third_party/zip/zipfile.c | 2 +- third_party/zlib/inflate.c | 2 +- tool/viz/float2bin.c | 50 - tool/viz/getopts.c | 199 --- tool/viz/magikarp.c | 2 +- 107 files changed, 1520 insertions(+), 2577 deletions(-) delete mode 100644 libc/fmt/fmt.c delete mode 100644 libc/fmt/fmt.internal.h delete mode 100644 libc/fmt/internal.h delete mode 100644 libc/fmt/itoa.c delete mode 100644 libc/fmt/ntoa.c delete mode 100644 libc/fmt/pad.c delete mode 100644 libc/fmt/pflink.h delete mode 100644 libc/fmt/stoa.c delete mode 100644 libc/nexgen32e/cescapec.c rename libc/{mem => stdio}/asprintf.c (100%) rename libc/{calls => stdio}/dprintf.c (98%) rename libc/{calls => stdio}/dprintf.h (62%) delete mode 100644 libc/stdio/dtoa.c create mode 100644 libc/stdio/fmt.c rename libc/{fmt => stdio}/snprintf.c (100%) rename libc/{fmt => stdio}/sprintf.c (100%) rename libc/{fmt => stdio}/sscanf.c (100%) rename libc/{fmt => stdio}/swprintf.c (100%) rename libc/{mem => stdio}/vasprintf.c (100%) rename libc/{fmt => stdio}/vcscanf.c (100%) rename libc/{calls => stdio}/vdprintf.c (100%) rename libc/{fmt => stdio}/vsnprintf.c (100%) rename libc/{fmt => stdio}/vsprintf.c (100%) rename libc/{fmt => stdio}/vsscanf.c (100%) delete mode 100644 test/libc/fmt/printf_uppercase_e_static_yoink_test.c delete mode 100644 test/libc/fmt/printf_uppercase_f_static_yoink_test.c delete mode 100644 test/libc/fmt/printf_uppercase_g_static_yoink_test.c delete mode 100644 test/libc/nexgen32e/cescapec_test.c rename test/libc/{fmt => stdio}/fmt_test.c (99%) rename test/libc/{fmt => stdio}/fprintf_test.c (100%) rename test/libc/{fmt => stdio}/palandprintf_test.c (99%) rename test/libc/{fmt => stdio}/snprintf_test.c (100%) rename test/libc/{fmt => stdio}/sprintf_s.inc (100%) rename test/libc/{fmt => stdio}/sprintf_s_test.c (95%) rename test/libc/{fmt => stdio}/sscanf_test.c (99%) delete mode 100644 third_party/gdtoa/strtod_l.c delete mode 100644 third_party/gdtoa/strtof_l.c delete mode 100644 third_party/gdtoa/strtold_l.c delete mode 100644 third_party/gdtoa/wcstold_l.c delete mode 100644 tool/viz/float2bin.c delete mode 100644 tool/viz/getopts.c diff --git a/Makefile b/Makefile index 3c367066a..84bd79b00 100644 --- a/Makefile +++ b/Makefile @@ -143,8 +143,8 @@ include third_party/gdtoa/gdtoa.mk # ├──DYNAMIC RUNTIME include third_party/nsync/mem/mem.mk # │ You can now use stdio include libc/thread/thread.mk # │ You can finally call malloc() include libc/zipos/zipos.mk # │ -include libc/time/time.mk # │ include libc/stdio/stdio.mk # │ +include libc/time/time.mk # │ include third_party/libcxx/libcxx.mk # │ include net/net.mk # │ include third_party/vqsort/vqsort.mk # │ diff --git a/README.md b/README.md index 7dee52bf1..38cc79483 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,9 @@ contains your non-monorepo artifacts. sudo mkdir -p /opt sudo chmod 1777 /opt git clone https://github.com/jart/cosmopolitan /opt/cosmo -(cd /opt/cosmo; make -j8 toolchain) +cd /opt/cosmo +make -j8 toolchain +ape/apeinstall.sh # optional mkdir -p /opt/cosmos/bin export PATH="/opt/cosmos/bin:$PATH" echo 'PATH="/opt/cosmos/bin:$PATH"' >>~/.profile diff --git a/ape/ape.lds b/ape/ape.lds index 0e93d0117..dd1ff57cc 100644 --- a/ape/ape.lds +++ b/ape/ape.lds @@ -257,7 +257,7 @@ SECTIONS { HIDDEN(ape_macho_end = .); KEEP(*(.ape.pad.head)) - . = ALIGN(SupportsWindows() || SupportsMetal() ? 4096 : 16); + . = ALIGN(SupportsWindows() || SupportsMetal() ? CONSTANT(COMMONPAGESIZE) : 16); HIDDEN(_ehead = .); } :Head @@ -311,7 +311,7 @@ SECTIONS { /* Privileged code invulnerable to magic */ KEEP(*(.ape.pad.privileged)); - . = ALIGN(__privileged_end > __privileged_start ? 4096 : 1); + . = ALIGN(__privileged_end > __privileged_start ? CONSTANT(COMMONPAGESIZE) : 1); /*END: morphable code */ __privileged_start = .; *(.privileged) @@ -368,13 +368,13 @@ SECTIONS { KEEP(*(SORT_BY_NAME(.sort.rodata.*))) KEEP(*(.ape.pad.text)) - . = ALIGN(4096); + . = ALIGN(CONSTANT(COMMONPAGESIZE)); HIDDEN(_etext = .); PROVIDE_HIDDEN(etext = .); /*END: Read Only Data (only needed for initialization) */ } :Rom - . = DATA_SEGMENT_ALIGN(4096, 4096); + . = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE)); /* initialization image for thread-local storage, this is copied */ /* out to actual TLS areas at runtime, so just make it read-only */ @@ -383,7 +383,7 @@ SECTIONS { *(SORT_BY_ALIGNMENT(.tdata)) *(SORT_BY_ALIGNMENT(.tdata.*)) _tdata_end = .; - . = ALIGN(4096); + . = ALIGN(CONSTANT(COMMONPAGESIZE)); } :Tls :Rom /*END: Read Only Data */ @@ -398,7 +398,9 @@ SECTIONS { _tbss_end = .; } :Tls - .data ALIGN(4096) : { + . = DATA_SEGMENT_RELRO_END(0, .); + + .data : { /*BEGIN: Read/Write Data */ KEEP(*(SORT_BY_NAME(.piro.data.sort.iat.*))) /*BEGIN: NT FORK COPYING */ @@ -428,7 +430,7 @@ SECTIONS { HIDDEN(_edata = .); PROVIDE_HIDDEN(edata = .); HIDDEN(_ezip = .); /* <-- very deprecated */ - . = ALIGN(4096); + . = ALIGN(CONSTANT(COMMONPAGESIZE)); } :Ram /*END: file content that's loaded by o/s */ @@ -454,7 +456,7 @@ SECTIONS { KEEP(*(.bssepilogue)) /*END: NT FORK COPYING */ - . = ALIGN(4096); + . = ALIGN(CONSTANT(COMMONPAGESIZE)); HIDDEN(_end = .); PROVIDE_HIDDEN(end = .); } :Bss @@ -537,7 +539,7 @@ HIDDEN(ape_rom_vaddr = ADDR(.head)); HIDDEN(ape_rom_paddr = LOADADDR(.head)); HIDDEN(ape_rom_filesz = LOADADDR(.data) - ape_rom_paddr); HIDDEN(ape_rom_memsz = ADDR(.data) - ADDR(.head)); -HIDDEN(ape_rom_align = 4096); +HIDDEN(ape_rom_align = CONSTANT(COMMONPAGESIZE)); HIDDEN(ape_rom_rva = RVA(ape_rom_vaddr)); HIDDEN(ape_ram_offset = ape_rom_offset + ape_rom_filesz); @@ -545,7 +547,7 @@ HIDDEN(ape_ram_vaddr = ADDR(.data)); HIDDEN(ape_ram_paddr = LOADADDR(.data)); HIDDEN(ape_ram_filesz = SIZEOF(.data)); HIDDEN(ape_ram_memsz = ADDR(.bss) + SIZEOF(.bss) - ape_ram_vaddr); -HIDDEN(ape_ram_align = 4096); +HIDDEN(ape_ram_align = CONSTANT(COMMONPAGESIZE)); HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr)); HIDDEN(ape_stack_pf = DEFINED(ape_stack_pf) ? ape_stack_pf : PF_R | PF_W); @@ -569,7 +571,7 @@ HIDDEN(ape_text_paddr = LOADADDR(.text)); HIDDEN(ape_text_vaddr = ADDR(.text)); HIDDEN(ape_text_filesz = SIZEOF(.text) + SIZEOF(.tdata)); HIDDEN(ape_text_memsz = SIZEOF(.text) + SIZEOF(.tdata)); -HIDDEN(ape_text_align = 4096); +HIDDEN(ape_text_align = CONSTANT(COMMONPAGESIZE)); HIDDEN(ape_text_rva = RVA(ape_text_vaddr)); HIDDEN(ape_data_offset = ape_ram_offset + LOADADDR(.data) - ape_ram_paddr); @@ -577,7 +579,7 @@ HIDDEN(ape_data_paddr = LOADADDR(.data)); HIDDEN(ape_data_vaddr = ADDR(.data)); HIDDEN(ape_data_filesz = SIZEOF(.data)); HIDDEN(ape_data_memsz = SIZEOF(.data)); -HIDDEN(ape_data_align = 4096); +HIDDEN(ape_data_align = CONSTANT(COMMONPAGESIZE)); HIDDEN(ape_data_rva = RVA(ape_data_vaddr)); HIDDEN(ape_bss_offset = ape_ram_offset + LOADADDR(.bss) - ape_ram_paddr); @@ -585,7 +587,7 @@ HIDDEN(ape_bss_paddr = LOADADDR(.bss)); HIDDEN(ape_bss_vaddr = ADDR(.bss)); HIDDEN(ape_bss_filesz = 0); HIDDEN(ape_bss_memsz = SIZEOF(.bss)); -HIDDEN(ape_bss_align = 4096); +HIDDEN(ape_bss_align = CONSTANT(COMMONPAGESIZE)); /* we roundup here because xnu wants the file load segments page-aligned */ /* but we don't want to add the nop padding to the ape program, so we'll */ @@ -593,7 +595,7 @@ HIDDEN(ape_bss_align = 4096); SHSTUB2(ape_loader_dd_skip, DEFINED(ape_loader) ? RVA(ape_loader) / 64 : 0); SHSTUB2(ape_loader_dd_count, DEFINED(ape_loader_end) - ? ROUNDUP(ape_loader_end - ape_loader, 4096) / 64 + ? ROUNDUP(ape_loader_end - ape_loader, CONSTANT(COMMONPAGESIZE)) / 64 : 0); #if defined(APE_IS_SHELL_SCRIPT) && !IsTiny() diff --git a/build/definitions.mk b/build/definitions.mk index cd4d9f430..2b515e927 100644 --- a/build/definitions.mk +++ b/build/definitions.mk @@ -241,7 +241,7 @@ DEFAULT_LDFLAGS = \ -nostdlib \ --gc-sections \ --build-id=none \ - --no-dynamic-linker --cref -Map=$@.map + --no-dynamic-linker #--cref -Map=$@.map ifeq ($(ARCH), aarch64) DEFAULT_LDFLAGS += \ diff --git a/examples/hello.c b/examples/hello.c index 0e42430d0..f56cbae1e 100644 --- a/examples/hello.c +++ b/examples/hello.c @@ -7,12 +7,9 @@ │ • http://creativecommons.org/publicdomain/zero/1.0/ │ ╚─────────────────────────────────────────────────────────────────*/ #endif -#include "libc/calls/calls.h" #include "libc/stdio/stdio.h" -STATIC_YOINK("mmap"); // TODO: fix bandaid for MODE=asan - int main() { - printf("%s\n", "hello world"); + printf("hello world\n"); return 0; } diff --git a/examples/hello3.c b/examples/hello3.c index 64fbdbbb2..a81ddf045 100644 --- a/examples/hello3.c +++ b/examples/hello3.c @@ -8,10 +8,10 @@ ╚─────────────────────────────────────────────────────────────────*/ #endif #include "libc/errno.h" -#include "libc/fmt/fmt.h" +#include "libc/math.h" #include "libc/stdio/stdio.h" int main() { - printf("%`'s\n", "hello\1\2world→→"); + printf("%g %`'s\n", M_PI, "hello\1\2world→→"); return errno; } diff --git a/libc/dns/getnameinfo.c b/libc/dns/getnameinfo.c index b490f2346..e5120d8f4 100644 --- a/libc/dns/getnameinfo.c +++ b/libc/dns/getnameinfo.c @@ -103,9 +103,12 @@ int getnameinfo(const struct sockaddr *addr, socklen_t addrlen, char *name, if (service != NULL && servicelen != 0) { if ((flags & NI_NUMERICSERV) || LookupServicesByPort(port, ((flags & NI_DGRAM) ? "udp" : "tcp"), 4, - info, sizeof(info), NULL) == -1) - itoa(port, info, 10); - if (strlen(info) + 1 > servicelen) return EAI_OVERFLOW; + info, sizeof(info), NULL) == -1) { + FormatInt32(info, port); + } + if (strlen(info) + 1 > servicelen) { + return EAI_OVERFLOW; + } strcpy(service, info); } diff --git a/libc/fmt/conv.h b/libc/fmt/conv.h index 4b47e05b9..1d0df03ff 100644 --- a/libc/fmt/conv.h +++ b/libc/fmt/conv.h @@ -40,6 +40,14 @@ unsigned long long wcstoull(const wchar_t *, wchar_t **, int); int wcscoll(const wchar_t *, const wchar_t *); size_t wcsxfrm(wchar_t *, const wchar_t *, size_t); +double atof(const char *); +float strtof(const char *, char **); +double strtod(const char *, char **); +long double strtold(const char *, char **); +float wcstof(const wchar_t *, wchar_t **); +double wcstod(const wchar_t *, wchar_t **); +long double wcstold(const wchar_t *, wchar_t **); + /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § conversion » time ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ diff --git a/libc/fmt/fmt.c b/libc/fmt/fmt.c deleted file mode 100644 index 4fce31775..000000000 --- a/libc/fmt/fmt.c +++ /dev/null @@ -1,431 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2021 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/fmt/fmt.h" -#include "libc/assert.h" -#include "libc/errno.h" -#include "libc/fmt/conv.h" -#include "libc/fmt/fmt.internal.h" -#include "libc/fmt/internal.h" -#include "libc/fmt/itoa.h" -#include "libc/intrin/bits.h" -#include "libc/intrin/nomultics.internal.h" -#include "libc/intrin/weaken.h" -#include "libc/macros.internal.h" -#include "libc/mem/mem.h" -#include "libc/runtime/internal.h" -#include "libc/str/str.h" -#include "libc/sysv/errfuns.h" -#include "third_party/gdtoa/gdtoa.h" - -static int __fmt_atoi(const char **str) { - int i; - for (i = 0; '0' <= **str && **str <= '9'; ++*str) { - i *= 10; - i += **str - '0'; - } - return i; -} - -/** - * Implements {,v}{,s{,n},{,{,x}as},f,d}printf domain-specific language. - * - * Type Specifiers - * - * - `%s` char * (thompson-pike unicode) - * - `%ls` wchar_t * (32-bit unicode → thompson-pike unicode) - * - `%hs` char16_t * (16-bit unicode → thompson-pike unicode) - * - `%b` int (radix 2 binary) - * - `%o` int (radix 8 octal) - * - `%d` int (radix 10 decimal) - * - `%x` int (radix 16 hexadecimal) - * - `%X` int (radix 16 hexadecimal uppercase) - * - `%p` pointer (48-bit hexadecimal) - * - `%u` unsigned - * - `%g` double (smart formatting) - * - `%e` double (expo formatting) - * - `%f` double (ugly formatting) - * - `%a` double (hex formatting) - * - `%Lg` long double - * - * Size Modifiers - * - * - `%hhd` char (8-bit) - * - `%hd` short (16-bit) - * - `%ld` long (64-bit) - * - `%lu` unsigned long (64-bit) - * - `%lx` unsigned long (64-bit hexadecimal) - * - `%jd` intmax_t (64-bit) - * - `%jjd` int128_t (128-bit) - * - * Width Modifiers - * - * - `%08d` fixed columns w/ zero leftpadding - * - `%8d` fixed columns w/ space leftpadding - * - `%*s` variable column string (thompson-pike) - * - * Precision Modifiers - * - * - `%.8s` supplied byte length (obeys nul terminator) - * - `%.*s` supplied byte length argument (obeys nul terminator) - * - ``%`.*s`` supplied byte length argument c escaped (ignores nul term) - * - `%#.*s` supplied byte length argument visualized (ignores nul term) - * - `%.*hs` supplied char16_t length argument (obeys nul terminator) - * - `%.*ls` supplied wchar_t length argument (obeys nul terminator) - * - * Formatting Modifiers - * - * - `%,d` thousands separators - * - `%'s` escaped c string literal - * - ``%`c`` c escaped character - * - ``%`'c`` c escaped character quoted - * - ``%`s`` c escaped string - * - ``%`'s`` c escaped string quoted - * - ``%`s`` escaped double quoted c string literal - * - ``%`c`` escaped double quoted c character literal - * - `%+d` plus leftpad if positive (aligns w/ negatives) - * - `% d` space leftpad if positive (aligns w/ negatives) - * - `%#s` datum (radix 256 null-terminated ibm cp437) - * - `%#x` int (radix 16 hexadecimal w/ 0x prefix if not zero) - * - * @note implementation detail of printf(), snprintf(), etc. - * @see printf() for wordier documentation - * @note netlib.org is so helpful - * @asyncsignalsafe if floating point isn't used - * @vforksafe if floating point isn't used - */ -_Hide int __fmt(void *fn, void *arg, const char *format, va_list va) { - long ld; - void *p; - unsigned u; - char ibuf[21]; - bool longdouble; - unsigned long lu; - wchar_t charbuf[1]; - char *s, *q, qchar; - const char *alphabet; - unsigned char signbit, log2base; - int (*out)(const char *, void *, size_t); - int d, w, n, sign, prec, flags, width, lasterr; - - lasterr = errno; - out = fn ? fn : (void *)_missingno; - - while (*format) { - if (*format != '%') { - for (n = 1; format[n]; ++n) { - if (format[n] == '%') break; - } - if (out(format, arg, n) == -1) return -1; - format += n; - continue; - } - - if (!IsTiny()) { - if (format[1] == 's') { // FAST PATH: PLAIN STRING - s = va_arg(va, char *); - if (!s) s = "(null)"; - if (out(s, arg, strlen(s)) == -1) return -1; - format += 2; - continue; - } else if (format[1] == 'd') { // FAST PATH: PLAIN INTEGER - d = va_arg(va, int); - if (out(ibuf, arg, FormatInt32(ibuf, d) - ibuf) == -1) return -1; - format += 2; - continue; - } else if (format[1] == 'u') { // FAST PATH: PLAIN UNSIGNED - u = va_arg(va, unsigned); - if (out(ibuf, arg, FormatUint32(ibuf, u) - ibuf) == -1) return -1; - format += 2; - continue; - } else if (format[1] == 'x') { // FAST PATH: PLAIN HEX - u = va_arg(va, unsigned); - if (out(ibuf, arg, uint64toarray_radix16(u, ibuf)) == -1) return -1; - format += 2; - continue; - } else if (format[1] == 'l' && format[2] == 'x') { - lu = va_arg(va, unsigned long); // FAST PATH: PLAIN LONG HEX - if (out(ibuf, arg, uint64toarray_radix16(lu, ibuf)) == -1) return -1; - format += 3; - continue; - } else if (format[1] == 'l' && format[2] == 'd') { - ld = va_arg(va, long); // FAST PATH: PLAIN LONG - if (out(ibuf, arg, FormatInt64(ibuf, ld) - ibuf) == -1) return -1; - format += 3; - continue; - } else if (format[1] == 'l' && format[2] == 'u') { - lu = va_arg(va, unsigned long); // FAST PATH: PLAIN UNSIGNED LONG - if (out(ibuf, arg, FormatUint64(ibuf, lu) - ibuf) == -1) return -1; - format += 3; - continue; - } else if (format[1] == '.' && format[2] == '*' && format[3] == 's') { - n = va_arg(va, unsigned); // FAST PATH: PRECISION STRING - s = va_arg(va, const char *); - if (s) { - n = strnlen(s, n); - } else { - s = "(null)"; - n = MIN(6, n); - } - if (out(s, arg, n) == -1) return -1; - format += 4; - continue; - } - } - - // GENERAL PATH - format++; - sign = 0; - flags = 0; - getflag: - switch (*format++) { - case '0': - flags |= FLAGS_ZEROPAD; - goto getflag; - case '-': - flags |= FLAGS_LEFT; - goto getflag; - case '+': - sign = '+'; - flags |= FLAGS_PLUS; - goto getflag; - case ' ': - sign = ' '; - flags |= FLAGS_SPACE; - goto getflag; - case '#': - flags |= FLAGS_HASH; - goto getflag; - case ',': - flags |= FLAGS_GROUPING; - goto getflag; - case '`': - flags |= FLAGS_REPR; - // fallthrough - case '\'': - flags |= FLAGS_QUOTE; - goto getflag; - default: - format--; - break; - } - - // evaluate width field - width = 0; - if (isdigit(*format)) { - width = __fmt_atoi(&format); - } else if (*format == '*') { - w = va_arg(va, int); - if (w < 0) { - flags |= FLAGS_LEFT; // reverse padding - width = -w; - sign = '-'; - } else { - width = w; - } - format++; - } - - // evaluate prec field - prec = 0; - if (*format == '.') { - flags |= FLAGS_PRECISION; - format++; - if (isdigit(*format)) { - prec = __fmt_atoi(&format); - } else if (*format == '*') { - prec = va_arg(va, int); - format++; - } - } - if (prec < 0) { - prec = 0; - flags &= ~FLAGS_PRECISION; - } - - // evaluate length field - signbit = 31; - longdouble = false; - switch (*format) { - case 'j': // intmax_t - format++; - signbit = sizeof(intmax_t) * 8 - 1; - if (*format == 'j') { - format++; - signbit = sizeof(int128_t) * 8 - 1; - } - break; - case 'l': - if (format[1] == 'f' || format[1] == 'F') { - format++; - break; - } - if (format[1] == 'l') format++; - // fallthrough - case 't': // ptrdiff_t - case 'z': // size_t - case 'Z': // size_t - format++; - signbit = 63; - break; - case 'L': // long double - format++; - longdouble = true; - break; - case 'h': - format++; - if (*format == 'h') { - format++; - signbit = 7; - } else { - signbit = 15; - } - break; - default: - break; - } - - // evaluate specifier - qchar = '"'; - log2base = 0; - alphabet = "0123456789abcdefpx"; - switch ((d = *format++)) { - case 'p': - flags |= FLAGS_HASH; - log2base = 4; - signbit = 63; - goto FormatNumber; - case 'X': - alphabet = "0123456789ABCDEFPX"; - // fallthrough - case 'x': - log2base = 4; - goto FormatNumber; - case 'b': - log2base = 1; - alphabet = "0123456789abcdefpb"; - goto FormatNumber; - case 'o': - log2base = 3; - goto FormatNumber; - case 'd': - case 'i': - flags |= FLAGS_ISSIGNED; - // fallthrough - case 'u': { - uint128_t value; - flags &= ~FLAGS_HASH; // no hash for dec format - FormatNumber: - if (signbit > 63) { - value = va_arg(va, uint128_t); - } else { - value = va_arg(va, uint64_t); - } - if (__fmt_ntoa(out, arg, value, signbit, log2base, prec, width, flags, - alphabet) == -1) { - return -1; - } - break; - } - case 'c': - if ((charbuf[0] = va_arg(va, int))) { - p = charbuf; - qchar = '\''; - flags |= FLAGS_PRECISION; - prec = 1; - goto FormatString; - } else { - __FMT_PUT('\0'); - break; - } - case 'm': - p = _weaken(strerror) ? _weaken(strerror)(lasterr) : "?"; - signbit = 0; - goto FormatString; - case 'r': - // undocumented %r specifier - // used for good carriage return - // helps integrate loggers with repls - if (!__replstderr) { - break; - } else { - p = "\r\e[K"; - goto FormatString; - } - case 'S': - // Specified by POSIX to be equivalent to %ls - signbit = 63; - goto FormatStringPNotFetchedYet; - case 'q': - flags |= FLAGS_QUOTE; - // fallthrough - case 's': - FormatStringPNotFetchedYet: - p = va_arg(va, void *); - FormatString: - if (__fmt_stoa(out, arg, p, flags, prec, width, signbit, qchar) == -1) { - return -1; - } - break; - case 'n': - __FMT_PUT('\n'); - break; - case 'F': - case 'f': - case 'G': - case 'g': - case 'e': - case 'E': - case 'a': - case 'A': { - int rc; - if (!_weaken(__fmt_dtoa)) { - p = "?"; - prec = 0; - flags &= ~(FLAGS_PRECISION | FLAGS_PLUS | FLAGS_SPACE); - goto FormatString; - } - rc = _weaken(__fmt_dtoa)(out, arg, d, flags, prec, sign, width, - longdouble, qchar, signbit, alphabet, va); - if (rc == -1) return -1; -#ifdef __aarch64__ - // huge kludge - switch (rc) { - case __FMT_CONSUMED_DOUBLE: - va_arg(va, double); - break; - case __FMT_CONSUMED_LONG_DOUBLE: - va_arg(va, long double); - break; - default: - __builtin_unreachable(); - } -#endif /* __aarch64__ */ - break; - } - case '%': - __FMT_PUT('%'); - break; - default: - __FMT_PUT(format[-1]); - break; - } - } - - return 0; -} diff --git a/libc/fmt/fmt.h b/libc/fmt/fmt.h index 9835ef278..d8c9e84d9 100644 --- a/libc/fmt/fmt.h +++ b/libc/fmt/fmt.h @@ -1,6 +1,5 @@ #ifndef COSMOPOLITAN_LIBC_FMT_FMT_H_ #define COSMOPOLITAN_LIBC_FMT_FMT_H_ -#include "libc/fmt/pflink.h" /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § string formatting ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ @@ -31,19 +30,6 @@ char *fcvt(double, int, int *, int *); char *ecvt(double, int, int *, int *); char *gcvt(double, int, char *); -/*───────────────────────────────────────────────────────────────────────────│─╗ -│ cosmopolitan § string formatting » optimizations ─╬─│┼ -╚────────────────────────────────────────────────────────────────────────────│*/ - -#if defined(COSMO) && !defined(__cplusplus) -#define sprintf(BUF, FMT, ...) (sprintf)(BUF, PFLINK(FMT), ##__VA_ARGS__) -#define vsprintf(BUF, FMT, VA) (vsprintf)(BUF, PFLINK(FMT), VA) -#define snprintf(B, Z, F, ...) (snprintf)(B, Z, PFLINK(F), ##__VA_ARGS__) -#define vsnprintf(BUF, SIZE, FMT, VA) (vsnprintf)(BUF, SIZE, PFLINK(FMT), VA) -#define sscanf(STR, FMT, ...) (sscanf)(STR, SFLINK(FMT), ##__VA_ARGS__) -#define vsscanf(STR, FMT, VA) (vsscanf)(STR, SFLINK(FMT), VA) -#endif - COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_FMT_FMT_H_ */ diff --git a/libc/fmt/fmt.internal.h b/libc/fmt/fmt.internal.h deleted file mode 100644 index 0b25609a9..000000000 --- a/libc/fmt/fmt.internal.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_FMT_FMT_INTERNAL_H_ -#define COSMOPOLITAN_LIBC_FMT_FMT_INTERNAL_H_ - -#define PRINTF_NTOA_BUFFER_SIZE 144 - -#define __FMT_CONSUMED_DOUBLE 1 -#define __FMT_CONSUMED_LONG_DOUBLE 2 - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -#define __FMT_PUT(C) \ - do { \ - char Buf[1] = {C}; \ - if (out(Buf, arg, 1) == -1) { \ - return -1; \ - } \ - } while (0) - -int __fmt_pad(int (*)(const char *, void *, size_t), void *, - unsigned long) _Hide; -int __fmt_stoa(int (*)(const char *, void *, size_t), void *, void *, - unsigned long, unsigned long, unsigned long, unsigned char, - unsigned char) _Hide; -int __fmt_ntoa(int (*)(const char *, void *, size_t), void *, uint128_t, - unsigned char, unsigned long, unsigned long, unsigned long, - unsigned char, const char *) _Hide; -int __fmt_dtoa(int (*)(const char *, void *, size_t), void *, int, int, int, - int, int, bool, char, unsigned char, const char *, va_list); - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_FMT_FMT_INTERNAL_H_ */ diff --git a/libc/fmt/internal.h b/libc/fmt/internal.h deleted file mode 100644 index 2ce4642b1..000000000 --- a/libc/fmt/internal.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_FMT_INTERNAL_H_ -#define COSMOPOLITAN_LIBC_FMT_INTERNAL_H_ - -#define FLAGS_ZEROPAD 0x01 -#define FLAGS_LEFT 0x02 -#define FLAGS_PLUS 0x04 -#define FLAGS_SPACE 0x08 -#define FLAGS_HASH 0x10 -#define FLAGS_PRECISION 0x20 -#define FLAGS_ISSIGNED 0x40 -#define FLAGS_NOQUOTE 0x80 -#define FLAGS_QUOTE FLAGS_SPACE -#define FLAGS_GROUPING FLAGS_NOQUOTE -#define FLAGS_REPR FLAGS_PLUS - -#endif /* COSMOPOLITAN_LIBC_FMT_INTERNAL_H_ */ diff --git a/libc/fmt/itoa.c b/libc/fmt/itoa.c deleted file mode 100644 index d513e374b..000000000 --- a/libc/fmt/itoa.c +++ /dev/null @@ -1,30 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/fmt/conv.h" -#include "libc/fmt/fmt.h" - -compatfn char *itoa(int value, char *str, int radix) { - (sprintf)(str, - VEIL("r", radix == 16 ? "%x" - : radix == 8 ? "%d" - : radix == 2 ? "%b" - : "%d"), - value); - return str; -} diff --git a/libc/fmt/ntoa.c b/libc/fmt/ntoa.c deleted file mode 100644 index 8f0e2f848..000000000 --- a/libc/fmt/ntoa.c +++ /dev/null @@ -1,196 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2021 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/assert.h" -#include "libc/fmt/conv.h" -#include "libc/fmt/divmod10.internal.h" -#include "libc/fmt/fmt.internal.h" -#include "libc/fmt/internal.h" -#include "libc/limits.h" -#include "libc/mem/reverse.internal.h" - -#define BUFFER_SIZE 144 - -uint128_t __udivmodti4(uint128_t, uint128_t, uint128_t *); - -static int __fmt_ntoa_format(int out(const char *, void *, size_t), void *arg, - char *buf, unsigned len, bool negative, - unsigned log2base, unsigned prec, unsigned width, - unsigned char flags, const char *alphabet) { - unsigned i, prec_width_zeros; - char alternate_form_middle_char, sign_character; - unsigned actual_buf_len; - actual_buf_len = len; - prec_width_zeros = 0; - /* pad leading zeros */ - if (width && (flags & FLAGS_ZEROPAD) && - (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { - width--; - } - if (len < prec) { - prec_width_zeros += (prec - len); - len = prec; - } - if ((flags & FLAGS_ZEROPAD) && (len < width)) { - prec_width_zeros += (width - len); - len = width; - } - /* handle hash */ - if (flags & FLAGS_HASH) { - if ((!(flags & FLAGS_PRECISION) || log2base == 3) && len && - ((len >= prec) || (len >= width)) && - (prec_width_zeros || buf[len - 1] == '0')) { - if (prec_width_zeros) { - --prec_width_zeros; - } - --len; - if (len < actual_buf_len) { - actual_buf_len = len; - } - if (len && (log2base == 4 || log2base == 1) && - (prec_width_zeros || buf[len - 1] == '0')) { - if (prec_width_zeros) { - --prec_width_zeros; - } - --len; - if (len < actual_buf_len) { - actual_buf_len = len; - } - } - } - alternate_form_middle_char = '\0'; - if ((log2base == 4 || log2base == 1)) { - ++len; - alternate_form_middle_char = - alphabet[17]; // x, X or b (for the corresponding conversion - // specifiers) - } - ++len; - } - sign_character = '\0'; - if (negative) { - ++len; - sign_character = '-'; - } else if (flags & FLAGS_PLUS) { - ++len; - sign_character = '+'; /* ignore the space if the '+' exists */ - } else if (flags & FLAGS_SPACE) { - ++len; - sign_character = ' '; - } - /* pad spaces up to given width */ - if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { - if (len < width) { - if (__fmt_pad(out, arg, width - len) == -1) return -1; - } - } - if (sign_character != '\0' && out(&sign_character, arg, 1) == -1) return -1; - if (flags & FLAGS_HASH) { - if (out("0", arg, 1) == -1) return -1; - if (alternate_form_middle_char != '\0' && - out(&alternate_form_middle_char, arg, 1) == -1) - return -1; - } - for (i = 0; i < prec_width_zeros; ++i) - if (out("0", arg, 1) == -1) return -1; - reverse(buf, actual_buf_len); - if (out(buf, arg, actual_buf_len) == -1) return -1; - /* append pad spaces up to given width */ - if (flags & FLAGS_LEFT) { - if (len < width) { - if (__fmt_pad(out, arg, width - len) == -1) return -1; - } - } - return 0; -} - -int __fmt_ntoa2(int out(const char *, void *, size_t), void *arg, - uint128_t value, bool neg, unsigned log2base, unsigned prec, - unsigned width, unsigned flags, const char *alphabet) { - uint128_t remainder; - unsigned len, count, digit; - char buf[BUFFER_SIZE]; - len = 0; - /* we check for log2base != 3 because otherwise we'll print nothing for a - * value of 0 with precision 0 when # mandates that one be printed */ - if (!value && log2base != 3) flags &= ~FLAGS_HASH; - if (value || !(flags & FLAGS_PRECISION)) { - count = 0; - do { - if (!log2base) { - if (value <= UINT64_MAX) { - value = DivMod10(value, &digit); - } else { - value = __udivmodti4(value, 10, &remainder); - digit = remainder; - } - } else { - digit = value; - digit &= (1u << log2base) - 1; - value >>= log2base; - } - if ((flags & FLAGS_GROUPING) && count == 3) { - buf[len++] = ','; - count = 1; - } else { - count++; - } - buf[len++] = alphabet[digit]; - } while (value); - _npassert(count <= BUFFER_SIZE); - } - return __fmt_ntoa_format(out, arg, buf, len, neg, log2base, prec, width, - flags, alphabet); -} - -int __fmt_ntoa(int out(const char *, void *, size_t), void *arg, - uint128_t value, unsigned char signbit, unsigned long log2base, - unsigned long prec, unsigned long width, unsigned char flags, - const char *lang) { - bool neg; - uint128_t sign; - - /* ignore '0' flag when prec or minus flag is given */ - if (flags & (FLAGS_PRECISION | FLAGS_LEFT)) { - flags &= ~FLAGS_ZEROPAD; - } - - /* no plus / space flag for u, x, X, o, b */ - if (!(flags & FLAGS_ISSIGNED)) { - flags &= ~(FLAGS_PLUS | FLAGS_SPACE); - } - - neg = 0; - sign = 1; - sign <<= signbit; - value &= sign | (sign - 1); - if (flags & FLAGS_ISSIGNED) { - if (value != sign) { - if (value & sign) { - value = ~value + 1; - value &= sign | (sign - 1); - neg = 1; - } - value &= sign - 1; - } else { - neg = 1; - } - } - - return __fmt_ntoa2(out, arg, value, neg, log2base, prec, width, flags, lang); -} diff --git a/libc/fmt/pad.c b/libc/fmt/pad.c deleted file mode 100644 index 9a1eac704..000000000 --- a/libc/fmt/pad.c +++ /dev/null @@ -1,26 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/fmt/fmt.internal.h" - -int __fmt_pad(int out(const char *, void *, size_t), void *arg, - unsigned long n) { - int i, rc; - for (rc = i = 0; i < n; ++i) rc |= out(" ", arg, 1); - return rc; -} diff --git a/libc/fmt/pflink.h b/libc/fmt/pflink.h deleted file mode 100644 index 1f654d3ef..000000000 --- a/libc/fmt/pflink.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_FMT_PFLINK_H_ -#define COSMOPOLITAN_LIBC_FMT_PFLINK_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -#ifdef COSMO - -/** - * @fileoverview builtin+preprocessor+linker tricks for printf/scanf. - * - * Your printf() function only requires that you pay for what you use. - * These macros ensure that its code size starts at under 4kb, growing - * to about 40kb for a fully-loaded implementation. This works best when - * format strings are constexprs that only contain directives. - */ - -#define PFLINK(...) _PFLINK(__VA_ARGS__) -#define _PFLINK(FMT, ...) \ - ({ \ - if (___PFLINK(FMT, strpbrk, "fFaAeEgG")) STATIC_YOINK("__fmt_dtoa"); \ - if (___PFLINK(FMT, strpbrk, "cmrqs")) { \ - if (___PFLINK(FMT, strstr, "%m")) STATIC_YOINK("strerror"); \ - if (___PFLINK(FMT, strstr, "%*") || \ - ___PFLINK(FMT, strpbrk, "0123456789")) { \ - STATIC_YOINK("strnwidth"); \ - STATIC_YOINK("strnwidth16"); \ - STATIC_YOINK("wcsnwidth"); \ - } \ - } \ - FMT; \ - }) - -#define SFLINK(...) _SFLINK(__VA_ARGS__) -#define _SFLINK(FMT) \ - ({ \ - if (___PFLINK(FMT, strchr, 'm')) { \ - STATIC_YOINK("malloc"); \ - STATIC_YOINK("calloc"); \ - STATIC_YOINK("free"); \ - STATIC_YOINK("__grow"); \ - } \ - FMT; \ - }) - -#if __GNUC__ + 0 < 4 || defined(__llvm__) -#define ___PFLINK(FMT, FN, C) 1 -#else -#define ___PFLINK(FMT, FN, C) \ - !__builtin_constant_p(FMT) || ((FMT) && __builtin_##FN(FMT, C) != NULL) -#endif - -#if defined(__GNUC__) && __GNUC__ < 6 -/* - * Compilers don't understand the features we've added to the format - * string DSL, such as c string escaping, therefore we can't use it. - * Ideally compilers should grant us more flexibility to define DSLs - * - * The recommended approach to turning this back on is `CFLAGS=-std=c11` - * which puts the compiler in __STRICT_ANSI__ mode, which Cosmopolitan - * respects by disabling all the esoteric tuning in headers like this. - */ -#pragma GCC diagnostic ignored "-Wformat-security" -#endif /* __GNUC__ + 0 < 6 */ - -#else -STATIC_YOINK("strerror"); -STATIC_YOINK("strnwidth"); -STATIC_YOINK("__fmt_dtoa"); -STATIC_YOINK("strnwidth16"); -STATIC_YOINK("wcsnwidth"); -#endif /* COSMO */ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_FMT_PFLINK_H_ */ diff --git a/libc/fmt/stoa.c b/libc/fmt/stoa.c deleted file mode 100644 index 6b6d02450..000000000 --- a/libc/fmt/stoa.c +++ /dev/null @@ -1,219 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/fmt/fmt.internal.h" -#include "libc/fmt/internal.h" -#include "libc/intrin/bits.h" -#include "libc/intrin/bsr.h" -#include "libc/intrin/safemacros.internal.h" -#include "libc/intrin/tpenc.h" -#include "libc/intrin/weaken.h" -#include "libc/str/str.h" -#include "libc/str/strwidth.h" -#include "libc/str/tab.internal.h" -#include "libc/str/thompike.h" -#include "libc/str/unicode.h" -#include "libc/str/utf16.h" - -typedef int (*out_f)(const char *, void *, size_t); -typedef int (*emit_f)(out_f, void *, uint64_t); - -static int __fmt_stoa_byte(out_f out, void *a, uint64_t c) { - char buf[1] = {c}; - return out(buf, a, 1); -} - -static int __fmt_stoa_wide(out_f out, void *a, uint64_t w) { - char buf[8]; - if (!isascii(w)) w = _tpenc(w); - WRITE64LE(buf, w); - return out(buf, a, w ? (_bsr(w) >> 3) + 1 : 1); -} - -static int __fmt_stoa_bing(out_f out, void *a, uint64_t w) { - char buf[8]; - w = _tpenc(kCp437[w & 0xFF]); - WRITE64LE(buf, w); - return out(buf, a, w ? (_bsr(w) >> 3) + 1 : 1); -} - -static int __fmt_stoa_quoted(out_f out, void *a, uint64_t w) { - char buf[8]; - if (isascii(w)) { - w = _cescapec(w); - } else { - w = _tpenc(w); - } - WRITE64LE(buf, w); - return out(buf, a, w ? (_bsr(w) >> 3) + 1 : 1); -} - -/** - * Converts string to array. - * - * This is used by __fmt() to implement the %s and %c directives. The - * content outputted to the array is always UTF-8, but the input may be - * UTF-16 or UTF-32. - * - * @see __fmt() - */ -int __fmt_stoa(int out(const char *, void *, size_t), void *arg, void *data, - unsigned long flags, unsigned long precision, - unsigned long width, unsigned char signbit, - unsigned char qchar) { - wint_t wc; - unsigned n; - emit_f emit; - char *p, buf[1]; - unsigned w, c, pad; - bool justdobytes, ignorenul; - - p = data; - if (!p) { - p = ((flags & FLAGS_REPR) ? "NULL" : "(null)"); - signbit = 0; - flags |= FLAGS_NOQUOTE; - if (flags & FLAGS_PRECISION) { - precision = min(strlen(p), precision); - } - } - - ignorenul = false; - justdobytes = false; - if (signbit == 15 || signbit == 63) { - if (flags & FLAGS_QUOTE) { - emit = __fmt_stoa_quoted; - ignorenul = flags & FLAGS_PRECISION; - } else { - emit = __fmt_stoa_wide; - } - } else if ((flags & FLAGS_HASH) && _weaken(kCp437)) { - justdobytes = true; - emit = __fmt_stoa_bing; - ignorenul = flags & FLAGS_PRECISION; - } else if (flags & FLAGS_QUOTE) { - emit = __fmt_stoa_quoted; - ignorenul = flags & FLAGS_PRECISION; - } else { - justdobytes = true; - emit = __fmt_stoa_byte; - } - - if (!(flags & FLAGS_PRECISION)) precision = -1; - if (!(flags & FLAGS_PRECISION) || !ignorenul) { - if (signbit == 63) { - precision = wcsnlen((const wchar_t *)p, precision); - } else if (signbit == 15) { - precision = strnlen16((const char16_t *)p, precision); - } else { - precision = strnlen(p, precision); - } - } - - pad = 0; - if (width) { - w = precision; - if (signbit == 63) { - if (_weaken(wcsnwidth)) { - w = _weaken(wcsnwidth)((const wchar_t *)p, precision, 0); - } - } else if (signbit == 15) { - if (_weaken(strnwidth16)) { - w = _weaken(strnwidth16)((const char16_t *)p, precision, 0); - } - } else if (_weaken(strnwidth)) { - w = _weaken(strnwidth)(p, precision, 0); - } - if (!(flags & FLAGS_NOQUOTE) && (flags & FLAGS_REPR)) { - w += 2 + (signbit == 63) + (signbit == 15); - } - if (w < width) { - pad = width - w; - } - } - - if (pad && !(flags & FLAGS_LEFT)) { - if (__fmt_pad(out, arg, pad) == -1) return -1; - } - - if (!(flags & FLAGS_NOQUOTE) && (flags & FLAGS_REPR)) { - if (signbit == 63) { - if (out("L", arg, 1) == -1) return -1; - } else if (signbit == 15) { - if (out("u", arg, 1) == -1) return -1; - } - buf[0] = qchar; - if (out(buf, arg, 1) == -1) return -1; - } - - if (justdobytes) { - while (precision--) { - wc = *p++ & 0xff; - if (!wc && !ignorenul) break; - if (emit(out, arg, wc) == -1) return -1; - } - } else { - while (precision--) { - if (signbit == 15) { - wc = *(const char16_t *)p; - if (!wc && !ignorenul) break; - if (IsUcs2(wc)) { - p += sizeof(char16_t); - } else if (IsUtf16Cont(wc)) { - p += sizeof(char16_t); - continue; - } else if (!precision) { - break; - } else { - --precision; - wc = MergeUtf16(wc, *(const char16_t *)p); - } - } else if (signbit == 63) { - wc = *(const wint_t *)p; - if (!wc && !ignorenul) break; - p += sizeof(wint_t); - if (!wc) break; - } else { - wc = *p++ & 0xff; - if (!wc && !ignorenul) break; - if (!isascii(wc)) { - if (ThomPikeCont(wc)) continue; - n = ThomPikeLen(wc) - 1; - wc = ThomPikeByte(wc); - if (n > precision) break; - precision -= n; - while (n--) { - wc = ThomPikeMerge(wc, *p++); - } - } - } - if (emit(out, arg, wc) == -1) return -1; - } - } - - if (!(flags & FLAGS_NOQUOTE) && (flags & FLAGS_REPR)) { - buf[0] = qchar; - if (out(buf, arg, 1) == -1) return -1; - } - - if (pad && (flags & FLAGS_LEFT)) { - if (__fmt_pad(out, arg, pad) == -1) return -1; - } - - return 0; -} diff --git a/libc/isystem/stdio.h b/libc/isystem/stdio.h index cf5d81c8f..d36eac7ed 100644 --- a/libc/isystem/stdio.h +++ b/libc/isystem/stdio.h @@ -1,7 +1,7 @@ #ifndef LIBC_ISYSTEM_STDIO_H_ #define LIBC_ISYSTEM_STDIO_H_ #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/libc/isystem/stdlib.h b/libc/isystem/stdlib.h index 79609ca1d..fe583d7ec 100644 --- a/libc/isystem/stdlib.h +++ b/libc/isystem/stdlib.h @@ -1,18 +1,17 @@ #ifndef LIBC_ISYSTEM_STDLIB_H_ #define LIBC_ISYSTEM_STDLIB_H_ #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" #include "libc/mem/alg.h" #include "libc/mem/mem.h" #include "libc/runtime/runtime.h" +#include "libc/stdio/dprintf.h" #include "libc/stdio/rand.h" #include "libc/stdio/temp.h" #include "libc/str/str.h" #include "libc/sysv/consts/exit.h" -#include "third_party/gdtoa/gdtoa.h" #include "third_party/getopt/getopt.h" #include "third_party/musl/crypt.h" #include "third_party/musl/rand48.h" diff --git a/libc/log/logerrno.c b/libc/log/logerrno.c index 1ea8b5ffe..69be9d43b 100644 --- a/libc/log/logerrno.c +++ b/libc/log/logerrno.c @@ -23,5 +23,5 @@ #include "libc/str/str.h" dontinstrument void _log_errno(const char *file, int line, const char *form) { - flogf(kLogWarn, file, line, NULL, PFLINK("%s → %s"), form, strerror(errno)); + flogf(kLogWarn, file, line, NULL, "%s → %s", form, strerror(errno)); } diff --git a/libc/log/meminfo.c b/libc/log/meminfo.c index 587e6eee8..ed39d5e19 100644 --- a/libc/log/meminfo.c +++ b/libc/log/meminfo.c @@ -17,7 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/fmt/fmt.h" #include "libc/log/log.h" #include "libc/mem/mem.h" diff --git a/libc/log/memsummary.c b/libc/log/memsummary.c index 133af514f..7aa3b8c56 100644 --- a/libc/log/memsummary.c +++ b/libc/log/memsummary.c @@ -17,7 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/log/log.h" #include "libc/mem/mem.h" diff --git a/libc/log/vflogf.c b/libc/log/vflogf.c index 5eabc4c43..a07915d4d 100644 --- a/libc/log/vflogf.c +++ b/libc/log/vflogf.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/blockcancel.internal.h" #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/struct/stat.h" #include "libc/calls/struct/timeval.h" #include "libc/dce.h" diff --git a/libc/mem/fmt.h b/libc/mem/fmt.h index 5691f040e..bf19f197b 100644 --- a/libc/mem/fmt.h +++ b/libc/mem/fmt.h @@ -1,6 +1,5 @@ #ifndef COSMOPOLITAN_LIBC_MEM_FMT_H_ #define COSMOPOLITAN_LIBC_MEM_FMT_H_ -#include "libc/fmt/pflink.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ @@ -8,11 +7,6 @@ int asprintf(char **, const char *, ...) printfesque(2) paramsnonnull((1, 2)) libcesque; int vasprintf(char **, const char *, va_list) paramsnonnull() libcesque; -#if defined(COSMO) && !defined(__cplusplus) -#define asprintf(SP, FMT, ...) (asprintf)(SP, PFLINK(FMT), ##__VA_ARGS__) -#define vasprintf(SP, FMT, VA) (vasprintf)(SP, PFLINK(FMT), VA) -#endif - COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_MEM_FMT_H_ */ diff --git a/libc/nexgen32e/cescapec.c b/libc/nexgen32e/cescapec.c deleted file mode 100644 index 4573ef18b..000000000 --- a/libc/nexgen32e/cescapec.c +++ /dev/null @@ -1,56 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2023 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/str/str.h" - -/** - * Converts byte to word-encoded C string literal representation. - */ -int _cescapec(int c) { - switch ((c &= 255)) { - case '\a': - return '\\' | 'a' << 8; - case '\b': - return '\\' | 'b' << 8; - case '\t': - return '\\' | 't' << 8; - case '\n': - return '\\' | 'n' << 8; - case '\v': - return '\\' | 'v' << 8; - case '\f': - return '\\' | 'f' << 8; - case '\r': - return '\\' | 'r' << 8; - case '"': - return '\\' | '"' << 8; - case '\'': - return '\\' | '\'' << 8; - case '\\': - return '\\' | '\\' << 8; - default: - if (' ' <= c && c <= '~') { - return c; - } else { - return '\\' | // - ('0' + (c >> 6)) << 8 | // - ('0' + ((c >> 3) & 7)) << 16 | // - ('0' + (c & 7)) << 24; - } - } -} diff --git a/libc/sock/syslog.c b/libc/sock/syslog.c index 84fd6cdf6..cfea998f3 100644 --- a/libc/sock/syslog.c +++ b/libc/sock/syslog.c @@ -19,7 +19,7 @@ #include "libc/sock/syslog.h" #include "libc/calls/blockcancel.internal.h" #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/struct/timespec.h" #include "libc/calls/weirdtypes.h" #include "libc/dce.h" diff --git a/libc/mem/asprintf.c b/libc/stdio/asprintf.c similarity index 100% rename from libc/mem/asprintf.c rename to libc/stdio/asprintf.c diff --git a/libc/calls/dprintf.c b/libc/stdio/dprintf.c similarity index 98% rename from libc/calls/dprintf.c rename to libc/stdio/dprintf.c index e5fb62544..9d4b32281 100644 --- a/libc/calls/dprintf.c +++ b/libc/stdio/dprintf.c @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" /** * Formats string directly to file descriptor. diff --git a/libc/calls/dprintf.h b/libc/stdio/dprintf.h similarity index 62% rename from libc/calls/dprintf.h rename to libc/stdio/dprintf.h index 29a87a350..0b2f7dde0 100644 --- a/libc/calls/dprintf.h +++ b/libc/stdio/dprintf.h @@ -1,17 +1,11 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_DPRINTF_H_ #define COSMOPOLITAN_LIBC_CALLS_DPRINTF_H_ -#include "libc/fmt/pflink.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ int dprintf(int, const char *, ...) printfesque(2) paramsnonnull((2)); int vdprintf(int, const char *, va_list) paramsnonnull(); -#if defined(COSMO) && !defined(__cplusplus) -#define dprintf(FD, FMT, ...) (dprintf)(FD, PFLINK(FMT), ##__VA_ARGS__) -#define vdprintf(FD, FMT, VA) (vdprintf)(FD, PFLINK(FMT), VA) -#endif /* GNU && !ANSI */ - COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_CALLS_DPRINTF_H_ */ diff --git a/libc/stdio/dtoa.c b/libc/stdio/dtoa.c deleted file mode 100644 index 140bbcc34..000000000 --- a/libc/stdio/dtoa.c +++ /dev/null @@ -1,567 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright (C) 1997, 1999, 2001 Lucent Technologies │ -│ All Rights Reserved │ -│ │ -│ Permission to use, copy, modify, and distribute this software and │ -│ its documentation for any purpose and without fee is hereby │ -│ granted, provided that the above copyright notice appear in all │ -│ copies and that both that the copyright notice and this │ -│ permission notice and warranty disclaimer appear in supporting │ -│ documentation, and that the name of Lucent or any of its entities │ -│ not be used in advertising or publicity pertaining to │ -│ distribution of the software without specific, written prior │ -│ permission. │ -│ │ -│ LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, │ -│ INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. │ -│ IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY │ -│ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES │ -│ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER │ -│ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, │ -│ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF │ -│ THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/assert.h" -#include "libc/fmt/fmt.h" -#include "libc/fmt/fmt.internal.h" -#include "libc/fmt/internal.h" -#include "libc/intrin/bsr.h" -#include "libc/macros.internal.h" -#include "libc/math.h" -#include "libc/str/str.h" -#include "third_party/gdtoa/gdtoa.h" - -/** - * @fileoverview Floating-Point Formatting - * - * This implements most of ANSI C's printf floating-point directives. - * omitting L, with %.0g and %.0G giving the shortest decimal string - * that rounds to the number being converted, and with negative - * precisions allowed for %f. - */ - -struct FPBits { - uint32_t bits[4]; - const FPI *fpi; - int sign; - int ex; // exponent - int kind; -}; - -union U { - double d; - uint64_t q; - long double ld; - uint32_t ui[4]; - uint16_t us[5]; -}; - -static const FPI kFpiDbl = { - .nbits = DBL_MANT_DIG, - .emin = 3 - DBL_MAX_EXP - DBL_MANT_DIG, - .emax = DBL_MAX_EXP - DBL_MANT_DIG, - .rounding = FPI_Round_near, - .sudden_underflow = 0, -}; - -static const FPI kFpiLdbl = { - .nbits = LDBL_MANT_DIG, - .emin = 3 - LDBL_MAX_EXP - LDBL_MANT_DIG, - .emax = LDBL_MAX_EXP - LDBL_MANT_DIG, - .rounding = FPI_Round_near, - .sudden_underflow = 0, -}; - -static const char kSpecialFloats[2][2][4] = { - {"INF", "inf"}, - {"NAN", "nan"}, -}; - -static void dfpbits(union U *u, struct FPBits *b) { - int ex, i; - b->fpi = &kFpiDbl; - b->sign = u->ui[1] & 0x80000000L; - b->bits[1] = u->ui[1] & 0xfffff; - b->bits[0] = u->ui[0]; - if ((ex = (u->ui[1] & 0x7ff00000L) >> 20) != 0) { - if (ex != 0x7ff) { - i = STRTOG_Normal; - b->bits[1] |= 1 << (52 - 32); // set lowest exponent bit - } else if (b->bits[0] | b->bits[1]) { - i = STRTOG_NaN; - } else { - i = STRTOG_Infinite; - } - } else if (b->bits[0] | b->bits[1]) { - i = STRTOG_Denormal; - ex = 1; - } else { - i = STRTOG_Zero; - } - b->kind = i; - b->ex = ex - (0x3ff + 52); -} - -static void ldfpbits(union U *u, struct FPBits *b) { -#if LDBL_MANT_DIG == 53 - dfpbits(u, b); -#else - int ex, i; - uint16_t sex; -#if LDBL_MANT_DIG == 64 - b->bits[3] = 0; - b->bits[2] = 0; - b->bits[1] = ((unsigned)u->us[3] << 16) | u->us[2]; - b->bits[0] = ((unsigned)u->us[1] << 16) | u->us[0]; - sex = u->us[4]; -#elif LDBL_MANT_DIG == 113 - b->bits[3] = u->ui[3] & 0xffff; - b->bits[2] = u->ui[2]; - b->bits[1] = u->ui[1]; - b->bits[0] = u->ui[0]; - sex = u->ui[3] >> 16; -#else -#error "unsupported architecture" -#endif - b->fpi = &kFpiLdbl; - b->sign = sex & 0x8000; - if ((ex = sex & 0x7fff) != 0) { - if (ex != 0x7fff) { - i = STRTOG_Normal; -#if LDBL_MANT_DIG == 113 - b->bits[3] |= 1 << (112 - 32 * 3); // set lowest exponent bit -#endif - } else if (b->bits[0] | b->bits[1] | b->bits[2] | b->bits[3]) { - i = STRTOG_NaN; - } else { - i = STRTOG_Infinite; - } - } else if (b->bits[0] | b->bits[1] | b->bits[2] | b->bits[3]) { - i = STRTOG_Denormal; - ex = 1; - } else { - i = STRTOG_Zero; - } - b->kind = i; - b->ex = ex - (0x3fff + (LDBL_MANT_DIG - 1)); -#endif -} - -// returns number of hex digits minus 1, or 0 for zero -static int fpiprec(struct FPBits *b) { - FPI *fpi; - int i, j, k, m; - uint32_t *bits; - if (b->kind == STRTOG_Zero) return (b->ex = 0); - fpi = b->fpi; - bits = b->bits; - for (k = (fpi->nbits - 1) >> 2; k > 0; --k) { - if ((bits[k >> 3] >> 4 * (k & 7)) & 0xf) { - m = k >> 3; - for (i = 0; i <= m; ++i) - if (bits[i]) { - if (i > 0) { - k -= 8 * i; - b->ex += 32 * i; - for (j = i; j <= m; ++j) { - bits[j - i] = bits[j]; - } - } - break; - } - for (i = 0; i < 28 && !((bits[0] >> i) & 0xf); i += 4) donothing; - if (i) { - b->ex += i; - m = k >> 3; - k -= (i >> 2); - for (j = 0;; ++j) { - bits[j] >>= i; - if (j == m) break; - bits[j] |= bits[j + 1] << (32 - i); - } - } - break; - } - } - return k; -} - -// round to prec hex digits after the "." -// prec1 = incoming precision (after ".") -static int bround(struct FPBits *b, int prec, int prec1) { - uint32_t *bits, t; - int i, inc, j, k, m, n; - m = prec1 - prec; - bits = b->bits; - inc = 0; - k = m - 1; - if ((t = bits[k >> 3] >> (j = (k & 7) * 4)) & 8) { - if (t & 7) goto inc1; - if (j && bits[k >> 3] << (32 - j)) goto inc1; - while (k >= 8) { - k -= 8; - if (bits[k >> 3]) { - inc1: - inc = 1; - goto haveinc; - } - } - } -haveinc: - b->ex += m * 4; - i = m >> 3; - k = prec1 >> 3; - j = i; - if ((n = 4 * (m & 7))) - for (;; ++j) { - bits[j - i] = bits[j] >> n; - if (j == k) break; - bits[j - i] |= bits[j + 1] << (32 - n); - } - else - for (;; ++j) { - bits[j - i] = bits[j]; - if (j == k) break; - } - k = prec >> 3; - if (inc) { - for (j = 0; !(++bits[j] & 0xffffffff); ++j) donothing; - if (j > k) { - onebit: - bits[0] = 1; - b->ex += 4 * prec; - return 1; - } - if ((j = prec & 7) < 7 && bits[k] >> (j + 1) * 4) goto onebit; - } - for (i = 0; !(bits[i >> 3] & (0xf << 4 * (i & 7))); ++i) donothing; - if (i) { - b->ex += 4 * i; - prec -= i; - j = i >> 3; - i &= 7; - i *= 4; - for (m = j;; ++m) { - bits[m - j] = bits[m] >> i; - if (m == k) break; - bits[m - j] |= bits[m + 1] << (32 - i); - } - } - return prec; -} - -int __fmt_dtoa(int (*out)(const char *, void *, size_t), void *arg, int d, - int flags, int prec, int sign, int width, bool longdouble, - char qchar, unsigned char signbit, const char *alphabet, - va_list va) { - double x; - union U u; - struct FPBits fpb; - char *s, *q, *se, *s0, special[8]; - int c, k, i1, ui, bw, rc, bex, sgn, prec1, decpt, consumed; - x = 0; - switch (d) { - case 'F': - case 'f': - if (!(flags & FLAGS_PRECISION)) prec = 6; - if (!longdouble) { - x = va_arg(va, double); - consumed = __FMT_CONSUMED_DOUBLE; - s = s0 = dtoa(x, 3, prec, &decpt, &fpb.sign, &se); - if (decpt == 9999) { - if (s && s[0] == 'N') { - fpb.kind = STRTOG_NaN; - } else { - fpb.kind = STRTOG_Infinite; - } - } - } else { - u.ld = va_arg(va, long double); - consumed = __FMT_CONSUMED_LONG_DOUBLE; - ldfpbits(&u, &fpb); - s = s0 = - gdtoa(fpb.fpi, fpb.ex, fpb.bits, &fpb.kind, 3, prec, &decpt, &se); - } - if (decpt == 9999) { - Format9999: - if (s0) freedtoa(s0); - bzero(special, sizeof(special)); - s = q = special; - if (fpb.sign) { - *q++ = '-'; - } else if (flags & FLAGS_PLUS) { - *q++ = '+'; - } else if (flags & FLAGS_SPACE) { - *q++ = ' '; - } - memcpy(q, kSpecialFloats[fpb.kind == STRTOG_NaN][d >= 'a'], 4); - flags &= ~(FLAGS_PRECISION | FLAGS_PLUS | FLAGS_HASH | FLAGS_SPACE); - prec = 0; - rc = __fmt_stoa(out, arg, s, flags, prec, width, signbit, qchar); - if (rc == -1) return -1; - return consumed; - } - FormatReal: - if (fpb.sign /* && (x || sign) */) sign = '-'; - if (prec > 0) width -= prec; - if (width > 0) { - if (sign) --width; - if (decpt <= 0) { - --width; - if (prec > 0) --width; - } else { - if (s == se) decpt = 1; - width -= decpt; - if (prec > 0 || (flags & FLAGS_HASH)) --width; - } - } - if (width > 0 && !(flags & FLAGS_LEFT)) { - if ((flags & FLAGS_ZEROPAD)) { - if (sign) __FMT_PUT(sign); - sign = 0; - do __FMT_PUT('0'); - while (--width > 0); - } else - do __FMT_PUT(' '); - while (--width > 0); - } - if (sign) __FMT_PUT(sign); - if (decpt <= 0) { - __FMT_PUT('0'); - if (prec > 0 || (flags & FLAGS_HASH)) __FMT_PUT('.'); - while (decpt < 0) { - __FMT_PUT('0'); - prec--; - decpt++; - } - } else { - do { - if ((c = *s)) { - s++; - } else { - c = '0'; - } - __FMT_PUT(c); - } while (--decpt > 0); - if (prec > 0 || (flags & FLAGS_HASH)) __FMT_PUT('.'); - } - while (--prec >= 0) { - if ((c = *s)) { - s++; - } else { - c = '0'; - } - __FMT_PUT(c); - } - while (--width >= 0) __FMT_PUT(' '); - if (s0) freedtoa(s0); - break; - - case 'G': - case 'g': - if (!(flags & FLAGS_PRECISION)) prec = 6; - if (prec < 1) prec = 1; - if (!longdouble) { - x = va_arg(va, double); - consumed = __FMT_CONSUMED_DOUBLE; - s = s0 = dtoa(x, 2, prec, &decpt, &fpb.sign, &se); - if (decpt == 9999) { - if (s && s[0] == 'N') { - fpb.kind = STRTOG_NaN; - } else { - fpb.kind = STRTOG_Infinite; - } - } - } else { - u.ld = va_arg(va, long double); - consumed = __FMT_CONSUMED_LONG_DOUBLE; - ldfpbits(&u, &fpb); - s = s0 = gdtoa(fpb.fpi, fpb.ex, fpb.bits, &fpb.kind, prec ? 2 : 0, prec, - &decpt, &se); - } - if (decpt == 9999) goto Format9999; - c = se - s; - prec1 = prec; - if (!prec) { - prec = c; - prec1 = c + (s[1] || (flags & FLAGS_HASH) ? 5 : 4); - // %.0g gives 10 rather than 1e1 - } - if (decpt > -4 && decpt <= prec1) { - if ((flags & FLAGS_HASH)) - prec -= decpt; - else - prec = c - decpt; - if (prec < 0) prec = 0; - goto FormatReal; - } - d -= 2; - if (!(flags & FLAGS_HASH) && prec > c) prec = c; - --prec; - goto FormatExpo; - - case 'e': - case 'E': - if (!(flags & FLAGS_PRECISION)) prec = 6; - if (prec < 0) prec = 0; - if (!longdouble) { - x = va_arg(va, double); - consumed = __FMT_CONSUMED_DOUBLE; - s = s0 = dtoa(x, 2, prec + 1, &decpt, &fpb.sign, &se); - if (decpt == 9999) { - if (s && s[0] == 'N') { - fpb.kind = STRTOG_NaN; - } else { - fpb.kind = STRTOG_Infinite; - } - } - } else { - u.ld = va_arg(va, long double); - consumed = __FMT_CONSUMED_LONG_DOUBLE; - ldfpbits(&u, &fpb); - s = s0 = gdtoa(fpb.fpi, fpb.ex, fpb.bits, &fpb.kind, prec ? 2 : 0, prec, - &decpt, &se); - } - if (decpt == 9999) goto Format9999; - FormatExpo: - if (fpb.sign /* && (x || sign) */) sign = '-'; - if ((width -= prec + 5) > 0) { - if (sign) --width; - if (prec || (flags & FLAGS_HASH)) --width; - } - if ((c = --decpt) < 0) c = -c; - while (c >= 100) { - --width; - c /= 10; - } - if (width > 0 && !(flags & FLAGS_LEFT)) { - if ((flags & FLAGS_ZEROPAD)) { - if (sign) __FMT_PUT(sign); - sign = 0; - do __FMT_PUT('0'); - while (--width > 0); - } else - do __FMT_PUT(' '); - while (--width > 0); - } - if (sign) __FMT_PUT(sign); - __FMT_PUT(*s++); - if (prec || (flags & FLAGS_HASH)) __FMT_PUT('.'); - while (--prec >= 0) { - if ((c = *s)) - s++; - else - c = '0'; - __FMT_PUT(c); - } - __FMT_PUT(d); - if (decpt < 0) { - __FMT_PUT('-'); - decpt = -decpt; - } else - __FMT_PUT('+'); - for (c = 2, k = 10; 10 * k <= decpt; c++, k *= 10) donothing; - for (;;) { - i1 = decpt / k; - __FMT_PUT(i1 + '0'); - if (--c <= 0) break; - decpt -= i1 * k; - decpt *= 10; - } - while (--width >= 0) __FMT_PUT(' '); - freedtoa(s0); - break; - - case 'A': - alphabet = "0123456789ABCDEFPX"; - goto FormatBinary; - case 'a': - alphabet = "0123456789abcdefpx"; - FormatBinary: - if (longdouble) { - u.ld = va_arg(va, long double); - consumed = __FMT_CONSUMED_LONG_DOUBLE; - ldfpbits(&u, &fpb); - } else { - u.d = va_arg(va, double); - consumed = __FMT_CONSUMED_DOUBLE; - dfpbits(&u, &fpb); - } - if (fpb.kind == STRTOG_Infinite || fpb.kind == STRTOG_NaN) { - s0 = 0; - goto Format9999; - } - prec1 = fpiprec(&fpb); - if ((flags & FLAGS_PRECISION) && prec < prec1) { - prec1 = bround(&fpb, prec, prec1); - } - bw = 1; - bex = fpb.ex + 4 * prec1; - if (bex) { - if ((i1 = bex) < 0) i1 = -i1; - while (i1 >= 10) { - ++bw; - i1 /= 10; - } - } - if (fpb.sign /* && (sign || fpb.kind != STRTOG_Zero) */) { - sign = '-'; - } - if ((width -= bw + 5) > 0) { - if (sign) --width; - if (prec1 || (flags & FLAGS_HASH)) --width; - } - if ((width -= prec1) > 0 && !(flags & FLAGS_LEFT) && - !(flags & FLAGS_ZEROPAD)) { - do __FMT_PUT(' '); - while (--width > 0); - } - if (sign) __FMT_PUT(sign); - __FMT_PUT('0'); - __FMT_PUT(alphabet[17]); - if ((flags & FLAGS_ZEROPAD) && width > 0 && !(flags & FLAGS_LEFT)) { - do __FMT_PUT('0'); - while (--width > 0); - } - i1 = prec1 & 7; - k = prec1 >> 3; - __FMT_PUT(alphabet[(fpb.bits[k] >> 4 * i1) & 0xf]); - if (prec1 > 0 || (flags & FLAGS_HASH)) __FMT_PUT('.'); - if (prec1 > 0) { - prec -= prec1; - while (prec1 > 0) { - if (--i1 < 0) { - if (--k < 0) break; - i1 = 7; - } - __FMT_PUT(alphabet[(fpb.bits[k] >> 4 * i1) & 0xf]); - --prec1; - } - if ((flags & FLAGS_HASH) && prec > 0) { - do __FMT_PUT(0); - while (--prec > 0); - } - } - __FMT_PUT(alphabet[16]); - if (bex < 0) { - __FMT_PUT('-'); - bex = -bex; - } else - __FMT_PUT('+'); - for (c = 1; 10 * c <= bex; c *= 10) donothing; - for (;;) { - i1 = bex / c; - __FMT_PUT('0' + i1); - if (!--bw) break; - bex -= i1 * c; - bex *= 10; - } - while (--width >= 0) __FMT_PUT(' '); - break; - default: - __builtin_unreachable(); - } - return consumed; -} diff --git a/libc/stdio/fmt.c b/libc/stdio/fmt.c new file mode 100644 index 000000000..7fa2cbb10 --- /dev/null +++ b/libc/stdio/fmt.c @@ -0,0 +1,1375 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +│ │ +│ Copyright (C) 1997, 1999, 2001 Lucent Technologies │ +│ All Rights Reserved │ +│ │ +│ Permission to use, copy, modify, and distribute this software and │ +│ its documentation for any purpose and without fee is hereby │ +│ granted, provided that the above copyright notice appear in all │ +│ copies and that both that the copyright notice and this │ +│ permission notice and warranty disclaimer appear in supporting │ +│ documentation, and that the name of Lucent or any of its entities │ +│ not be used in advertising or publicity pertaining to │ +│ distribution of the software without specific, written prior │ +│ permission. │ +│ │ +│ LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, │ +│ INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. │ +│ IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY │ +│ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES │ +│ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER │ +│ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, │ +│ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF │ +│ THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/fmt.h" +#include "libc/assert.h" +#include "libc/errno.h" +#include "libc/fmt/conv.h" +#include "libc/fmt/divmod10.internal.h" +#include "libc/fmt/itoa.h" +#include "libc/intrin/bits.h" +#include "libc/intrin/bsr.h" +#include "libc/intrin/nomultics.internal.h" +#include "libc/intrin/safemacros.internal.h" +#include "libc/intrin/tpenc.h" +#include "libc/limits.h" +#include "libc/macros.internal.h" +#include "libc/math.h" +#include "libc/mem/mem.h" +#include "libc/mem/reverse.internal.h" +#include "libc/runtime/internal.h" +#include "libc/str/str.h" +#include "libc/str/strwidth.h" +#include "libc/str/tab.internal.h" +#include "libc/str/thompike.h" +#include "libc/str/unicode.h" +#include "libc/str/utf16.h" +#include "libc/sysv/errfuns.h" +#include "third_party/gdtoa/gdtoa.h" + +#define BUFFER_SIZE 144 + +#define PRINTF_NTOA_BUFFER_SIZE 144 + +#define __FMT_CONSUMED_DOUBLE 1 +#define __FMT_CONSUMED_LONG_DOUBLE 2 + +#define FLAGS_ZEROPAD 0x01 +#define FLAGS_LEFT 0x02 +#define FLAGS_PLUS 0x04 +#define FLAGS_SPACE 0x08 +#define FLAGS_HASH 0x10 +#define FLAGS_PRECISION 0x20 +#define FLAGS_ISSIGNED 0x40 +#define FLAGS_NOQUOTE 0x80 +#define FLAGS_QUOTE FLAGS_SPACE +#define FLAGS_GROUPING FLAGS_NOQUOTE +#define FLAGS_REPR FLAGS_PLUS + +#define __FMT_PUT(C) \ + do { \ + char Buf[1] = {C}; \ + if (out(Buf, arg, 1) == -1) { \ + return -1; \ + } \ + } while (0) + +struct FPBits { + uint32_t bits[4]; + const FPI *fpi; + int sign; + int ex; // exponent + int kind; +}; + +union U { + double d; + uint64_t q; + long double ld; + uint32_t ui[4]; + uint16_t us[5]; +}; + +static const FPI kFpiDbl = { + .nbits = DBL_MANT_DIG, + .emin = 3 - DBL_MAX_EXP - DBL_MANT_DIG, + .emax = DBL_MAX_EXP - DBL_MANT_DIG, + .rounding = FPI_Round_near, + .sudden_underflow = 0, +}; + +static const FPI kFpiLdbl = { + .nbits = LDBL_MANT_DIG, + .emin = 3 - LDBL_MAX_EXP - LDBL_MANT_DIG, + .emax = LDBL_MAX_EXP - LDBL_MANT_DIG, + .rounding = FPI_Round_near, + .sudden_underflow = 0, +}; + +static const char kSpecialFloats[2][2][4] = { + {"INF", "inf"}, + {"NAN", "nan"}, +}; + +typedef int (*out_f)(const char *, void *, size_t); +typedef int (*emit_f)(out_f, void *, uint64_t); + +uint128_t __udivmodti4(uint128_t, uint128_t, uint128_t *); + +static int __fmt_atoi(const char **str) { + int i; + for (i = 0; '0' <= **str && **str <= '9'; ++*str) { + i *= 10; + i += **str - '0'; + } + return i; +} + +static int __fmt_pad(int out(const char *, void *, size_t), void *arg, + unsigned long n) { + int i, rc; + for (rc = i = 0; i < n; ++i) rc |= out(" ", arg, 1); + return rc; +} + +static int __fmt_ntoa_format(int out(const char *, void *, size_t), void *arg, + char *buf, unsigned len, bool negative, + unsigned log2base, unsigned prec, unsigned width, + unsigned char flags, const char *alphabet) { + unsigned i, prec_width_zeros; + char alternate_form_middle_char, sign_character; + unsigned actual_buf_len; + actual_buf_len = len; + prec_width_zeros = 0; + /* pad leading zeros */ + if (width && (flags & FLAGS_ZEROPAD) && + (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + if (len < prec) { + prec_width_zeros += (prec - len); + len = prec; + } + if ((flags & FLAGS_ZEROPAD) && (len < width)) { + prec_width_zeros += (width - len); + len = width; + } + /* handle hash */ + if (flags & FLAGS_HASH) { + if ((!(flags & FLAGS_PRECISION) || log2base == 3) && len && + ((len >= prec) || (len >= width)) && + (prec_width_zeros || buf[len - 1] == '0')) { + if (prec_width_zeros) { + --prec_width_zeros; + } + --len; + if (len < actual_buf_len) { + actual_buf_len = len; + } + if (len && (log2base == 4 || log2base == 1) && + (prec_width_zeros || buf[len - 1] == '0')) { + if (prec_width_zeros) { + --prec_width_zeros; + } + --len; + if (len < actual_buf_len) { + actual_buf_len = len; + } + } + } + alternate_form_middle_char = '\0'; + if ((log2base == 4 || log2base == 1)) { + ++len; + alternate_form_middle_char = + alphabet[17]; // x, X or b (for the corresponding conversion + // specifiers) + } + ++len; + } + sign_character = '\0'; + if (negative) { + ++len; + sign_character = '-'; + } else if (flags & FLAGS_PLUS) { + ++len; + sign_character = '+'; /* ignore the space if the '+' exists */ + } else if (flags & FLAGS_SPACE) { + ++len; + sign_character = ' '; + } + /* pad spaces up to given width */ + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + if (len < width) { + if (__fmt_pad(out, arg, width - len) == -1) return -1; + } + } + if (sign_character != '\0' && out(&sign_character, arg, 1) == -1) return -1; + if (flags & FLAGS_HASH) { + if (out("0", arg, 1) == -1) return -1; + if (alternate_form_middle_char != '\0' && + out(&alternate_form_middle_char, arg, 1) == -1) + return -1; + } + for (i = 0; i < prec_width_zeros; ++i) + if (out("0", arg, 1) == -1) return -1; + reverse(buf, actual_buf_len); + if (out(buf, arg, actual_buf_len) == -1) return -1; + /* append pad spaces up to given width */ + if (flags & FLAGS_LEFT) { + if (len < width) { + if (__fmt_pad(out, arg, width - len) == -1) return -1; + } + } + return 0; +} + +static int ntoa2(int out(const char *, void *, size_t), void *arg, + uint128_t value, bool neg, unsigned log2base, unsigned prec, + unsigned width, unsigned flags, const char *alphabet) { + uint128_t remainder; + unsigned len, count, digit; + char buf[BUFFER_SIZE]; + len = 0; + /* we check for log2base != 3 because otherwise we'll print nothing for a + * value of 0 with precision 0 when # mandates that one be printed */ + if (!value && log2base != 3) flags &= ~FLAGS_HASH; + if (value || !(flags & FLAGS_PRECISION)) { + count = 0; + do { + if (!log2base) { + if (value <= UINT64_MAX) { + value = DivMod10(value, &digit); + } else { + value = __udivmodti4(value, 10, &remainder); + digit = remainder; + } + } else { + digit = value; + digit &= (1u << log2base) - 1; + value >>= log2base; + } + if ((flags & FLAGS_GROUPING) && count == 3) { + buf[len++] = ','; + count = 1; + } else { + count++; + } + buf[len++] = alphabet[digit]; + } while (value); + _npassert(count <= BUFFER_SIZE); + } + return __fmt_ntoa_format(out, arg, buf, len, neg, log2base, prec, width, + flags, alphabet); +} + +static int __fmt_ntoa(int out(const char *, void *, size_t), void *arg, + uint128_t value, unsigned char signbit, + unsigned long log2base, unsigned long prec, + unsigned long width, unsigned char flags, + const char *lang) { + bool neg; + uint128_t sign; + + /* ignore '0' flag when prec or minus flag is given */ + if (flags & (FLAGS_PRECISION | FLAGS_LEFT)) { + flags &= ~FLAGS_ZEROPAD; + } + + /* no plus / space flag for u, x, X, o, b */ + if (!(flags & FLAGS_ISSIGNED)) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + neg = 0; + sign = 1; + sign <<= signbit; + value &= sign | (sign - 1); + if (flags & FLAGS_ISSIGNED) { + if (value != sign) { + if (value & sign) { + value = ~value + 1; + value &= sign | (sign - 1); + neg = 1; + } + value &= sign - 1; + } else { + neg = 1; + } + } + + return ntoa2(out, arg, value, neg, log2base, prec, width, flags, lang); +} + +/** + * Converts byte to word-encoded C string literal representation. + */ +static int __fmt_cescapec(int c) { + switch ((c &= 255)) { + case '\a': + return '\\' | 'a' << 8; + case '\b': + return '\\' | 'b' << 8; + case '\t': + return '\\' | 't' << 8; + case '\n': + return '\\' | 'n' << 8; + case '\v': + return '\\' | 'v' << 8; + case '\f': + return '\\' | 'f' << 8; + case '\r': + return '\\' | 'r' << 8; + case '"': + return '\\' | '"' << 8; + case '\'': + return '\\' | '\'' << 8; + case '\\': + return '\\' | '\\' << 8; + default: + if (' ' <= c && c <= '~') { + return c; + } else { + return '\\' | // + ('0' + (c >> 6)) << 8 | // + ('0' + ((c >> 3) & 7)) << 16 | // + ('0' + (c & 7)) << 24; + } + } +} + +static int __fmt_stoa_byte(out_f out, void *a, uint64_t c) { + char buf[1] = {c}; + return out(buf, a, 1); +} + +static int __fmt_stoa_wide(out_f out, void *a, uint64_t w) { + char buf[8]; + if (!isascii(w)) w = _tpenc(w); + WRITE64LE(buf, w); + return out(buf, a, w ? (_bsr(w) >> 3) + 1 : 1); +} + +static int __fmt_stoa_bing(out_f out, void *a, uint64_t w) { + char buf[8]; + w = _tpenc(kCp437[w & 0xFF]); + WRITE64LE(buf, w); + return out(buf, a, w ? (_bsr(w) >> 3) + 1 : 1); +} + +static int __fmt_stoa_quoted(out_f out, void *a, uint64_t w) { + char buf[8]; + if (isascii(w)) { + w = __fmt_cescapec(w); + } else { + w = _tpenc(w); + } + WRITE64LE(buf, w); + return out(buf, a, w ? (_bsr(w) >> 3) + 1 : 1); +} + +/** + * Converts string to array. + * + * This is used by __fmt() to implement the %s and %c directives. The + * content outputted to the array is always UTF-8, but the input may be + * UTF-16 or UTF-32. + * + * @see __fmt() + */ +static int __fmt_stoa(int out(const char *, void *, size_t), void *arg, + void *data, unsigned long flags, unsigned long precision, + unsigned long width, unsigned char signbit, + unsigned char qchar) { + wint_t wc; + unsigned n; + emit_f emit; + char *p, buf[1]; + unsigned w, c, pad; + bool justdobytes, ignorenul; + + p = data; + if (!p) { + p = ((flags & FLAGS_REPR) ? "NULL" : "(null)"); + signbit = 0; + flags |= FLAGS_NOQUOTE; + if (flags & FLAGS_PRECISION) { + precision = min(strlen(p), precision); + } + } + + ignorenul = false; + justdobytes = false; + if (signbit == 15 || signbit == 63) { + if (flags & FLAGS_QUOTE) { + emit = __fmt_stoa_quoted; + ignorenul = flags & FLAGS_PRECISION; + } else { + emit = __fmt_stoa_wide; + } + } else if ((flags & FLAGS_HASH) && kCp437) { + justdobytes = true; + emit = __fmt_stoa_bing; + ignorenul = flags & FLAGS_PRECISION; + } else if (flags & FLAGS_QUOTE) { + emit = __fmt_stoa_quoted; + ignorenul = flags & FLAGS_PRECISION; + } else { + justdobytes = true; + emit = __fmt_stoa_byte; + } + + if (!(flags & FLAGS_PRECISION)) precision = -1; + if (!(flags & FLAGS_PRECISION) || !ignorenul) { + if (signbit == 63) { + precision = wcsnlen((const wchar_t *)p, precision); + } else if (signbit == 15) { + precision = strnlen16((const char16_t *)p, precision); + } else { + precision = strnlen(p, precision); + } + } + + pad = 0; + if (width) { + w = precision; + if (signbit == 63) { + w = wcsnwidth((const wchar_t *)p, precision, 0); + } else if (signbit == 15) { + w = strnwidth16((const char16_t *)p, precision, 0); + } else { + w = strnwidth(p, precision, 0); + } + if (!(flags & FLAGS_NOQUOTE) && (flags & FLAGS_REPR)) { + w += 2 + (signbit == 63) + (signbit == 15); + } + if (w < width) { + pad = width - w; + } + } + + if (pad && !(flags & FLAGS_LEFT)) { + if (__fmt_pad(out, arg, pad) == -1) return -1; + } + + if (!(flags & FLAGS_NOQUOTE) && (flags & FLAGS_REPR)) { + if (signbit == 63) { + if (out("L", arg, 1) == -1) return -1; + } else if (signbit == 15) { + if (out("u", arg, 1) == -1) return -1; + } + buf[0] = qchar; + if (out(buf, arg, 1) == -1) return -1; + } + + if (justdobytes) { + while (precision--) { + wc = *p++ & 0xff; + if (!wc && !ignorenul) break; + if (emit(out, arg, wc) == -1) return -1; + } + } else { + while (precision--) { + if (signbit == 15) { + wc = *(const char16_t *)p; + if (!wc && !ignorenul) break; + if (IsUcs2(wc)) { + p += sizeof(char16_t); + } else if (IsUtf16Cont(wc)) { + p += sizeof(char16_t); + continue; + } else if (!precision) { + break; + } else { + --precision; + wc = MergeUtf16(wc, *(const char16_t *)p); + } + } else if (signbit == 63) { + wc = *(const wint_t *)p; + if (!wc && !ignorenul) break; + p += sizeof(wint_t); + if (!wc) break; + } else { + wc = *p++ & 0xff; + if (!wc && !ignorenul) break; + if (!isascii(wc)) { + if (ThomPikeCont(wc)) continue; + n = ThomPikeLen(wc) - 1; + wc = ThomPikeByte(wc); + if (n > precision) break; + precision -= n; + while (n--) { + wc = ThomPikeMerge(wc, *p++); + } + } + } + if (emit(out, arg, wc) == -1) return -1; + } + } + + if (!(flags & FLAGS_NOQUOTE) && (flags & FLAGS_REPR)) { + buf[0] = qchar; + if (out(buf, arg, 1) == -1) return -1; + } + + if (pad && (flags & FLAGS_LEFT)) { + if (__fmt_pad(out, arg, pad) == -1) return -1; + } + + return 0; +} + +static void __fmt_dfpbits(union U *u, struct FPBits *b) { + int ex, i; + b->fpi = &kFpiDbl; + b->sign = u->ui[1] & 0x80000000L; + b->bits[1] = u->ui[1] & 0xfffff; + b->bits[0] = u->ui[0]; + if ((ex = (u->ui[1] & 0x7ff00000L) >> 20) != 0) { + if (ex != 0x7ff) { + i = STRTOG_Normal; + b->bits[1] |= 1 << (52 - 32); // set lowest exponent bit + } else if (b->bits[0] | b->bits[1]) { + i = STRTOG_NaN; + } else { + i = STRTOG_Infinite; + } + } else if (b->bits[0] | b->bits[1]) { + i = STRTOG_Denormal; + ex = 1; + } else { + i = STRTOG_Zero; + } + b->kind = i; + b->ex = ex - (0x3ff + 52); +} + +static void __fmt_ldfpbits(union U *u, struct FPBits *b) { +#if LDBL_MANT_DIG == 53 + __fmt_dfpbits(u, b); +#else + int ex, i; + uint16_t sex; +#if LDBL_MANT_DIG == 64 + b->bits[3] = 0; + b->bits[2] = 0; + b->bits[1] = ((unsigned)u->us[3] << 16) | u->us[2]; + b->bits[0] = ((unsigned)u->us[1] << 16) | u->us[0]; + sex = u->us[4]; +#elif LDBL_MANT_DIG == 113 + b->bits[3] = u->ui[3] & 0xffff; + b->bits[2] = u->ui[2]; + b->bits[1] = u->ui[1]; + b->bits[0] = u->ui[0]; + sex = u->ui[3] >> 16; +#else +#error "unsupported architecture" +#endif + b->fpi = &kFpiLdbl; + b->sign = sex & 0x8000; + if ((ex = sex & 0x7fff) != 0) { + if (ex != 0x7fff) { + i = STRTOG_Normal; +#if LDBL_MANT_DIG == 113 + b->bits[3] |= 1 << (112 - 32 * 3); // set lowest exponent bit +#endif + } else if (b->bits[0] | b->bits[1] | b->bits[2] | b->bits[3]) { + i = STRTOG_NaN; + } else { + i = STRTOG_Infinite; + } + } else if (b->bits[0] | b->bits[1] | b->bits[2] | b->bits[3]) { + i = STRTOG_Denormal; + ex = 1; + } else { + i = STRTOG_Zero; + } + b->kind = i; + b->ex = ex - (0x3fff + (LDBL_MANT_DIG - 1)); +#endif +} + +// returns number of hex digits minus 1, or 0 for zero +static int __fmt_fpiprec(struct FPBits *b) { + FPI *fpi; + int i, j, k, m; + uint32_t *bits; + if (b->kind == STRTOG_Zero) return (b->ex = 0); + fpi = b->fpi; + bits = b->bits; + for (k = (fpi->nbits - 1) >> 2; k > 0; --k) { + if ((bits[k >> 3] >> 4 * (k & 7)) & 0xf) { + m = k >> 3; + for (i = 0; i <= m; ++i) + if (bits[i]) { + if (i > 0) { + k -= 8 * i; + b->ex += 32 * i; + for (j = i; j <= m; ++j) { + bits[j - i] = bits[j]; + } + } + break; + } + for (i = 0; i < 28 && !((bits[0] >> i) & 0xf); i += 4) donothing; + if (i) { + b->ex += i; + m = k >> 3; + k -= (i >> 2); + for (j = 0;; ++j) { + bits[j] >>= i; + if (j == m) break; + bits[j] |= bits[j + 1] << (32 - i); + } + } + break; + } + } + return k; +} + +// round to prec hex digits after the "." +// prec1 = incoming precision (after ".") +static int __fmt_bround(struct FPBits *b, int prec, int prec1) { + uint32_t *bits, t; + int i, inc, j, k, m, n; + m = prec1 - prec; + bits = b->bits; + inc = 0; + k = m - 1; + if ((t = bits[k >> 3] >> (j = (k & 7) * 4)) & 8) { + if (t & 7) goto inc1; + if (j && bits[k >> 3] << (32 - j)) goto inc1; + while (k >= 8) { + k -= 8; + if (bits[k >> 3]) { + inc1: + inc = 1; + goto haveinc; + } + } + } +haveinc: + b->ex += m * 4; + i = m >> 3; + k = prec1 >> 3; + j = i; + if ((n = 4 * (m & 7))) + for (;; ++j) { + bits[j - i] = bits[j] >> n; + if (j == k) break; + bits[j - i] |= bits[j + 1] << (32 - n); + } + else + for (;; ++j) { + bits[j - i] = bits[j]; + if (j == k) break; + } + k = prec >> 3; + if (inc) { + for (j = 0; !(++bits[j] & 0xffffffff); ++j) donothing; + if (j > k) { + onebit: + bits[0] = 1; + b->ex += 4 * prec; + return 1; + } + if ((j = prec & 7) < 7 && bits[k] >> (j + 1) * 4) goto onebit; + } + for (i = 0; !(bits[i >> 3] & (0xf << 4 * (i & 7))); ++i) donothing; + if (i) { + b->ex += 4 * i; + prec -= i; + j = i >> 3; + i &= 7; + i *= 4; + for (m = j;; ++m) { + bits[m - j] = bits[m] >> i; + if (m == k) break; + bits[m - j] |= bits[m + 1] << (32 - i); + } + } + return prec; +} + +/** + * Implements {,v}{,s{,n},{,{,x}as},f,d}printf domain-specific language. + * + * Type Specifiers + * + * - `%s` char * (thompson-pike unicode) + * - `%ls` wchar_t * (32-bit unicode → thompson-pike unicode) + * - `%hs` char16_t * (16-bit unicode → thompson-pike unicode) + * - `%b` int (radix 2 binary) + * - `%o` int (radix 8 octal) + * - `%d` int (radix 10 decimal) + * - `%x` int (radix 16 hexadecimal) + * - `%X` int (radix 16 hexadecimal uppercase) + * - `%p` pointer (48-bit hexadecimal) + * - `%u` unsigned + * - `%g` double (smart formatting) + * - `%e` double (expo formatting) + * - `%f` double (ugly formatting) + * - `%a` double (hex formatting) + * - `%Lg` long double + * + * Size Modifiers + * + * - `%hhd` char (8-bit) + * - `%hd` short (16-bit) + * - `%ld` long (64-bit) + * - `%lu` unsigned long (64-bit) + * - `%lx` unsigned long (64-bit hexadecimal) + * - `%jd` intmax_t (64-bit) + * - `%jjd` int128_t (128-bit) + * + * Width Modifiers + * + * - `%08d` fixed columns w/ zero leftpadding + * - `%8d` fixed columns w/ space leftpadding + * - `%*s` variable column string (thompson-pike) + * + * Precision Modifiers + * + * - `%.8s` supplied byte length (obeys nul terminator) + * - `%.*s` supplied byte length argument (obeys nul terminator) + * - ``%`.*s`` supplied byte length argument c escaped (ignores nul term) + * - `%#.*s` supplied byte length argument visualized (ignores nul term) + * - `%.*hs` supplied char16_t length argument (obeys nul terminator) + * - `%.*ls` supplied wchar_t length argument (obeys nul terminator) + * + * Formatting Modifiers + * + * - `%,d` thousands separators + * - `%'s` escaped c string literal + * - ``%`c`` c escaped character + * - ``%`'c`` c escaped character quoted + * - ``%`s`` c escaped string + * - ``%`'s`` c escaped string quoted + * - ``%`s`` escaped double quoted c string literal + * - ``%`c`` escaped double quoted c character literal + * - `%+d` plus leftpad if positive (aligns w/ negatives) + * - `% d` space leftpad if positive (aligns w/ negatives) + * - `%#s` datum (radix 256 null-terminated ibm cp437) + * - `%#x` int (radix 16 hexadecimal w/ 0x prefix if not zero) + * + * This implements most of ANSI C's printf floating-point directives, + * omitting L, with %.0g and %.0G giving the shortest decimal string + * that rounds to the number being converted, and with negative + * precisions allowed for %f. + * + * @note implementation detail of printf(), snprintf(), etc. + * @see printf() for wordier documentation + * @note netlib.org is so helpful + * @asyncsignalsafe if floating point isn't used + * @vforksafe if floating point isn't used + */ +_Hide int __fmt(void *fn, void *arg, const char *format, va_list va) { + long ld; + void *p; + double x; + unsigned u; + union U un; + char ibuf[21]; + bool longdouble; + unsigned long lu; + struct FPBits fpb; + wchar_t charbuf[1]; + const char *alphabet; + unsigned char signbit, log2base; + int (*out)(const char *, void *, size_t); + char *se, *s0, *s, *q, qchar, special[8]; + int d, w, n, sign, prec, flags, width, lasterr; + int c, k, i1, ui, bw, rc, bex, sgn, prec1, decpt, consumed; + + x = 0; + lasterr = errno; + out = fn ? fn : (void *)_missingno; + + while (*format) { + if (*format != '%') { + for (n = 1; format[n]; ++n) { + if (format[n] == '%') break; + } + if (out(format, arg, n) == -1) return -1; + format += n; + continue; + } + + if (!IsTiny()) { + if (format[1] == 's') { // FAST PATH: PLAIN STRING + s = va_arg(va, char *); + if (!s) s = "(null)"; + if (out(s, arg, strlen(s)) == -1) return -1; + format += 2; + continue; + } else if (format[1] == 'd') { // FAST PATH: PLAIN INTEGER + d = va_arg(va, int); + if (out(ibuf, arg, FormatInt32(ibuf, d) - ibuf) == -1) return -1; + format += 2; + continue; + } else if (format[1] == 'u') { // FAST PATH: PLAIN UNSIGNED + u = va_arg(va, unsigned); + if (out(ibuf, arg, FormatUint32(ibuf, u) - ibuf) == -1) return -1; + format += 2; + continue; + } else if (format[1] == 'x') { // FAST PATH: PLAIN HEX + u = va_arg(va, unsigned); + if (out(ibuf, arg, uint64toarray_radix16(u, ibuf)) == -1) return -1; + format += 2; + continue; + } else if (format[1] == 'l' && format[2] == 'x') { + lu = va_arg(va, unsigned long); // FAST PATH: PLAIN LONG HEX + if (out(ibuf, arg, uint64toarray_radix16(lu, ibuf)) == -1) return -1; + format += 3; + continue; + } else if (format[1] == 'l' && format[2] == 'd') { + ld = va_arg(va, long); // FAST PATH: PLAIN LONG + if (out(ibuf, arg, FormatInt64(ibuf, ld) - ibuf) == -1) return -1; + format += 3; + continue; + } else if (format[1] == 'l' && format[2] == 'u') { + lu = va_arg(va, unsigned long); // FAST PATH: PLAIN UNSIGNED LONG + if (out(ibuf, arg, FormatUint64(ibuf, lu) - ibuf) == -1) return -1; + format += 3; + continue; + } else if (format[1] == '.' && format[2] == '*' && format[3] == 's') { + n = va_arg(va, unsigned); // FAST PATH: PRECISION STRING + s = va_arg(va, const char *); + if (s) { + n = strnlen(s, n); + } else { + s = "(null)"; + n = MIN(6, n); + } + if (out(s, arg, n) == -1) return -1; + format += 4; + continue; + } + } + + // GENERAL PATH + format++; + sign = 0; + flags = 0; + getflag: + switch (*format++) { + case '0': + flags |= FLAGS_ZEROPAD; + goto getflag; + case '-': + flags |= FLAGS_LEFT; + goto getflag; + case '+': + sign = '+'; + flags |= FLAGS_PLUS; + goto getflag; + case ' ': + sign = ' '; + flags |= FLAGS_SPACE; + goto getflag; + case '#': + flags |= FLAGS_HASH; + goto getflag; + case ',': + flags |= FLAGS_GROUPING; + goto getflag; + case '`': + flags |= FLAGS_REPR; + // fallthrough + case '\'': + flags |= FLAGS_QUOTE; + goto getflag; + default: + format--; + break; + } + + // evaluate width field + width = 0; + if (isdigit(*format)) { + width = __fmt_atoi(&format); + } else if (*format == '*') { + w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = -w; + sign = '-'; + } else { + width = w; + } + format++; + } + + // evaluate prec field + prec = 0; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (isdigit(*format)) { + prec = __fmt_atoi(&format); + } else if (*format == '*') { + prec = va_arg(va, int); + format++; + } + } + if (prec < 0) { + prec = 0; + flags &= ~FLAGS_PRECISION; + } + + // evaluate length field + signbit = 31; + longdouble = false; + switch (*format) { + case 'j': // intmax_t + format++; + signbit = sizeof(intmax_t) * 8 - 1; + if (*format == 'j') { + format++; + signbit = sizeof(int128_t) * 8 - 1; + } + break; + case 'l': + if (format[1] == 'f' || format[1] == 'F') { + format++; + break; + } + if (format[1] == 'l') format++; + // fallthrough + case 't': // ptrdiff_t + case 'z': // size_t + case 'Z': // size_t + format++; + signbit = 63; + break; + case 'L': // long double + format++; +#if !(LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024) + longdouble = true; +#endif + break; + case 'h': + format++; + if (*format == 'h') { + format++; + signbit = 7; + } else { + signbit = 15; + } + break; + default: + break; + } + + // evaluate specifier + qchar = '"'; + log2base = 0; + alphabet = "0123456789abcdefpx"; + switch ((d = *format++)) { + case 'p': + flags |= FLAGS_HASH; + log2base = 4; + signbit = 63; + goto FormatNumber; + case 'X': + alphabet = "0123456789ABCDEFPX"; + // fallthrough + case 'x': + log2base = 4; + goto FormatNumber; + case 'b': + log2base = 1; + alphabet = "0123456789abcdefpb"; + goto FormatNumber; + case 'o': + log2base = 3; + goto FormatNumber; + case 'd': + case 'i': + flags |= FLAGS_ISSIGNED; + // fallthrough + case 'u': { + uint128_t value; + flags &= ~FLAGS_HASH; // no hash for dec format + FormatNumber: + if (signbit > 63) { + value = va_arg(va, uint128_t); + } else { + value = va_arg(va, uint64_t); + } + if (__fmt_ntoa(out, arg, value, signbit, log2base, prec, width, flags, + alphabet) == -1) { + return -1; + } + break; + } + case 'c': + if ((charbuf[0] = va_arg(va, int))) { + p = charbuf; + qchar = '\''; + flags |= FLAGS_PRECISION; + prec = 1; + goto FormatString; + } else { + __FMT_PUT('\0'); + break; + } + case 'm': + p = strerror(lasterr); + signbit = 0; + goto FormatString; + case 'r': + // undocumented %r specifier + // used for good carriage return + // helps integrate loggers with repls + if (!__replstderr) { + break; + } else { + p = "\r\e[K"; + goto FormatString; + } + case 'S': + // Specified by POSIX to be equivalent to %ls + signbit = 63; + goto FormatStringPNotFetchedYet; + case 'q': + flags |= FLAGS_QUOTE; + // fallthrough + case 's': + FormatStringPNotFetchedYet: + p = va_arg(va, void *); + FormatString: + if (__fmt_stoa(out, arg, p, flags, prec, width, signbit, qchar) == -1) { + return -1; + } + break; + case 'n': + __FMT_PUT('\n'); + break; + + case 'F': + case 'f': + if (!(flags & FLAGS_PRECISION)) prec = 6; + if (!longdouble) { + x = va_arg(va, double); + consumed = __FMT_CONSUMED_DOUBLE; + s = s0 = dtoa(x, 3, prec, &decpt, &fpb.sign, &se); + if (decpt == 9999) { + if (s && s[0] == 'N') { + fpb.kind = STRTOG_NaN; + } else { + fpb.kind = STRTOG_Infinite; + } + } + } else { + un.ld = va_arg(va, long double); + consumed = __FMT_CONSUMED_LONG_DOUBLE; + __fmt_ldfpbits(&un, &fpb); + s = s0 = + gdtoa(fpb.fpi, fpb.ex, fpb.bits, &fpb.kind, 3, prec, &decpt, &se); + } + if (decpt == 9999) { + Format9999: + if (s0) freedtoa(s0); + bzero(special, sizeof(special)); + s = q = special; + if (fpb.sign) { + *q++ = '-'; + } else if (flags & FLAGS_PLUS) { + *q++ = '+'; + } else if (flags & FLAGS_SPACE) { + *q++ = ' '; + } + memcpy(q, kSpecialFloats[fpb.kind == STRTOG_NaN][d >= 'a'], 4); + flags &= ~(FLAGS_PRECISION | FLAGS_PLUS | FLAGS_HASH | FLAGS_SPACE); + prec = 0; + rc = __fmt_stoa(out, arg, s, flags, prec, width, signbit, qchar); + if (rc == -1) return -1; + return consumed; + } + FormatReal: + if (fpb.sign /* && (x || sign) */) sign = '-'; + if (prec > 0) width -= prec; + if (width > 0) { + if (sign) --width; + if (decpt <= 0) { + --width; + if (prec > 0) --width; + } else { + if (s == se) decpt = 1; + width -= decpt; + if (prec > 0 || (flags & FLAGS_HASH)) --width; + } + } + if (width > 0 && !(flags & FLAGS_LEFT)) { + if ((flags & FLAGS_ZEROPAD)) { + if (sign) __FMT_PUT(sign); + sign = 0; + do __FMT_PUT('0'); + while (--width > 0); + } else + do __FMT_PUT(' '); + while (--width > 0); + } + if (sign) __FMT_PUT(sign); + if (decpt <= 0) { + __FMT_PUT('0'); + if (prec > 0 || (flags & FLAGS_HASH)) __FMT_PUT('.'); + while (decpt < 0) { + __FMT_PUT('0'); + prec--; + decpt++; + } + } else { + do { + if ((c = *s)) { + s++; + } else { + c = '0'; + } + __FMT_PUT(c); + } while (--decpt > 0); + if (prec > 0 || (flags & FLAGS_HASH)) __FMT_PUT('.'); + } + while (--prec >= 0) { + if ((c = *s)) { + s++; + } else { + c = '0'; + } + __FMT_PUT(c); + } + while (--width >= 0) __FMT_PUT(' '); + if (s0) freedtoa(s0); + break; + + case 'G': + case 'g': + if (!(flags & FLAGS_PRECISION)) prec = 6; + if (prec < 1) prec = 1; + if (!longdouble) { + x = va_arg(va, double); + consumed = __FMT_CONSUMED_DOUBLE; + s = s0 = dtoa(x, 2, prec, &decpt, &fpb.sign, &se); + if (decpt == 9999) { + if (s && s[0] == 'N') { + fpb.kind = STRTOG_NaN; + } else { + fpb.kind = STRTOG_Infinite; + } + } + } else { + un.ld = va_arg(va, long double); + consumed = __FMT_CONSUMED_LONG_DOUBLE; + __fmt_ldfpbits(&un, &fpb); + s = s0 = gdtoa(fpb.fpi, fpb.ex, fpb.bits, &fpb.kind, prec ? 2 : 0, + prec, &decpt, &se); + } + if (decpt == 9999) goto Format9999; + c = se - s; + prec1 = prec; + if (!prec) { + prec = c; + prec1 = c + (s[1] || (flags & FLAGS_HASH) ? 5 : 4); + // %.0g gives 10 rather than 1e1 + } + if (decpt > -4 && decpt <= prec1) { + if ((flags & FLAGS_HASH)) + prec -= decpt; + else + prec = c - decpt; + if (prec < 0) prec = 0; + goto FormatReal; + } + d -= 2; + if (!(flags & FLAGS_HASH) && prec > c) prec = c; + --prec; + goto FormatExpo; + + case 'e': + case 'E': + if (!(flags & FLAGS_PRECISION)) prec = 6; + if (prec < 0) prec = 0; + if (!longdouble) { + x = va_arg(va, double); + consumed = __FMT_CONSUMED_DOUBLE; + s = s0 = dtoa(x, 2, prec + 1, &decpt, &fpb.sign, &se); + if (decpt == 9999) { + if (s && s[0] == 'N') { + fpb.kind = STRTOG_NaN; + } else { + fpb.kind = STRTOG_Infinite; + } + } + } else { + un.ld = va_arg(va, long double); + consumed = __FMT_CONSUMED_LONG_DOUBLE; + __fmt_ldfpbits(&un, &fpb); + s = s0 = gdtoa(fpb.fpi, fpb.ex, fpb.bits, &fpb.kind, prec ? 2 : 0, + prec, &decpt, &se); + } + if (decpt == 9999) goto Format9999; + FormatExpo: + if (fpb.sign /* && (x || sign) */) sign = '-'; + if ((width -= prec + 5) > 0) { + if (sign) --width; + if (prec || (flags & FLAGS_HASH)) --width; + } + if ((c = --decpt) < 0) c = -c; + while (c >= 100) { + --width; + c /= 10; + } + if (width > 0 && !(flags & FLAGS_LEFT)) { + if ((flags & FLAGS_ZEROPAD)) { + if (sign) __FMT_PUT(sign); + sign = 0; + do __FMT_PUT('0'); + while (--width > 0); + } else + do __FMT_PUT(' '); + while (--width > 0); + } + if (sign) __FMT_PUT(sign); + __FMT_PUT(*s++); + if (prec || (flags & FLAGS_HASH)) __FMT_PUT('.'); + while (--prec >= 0) { + if ((c = *s)) + s++; + else + c = '0'; + __FMT_PUT(c); + } + __FMT_PUT(d); + if (decpt < 0) { + __FMT_PUT('-'); + decpt = -decpt; + } else + __FMT_PUT('+'); + for (c = 2, k = 10; 10 * k <= decpt; c++, k *= 10) donothing; + for (;;) { + i1 = decpt / k; + __FMT_PUT(i1 + '0'); + if (--c <= 0) break; + decpt -= i1 * k; + decpt *= 10; + } + while (--width >= 0) __FMT_PUT(' '); + freedtoa(s0); + break; + + case 'A': + alphabet = "0123456789ABCDEFPX"; + goto FormatBinary; + case 'a': + alphabet = "0123456789abcdefpx"; + FormatBinary: + if (longdouble) { + un.ld = va_arg(va, long double); + consumed = __FMT_CONSUMED_LONG_DOUBLE; + __fmt_ldfpbits(&un, &fpb); + } else { + un.d = va_arg(va, double); + consumed = __FMT_CONSUMED_DOUBLE; + __fmt_dfpbits(&un, &fpb); + } + if (fpb.kind == STRTOG_Infinite || fpb.kind == STRTOG_NaN) { + s0 = 0; + goto Format9999; + } + prec1 = __fmt_fpiprec(&fpb); + if ((flags & FLAGS_PRECISION) && prec < prec1) { + prec1 = __fmt_bround(&fpb, prec, prec1); + } + bw = 1; + bex = fpb.ex + 4 * prec1; + if (bex) { + if ((i1 = bex) < 0) i1 = -i1; + while (i1 >= 10) { + ++bw; + i1 /= 10; + } + } + if (fpb.sign /* && (sign || fpb.kind != STRTOG_Zero) */) { + sign = '-'; + } + if ((width -= bw + 5) > 0) { + if (sign) --width; + if (prec1 || (flags & FLAGS_HASH)) --width; + } + if ((width -= prec1) > 0 && !(flags & FLAGS_LEFT) && + !(flags & FLAGS_ZEROPAD)) { + do __FMT_PUT(' '); + while (--width > 0); + } + if (sign) __FMT_PUT(sign); + __FMT_PUT('0'); + __FMT_PUT(alphabet[17]); + if ((flags & FLAGS_ZEROPAD) && width > 0 && !(flags & FLAGS_LEFT)) { + do __FMT_PUT('0'); + while (--width > 0); + } + i1 = prec1 & 7; + k = prec1 >> 3; + __FMT_PUT(alphabet[(fpb.bits[k] >> 4 * i1) & 0xf]); + if (prec1 > 0 || (flags & FLAGS_HASH)) __FMT_PUT('.'); + if (prec1 > 0) { + prec -= prec1; + while (prec1 > 0) { + if (--i1 < 0) { + if (--k < 0) break; + i1 = 7; + } + __FMT_PUT(alphabet[(fpb.bits[k] >> 4 * i1) & 0xf]); + --prec1; + } + if ((flags & FLAGS_HASH) && prec > 0) { + do __FMT_PUT(0); + while (--prec > 0); + } + } + __FMT_PUT(alphabet[16]); + if (bex < 0) { + __FMT_PUT('-'); + bex = -bex; + } else + __FMT_PUT('+'); + for (c = 1; 10 * c <= bex; c *= 10) donothing; + for (;;) { + i1 = bex / c; + __FMT_PUT('0' + i1); + if (!--bw) break; + bex -= i1 * c; + bex *= 10; + } + while (--width >= 0) __FMT_PUT(' '); + break; + + case '%': + __FMT_PUT('%'); + break; + default: + __FMT_PUT(format[-1]); + break; + } + } + + return 0; +} diff --git a/libc/fmt/snprintf.c b/libc/stdio/snprintf.c similarity index 100% rename from libc/fmt/snprintf.c rename to libc/stdio/snprintf.c diff --git a/libc/fmt/sprintf.c b/libc/stdio/sprintf.c similarity index 100% rename from libc/fmt/sprintf.c rename to libc/stdio/sprintf.c diff --git a/libc/fmt/sscanf.c b/libc/stdio/sscanf.c similarity index 100% rename from libc/fmt/sscanf.c rename to libc/stdio/sscanf.c diff --git a/libc/stdio/stdio.h b/libc/stdio/stdio.h index 2064caca9..ff6f19d94 100644 --- a/libc/stdio/stdio.h +++ b/libc/stdio/stdio.h @@ -1,6 +1,5 @@ #ifndef _STDIO_H #define _STDIO_H -#include "libc/fmt/pflink.h" #define L_ctermid 20 #define FILENAME_MAX PATH_MAX @@ -162,25 +161,6 @@ int fprintf_unlocked(FILE *, const char *, ...) printfesque(2) int vfprintf_unlocked(FILE *, const char *, va_list) paramsnonnull() dontthrow nocallback; -/*───────────────────────────────────────────────────────────────────────────│─╗ -│ cosmopolitan § standard i/o » optimizations ─╬─│┼ -╚────────────────────────────────────────────────────────────────────────────│*/ - -#if defined(COSMO) && !defined(__cplusplus) -/* clang-format off */ -#define printf(FMT, ...) (printf)(PFLINK(FMT), ##__VA_ARGS__) -#define vprintf(FMT, VA) (vprintf)(PFLINK(FMT), VA) -#define fprintf(F, FMT, ...) (fprintf)(F, PFLINK(FMT), ##__VA_ARGS__) -#define vfprintf(F, FMT, VA) (vfprintf)(F, PFLINK(FMT), VA) -#define fprintf_unlocked(F, FMT, ...) (fprintf_unlocked)(F, PFLINK(FMT), ##__VA_ARGS__) -#define vfprintf_unlocked(F, FMT, VA) (vfprintf_unlocked)(F, PFLINK(FMT), VA) -#define vscanf(FMT, VA) (vscanf)(SFLINK(FMT), VA) -#define scanf(FMT, ...) (scanf)(SFLINK(FMT), ##__VA_ARGS__) -#define fscanf(F, FMT, ...) (fscanf)(F, SFLINK(FMT), ##__VA_ARGS__) -#define vfscanf(F, FMT, VA) (vfscanf)(F, SFLINK(FMT), VA) -/* clang-format on */ -#endif - COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* _STDIO_H */ diff --git a/libc/fmt/swprintf.c b/libc/stdio/swprintf.c similarity index 100% rename from libc/fmt/swprintf.c rename to libc/stdio/swprintf.c diff --git a/libc/mem/vasprintf.c b/libc/stdio/vasprintf.c similarity index 100% rename from libc/mem/vasprintf.c rename to libc/stdio/vasprintf.c diff --git a/libc/fmt/vcscanf.c b/libc/stdio/vcscanf.c similarity index 100% rename from libc/fmt/vcscanf.c rename to libc/stdio/vcscanf.c diff --git a/libc/calls/vdprintf.c b/libc/stdio/vdprintf.c similarity index 100% rename from libc/calls/vdprintf.c rename to libc/stdio/vdprintf.c diff --git a/libc/fmt/vsnprintf.c b/libc/stdio/vsnprintf.c similarity index 100% rename from libc/fmt/vsnprintf.c rename to libc/stdio/vsnprintf.c diff --git a/libc/fmt/vsprintf.c b/libc/stdio/vsprintf.c similarity index 100% rename from libc/fmt/vsprintf.c rename to libc/stdio/vsprintf.c diff --git a/libc/fmt/vsscanf.c b/libc/stdio/vsscanf.c similarity index 100% rename from libc/fmt/vsscanf.c rename to libc/stdio/vsscanf.c diff --git a/libc/str/str.h b/libc/str/str.h index 4258f7f88..51d517a3e 100644 --- a/libc/str/str.h +++ b/libc/str/str.h @@ -26,7 +26,6 @@ int ispunct(int); int toupper(int); int toascii(int); int hextoint(int); -int _cescapec(int); int iswalnum(wint_t); int iswalpha(wint_t); diff --git a/libc/time/time.mk b/libc/time/time.mk index 40d46457b..e5c2021f9 100644 --- a/libc/time/time.mk +++ b/libc/time/time.mk @@ -29,13 +29,14 @@ LIBC_TIME_A_CHECKS = \ LIBC_TIME_A_DIRECTDEPS = \ LIBC_CALLS \ - LIBC_INTRIN \ LIBC_FMT \ + LIBC_INTRIN \ LIBC_MEM \ LIBC_NEXGEN32E \ LIBC_NT_KERNEL32 \ LIBC_NT_NTDLL \ LIBC_RUNTIME \ + LIBC_STDIO \ LIBC_STR \ LIBC_STUBS \ LIBC_SYSV \ diff --git a/libc/x/xasprintf.h b/libc/x/xasprintf.h index a689a39d3..a7d7db47b 100644 --- a/libc/x/xasprintf.h +++ b/libc/x/xasprintf.h @@ -1,6 +1,5 @@ #ifndef COSMOPOLITAN_LIBC_X_XASPRINTF_H_ #define COSMOPOLITAN_LIBC_X_XASPRINTF_H_ -#include "libc/fmt/pflink.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ @@ -9,11 +8,6 @@ char *xasprintf(const char *, ...) printfesque(1) paramsnonnull((1)) char *xvasprintf(const char *, va_list) paramsnonnull() returnspointerwithnoaliases dontthrow nocallback dontdiscard returnsnonnull; -#if defined(COSMO) && !defined(__cplusplus) -#define xasprintf(FMT, ...) (xasprintf)(PFLINK(FMT), ##__VA_ARGS__) -#define xvasprintf(FMT, VA) (xvasprintf)(PFLINK(FMT), VA) -#endif - COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_X_XASPRINTF_H_ */ diff --git a/net/finger/describesyn.c b/net/finger/describesyn.c index aa7670d88..2d0ac4195 100644 --- a/net/finger/describesyn.c +++ b/net/finger/describesyn.c @@ -16,8 +16,8 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/bits.h" #include "libc/fmt/itoa.h" +#include "libc/intrin/bits.h" #include "net/finger/finger.h" /** diff --git a/test/libc/calls/symlinkat_test.c b/test/libc/calls/symlinkat_test.c index 7d30ffd5b..8abf11981 100644 --- a/test/libc/calls/symlinkat_test.c +++ b/test/libc/calls/symlinkat_test.c @@ -21,8 +21,8 @@ #include "libc/errno.h" #include "libc/fmt/fmt.h" #include "libc/fmt/itoa.h" -#include "libc/stdio/rand.h" #include "libc/runtime/runtime.h" +#include "libc/stdio/rand.h" #include "libc/sysv/consts/at.h" #include "libc/sysv/consts/s.h" #include "libc/testlib/testlib.h" diff --git a/test/libc/fmt/printf_uppercase_e_static_yoink_test.c b/test/libc/fmt/printf_uppercase_e_static_yoink_test.c deleted file mode 100644 index 33b3cc95a..000000000 --- a/test/libc/fmt/printf_uppercase_e_static_yoink_test.c +++ /dev/null @@ -1,42 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2023 Gabriel Ravier │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ - -#include "libc/fmt/fmt.h" -#include "libc/intrin/kprintf.h" -#include "libc/runtime/runtime.h" -#include "libc/str/str.h" - -// We specifically avoid the test framework because otherwise __fmt_dtoa is -// always automatically pulled in from code in there - and this is what we're -// testing for here -int main() { - char buffer[30]; - - int snprintf_result = snprintf(buffer, sizeof(buffer), "%E", .0); - if (strcmp(buffer, "0.000000E+00")) { - kprintf( - "error: snprintf gave us '%s' instead of the expected '0.000000E+00'\n", - buffer); - abort(); - } - if (snprintf_result != 12) { - kprintf("error: snprintf returned %d instead of 12\n", snprintf_result); - abort(); - } -} diff --git a/test/libc/fmt/printf_uppercase_f_static_yoink_test.c b/test/libc/fmt/printf_uppercase_f_static_yoink_test.c deleted file mode 100644 index ebbb13d0c..000000000 --- a/test/libc/fmt/printf_uppercase_f_static_yoink_test.c +++ /dev/null @@ -1,41 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2023 Gabriel Ravier │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ - -#include "libc/fmt/fmt.h" -#include "libc/intrin/kprintf.h" -#include "libc/runtime/runtime.h" -#include "libc/str/str.h" - -// We specifically avoid the test framework because otherwise __fmt_dtoa is -// always automatically pulled in from code in there - and this is what we're -// testing for here -int main() { - char buffer[30]; - - int snprintf_result = snprintf(buffer, sizeof(buffer), "%F", .0); - if (strcmp(buffer, "0.000000")) { - kprintf("error: snprintf gave us '%s' instead of the expected '0.000000'\n", - buffer); - abort(); - } - if (snprintf_result != 8) { - kprintf("error: snprintf returned %d instead of 8\n", snprintf_result); - abort(); - } -} diff --git a/test/libc/fmt/printf_uppercase_g_static_yoink_test.c b/test/libc/fmt/printf_uppercase_g_static_yoink_test.c deleted file mode 100644 index c3270c3d8..000000000 --- a/test/libc/fmt/printf_uppercase_g_static_yoink_test.c +++ /dev/null @@ -1,41 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2023 Gabriel Ravier │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ - -#include "libc/fmt/fmt.h" -#include "libc/intrin/kprintf.h" -#include "libc/runtime/runtime.h" -#include "libc/str/str.h" - -// We specifically avoid the test framework because otherwise __fmt_dtoa is -// always automatically pulled in from code in there - and this is what we're -// testing for here -int main() { - char buffer[30]; - - int snprintf_result = snprintf(buffer, sizeof(buffer), "%G", .0); - if (strcmp(buffer, "0")) { - kprintf("error: snprintf gave us '%s' instead of the expected '0'\n", - buffer); - abort(); - } - if (snprintf_result != 1) { - kprintf("error: snprintf returned %d instead of 1\n", snprintf_result); - abort(); - } -} diff --git a/test/libc/nexgen32e/cescapec_test.c b/test/libc/nexgen32e/cescapec_test.c deleted file mode 100644 index 50e0fc725..000000000 --- a/test/libc/nexgen32e/cescapec_test.c +++ /dev/null @@ -1,286 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/str/str.h" -#include "libc/testlib/testlib.h" - -static const uint32_t kCescapecGolden[256] = { - [0] = '\\' | '0' << 8 | '0' << 16 | '0' << 24, - [1] = '\\' | '0' << 8 | '0' << 16 | '1' << 24, - [2] = '\\' | '0' << 8 | '0' << 16 | '2' << 24, - [3] = '\\' | '0' << 8 | '0' << 16 | '3' << 24, - [4] = '\\' | '0' << 8 | '0' << 16 | '4' << 24, - [5] = '\\' | '0' << 8 | '0' << 16 | '5' << 24, - [6] = '\\' | '0' << 8 | '0' << 16 | '6' << 24, - [7] = '\\' | 'a' << 8, - [8] = '\\' | 'b' << 8, - [9] = '\\' | 't' << 8, - [10] = '\\' | 'n' << 8, - [11] = '\\' | 'v' << 8, - [12] = '\\' | 'f' << 8, - [13] = '\\' | 'r' << 8, - [14] = '\\' | '0' << 8 | '1' << 16 | '6' << 24, - [15] = '\\' | '0' << 8 | '1' << 16 | '7' << 24, - [16] = '\\' | '0' << 8 | '2' << 16 | '0' << 24, - [17] = '\\' | '0' << 8 | '2' << 16 | '1' << 24, - [18] = '\\' | '0' << 8 | '2' << 16 | '2' << 24, - [19] = '\\' | '0' << 8 | '2' << 16 | '3' << 24, - [20] = '\\' | '0' << 8 | '2' << 16 | '4' << 24, - [21] = '\\' | '0' << 8 | '2' << 16 | '5' << 24, - [22] = '\\' | '0' << 8 | '2' << 16 | '6' << 24, - [23] = '\\' | '0' << 8 | '2' << 16 | '7' << 24, - [24] = '\\' | '0' << 8 | '3' << 16 | '0' << 24, - [25] = '\\' | '0' << 8 | '3' << 16 | '1' << 24, - [26] = '\\' | '0' << 8 | '3' << 16 | '2' << 24, - [27] = '\\' | '0' << 8 | '3' << 16 | '3' << 24, - [28] = '\\' | '0' << 8 | '3' << 16 | '4' << 24, - [29] = '\\' | '0' << 8 | '3' << 16 | '5' << 24, - [30] = '\\' | '0' << 8 | '3' << 16 | '6' << 24, - [31] = '\\' | '0' << 8 | '3' << 16 | '7' << 24, - [32] = ' ', - [33] = '!', - [34] = '\\' | '"' << 8, - [35] = '#', - [36] = '$', - [37] = '%', - [38] = '&', - [39] = '\\' | '\'' << 8, - [40] = '(', - [41] = ')', - [42] = '*', - [43] = '+', - [44] = ',', - [45] = '-', - [46] = '.', - [47] = '/', - [48] = '0', - [49] = '1', - [50] = '2', - [51] = '3', - [52] = '4', - [53] = '5', - [54] = '6', - [55] = '7', - [56] = '8', - [57] = '9', - [58] = ':', - [59] = ';', - [60] = '<', - [61] = '=', - [62] = '>', - [63] = '?', - [64] = '@', - [65] = 'A', - [66] = 'B', - [67] = 'C', - [68] = 'D', - [69] = 'E', - [70] = 'F', - [71] = 'G', - [72] = 'H', - [73] = 'I', - [74] = 'J', - [75] = 'K', - [76] = 'L', - [77] = 'M', - [78] = 'N', - [79] = 'O', - [80] = 'P', - [81] = 'Q', - [82] = 'R', - [83] = 'S', - [84] = 'T', - [85] = 'U', - [86] = 'V', - [87] = 'W', - [88] = 'X', - [89] = 'Y', - [90] = 'Z', - [91] = '[', - [92] = '\\' | '\\' << 8, - [93] = ']', - [94] = '^', - [95] = '_', - [96] = '`', - [97] = 'a', - [98] = 'b', - [99] = 'c', - [100] = 'd', - [101] = 'e', - [102] = 'f', - [103] = 'g', - [104] = 'h', - [105] = 'i', - [106] = 'j', - [107] = 'k', - [108] = 'l', - [109] = 'm', - [110] = 'n', - [111] = 'o', - [112] = 'p', - [113] = 'q', - [114] = 'r', - [115] = 's', - [116] = 't', - [117] = 'u', - [118] = 'v', - [119] = 'w', - [120] = 'x', - [121] = 'y', - [122] = 'z', - [123] = '{', - [124] = '|', - [125] = '}', - [126] = '~', - [127] = '\\' | '1' << 8 | '7' << 16 | '7' << 24, - [128] = '\\' | '2' << 8 | '0' << 16 | '0' << 24, - [129] = '\\' | '2' << 8 | '0' << 16 | '1' << 24, - [130] = '\\' | '2' << 8 | '0' << 16 | '2' << 24, - [131] = '\\' | '2' << 8 | '0' << 16 | '3' << 24, - [132] = '\\' | '2' << 8 | '0' << 16 | '4' << 24, - [133] = '\\' | '2' << 8 | '0' << 16 | '5' << 24, - [134] = '\\' | '2' << 8 | '0' << 16 | '6' << 24, - [135] = '\\' | '2' << 8 | '0' << 16 | '7' << 24, - [136] = '\\' | '2' << 8 | '1' << 16 | '0' << 24, - [137] = '\\' | '2' << 8 | '1' << 16 | '1' << 24, - [138] = '\\' | '2' << 8 | '1' << 16 | '2' << 24, - [139] = '\\' | '2' << 8 | '1' << 16 | '3' << 24, - [140] = '\\' | '2' << 8 | '1' << 16 | '4' << 24, - [141] = '\\' | '2' << 8 | '1' << 16 | '5' << 24, - [142] = '\\' | '2' << 8 | '1' << 16 | '6' << 24, - [143] = '\\' | '2' << 8 | '1' << 16 | '7' << 24, - [144] = '\\' | '2' << 8 | '2' << 16 | '0' << 24, - [145] = '\\' | '2' << 8 | '2' << 16 | '1' << 24, - [146] = '\\' | '2' << 8 | '2' << 16 | '2' << 24, - [147] = '\\' | '2' << 8 | '2' << 16 | '3' << 24, - [148] = '\\' | '2' << 8 | '2' << 16 | '4' << 24, - [149] = '\\' | '2' << 8 | '2' << 16 | '5' << 24, - [150] = '\\' | '2' << 8 | '2' << 16 | '6' << 24, - [151] = '\\' | '2' << 8 | '2' << 16 | '7' << 24, - [152] = '\\' | '2' << 8 | '3' << 16 | '0' << 24, - [153] = '\\' | '2' << 8 | '3' << 16 | '1' << 24, - [154] = '\\' | '2' << 8 | '3' << 16 | '2' << 24, - [155] = '\\' | '2' << 8 | '3' << 16 | '3' << 24, - [156] = '\\' | '2' << 8 | '3' << 16 | '4' << 24, - [157] = '\\' | '2' << 8 | '3' << 16 | '5' << 24, - [158] = '\\' | '2' << 8 | '3' << 16 | '6' << 24, - [159] = '\\' | '2' << 8 | '3' << 16 | '7' << 24, - [160] = '\\' | '2' << 8 | '4' << 16 | '0' << 24, - [161] = '\\' | '2' << 8 | '4' << 16 | '1' << 24, - [162] = '\\' | '2' << 8 | '4' << 16 | '2' << 24, - [163] = '\\' | '2' << 8 | '4' << 16 | '3' << 24, - [164] = '\\' | '2' << 8 | '4' << 16 | '4' << 24, - [165] = '\\' | '2' << 8 | '4' << 16 | '5' << 24, - [166] = '\\' | '2' << 8 | '4' << 16 | '6' << 24, - [167] = '\\' | '2' << 8 | '4' << 16 | '7' << 24, - [168] = '\\' | '2' << 8 | '5' << 16 | '0' << 24, - [169] = '\\' | '2' << 8 | '5' << 16 | '1' << 24, - [170] = '\\' | '2' << 8 | '5' << 16 | '2' << 24, - [171] = '\\' | '2' << 8 | '5' << 16 | '3' << 24, - [172] = '\\' | '2' << 8 | '5' << 16 | '4' << 24, - [173] = '\\' | '2' << 8 | '5' << 16 | '5' << 24, - [174] = '\\' | '2' << 8 | '5' << 16 | '6' << 24, - [175] = '\\' | '2' << 8 | '5' << 16 | '7' << 24, - [176] = '\\' | '2' << 8 | '6' << 16 | '0' << 24, - [177] = '\\' | '2' << 8 | '6' << 16 | '1' << 24, - [178] = '\\' | '2' << 8 | '6' << 16 | '2' << 24, - [179] = '\\' | '2' << 8 | '6' << 16 | '3' << 24, - [180] = '\\' | '2' << 8 | '6' << 16 | '4' << 24, - [181] = '\\' | '2' << 8 | '6' << 16 | '5' << 24, - [182] = '\\' | '2' << 8 | '6' << 16 | '6' << 24, - [183] = '\\' | '2' << 8 | '6' << 16 | '7' << 24, - [184] = '\\' | '2' << 8 | '7' << 16 | '0' << 24, - [185] = '\\' | '2' << 8 | '7' << 16 | '1' << 24, - [186] = '\\' | '2' << 8 | '7' << 16 | '2' << 24, - [187] = '\\' | '2' << 8 | '7' << 16 | '3' << 24, - [188] = '\\' | '2' << 8 | '7' << 16 | '4' << 24, - [189] = '\\' | '2' << 8 | '7' << 16 | '5' << 24, - [190] = '\\' | '2' << 8 | '7' << 16 | '6' << 24, - [191] = '\\' | '2' << 8 | '7' << 16 | '7' << 24, - [192] = '\\' | '3' << 8 | '0' << 16 | '0' << 24, - [193] = '\\' | '3' << 8 | '0' << 16 | '1' << 24, - [194] = '\\' | '3' << 8 | '0' << 16 | '2' << 24, - [195] = '\\' | '3' << 8 | '0' << 16 | '3' << 24, - [196] = '\\' | '3' << 8 | '0' << 16 | '4' << 24, - [197] = '\\' | '3' << 8 | '0' << 16 | '5' << 24, - [198] = '\\' | '3' << 8 | '0' << 16 | '6' << 24, - [199] = '\\' | '3' << 8 | '0' << 16 | '7' << 24, - [200] = '\\' | '3' << 8 | '1' << 16 | '0' << 24, - [201] = '\\' | '3' << 8 | '1' << 16 | '1' << 24, - [202] = '\\' | '3' << 8 | '1' << 16 | '2' << 24, - [203] = '\\' | '3' << 8 | '1' << 16 | '3' << 24, - [204] = '\\' | '3' << 8 | '1' << 16 | '4' << 24, - [205] = '\\' | '3' << 8 | '1' << 16 | '5' << 24, - [206] = '\\' | '3' << 8 | '1' << 16 | '6' << 24, - [207] = '\\' | '3' << 8 | '1' << 16 | '7' << 24, - [208] = '\\' | '3' << 8 | '2' << 16 | '0' << 24, - [209] = '\\' | '3' << 8 | '2' << 16 | '1' << 24, - [210] = '\\' | '3' << 8 | '2' << 16 | '2' << 24, - [211] = '\\' | '3' << 8 | '2' << 16 | '3' << 24, - [212] = '\\' | '3' << 8 | '2' << 16 | '4' << 24, - [213] = '\\' | '3' << 8 | '2' << 16 | '5' << 24, - [214] = '\\' | '3' << 8 | '2' << 16 | '6' << 24, - [215] = '\\' | '3' << 8 | '2' << 16 | '7' << 24, - [216] = '\\' | '3' << 8 | '3' << 16 | '0' << 24, - [217] = '\\' | '3' << 8 | '3' << 16 | '1' << 24, - [218] = '\\' | '3' << 8 | '3' << 16 | '2' << 24, - [219] = '\\' | '3' << 8 | '3' << 16 | '3' << 24, - [220] = '\\' | '3' << 8 | '3' << 16 | '4' << 24, - [221] = '\\' | '3' << 8 | '3' << 16 | '5' << 24, - [222] = '\\' | '3' << 8 | '3' << 16 | '6' << 24, - [223] = '\\' | '3' << 8 | '3' << 16 | '7' << 24, - [224] = '\\' | '3' << 8 | '4' << 16 | '0' << 24, - [225] = '\\' | '3' << 8 | '4' << 16 | '1' << 24, - [226] = '\\' | '3' << 8 | '4' << 16 | '2' << 24, - [227] = '\\' | '3' << 8 | '4' << 16 | '3' << 24, - [228] = '\\' | '3' << 8 | '4' << 16 | '4' << 24, - [229] = '\\' | '3' << 8 | '4' << 16 | '5' << 24, - [230] = '\\' | '3' << 8 | '4' << 16 | '6' << 24, - [231] = '\\' | '3' << 8 | '4' << 16 | '7' << 24, - [232] = '\\' | '3' << 8 | '5' << 16 | '0' << 24, - [233] = '\\' | '3' << 8 | '5' << 16 | '1' << 24, - [234] = '\\' | '3' << 8 | '5' << 16 | '2' << 24, - [235] = '\\' | '3' << 8 | '5' << 16 | '3' << 24, - [236] = '\\' | '3' << 8 | '5' << 16 | '4' << 24, - [237] = '\\' | '3' << 8 | '5' << 16 | '5' << 24, - [238] = '\\' | '3' << 8 | '5' << 16 | '6' << 24, - [239] = '\\' | '3' << 8 | '5' << 16 | '7' << 24, - [240] = '\\' | '3' << 8 | '6' << 16 | '0' << 24, - [241] = '\\' | '3' << 8 | '6' << 16 | '1' << 24, - [242] = '\\' | '3' << 8 | '6' << 16 | '2' << 24, - [243] = '\\' | '3' << 8 | '6' << 16 | '3' << 24, - [244] = '\\' | '3' << 8 | '6' << 16 | '4' << 24, - [245] = '\\' | '3' << 8 | '6' << 16 | '5' << 24, - [246] = '\\' | '3' << 8 | '6' << 16 | '6' << 24, - [247] = '\\' | '3' << 8 | '6' << 16 | '7' << 24, - [248] = '\\' | '3' << 8 | '7' << 16 | '0' << 24, - [249] = '\\' | '3' << 8 | '7' << 16 | '1' << 24, - [250] = '\\' | '3' << 8 | '7' << 16 | '2' << 24, - [251] = '\\' | '3' << 8 | '7' << 16 | '3' << 24, - [252] = '\\' | '3' << 8 | '7' << 16 | '4' << 24, - [253] = '\\' | '3' << 8 | '7' << 16 | '5' << 24, - [254] = '\\' | '3' << 8 | '7' << 16 | '6' << 24, - [255] = '\\' | '3' << 8 | '7' << 16 | '7' << 24, -}; - -TEST(_cescapec, test) { - int i; - for (i = 0; i < 256; ++i) { - ASSERT_EQ(kCescapecGolden[i], _cescapec(i)); - } -} diff --git a/test/libc/fmt/fmt_test.c b/test/libc/stdio/fmt_test.c similarity index 99% rename from test/libc/fmt/fmt_test.c rename to test/libc/stdio/fmt_test.c index dc3a51489..5ab4c8e47 100644 --- a/test/libc/fmt/fmt_test.c +++ b/test/libc/stdio/fmt_test.c @@ -17,7 +17,6 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/fmt/fmt.h" - #include "libc/limits.h" #include "libc/log/log.h" #include "libc/math.h" diff --git a/test/libc/fmt/fprintf_test.c b/test/libc/stdio/fprintf_test.c similarity index 100% rename from test/libc/fmt/fprintf_test.c rename to test/libc/stdio/fprintf_test.c diff --git a/test/libc/fmt/palandprintf_test.c b/test/libc/stdio/palandprintf_test.c similarity index 99% rename from test/libc/fmt/palandprintf_test.c rename to test/libc/stdio/palandprintf_test.c index 72cdb4be9..5e6a3349c 100644 --- a/test/libc/fmt/palandprintf_test.c +++ b/test/libc/stdio/palandprintf_test.c @@ -611,8 +611,6 @@ TEST(snprintf, twosBaneWithTypePromotion) { } TEST(snprintf, formatStringLiteral) { - EXPECT_EQ('\\' | 'n' << 8, _cescapec('\n')); - EXPECT_EQ('\\' | '3' << 8 | '7' << 16 | '7' << 24, _cescapec('\377')); EXPECT_STREQ("\"hi\\n\"", Format("%`'s", "hi\n")); EXPECT_STREQ("\"\\000\"", Format("%`'.*s", 1, "\0")); } diff --git a/test/libc/fmt/snprintf_test.c b/test/libc/stdio/snprintf_test.c similarity index 100% rename from test/libc/fmt/snprintf_test.c rename to test/libc/stdio/snprintf_test.c diff --git a/test/libc/fmt/sprintf_s.inc b/test/libc/stdio/sprintf_s.inc similarity index 100% rename from test/libc/fmt/sprintf_s.inc rename to test/libc/stdio/sprintf_s.inc diff --git a/test/libc/fmt/sprintf_s_test.c b/test/libc/stdio/sprintf_s_test.c similarity index 95% rename from test/libc/fmt/sprintf_s_test.c rename to test/libc/stdio/sprintf_s_test.c index ce42e44bc..37debe004 100644 --- a/test/libc/fmt/sprintf_s_test.c +++ b/test/libc/stdio/sprintf_s_test.c @@ -39,7 +39,7 @@ static char buffer[128]; #define SUITE(NAME) NAME##s #define FORMAT(STR) STR "s" #define STRING(STR) STR -#include "test/libc/fmt/sprintf_s.inc" +#include "test/libc/stdio/sprintf_s.inc" #undef SUITE #undef FORMAT #undef STRING @@ -47,7 +47,7 @@ static char buffer[128]; #define SUITE(NAME) NAME##hs #define FORMAT(STR) STR "hs" #define STRING(STR) u##STR -#include "test/libc/fmt/sprintf_s.inc" +#include "test/libc/stdio/sprintf_s.inc" #undef SUITE #undef FORMAT #undef STRING @@ -55,7 +55,7 @@ static char buffer[128]; #define SUITE(NAME) NAME##ls #define FORMAT(STR) STR "ls" #define STRING(STR) L##STR -#include "test/libc/fmt/sprintf_s.inc" +#include "test/libc/stdio/sprintf_s.inc" #undef SUITE #undef FORMAT #undef STRING diff --git a/test/libc/fmt/sscanf_test.c b/test/libc/stdio/sscanf_test.c similarity index 99% rename from test/libc/fmt/sscanf_test.c rename to test/libc/stdio/sscanf_test.c index 399f7b604..2fed3445a 100644 --- a/test/libc/fmt/sscanf_test.c +++ b/test/libc/stdio/sscanf_test.c @@ -64,7 +64,6 @@ TEST(sscanf, testOctal) { } TEST(sscanf, testNonDirectiveCharacterMatching) { - EXPECT_EQ(0, sscanf("", "")); EXPECT_EQ(0, sscanf("%", "%%")); } diff --git a/test/libc/tinymath/strtod_test.c b/test/libc/tinymath/strtod_test.c index 6dacc29fe..bdb559108 100644 --- a/test/libc/tinymath/strtod_test.c +++ b/test/libc/tinymath/strtod_test.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/conv.h" #include "libc/fmt/fmt.h" #include "libc/macros.internal.h" #include "libc/mem/gc.h" @@ -25,7 +26,6 @@ #include "libc/testlib/testlib.h" #include "libc/x/xasprintf.h" #include "third_party/double-conversion/wrapper.h" -#include "third_party/gdtoa/gdtoa.h" #define HEX(d) (union Pun){d}.i diff --git a/test/net/http/parseurl_test.c b/test/net/http/parseurl_test.c index 78df73b17..0ce1641f7 100644 --- a/test/net/http/parseurl_test.c +++ b/test/net/http/parseurl_test.c @@ -16,7 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/fmt/internal.h" #include "libc/limits.h" #include "libc/mem/gc.internal.h" #include "libc/mem/mem.h" diff --git a/third_party/awk/lib.c b/third_party/awk/lib.c index 23911a3a1..a7e1b2718 100644 --- a/third_party/awk/lib.c +++ b/third_party/awk/lib.c @@ -28,6 +28,7 @@ #define DEBUG #include "libc/calls/calls.h" #include "libc/errno.h" +#include "libc/fmt/conv.h" #include "libc/fmt/fmt.h" #include "libc/limits.h" #include "libc/math.h" @@ -35,7 +36,6 @@ #include "libc/runtime/runtime.h" #include "libc/str/str.h" #include "third_party/awk/awk.h" -#include "third_party/gdtoa/gdtoa.h" // clang-format off char EMPTY[] = { '\0' }; diff --git a/third_party/ctags/args.h b/third_party/ctags/args.h index e52495e73..438720fb1 100644 --- a/third_party/ctags/args.h +++ b/third_party/ctags/args.h @@ -18,7 +18,7 @@ #include "third_party/ctags/general.h" /* must always come first */ #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/ctags/eiffel.c b/third_party/ctags/eiffel.c index 4a52745bc..b4347a4a5 100644 --- a/third_party/ctags/eiffel.c +++ b/third_party/ctags/eiffel.c @@ -19,7 +19,7 @@ #ifdef TYPE_REFERENCE_TOOL #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/ctags/entry.h b/third_party/ctags/entry.h index ca43387ae..2dbf20980 100644 --- a/third_party/ctags/entry.h +++ b/third_party/ctags/entry.h @@ -18,7 +18,7 @@ #include "third_party/ctags/general.h" /* must always come first */ #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/ctags/flex.c b/third_party/ctags/flex.c index 625962a84..f37f99e69 100644 --- a/third_party/ctags/flex.c +++ b/third_party/ctags/flex.c @@ -25,7 +25,7 @@ #include "libc/runtime/runtime.h" #ifdef DEBUG #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/ctags/jscript.c b/third_party/ctags/jscript.c index b82cfa81c..9878c963f 100644 --- a/third_party/ctags/jscript.c +++ b/third_party/ctags/jscript.c @@ -24,7 +24,7 @@ #include "libc/runtime/runtime.h" #ifdef DEBUG #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/ctags/main.h b/third_party/ctags/main.h index 7e3a6b112..0b2bb7f50 100644 --- a/third_party/ctags/main.h +++ b/third_party/ctags/main.h @@ -18,7 +18,7 @@ #include "third_party/ctags/general.h" /* must always come first */ #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/ctags/options.c b/third_party/ctags/options.c index 16265a475..fdefd60f3 100644 --- a/third_party/ctags/options.c +++ b/third_party/ctags/options.c @@ -16,7 +16,7 @@ #include "third_party/ctags/general.h" /* must always come first */ #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" @@ -34,7 +34,7 @@ #include "libc/mem/alg.h" #include "libc/str/str.h" #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/ctags/read.h b/third_party/ctags/read.h index b8a2fc66c..d9de83c5d 100644 --- a/third_party/ctags/read.h +++ b/third_party/ctags/read.h @@ -24,7 +24,7 @@ #include "third_party/ctags/general.h" /* must always come first */ #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/ctags/sort.c b/third_party/ctags/sort.c index 9019f8b82..ad28db151 100644 --- a/third_party/ctags/sort.c +++ b/third_party/ctags/sort.c @@ -18,7 +18,7 @@ #if defined (HAVE_STDLIB_H) #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" @@ -37,7 +37,7 @@ #include "libc/mem/alg.h" #include "libc/str/str.h" #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/ctags/sql.c b/third_party/ctags/sql.c index 3321f109e..1f69f0c3e 100644 --- a/third_party/ctags/sql.c +++ b/third_party/ctags/sql.c @@ -20,7 +20,7 @@ #include "libc/runtime/runtime.h" #ifdef DEBUG #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/ctags/tex.c b/third_party/ctags/tex.c index b5e6304b0..e67f3f6cd 100644 --- a/third_party/ctags/tex.c +++ b/third_party/ctags/tex.c @@ -21,7 +21,7 @@ #include "libc/runtime/runtime.h" #ifdef DEBUG #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/ctags/vim.c b/third_party/ctags/vim.c index 3a9b4d92f..989d8e91c 100644 --- a/third_party/ctags/vim.c +++ b/third_party/ctags/vim.c @@ -23,7 +23,7 @@ #include "libc/runtime/runtime.h" #ifdef DEBUG #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/ctags/vstring.h b/third_party/ctags/vstring.h index d25830166..b3e7408dd 100644 --- a/third_party/ctags/vstring.h +++ b/third_party/ctags/vstring.h @@ -19,7 +19,7 @@ #if defined(HAVE_STDLIB_H) #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" diff --git a/third_party/gdtoa/atof.c b/third_party/gdtoa/atof.c index 1326dfa5f..c4dc66203 100644 --- a/third_party/gdtoa/atof.c +++ b/third_party/gdtoa/atof.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/conv.h" #include "third_party/gdtoa/gdtoa.h" /** diff --git a/third_party/gdtoa/gdtoa.h b/third_party/gdtoa/gdtoa.h index 30c0e5798..222827e1f 100644 --- a/third_party/gdtoa/gdtoa.h +++ b/third_party/gdtoa/gdtoa.h @@ -3,6 +3,42 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ +#define dtoa __dtoa +#define gdtoa __gdtoa +#define strtodg __strtodg +#define freedtoa __freedtoa +#define g_ddfmt __g_ddfmt +#define g_ddfmt_p __g_ddfmt_p +#define g_dfmt __g_dfmt +#define g_dfmt_p __g_dfmt_p +#define g_ffmt __g_ffmt +#define g_ffmt_p __g_ffmt_p +#define g_Qfmt __g_Qfmt +#define g_Qfmt_p __g_Qfmt_p +#define g_xfmt __g_xfmt +#define g_xfmt_p __g_xfmt_p +#define g_xLfmt __g_xLfmt +#define g_xLfmt_p __g_xLfmt_p +#define strtoId __strtoId +#define strtoIdd __strtoIdd +#define strtoIf __strtoIf +#define strtoIQ __strtoIQ +#define strtoIx __strtoIx +#define strtoIxL __strtoIxL +#define strtord __strtord +#define strtordd __strtordd +#define strtorf __strtorf +#define strtorQ __strtorQ +#define strtorx __strtorx +#define strtorxL __strtorxL +#define strtodI __strtodI +#define strtopd __strtopd +#define strtopdd __strtopdd +#define strtopf __strtopf +#define strtopQ __strtopQ +#define strtopx __strtopx +#define strtopxL __strtopxL + /** * Configures g_*fmt() * @@ -61,13 +97,8 @@ enum { char *dtoa(double, int, int, int *, int *, char **); char *gdtoa(const FPI *, int, unsigned *, int *, int, int, int *, char **); -void freedtoa(char *); - -double atof(const char *); -float strtof(const char *, char **); -double strtod(const char *, char **); int strtodg(const char *, char **, const FPI *, int *, unsigned *); -long double strtold(const char *, char **); +void freedtoa(char *); char *g_ddfmt(char *, double *, int, size_t); char *g_ddfmt_p(char *, double *, int, size_t, int); @@ -95,7 +126,6 @@ int strtorQ(const char *, char **, int, void *); int strtorx(const char *, char **, int, void *); int strtorxL(const char *, char **, int, void *); -#if 1 int strtodI(const char *, char **, double *); int strtopd(const char *, char **, double *); int strtopdd(const char *, char **, double *); @@ -103,18 +133,6 @@ int strtopf(const char *, char **, float *); int strtopQ(const char *, char **, void *); int strtopx(const char *, char **, void *); int strtopxL(const char *, char **, void *); -#else -#define strtopd(s, se, x) strtord(s, se, 1, x) -#define strtopdd(s, se, x) strtordd(s, se, 1, x) -#define strtopf(s, se, x) strtorf(s, se, 1, x) -#define strtopQ(s, se, x) strtorQ(s, se, 1, x) -#define strtopx(s, se, x) strtorx(s, se, 1, x) -#define strtopxL(s, se, x) strtorxL(s, se, 1, x) -#endif - -float wcstof(const wchar_t *, wchar_t **); -double wcstod(const wchar_t *, wchar_t **); -long double wcstold(const wchar_t *, wchar_t **); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/third_party/gdtoa/strtod.c b/third_party/gdtoa/strtod.c index 74f9d7222..77e405342 100644 --- a/third_party/gdtoa/strtod.c +++ b/third_party/gdtoa/strtod.c @@ -30,6 +30,7 @@ │ │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/errno.h" +#include "libc/fmt/conv.h" #include "libc/runtime/fenv.h" #include "third_party/gdtoa/gdtoa.internal.h" /* clang-format off */ @@ -685,3 +686,5 @@ ret: *se = (char *)s; return sign ? -dval(&rv) : dval(&rv); } + +__weak_reference(strtod, strtod_l); diff --git a/third_party/gdtoa/strtod_l.c b/third_party/gdtoa/strtod_l.c deleted file mode 100644 index e89b5cda1..000000000 --- a/third_party/gdtoa/strtod_l.c +++ /dev/null @@ -1,24 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2022 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/str/locale.h" -#include "third_party/gdtoa/gdtoa.h" - -double strtod_l(const char *s, char **endptr, locale_t l) { - return strtod(s, endptr); -} diff --git a/third_party/gdtoa/strtof.c b/third_party/gdtoa/strtof.c index 4017171b5..d0248b9e2 100644 --- a/third_party/gdtoa/strtof.c +++ b/third_party/gdtoa/strtof.c @@ -29,6 +29,7 @@ │ THIS SOFTWARE. │ │ │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/conv.h" #include "third_party/gdtoa/gdtoa.h" #include "third_party/gdtoa/gdtoa.internal.h" /* clang-format off */ @@ -66,3 +67,5 @@ strtof(const char *s, char **sp) u.L[0] |= 0x80000000L; return u.f; } + +__weak_reference(strtof, strtof_l); diff --git a/third_party/gdtoa/strtof_l.c b/third_party/gdtoa/strtof_l.c deleted file mode 100644 index 48ba3d17b..000000000 --- a/third_party/gdtoa/strtof_l.c +++ /dev/null @@ -1,24 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2022 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/str/locale.h" -#include "third_party/gdtoa/gdtoa.h" - -float strtof_l(const char *s, char **sp, locale_t l) { - return strtof(s, sp); -} diff --git a/third_party/gdtoa/strtold.c b/third_party/gdtoa/strtold.c index e9abe0f31..410d2beb2 100644 --- a/third_party/gdtoa/strtold.c +++ b/third_party/gdtoa/strtold.c @@ -29,6 +29,7 @@ │ THIS SOFTWARE. │ │ │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/conv.h" #include "third_party/gdtoa/gdtoa.h" /** @@ -39,3 +40,5 @@ long double strtold(const char *s, char **endptr) { strtorx(s, endptr, FPI_Round_near, &x); return x; } + +__weak_reference(strtold, strtold_l); diff --git a/third_party/gdtoa/strtold_l.c b/third_party/gdtoa/strtold_l.c deleted file mode 100644 index 3559fb55e..000000000 --- a/third_party/gdtoa/strtold_l.c +++ /dev/null @@ -1,40 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│ -│vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi│ -╚──────────────────────────────────────────────────────────────────────────────╝ -│ │ -│ The author of this software is David M. Gay. │ -│ Please send bug reports to David M. Gay │ -│ or Justine Tunney │ -│ │ -│ Copyright (C) 1998, 1999 by Lucent Technologies │ -│ All Rights Reserved │ -│ │ -│ Permission to use, copy, modify, and distribute this software and │ -│ its documentation for any purpose and without fee is hereby │ -│ granted, provided that the above copyright notice appear in all │ -│ copies and that both that the copyright notice and this │ -│ permission notice and warranty disclaimer appear in supporting │ -│ documentation, and that the name of Lucent or any of its entities │ -│ not be used in advertising or publicity pertaining to │ -│ distribution of the software without specific, written prior │ -│ permission. │ -│ │ -│ LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, │ -│ INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. │ -│ IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY │ -│ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES │ -│ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER │ -│ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, │ -│ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF │ -│ THIS SOFTWARE. │ -│ │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/str/locale.h" -#include "third_party/gdtoa/gdtoa.h" - -/** - * Converts string to long double. - */ -long double strtold_l(const char *s, char **endptr, locale_t l) { - return strtold(s, endptr); -} diff --git a/third_party/gdtoa/wcstold.c b/third_party/gdtoa/wcstold.c index 17cdaa38b..b7089bac8 100644 --- a/third_party/gdtoa/wcstold.c +++ b/third_party/gdtoa/wcstold.c @@ -26,3 +26,5 @@ long double wcstold(const wchar_t *nptr, wchar_t **endptr) { assert(!"not implemented"); abort(); } + +__weak_reference(strtold, strtold_l); diff --git a/third_party/gdtoa/wcstold_l.c b/third_party/gdtoa/wcstold_l.c deleted file mode 100644 index f7682a623..000000000 --- a/third_party/gdtoa/wcstold_l.c +++ /dev/null @@ -1,25 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2022 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/fmt/conv.h" -#include "libc/str/locale.h" -#include "third_party/gdtoa/gdtoa.h" - -long double wcstold_l(const wchar_t *nptr, wchar_t **endptr, locale_t l) { - return wcstold(nptr, endptr); -} diff --git a/third_party/hiredis/alloc.c b/third_party/hiredis/alloc.c index 84df76d6a..b6625c67d 100644 --- a/third_party/hiredis/alloc.c +++ b/third_party/hiredis/alloc.c @@ -33,7 +33,7 @@ #include "libc/mem/alg.h" #include "libc/str/str.h" #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" diff --git a/third_party/hiredis/async.c b/third_party/hiredis/async.c index 0399dee4e..b61f1c436 100644 --- a/third_party/hiredis/async.c +++ b/third_party/hiredis/async.c @@ -32,7 +32,7 @@ #include "third_party/hiredis/alloc.h" #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" diff --git a/third_party/hiredis/dict.c b/third_party/hiredis/dict.c index 6e57575d5..509f38ae5 100644 --- a/third_party/hiredis/dict.c +++ b/third_party/hiredis/dict.c @@ -36,7 +36,7 @@ #include "third_party/hiredis/alloc.h" #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" diff --git a/third_party/hiredis/hiredis.c b/third_party/hiredis/hiredis.c index 57b54d7cf..cc58a8ba5 100644 --- a/third_party/hiredis/hiredis.c +++ b/third_party/hiredis/hiredis.c @@ -35,7 +35,7 @@ #include "libc/mem/alg.h" #include "libc/str/str.h" #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" diff --git a/third_party/hiredis/net.c b/third_party/hiredis/net.c index a69c9eb0a..dbd828717 100644 --- a/third_party/hiredis/net.c +++ b/third_party/hiredis/net.c @@ -66,7 +66,7 @@ #include "libc/errno.h" #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" @@ -80,7 +80,7 @@ #include "libc/sysv/consts/xopen.h" #include "libc/thread/thread.h" #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" diff --git a/third_party/hiredis/read.c b/third_party/hiredis/read.c index 2adf6b4e0..31af6cfa9 100644 --- a/third_party/hiredis/read.c +++ b/third_party/hiredis/read.c @@ -33,7 +33,7 @@ #include "libc/mem/alg.h" #include "libc/str/str.h" #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" diff --git a/third_party/hiredis/read.h b/third_party/hiredis/read.h index ed0b330e7..b0fb0d143 100644 --- a/third_party/hiredis/read.h +++ b/third_party/hiredis/read.h @@ -34,7 +34,7 @@ #ifndef __HIREDIS_READ_H #define __HIREDIS_READ_H #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/hiredis/sds.c b/third_party/hiredis/sds.c index 00586843c..76bc8a6f2 100644 --- a/third_party/hiredis/sds.c +++ b/third_party/hiredis/sds.c @@ -32,7 +32,7 @@ */ #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" @@ -40,7 +40,7 @@ #include "libc/stdio/temp.h" #include "third_party/musl/tempnam.h" #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" @@ -1145,7 +1145,7 @@ void sds_free(void *ptr) { s_free(ptr); } #if defined(SDS_TEST_MAIN) #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/lua/luaconf.h b/third_party/lua/luaconf.h index 0a6d34fc5..74ef92328 100644 --- a/third_party/lua/luaconf.h +++ b/third_party/lua/luaconf.h @@ -2,10 +2,10 @@ #define luaconf_h #include "libc/assert.h" #include "libc/dce.h" +#include "libc/fmt/conv.h" #include "libc/fmt/fmt.h" #include "libc/limits.h" #include "libc/str/unicode.h" -#include "third_party/gdtoa/gdtoa.h" #define LUA_USE_POSIX #define LUA_USE_LINENOISE diff --git a/third_party/quickjs/atof.c b/third_party/quickjs/atof.c index 4bcb99abd..272fc4108 100644 --- a/third_party/quickjs/atof.c +++ b/third_party/quickjs/atof.c @@ -23,9 +23,9 @@ * THE SOFTWARE. */ #include "libc/assert.h" +#include "libc/fmt/conv.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" -#include "third_party/gdtoa/gdtoa.h" #include "third_party/quickjs/internal.h" asm(".ident\t\"\\n\\n\ diff --git a/third_party/quickjs/qjs.c b/third_party/quickjs/qjs.c index 749e3b9eb..75ae383ed 100644 --- a/third_party/quickjs/qjs.c +++ b/third_party/quickjs/qjs.c @@ -25,6 +25,7 @@ #include "libc/assert.h" #include "libc/calls/weirdtypes.h" #include "libc/dce.h" +#include "libc/fmt/conv.h" #include "libc/log/log.h" #include "libc/mem/mem.h" #include "libc/runtime/runtime.h" @@ -32,7 +33,6 @@ #include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/time/time.h" -#include "third_party/gdtoa/gdtoa.h" #include "third_party/quickjs/cutils.h" #include "third_party/quickjs/quickjs-libc.h" #include "tool/args/args.h" diff --git a/third_party/quickjs/qjsc.c b/third_party/quickjs/qjsc.c index 2bdc46b50..a143076de 100644 --- a/third_party/quickjs/qjsc.c +++ b/third_party/quickjs/qjsc.c @@ -24,6 +24,7 @@ #include "libc/assert.h" #include "libc/calls/calls.h" #include "libc/dce.h" +#include "libc/fmt/conv.h" #include "libc/fmt/fmt.h" #include "libc/log/log.h" #include "libc/mem/gc.h" @@ -32,7 +33,6 @@ #include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/x/xasprintf.h" -#include "third_party/gdtoa/gdtoa.h" #include "third_party/getopt/getopt.h" #include "third_party/quickjs/cutils.h" #include "third_party/quickjs/quickjs-libc.h" diff --git a/third_party/regex/regex.mk b/third_party/regex/regex.mk index e7441e684..df2a41cb2 100644 --- a/third_party/regex/regex.mk +++ b/third_party/regex/regex.mk @@ -15,7 +15,7 @@ THIRD_PARTY_REGEX_A_OBJS = \ $(THIRD_PARTY_REGEX_A_SRCS:%.c=o/$(MODE)/%.o) THIRD_PARTY_REGEX_A_DIRECTDEPS = \ - LIBC_FMT \ + LIBC_STDIO \ LIBC_INTRIN \ LIBC_MEM \ LIBC_NEXGEN32E \ diff --git a/third_party/sqlite3/geopoly.inc b/third_party/sqlite3/geopoly.inc index 54188a9f4..ea7243a31 100644 --- a/third_party/sqlite3/geopoly.inc +++ b/third_party/sqlite3/geopoly.inc @@ -16,7 +16,7 @@ ** This file is #include-ed onto the end of "rtree.c" so that it has ** access to all of the R-Tree internals. */ -#include "third_party/gdtoa/gdtoa.h" +#include "libc/fmt/conv.h" /* clang-format off */ /* Enable -DGEOPOLY_ENABLE_DEBUG for debugging facilities */ diff --git a/third_party/sqlite3/json.c b/third_party/sqlite3/json.c index eacfa6001..18f790814 100644 --- a/third_party/sqlite3/json.c +++ b/third_party/sqlite3/json.c @@ -22,8 +22,9 @@ ** how JSONB might improve on that.) */ #ifndef SQLITE_OMIT_JSON +#include "libc/fmt/conv.h" #include "third_party/sqlite3/sqliteInt.h" -#include "third_party/gdtoa/gdtoa.h" +// clang-format off /* ** Growing our own isspace() routine this way is twice as fast as diff --git a/third_party/zip/tailor.h b/third_party/zip/tailor.h index 7bff89adc..ab5cef02a 100644 --- a/third_party/zip/tailor.h +++ b/third_party/zip/tailor.h @@ -221,7 +221,7 @@ /* Define void, zvoid, and extent (size_t) */ #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" @@ -235,7 +235,7 @@ #ifndef NO_STDLIB_H #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" diff --git a/third_party/zip/zip.c b/third_party/zip/zip.c index f3ad306d9..f493d6879 100644 --- a/third_party/zip/zip.c +++ b/third_party/zip/zip.c @@ -85,7 +85,7 @@ #include "libc/sysv/consts/sicode.h" #include "libc/sysv/consts/ss.h" #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/third_party/zip/zipcloak.c b/third_party/zip/zipcloak.c index 552e7880d..4daaa0dc7 100644 --- a/third_party/zip/zipcloak.c +++ b/third_party/zip/zipcloak.c @@ -37,7 +37,7 @@ #include "libc/sysv/consts/ss.h" #ifndef NO_STDLIB_H #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" diff --git a/third_party/zip/zipfile.c b/third_party/zip/zipfile.c index e8d88355f..4b3cdc0d5 100644 --- a/third_party/zip/zipfile.c +++ b/third_party/zip/zipfile.c @@ -23,7 +23,7 @@ /* for realloc 2/6/2005 EG */ #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/termios.h" #include "libc/fmt/conv.h" #include "libc/limits.h" diff --git a/third_party/zlib/inflate.c b/third_party/zlib/inflate.c index a29d4e65e..f267b42c5 100644 --- a/third_party/zlib/inflate.c +++ b/third_party/zlib/inflate.c @@ -328,7 +328,7 @@ struct inflate_state FAR *state; #ifdef MAKEFIXED #include "libc/calls/calls.h" -#include "libc/calls/dprintf.h" +#include "libc/stdio/dprintf.h" #include "libc/calls/weirdtypes.h" #include "libc/fmt/fmt.h" #include "libc/mem/fmt.h" diff --git a/tool/viz/float2bin.c b/tool/viz/float2bin.c deleted file mode 100644 index e3ccc0c9b..000000000 --- a/tool/viz/float2bin.c +++ /dev/null @@ -1,50 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2021 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/stdio/stdio.h" -#include "third_party/gdtoa/gdtoa.h" - -const char kDoubleBits[] = "\ -┌sign\n\ -│ ┌exponent\n\ -│ │ ┌fraction\n\ -│ │ │\n\ -│┌┴────────┐┌┴─────────────────────────────────────────────────┐\n"; - -const char kLongDoubleBits[] = "\ -┌sign\n\ -│ ┌exponent\n\ -│ │ ┌intpart\n\ -│ │ │ ┌fraction\n\ -│ │ │ │\n\ -│┌┴────────────┐│┌┴────────────────────────────────────────────────────────────┐\n"; - -int main(int argc, char *argv[]) { - int i; - union { - double f; - uint64_t i; - } u; - if (argc <= 1) return 1; - fputs(kDoubleBits, stdout); - for (i = 1; i < argc; ++i) { - u.f = strtod(argv[i], 0); - printf("%064lb %.15g\n", u.i, u.f); - } - return 0; -} diff --git a/tool/viz/getopts.c b/tool/viz/getopts.c deleted file mode 100644 index 87317ada7..000000000 --- a/tool/viz/getopts.c +++ /dev/null @@ -1,199 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2022 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/stdio/stdio.h" -#include "libc/str/str.h" - -/** - * @fileoverview Tool for printing which getopt() letters are used, e.g. - * - * o//tool/viz/getopts.com jkazhdugvVsmbBfe:A:l:p:r:R:H - */ - -int letters_used[256]; -bool letters_with_args[256]; - -bool IsLegal(int c) { - return isgraph(c) && c != ':' && c != '?'; -} - -int main(int argc, char *argv[]) { - int i, j; - bool hasargless; - - for (i = 1; i < argc; ++i) { - for (j = 0; argv[i][j]; ++j) { - ++letters_used[argv[i][j] & 255]; - if (argv[i][j + 1] == ':') { - letters_with_args[argv[i][j] & 255] = true; - } - } - } - - // usage report - fprintf(stderr, "// options used: "); - for (j = i = 0; i < 128; ++i) { - if (!IsLegal(i)) continue; - if (letters_used[i]) { - if (j++) fprintf(stderr, ""); - fprintf(stderr, "%c", i); - } - } - if (!j) fprintf(stderr, "none"); - fprintf(stderr, "\n"); - fprintf(stderr, "// letters not used: "); - for (j = i = 0; i < 128; ++i) { - if (!isalpha(i)) continue; - if (!letters_used[i]) { - if (j++) fprintf(stderr, ""); - fprintf(stderr, "%c", i); - } - } - if (!j) fprintf(stderr, "none"); - fprintf(stderr, "\n"); - fprintf(stderr, "// digits not used: "); - for (j = i = 0; i < 128; ++i) { - if (!isdigit(i)) continue; - if (!letters_used[i]) { - if (j++) fprintf(stderr, ""); - fprintf(stderr, "%c", i); - } - } - if (!j) fprintf(stderr, "none"); - fprintf(stderr, "\n"); - fprintf(stderr, "// puncts not used: "); - for (j = i = 0; i < 128; ++i) { - if (!IsLegal(i)) continue; - if (isalnum(i)) continue; - if (!letters_used[i]) { - if (j++) fprintf(stderr, ""); - fprintf(stderr, "%c", i); - } - } - if (!j) fprintf(stderr, "none"); - fprintf(stderr, "\n"); - fprintf(stderr, "// letters duplicated: "); - for (j = i = 0; i < 128; ++i) { - if (!IsLegal(i)) continue; - if (letters_used[i] > 1) { - if (j++) fprintf(stderr, ""); - fprintf(stderr, "%c", i); - } - } - if (!j) fprintf(stderr, "none"); - fprintf(stderr, "\n"); - - // generated code - hasargless = false; - printf("#define GETOPTS \""); - for (j = i = 0; i < 128; ++i) { - if (!IsLegal(i)) continue; - if (letters_used[i] && !letters_with_args[i]) { - printf("%c", i); - hasargless = true; - } - } - for (j = i = 0; i < 128; ++i) { - if (!IsLegal(i)) continue; - if (letters_used[i] && letters_with_args[i]) { - printf("%c:", i); - } - } - printf("\"\n"); - printf("\n#define USAGE \"\\\n"); - printf("Usage: program.com"); - if (hasargless) { - printf(" [-"); - for (j = i = 0; i < 128; ++i) { - if (!IsLegal(i)) continue; - if (letters_used[i] && !letters_with_args[i]) { - printf("%c", i); - hasargless = true; - } - } - printf("]"); - } - printf(" ARGS...\\n\\\n"); - for (j = i = 0; i < 128; ++i) { - if (!IsLegal(i)) continue; - if (letters_used[i] && !letters_with_args[i]) { - printf(" -%c the %c option\\n\\\n", i, i); - } - } - for (j = i = 0; i < 128; ++i) { - if (!IsLegal(i)) continue; - if (letters_with_args[i]) { - printf(" -%c VAL the %c option\\n\\\n", i, i); - } - } - printf("\"\n\n"); - - for (i = 0; i < 128; ++i) { - if (!IsLegal(i)) continue; - if (letters_used[i]) { - if (letters_with_args[i]) { - printf("const char *"); - } else { - printf("int "); - } - if (isalnum(i) || i == '_') { - printf("g_%cflag;\n", i); - } - } - } - - printf("\n\ -static void GetOpts(int argc, char *argv[]) {\n\ - int opt;\n\ - while ((opt = getopt(argc, argv, GETOPTS)) != -1) {\n\ - switch (opt) {\n"); - for (i = 0; i < 128; ++i) { - if (!IsLegal(i)) continue; - if (letters_used[i]) { - printf(" case '%c':\n", i); - if (isalnum(i) || i == '_') { - printf(" g_%cflag", i); - } else { - printf(" g_XXXflag", i); - } - if (letters_with_args[i]) { - printf(" = optarg;\n"); - } else { - printf("++;\n"); - } - printf(" break;\n"); - } - } - - printf(" case '?':\n"); - printf(" write(1, USAGE, sizeof(USAGE) - 1);\n"); - printf(" exit(0);\n"); - printf(" default:\n"); - printf(" write(2, USAGE, sizeof(USAGE) - 1);\n"); - printf(" exit(64);\n"); - printf(" }\n"); - printf(" }\n"); - printf("}\n"); - printf("\n"); - - printf("int main(int argc, char *argv[]) {\n"); - printf(" GetOpts(argc, argv);\n"); - printf("}\n"); - - return 0; -} diff --git a/tool/viz/magikarp.c b/tool/viz/magikarp.c index dceaa0fb3..2057f601d 100644 --- a/tool/viz/magikarp.c +++ b/tool/viz/magikarp.c @@ -23,6 +23,7 @@ #include "libc/assert.h" #include "libc/calls/calls.h" #include "libc/calls/struct/stat.h" +#include "libc/fmt/conv.h" #include "libc/limits.h" #include "libc/log/check.h" #include "libc/log/log.h" @@ -40,7 +41,6 @@ #include "libc/sysv/consts/prot.h" #include "libc/testlib/testlib.h" #include "libc/x/x.h" -#include "third_party/gdtoa/gdtoa.h" #include "third_party/getopt/getopt.h" #include "third_party/stb/stb_image.h" #include "tool/viz/lib/bilinearscale.h"